def run_classification(self): """Run method that performs all the real work""" self.Cdlg.setModal(False) self.Cdlg.show() #Dialog event loop result = self.Cdlg.exec_() if result: import utils import traceback import qgis.core import ogr #import subprocess #Get user edits valid_input = self.updateCForm() #TODO:fix self.classification_type = 'libsvm' self.svmModel = self.in_train[:-4] + '_svmModel.svm' self.ConfMatrix = self.in_train[:-4] + '_CM.csv' try: import otbApplication except: self.errorMsg('Plugin requires installation of OrfeoToolbox') e = 'Unspecified error' try: #instantiate utilities functions ut = utils.utils() try: #check if input is not empty string 1 / valid_input except ZeroDivisionError: e = str('Please fill all required input fields') raise Exception #check if training fields overlap with raster if not self.external: try: error, overlap = ut.vector_raster_overlap( self.in_train, self.raster) except: e = str( 'Unspecified error while trying to execute utils.vector_raster_overlap function' ) raise Exception if error != 'SUCCESS': e = error raise Exception else: try: 1 / overlap except ZeroDivisionError: e = str( 'At least one feature in {} does not overlap with {}' .format(self.in_train, self.raster)) raise Exception #generate image statistics try: self.stats = str(self.raster[:-4] + '_stats.xml') error = ut.otb_image_statistics(str(self.raster), str(self.stats)) if error != 'success': raise ZeroDivisionError qgis.core.QgsMessageLog.logMessage( str('Calculated image statistics {} for {}'.format( self.stats, self.raster))) except ZeroDivisionError: e = str( 'Could not execute OTB Image Statistics on: {}. \nError is:{}' .format(self.raster, error)) raise Exception #differntiate two cases case 1) external SVM provided an case 2) on the fly SVM training if self.external: if self.in_train != '': #use full training set for testing self.test = self.in_train #get SVM filename self.svmModel = self.Cdlg.lineEdit_4.text() else: #split training dataset in 80% train 20% testing [self.error, self.test, self.train] = ut.split_train(self.in_train, self.label, self.startupinfo) if self.error != 'success': e = self.error raise Exception else: qgis.core.QgsMessageLog.logMessage( str('Splitted ground truth data set in {} (~80%) and {} (~20%)' .format(self.train, self.test))) #train classifier #on the fly (wrong) confusion matrix gets overwritten later try: error = ut.otb_train_classifier( self.raster, self.train, self.stats, self.classification_type, self.label, self.svmModel, self.ConfMatrix) if error != 'success': raise ZeroDivisionError qgis.core.QgsMessageLog.logMessage( str('Trained image classifier using {} and {}'. format(self.raster, self.train))) except ZeroDivisionError: e = 'Could not execute OTB TrainClassifiers with {} {} {} {} {} {} {}. \nError is:{}'.format( self.raster, self.train, self.stats, self.classification_type, self.label, self.svmModel, self.ConfMatrix, error) raise Exception #classify image try: error = ut.otb_classification(self.raster, self.stats, self.svmModel, self.out_fname) if error != 'success': raise ZeroDivisionError qgis.core.QgsMessageLog.logMessage( str('Image {} classified as {}'.format( self.raster, self.out_fname))) except ZeroDivisionError: e = 'Could not execute OTB Classifier with {}, {}, {}, {}. \n Error is: {}'.format( self.raster, self.stats, self.svmModel, self.out_fname, error) raise Exception #confusion matrix try: #testing is optional in case of externally provided SVM if self.in_train != '': error = ut.otb_confusion_matrix( self.out_fname, self.ConfMatrix, self.test, self.label) if error != 'success': raise ZeroDivisionError qgis.core.QgsMessageLog.logMessage( str('Confusion matrix calculated on classified image {} with test set {} saved as {}' .format(self.out_fname, self.test, self.ConfMatrix))) except ZeroDivisionError: e = 'Could not execute OTB Confusion Matrix with {}, {}, {}, {}. \nError is: {}'.format( self.out_fname, self.ConfMatrix, self.test, self.label) raise Exception #if sieving is asked perform sieving if self.Cdlg.checkBox_3.isChecked(): try: if os.name == 'nt': cmd = [ 'gdal_sieve.bat', '-q', '-st', str(self.sieve), '-8', str(self.out_fname) ] else: cmd = [ 'gdal_sieve.py', '-q', '-st', str(self.sieve), '-8', str(self.out_fname) ] subprocess.check_call(cmd, startupinfo=self.startupinfo) except subprocess.CalledProcessError: e = 'Could not execute {}'.format(cmd) raise Exception #add to map canvas if checked if self.Cdlg.checkBox_2.isChecked(): try: self.iface.addRasterLayer(str(self.out_fname), "SatEx_classified_scene") except: e = str('Could not add {} to the layer canvas'.format( self.out_fname)) raise Exception except: self.errorMsg(e) qgis.core.QgsMessageLog.logMessage(e) else: qgis.core.QgsMessageLog.logMessage(str('Processing completed')) self.iface.messageBar().pushMessage( 'Processing successfully completed, see log for details', self.iface.messageBar().SUCCESS, duration=3)
def run_preprocessing(self): """Run method that performs all the real work""" self.Pdlg.setModal(False) self.Pdlg.show() #Dialog event loop result = self.Pdlg.exec_() if result: self.processed = 0 self.percentage = 0 #TODO:fix self.ntasks = 3 #Get user edits and check if not empty valid_input = self.updatePForm() import utils import traceback import qgis.core import ogr try: import otbApplication except: self.errorMsg('Plugin requires installation of OrfeoToolbox') #find the number of different L8 scenes #by reading all TIFs splitting off '_Bxy.TIF' and getting unique strings e = 'Unspecified error' #instantiate utilities function ut = utils.utils() try: try: #check if input is not empty string 1 / valid_input except ZeroDivisionError: e = str('Please fill all required input fields') raise Exception try: #delete any old tmp files that might be in the directory from a killed task old = ut.delete_tmps(self.ls_path) if old > 0: qgis.core.QgsMessageLog.logMessage( 'Old *satexTMP* files were present. They were deleted.' ) except: e = str( 'Could not delete old *satexTMP* files. Function utils.delete_tmps.' ) raise Exception try: pattern = '*.TIF' scenes = set([ '_'.join(s.split('_')[:1]) for s in ut.findFiles(self.ls_path, pattern) ]) if len(scenes) == 0: pattern = '*.tif' scenes = set([ '_'.join(s.split('_')[:1]) for s in ut.findFiles(self.ls_path, pattern) ]) 1 / len(scenes) except ZeroDivisionError: e = str('Found no scene in {}'.format(self.ls_path)) raise Exception else: qgis.core.QgsMessageLog.logMessage( str('Found {} scene(s) in {}'.format( len(scenes), self.ls_path))) #check shapefile roi try: driver = ogr.GetDriverByName('ESRI Shapefile') dataSource = driver.Open(self.roi, 0) layer = dataSource.GetLayer() qgis.core.QgsMessageLog.logMessage( str('Using {} as ROI'.format(self.roi))) except AttributeError: e = str('Could not open {}'.format(self.roi)) raise Exception #loop through all scenes out_files = [] for scene in scenes: #find all bands for scene exclude quality band BQA and B8 try: bands = [ b for b in ut.findFiles(self.ls_path, scene + '*_B' + pattern) if '_BQA' not in b ] bands = [b for b in bands if '_B8' not in b] #in case of multiple scenes (and not first scene is processed) check if nr of bands are equal try: #only if more than one scene and at least second scene nr_bands except: if len(bands) == 0: e = str('Found no bands for scene {}.'.format( scene)) raise Exception else: #store number of bands for potential additonal scenes nr_bands = len(bands) qgis.core.QgsMessageLog.logMessage( str('Found {} bands (if present, excluding B8 and BQA) for scene {} ' .format(nr_bands, scene))) else: if len(bands) != nr_bands: e = str( 'Found {} instead of {} bands (excluding B8 and BQA) for scene {}. If multiple scenes are provided in the input directory, ensure they have equal bands!' .format(len(bands), nr_bands, scene)) else: qgis.core.QgsMessageLog.logMessage( str('Found {} bands (if present, excluding B8 and BQA) for scene {} ' .format(len(bands), scene))) except: raise Exception #Check if ROI and scene overlap try: error, overlap = ut.vector_raster_overlap( self.roi, self.ls_path + bands[0]) except: e = str( 'Unspecified error while trying to execute utils.vector_raster_overlap function with {} and {}' .format(self.roi, bands[0])) raise Exception if error != 'SUCCESS': e = error raise Exception else: try: 1 / overlap except ZeroDivisionError: e = str( 'The provided ROI {} does not overlap with scene {}' .format(self.roi, scene)) raise Exception #use gdalwarp to cut bands to roi try: #go through bands for band in bands: cmd = [ 'gdalwarp', '-overwrite', '-q', '-cutline', self.roi, '-crop_to_cutline', self.ls_path + band, self.ls_path + band[:-4] + '_satexTMP_ROI' + pattern[1:] ] subprocess.check_call(cmd, startupinfo=self.startupinfo) qgis.core.QgsMessageLog.logMessage( str('Cropped band {} to ROI'.format(band))) except subprocess.CalledProcessError: e = str( 'Could not execute gdalwarp cmd: {}.\nError is:{}'. format(' '.join(cmd), error)) raise Exception # Layerstack try: #respect order B1,B2,B3,B4,B5,B6,B7,B9,B10,B11 in_files = [ str(self.ls_path + b[:-4] + '_satexTMP_ROI' + pattern[1:]) for b in bands ] in_files.sort() if nr_bands == 10: # For Landsat 8 B10,B11 considered smaller --> resort in_files = in_files[2:] + in_files[0:2] out_file = str( os.path.dirname(self.out_fname) + '/' + scene + '_satex_mul' + pattern[1:]) #call otb wrapper error = ut.otb_concatenate(in_files, out_file) if error != 'success': raise ZeroDivisionError #append file to list out_files.append(out_file) qgis.core.QgsMessageLog.logMessage( str('Concatenated bands for scene {}'.format( scene))) except ZeroDivisionError: e = str( 'Could not execute OTB ConcatenateImages for scene: {}\nin_files: {}\nout_file: {}. \nError is: {}' .format(scene, in_files, out_file, error)) raise Exception # after all scenes were processed combine them to a virtual raster tile try: cmd = [ "gdalbuildvrt", "-q", "-srcnodata", "0", "-overwrite", self.out_fname ] for f in out_files: cmd.append(f) subprocess.check_call(cmd, startupinfo=self.startupinfo) qgis.core.QgsMessageLog.logMessage( str('Merged {} different scenes to {}'.format( len(out_files), self.out_fname))) except subprocess.CalledProcessError: e = str('Could not execute gdalbuildvrt cmd: {}'.format( ' '.join(cmd))) raise Exception #add to map canvas if checked if self.Pdlg.checkBox.isChecked(): try: self.iface.addRasterLayer(str(self.out_fname), "SatEx_vrt") except: e = str('Could not add {} to the layer canvas'.format( self.out_fname)) raise Exception except: self.errorMsg(e) qgis.core.QgsMessageLog.logMessage( str('Exception: {}'.format(e))) qgis.core.QgsMessageLog.logMessage( str('Exception occurred...deleting temporary files')) ut.delete_tmps(self.ls_path) else: qgis.core.QgsMessageLog.logMessage( str('Processing sucessfully completed')) qgis.core.QgsMessageLog.logMessage( str('Deleting temporary files')) self.iface.messageBar().pushMessage( 'Processing successfully completed, see log for details', self.iface.messageBar().SUCCESS, duration=3) ut.delete_tmps(self.ls_path)
def run_classification(self): """Run method that performs all the real work""" self.Cdlg.setModal(False) self.Cdlg.show() #Dialog event loop result = self.Cdlg.exec_() if result: import utils import traceback import qgis.core import ogr #import subprocess self.processed = 0 self.percentage = 0 #TODO:fix self.ntasks = 3 #Get user edits valid_input=self.updateCForm() #TODO:fix self.classification_type='libsvm' self.svmModel = self.in_train[:-4]+'_svmModel.svm' self.ConfMatrix = self.in_train[:-4]+'_CM.csv' try: import otbApplication except: self.errorMsg('Plugin requires installation of OrfeoToolbox') e = 'unspecified error' try: #instantiate utilities functions ut = utils.utils() try: #check if input is not empty string 1/valid_input except Exception as e: e = str('Please fill all required input fields') raise Exception #check if training fields overlap with raster if not self.external: try: 1/ut.vector_raster_overlap(self.in_train,self.raster) except: e = str('At least one feature in {} does not overlap with {}'.format(self.in_train,self.raster)) raise Exception #generate image statistics try: self.stats = str(self.raster[:-4]+'_stats.xml') ut.otb_image_statistics(str(self.raster),str(self.stats)) qgis.core.QgsMessageLog.logMessage(str('Calculated image statistics {} for {}'.format(self.stats,self.raster))) #self.calculate_progress() except: e = str('Could not execute OTB Image Statistics on: {}'.format(self.raster)) raise Exception #differntiate two cases case 1) external SVM provided an case 2) on the fly SVM training if self.external: if self.in_train!='': #use full training set for testing self.test = self.in_train #get SVM filename self.svmModel = self.Cdlg.lineEdit_4.text() else: #split training dataset in 80% train 20% testing [self.error,self.test,self.train] = ut.split_train(self.in_train,self.label,self.startupinfo) if self.error != 'success': e=self.error raise Exception else: qgis.core.QgsMessageLog.logMessage(str('Splitted ground truth data set in {} (~80%) and {} (~20%)'.format(self.train,self.test))) #train classifier #on the fly (wrong) confusion matrix gets overwritten later try: ut.otb_train_classifier(self.raster, self.train, self.stats, self.classification_type, self.label, self.svmModel, self.ConfMatrix) qgis.core.QgsMessageLog.logMessage(str('Trained image classifier using {} and {}'.format(self.raster,self.train))) except Exception as e: e = 'Could not execute OTB TrainClassifiers with {} {} {} {} {} {} {}'.format(self.raster, self.train, self.stats, self.classification_type, self.label, self.svmModel, self.ConfMatrix) raise Exception #classify image try: ut.otb_classification(self.raster, self.stats, self.svmModel, self.out_fname) qgis.core.QgsMessageLog.logMessage(str('Image {} classified as {}'.format(self.raster,self.out_fname))) except Exception as e: e = 'Could not execute OTB Classifier with {}, {}, {}, {}'.format(self.raster, self.stats, self.svmModel, self.out_fname) raise Exception #confusion matrix try: #testing is optional in case of externally provided SVM if self.in_train!='': ut.otb_confusion_matrix(self.out_fname,self.ConfMatrix,self.test,self.label) qgis.core.QgsMessageLog.logMessage(str('Confusion matrix calcualted on classified image {} with test set {} saved as {}'.format(self.out_fname,self.test,self.ConfMatrix))) except Exception as e: e = 'Could not execute OTB Confusion Matrix with {}, {}, {}, {}'.format(self.out_fname, self.ConfMatrix, self.test, self.label) raise Exception #if sieving is asked perform sieving if self.Cdlg.checkBox_3.isChecked(): try: if os.name=='nt': cmd = ['gdal_sieve.bat','-q','-st',str(self.sieve),'-8',str(self.out_fname)] else: cmd = ['gdal_sieve.py','-q','-st',str(self.sieve),'-8',str(self.out_fname)] subprocess.check_call(cmd,startupinfo=self.startupinfo) except Exception as e: e = 'Could not execute {}'.format(cmd) raise Exception #add to map canvas if checked if self.Cdlg.checkBox_2.isChecked(): self.iface.addRasterLayer(str(self.out_fname), "SatEx_classified_scene") except: self.errorMsg(e) qgis.core.QgsMessageLog.logMessage(e) qgis.core.QgsMessageLog.logMessage(str('Exception: Deleting temporary files')) #ut.delete_tmps(self.ls_path) else: qgis.core.QgsMessageLog.logMessage(str('Processing completed')) qgis.core.QgsMessageLog.logMessage(str('Deleting temporary files')) self.iface.messageBar().pushMessage('Processing successfully completed, see log for details',self.iface.messageBar().SUCCESS,duration=3)
def run_preprocessing(self): """Run method that performs all the real work""" self.Pdlg.setModal(False) self.Pdlg.show() #Dialog event loop result = self.Pdlg.exec_() if result: self.processed = 0 self.percentage = 0 #TODO:fix self.ntasks = 3 #Get user edits and check if not empty valid_input=self.updatePForm() #self.Pdlg.startWorker(self.iface, self.ls_path, self.roi, self.out_fname) import utils import traceback import qgis.core import ogr #import subprocess try: import otbApplication except: self.errorMsg('Plugin requires installation of OrfeoToolbox') #find the number of different L8 scenes #by reading all TIFs splitting off '_Bxy.TIF' and getting unique strings e = 'unspecified error' #instantiate utilities function ut = utils.utils() try: try: #check if input is not empty string 1/valid_input except Exception as e: e = str('Please fill all required input fields') raise Exception try: #delete any old tmp files that might be in the directory from a killed task old=ut.delete_tmps(self.ls_path) if old > 0: qgis.core.QgsMessageLog.logMessage('Old *satexTMP* files were present. They were deleted.') scenes = set(['_'.join(s.split('_')[:1]) for s in ut.findFiles(self.ls_path,'*.TIF')]) #adjust number of tasks self.ntasks = self.ntasks*len(scenes) qgis.core.QgsMessageLog.logMessage(str('Found {} Landsat 8 scene(s) in {}'.format(len(scenes),self.ls_path))) except Exception as e: e = str('Found no Landsat 8 scene in {}'.format(self.ls_path)) raise Exception #check shapefile roi try: driver = ogr.GetDriverByName('ESRI Shapefile') dataSource = driver.Open(self.roi,0) layer = dataSource.GetLayer() qgis.core.QgsMessageLog.logMessage(str('Using {} as ROI'.format(self.roi))) except Exception as e: e = str('Could not open {}'.format(self.roi)) raise Exception #loop through all scenes for scene in scenes: #find all bands for scene exclude quality band BQA and B8 try: bands = [b for b in ut.findFiles(self.ls_path,scene+'*_B*.TIF') if '_BQA' not in b] bands = [b for b in bands if '_B8' not in b] #check if there are 10 bands #if len(bands)!=11: if len(bands)!=10: e = str('Found {} instead of 10 bands (excluding B8 and BQA) for scene {}'.format(len(bands),scene)) raise Exception else: #self.status.emit('Found all 11 bands for scene {}'.format(scene)) qgis.core.QgsMessageLog.logMessage(str('Found all 10 bands (excluding B8 and BQA) for scene {} '.format(scene))) except Exception as e: e = str('Could not find all 10 bands (excluding B8 and BQA) for scene {}'.format(scene)) raise Exception #Check if ROI and scene overlap try: 1/ut.vector_raster_overlap(self.roi,self.ls_path+scene+'_B1.TIF') except: e = str('The provided ROI {} does not overlap with scene {}'.format(self.roi,scene)) raise Exception #use gdalwarp to cut bands to roi try: #go through bands for band in bands: #self.status.emit('Cropping band {} to ROI'.format(band)) qgis.core.QgsMessageLog.logMessage(str('Cropping band {} to ROI'.format(band))) cmd = ['gdalwarp','-overwrite','-q','-cutline',self.roi,'-crop_to_cutline',self.ls_path+band,self.ls_path+band[:-4]+'_satexTMP_ROI.TIF'] subprocess.check_call(cmd,startupinfo=self.startupinfo) # self.calculate_progress() except Exception as e: e = str('Could not execute gdalwarp cmd: {}'.format(' '.join(cmd))) raise Exception # Layerstack try: #respect order B1,B2,B3,B4,B5,B6,B7,B9,B10,B11 #in_files = [str(self.ls_path+b[:-4]+'_satexTMP_ROI.TIF') for b in bands if '_B8' not in b] in_files = [str(self.ls_path+b[:-4]+'_satexTMP_ROI.TIF') for b in bands] in_files.sort() #B10,B11 considered smaller --> resort in_files = in_files[2:] + in_files[0:2] out_file = str(self.ls_path+scene+'_satex_mul.TIF') #call otb wrapper #self.status.emit('Concatenating bands for pansharpening scene {}'.format(scene)) qgis.core.QgsMessageLog.logMessage(str('Concatenate bands for pansharpening scene {}'.format(scene))) ut.otb_concatenate(in_files,out_file) #self.calculate_progress() except Exception as e: e = str('Could not execute OTB ConcatenateImages for scene: {}\nin_files: {}\nout_file: {}'.format(scene,in_files,out_file)) raise Exception # after all scenes were processed combine them to a virtual raster tile try: cmd = ["gdalbuildvrt","-q","-srcnodata","0","-overwrite",self.out_fname] files = [f for f in ut.findFiles(self.ls_path,'*satex_mul.TIF')] for f in files: cmd.append(str(self.ls_path+f)) subprocess.check_call(cmd,startupinfo=self.startupinfo) qgis.core.QgsMessageLog.logMessage(str('Merged {} different L8 scenes to {}'.format(len(files),self.out_fname))) #self.calculate_progress() except: e = str('Could not execute gdalbuildvrt cmd: {}'.format(' '.join(cmd))) raise Exception #add to map canvas if checked if self.Pdlg.checkBox.isChecked(): self.iface.addRasterLayer(str(self.out_fname), "SatEx_vrt") except: self.errorMsg(e) qgis.core.QgsMessageLog.logMessage(str('Exception: {}'.format(e))) qgis.core.QgsMessageLog.logMessage(str('Exception: Deleting temporary files')) ut.delete_tmps(self.ls_path) else: qgis.core.QgsMessageLog.logMessage(str('Processing sucessfully completed')) qgis.core.QgsMessageLog.logMessage(str('Deleting temporary files')) self.iface.messageBar().pushMessage('Processing successfully completed, see log for details',self.iface.messageBar().SUCCESS,duration=3) ut.delete_tmps(self.ls_path)
def run_preprocessing(self): """Run method that performs all the real work""" self.Pdlg.setModal(False) self.Pdlg.show() #Dialog event loop result = self.Pdlg.exec_() if result: self.processed = 0 self.percentage = 0 #TODO:fix self.ntasks = 3 #Get user edits and check if not empty valid_input=self.updatePForm() import utils import traceback import qgis.core import ogr try: import otbApplication except: self.errorMsg('Plugin requires installation of OrfeoToolbox') #find the number of different L8 scenes #by reading all TIFs splitting off '_Bxy.TIF' and getting unique strings e = 'Unspecified error' #instantiate utilities function ut = utils.utils() try: try: #check if input is not empty string 1/valid_input except ZeroDivisionError: e = str('Please fill all required input fields') raise Exception try: #delete any old tmp files that might be in the directory from a killed task old=ut.delete_tmps(self.ls_path) if old > 0: qgis.core.QgsMessageLog.logMessage('Old *satexTMP* files were present. They were deleted.') except: e = str('Could not delete old *satexTMP* files. Function utils.delete_tmps.') raise Exception try: pattern = '*.TIF' scenes = set(['_'.join(s.split('_')[:1]) for s in ut.findFiles(self.ls_path,pattern)]) if len(scenes)==0: pattern = '*.tif' scenes = set(['_'.join(s.split('_')[:1]) for s in ut.findFiles(self.ls_path,pattern)]) 1/len(scenes) except ZeroDivisionError: e = str('Found no scene in {}'.format(self.ls_path)) raise Exception else: qgis.core.QgsMessageLog.logMessage(str('Found {} scene(s) in {}'.format(len(scenes),self.ls_path))) #check shapefile roi try: driver = ogr.GetDriverByName('ESRI Shapefile') dataSource = driver.Open(self.roi,0) layer = dataSource.GetLayer() qgis.core.QgsMessageLog.logMessage(str('Using {} as ROI'.format(self.roi))) except AttributeError: e = str('Could not open {}'.format(self.roi)) raise Exception #loop through all scenes out_files = [] for scene in scenes: #find all bands for scene exclude quality band BQA and B8 try: bands = [b for b in ut.findFiles(self.ls_path,scene+'*_B'+pattern) if '_BQA' not in b] bands = [b for b in bands if '_B8' not in b] #in case of multiple scenes (and not first scene is processed) check if nr of bands are equal try: #only if more than one scene and at least second scene nr_bands except: if len(bands)==0: e = str('Found no bands for scene {}.'.format(scene)) raise Exception else: #store number of bands for potential additonal scenes nr_bands = len(bands) qgis.core.QgsMessageLog.logMessage(str('Found {} bands (if present, excluding B8 and BQA) for scene {} '.format(nr_bands,scene))) else: if len(bands)!=nr_bands: e = str('Found {} instead of {} bands (excluding B8 and BQA) for scene {}. If multiple scenes are provided in the input directory, ensure they have equal bands!'.format(len(bands),nr_bands,scene)) else: qgis.core.QgsMessageLog.logMessage(str('Found {} bands (if present, excluding B8 and BQA) for scene {} '.format(len(bands),scene))) except: raise Exception #Check if ROI and scene overlap try: error,overlap = ut.vector_raster_overlap(self.roi,self.ls_path+bands[0]) except: e = str('Unspecified error while trying to execute utils.vector_raster_overlap function with {} and {}'.format(self.roi,bands[0])) raise Exception if error!='SUCCESS': e = error raise Exception else: try: 1/overlap except ZeroDivisionError: e = str('The provided ROI {} does not overlap with scene {}'.format(self.roi,scene)) raise Exception #use gdalwarp to cut bands to roi try: #go through bands for band in bands: cmd = ['gdalwarp','-overwrite','-q','-cutline',self.roi,'-crop_to_cutline',self.ls_path+band,self.ls_path+band[:-4]+'_satexTMP_ROI'+pattern[1:]] subprocess.check_call(cmd,startupinfo=self.startupinfo) qgis.core.QgsMessageLog.logMessage(str('Cropped band {} to ROI'.format(band))) except subprocess.CalledProcessError: e = str('Could not execute gdalwarp cmd: {}.\nError is:{}'.format(' '.join(cmd),error)) raise Exception # Layerstack try: #respect order B1,B2,B3,B4,B5,B6,B7,B9,B10,B11 in_files = [str(self.ls_path+b[:-4]+'_satexTMP_ROI'+pattern[1:]) for b in bands] in_files.sort() if nr_bands==10: # For Landsat 8 B10,B11 considered smaller --> resort in_files = in_files[2:] + in_files[0:2] out_file = str(os.path.dirname(self.out_fname)+'/'+scene+'_satex_mul'+pattern[1:]) #call otb wrapper error = ut.otb_concatenate(in_files,out_file) if error!='success': raise ZeroDivisionError #append file to list out_files.append(out_file) qgis.core.QgsMessageLog.logMessage(str('Concatenated bands for scene {}'.format(scene))) except ZeroDivisionError: e = str('Could not execute OTB ConcatenateImages for scene: {}\nin_files: {}\nout_file: {}. \nError is: {}'.format(scene,in_files,out_file,error)) raise Exception # after all scenes were processed combine them to a virtual raster tile try: cmd = ["gdalbuildvrt","-q","-srcnodata","0","-overwrite",self.out_fname] for f in out_files: cmd.append(f) subprocess.check_call(cmd,startupinfo=self.startupinfo) qgis.core.QgsMessageLog.logMessage(str('Merged {} different scenes to {}'.format(len(out_files),self.out_fname))) except subprocess.CalledProcessError: e = str('Could not execute gdalbuildvrt cmd: {}'.format(' '.join(cmd))) raise Exception #add to map canvas if checked if self.Pdlg.checkBox.isChecked(): try: self.iface.addRasterLayer(str(self.out_fname), "SatEx_vrt") except: e = str('Could not add {} to the layer canvas'.format(self.out_fname)) raise Exception except: self.errorMsg(e) qgis.core.QgsMessageLog.logMessage(str('Exception: {}'.format(e))) qgis.core.QgsMessageLog.logMessage(str('Exception occurred...deleting temporary files')) ut.delete_tmps(self.ls_path) else: qgis.core.QgsMessageLog.logMessage(str('Processing sucessfully completed')) qgis.core.QgsMessageLog.logMessage(str('Deleting temporary files')) self.iface.messageBar().pushMessage('Processing successfully completed, see log for details',self.iface.messageBar().SUCCESS,duration=3) ut.delete_tmps(self.ls_path)
def run_preprocessing(self): """Run method that performs all the real work""" self.Pdlg.setModal(False) self.Pdlg.show() #Dialog event loop result = self.Pdlg.exec_() if result: self.processed = 0 self.percentage = 0 #TODO:fix self.ntasks = 3 #Get user edits and check if not empty valid_input = self.updatePForm() #self.Pdlg.startWorker(self.iface, self.ls_path, self.roi, self.out_fname) import utils import traceback import qgis.core import ogr #import subprocess try: import otbApplication except: self.errorMsg('Plugin requires installation of OrfeoToolbox') #find the number of different L8 scenes #by reading all TIFs splitting off '_Bxy.TIF' and getting unique strings e = 'unspecified error' #instantiate utilities function ut = utils.utils() try: try: #check if input is not empty string 1 / valid_input except Exception as e: e = str('Please fill all required input fields') raise Exception try: #delete any old tmp files that might be in the directory from a killed task old = ut.delete_tmps(self.ls_path) if old > 0: qgis.core.QgsMessageLog.logMessage( 'Old *satexTMP* files were present. They were deleted.' ) scenes = set([ '_'.join(s.split('_')[:1]) for s in ut.findFiles(self.ls_path, '*.TIF') ]) #adjust number of tasks self.ntasks = self.ntasks * len(scenes) qgis.core.QgsMessageLog.logMessage( str('Found {} Landsat 8 scene(s) in {}'.format( len(scenes), self.ls_path))) except Exception as e: e = str('Found no Landsat 8 scene in {}'.format( self.ls_path)) raise Exception #check shapefile roi try: driver = ogr.GetDriverByName('ESRI Shapefile') dataSource = driver.Open(self.roi, 0) layer = dataSource.GetLayer() qgis.core.QgsMessageLog.logMessage( str('Using {} as ROI'.format(self.roi))) except Exception as e: e = str('Could not open {}'.format(self.roi)) raise Exception #loop through all scenes for scene in scenes: #find all bands for scene exclude quality band BQA and B8 try: bands = [ b for b in ut.findFiles(self.ls_path, scene + '*_B*.TIF') if '_BQA' not in b ] bands = [b for b in bands if '_B8' not in b] #check if there are 10 bands #if len(bands)!=11: if len(bands) != 10: e = str( 'Found {} instead of 10 bands (excluding B8 and BQA) for scene {}' .format(len(bands), scene)) raise Exception else: #self.status.emit('Found all 11 bands for scene {}'.format(scene)) qgis.core.QgsMessageLog.logMessage( str('Found all 10 bands (excluding B8 and BQA) for scene {} ' .format(scene))) except Exception as e: e = str( 'Could not find all 10 bands (excluding B8 and BQA) for scene {}' .format(scene)) raise Exception #Check if ROI and scene overlap try: 1 / ut.vector_raster_overlap( self.roi, self.ls_path + scene + '_B1.TIF') except: e = str( 'The provided ROI {} does not overlap with scene {}' .format(self.roi, scene)) raise Exception #use gdalwarp to cut bands to roi try: #go through bands for band in bands: #self.status.emit('Cropping band {} to ROI'.format(band)) qgis.core.QgsMessageLog.logMessage( str('Cropping band {} to ROI'.format(band))) cmd = [ 'gdalwarp', '-overwrite', '-q', '-cutline', self.roi, '-crop_to_cutline', self.ls_path + band, self.ls_path + band[:-4] + '_satexTMP_ROI.TIF' ] subprocess.check_call(cmd, startupinfo=self.startupinfo) # self.calculate_progress() except Exception as e: e = str('Could not execute gdalwarp cmd: {}'.format( ' '.join(cmd))) raise Exception # Layerstack try: #respect order B1,B2,B3,B4,B5,B6,B7,B9,B10,B11 #in_files = [str(self.ls_path+b[:-4]+'_satexTMP_ROI.TIF') for b in bands if '_B8' not in b] in_files = [ str(self.ls_path + b[:-4] + '_satexTMP_ROI.TIF') for b in bands ] in_files.sort() #B10,B11 considered smaller --> resort in_files = in_files[2:] + in_files[0:2] out_file = str(self.ls_path + scene + '_satex_mul.TIF') #call otb wrapper #self.status.emit('Concatenating bands for pansharpening scene {}'.format(scene)) qgis.core.QgsMessageLog.logMessage( str('Concatenate bands for pansharpening scene {}'. format(scene))) ut.otb_concatenate(in_files, out_file) #self.calculate_progress() except Exception as e: e = str( 'Could not execute OTB ConcatenateImages for scene: {}\nin_files: {}\nout_file: {}' .format(scene, in_files, out_file)) raise Exception # after all scenes were processed combine them to a virtual raster tile try: cmd = [ "gdalbuildvrt", "-q", "-srcnodata", "0", "-overwrite", self.out_fname ] files = [ f for f in ut.findFiles(self.ls_path, '*satex_mul.TIF') ] for f in files: cmd.append(str(self.ls_path + f)) subprocess.check_call(cmd, startupinfo=self.startupinfo) qgis.core.QgsMessageLog.logMessage( str('Merged {} different L8 scenes to {}'.format( len(files), self.out_fname))) #self.calculate_progress() except: e = str('Could not execute gdalbuildvrt cmd: {}'.format( ' '.join(cmd))) raise Exception #add to map canvas if checked if self.Pdlg.checkBox.isChecked(): self.iface.addRasterLayer(str(self.out_fname), "SatEx_vrt") except: self.errorMsg(e) qgis.core.QgsMessageLog.logMessage( str('Exception: {}'.format(e))) qgis.core.QgsMessageLog.logMessage( str('Exception: Deleting temporary files')) ut.delete_tmps(self.ls_path) else: qgis.core.QgsMessageLog.logMessage( str('Processing sucessfully completed')) qgis.core.QgsMessageLog.logMessage( str('Deleting temporary files')) self.iface.messageBar().pushMessage( 'Processing successfully completed, see log for details', self.iface.messageBar().SUCCESS, duration=3) ut.delete_tmps(self.ls_path)