예제 #1
0
    def _alg_tester(self, alg_name, input_layer, parameters):

        alg = self.registry.createAlgorithmById(alg_name)

        self.assertIsNotNone(alg)
        parameters['INPUT'] = input_layer
        parameters['OUTPUT'] = 'memory:'

        old_features = [f for f in input_layer.getFeatures()]
        input_layer.selectByIds([old_features[0].id()])
        # Check selected
        self.assertEqual(input_layer.selectedFeatureIds(), [old_features[0].id()], alg_name)

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        input_layer.rollBack()
        ok = False
        ok, _ = execute_in_place_run(
            alg, parameters, context=context, feedback=feedback, raise_exceptions=True)
        new_features = [f for f in input_layer.getFeatures()]

        # Check ret values
        self.assertTrue(ok, alg_name)

        # Check geometry types (drop Z or M)
        self.assertEqual(new_features[0].geometry().wkbType(), old_features[0].geometry().wkbType())

        return old_features, new_features
예제 #2
0
    def testRun(self):
        context = QgsProcessingContext()

        # try running an alg using processing.run - ownership of result layer should be transferred back to the caller
        res = processing.run('qgis:buffer',
                             {'DISTANCE': 1, 'INPUT': points(), 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT},
                             context=context)
        self.assertIn('OUTPUT', res)
        # output should be the layer instance itself
        self.assertIsInstance(res['OUTPUT'], QgsVectorLayer)
        # Python should have ownership
        self.assertTrue(sip.ispyowned(res['OUTPUT']))
        del context
        gc.collect()
        self.assertFalse(sip.isdeleted(res['OUTPUT']))

        # now try using processing.run with is_child_algorithm = True. Ownership should remain with the context
        context = QgsProcessingContext()
        res = processing.run('qgis:buffer',
                             {'DISTANCE': 1, 'INPUT': points(), 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT},
                             context=context, is_child_algorithm=True)
        self.assertIn('OUTPUT', res)
        # output should be a layer string reference, NOT the layer itself
        self.assertIsInstance(res['OUTPUT'], str)
        layer = context.temporaryLayerStore().mapLayer(res['OUTPUT'])
        self.assertIsInstance(layer, QgsVectorLayer)
        # context should have ownership
        self.assertFalse(sip.ispyowned(layer))
        del context
        gc.collect()
        self.assertTrue(sip.isdeleted(layer))
    def testGdalScripts(self):
        '''Test GDAL scripts2'''
        layer = QgsRasterLayer(os.path.join(os.path.dirname(__file__), "data","dem25.tif"),
                                    "dem")
        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById('gdal:rastercalculator')
        self.assertIsNotNone(alg)

        parameters = {'INPUT_A':'dem',
                        'BAND_A':1,'INPUT_B':None,'BAND_B':-1,
                        'INPUT_C':None,'BAND_C':-1,'INPUT_D':None,
                        'BAND_D':-1,'INPUT_E':None,'BAND_E':-1,
                        'INPUT_F':None,'BAND_F':-1,'FORMULA':'A*2',
                        'NO_DATA':None,'RTYPE':5,'OPTIONS':'',
                        'OUTPUT':'TEMPORARY_OUTPUT'}
        feedback = QgsProcessingFeedback()

        results, ok = alg.run(parameters, context, feedback)
        self.assertTrue(ok)
        self.assertTrue(os.path.exists(results["OUTPUT"]))

        QgsProject.instance().removeMapLayer(layer)        
예제 #4
0
    def test_select_all_features(self):
        """Check that if there is no selection, the alg will run on all features"""

        self.vl.rollBack()
        self.vl.removeSelection()
        old_count = self.vl.featureCount()

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        alg = self.registry.createAlgorithmById('native:translategeometry')

        self.assertIsNotNone(alg)

        parameters = {
            'DELTA_X': 1.1,
            'DELTA_Y': 1.1,
        }
        parameters['INPUT'] = self.vl
        parameters['OUTPUT'] = 'memory:'

        old_features = [f for f in self.vl.getFeatures()]

        ok, _ = execute_in_place_run(
            alg, parameters, context=context, feedback=feedback, raise_exceptions=True)
        new_features = [f for f in self.vl.getFeatures()]

        self.assertEqual(len(new_features), old_count)

        # Check all are selected
        self.assertEqual(len(self.vl.selectedFeatureIds()), old_count)
예제 #5
0
    def test_parameterAs_ScriptMode(self):
        """
        This test will pass an instance of QgsCoordinateReferenceSystem for 'epsg' parameter
        of otb::Rasterization. There is same test in otb_algorithm_tests.yaml which passes
        an instance of str for epsg parameter.
        """
        outdir = tempfile.mkdtemp()
        self.cleanup_paths.append(outdir)

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = QgsProcessingFeedback()

        vectorFile = os.path.join(AlgorithmsTestBase.processingTestDataPath(), 'polys.gml')
        vectorLayer = QgsProcessingUtils.mapLayerFromString(vectorFile, context)
        parameters = {
            'in': vectorLayer,
            'epsg': QgsCoordinateReferenceSystem('EPSG:4326'),
            'spx': 1.0,
            'spy': 1.0,
            'outputpixeltype': 1,
            'out': os.path.join(outdir, 'raster.tif')
        }
        results = processing.run('otb:Rasterization', parameters, None, feedback)
        result_lyr = QgsProcessingUtils.mapLayerFromString(results['out'], context)
        self.assertTrue(result_lyr.isValid())
예제 #6
0
    def test_check_validity(self):
        """Test that the output invalid contains the error reason"""

        polygon_layer = self._make_layer('Polygon')
        self.assertTrue(polygon_layer.startEditing())
        f = QgsFeature(polygon_layer.fields())
        f.setAttributes([1])
        # Flake!
        f.setGeometry(QgsGeometry.fromWkt(
            'POLYGON ((0 0, 2 2, 0 2, 2 0, 0 0))'))
        self.assertTrue(f.isValid())
        f2 = QgsFeature(polygon_layer.fields())
        f2.setAttributes([1])
        f2.setGeometry(QgsGeometry.fromWkt(
            'POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))'))
        self.assertTrue(f2.isValid())
        self.assertTrue(polygon_layer.addFeatures([f, f2]))
        polygon_layer.commitChanges()
        polygon_layer.rollBack()
        self.assertEqual(polygon_layer.featureCount(), 2)

        QgsProject.instance().addMapLayers([polygon_layer])

        alg = self.registry.createAlgorithmById('qgis:checkvalidity')

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        self.assertIsNotNone(alg)
        parameters = {}
        parameters['INPUT_LAYER'] = polygon_layer.id()
        parameters['VALID_OUTPUT'] = 'memory:'
        parameters['INVALID_OUTPUT'] = 'memory:'
        parameters['ERROR_OUTPUT'] = 'memory:'

        # QGIS method
        parameters['METHOD'] = 1
        ok, results = execute(
            alg, parameters, context=context, feedback=feedback)
        self.assertTrue(ok)
        invalid_layer = QgsProcessingUtils.mapLayerFromString(
            results['INVALID_OUTPUT'], context)
        self.assertEqual(invalid_layer.fields().names()[-1], '_errors')
        self.assertEqual(invalid_layer.featureCount(), 1)
        f = next(invalid_layer.getFeatures())
        self.assertEqual(f.attributes(), [
                         1, 'segments 0 and 2 of line 0 intersect at 1, 1'])

        # GEOS method
        parameters['METHOD'] = 2
        ok, results = execute(
            alg, parameters, context=context, feedback=feedback)
        self.assertTrue(ok)
        invalid_layer = QgsProcessingUtils.mapLayerFromString(
            results['INVALID_OUTPUT'], context)
        self.assertEqual(invalid_layer.fields().names()[-1], '_errors')
        self.assertEqual(invalid_layer.featureCount(), 1)
        f = next(invalid_layer.getFeatures())
        self.assertEqual(f.attributes(), [1, 'Self-intersection'])
    def testFeatureSourceInput(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer("Point?crs=epsg:3857&field=fldtxt:string&field=fldint:integer",
                               "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(110, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)

        # select first feature
        layer.selectByIds([next(layer.getFeatures()).id()])
        self.assertEqual(len(layer.selectedFeatureIds()), 1)

        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById('grass7:v.buffer')
        self.assertIsNotNone(alg)
        temp_file = os.path.join(self.temp_dir, 'grass_output_sel.shp')
        parameters = {'input': QgsProcessingFeatureSourceDefinition('testmem', True),
                      'cats': '',
                      'where': '',
                      'type': [0, 1, 4],
                      'distance': 1,
                      'minordistance': None,
                      'angle': 0,
                      'column': None,
                      'scale': 1,
                      'tolerance': 0.01,
                      '-s': False,
                      '-c': False,
                      '-t': False,
                      'output': temp_file,
                      'GRASS_REGION_PARAMETER': None,
                      'GRASS_SNAP_TOLERANCE_PARAMETER': -1,
                      'GRASS_MIN_AREA_PARAMETER': 0.0001,
                      'GRASS_OUTPUT_TYPE_PARAMETER': 0,
                      'GRASS_VECTOR_DSCO': '',
                      'GRASS_VECTOR_LCO': ''}
        feedback = QgsProcessingFeedback()

        results, ok = alg.run(parameters, context, feedback)
        self.assertTrue(ok)
        self.assertTrue(os.path.exists(temp_file))

        # make sure that layer has correct features
        res = QgsVectorLayer(temp_file, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 1)

        QgsProject.instance().removeMapLayer(layer)
예제 #8
0
    def check_algorithm(self, name, defs):
        """
        Will run an algorithm definition and check if it generates the expected result
        :param name: The identifier name used in the test output heading
        :param defs: A python dict containing a test algorithm definition
        """
        self.vector_layer_params = {}
        QgsProject.instance().removeAllMapLayers()

        params = self.load_params(defs['params'])

        print('Running alg: "{}"'.format(defs['algorithm']))
        alg = QgsApplication.processingRegistry().createAlgorithmById(defs['algorithm'])

        parameters = {}
        if isinstance(params, list):
            for param in zip(alg.parameterDefinitions(), params):
                parameters[param[0].name()] = param[1]
        else:
            for k, p in list(params.items()):
                parameters[k] = p

        for r, p in list(defs['results'].items()):
            if not 'in_place_result' in p or not p['in_place_result']:
                parameters[r] = self.load_result_param(p)

        expectFailure = False
        if 'expectedFailure' in defs:
            exec(('\n'.join(defs['expectedFailure'][:-1])), globals(), locals())
            expectFailure = eval(defs['expectedFailure'][-1])

        # ignore user setting for invalid geometry handling
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        if 'skipInvalid' in defs and defs['skipInvalid']:
            context.setInvalidGeometryCheck(QgsFeatureRequest.GeometrySkipInvalid)

        feedback = QgsProcessingFeedback()

        print('Algorithm parameters are {}'.format(parameters))

        # first check that algorithm accepts the parameters we pass...
        ok, msg = alg.checkParameterValues(parameters, context)
        self.assertTrue(ok, 'Algorithm failed checkParameterValues with result {}'.format(msg))

        if expectFailure:
            try:
                results, ok = alg.run(parameters, context, feedback)
                self.check_results(results, context, parameters, defs['results'])
                if ok:
                    raise _UnexpectedSuccess
            except Exception:
                pass
        else:
            results, ok = alg.run(parameters, context, feedback)
            self.assertTrue(ok, 'params: {}, results: {}'.format(parameters, results))
            self.check_results(results, context, parameters, defs['results'])
예제 #9
0
    def test_bad_script_dont_crash(self):  # spellok
        """Test regression #21270 (segfault)"""

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        task = QgsProcessingAlgRunnerTask(CrashingProcessingAlgorithm(), {}, context=context, feedback=feedback)
        self.assertTrue(task.isCanceled())
        self.assertIn('name \'ExampleProcessingAlgorithm\' is not defined', feedback._error)
예제 #10
0
    def check_algorithm(self, name, defs):
        """
        Will run an algorithm definition and check if it generates the expected result
        :param name: The identifier name used in the test output heading
        :param defs: A python dict containing a test algorithm definition
        """
        self.vector_layer_params = {}
        QgsProject.instance().removeAllMapLayers()

        params = self.load_params(defs['params'])

        if defs['algorithm'].startswith('script:'):
            filePath = os.path.join(processingTestDataPath(), 'scripts', '{}.py'.format(defs['algorithm'][len('script:'):]))
            alg = ScriptAlgorithm(filePath)
            alg.initAlgorithm()
        else:
            alg = QgsApplication.processingRegistry().createAlgorithmById(defs['algorithm'])

        parameters = {}
        if isinstance(params, list):
            for param in zip(alg.parameterDefinitions(), params):
                parameters[param[0].name()] = param[1]
        else:
            for k, p in list(params.items()):
                parameters[k] = p

        for r, p in list(defs['results'].items()):
            if not 'in_place_result' in p or not p['in_place_result']:
                parameters[r] = self.load_result_param(p)

        expectFailure = False
        if 'expectedFailure' in defs:
            exec(('\n'.join(defs['expectedFailure'][:-1])), globals(), locals())
            expectFailure = eval(defs['expectedFailure'][-1])

        # ignore user setting for invalid geometry handling
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = QgsProcessingFeedback()

        if expectFailure:
            try:
                results, ok = alg.run(parameters, context, feedback)
                self.check_results(results, context, defs['params'], defs['results'])
                if ok:
                    raise _UnexpectedSuccess
            except Exception:
                pass
        else:
            results, ok = alg.run(parameters, context, feedback)
            self.assertTrue(ok, 'params: {}, results: {}'.format(parameters, results))
            self.check_results(results, context, defs['params'], defs['results'])
예제 #11
0
 def test_bug21373_mode_raster(self):
     """
     This issue is reported on qgis bug tracker: #21373
     """
     context = QgsProcessingContext()
     context.setProject(QgsProject.instance())
     feedback = QgsProcessingFeedback()
     parameters = {
         'in': TestOtbAlgorithms.__input_raster_layer(),
         'filter': 'meanshift',
         'mode': 'raster',
         'mode.raster.out': 'raster.tif'
     }
     alg = OtbAlgorithm('Segmentation', 'Segmentation', os.path.join(self.descrFolder, 'Segmentation.txt'))
     results = alg.processAlgorithm(parameters, context, feedback)
     self.assertDictEqual(results, {'mode.raster.out': 'raster.tif'})
예제 #12
0
    def test_bug21374_Fail(self):
        """
        This issue is reported on qgis bug tracker: #21374
        """
        outdir = tempfile.mkdtemp()
        self.cleanup_paths.append(outdir)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = QgsProcessingFeedback()
        parameters = {
            'in': TestOtbAlgorithms.__input_raster_layer(),
            'filter': 'cc',
            'mode.vector.out': os.path.join(outdir, 'vector.shp')
        }

        alg = OtbAlgorithm('Segmentation', 'Segmentation', os.path.join(self.descrFolder, 'Segmentation.txt'))
        ok, msg = alg.checkParameterValues(parameters, context)
        self.assertFalse(ok, 'Algorithm failed checkParameterValues with result {}'.format(msg))
예제 #13
0
    def testRunAndLoadResults(self):
        QgsProject.instance().removeAllMapLayers()
        context = QgsProcessingContext()

        # try running an alg using processing.runAndLoadResults - ownership of result layer should be transferred to
        # project, and layer should be present in project
        res = processing.runAndLoadResults('qgis:buffer',
                                           {'DISTANCE': 1, 'INPUT': points(), 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT},
                                           context=context)
        self.assertIn('OUTPUT', res)
        # output should be the layer path
        self.assertIsInstance(res['OUTPUT'], str)

        self.assertEqual(context.layersToLoadOnCompletion()[res['OUTPUT']].project, QgsProject.instance())
        layer = QgsProject.instance().mapLayer(res['OUTPUT'])
        self.assertIsInstance(layer, QgsVectorLayer)

        # Python should NOT have ownership
        self.assertFalse(sip.ispyowned(layer))
예제 #14
0
    def _make_compatible_tester(self, feature_wkt, layer_wkb_name, attrs=[1]):
        layer = self._make_layer(layer_wkb_name)
        layer.startEditing()

        f = QgsFeature(layer.fields())
        f.setAttributes(attrs)
        f.setGeometry(QgsGeometry.fromWkt(feature_wkt))
        self.assertTrue(f.isValid())

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        # Fix it!
        new_features = make_features_compatible([f], layer)

        for new_f in new_features:
            self.assertEqual(new_f.geometry().wkbType(), layer.wkbType())

        self.assertTrue(layer.addFeatures(new_features), "Fail: %s - %s - %s" % (feature_wkt, attrs, layer_wkb_name))
        return layer, new_features
예제 #15
0
    def test_non_ascii_output(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer("Point?crs=epsg:3857&field=fldtxt:string&field=fldint:integer",
                               "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(110, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)
        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById('saga:fixeddistancebuffer')
        self.assertIsNotNone(alg)

        temp_file = os.path.join(self.temp_dir, 'non_ascii_ñññ.shp')
        parameters = {'SHAPES': 'testmem',
                      'DIST_FIELD_DEFAULT': 5,
                      'NZONES': 1,
                      'DARC': 5,
                      'DISSOLVE': False,
                      'POLY_INNER': False,
                      'BUFFER': temp_file}
        feedback = QgsProcessingFeedback()

        results, ok = alg.run(parameters, context, feedback)
        self.assertTrue(ok)
        self.assertTrue(os.path.exists(temp_file))

        # make sure that layer has correct features
        res = QgsVectorLayer(temp_file, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 2)

        QgsProject.instance().removeMapLayer(layer)
예제 #16
0
    def createBaseMapLayer(self, map_theme, layer, tile_size, map_units_per_pixel):
        """
        Create a basemap from map layer(s)

        :param dataPath:             The path where the basemap should be writtent to
        :param extent:               The extent rectangle in which data shall be fetched
        :param map_theme:            The name of the map theme to be rendered
        :param layer:                A layer id to be rendered. Will only be used if map_theme is None.
        :param tile_size:            The extent rectangle in which data shall be fetched
        :param map_units_per_pixel:  Number of map units per pixel (1: 1 m per pixel, 10: 10 m per pixel...)
        """
        extent_string = '{},{},{},{}'.format(self.extent.xMinimum(), self.extent.xMaximum(), self.extent.yMinimum(),
                                             self.extent.yMaximum())

        alg = QgsApplication.instance().processingRegistry().createAlgorithmById('qgis:rasterize')

        params = {
            'EXTENT': extent_string,
            'MAP_THEME': map_theme,
            'LAYER': layer,
            'MAP_UNITS_PER_PIXEL': map_units_per_pixel,
            'TILE_SIZE': tile_size,
            'MAKE_BACKGROUND_TRANSPARENT': False,

            'OUTPUT': os.path.join(self.export_folder, 'basemap.gpkg')
        }

        feedback = QgsProcessingFeedback()
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        results, ok = alg.run(params, context, feedback)

        new_layer = QgsRasterLayer(results['OUTPUT'], self.tr('Basemap'))

        resample_filter = new_layer.resampleFilter()
        resample_filter.setZoomedInResampler(QgsCubicRasterResampler())
        resample_filter.setZoomedOutResampler(QgsBilinearRasterResampler())
        self.project_configuration.project.addMapLayer(new_layer, False)
        layer_tree = QgsProject.instance().layerTreeRoot()
        layer_tree.insertLayer(len(layer_tree.children()), new_layer)
예제 #17
0
    def testGetOgrCompatibleSourceFromFeatureSource(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                               "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)
        # select first feature
        layer.selectByIds([next(layer.getFeatures()).id()])
        self.assertEqual(len(layer.selectedFeatureIds()), 1)
        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById('gdal:buffervectors')
        self.assertIsNotNone(alg)
        parameters = {'INPUT': QgsProcessingFeatureSourceDefinition('testmem', True)}
        feedback = QgsProcessingFeedback()
        # check that memory layer is automatically saved out to shape when required by GDAL algorithms
        ogr_data_path, ogr_layer_name = alg.getOgrCompatibleSource('INPUT', parameters, context, feedback,
                                                                   executing=True)
        self.assertTrue(ogr_data_path)
        self.assertTrue(ogr_data_path.endswith('.shp'))
        self.assertTrue(os.path.exists(ogr_data_path))
        self.assertTrue(ogr_layer_name)

        # make sure that layer has only selected feature
        res = QgsVectorLayer(ogr_data_path, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 1)

        QgsProject.instance().removeMapLayer(layer)
예제 #18
0
    def processAlgorithm(self, parameters, context, feedback):
        connection = self.parameterAsString(parameters, self.DATABASE, context)
        id_field = self.parameterAsString(parameters, self.ID_FIELD, context)
        geom_field = self.parameterAsString(parameters, self.GEOMETRY_FIELD,
                                            context)
        uri = postgis.uri_from_name(connection)
        sql = self.parameterAsString(parameters, self.SQL, context)
        sql = sql.replace('\n', ' ')
        uri.setDataSource("", "(" + sql + ")", geom_field, "", id_field)

        vlayer = QgsVectorLayer(uri.uri(), "layername", "postgres")

        if not vlayer.isValid():
            raise QgsProcessingException(
                self.tr("""This layer is invalid!
                Please check the PostGIS log for error messages."""))

        context.temporaryLayerStore().addMapLayer(vlayer)
        context.addLayerToLoadOnCompletion(
            vlayer.id(),
            QgsProcessingContext.LayerDetails('SQL layer', context.project(),
                                              self.OUTPUT))

        return {self.OUTPUT: vlayer.id()}
예제 #19
0
    def test_getConnectionString(self):

        obj = Ogr2OgrToPostGis()
        obj.initAlgorithm({})

        parameters = {}
        context = QgsProcessingContext()

        # NOTE: defaults are debatable, see
        # https://github.com/qgis/QGIS/pull/3607#issuecomment-253971020
        self.assertEqual(obj.getConnectionString(parameters, context),
                         "host=localhost port=5432 active_schema=public")

        parameters['HOST'] = 'remote'
        self.assertEqual(obj.getConnectionString(parameters, context),
                         "host=remote port=5432 active_schema=public")

        parameters['HOST'] = ''
        self.assertEqual(obj.getConnectionString(parameters, context),
                         "port=5432 active_schema=public")

        parameters['PORT'] = '5555'
        self.assertEqual(obj.getConnectionString(parameters, context),
                         "port=5555 active_schema=public")

        parameters['PORT'] = ''
        self.assertEqual(obj.getConnectionString(parameters, context),
                         "active_schema=public")

        parameters['USER'] = '******'
        self.assertEqual(obj.getConnectionString(parameters, context),
                         "active_schema=public user=usr")

        parameters['PASSWORD'] = '******'
        self.assertEqual(obj.getConnectionString(parameters, context),
                         "password=pwd active_schema=public user=usr")
예제 #20
0
    def _alg_tester(self,
                    alg_name,
                    input_layer,
                    parameters,
                    invalid_geometry_policy=QgsFeatureRequest.GeometryNoCheck,
                    retain_selection=False):

        alg = self.registry.createAlgorithmById(alg_name)

        self.assertIsNotNone(alg)
        parameters['INPUT'] = input_layer
        parameters['OUTPUT'] = 'memory:'

        old_features = [f for f in input_layer.getFeatures()]

        if not retain_selection:
            input_layer.selectByIds([old_features[0].id()])
            # Check selected
            self.assertEqual(input_layer.selectedFeatureIds(),
                             [old_features[0].id()], alg_name)

        context = QgsProcessingContext()
        context.setInvalidGeometryCheck(invalid_geometry_policy)
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        input_layer.rollBack()
        ok = False
        ok, _ = execute_in_place_run(alg,
                                     parameters,
                                     context=context,
                                     feedback=feedback,
                                     raise_exceptions=True)
        new_features = [f for f in input_layer.getFeatures()]

        # Check ret values
        self.assertTrue(ok, alg_name)

        # Check geometry types (drop Z or M)
        self.assertEqual(new_features[0].geometry().wkbType(),
                         old_features[0].geometry().wkbType())

        return old_features, new_features
예제 #21
0
    def testValues(self):
        context = QgsProcessingContext()

        # disable check for geometry validity
        context.setFlags(QgsProcessingContext.Flags(0))

        test_data = points()
        test_layer = QgsVectorLayer(test_data, 'test', 'ogr')

        # field by index
        res = vector.values(test_layer, context, 1)
        self.assertEqual(res[1], [1, 2, 3, 4, 5, 6, 7, 8, 9])

        # field by name
        res = vector.values(test_layer, context, 'id')
        self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8, 9])

        # two fields
        res = vector.values(test_layer, context, 1, 2)
        self.assertEqual(res[1], [1, 2, 3, 4, 5, 6, 7, 8, 9])
        self.assertEqual(res[2], [2, 1, 0, 2, 1, 0, 0, 0, 0])

        # two fields by name
        res = vector.values(test_layer, context, 'id', 'id2')
        self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8, 9])
        self.assertEqual(res['id2'], [2, 1, 0, 2, 1, 0, 0, 0, 0])

        # two fields by name and index
        res = vector.values(test_layer, context, 'id', 2)
        self.assertEqual(res['id'], [1, 2, 3, 4, 5, 6, 7, 8, 9])
        self.assertEqual(res[2], [2, 1, 0, 2, 1, 0, 0, 0, 0])

        # test with selected features
        context.setFlags(QgsProcessingContext.UseSelectionIfPresent)
        test_layer.selectByIds([2, 4, 6])
        res = vector.values(test_layer, context, 1)
        self.assertEqual(set(res[1]), set([5, 7, 3]))
    def processAlgorithm(self, parameters, context, feedback):
        destination = self.parameterAsFile(parameters, self.DESTINATION,
                                           context)

        try:
            db = postgis.GeoDB.from_name(destination)
            is_geopackage = False
            schema = self.parameterAsFile(parameters, self.SCHEMA, context)
        except QgsProcessingException:
            is_geopackage = True
            schema = None

        if is_geopackage:
            if not destination.lower().endswith('.gpkg'):
                destination += '.gpkg'
            uri = destination
        else:
            database_uri = db.uri
            info = database_uri.connectionInfo(True)
            conn = psycopg2.connect(info)
            cur = conn.cursor()
            sql = "DROP VIEW IF EXISTS {}.{};".format(schema, self.VIEW_NAME)
            feedback.pushInfo(sql)
            cur.execute(sql)
            conn.commit()

        crs = self.parameterAsCrs(parameters, self.CRS, context)

        options = dict()
        options['update'] = True

        if is_geopackage:
            options['layerOptions'] = ['FID=id']
            options['fileEncoding'] = 'UTF-8'

        output_layers = []
        for table, geom in MAPPING.items():
            # create virtual layer
            if geom[0]:
                vl_path = '{}?crs={}&'.format(geom[0], crs.authid())
            else:
                vl_path = 'None?'

            csv_path = resources_path('data_models', '{}.csv'.format(table))
            csv = QgsVectorLayer(csv_path, table, 'ogr')
            if not csv.isValid():
                csv_path = resources_path('data_models',
                                          '{}.csv'.format(table))
                raise QgsProcessingException(
                    tr('* ERROR: Can\'t load CSV {}').format(csv_path))

            fields = []
            for c_f in csv.getFeatures():
                fields.append('field={}:{}'.format(c_f['name'],
                                                   c_f['typeName']))
            del csv

            vl_path += '&'.join(fields)
            LOGGER.debug('Memory layer "{}" created with {}'.format(
                table, vl_path))
            vl = QgsVectorLayer(vl_path, table, 'memory')

            if vl.fields().count() != len(fields):
                raise QgsProcessingException(
                    tr('* ERROR while creating fields in layer "{}"').format(
                        table))

            # export layer
            options['layerName'] = vl.name()
            if not is_geopackage:
                uri = QgsDataSourceUri(database_uri)
                if Qgis.QGIS_VERSION_INT >= 31000:
                    uri.setTable(vl.name())
                    if vl.isSpatial():
                        uri.setGeometryColumn('geom')
                else:
                    uri_string = uri.uri(True)
                    if vl.isSpatial():
                        uri_string = uri_string.replace(
                            'table=""', 'table="{}" (geom)'.format(vl.name()))
                    else:
                        uri_string = uri_string.replace(
                            'table=""', 'table="{}"'.format(vl.name()))
                    uri = QgsDataSourceUri(uri_string)
                # Schema is updating the table name,
                # so after search&replace
                uri.setSchema(schema)
                uri.setKeyColumn(vl.fields().at(0).name())

            exporter = QgsVectorLayerExporter(
                uri if is_geopackage else uri.uri(),
                'ogr' if is_geopackage else 'postgres', vl.fields(),
                vl.wkbType(), vl.crs(), True, options)

            # result
            if exporter.errorCode() != QgsVectorLayerExporter.NoError:
                source = uri if is_geopackage else uri.uri()
                raise QgsProcessingException(
                    tr('* ERROR while exporting the layer to "{}":"{}"').
                    format(source, exporter.errorMessage()))

            # Do create sequence
            if geom[2] and not is_geopackage:
                cur = conn.cursor()
                sql = "CREATE SEQUENCE {}.{}_{}_seq;".format(
                    schema, table, geom[2])
                cur.execute(sql)
                conn.commit()
                sql = ("ALTER TABLE {0}.{1} "
                       "ALTER COLUMN {2} "
                       "SET DEFAULT nextval('{0}.{1}_{2}_seq'::regclass);"
                       ).format(schema, table, geom[2])
                cur.execute(sql)
                conn.commit()

            # connection troncon_rereau_classif in geopackage
            if is_geopackage:
                dest_layer = QgsVectorLayer(
                    '{}|layername={}'.format(uri, table), table, 'ogr')
            else:
                uri = QgsDataSourceUri(database_uri)
                if Qgis.QGIS_VERSION_INT >= 31000:
                    uri.setTable(vl.name())
                    if vl.isSpatial():
                        uri.setGeometryColumn('geom')
                else:
                    uri_string = uri.uri(True)
                    if vl.isSpatial():
                        uri_string = uri_string.replace(
                            'table=""', 'table="{}" (geom)'.format(vl.name()))
                    else:
                        uri_string = uri_string.replace(
                            'table=""', 'table="{}"'.format(vl.name()))
                    uri = QgsDataSourceUri(uri_string)
                # Schema is updating the table name,
                # so after search&replace
                uri.setSchema(schema)
                uri.setKeyColumn(vl.fields().at(0).name())
                dest_layer = QgsVectorLayer(uri.uri(False), table, 'postgres')
            if not dest_layer.isValid():
                source = uri if is_geopackage else uri.uri()
                raise QgsProcessingException(
                    tr('* ERROR: Can\'t load table "{}" in URI "{}"').format(
                        table, source))

            feedback.pushInfo('The layer {} has been created'.format(table))

            output_layers.append(dest_layer.id())

            # Add layer to project
            context.temporaryLayerStore().addMapLayer(dest_layer)
            context.addLayerToLoadOnCompletion(
                dest_layer.id(),
                QgsProcessingContext.LayerDetails(table, context.project(),
                                                  self.OUTPUT_LAYERS))

        # Get connection
        if is_geopackage:
            conn = spatialite_connect(uri)

        # Do create view
        cur = conn.cursor()
        prefix = ''
        view_destination = self.VIEW_NAME
        if not is_geopackage:
            prefix = '{}.'.format(schema)
            view_destination = '{}{}'.format(prefix, view_destination)
        sql = ("CREATE VIEW {0} AS "
               "SELECT r.id, r.caa, r.id_geom_regard, r.id_file, g.geom "
               "FROM {1}regard r, {1}geom_regard g "
               "WHERE r.id_geom_regard = g.id;").format(
                   view_destination, prefix)
        feedback.pushInfo(sql)
        cur.execute(sql)
        conn.commit()

        if is_geopackage:
            sql = ("INSERT INTO gpkg_contents "
                   "(table_name, identifier, data_type, srs_id) "
                   "VALUES ( '{0}', '{0}', 'features', {1});").format(
                       self.VIEW_NAME, crs.postgisSrid())
            feedback.pushInfo(sql)
            cur.execute(sql)
            conn.commit()
            sql = (
                "INSERT INTO gpkg_geometry_columns "
                "(table_name, column_name, geometry_type_name, srs_id, z, m) "
                "VALUES ('{0}', 'geom', 'POINT', {1}, 0, 0);").format(
                    self.VIEW_NAME, crs.postgisSrid())
            feedback.pushInfo(sql)
            cur.execute(sql)
            conn.commit()

        conn.close()

        # Connexion à la couche view_regard_localized dans le Geopackage
        if is_geopackage:
            view_layer = QgsVectorLayer(
                '{}|layername={}'.format(uri, self.VIEW_NAME), self.VIEW_NAME,
                'ogr')
        else:
            uri = QgsDataSourceUri(database_uri)
            if Qgis.QGIS_VERSION_INT >= 31000:
                uri.setTable(self.VIEW_NAME)
                uri.setGeometryColumn('geom')
            else:
                uri_string = uri.uri(True)
                uri_string = uri_string.replace(
                    'table=""', 'table="{}" (geom)'.format(self.VIEW_NAME))
                uri = QgsDataSourceUri(uri_string)
            # Schema is updating the table name,
            # so after search&replace
            uri.setSchema(schema)
            uri.setKeyColumn('id')
            view_layer = QgsVectorLayer(uri.uri(False), self.VIEW_NAME,
                                        'postgres')
        if not view_layer.isValid():
            source = uri if is_geopackage else uri.uri()
            raise QgsProcessingException(
                tr('* ERROR: Can\'t load layer {} in {}').format(
                    self.VIEW_NAME, source))

        output_layers.append(view_layer.id())

        # Add layer to project
        context.temporaryLayerStore().addMapLayer(view_layer)
        context.addLayerToLoadOnCompletion(
            view_layer.id(),
            QgsProcessingContext.LayerDetails(self.VIEW_NAME,
                                              context.project(),
                                              self.OUTPUT_LAYERS))

        feedback.pushInfo('The data model has been created in {}'.format(uri))

        return {self.DESTINATION: uri, self.OUTPUT_LAYERS: output_layers}
예제 #23
0
def createContext(feedback=None):
    """
    Creates a default processing context
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())
    context.setFeedback(feedback)

    invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if invalid_features_method is None:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding", "System"))

    context.setExpressionContext(createExpressionContext())

    return context
예제 #24
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        source = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        field_insee = self.parameterAsString(parameters, self.INSEE_CODE,
                                             context)
        field_commune = self.parameterAsString(parameters, self.COMMUNE_NAME,
                                               context)
        value_epsg = self.parameterAsString(parameters, self.EPSG_CODE,
                                            context)

        if value_epsg == '2154' or value_epsg == '3942' or value_epsg == '3943' or value_epsg == '3944' or value_epsg == '3945' or value_epsg == '3946' or value_epsg == '3947' or value_epsg == '3948' or value_epsg == '3949' or value_epsg == '3950' or value_epsg == '32630' or value_epsg == ' 32631' or value_epsg == '32632' or value_epsg == '3857' or value_epsg == '4326' or value_epsg == '4258' or value_epsg == '32620' or value_epsg == '2970' or value_epsg == '2972' or value_epsg == '2973' or value_epsg == '2975' or value_epsg == '32622' or value_epsg == '32740' or value_epsg == '32738' or value_epsg == '4471' or value_epsg == '32621':

            feedback.pushInfo('EPSG code' + value_epsg)
            tab = []

            for f in source.getFeatures():

                col_select = f[field_insee], (''.join(
                    (c for c in unicodedata.normalize('NFD', f[field_commune])
                     if unicodedata.category(c) != 'Mn')))

                # Insere chaque ligne du CSV dans le tableau
                tab.append(col_select)

                #Permet la suppression des doublons et le tri
                Lt = sorted(set(tab))

                print(Lt)

            for c_insee, n_couche in Lt:

                urlWithParams = "url=http://inspire.cadastre.gouv.fr/scpc/" + c_insee + ".wms?contextualWMSLegend=0&crs=EPSG:" + value_epsg + "&dpiMode=7&featureCount=10&format=image/png&layers=VOIE_COMMUNICATION&styles=&maxHeight=1024&maxWidth=1280"
                rlayer = QgsRasterLayer(
                    urlWithParams, 'Petites_voies_de_communication_' +
                    n_couche + '_' + c_insee, 'wms')
                feedback.pushInfo('Category :' + n_couche + ' - ' + c_insee)
                feedback.pushInfo('Validity of WMS : %s' % rlayer.isValid())
                if not rlayer.isValid():
                    print('Petites_voies_de_communication_' + n_couche + '_' +
                          c_insee + ' failed to load!')
                    feedback.pushInfo('WMS INVALID : Cadastre_' + n_couche +
                                      '_' + c_insee)
                else:
                    #Source : https://gis.stackexchange.com/questions/342802/loading-openstreetmap-in-pyqgis
                    output_layers = []
                    output_layers.append(rlayer)
                    context.temporaryLayerStore().addMapLayer(rlayer)
                    context.addLayerToLoadOnCompletion(
                        rlayer.id(),
                        QgsProcessingContext.LayerDetails(
                            'Petites_voies_de_communication_' + n_couche +
                            '_' + c_insee, context.project(),
                            self.OUTPUT_LAYERS))
        else:
            feedback.pushInfo('Error EPSG code')

        # Return the results of the algorithm. In this case our only result is
        # the feature sink which contains the processed features, but some
        # algorithms may return multiple feature sinks, calculated numeric
        # statistics, etc. These should all be included in the returned
        # dictionary, with keys matching the feature corresponding parameter
        # or output names.
        # At the end of the processAlgorithmn
        # Add the layer to the project
        return {}
예제 #25
0
    def test_check_validity(self):
        """Test that the output invalid contains the error reason"""

        polygon_layer = self._make_layer('Polygon')
        self.assertTrue(polygon_layer.startEditing())
        f = QgsFeature(polygon_layer.fields())
        f.setAttributes([1])
        # Flake!
        f.setGeometry(
            QgsGeometry.fromWkt('POLYGON ((0 0, 2 2, 0 2, 2 0, 0 0))'))
        self.assertTrue(f.isValid())
        f2 = QgsFeature(polygon_layer.fields())
        f2.setAttributes([1])
        f2.setGeometry(
            QgsGeometry.fromWkt(
                'POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))'))
        self.assertTrue(f2.isValid())
        self.assertTrue(polygon_layer.addFeatures([f, f2]))
        polygon_layer.commitChanges()
        polygon_layer.rollBack()
        self.assertEqual(polygon_layer.featureCount(), 2)

        QgsProject.instance().addMapLayers([polygon_layer])

        alg = self.registry.createAlgorithmById('qgis:checkvalidity')

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        self.assertIsNotNone(alg)
        parameters = {}
        parameters['INPUT_LAYER'] = polygon_layer.id()
        parameters['VALID_OUTPUT'] = 'memory:'
        parameters['INVALID_OUTPUT'] = 'memory:'
        parameters['ERROR_OUTPUT'] = 'memory:'

        # QGIS method
        parameters['METHOD'] = 1
        ok, results = execute(alg,
                              parameters,
                              context=context,
                              feedback=feedback)
        self.assertTrue(ok)
        invalid_layer = QgsProcessingUtils.mapLayerFromString(
            results['INVALID_OUTPUT'], context)
        self.assertEqual(invalid_layer.fields().names()[-1], '_errors')
        self.assertEqual(invalid_layer.featureCount(), 1)
        f = next(invalid_layer.getFeatures())
        self.assertEqual(f.attributes(),
                         [1, 'segments 0 and 2 of line 0 intersect at 1, 1'])

        # GEOS method
        parameters['METHOD'] = 2
        ok, results = execute(alg,
                              parameters,
                              context=context,
                              feedback=feedback)
        self.assertTrue(ok)
        invalid_layer = QgsProcessingUtils.mapLayerFromString(
            results['INVALID_OUTPUT'], context)
        self.assertEqual(invalid_layer.fields().names()[-1], '_errors')
        self.assertEqual(invalid_layer.featureCount(), 1)
        f = next(invalid_layer.getFeatures())
        self.assertEqual(f.attributes(), [1, 'Self-intersection'])
예제 #26
0
    def testInputs(self):
        """
        Test creation of script with algorithm inputs
        """
        alg = RAlgorithm(description_file=os.path.join(test_data_path,
                                                       'test_algorithm_2.rsx'))
        alg.initAlgorithm()

        context = QgsProcessingContext()
        feedback = QgsProcessingFeedback()

        # enum evaluation
        script = alg.build_import_commands({'in_enum': 0}, context, feedback)
        self.assertIn('in_enum <- 0', script)

        # boolean evaluation
        script = alg.build_import_commands({'in_bool': True}, context,
                                           feedback)
        self.assertIn('in_bool <- TRUE', script)
        script = alg.build_import_commands({'in_bool': False}, context,
                                           feedback)
        self.assertIn('in_bool <- FALSE', script)

        # number evaluation
        script = alg.build_import_commands({'in_number': None}, context,
                                           feedback)
        self.assertIn('in_number <- NULL', script)
        script = alg.build_import_commands({'in_number': 5}, context, feedback)
        self.assertIn('in_number <- 5.0', script)
        script = alg.build_import_commands({'in_number': 5.5}, context,
                                           feedback)
        self.assertIn('in_number <- 5.5', script)

        # folder destination
        script = alg.build_import_commands(
            {'param_folder_dest': '/tmp/processing/test_algorithm_2_r/'},
            context, feedback)

        # file destination
        script = alg.build_import_commands(
            {
                'param_html_dest':
                '/tmp/processing/test_algorithm_2_r/dest.html'
            }, context, feedback)
        self.assertIn(
            'param_html_dest <- "/tmp/processing/test_algorithm_2_r/dest.html"',
            script)
        script = alg.build_import_commands(
            {
                'param_file_dest':
                '/tmp/processing/test_algorithm_2_r/dest.file'
            }, context, feedback)
        self.assertIn(
            'param_file_dest <- "/tmp/processing/test_algorithm_2_r/dest.file"',
            script)
        script = alg.build_import_commands(
            {'param_csv_dest': '/tmp/processing/test_algorithm_2_r/dest.csv'},
            context, feedback)
        self.assertIn(
            'param_csv_dest <- "/tmp/processing/test_algorithm_2_r/dest.csv"',
            script)
예제 #27
0
    def _export_basemap(self) -> bool:
        self.total_progress_updated.emit(0, 1,
                                         self.trUtf8("Creating base map…"))

        if not self._export_basemap_requirements_check():
            return False

        project = QgsProject.instance()
        basemap_extent = self.area_of_interest.boundingBox()

        if basemap_extent.isNull() or not basemap_extent.isFinite():
            self.warning.emit(
                self.tr("Failed to create basemap"),
                self.tr(
                    "Cannot create basemap for the given area of interest."),
            )
            return False

        if not self.project_configuration.base_map_layer.strip():
            self.warning.emit(
                self.tr("Failed to create basemap"),
                self.
                tr("No basemap layer selected. Please check the project configuration."
                   ).format(self.project_configuration.base_map_layer),
            )
            return False

        extent = basemap_extent
        base_map_type = self.project_configuration.base_map_type
        if base_map_type == ProjectProperties.BaseMapType.SINGLE_LAYER:
            basemap_layer = project.mapLayer(
                self.project_configuration.base_map_layer)

            if not basemap_layer:
                self.warning.emit(
                    self.tr("Failed to create basemap"),
                    self.
                    tr('Cannot find the configured base layer with id "{}". Please check the project configuration.'
                       ).format(self.project_configuration.base_map_layer),
                )
                return False

            # we need to transform the extent to match the one of the selected layer
            extent = QgsCoordinateTransform(
                QgsCoordinateReferenceSystem(self.area_of_interest_crs),
                project.crs(),
                project,
            ).transformBoundingBox(basemap_extent)
        elif base_map_type == ProjectProperties.BaseMapType.MAP_THEME:
            if not project.mapThemeCollection().hasMapTheme(
                    self.project_configuration.base_map_theme):
                self.warning.emit(
                    self.tr("Failed to create basemap"),
                    self.
                    tr('Cannot find the configured base theme with name "{}". Please check the project configuration.'
                       ).format(self.project_configuration.base_map_theme),
                )
                return False

        extent_string = "{},{},{},{}".format(
            extent.xMinimum(),
            extent.xMaximum(),
            extent.yMinimum(),
            extent.yMaximum(),
        )

        alg = (QgsApplication.instance().processingRegistry().
               createAlgorithmById("native:rasterize"))

        params = {
            "EXTENT": extent_string,
            "EXTENT_BUFFER": 0,
            "TILE_SIZE": self.project_configuration.base_map_tile_size,
            "MAP_UNITS_PER_PIXEL": self.project_configuration.base_map_mupp,
            "MAKE_BACKGROUND_TRANSPARENT": False,
            "OUTPUT": os.path.join(self.export_folder, "basemap.gpkg"),
        }

        if base_map_type == ProjectProperties.BaseMapType.SINGLE_LAYER:
            params["LAYERS"] = [self.project_configuration.base_map_layer]
        elif base_map_type == ProjectProperties.BaseMapType.MAP_THEME:
            params["MAP_THEME"] = self.project_configuration.base_map_theme

        feedback = QgsProcessingFeedback()
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        results, ok = alg.run(params, context, feedback)

        if not ok:
            self.warning.emit(self.tr("Failed to create basemap"),
                              feedback.textLog())
            return False

        new_layer = QgsRasterLayer(results["OUTPUT"], self.tr("Basemap"))

        resample_filter = new_layer.resampleFilter()
        resample_filter.setZoomedInResampler(QgsCubicRasterResampler())
        resample_filter.setZoomedOutResampler(QgsBilinearRasterResampler())
        self.project_configuration.project.addMapLayer(new_layer, False)
        layer_tree = QgsProject.instance().layerTreeRoot()
        layer_tree.insertLayer(len(layer_tree.children()), new_layer)

        return True
예제 #28
0
    def testGdalTranslate(self):
        context = QgsProcessingContext()
        feedback = QgsProcessingFeedback()
        source = os.path.join(testDataPath, 'dem.tif')
        translate_alg = translate()
        translate_alg.initAlgorithm()

        # with no NODATA value
        self.assertEqual(
            translate_alg.getConsoleCommands({'INPUT': source,
                                              'OUTPUT': 'd:/temp/check.jpg'}, context, feedback),
            ['gdal_translate',
             '-ot Float32 -of JPEG ' +
             source + ' ' +
             'd:/temp/check.jpg'])
        # with NODATA value
        self.assertEqual(
            translate_alg.getConsoleCommands({'INPUT': source,
                                              'NODATA': 9999,
                                              'OUTPUT': 'd:/temp/check.jpg'}, context, feedback),
            ['gdal_translate',
             '-a_nodata 9999.0 ' +
             '-ot Float32 -of JPEG ' +
             source + ' ' +
             'd:/temp/check.jpg'])
        # with "0" NODATA value
        self.assertEqual(
            translate_alg.getConsoleCommands({'INPUT': source,
                                              'NODATA': 0,
                                              'OUTPUT': 'd:/temp/check.jpg'}, context, feedback),
            ['gdal_translate',
             '-a_nodata 0.0 ' +
             '-ot Float32 -of JPEG ' +
             source + ' ' +
             'd:/temp/check.jpg'])
        # with target srs
        self.assertEqual(
            translate_alg.getConsoleCommands({'INPUT': source,
                                              'TARGET_CRS': 'EPSG:3111',
                                              'OUTPUT': 'd:/temp/check.jpg'}, context, feedback),
            ['gdal_translate',
             '-a_srs EPSG:3111 ' +
             '-ot Float32 -of JPEG ' +
             source + ' ' +
             'd:/temp/check.jpg'])
        # with target srs
        self.assertEqual(
            translate_alg.getConsoleCommands({'INPUT': source,
                                              'TARGET_CRS': 'EPSG:3111',
                                              'OUTPUT': 'd:/temp/check.jpg'}, context, feedback),
            ['gdal_translate',
             '-a_srs EPSG:3111 ' +
             '-ot Float32 -of JPEG ' +
             source + ' ' +
             'd:/temp/check.jpg'])
        # with copy subdatasets
        self.assertEqual(
            translate_alg.getConsoleCommands({'INPUT': source,
                                              'COPY_SUBDATASETS': True,
                                              'OUTPUT': 'd:/temp/check.tif'}, context, feedback),
            ['gdal_translate',
             '-sds ' +
             '-ot Float32 -of GTiff ' +
             source + ' ' +
             'd:/temp/check.tif'])
예제 #29
0
파일: dataobjects.py 프로젝트: rskelly/QGIS
def createContext():
    """
    Creates a default processing context
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())

    invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if invalid_features_method is None:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    def raise_error(f):
        raise GeoAlgorithmExecutionException(QCoreApplication.translate("FeatureIterator",
                                                                        'Features with invalid geometries found. Please fix these geometries or specify the "Ignore invalid input features" flag'))

    context.setInvalidGeometryCallback(raise_error)

    def raise_transform_error(f):
        raise GeoAlgorithmExecutionException(QCoreApplication.translate("FeatureIterator",
                                                                        'Encountered a transform error when reprojecting feature with id {}.'.format(f.id())))
    context.setTransformErrorCallback(raise_transform_error)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding", "System"))

    return context
예제 #30
0
    def produce_warped_tif(self, write_result):
        
        self.out("produce_warped_tif()")
        
        """
        ASCII to warped TIF
        """
        
        # very important!
        if path.exists(self._full_tif_filename):
            #self.out("removing old version of warped TIF before creating a new one...")
            os.remove(self._full_tif_filename)
        
        
        proj_radolan = self._model.projection_radolan
        
        """
        METHOD Options:
        0 - near
        1 - bilinear
        2 - cubic
        3 - cubicspline
        4 - lanczos
        Eigentlich Default: 0 - aber man muss es angeben (QGIS 2.14 "Essen")
        
        RTYPE:  default: 5 = Float32
        
        COMPRESS(GeoTIFF options. Compression type:)
        0 - NONE
        1 - JPEG
        2 - LZW
        3 - PACKBITS
        4 - DEFLATE
        wohl kein Default, also angeben
        """
        # Standard (certain) params:
        params = {
            "INPUT":      self._full_asc_filename,
            "SOURCE_SRS": proj_radolan,
            #"DEST_SRS":  'EPSG:3035',    # QGIS 2?
            "TARGET_CRS": 'EPSG:3035',
            "METHOD":     0,
            "COMPRESS":   4
        }
        
        """
        useful tip:
        If you don't need to use the output for further elaborations, you may save it as memory layer.
        For doing this you only need to set the 'output' parameter as None:
        
        first = processing.runalg("gdalogr:warpreproject", { "INPUT": ... , "OUTPUT": None } )
        
        Instead, if you want to use the output, you may easily do this by giving it a name and
        then by calling it with getObject():
        
        second = processing.getObject( first['OUTPUT'] )

        -> https://gis.stackexchange.com/questions/224389/pyqgis-processing-runalg-release-input-in-windows
        """
        
        #params['OUTPUT'] = self._full_tif_filename if write_result  else None
        params['OUTPUT'] = self._full_tif_filename if write_result  else 'none'    # in QGIS 3. Verrückt
        
        
        # New GdalUtils version with some additional parameters! (RAST_EXT, ...)
        #if version >= 2000000:
        # Other possibility:
        #>>> QgsExpressionContextUtils.globalScope().variableNames(): show all avail vars
        #>>> QgsExpressionContextUtils.globalScope().variable('qgis_version')       # with name
        # out: u'2.99.0-Master'
        #>>> QgsExpressionContextUtils.globalScope().variable('qgis_version_no')    # better
        
        """ .............................................................
        HERE WE CAN SEND A GDAL CALL ADAPTED TO THE CORRESPONDING VERION!
        ............................................................. """
        
        add_additional_keys = False
        
        try:
            version = GdalUtils.version()
            
            if platform.system() == 'Windows':
                system_name = "{} {}".format(platform.system(), platform.release())
                raise OSError("Running on '{}'".format(system_name))
            
        #except AttributeError as ex:    # ex: class GdalUtils has no attribute 'version'
        except AttributeError:
            self.out("WARN: GdalUtils.version could not determined (older version?)", False)
            self.out("continue without dict keys 'RAST_EXT', 'EXT_CRS'", False)
        
        except OSError as e:
            self.out(e, False)
            self.out("continue without dict keys 'RAST_EXT', 'EXT_CRS'", False)
        
        # Nur wenn Try OK: section for determining the extent of input raster by creating layer datatype
        else:
            self.out("GdalUtils.version is {}".format(version))
            # Result for
            # Dev-Version/Linux:  2010200
            # 2.18.15 Las Palmas: 2020300
            
            # Für diese Versionsnummer ging es nämlich NICHT! (openSUSE Leap 42.3, obige QGIS-Version)
            if version != 2020300:
                add_additional_keys = True
            
        # Ende try-except-else-Block
        
        
        if add_additional_keys:
            # Make layer type from ASCII file to determine the mandatory 'extent':
            asc_layer = self._create_QGSRasterLayer_with_projection(proj_radolan)    # avoid projection dialog
            extent = asc_layer.extent()
            
            extent_params_as_string = "%f,%f,%f,%f" \
                % (extent.xMinimum(), extent.xMaximum(), extent.yMinimum(), extent.yMaximum() )
            
            # insert these params later for newer GDAL versions:
            params['RAST_EXT'] = extent_params_as_string    ### NEW! for new gdal versions.
            params['EXT_CRS' ] = proj_radolan               ### NEW! for new gdal versions. MUST be Radolan-Proj.!!!
            self.out("  -> inserting new keys 'RAST_EXT', 'EXT_CRS'")
        
        
        
        # Diagnose:
        print("### Dict params are:\n ", params)
        
        
        # For overview of the parameters use in QGIS python console:
        # processing.alghelp("gdalogr:warpreproject")
        #target = processing.runalg("gdalogr:warpreproject", params )    # return: dict    QGIS 2
        target = processing.run("gdal:warpreproject", params)    # QGIS 3
        
        fallback = False
        
        # TIF shouldt be written but doesn't exists:
        if write_result and not path.exists(self._full_tif_filename):
            fallback = True
        
        
        # Normal mode: return Memory Layer:
        if not fallback:
            #self._result = processing.getObject(target["OUTPUT"])    # key of dict, QGIS 2
            context = QgsProcessingContext()
            self._result = QgsProcessingUtils.mapLayerFromString(target["OUTPUT"], context)
            #print("result =", self._result)
            return    #return self._result
        
        
        """
        When warped TIF wasn't created:
        FALLBACK MODE without dict
            normally not, when dict is working
        The normal way is positive tested on a QGIS-dev on Linux 2.12.99.
        But the following fallback way need to implemented for the following
        configuration: also on Linux, Python-Version 2.7.12 (default, Jul 01 2016, 15:36:53) [GCC]
        QGIS-Version: 2.8.2 "Wien", exported
        """
        #return
        self._produce_warped_tif_fallback(write_result)
예제 #31
0
    def testFeatureSourceInput(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer(
            "Point?crs=epsg:3857&field=fldtxt:string&field=fldint:integer",
            "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(110, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)

        # select first feature
        layer.selectByIds([next(layer.getFeatures()).id()])
        self.assertEqual(len(layer.selectedFeatureIds()), 1)

        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById(
            'grass7:v.buffer')
        self.assertIsNotNone(alg)
        temp_file = os.path.join(self.temp_dir, 'grass_output_sel.shp')
        parameters = {
            'input': QgsProcessingFeatureSourceDefinition('testmem', True),
            'cats': '',
            'where': '',
            'type': [0, 1, 4],
            'distance': 1,
            'minordistance': None,
            'angle': 0,
            'column': None,
            'scale': 1,
            'tolerance': 0.01,
            '-s': False,
            '-c': False,
            '-t': False,
            'output': temp_file,
            'GRASS_REGION_PARAMETER': None,
            'GRASS_SNAP_TOLERANCE_PARAMETER': -1,
            'GRASS_MIN_AREA_PARAMETER': 0.0001,
            'GRASS_OUTPUT_TYPE_PARAMETER': 0,
            'GRASS_VECTOR_DSCO': '',
            'GRASS_VECTOR_LCO': ''
        }
        feedback = QgsProcessingFeedback()

        results, ok = alg.run(parameters, context, feedback)
        self.assertTrue(ok)
        self.assertTrue(os.path.exists(temp_file))

        # make sure that layer has correct features
        res = QgsVectorLayer(temp_file, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 1)

        QgsProject.instance().removeMapLayer(layer)
예제 #32
0
    def processAlgorithm(self, parameters, context, feedback):
        # extract input parameters
        alg = self.parameterAsEnum(parameters, self.INPUT_ALG_NAME, context)

        extent = self.parameterAsVectorLayer(parameters, self.INPUT_EXTENT, context)

        raster_1_id = self.parameterAsString(parameters, self.INPUT_RASTER_1, context)
        raster_1 = QgsProject.instance().mapLayer(raster_1_id)

        raster_2_id = self.parameterAsString(parameters, self.INPUT_RASTER_2, context)
        raster_2 = QgsProject.instance().mapLayer(raster_2_id)

        (sink, self.dest_id) = self.parameterAsSink(
            parameters,
            self.OUTPUT_BUFFER,
            context,
            QgsFields(),
            extent.wkbType(),
            extent.sourceCrs(),
        )

        outputFile = self.parameterAsRasterLayer(
            parameters, self.OUTPUT_CHANGES, context
        )

        # create a temporary vector layer
        tmp = tempfile.mkdtemp()
        path_roi = os.path.join(tmp, "roi.shp")
        writer = QgsVectorFileWriter(
            path_roi,
            "UTF-8",
            QgsFields(),
            QgsWkbTypes.Polygon,
            extent.sourceCrs(),
            "ESRI Shapefile",
        )

        # create buffered extent and update temporary shp for detector
        for feature in extent.getFeatures():
            geom = feature.geometry()
            buffer = geom.buffer(
                10, 100, QgsGeometry.CapFlat, QgsGeometry.JoinStyleMiter, 100
            )
            feature.setGeometry(buffer)
            feature.setFields(QgsFields())
            sink.addFeature(feature)
            writer.addFeature(feature)
        del writer

        # run change detector
        path1 = raster_1.source()
        path2 = raster_2.source()
        detector = LittoDynChangeDetectorPca(path1, path2, path_roi)
        if alg == 1:
            detector = LittoDynChangeDetectorEvi(path1, path2, path_roi)
        elif alg == 2:
            detector = LittoDynChangeDetectorNdvi(path1, path2, path_roi)
        elif alg == 3:
            detector = LittoDynChangeDetectorNgrdi(path1, path2, path_roi)
        elif alg == 4:
            detector = LittoDynChangeDetectorNormEuclid(path1, path2, path_roi)
        elif alg == 5:
            detector = LittoDynChangeDetectorNormCorr(path1, path2, path_roi)
        elif alg == 6:
            detector = LittoDynChangeDetectorNormCos(path1, path2, path_roi)
        detector.detect()

        # store output layers in group
        alg_name = self.options[alg].lower().replace(" ", "_")
        if Qgis.QGIS_VERSION_INT >= 31500:
            name = "{}_{}_{}".format(raster_1.name(), raster_2.name(), alg_name)
            ProcessingConfig.setSettingValue(ProcessingConfig.RESULTS_GROUP_NAME, name)

        # save result in temporary file
        tmp = tempfile.mkdtemp()
        path_changes = os.path.join(tmp, "{}_changes.tif".format(alg_name))
        detector.save(path_changes)

        rl = QgsRasterLayer(path_changes, "{}_changes".format(alg_name), "gdal")
        context.temporaryLayerStore().addMapLayer(rl)
        context.addLayerToLoadOnCompletion(
            rl.id(),
            QgsProcessingContext.LayerDetails(
                "{}_changes".format(alg_name), context.project(), self.OUTPUT_CHANGES
            ),
        )

        return {
            self.OUTPUT_CHANGES: rl.id(),
            self.OUTPUT_BUFFER: self.dest_id,
            self.OUTPUT_CHANGES: rl.id(),
        }
예제 #33
0
    def check_algorithm(self, name, defs):
        """
        Will run an algorithm definition and check if it generates the expected result
        :param name: The identifier name used in the test output heading
        :param defs: A python dict containing a test algorithm definition
        """
        self.vector_layer_params = {}
        QgsProject.instance().clear()

        if 'project' in defs:
            full_project_path = os.path.join(processingTestDataPath(),
                                             defs['project'])
            project_read_success = QgsProject.instance().read(
                full_project_path)
            self.assertTrue(project_read_success,
                            'Failed to load project file: ' + defs['project'])

        if 'project_crs' in defs:
            QgsProject.instance().setCrs(
                QgsCoordinateReferenceSystem(defs['project_crs']))
        else:
            QgsProject.instance().setCrs(QgsCoordinateReferenceSystem())

        if 'ellipsoid' in defs:
            QgsProject.instance().setEllipsoid(defs['ellipsoid'])
        else:
            QgsProject.instance().setEllipsoid('')

        params = self.load_params(defs['params'])

        print('Running alg: "{}"'.format(defs['algorithm']))
        alg = QgsApplication.processingRegistry().createAlgorithmById(
            defs['algorithm'])

        parameters = {}
        if isinstance(params, list):
            for param in zip(alg.parameterDefinitions(), params):
                parameters[param[0].name()] = param[1]
        else:
            for k, p in params.items():
                parameters[k] = p

        for r, p in list(defs['results'].items()):
            if 'in_place_result' not in p or not p['in_place_result']:
                parameters[r] = self.load_result_param(p)

        expectFailure = False
        if 'expectedFailure' in defs:
            exec(('\n'.join(defs['expectedFailure'][:-1])), globals(),
                 locals())
            expectFailure = eval(defs['expectedFailure'][-1])

        if 'expectedException' in defs:
            expectFailure = True

        # ignore user setting for invalid geometry handling
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        if 'skipInvalid' in defs and defs['skipInvalid']:
            context.setInvalidGeometryCheck(
                QgsFeatureRequest.GeometrySkipInvalid)

        feedback = QgsProcessingFeedback()

        print('Algorithm parameters are {}'.format(parameters))

        # first check that algorithm accepts the parameters we pass...
        ok, msg = alg.checkParameterValues(parameters, context)
        self.assertTrue(
            ok,
            'Algorithm failed checkParameterValues with result {}'.format(msg))

        if expectFailure:
            try:
                results, ok = alg.run(parameters, context, feedback)
                self.check_results(results, context, parameters,
                                   defs['results'])
                if ok:
                    raise _UnexpectedSuccess
            except Exception:
                pass
        else:
            results, ok = alg.run(parameters, context, feedback)
            self.assertTrue(
                ok, 'params: {}, results: {}'.format(parameters, results))
            self.check_results(results, context, parameters, defs['results'])
예제 #34
0
    def startWorker(self):
        """Initialises and starts."""
        self.inputbuffers = {}
        self.referencebuffers = {}
        self.polycount = {}
        self.completeness = {}
        self.miscodings = {}
        self.statistics = {}
        self.testcounter = 0

        try:
            layerindex = self.inputLayer.currentIndex()
            layerId = self.inputLayer.itemData(layerindex)
            self.inputlayer = QgsProject.instance().mapLayer(layerId)
            if self.inputlayer is None:
                self.showError(self.tr('No input layer defined'))
                return
            refindex = self.referenceLayer.currentIndex()
            reflayerId = self.referenceLayer.itemData(refindex)
            self.reflayer = QgsProject.instance().mapLayer(reflayerId)
            if layerId == reflayerId:
                self.showInfo('The reference layer must be different'
                              ' from the input layer!')
                return
            if self.reflayer is None:
                self.showError(self.tr('No reference layer defined'))
                return
            if self.inputlayer.sourceCrs().authid() != self.reflayer.sourceCrs(
            ).authid():
                self.showWarning('Layers must have the same CRS - Input: ' +
                                 str(self.inputlayer.sourceCrs().authid()) +
                                 ' Reference: ' +
                                 str(self.reflayer.sourceCrs().authid()))
                return
            if self.reflayer.sourceCrs().isGeographic():
                self.showWarning('Geographic CRS used -' +
                                 ' computations will be in decimal degrees!')
            # Algorithms
            self.bufferalg = QgsApplication.processingRegistry().algorithmById(
                'native:buffer')
            #self.bufferalg=QgsApplication.processingRegistry().algorithmById('qgis:buffer')
            self.unionalg = QgsApplication.processingRegistry().algorithmById(
                'qgis:union')
            self.intersectionalg = QgsApplication.processingRegistry(
            ).algorithmById('qgis:intersection')
            self.differencealg = QgsApplication.processingRegistry(
            ).algorithmById('qgis:difference')
            self.multitosinglealg = QgsApplication.processingRegistry(
            ).algorithmById('qgis:multiparttosingleparts')
            self.statalg = QgsApplication.processingRegistry().algorithmById(
                'qgis:statisticsbycategories')

            # Calculate the total length of lines in the layers
            self.inpgeomlength = 0
            for f in self.inputlayer.getFeatures():
                self.inpgeomlength = self.inpgeomlength + f.geometry().length()
            self.refgeomlength = 0
            for f in self.reflayer.getFeatures():
                self.refgeomlength = self.refgeomlength + f.geometry().length()

            # Number of steps and radii
            steps = self.stepsSB.value()
            startradius = self.startRadiusSB.value()
            endradius = self.endRadiusSB.value()
            delta = (endradius - startradius) / (steps - 1)
            self.radiuses = []
            for step in range(steps):
                self.radiuses.append(startradius + step * delta)
            #self.radiuses = [10,20,50]
            #self.showInfo(str(self.radiuses))
            feedback = QgsProcessingFeedback()
            selectedinputonly = self.selectedFeaturesCheckBox.isChecked()
            selectedrefonly = self.selectedRefFeaturesCheckBox.isChecked()
            #plugincontext = dataobjects.createContext(feedback)
            #self.showInfo('Plugin context: ' + str(plugincontext))
            #self.showInfo('GUI thread: ' + str(QThread.currentThread()) + ' ID: ' + str(QThread.currentThreadId()))

            ###### Testing QgsTask!!!
            # I følge oppskrifta på opengis.ch
            context = QgsProcessingContext()
            #context = plugincontext
            #self.showInfo('Normal context: ' + str(context))
            #context.setProject(QgsProject.instance())
            for radius in self.radiuses:
                # Buffer input  # Works!
                inlayercopy = QgsVectorLayer(self.inputlayer.source(),
                                             'in' + str(radius),
                                             self.inputlayer.providerType())
                ##inlayercopy = self.copylayer(self.inputlayer, 'in' + str(radius))
                params = {
                    'INPUT': inlayercopy,
                    #'INPUT': self.inputlayer,
                    'DISTANCE': radius,
                    #'OUTPUT':'/home/havatv/test.shp'
                    'OUTPUT': 'memory:InputBuffer'
                }
                task = QgsProcessingAlgRunnerTask(self.bufferalg, params,
                                                  context)
                ##task = QgsProcessingAlgRunnerTask(self.bufferalg,params,context,feedback)
                # Add a few extra parameters (context, radius and "input") using "partial"
                task.executed.connect(
                    partial(self.buffer_executed, context, radius, self.INPUT))
                QgsApplication.taskManager().addTask(task)
                self.showInfo('Start Input buffer: ' + str(radius))
                # Buffer reference  # Works!
                reflayercopy = QgsVectorLayer(self.reflayer.source(),
                                              'ref' + str(radius),
                                              self.reflayer.providerType())
                #reflayercopy = self.copylayer(self.reflayer, 'ref' + str(radius))
                params = {
                    'INPUT': reflayercopy,
                    #'INPUT': self.reflayer,
                    'DISTANCE': radius,
                    #'OUTPUT':'/home/havatv/test.shp'
                    'OUTPUT': 'memory:ReferenceBuffer'
                }
                task = QgsProcessingAlgRunnerTask(self.bufferalg, params,
                                                  context)
                #task = QgsProcessingAlgRunnerTask(self.bufferalg,params,context,feedback)
                # Add a few extra parameters (context, radius and "reference") using "partial"
                task.executed.connect(
                    partial(self.buffer_executed, context, radius, self.REF))
                QgsApplication.taskManager().addTask(task)
                self.showInfo('Start Ref buffer: ' + str(radius))

            ##task.begun.connect(self.task_begun)
            ##task.taskCompleted.connect(self.task_completed)
            ##task.progressChanged.connect(self.task_progress)
            ##task.taskTerminated.connect(self.task_stopped)

            #iteration = 5   # Identifiserer hvilken iterasjon det er snakk om

            ## I følge oppskrifta på opengis.ch (partial legger inn context som første parameter):
            ## context ser ut til å være helt nødvendig!
            #task.executed.connect(partial(self.task_executed, context, iteration))
            #self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
            #self.button_box.button(QDialogButtonBox.Close).setEnabled(False)
            #self.button_box.button(QDialogButtonBox.Cancel).setEnabled(True)
        except:
            import traceback
            self.showError(traceback.format_exc())
        else:
            pass
    def processAlgorithm(self, parameters, context, feedback):
        self.dest_id = None
        # Parameters
        # lighting = self.parameterAsVectorLayer(parameters, self.LIGHTING, context)
        lighting_source, lighting_layer = qgsTreatments.parameterAsSourceLayer(
            self, parameters, self.LIGHTING, context, feedback=feedback)
        if not lighting_source:
            raise QgsProcessingException("No lighting layer")
        fieldname = self.parameterAsString(parameters, self.FLUX_FIELD,
                                           context)
        if not fieldname:
            raise QgsProcessingException("No field given for light flux")
        flux_div_flag = self.parameterAsBool(parameters, self.FLUX_DIV,
                                             context)
        reporting, reporting_layer = qgsTreatments.parameterAsSourceLayer(
            self, parameters, self.REPORTING, context, feedback=feedback)
        if not reporting:
            raise QgsProcessingException("No reporting layer")
        init_reporting_fields = reporting_layer.fields().names()
        surface, surface_layer = qgsTreatments.parameterAsSourceLayer(
            self, parameters, self.SURFACE, context, feedback=feedback)
        dissolve_flag = self.parameterAsBool(parameters, self.DISSOLVE,
                                             context)
        clip_val = self.parameterAsInt(parameters, self.CLIP_DISTANCE, context)
        reporting_fields = self.parameterAsFields(parameters,
                                                  self.REPORTING_FIELDS,
                                                  context)
        skip_flag = self.parameterAsBool(parameters, self.SKIP_EMPTY, context)
        min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
        min_lamps = self.parameterAsInt(parameters, self.MIN_NB_LAMPS, context)

        # Reprojection if needed
        light_crs = lighting_source.sourceCrs().authid()
        reporting_crs = reporting.sourceCrs()
        # reporting_crs = reporting.dataProvider().sourceCrs()
        if reporting_crs.isGeographic():
            raise QgsProcessingException(
                "Reporting CRS must be a projection (not lat/lon)")
        feedback.pushDebugInfo("reporting_crs = " + str(type(reporting_crs)))
        feedback.pushDebugInfo("reporting_crs = " + str(reporting_crs))
        reporting_crs_id = reporting_crs.authid()
        feedback.pushDebugInfo("reporting_crs_id = " +
                               str(type(reporting_crs_id)))
        feedback.pushDebugInfo("reporting_crs_id = " + str(reporting_crs_id))
        if light_crs != reporting_crs_id:
            lighting_path = QgsProcessingUtils.generateTempFilename(
                'light_reproj.gpkg')
            qgsTreatments.applyReprojectLayer(lighting_layer,
                                              reporting_crs,
                                              lighting_path,
                                              context=context,
                                              feedback=feedback)
            lighting_layer = lighting_path
        if surface:
            surface_crs = surface.sourceCrs().authid()
            if reporting_crs_id != surface_crs:
                surface_reproj = QgsProcessingUtils.generateTempFilename(
                    'surface_reproj.gpkg')
                qgsTreatments.applyReprojectLayer(surface_layer,
                                                  reporting_crs,
                                                  surface_reproj,
                                                  context=context,
                                                  feedback=feedback)
                surface_fixed = QgsProcessingUtils.generateTempFilename(
                    'surface_fixed.gpkg')
                qgsTreatments.fixGeometries(surface_reproj,
                                            surface_fixed,
                                            context=context,
                                            feedback=feedback)
                surface_layer = qgsUtils.loadVectorLayer(surface_fixed)
                qgsTreatments.createSpatialIndex(surface_layer,
                                                 context=context,
                                                 feedback=feedback)

        # Output fields initialization
        nb_lamps_field = QgsField(self.NB_LAMPS, QVariant.Int)
        flux_sum_field = QgsField(self.FLUX_SUM, QVariant.Double)
        surface_field = QgsField(self.SURFACE_AREA, QVariant.Double)
        flux_den_field = QgsField(self.FLUX_DEN, QVariant.Double)
        out_fields = QgsFields()
        for f in reporting_layer.fields():
            if f.name() in reporting_fields:
                # feedback.pushDebugInfo("f2 = " + str( f.name()))
                out_fields.append(f)
        out_fields.append(nb_lamps_field)
        out_fields.append(flux_sum_field)
        out_fields.append(surface_field)
        out_fields.append(flux_den_field)
        (sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                    context, out_fields,
                                                    reporting.wkbType(),
                                                    reporting.sourceCrs())

        # Progess bar step
        nb_feats = reporting.featureCount()
        total = 100.0 / nb_feats if nb_feats else 0

        # Clip according to distance to lighting
        if clip_val:
            buffered_path = QgsProcessingUtils.generateTempFilename(
                'light_buf.gpkg')
            buffered = qgsTreatments.applyBufferFromExpr(lighting_layer,
                                                         clip_val,
                                                         buffered_path,
                                                         context=context,
                                                         feedback=feedback)
            clipped_path = QgsProcessingUtils.generateTempFilename(
                'reporting_clip.gpkg')
            qgsTreatments.createSpatialIndex(reporting_layer,
                                             context=context,
                                             feedback=feedback)
            clipped = qgsTreatments.applyVectorClip(reporting_layer,
                                                    buffered_path,
                                                    clipped_path,
                                                    context=context,
                                                    feedback=feedback)
            reporting_layer = clipped_path

        # Get reporting units count per light
        if flux_div_flag:
            if 'ID' in init_reporting_fields:
                id_field = 'ID'
            elif 'fid' in init_reporting_fields:
                id_field = 'fid'
            else:
                raise QgsProcessingException(
                    "ID field does not exist in reporting layer")
            qgsTreatments.createSpatialIndex(lighting_layer,
                                             context=context,
                                             feedback=feedback)
            joined_light_path = QgsProcessingUtils.generateTempFilename(
                'joined_light.gpkg')
            qgsTreatments.joinByLocSummary(lighting_layer,
                                           reporting_layer,
                                           joined_light_path, [id_field],
                                           summaries=[0],
                                           predicates=[0],
                                           context=context,
                                           feedback=feedback)
            joined_light_layer = qgsUtils.loadVectorLayer(joined_light_path)
            id_cpt_name = id_field + '_count'

            def funcDiv(f):
                if f[fieldname]:
                    try:
                        flux = float(f[fieldname])
                        nb_units = int(f[id_cpt_name])
                        return flux / nb_units
                    except ValueError:
                        return None
                else:
                    return None

            qgsUtils.createOrUpdateField(joined_light_layer, funcDiv,
                                         self.FLUX_DIV_FIELD)
            lighting_layer, fieldname = joined_light_layer, self.FLUX_DIV_FIELD
        # Join light points summary by reporting unit
        joined_path = QgsProcessingUtils.generateTempFilename('joined.gpkg')
        # SUM = 5
        summaries = [0, 1, 2, 3, 5, 6]
        qgsTreatments.createSpatialIndex(reporting_layer,
                                         context=context,
                                         feedback=feedback)
        joined = qgsTreatments.joinByLocSummary(reporting_layer,
                                                lighting_layer,
                                                joined_path, [fieldname],
                                                summaries,
                                                predicates=[0],
                                                context=context,
                                                feedback=feedback)
        joined_layer = qgsUtils.loadVectorLayer(joined_path)
        nb_lamps_fieldname = fieldname + "_count"
        flux_field_sum = fieldname + "_sum"

        # Set context and feedback
        if not context:
            context = QgsProcessingContext()
        context = context.setInvalidGeometryCheck(
            QgsFeatureRequest.GeometryNoCheck)
        multi_feedback = QgsProcessingMultiStepFeedback(nb_feats, feedback)

        # Iteration on each reporting unit
        qgsTreatments.createSpatialIndex(joined_layer,
                                         context=context,
                                         feedback=feedback)
        for current, feat in enumerate(joined_layer.getFeatures()):
            if feedback.isCanceled():
                break
            f_geom = feat.geometry()
            f_area = f_geom.area()
            f_id = feat.id()
            nb_lamps = feat[nb_lamps_fieldname]
            flux_sum = feat[flux_field_sum]
            if skip_flag and flux_sum == 0:
                continue
            if f_area < min_area:
                continue
            if nb_lamps < min_lamps:
                continue

            try:
                if surface:
                    # Clip surface layer to reporting feature boundaries to retrieve intersecting area
                    nb_steps = 4 if dissolve_flag else 3
                    mmf = QgsProcessingMultiStepFeedback(
                        nb_steps, multi_feedback)
                    joined_layer.selectByIds([f_id])
                    suffix = "_" + str(f_id) + ".gpkg"
                    input_feat = QgsProcessingUtils.generateTempFilename(
                        "selection" + suffix)
                    qgsTreatments.saveSelectedAttributes(joined_layer,
                                                         input_feat,
                                                         context=context,
                                                         feedback=mmf)
                    mmf.setCurrentStep(1)
                    # input_feat = QgsProcessingFeatureSourceDefinition(joined_layer.id(),True)
                    clipped_path = QgsProcessingUtils.generateTempFilename(
                        "clipped" + str(f_id) + ".gpkg")
                    clipped = qgsTreatments.applyVectorClip(surface_layer,
                                                            input_feat,
                                                            clipped_path,
                                                            context=context,
                                                            feedback=mmf)
                    mmf.setCurrentStep(2)
                    if dissolve_flag:
                        feat_surface_path = QgsProcessingUtils.generateTempFilename(
                            "dissolved" + str(f_id) + ".gpkg")
                        qgsTreatments.dissolveLayer(clipped,
                                                    feat_surface_path,
                                                    context=context,
                                                    feedback=mmf)
                        mmf.setCurrentStep(3)
                    else:
                        feat_surface_path = clipped_path
                    feat_surface_layer = qgsUtils.loadVectorLayer(
                        feat_surface_path)
                    joined_layer.removeSelection()

                    surface_area = 0
                    for surface_feat in feat_surface_layer.getFeatures():
                        surface_geom = surface_feat.geometry()
                        intersection = f_geom.intersection(surface_geom)
                        surface_area += intersection.area()
                    mmf.setCurrentStep(nb_steps)
                else:
                    surface_area = f_area

                # Output result feature
                new_feat = QgsFeature(out_fields)
                new_feat.setGeometry(feat.geometry())
                for report_field in reporting_fields:
                    new_feat[report_field] = feat[report_field]
                new_feat[self.NB_LAMPS] = nb_lamps
                new_feat[self.FLUX_SUM] = flux_sum
                new_feat[self.SURFACE_AREA] = surface_area
                new_feat[
                    self.
                    FLUX_DEN] = flux_sum / surface_area if surface_area > 0 else None
                sink.addFeature(new_feat, QgsFeatureSink.FastInsert)
            except Exception as e:
                feedback.reportError('Unexpected error : ' + str(e))
                raise e

            multi_feedback.setCurrentStep(current + 1)

        return {self.OUTPUT: self.dest_id}
class CartogramWorkOrchestratorMixIn:
    """Manage the tasks of the plugin’s workers."""
    def __init__(self):
        """Manage the tasks of the plugin’s workers."""
        super(CartogramWorkOrchestratorMixIn, self).__init__()
        self.add_processing_provider()

    def add_processing_provider(self):
        self.provider = CartogramProcessingProvider()
        QgsApplication.processingRegistry().addProvider(self.provider)

    def cancel_task(self):
        self.disable_cancel_button()
        self.task.cancel()

    def is_task_running(self):
        try:
            return self.task.isActive()
        except (AttributeError, RuntimeError):  # (no self.task)
            return False

    def remove_processing_provider(self):
        QgsApplication.processingRegistry().removeProvider(self.provider)

    def sample_layer(self):
        source_layer = QgsVectorLayer(
            os.path.join(self.plugin_dir, "data", "Austria_PopulationByNUTS2.gml"),
            ""
        )

        # (empty) memory layer
        sample_layer = QgsVectorLayer(
            QgsWkbTypes.geometryDisplayString(source_layer.geometryType())
            + "?crs=" + source_layer.crs().authid()
            + "&index=yes",
            "Austria_Population_NUTS2_20170101",
            "memory"
        )
        sample_layer_data_provider = sample_layer.dataProvider()
        sample_layer_data_provider.addAttributes(source_layer.fields().toList())
        sample_layer.updateFields()
        sample_layer_data_provider.addFeatures(list(source_layer.getFeatures()))

        sample_layer.loadNamedStyle(
            os.path.join(self.plugin_dir, "data", "Austria_PopulationByNUTS2.qml")
        )

        sample_layer.setTitle("Austria: Population by NUTS2 regions, 1 Jan 2017")
        sample_layer.setShortName("Austria_Population_NUTS2_20170101")
        sample_layer.setAbstract(
            "Austria’s population by NUTS2 region, as of 1 Jan 2017 \n"
            + "\n"
            + "Data sources: \n"
            + "    http://ec.europa.eu/eurostat/web/gisco/geodata/"
            + "reference-data/administrative-units-statistical-units/"
            + "nuts#nuts13 \n"
            + "    http://www.statistik.at/web_de/statistiken/"
            + "menschen_und_gesellschaft/bevoelkerung/"
            + "bevoelkerungsstand_und_veraenderung/"
            + "bevoelkerung_zu_jahres-_quartalsanfang/index.html"
        )

        return sample_layer

    def start_task(self, input_layer, field, max_iterations, max_average_error):
        self.context = QgsProcessingContext()
        self.feedback = QgsProcessingFeedback()
        self.task = QgsProcessingAlgRunnerTask(
            QgsApplication.processingRegistry().algorithmById("cartogram3:compute_cartogram"),
            {
                "INPUT": input_layer,
                "FIELD": field,
                "MAX_ITERATIONS": max_iterations,
                "MAX_AVERAGE_ERROR": max_average_error,
                "OUTPUT": "memory:"
            },
            self.context,
            self.feedback
        )
        self.task.executed.connect(self.task_finished)
        self.feedback.progressChanged.connect(self.update_progress)
        QgsApplication.taskManager().addTask(self.task)

    def task_finished(self, successful, results={}):
        if successful:
            output_layer = self.context.getMapLayer(results["OUTPUT"])
            if output_layer and output_layer.isValid():
                layer = self.context.takeResultLayer(output_layer.id())
                self.add_result_layer_to_map_canvas(layer, results["FIELD"])
                self.feedback.pushInfo(
                    (
                        "Finished computing cartogram for layer {:s} on field {:s} "
                        + "after {:d} iterations with {:.2n}% residual error."
                    ).format(
                        self.input_layer.name(),
                        results["FIELD"],
                        results["ITERATIONS"],
                        results["RESIDUAL_AVERAGE_ERROR"]
                    )
                )
        else:
            if self.feedback.isCanceled():
                self.feedback.pushWarning("User canceled cartogram computation")
            self.feedback.reportError("Failed to compute cartogram")

        self.clean_up_ui()  # remove progress bar

    def update_progress(self, progress):
        self.update_progress_bar(progress)
예제 #37
0
def createContext(feedback=None):
    """
    Creates a default processing context

    :param feedback: Optional existing QgsProcessingFeedback object, or None to use a default feedback object
    :type feedback: Optional[QgsProcessingFeedback]

    :returns: New QgsProcessingContext object
    :rtype: QgsProcessingContext
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())
    context.setFeedback(feedback)

    invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if invalid_features_method is None:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding", "System"))

    context.setExpressionContext(createExpressionContext())

    return context
예제 #38
0
def createContext():
    """
    Creates a default processing context
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())

    invalid_features_method = ProcessingConfig.getSetting(
        ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if invalid_features_method is None:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    def raise_error(f):
        raise GeoAlgorithmExecutionException(
            QCoreApplication.translate(
                "FeatureIterator",
                'Features with invalid geometries found. Please fix these geometries or specify the "Ignore invalid input features" flag'
            ))

    context.setInvalidGeometryCallback(raise_error)

    def raise_transform_error(f):
        raise GeoAlgorithmExecutionException(
            QCoreApplication.translate(
                "FeatureIterator",
                'Encountered a transform error when reprojecting feature with id {}.'
                .format(f.id())))

    context.setTransformErrorCallback(raise_transform_error)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding",
                                              "System"))

    return context
예제 #39
0
    def testOgr2Ogr(self):
        context = QgsProcessingContext()
        feedback = QgsProcessingFeedback()
        source = os.path.join(testDataPath, 'polys.gml')
        multi_source = os.path.join(testDataPath, 'multi_layers.gml')
        alg = ogr2ogr()
        alg.initAlgorithm()

        with tempfile.TemporaryDirectory() as outdir:
            self.assertEqual(
                alg.getConsoleCommands(
                    {
                        'INPUT': source,
                        'OUTPUT': outdir + '/check.shp'
                    }, context, feedback), [
                        'ogr2ogr', '-f "ESRI Shapefile" ' + outdir +
                        '/check.shp ' + source + ' polys2'
                    ])

            self.assertEqual(
                alg.getConsoleCommands(
                    {
                        'INPUT': source,
                        'OUTPUT': outdir + '/check.kml'
                    }, context, feedback), [
                        'ogr2ogr', '-f "LIBKML" ' + outdir + '/check.kml ' +
                        source + ' polys2'
                    ])

            self.assertEqual(
                alg.getConsoleCommands(
                    {
                        'INPUT': source,
                        'OUTPUT': outdir + '/my out/check.kml'
                    }, context, feedback), [
                        'ogr2ogr', '-f "LIBKML" "' + outdir +
                        '/my out/check.kml" ' + source + ' polys2'
                    ])

            self.assertEqual(
                alg.getConsoleCommands(
                    {
                        'INPUT': source,
                        'OUTPUT': outdir + '/check.gpkg'
                    }, context, feedback),
                [
                    'ogr2ogr',
                    '-f "GPKG" ' + outdir + '/check.gpkg ' + source + ' polys2'
                ])

            self.assertEqual(
                alg.getConsoleCommands(
                    {
                        'INPUT': multi_source + '|layername=lines',
                        'CONVERT_ALL_LAYERS': False,
                        'OUTPUT': outdir + '/check.gpkg'
                    }, context, feedback), [
                        'ogr2ogr', '-f "GPKG" ' + outdir + '/check.gpkg ' +
                        multi_source + ' lines'
                    ])

            self.assertEqual(
                alg.getConsoleCommands(
                    {
                        'INPUT': multi_source + '|layername=lines',
                        'CONVERT_ALL_LAYERS': True,
                        'OUTPUT': outdir + '/check.gpkg'
                    }, context, feedback), [
                        'ogr2ogr',
                        '-f "GPKG" ' + outdir + '/check.gpkg ' + multi_source
                    ])
예제 #40
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        source_pts = self.parameterAsSource(parameters, self.INPUT_POINTS,
                                            context)
        input_field = self.parameterAsString(parameters, self.INPUT_FIELD,
                                             context)
        source_dem = self.parameterAsRasterLayer(parameters, self.INPUT_DEM,
                                                 context)
        out_directory = self.parameterAsString(parameters, self.OUTPUT_DIR,
                                               context)
        out_type_nr = self.parameterAsInt(parameters, self.OUTPUT_TYPE,
                                          context)
        out_type = QgsVectorFileWriter.supportedFormatExtensions(
        )[:2][out_type_nr]
        to_gpkg = out_type == 'gpkg'
        load_results = self.parameterAsBool(parameters, self.LOAD_RESULTS,
                                            context)
        if source_pts is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT_POINTS))
        if source_dem is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT_DEM))

        feedback.pushInfo("Input data loaded! Creating catchments...")
        feedback.setProgress(1)

        unique_field = input_field if input_field else ""
        if unique_field:
            field_idx = source_pts.fields().lookupField(unique_field)
            unique_values = source_pts.uniqueValues(field_idx)
        else:
            unique_values = [f.id() for f in source_pts.getFeatures()]

        feedback.pushInfo(f"Creating directory: {out_directory}")
        mkdir(out_directory)
        bname = f"catchment{'s' if to_gpkg else ''}"
        output_basename = os.path.join(out_directory, bname)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        total_nr = len(unique_values)
        total = 100. / total_nr if source_pts.featureCount() else 1
        output_layers = []

        for i, unique_value in enumerate(unique_values):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            table = f"catchment_{unique_value}" if to_gpkg else ""
            file_mod = "" if to_gpkg else f"_{unique_value}"
            filename = f"{output_basename}{file_mod}"
            destination = f"{filename}.{out_type}"
            output_uri = destination + (f"|layername={table}"
                                        if to_gpkg else "")
            feedback.pushInfo(
                self.tr('Creating layer: {}').format(destination))

            if unique_field:
                req_filter = f"{QgsExpression.quotedColumnRef(unique_field)}={QgsExpression.quotedValue(unique_value)}"
                req = QgsFeatureRequest().setFilterExpression(req_filter)
            else:
                req = QgsFeatureRequest(unique_value)  # feature id

            for source_pt in source_pts.getFeatures(req):
                if feedback.isCanceled():
                    break

                # Get x and y coordinate from point feature
                geom = source_pt.geometry()
                p = geom.asPoint()
                x = p.x()
                y = p.y()

                feedback.pushInfo(
                    'Creating upslope area for point ({:.2f}, {:.2f}) - {} of {}'
                    .format(x, y, i + 1, total_nr))

                # Calculate catchment raster from point feature
                catchraster = processing.run(
                    "saga:upslopearea",
                    {
                        'TARGET': None,
                        'TARGET_PT_X': x,
                        'TARGET_PT_Y': y,
                        'ELEVATION': source_dem,
                        'SINKROUTE': None,
                        'METHOD': 0,
                        'CONVERGE': 1.1,
                        'AREA': 'TEMPORARY_OUTPUT'
                    },
                    context=context,
                    feedback=feedback,
                )

                # Polygonize raster catchment
                catchpoly = processing.run(
                    "gdal:polygonize",
                    {
                        'INPUT': catchraster["AREA"],
                        'BAND': 1,
                        'FIELD': 'DN',
                        'EIGHT_CONNECTEDNESS': False,
                        'OUTPUT': 'TEMPORARY_OUTPUT'
                    },
                    context=context,
                    feedback=feedback,
                )

                # Select features having DN = 100
                catchpoly_lyr = QgsProcessingUtils.mapLayerFromString(
                    catchpoly["OUTPUT"], context=context)
                catchpoly_lyr.selectByExpression('"DN"=100')

                options = QgsVectorFileWriter.SaveVectorOptions()
                options.driverName = "GPKG" if to_gpkg else "ESRI Shapefile"
                options.layerName = table
                options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
                options.onlySelectedFeatures = True
                trans_context = QgsCoordinateTransformContext()

                write_result, error_message = QgsVectorFileWriter.writeAsVectorFormatV2(
                    catchpoly_lyr, destination, trans_context, options)
                if write_result != 0:
                    feedback.pushInfo(f"Initial write failed: {error_message}")
                    # retry with option for creating the dataset
                    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
                    write_result, error_message = QgsVectorFileWriter.writeAsVectorFormatV2(
                        catchpoly_lyr, destination, trans_context, options)

                feedback.pushInfo(
                    f"Final write attempt: {write_result} == 0 -> SUCCESS or {error_message}"
                )

                output_layer = QgsProcessingUtils.mapLayerFromString(
                    output_uri, context=context)
                output_layers.append(output_uri)
                if load_results:
                    context.temporaryLayerStore().addMapLayer(output_layer)
                    context.addLayerToLoadOnCompletion(
                        output_layer.id(),
                        QgsProcessingContext.LayerDetails(
                            table if to_gpkg else f"catchment {unique_value}",
                            context.project(), self.OUTPUT_LAYERS))

            feedback.setProgress(int((i + 1) * total))

        return {
            self.OUTPUT_DIR: out_directory,
            self.OUTPUT_LAYERS: output_layers
        }
예제 #41
0
    def testReadOgr(self):
        """
        Test reading vector inputs
        """
        alg = RAlgorithm(
            description_file=os.path.join(test_data_path, 'test_vectorin.rsx'))
        alg.initAlgorithm()

        context = QgsProcessingContext()
        feedback = QgsProcessingFeedback()
        script = alg.build_import_commands(
            {'Layer': os.path.join(test_data_path, 'lines.shp')}, context,
            feedback)

        USE_NEW_API = Qgis.QGIS_VERSION_INT >= 30900 and hasattr(
            QgsProcessingAlgorithm,
            'parameterAsCompatibleSourceLayerPathAndLayerName')
        if USE_NEW_API:
            self.assertEqual(
                script[0], 'Layer <- readOGR("{}")'.format(
                    os.path.join(test_data_path, 'lines.shp')))
        else:
            self.assertEqual(
                script[0], 'Layer <- readOGR("{}")'.format(
                    os.path.join(test_data_path, 'lines.shp')))
        script = alg.build_import_commands(
            {
                'Layer':
                os.path.join(test_data_path, 'lines.shp').replace('/', '\\')
            }, context, feedback)
        if USE_NEW_API:
            self.assertEqual(
                script[0], 'Layer <- readOGR("{}")'.format(
                    os.path.join(test_data_path, 'lines.shp')))
        else:
            self.assertEqual(
                script[0], 'Layer <- readOGR("{}")'.format(
                    os.path.join(test_data_path, 'lines.shp')))
        vl = QgsVectorLayer(
            os.path.join(test_data_path, 'test_gpkg.gpkg') +
            '|layername=points')
        self.assertTrue(vl.isValid())
        vl2 = QgsVectorLayer(
            os.path.join(test_data_path, 'test_gpkg.gpkg') +
            '|layername=lines')
        self.assertTrue(vl2.isValid())
        script = alg.build_import_commands({
            'Layer': vl,
            'Layer2': vl2
        }, context, feedback)

        if USE_NEW_API:
            # use the newer api and avoid unnecessary layer translation
            self.assertEqual(script, [
                'Layer <- readOGR("{}", layer="points")'.format(
                    os.path.join(test_data_path, 'test_gpkg.gpkg')),
                'Layer2 <- readOGR("{}", layer="lines")'.format(
                    os.path.join(test_data_path, 'test_gpkg.gpkg'))
            ])
        else:
            # older version, forced to use inefficient api
            self.assertIn('Layer <- readOGR("/tmp', script[0])
            self.assertIn('Layer2 <- readOGR("/tmp', script[1])
    def processAlgorithm(self, parameters, context, feedback):
        # Init ORS client
        providers = configmanager.read_config()['providers']
        provider = providers[self.parameterAsEnum(parameters, self.IN_PROVIDER,
                                                  context)]
        clnt = client.Client(provider)
        clnt.overQueryLimit.connect(
            lambda: feedback.reportError("OverQueryLimit: Retrying..."))

        params = dict()

        geometry_param = self.GEOMETRY_TYPES[self.parameterAsEnum(
            parameters, self.IN_GEOMETRY, context)]
        params[
            self.IN_GEOMETRY] = True if geometry_param == 'Polygon' else False

        mode = self.MODE_TYPES[self.parameterAsEnum(parameters, self.IN_MODE,
                                                    context)]

        source = self.parameterAsSource(parameters, self.IN_POINTS, context)
        if source.wkbType() == 4:
            raise QgsProcessingException(
                "TypeError: Multipoint Layers are not accepted. Please convert to single geometry layer."
            )

        # Get ID field properties
        id_field_name = self.parameterAsString(parameters, self.IN_FIELD,
                                               context)
        id_field_id = source.fields().lookupField(id_field_name)
        if id_field_name == '':
            id_field_id = 0
            id_field_name = source.fields().field(id_field_id).name()
        id_field = source.fields().field(id_field_id)

        # Populate iso_layer instance with parameters
        self.isochrones.set_parameters(self.PROFILE, geometry_param,
                                       id_field.type(), id_field_name)

        layer_time = QgsVectorLayer(f'{geometry_param}?crs=EPSG:4326',
                                    f'Isochrones {self.PROFILE.capitalize()}',
                                    'memory')
        self.isos_time_id = layer_time.id()
        layer_time_pr = layer_time.dataProvider()
        layer_time_pr.addAttributes(self.isochrones.get_fields())
        layer_time.updateFields()

        layer_dist = QgsVectorLayer(
            f'{geometry_param}?crs=EPSG:4326',
            f'Isodistances {self.PROFILE.capitalize()}', 'memory')
        self.isos_dist_id = layer_dist.id()
        layer_dist_pr = layer_dist.dataProvider()
        layer_dist_pr.addAttributes(self.isochrones.get_fields())
        layer_dist.updateFields()

        layer_snapped_points = QgsVectorLayer(
            f'MultiPoint?crs=EPSG:4326',
            f'Snapped Points {self.PROFILE.capitalize()}', 'memory')
        self.points_snapped_id = layer_snapped_points.id()
        layer_snapped_points_pr = layer_snapped_points.dataProvider()
        layer_snapped_points_pr.addAttributes(
            self.isochrones.get_point_fields())
        layer_snapped_points.updateFields()

        layer_input_points = QgsVectorLayer(
            f'Point?crs=EPSG:4326',
            f'Input Points {self.PROFILE.capitalize()}', 'memory')
        self.points_input_id = layer_input_points.id()
        layer_input_points_pr = layer_input_points.dataProvider()
        layer_input_points_pr.addAttributes(self.isochrones.get_point_fields())
        layer_input_points.updateFields()

        denoise = self.parameterAsDouble(parameters, self.IN_DENOISE, context)
        if denoise:
            params[self.IN_DENOISE] = denoise

        generalize = self.parameterAsDouble(parameters, self.IN_GENERALIZE,
                                            context)
        if generalize:
            params[self.IN_GENERALIZE] = generalize

        avoid_layer = self.parameterAsLayer(parameters, self.IN_AVOID, context)
        if avoid_layer:
            params['avoid_locations'] = get_avoid_locations(avoid_layer)

        show_locations = self.parameterAsBool(parameters,
                                              self.IN_SHOW_LOCATIONS, context)

        # Sets all advanced parameters as attributes of self.costing_options
        self.costing_options.set_costing_options(self, parameters, context)

        intervals_time = self.parameterAsString(parameters,
                                                self.IN_INTERVALS_TIME,
                                                context)
        intervals_distance = self.parameterAsString(parameters,
                                                    self.IN_INTERVALS_DISTANCE,
                                                    context)

        feat_count = source.featureCount(
        ) if not intervals_time else source.featureCount() * 2

        self.intervals = {
            "time": [{
                "time": int(x)
            } for x in intervals_time.split(',')] if intervals_time else [],
            "distance": [{
                "distance": int(x)
            } for x in intervals_distance.split(',')]
            if intervals_distance else []
        }

        counter = 0

        for metric, interv in self.intervals.items():
            if feedback.isCanceled():
                break
            if not interv:
                continue
            # Make the actual requests
            requests = []
            for properties in self.get_sorted_feature_parameters(source):
                if feedback.isCanceled():
                    break
                r_params = deepcopy(params)
                r_params['contours'] = interv
                # Get transformed coordinates and feature
                locations, feat = properties
                r_params.update(
                    get_directions_params(locations, self.PROFILE,
                                          self.costing_options, mode))
                r_params['id'] = feat[id_field_name]
                requests.append(r_params)

            for params in requests:
                counter += 1
                if feedback.isCanceled():
                    break
                # If feature causes error, report and continue with next
                try:
                    # Populate features from response
                    response = clnt.request('/isochrone', post_json=params)
                except (exceptions.ApiError) as e:
                    msg = "Feature ID {} caused a {}:\n{}".format(
                        params['id'], e.__class__.__name__, str(e))
                    feedback.reportError(msg)
                    logger.log(msg, 2)
                    continue
                except (exceptions.InvalidKey,
                        exceptions.GenericServerError) as e:
                    msg = "{}:\n{}".format(e.__class__.__name__, str(e))
                    feedback.reportError(msg)
                    logger.log(msg)
                    raise

                options = {}
                if params.get('costing_options'):
                    options = params['costing_options']

                self.isochrones.set_response(response)
                for isochrone in self.isochrones.get_features(
                        params['id'], options.get(self.PROFILE)):
                    if metric == 'time':
                        layer_time_pr.addFeature(isochrone)
                    elif metric == 'distance':
                        layer_dist_pr.addFeature(isochrone)

                if show_locations:
                    for point_feat in self.isochrones.get_multipoint_features(
                            params['id']):
                        layer_snapped_points_pr.addFeature(point_feat)
                    for point_feat in self.isochrones.get_point_features(
                            params['id']):
                        layer_input_points_pr.addFeature(point_feat)

                feedback.setProgress(int((counter / feat_count) * 100))

        temp = []
        if layer_time.hasFeatures():
            layer_time.updateExtents()
            context.temporaryLayerStore().addMapLayer(layer_time)
            temp.append(
                ("Isochrones " + self.PROFILE.capitalize(), self.OUT_TIME,
                 layer_time.id()))
        if layer_dist.hasFeatures():
            layer_dist.updateExtents()
            context.temporaryLayerStore().addMapLayer(layer_dist)
            temp.append(
                ("Isochrones " + self.PROFILE.capitalize(), self.OUT_DISTANCE,
                 layer_dist.id()))
        if show_locations:
            layer_snapped_points.updateExtents()
            context.temporaryLayerStore().addMapLayer(layer_snapped_points)
            temp.append(("Snapped Points " + self.PROFILE.capitalize(),
                         self.POINTS_SNAPPED, layer_snapped_points.id()))

            layer_input_points.updateExtents()
            context.temporaryLayerStore().addMapLayer(layer_input_points)
            temp.append(("Input Points " + self.PROFILE.capitalize(),
                         self.POINTS_INPUT, layer_input_points.id()))

        results = dict()
        for l_name, e_id, l_id in temp:
            results[e_id] = l_id
            context.addLayerToLoadOnCompletion(
                l_id,
                QgsProcessingContext.LayerDetails(l_name, context.project(),
                                                  l_name))

        return results
예제 #43
0
def createContext(feedback=None):
    """
    Creates a default processing context

    :param feedback: Optional existing QgsProcessingFeedback object, or None to use a default feedback object
    :type feedback: Optional[QgsProcessingFeedback]

    :returns: New QgsProcessingContext object
    :rtype: QgsProcessingContext
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())
    context.setFeedback(feedback)

    invalid_features_method = ProcessingConfig.getSetting(
        ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if invalid_features_method is None:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding",
                                              "System"))

    context.setExpressionContext(createExpressionContext())

    return context
예제 #44
0
def createContext():
    """
    Creates a default processing context
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())

    use_selection = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
    if use_selection:
        context.setFlags(QgsProcessingContext.UseSelectionIfPresent)

    invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if not invalid_features_method:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    def raise_error(f):
        raise GeoAlgorithmExecutionException(QCoreApplication.translate("FeatureIterator",
                                                                        'Features with invalid geometries found. Please fix these geometries or specify the "Ignore invalid input features" flag'))

    context.setInvalidGeometryCallback(raise_error)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding", "System"))

    return context
예제 #45
0
    def testOgr2PostGis(self):
        context = QgsProcessingContext()
        feedback = QgsProcessingFeedback()
        source = os.path.join(testDataPath, 'polys.gml')
        source_with_space = os.path.join(testDataPath,
                                         'filename with spaces.gml')
        alg = OgrToPostGis()
        alg.initAlgorithm()

        self.assertEqual(
            alg.getConsoleCommands({'INPUT': source}, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({'INPUT': source_with_space}, context,
                                   feedback),
            [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 "' + source_with_space + '" filename_with_spaces '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.filename_with_spaces -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'HOST': 'google.com'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=google.com port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'PORT': 3333
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=3333 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'USER': '******'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public user=kevin_bacon" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'DBNAME': 'secret_stuff'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 dbname=secret_stuff active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'PASSWORD': '******'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 password=passw0rd active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'SCHEMA': 'desktop'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=desktop" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln desktop.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'TABLE': 'out_table'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.out_table -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'PK': ''
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'PK': 'new_fid'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=new_fid -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands(
                {
                    'INPUT': source,
                    'PK': '',
                    'PRIMARY_KEY': 'objectid'
                }, context, feedback),
            [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=objectid -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands(
                {
                    'INPUT': source,
                    'PK': 'new_id',
                    'PRIMARY_KEY': 'objectid'
                }, context, feedback),
            [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=new_id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'GEOCOLUMN': 'my_geom'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=my_geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'DIM': 1
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=3 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'SIMPLIFY': 5
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -simplify 5 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'SEGMENTIZE': 4
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -segmentize 4 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands(
                {
                    'INPUT': source,
                    'SPAT': QgsRectangle(1, 2, 3, 4)
                }, context, feedback),
            [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -spat 1.0 2.0 3.0 4.0 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'FIELDS': ['f1', 'f2']
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 -select "f1,f2" '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'WHERE': '0=1'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -where "0=1" -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'GT': 2
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -gt 2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'OVERWRITE': False
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'APPEND': True
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-append -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'ADDFIELDS': True
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-addfields -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'LAUNDER': True
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-lco LAUNDER=NO -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'INDEX': True
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-lco SPATIAL_INDEX=OFF -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'SKIPFAILURES': True
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -skipfailures -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'PROMOTETOMULTI': False
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'PRECISION': False
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI -lco PRECISION=NO'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'OPTIONS': 'blah'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI blah'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'SHAPE_ENCODING': 'blah'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES --config SHAPE_ENCODING blah -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'GTYPE': 4
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -nlt LINESTRING -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'A_SRS': 'EPSG:3111'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -a_srs EPSG:3111 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands(
                {
                    'INPUT': source,
                    'A_SRS': QgsCoordinateReferenceSystem('EPSG:3111')
                }, context, feedback),
            [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -a_srs EPSG:3111 -nlt PROMOTE_TO_MULTI'
            ])

        custom_crs = 'proj4: +proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs'
        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'A_SRS': custom_crs
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -a_srs EPSG:20936 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'T_SRS': 'EPSG:3111'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -t_srs EPSG:3111 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands(
                {
                    'INPUT': source,
                    'T_SRS': QgsCoordinateReferenceSystem('EPSG:3111')
                }, context, feedback),
            [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -t_srs EPSG:3111 -nlt PROMOTE_TO_MULTI'
            ])

        custom_crs = 'proj4: +proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs'
        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'T_SRS': custom_crs
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -t_srs EPSG:20936 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'S_SRS': 'EPSG:3111'
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -s_srs EPSG:3111 -nlt PROMOTE_TO_MULTI'
            ])

        self.assertEqual(
            alg.getConsoleCommands(
                {
                    'INPUT': source,
                    'S_SRS': QgsCoordinateReferenceSystem('EPSG:3111')
                }, context, feedback),
            [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -s_srs EPSG:3111 -nlt PROMOTE_TO_MULTI'
            ])

        custom_crs = 'proj4: +proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs'
        self.assertEqual(
            alg.getConsoleCommands({
                'INPUT': source,
                'S_SRS': custom_crs
            }, context, feedback), [
                'ogr2ogr',
                '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" '
                '-lco DIM=2 ' + source + ' polys2 '
                '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -s_srs EPSG:20936 -nlt PROMOTE_TO_MULTI'
            ])
예제 #46
0
    def __init__(self, parent: QWidget = None) -> None:
        QDialog.__init__(self, parent)
        self.setupUi(self)

        self.message_bar: QgsMessageBar

        self.btn_load.clicked.connect(self.__load_wfs_layer)
        self.btn_select.clicked.connect(self.__select_wfs_layer)
        self.btn_clear_search.clicked.connect(
            self.__clear_stored_wfs_queries_search)

        # Typing
        self.extent_group_box_bbox: QgsExtentGroupBox
        self.progress_bar: QProgressBar
        self.search_ln_ed: QgsFilterLineEdit
        self.search_ln_ed.valueChanged.connect(self.__search_stored_wfs_layers)

        self.extent_group_box_bbox.setOriginalExtent(
            iface.mapCanvas().extent(),
            iface.mapCanvas().mapSettings().destinationCrs(),
        )
        self.extent_group_box_bbox.setCurrentExtent(
            iface.mapCanvas().extent(),
            iface.mapCanvas().mapSettings().destinationCrs(),
        )
        self.extent_group_box_bbox.setOutputCrs(
            QgsCoordinateReferenceSystem("EPSG:4326"))
        try:
            self.extent_group_box_bbox.setMapCanvas(iface.mapCanvas(),
                                                    drawOnCanvasOption=False)
        except TypeError:
            self.extent_group_box_bbox.setMapCanvas(iface.mapCanvas())
        self.extent_group_box_bbox.setOutputExtentFromCurrent()
        self.chk_box_add_to_map: QCheckBox
        self.btn_output_dir_select: QgsFileWidget
        self.btn_output_dir_select.setFilePath(
            str(
                Path(QgsProject.absoluteFilePath(
                    QgsProject.instance())).parent))

        self.progress_bar.setValue(0)

        # Context and feedback for processing algorithms
        self.context: QgsProcessingContext = QgsProcessingContext()
        self.feedback: QgsProcessingFeedback = LoggerProcessingFeedBack(
            use_logger=True)

        self.responsive_items = {
            self.btn_load,
            self.btn_select,
            self.chk_box_add_to_map,
            self.btn_clear_search,
        }

        self.task: Optional[BaseLoader] = None
        self.sq_factory = StoredQueryFactory(Settings.FMI_WFS_URL.get(),
                                             Settings.FMI_WFS_VERSION.get())
        self.stored_queries: List[StoredQuery] = []
        self.selected_stored_query: Optional[StoredQuery] = None

        # populating dynamically the parameters of main dialog
        self.grid: QGridLayout
        self.parameter_rows: Dict[str, Set[QWidget]] = {}
        self.tbl_wdgt_stored_queries: QTableWidget

        # populating the layer list when opening
        self.__refresh_stored_wfs_queries()
예제 #47
0
def createContext(feedback=None):
    """
    Creates a default processing context
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())
    context.setFeedback(feedback)

    invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if invalid_features_method is None:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding", "System"))

    context.setExpressionContext(createExpressionContext())

    return context
예제 #48
0
    def testInPlace(self):
        geocoder = TestGeocoderExtraFields()

        alg = TestGeocoderAlgorithm(geocoder)
        alg.initParameters({'IN_PLACE': True})

        fields = QgsFields()
        fields.append(QgsField('some_pk', QVariant.Int))
        fields.append(QgsField('address', QVariant.String))
        fields.append(QgsField('parsedx', QVariant.String))
        fields.append(QgsField('accuracyx', QVariant.Int))

        output_fields = alg.outputFields(fields)
        self.assertEqual([f.name() for f in output_fields],
                         ['some_pk', 'address', 'parsedx', 'accuracyx'])
        self.assertEqual(
            [f.type() for f in output_fields],
            [QVariant.Int, QVariant.String, QVariant.String, QVariant.Int])

        f = QgsFeature(fields)
        f.initAttributes(4)
        f['some_pk'] = 17

        # not storing additional attributes
        params = {'FIELD': 'address'}

        context = QgsProcessingContext()
        feedback = QgsProcessingFeedback()
        self.assertTrue(alg.prepareAlgorithm(params, context, feedback))

        # empty field
        res = alg.processFeature(f, context, feedback)
        self.assertEqual(len(res), 1)
        self.assertTrue(res[0].geometry().isNull())
        self.assertEqual(res[0].attributes(), [17, NULL, NULL, NULL])

        f['address'] = 'a'
        res = alg.processFeature(f, context, feedback)
        self.assertEqual(len(res), 1)
        self.assertEqual(res[0].geometry().asWkt(), 'Point (1 2)')
        self.assertEqual(res[0].attributes(), [17, 'a', None, None])

        f.clearGeometry()
        f['address'] = NULL

        # storing additional attributes
        params = {
            'FIELD': 'address',
            'parsed': 'parsedx',
            'accuracy': 'accuracyx'
        }

        context = QgsProcessingContext()
        feedback = QgsProcessingFeedback()
        self.assertTrue(alg.prepareAlgorithm(params, context, feedback))

        # empty field
        res = alg.processFeature(f, context, feedback)
        self.assertEqual(len(res), 1)
        self.assertTrue(res[0].geometry().isNull())
        self.assertEqual(res[0].attributes(), [17, NULL, NULL, NULL])

        f['address'] = 'b'
        res = alg.processFeature(f, context, feedback)
        self.assertEqual(len(res), 1)
        self.assertEqual(res[0].geometry().asWkt(), 'Point (11 12)')
        self.assertEqual(res[0].attributes(), [17, 'b', 'xyz2', 456])
예제 #49
0
    def test_flags(self):
        """
        Test task flags
        """
        thread_safe_alg = QgsApplication.processingRegistry().algorithmById(
            'native:buffer')
        nonthread_safe_alg = QgsApplication.processingRegistry().algorithmById(
            'native:setprojectvariable')
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback)
        self.assertEqual(task.flags(), QgsTask.CanCancel)
        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.Flags())
        self.assertEqual(task.flags(), QgsTask.Flags())
        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.CanCancel)
        self.assertEqual(task.flags(), QgsTask.CanCancel)
        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.CancelWithoutPrompt)
        self.assertEqual(task.flags(), QgsTask.CancelWithoutPrompt)
        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.CancelWithoutPrompt
                                          | QgsTask.CanCancel)
        self.assertEqual(task.flags(),
                         QgsTask.CancelWithoutPrompt | QgsTask.CanCancel)

        # alg which can't be canceled
        task = QgsProcessingAlgRunnerTask(nonthread_safe_alg, {},
                                          context=context,
                                          feedback=feedback)
        self.assertEqual(task.flags(), QgsTask.Flags())
        # we clear the CanCancel flag automatically, since the algorithm itself cannot be canceled
        task = QgsProcessingAlgRunnerTask(nonthread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.CanCancel)
        self.assertEqual(task.flags(), QgsTask.Flags())

        # hidden task
        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.Hidden)
        self.assertEqual(task.flags(), QgsTask.Hidden)
        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.Hidden
                                          | QgsTask.CanCancel)
        self.assertEqual(task.flags(), QgsTask.Hidden | QgsTask.CanCancel)
        task = QgsProcessingAlgRunnerTask(thread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.Hidden
                                          | QgsTask.CanCancel
                                          | QgsTask.CancelWithoutPrompt)
        self.assertEqual(
            task.flags(),
            QgsTask.Hidden | QgsTask.CanCancel | QgsTask.CancelWithoutPrompt)

        task = QgsProcessingAlgRunnerTask(nonthread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.Hidden)
        self.assertEqual(task.flags(), QgsTask.Hidden)
        task = QgsProcessingAlgRunnerTask(nonthread_safe_alg, {},
                                          context=context,
                                          feedback=feedback,
                                          flags=QgsTask.Hidden
                                          | QgsTask.CanCancel)
        self.assertEqual(task.flags(), QgsTask.Hidden)
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        source = self.parameterAsSource(parameters, self.INPUT, context)
        path = self.parameterAsFile(parameters, self.OUTPUT, context)

        field_def = {
            'idx': QVariant.Int,
            'name': QVariant.String,
            'type': QVariant.Int,
            'typeName': QVariant.String,
            'length': QVariant.Int,
            'precision': QVariant.Int,
            'comment': QVariant.String,
            'alias': QVariant.String
        }

        # create virtual layer
        vl = QgsVectorLayer("None", "fields", "memory")
        pr = vl.dataProvider()

        # define fields
        fields = QgsFields()
        for n, t in field_def.items():
            fields.append(QgsField(name=n, type=t))

        # add fields
        pr.addAttributes(fields)
        vl.updateFields(
        )  # tell the vector layer to fetch changes from the provider

        # add feature based on field description
        field_index = 0
        for f in providerFields(source.fields()):
            field_index += 1
            feat = QgsFeature()
            feat.setAttributes([
                field_index,
                f.name(),
                f.type(),
                f.typeName(),
                f.length(),
                f.precision(),
                f.comment(),
                f.alias()
            ])
            pr.addFeatures([feat])

        # set create file layer options
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = QgsVectorFileWriter.driverForExtension('csv')
        options.fileEncoding = 'UTF-8'
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
        options.layerOptions = ['CREATE_CSVT=YES']

        # write file
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            vl, path, options)

        # result
        if write_result != QgsVectorFileWriter.NoError:
            raise QgsProcessingException(
                self.tr('* ERROR: {0}').format(error_message))

        del fields
        del pr
        del vl

        # create layer
        dest_layer = QgsVectorLayer(path, self.OUTPUT_LAYER, 'ogr')
        if not dest_layer.isValid():
            raise QgsProcessingException(
                self.tr('* ERROR: Can\'t load layer {1} in {0}').format(
                    path, self.OUTPUT_LAYER))

        # Add layer to context
        context.temporaryLayerStore().addMapLayer(dest_layer)
        context.addLayerToLoadOnCompletion(
            dest_layer.id(),
            QgsProcessingContext.LayerDetails(self.OUTPUT_LAYER,
                                              context.project(),
                                              self.OUTPUT_LAYER))

        return {self.OUTPUT: path, self.OUTPUT_LAYER: dest_layer.id()}