Пример #1
0
    def generate_detection_layer(self):
        from pca4cd.pca4cd import PCA4CD as pca4cd
        detection_from = self.RangeChangeFrom.value()
        detection_to = self.RangeChangeTo.value()
        output_change_layer = Path(pca4cd.tmp_dir,
                                   self.pc_layer.name() + "_detection.tif")

        # compute the detection layer between range values
        da_pc = da.from_array(self.pc_data, chunks=(2000, 2000))

        def calc(block, range_from, range_to):
            result = np.zeros_like(block)
            result[(block >= range_from) & (block <= range_to) &
                   (block != 0)] = 1
            return result

        # process
        map_blocks = da.map_blocks(calc,
                                   da_pc,
                                   range_from=detection_from,
                                   range_to=detection_to,
                                   dtype=np.int8)
        detection_layer_ds = map_blocks.compute(scheduler='threads',
                                                num_workers=cpu_count())
        # save
        if self.driver_detection_layer is None:
            driver = gdal.GetDriverByName("GTiff")
            self.driver_detection_layer = driver.Create(
                str(output_change_layer), self.pc_gdal_ds.RasterXSize,
                self.pc_gdal_ds.RasterYSize, 1, gdal.GDT_Byte,
                ["NBITS=1", "COMPRESS=NONE"])
        dl_band = self.driver_detection_layer.GetRasterBand(1)
        dl_band.SetNoDataValue(0)
        dl_band.WriteArray(detection_layer_ds)
        # set projection and geotransform
        if self.pc_gdal_ds.GetGeoTransform() is not None:
            self.driver_detection_layer.SetGeoTransform(
                self.pc_gdal_ds.GetGeoTransform())
        if self.pc_gdal_ds.GetProjection() is not None:
            self.driver_detection_layer.SetProjection(
                self.pc_gdal_ds.GetProjection())
        dl_band.FlushCache()
        dl_band = None
        self.driver_detection_layer.FlushCache()
        # necessary for fix flushing cache generating the detection layer the first time (Linux/Mac)
        # and not in Windows due to permission problems when the detection layer is overwritten
        if platform.system() != 'Windows':
            self.driver_detection_layer = None

        detection_layer = load_layer(output_change_layer, add_to_legend=False)
        apply_symbology(detection_layer, [("0", 0, (255, 255, 255, 0)),
                                          ("1", 1, (255, 255, 0, 255))])

        self.render_widget.set_detection_layer(detection_layer)
        self.parent_view_widget.render_widget.set_detection_layer(
            detection_layer)
        self.parent_view_widget.EnableChangeDetection.setChecked(True)
        self.ShowHideChangeDetection.setEnabled(True)
        self.ShowHideChangeDetection.setChecked(True)
Пример #2
0
    def do_merge_change_layers(self, merge_dialog):
        merged_change_layer = Path(merge_dialog.MergeFileWidget.filePath())
        MergeChangeLayersDialog.merged_file_path = merged_change_layer
        # first unload layer from qgis if exists
        unload_layer(merged_change_layer)

        merge_method = merge_dialog.MergeMethod.currentText()

        if len(self.activated_change_layers) == 1:
            shutil.copy(get_file_path_of_layer(self.activated_change_layers[0]), merged_change_layer)

        if len(self.activated_change_layers) > 1 and merge_method == "Union":
            cmd = ['gdal_merge' if platform.system() == 'Windows' else 'gdal_merge.py',
                   '-of', 'GTiff', '-o', str(merged_change_layer), '-n', '0', '-a_nodata', '0', '-ot',
                   'Byte'] + [str(get_file_path_of_layer(layer)) for layer in self.activated_change_layers]
            subprocess.run(" ".join(cmd), shell=True)

        if len(self.activated_change_layers) > 1 and merge_method == "Intersection":
            alpha_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
                          "T", "U", "V", "W", "X", "Y", "Z"]
            input_files = {alpha_list[x]: str(get_file_path_of_layer(f)) for x, f in enumerate(self.activated_change_layers)}
            filter_ones = ",".join([alpha_list[x] + "==1" for x in range(len(self.activated_change_layers))])
            filter_zeros = ",".join([alpha_list[x] + "==0" for x in range(len(self.activated_change_layers))])

            cmd = ['gdal_calc' if platform.system() == 'Windows' else 'gdal_calc.py', '--overwrite',
                   '--calc', '"0*(numpy.any([{filter_zeros}], axis=0)) + 1*(numpy.all([{filter_ones}], axis=0))"'
                       .format(filter_zeros=filter_zeros, filter_ones=filter_ones),
                   '--outfile', str(merged_change_layer), '--NoDataValue=0', '--type=Byte'] + \
                  [i for sl in [["-{}".format(letter), filepath] for letter, filepath in input_files.items()] for i in sl]
            subprocess.run(" ".join(cmd), shell=True)

        # unset nodata
        cmd = ['gdal_edit' if platform.system() == 'Windows' else 'gdal_edit.py',
               '"{}"'.format(merged_change_layer), '-unsetnodata']
        subprocess.run(" ".join(cmd), shell=True)
        # apply style
        merged_layer = load_layer(merged_change_layer, add_to_legend=True if merge_dialog.LoadInQgis.isChecked() else False)
        apply_symbology(merged_layer, [("0", 0, (255, 255, 255, 0)), ("1", 1, (255, 255, 0, 255))])
        # save named style in QML aux file
        merged_layer.saveNamedStyle(str(merged_change_layer.with_suffix(".qml")))

        # add the merged layer to input and auxiliary view
        for view_widget in MainAnalysisDialog.view_widgets:
            if view_widget.pc_id is None:
                view_widget.WidgetDetectionLayer.setEnabled(True)
                view_widget.QPBtn_ComponentAnalysisDialog.setToolTip("")
                view_widget.render_widget.set_detection_layer(merged_layer)
                if view_widget.is_active:
                    view_widget.EnableChangeDetection.setChecked(True)
                    view_widget.QPBtn_ComponentAnalysisDialog.setEnabled(True)

        if len(self.activated_ids) == 1:
            self.MsgBar.pushMessage(
                "The change detection for {} was saved and loaded successfully".format(
                    self.activated_ids[0]), level=Qgis.Success)
        else:
            self.MsgBar.pushMessage(
                "The change detection for {} were merged, saved and loaded successfully".format(
                    ", ".join(self.activated_ids)), level=Qgis.Success)
Пример #3
0
    def generate_principal_components(self):
        from pca4cd.pca4cd import PCA4CD as pca4cd
        # check if is valid the input raster layer
        if self.QCBox_InputData_A.currentLayer() is None:
            self.MsgBar.pushMessage("Select a valid input raster layer",
                                    level=Qgis.Warning)
            return
        # check both layers
        if not self.check_input_layers(self.QCBox_InputData_A.currentLayer(),
                                       self.QCBox_InputData_B.currentLayer()):
            return
        # check the nodata value
        nodata = self.NoData_ComputePCA.text() if self.NoData_ComputePCA.text(
        ) not in ["", "None", "nan"] else None
        if nodata is not None:
            try:
                nodata = float(nodata)
            except:
                self.MsgBar.pushMessage("The nodata value is not valid",
                                        level=Qgis.Warning)
                return

        path_layer_A = get_file_path_of_layer(
            self.QCBox_InputData_A.currentLayer())
        path_layer_B = get_file_path_of_layer(
            self.QCBox_InputData_B.currentLayer())
        n_pc = int(self.QCBox_nComponents.currentText())
        estimator_matrix = self.QCBox_EstimatorMatrix.currentText()

        pca_files, pca_stats = pca(path_layer_A, path_layer_B, n_pc,
                                   estimator_matrix, pca4cd.tmp_dir,
                                   self.nThreads.value(),
                                   self.BlockSize.value(), nodata)

        pca_layers = []
        if pca_files:
            for pca_file in pca_files:
                pca_layers.append(load_layer(pca_file, add_to_legend=False))
            # then, open main analysis dialog
            self.open_main_analysis_dialog(pca_layers, pca_stats, nodata)
        else:
            self.MsgBar.pushMessage(
                "Error while generating the principal components, check the Qgis log",
                level=Qgis.Critical)
Пример #4
0
    def load_external_pc_in_main_analysis_dialog(self):
        from pca4cd.pca4cd import PCA4CD as pca4cd
        stack_path = self.QgsFile_LoadStackPCA.filePath()
        if not os.path.isfile(stack_path):
            self.MsgBar.pushMessage("Select a valid stack for load",
                                    level=Qgis.Warning)
            return False
        # check the nodata value
        nodata = self.NoData_LoadPCA.text() if self.NoData_LoadPCA.text(
        ) not in ["", "None", "nan"] else None
        if nodata is not None:
            try:
                nodata = float(nodata)
            except:
                self.MsgBar.pushMessage("The nodata value is not valid",
                                        level=Qgis.Warning)
                return

        # extract each band as component in tmp file
        src_ds = gdal.Open(stack_path, gdal.GA_ReadOnly)
        num_bands = src_ds.RasterCount
        del src_ds
        pca_layers = []
        for component in range(num_bands):
            tmp_pca_file = pca4cd.tmp_dir / 'pc_{}.tif'.format(component + 1)
            gdal.Translate(str(tmp_pca_file),
                           stack_path,
                           bandList=[component + 1],
                           noData=nodata)
            pca_layers.append(load_layer(tmp_pca_file, add_to_legend=False))

        # pca statistics
        pca_stats = {}
        pca_stats["eigenvals"] = None

        self.main_analysis_dialog = MainAnalysisDialog(None, None, pca_layers,
                                                       pca_stats, nodata)
        # open dialog
        self.main_analysis_dialog.show()
        self.main_analysis_dialog.update_pc_style()