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)
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
파일: satex.py 프로젝트: m-haas/SatEx
    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)
예제 #6
0
    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)