Ejemplo n.º 1
0
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(8, model_feedback)
        results = {}
        outputs = {}

        tracks = self.parameterAsSource(parameters, self.TRACKS, context)

        # prepare_tracks
        alg_params = {
            "TRACKS": parameters[self.TRACKS],
            "AXIS": parameters[self.AXIS],
            "NAME_FIELD": parameters[self.NAME_FIELD],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["PrepareTracks"] = processing.run(
            "precourlis:prepare_tracks",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["PrepareTracks"]["OUTPUT"]

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # addautoincrementalfield
        alg_params = {
            "INPUT": current,
            "FIELD_NAME": "sec_index",
            "START": 1,
            "GROUP_FIELDS": [],
            "SORT_EXPRESSION": '"abs_long"',
            "SORT_ASCENDING": True,
            "SORT_NULLS_FIRST": False,
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["AddAutoincrementalField"] = processing.run(
            "native:addautoincrementalfield",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["AddAutoincrementalField"]["OUTPUT"]

        feedback.setCurrentStep(2)
        if feedback.isCanceled():
            return {}

        # fieldcalculator
        alg_params = {
            "INPUT": current,
            "FIELD_NAME": "sec_id",
            "FIELD_TYPE": 0,
            "FIELD_LENGTH": 10,
            "FIELD_PRECISION": 3,
            "NEW_FIELD": False,
            "FORMULA": ' "sec_index" ',
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["FieldCalculator"] = processing.run(
            "qgis:fieldcalculator",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["FieldCalculator"]["OUTPUT"]

        feedback.setCurrentStep(3)
        if feedback.isCanceled():
            return {}

        strict_distance = self.parameterAsBool(
            parameters, self.STRICT_DISTANCE, context
        )
        if strict_distance:
            # pointsalonglines
            alg_params = {
                "INPUT": current,
                "DISTANCE": parameters[self.DISTANCE],
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["PointsAlongLines"] = processing.run(
                "precourlis:pointsalonglines",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )
            current = outputs["PointsAlongLines"]["OUTPUT"]
            points_order_field = "distance"
        else:
            # v.to.points
            v_to_points = QgsApplication.processingRegistry().createAlgorithmById(
                "grass7:v.to.points"
            )
            alg_params = {
                "-i": True,
                "-t": False,
                "dmax": parameters[self.DISTANCE],
                "input": current,
                "type": [1],
                "use": 1,
                "output": v_to_points.parameterDefinition(
                    "output"
                ).generateTemporaryDestination(),
            }
            outputs["Vtopoints"] = processing.run(
                "grass7:v.to.points",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )
            current = outputs["Vtopoints"]["output"]
            points_order_field = "fid"

        feedback.setCurrentStep(4)
        if feedback.isCanceled():
            return {}

        # assignprojection
        alg_params = {
            "INPUT": current,
            "CRS": tracks.sourceCrs(),
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["AssignProjection"] = processing.run(
            "native:assignprojection",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["AssignProjection"]["OUTPUT"]

        feedback.setCurrentStep(5)
        if feedback.isCanceled():
            return {}

        # point_to_lines
        alg_params = {
            "INPUT": current,
            "FIRST_SECTION_ABS_LONG": parameters.get(self.FIRST_SECTION_ABS_LONG, None),
            "FIRST_AXIS_POINT_ABS_LONG": parameters.get(
                self.FIRST_AXIS_POINT_ABS_LONG, None
            ),
            "GROUP_FIELD": "sec_id",
            "ORDER_FIELD": points_order_field,
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["PointsToLines"] = processing.run(
            "precourlis:points_to_lines",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["PointsToLines"]["OUTPUT"]

        feedback.setCurrentStep(6)
        if feedback.isCanceled():
            return {}

        # import_layer_from_dem (edit layer in place with edit buffer)
        layer = context.getMapLayer(current)
        alg_params = {
            "INPUT": layer,
            "LAYER_NAME": "zfond",
            "DEM": parameters[self.DEM],
            "BAND": 1,
        }
        outputs["ImportLayerFromDem"] = processing.run(
            "precourlis:import_layer_from_dem",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(7)
        if feedback.isCanceled():
            return {}

        # orderbyexpression (dump layer with changes from edit buffer)
        layer.selectAll()
        alg_params = {
            "INPUT": layer,
            "EXPRESSION": '"sec_id"',
            "ASCENDING": True,
            "NULLS_FIRST": False,
            "OUTPUT": self.parameterAsOutputLayer(parameters, self.OUTPUT, context),
        }
        outputs["OrderByExpression"] = processing.run(
            "native:orderbyexpression",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["OrderByExpression"]["OUTPUT"]

        results["OUTPUT"] = current
        return results
Ejemplo n.º 2
0
    def getSystematicGridFeaturesWithConstraint(self, featureList, inputLyr, stopScale,
                                                coordinateTransformer, fields, feedback=None, predicate=None):
        """
        TODO: Progress
        """
        if feedback is not None and feedback.isCanceled():
            return
        predicate = 'intersects' if predicate is None else predicate
        multiStepFeedback = QgsProcessingMultiStepFeedback(2, feedback)
        multiStepFeedback.setCurrentStep(0)
        multiStepFeedback.pushInfo(self.tr('Creating spatial index'))
        spatialIdx, idDict = self.buildSpatialIndexAndIdDict(
            inputLyr,
            feedback=multiStepFeedback
        )
        multiStepFeedback.pushInfo(self.tr('Getting candidate start indexes'))
        xmin, ymin, xmax, ymax = self.getLyrUnprojectedGeographicBounds(
            inputLyr
        )
        inomenList = self.utmGrid.get_INOM_range_from_BB(
            xmin, ymin, xmax, ymax
        )
        multiStepFeedback.setCurrentStep(1)
        multiStepFeedback.pushInfo(self.tr('Building grid'))
        gridMultistepFeedback = QgsProcessingMultiStepFeedback(
            len(inomenList),
            multiStepFeedback
        )
        constraintDict = {
            'spatialIdx': spatialIdx,
            'idDict': idDict,
            'predicate': predicate
        }
        sys.setrecursionlimit(10**7)

        def compute(x):
            self.getSystematicGridFeatures(
                featureList,
                x,
                stopScale,
                coordinateTransformer,
                fields,
                constraintDict=constraintDict,
                feedback=gridMultistepFeedback
            )
        pool = concurrent.futures.ThreadPoolExecutor(os.cpu_count())
        futures = []
        current_idx = 0
        for inomen in inomenList:
            # gridMultistepFeedback.setCurrentStep(i)
            if gridMultistepFeedback.isCanceled():
                break
            futures.append(
                pool.submit(compute, inomen)
            )

        for x in concurrent.futures.as_completed(futures):
            if gridMultistepFeedback.isCanceled():
                break
            gridMultistepFeedback.setCurrentStep(current_idx)
            current_idx += 1
Ejemplo n.º 3
0
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(4, model_feedback)
        results = {}
        outputs = {}

        sections = self.parameterAsSource(parameters, self.SECTIONS, context)

        # Retreive first section longitudinal abscissa
        request = (QgsFeatureRequest().setFlags(
            QgsFeatureRequest.NoGeometry
            | QgsFeatureRequest.SubsetOfAttributes).setSubsetOfAttributes(
                ["abs_long"],
                sections.fields()).addOrderBy('"sec_id"', True,
                                              True).setLimit(1))
        first_section = next(sections.getFeatures(request))
        first_abs_long = first_section.attribute("abs_long")

        # Lines to points
        alg_params = {
            "INPUT":
            parameters[self.SECTIONS],
            "OUTPUT":
            QgsProcessingUtils.generateTempFilename("lines_to_points.shp"),
        }
        outputs["LinesToPoints"] = processing.run(
            "precourlis:lines_to_points",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["LinesToPoints"]["OUTPUT"]

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # Interpolate points
        alg_params = {
            "SECTIONS":
            current,
            "AXIS":
            parameters[self.AXIS],
            "CONSTRAINT_LINES":
            parameters.get(self.CONSTRAINT_LINES),
            "LONG_STEP":
            parameters[self.LONG_STEP],
            "LAT_STEP":
            parameters[self.LAT_STEP],
            "ATTR_CROSS_SECTION":
            "sec_id",
            "OUTPUT":
            QgsProcessingUtils.generateTempFilename("interpolate_points.shp"),
        }
        outputs["InterpolatePoints"] = processing.run(
            "precourlis:interpolate_points",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["InterpolatePoints"]["OUTPUT"]

        feedback.setCurrentStep(2)
        if feedback.isCanceled():
            return {}

        # assignprojection
        alg_params = {
            "INPUT": current,
            "CRS": sections.sourceCrs(),
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["AssignProjection"] = processing.run(
            "native:assignprojection",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["AssignProjection"]["OUTPUT"]

        feedback.setCurrentStep(3)
        if feedback.isCanceled():
            return {}

        output = QgsProcessingOutputLayerDefinition(parameters[self.OUTPUT])
        output.destinationName = self.tr("Interpolated")

        # Points to lines
        alg_params = {
            "INPUT": current,
            "AXIS": parameters[self.AXIS],
            "FIRST_SECTION_ABS_LONG": first_abs_long,
            "GROUP_FIELD": "abs_long",
            "ORDER_FIELD": "p_id",
            "OUTPUT": output,
        }
        outputs["PointsToLines"] = processing.run(
            "precourlis:points_to_lines",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        current = outputs["PointsToLines"]["OUTPUT"]

        results["OUTPUT"] = current
        return results
 def processAlgorithm(self, parameters, context, feedback):
     # Params
     reporting_mode = self.parameterAsEnum(parameters, self.REPORTING_MODE,
                                           context)
     lighting_source, lighting_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, self.LIGHTING, context, feedback=feedback)
     self.fieldname = self.parameterAsString(parameters, FDA.FLUX_FIELD,
                                             context)
     surface_source, surface_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, self.SURFACE, context, feedback=feedback)
     roads_source, roads_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, RE.ROADS, context, feedback=feedback)
     # Advanced params
     clip_distance = self.parameterAsDouble(parameters, self.CLIP_DISTANCE,
                                            context)
     # Outputs
     self.output = self.parameterAsOutputLayer(parameters, self.OUTPUT,
                                               context)
     out_linear = reporting_mode == 1
     # Init steps
     nb_steps = 3 if out_linear else 2
     mf = QgsProcessingMultiStepFeedback(nb_steps, feedback)
     if out_linear:
         id_field = 'ID'
         if id_field not in roads_layer.fields().names():
             raise QgsProcessingException("No 'ID' field in roads layer")
     qgsTreatments.fixShapefileFID(surface_layer,
                                   context=context,
                                   feedback=feedback)
     # Reporting
     reporting_layer = QgsProcessingUtils.generateTempFilename(
         'reporting.gpkg')
     if reporting_mode == 3:  # voronoi
         if qgsUtils.isMultipartLayer(lighting_layer):
             in_voronoi = QgsProcessingUtils.generateTempFilename(
                 'lighting_single.gpkg')
             qgsTreatments.multiToSingleGeom(lighting_layer,
                                             in_voronoi,
                                             context=context,
                                             feedback=mf)
         else:
             in_voronoi = lighting_layer
         qgsTreatments.applyVoronoi(in_voronoi,
                                    reporting_layer,
                                    context=context,
                                    feedback=mf)
     else:
         reporting_params = parameters.copy()
         reporting_params[RR.ROADS] = roads_layer
         reporting_params[RR.BUFFER_EXPR] = RR.DEFAULT_BUFFER_EXPR
         reporting_params[RR.NAME_FIELD] = RR.DEFAULT_NAME_FIELD
         reporting_params[RR.END_CAP_STYLE] = 1  # Flat buffer cap style
         reporting_params[RR.DISSOLVE] = reporting_mode in [2]  # Roads
         reporting_params[RR.OUTPUT] = reporting_layer
         qgsTreatments.applyProcessingAlg('LPT',
                                          RR.ALG_NAME,
                                          reporting_params,
                                          context=context,
                                          feedback=mf)
     mf.setCurrentStep(1)
     # Light surfacic density
     density_params = parameters.copy()
     density_params[FDA.LIGHTING] = lighting_layer
     density_params[FDA.REPORTING] = reporting_layer
     density_params[FDA.CLIP_DISTANCE] = clip_distance
     density_params[FDA.SURFACE] = surface_layer
     if out_linear:
         output_surf = QgsProcessingUtils.generateTempFilename(
             'output_surface.gpkg')
         density_params[FDA.REPORTING_FIELDS] = [id_field]
         density_params[FDA.OUTPUT] = output_surf
     else:
         density_params[FDA.OUTPUT] = self.output
     self.out_id = qgsTreatments.applyProcessingAlg('LPT',
                                                    FDA.ALG_NAME,
                                                    density_params,
                                                    context=context,
                                                    feedback=mf)
     mf.setCurrentStep(3)
     # Join if output linear
     if out_linear:
         copy_fields = [
             FDA.NB_LAMPS, FDA.FLUX_SUM, FDA.SURFACE_AREA, FDA.FLUX_DEN
         ]
         self.out_id = qgsTreatments.joinByAttribute(
             roads_layer,
             id_field,
             output_surf,
             id_field,
             copy_fields=copy_fields,
             out_layer=self.output,
             context=context,
             feedback=mf)
     return {self.OUTPUT: self.output}
Ejemplo n.º 5
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)
        results = {}
        outputs = {}

        # Convert enumerator to zero based index value
        valor_classifica = self.parameterAsEnum(
            parameters, self.VALOR_CLASSIFICA, context) + 1

        valor_natureza_linha = self.parameterAsEnum(
            parameters, self.VALOR_NATUREZA_LINHA, context) + 1

        # Refactor fields
        alg_params = {
            'FIELDS_MAPPING': [{
                'expression': 'now()',
                'length': -1,
                'name': 'inicio_objeto',
                'precision': -1,
                'type': 14
            }, {
                'expression': str(valor_classifica),
                'length': 255,
                'name': 'valor_classifica',
                'precision': -1,
                'type': 10
            }, {
                'expression': str(valor_natureza_linha),
                'length': 255,
                'name': 'valor_natureza_linha',
                'precision': -1,
                'type': 10
            }],
            'INPUT':
            parameters['INPUT'],
            'OUTPUT':
            QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['RefactorFields'] = processing.run('qgis:refactorfields',
                                                   alg_params,
                                                   context=context,
                                                   feedback=feedback,
                                                   is_child_algorithm=True)

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # Export to PostgreSQL (available connections)
        idx = self.parameterAsEnum(parameters, self.POSTGRES_CONNECTION,
                                   context)

        postgres_connection = self.postgres_connections_list[idx]

        alg_params = {
            'ADDFIELDS': True,
            'APPEND': True,
            'A_SRS': None,
            'CLIP': False,
            'DATABASE': postgres_connection,
            'DIM': 1,
            'GEOCOLUMN': 'geometria',
            'GT': '',
            'GTYPE': 4,
            'INDEX': True,
            'INPUT': outputs['RefactorFields']['OUTPUT'],
            'LAUNDER': True,
            'OPTIONS': '',
            'OVERWRITE': False,
            'PK': '',
            'PRECISION': True,
            'PRIMARY_KEY': 'identificador',
            'PROMOTETOMULTI': True,
            'SCHEMA': 'public',
            'SEGMENTIZE': '',
            'SHAPE_ENCODING': '',
            'SIMPLIFY': '',
            'SKIPFAILURES': False,
            'SPAT': None,
            'S_SRS': None,
            'TABLE': 'linha_de_quebra',
            'T_SRS': None,
            'WHERE': ''
        }
        outputs['ExportToPostgresqlAvailableConnections'] = processing.run(
            'gdal:importvectorintopostgisdatabaseavailableconnections',
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True)
        return results
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
        results = {}
        outputs = {}
        #parameters['Out']='/tmp/nasa_1km3857clean_r6s3SE250m_statr4.shp'
        parameters['Slope'] = self.parameterAsRasterLayer(parameters, self.INPUT1, context).source()
        if parameters['Slope'] is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT1))
        
        parameters['Inventory'] = self.parameterAsVectorLayer(parameters, self.INPUT, context).source()
        if parameters['Inventory'] is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
            
        parameters['poly'] = self.parameterAsVectorLayer(parameters, self.EXTENT, context).source()
        if parameters['poly'] is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.EXTENT))
            
        parameters['BufferRadiousInPxl'] = self.parameterAsInt(parameters, self.RADIUS, context)
        if parameters['BufferRadiousInPxl'] is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.RADIUS))    
            
        #parameters['out1']=self.parameterAsSink(parameters,self.OUTPUT,context)
        #if parameters['out1'] is None:
        #    raise QgsProcessingException(self.invalidSourceError(parameters, self.OUTPUT))
        
        outFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
        parameters['Out'], outputFormat = GdalUtils.ogrConnectionStringAndFormat(outFile, context)
        if parameters['Out'] is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.OUTPUT))
        
        #parameters['Out'] = self.parameterAsSink(
        #    parameters,
        #    self.OUTPUT,
        #    context)

        print('importing')
        alg_params = {
            'INPUT': parameters['poly'],
            'INPUT2': parameters['Slope'],
            'INPUT3' : parameters['Inventory']
        }
        raster,ds1,XY=self.importing(alg_params)
        outputs['raster'] = raster
        outputs['ds1'] = ds1
        outputs['XY'] = XY

        print('indexing')
        alg_params = {
            'INPUT': parameters['BufferRadiousInPxl'],
            'INPUT3': outputs['raster'],
            'INPUT2': outputs['XY'],
            'INPUT1': outputs['ds1']
        }
        XYcoord,attributi=self.indexing(alg_params)
        outputs['XYcoord'] = XYcoord
        outputs['attributi'] = attributi

        print('save')
        alg_params = {
            'OUTPUT': parameters['Out'],
            'INPUT2': outputs['XYcoord'],
            'INPUT': outputs['ds1'],
            'INPUT3': outputs['attributi']
        }
        self.saveV(alg_params)

        # vlayer = QgsVectorLayer(parameters['Out'], 'vector', "ogr")
        # QgsProject.instance().addMapLayer(vlayer)

        # # Join attributes by location
        # alg_params = {
        #     'DISCARD_NONMATCHING': False,
        #     'INPUT': parameters['Inventory'],
        #     'JOIN': parameters['Out'],
        #     'JOIN_FIELDS': [''],
        #     'METHOD': 1,
        #     'PREDICAT4E': [2],
        #     'PREFIX': '',
        #     'OUTPUT': parameters['Out1']
        # }
        # outputs['JoinAttributesByLocation'] = processing.run('native:joinattributesbylocation', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        # results['Out'] = outputs['JoinAttributesByLocation']['OUTPUT']

        # vlayer = QgsVectorLayer(parameters['Out1'], 'vector', "ogr")
        # QgsProject.instance().addMapLayer(vlayer)

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}
        return results
 def _prepare_progress_bar(self, feedback):
     """Prepare number of steps for progress bar."""
     self.multi_feedback = QgsProcessingMultiStepFeedback(
         self.step_count, feedback)
     self.run_next_step = QgisStepManager(self.multi_feedback)
Ejemplo n.º 8
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(24, model_feedback)
        results = {}
        outputs = {}

        # Gitter (Nächster Nachbar)
        alg_params = {
            'ANGLE': 0,
            'DATA_TYPE': 5,
            'INPUT': parameters['depth'],
            'NODATA': 0,
            'OPTIONS': '',
            'RADIUS_1': 0,
            'RADIUS_2': 0,
            'Z_FIELD': parameters['timeaffterspillinminutes'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['GitterNchsterNachbar'] = processing.run('gdal:gridnearestneighbor', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # Gitter (Nächster Nachbar)
        alg_params = {
            'ANGLE': 0,
            'DATA_TYPE': 5,
            'INPUT': parameters['velocityy'],
            'NODATA': 0,
            'OPTIONS': '',
            'RADIUS_1': 0,
            'RADIUS_2': 0,
            'Z_FIELD': parameters['timeaffterspillinminutes'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['GitterNchsterNachbar'] = processing.run('gdal:gridnearestneighbor', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(2)
        if feedback.isCanceled():
            return {}

        # Zufällige Auswahl
        alg_params = {
            'INPUT': parameters['percedingspillstage'],
            'METHOD': 1,
            'NUMBER': QgsExpression('100- floor( (5.91 + 0.045 *@temperatureinc  )*ln(@timemin) - ((5.91 + 0.045 * @temperatureinc )*ln(@timemin-1)))').evaluate()
        }
        outputs['ZuflligeAuswahl'] = processing.run('qgis:randomselection', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(3)
        if feedback.isCanceled():
            return {}

        # Gewählte Objekte exportieren
        alg_params = {
            'INPUT': outputs['ZuflligeAuswahl']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['GewhlteObjekteExportieren'] = processing.run('native:saveselectedfeatures', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(4)
        if feedback.isCanceled():
            return {}

        # Gitter (Nächster Nachbar)
        alg_params = {
            'ANGLE': 0,
            'DATA_TYPE': 5,
            'INPUT': parameters['velocityx'],
            'NODATA': 0,
            'OPTIONS': '',
            'RADIUS_1': 0,
            'RADIUS_2': 0,
            'Z_FIELD': parameters['timeaffterspillinminutes'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['GitterNchsterNachbar'] = processing.run('gdal:gridnearestneighbor', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(5)
        if feedback.isCanceled():
            return {}

        # Minimale begrenzende Geometrie
        alg_params = {
            'FIELD': None,
            'INPUT': outputs['GewhlteObjekteExportieren']['OUTPUT'],
            'TYPE': 3,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['MinimaleBegrenzendeGeometrie'] = processing.run('qgis:minimumboundinggeometry', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(6)
        if feedback.isCanceled():
            return {}

        # Felder überarbeiten
        alg_params = {
            'FIELDS_MAPPING': [{'expression': '"id"', 'length': 10, 'name': 'id', 'precision': 0, 'type': 4}],
            'INPUT': outputs['GewhlteObjekteExportieren']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['FelderBerarbeiten'] = processing.run('qgis:refactorfields', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(7)
        if feedback.isCanceled():
            return {}

        # "Leerwert" füllen
        alg_params = {
            'BAND': 1,
            'DISTANCE': 10,
            'INPUT': outputs['GitterNchsterNachbar']['OUTPUT'],
            'ITERATIONS': 0,
            'MASK_LAYER': None,
            'NO_MASK': False,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['LeerwertFllen'] = processing.run('gdal:fillnodata', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(8)
        if feedback.isCanceled():
            return {}

        # "Leerwert" füllen
        alg_params = {
            'BAND': 1,
            'DISTANCE': 10,
            'INPUT': outputs['GitterNchsterNachbar']['OUTPUT'],
            'ITERATIONS': 0,
            'MASK_LAYER': None,
            'NO_MASK': False,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['LeerwertFllen'] = processing.run('gdal:fillnodata', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(9)
        if feedback.isCanceled():
            return {}

        # Zentroide
        alg_params = {
            'ALL_PARTS': False,
            'INPUT': outputs['MinimaleBegrenzendeGeometrie']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['Zentroide'] = processing.run('native:centroids', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(10)
        if feedback.isCanceled():
            return {}

        # Add raster values to features
        alg_params = {
            'GRIDS': [outputs['LeerwertFllen']['OUTPUT'],outputs['LeerwertFllen']['OUTPUT'],outputs['GitterNchsterNachbar']['OUTPUT']],
            'RESAMPLING': 0,
            'SHAPES': parameters['perimeter'],
            'RESULT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['AddRasterValuesToFeatures'] = processing.run('saga:addrastervaluestofeatures', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(11)
        if feedback.isCanceled():
            return {}

        # Attribute nach Position zusammenfügen
        alg_params = {
            'DISCARD_NONMATCHING': False,
            'INPUT': outputs['FelderBerarbeiten']['OUTPUT'],
            'JOIN': outputs['AddRasterValuesToFeatures']['RESULT'],
            'JOIN_FIELDS': None,
            'METHOD': 1,
            'PREDICATE': 0,
            'PREFIX': '',
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['AttributeNachPositionZusammenfgen'] = processing.run('qgis:joinattributesbylocation', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(12)
        if feedback.isCanceled():
            return {}

        # Verschieben
        alg_params = {
            'DELTA_M': 0,
            'DELTA_X': QgsProperty.fromExpression('CASE 
WHEN "OUTPUT_2" > 0  THEN 
(sqrt((pi()*1.21^2*(((@volumeofthespillinlitres/1000)^2*9.81*0.1793*((1/60)* @timemin )^1.5)/0.000001139^0.5)^(1/3))/pi()))/60 * sin(azimuth( make_point( @Zentroide_OUTPUT_maxx , @Zentroide_OUTPUT_maxy ), $geometry))*60* @timespan
ELSE 0
END'),
            'DELTA_Y': QgsProperty.fromExpression('CASE 
WHEN "OUTPUT_2" > 0  THEN 
(sqrt((pi()*1.21^2*(((@volumeofthespillinlitres/1000)^2*9.81*0.1793*((1/60)* @timemin )^1.5)/0.000001139^0.5)^(1/3))/pi()))/60 * cos(azimuth( make_point( @Zentroide_OUTPUT_maxx , @Zentroide_OUTPUT_maxy ), $geometry))*60* @timespan
ELSE 0
END'),
            'DELTA_Z': 0,
            'INPUT': outputs['AttributeNachPositionZusammenfgen']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['Verschieben'] = processing.run('native:translategeometry', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(13)
        if feedback.isCanceled():
            return {}

        # Felder überarbeiten
        alg_params = {
            'FIELDS_MAPPING': [{'expression': '"id"', 'length': 10, 'name': 'id', 'precision': 0, 'type': 4}],
            'INPUT': outputs['Verschieben']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['FelderBerarbeiten'] = processing.run('qgis:refactorfields', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(14)
        if feedback.isCanceled():
            return {}

        # Attribute nach Position zusammenfügen
        alg_params = {
            'DISCARD_NONMATCHING': False,
            'INPUT': outputs['FelderBerarbeiten']['OUTPUT'],
            'JOIN': outputs['AddRasterValuesToFeatures']['RESULT'],
            'JOIN_FIELDS': None,
            'METHOD': 0,
            'PREDICATE': 0,
            'PREFIX': '',
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['AttributeNachPositionZusammenfgen'] = processing.run('qgis:joinattributesbylocation', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(15)
        if feedback.isCanceled():
            return {}

        # Verschieben
        alg_params = {
            'DELTA_M': 0,
            'DELTA_X': QgsProperty.fromExpression('CASE 
WHEN "OUTPUT_2" > 0.001 
THEN "OUTPUT" * 60 *  @timespan
ELSE 0
END'),
            'DELTA_Y': QgsProperty.fromExpression('CASE 
WHEN "OUTPUT_2" > 0.001 
THEN "OUTPUT_1" * 60 *  @timespan
ELSE 0
END'),
            'DELTA_Z': 0,
            'INPUT': outputs['AttributeNachPositionZusammenfgen']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['Verschieben'] = processing.run('native:translategeometry', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(16)
        if feedback.isCanceled():
            return {}

        # Minimale begrenzende Geometrie
        alg_params = {
            'FIELD': None,
            'INPUT': outputs['Verschieben']['OUTPUT'],
            'TYPE': 3,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['MinimaleBegrenzendeGeometrie'] = processing.run('qgis:minimumboundinggeometry', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(17)
        if feedback.isCanceled():
            return {}

        # Difference
        alg_params = {
            'A': outputs['MinimaleBegrenzendeGeometrie']['OUTPUT'],
            'B': parameters['breaklines'],
            'SPLIT': True,
            'RESULT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['Difference'] = processing.run('saga:difference', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(18)
        if feedback.isCanceled():
            return {}

        # Nach Position extrahieren
        alg_params = {
            'INPUT': outputs['Verschieben']['OUTPUT'],
            'INTERSECT': parameters['breaklines'],
            'PREDICATE': 2,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['NachPositionExtrahieren'] = processing.run('native:extractbylocation', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(19)
        if feedback.isCanceled():
            return {}

        # Attribute nach Position zusammenfügen
        alg_params = {
            'DISCARD_NONMATCHING': True,
            'INPUT': outputs['Verschieben']['OUTPUT'],
            'JOIN': parameters['breaklines'],
            'JOIN_FIELDS': None,
            'METHOD': 1,
            'PREDICATE': 5,
            'PREFIX': ''
        }
        outputs['AttributeNachPositionZusammenfgen'] = processing.run('qgis:joinattributesbylocation', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(20)
        if feedback.isCanceled():
            return {}

        # Zufällige Punkte in Polygonen
        alg_params = {
            'EXPRESSION': outputs['AttributeNachPositionZusammenfgen']['JOINED_COUNT'],
            'INPUT': outputs['Difference']['RESULT'],
            'MIN_DISTANCE': 0,
            'STRATEGY': 0,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['ZuflligePunkteInPolygonen'] = processing.run('qgis:randompointsinsidepolygons', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(21)
        if feedback.isCanceled():
            return {}

        # Duplikate nach Attribut löschen
        alg_params = {
            'FIELDS': parameters['id'],
            'INPUT': outputs['ZuflligePunkteInPolygonen']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['DuplikateNachAttributLschen'] = processing.run('native:removeduplicatesbyattribute', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(22)
        if feedback.isCanceled():
            return {}

        # Felder überarbeiten
        alg_params = {
            'FIELDS_MAPPING': [{'expression': '"id"', 'length': 10, 'name': 'id', 'precision': 0, 'type': 4}],
            'INPUT': outputs['DuplikateNachAttributLschen']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['FelderBerarbeiten'] = processing.run('qgis:refactorfields', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(23)
        if feedback.isCanceled():
            return {}

        # Vektorlayer zusammenführen
        alg_params = {
            'CRS': None,
            'LAYERS': [outputs['NachPositionExtrahieren']['OUTPUT'],outputs['FelderBerarbeiten']['OUTPUT']],
            'OUTPUT': parameters['OutputSecondStage']
        }
        outputs['VektorlayerZusammenfhren'] = processing.run('native:mergevectorlayers', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['OutputSecondStage'] = outputs['VektorlayerZusammenfhren']['OUTPUT']
        return results
Ejemplo n.º 9
0
    def processAlgorithm(self, params, context, feedback):
        steps = 0
        totalStpes = 3
        # fieldPopulation = params['FIELD_POPULATION']
        fieldActivities = str(params['FIELD_ACTIVITIES'])

        feedback = QgsProcessingMultiStepFeedback(totalStpes, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        if not OPTIONAL_GRID_INPUT: params['CELL_SIZE'] = P_CELL_SIZE
        grid, isStudyArea = buildStudyArea(params['CELL_SIZE'],
                                           params['BLOCKS'],
                                           params['STUDY_AREA_GRID'], context,
                                           feedback)
        gridNeto = grid

        tempOutput = self.CURRENT_PATH + '/zaux.shp'

        # print(QgsProcessing.TEMPORARY_OUTPUT)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        activitiesGrid = joinAttrByLocation(params['TERTIARYUSES_ACTIVITIES'],
                                            gridNeto['OUTPUT'], ['id_grid'],
                                            [INTERSECTA],
                                            UNDISCARD_NONMATCHING, context,
                                            feedback, tempOutput)

        # steps = steps+1
        # feedback.setCurrentStep(steps)
        # rep = calculateField(gridNeto['OUTPUT'], 'id_ter', '$id', context,
        #                               feedback, type=1)

        activitiesLayer = QgsVectorLayer(tempOutput, "activitiesGrid", "ogr")

        # activitiesLayer = convertTempOuputToObject(activitiesGrid)

        # layer = self.parameterAsVectorLayer(params, activitiesLayer, context)
        layer = activitiesLayer
        # layer = activitiesGrid
        features = layer.getFeatures()
        # fields = layer.dataProvider().fields()
        field_names = [field.name() for field in layer.fields()]
        # print(field_names)
        # print(len(features))

        df = pd.DataFrame(features, columns=field_names)

        # df["id_grid"]= df["id_grid"].astype(int)

        aggregation = {fieldActivities: {'amount_class': 'count'}}

        grouped = df.groupby(['id_grid', fieldActivities]).agg(aggregation)
        grouped.columns = grouped.columns.droplevel(level=0)

        aggregation = {
            fieldActivities: {
                'total_class': 'count'  # conteo de todos los puntos
                # 'total_class':'nunique' # conteo de los puntos no repetidos
            }
        }

        grouped2 = df.groupby(['id_grid']).agg(aggregation)
        grouped2.columns = grouped2.columns.droplevel(level=0)

        res = grouped.join(grouped2).reset_index()

        print(res['amount_class'])
        print(res)

        uniqueActivities = pd.unique(df[fieldActivities])
        totalActivities = len(uniqueActivities)
        res["total_study"] = totalActivities

        # cross = pd.crosstab(df['id'], df[fieldActivities])
        res["proporcion"] = ((res['amount_class'] / res['total_class']) *
                             np.log(res['amount_class'] / res['total_class']))
        aggregation = {'proporcion': {'shannon': 'sum'}}

        res = res.groupby(['id_grid']).agg(aggregation)
        res.columns = res.columns.droplevel(level=0)
        res['shannon'] = res['shannon'] * -1

        outputCsv = self.CURRENT_PATH + '/sett_shannon.csv'

        feedback.pushConsoleInfo(str(('Settings shannon en ' + outputCsv)))
        # res.to_csv(outputCsv, sep = ";", encoding='utf-8')
        res.to_csv(outputCsv)

        print(res)

        exitCsv = os.path.exists(outputCsv)
        if (exitCsv):
            print("El archivo CSV existe")
        else:
            print("No se encuentra CSV")

        CSV = QgsVectorLayer(outputCsv, "csv", "ogr")
        featuresCSV = CSV.getFeatures()
        # fields = layer.dataProvider().fields()
        field_names = [field.name() for field in CSV.fields()]

        print(field_names)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        formulaDummy = 'to_string(id_grid)'
        gridDummy = calculateField(gridNeto['OUTPUT'], 'griid', formulaDummy,
                                   context, feedback,
                                   QgsProcessing.TEMPORARY_OUTPUT, 2)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        gridShannon = joinByAttr2(gridDummy['OUTPUT'], 'griid', outputCsv,
                                  'id_grid', 'shannon', UNDISCARD_NONMATCHING,
                                  '', 1, context, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        formulaDummy = 'coalesce(shannon * 1, "")'
        result = calculateField(gridShannon['OUTPUT'], NAMES_INDEX['IA11'][0],
                                formulaDummy, context, feedback,
                                params['OUTPUT'])

        # gridShannon = joinByAttr(r'/Users/terra/llactalab/data/SHAPES_PARA_INDICADORES/SIS-OUTPUTS/ia11.shp', 'id_grid',
        #                           '/Users/terra/llactalab/data/SHAPES_PARA_INDICADORES/SIS-OUTPUTS/sett_shannon.csv', 'id_grid',
        #                           ['shannon'],
        #                           UNDISCARD_NONMATCHING,
        #                           '',
        #                           1,
        #                           context,
        #                           feedback, params['OUTPUT'])

        # res.iloc[1:, [4]] = res.iloc[1:, [2]] / res.iloc[1:, [3]]

        # print(totalActivities)
        # print(grouped)
        # print(grouped2)

        # print(un)
        # print(cross)

        # print(df[fieldActivities])

        return result
Ejemplo n.º 10
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # variables propres à Processing
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)
        results = {}

        # entrées
        profils = self.parameterAsVectorLayer(parameters, 'profils', context)
        mnt = self.parameterAsRasterLayer(parameters, 'mnt', context)

        # sorties
        output = self.parameterAsOutputLayer(parameters, 'OUTPUT', context)

        # paramètres
        echantillons_nb = parameters[
            'echantillons_nb']  # nombre d'échantillons
        profils_pt = []  # géométries des points
        profils_sp = []  # valeur des points
        # les deux listes sont à deux dimension : chaque ligne correspond à un profil

        # traitement

        # discrétisation des points sur chaque profil
        for profil_f in profils.getFeatures():
            profil_g = profil_f.geometry()
            freq = profil_g.length() / (echantillons_nb - 1)
            echantillons_g = [
                QgsGeometry().fromPointXY(profil_g.asMultiPolyline()[0][0])
            ]
            for i in range(1, echantillons_nb - 1):
                echantillons_g.append(profil_g.interpolate(freq * i))
            echantillons_g.append(QgsGeometry().fromPointXY(
                profil_g.asMultiPolyline()[0][-1]))
            # note pour ci-dessus : l'interpolation des premiers et derniers points sur une ligne peut parfois planter, on les place à la main pour lever le risque
            profils_pt.append(echantillons_g)
            elevations = []
            for echantillon_g in echantillons_g:
                elevation = mnt.dataProvider().sample(echantillon_g.asPoint(),
                                                      1)[0]
                elevations.append(elevation)
            profils_sp.append(elevations)

        # interpolation linéaire : calcul des valeurs des points entre le premier et le dernier profil de point à point
        steps = []
        nb_profils = len(profils_sp)
        for i in range(0, echantillons_nb):
            # on récupère la valeur du point sur le premier et le dernier profil
            v1 = profils_sp[0][i]
            v2 = profils_sp[-1][i]
            # on détermine le pas de l'interpolation
            steps.append((v2 - v1) / nb_profils)
        for i in range(1, nb_profils - 1):
            for j in range(0, echantillons_nb):
                profils_sp[i][j] = profils_sp[i - 1][j] + steps[j]

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # écriture des données en sortie
        fields = QgsFields()
        fields.append(QgsField("elevation", QVariant.Double))
        writer = QgsVectorFileWriter(output, "System", fields,
                                     QgsWkbTypes.Point,
                                     QgsCoordinateReferenceSystem(2154),
                                     "ESRI Shapefile")
        for i in range(0, nb_profils):
            for j in range(0, echantillons_nb):
                f = QgsFeature()
                f.setGeometry(profils_pt[i][j])
                f.setAttributes([profils_sp[i][j]])
                writer.addFeature(f)

        feedback.setCurrentStep(2)

        results['OUTPUT'] = output
        return results
    def processAlgorithm(self, parameters, context, model_feedback):
        """
        Process the algorithm
        :param parameters: parameters of the process
        :param context: context of the process
        :param model_feedback: feedback instance for the process
        :return:
        """
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        self.xml_path = parameters["XMLPATH"]
        self.gpkg_path = parameters["GPKGPATH"]
        if not self.xml_path.lower().endswith(".xml"):
            feedback = QgsProcessingMultiStepFeedback(0, model_feedback)
            feedback.reportError(
                "XML Workspace Definition is not an XML file!", True)
            return {}
        if not self.gpkg_path.lower().endswith(".gpkg"):
            feedback = QgsProcessingMultiStepFeedback(0, model_feedback)
            feedback.reportError("GeoPackage is not an GPKG file!", True)
            return {}
        self.pg_conn_name = parameters["DBNAME"]
        self.pg_schema = parameters["SCHEMA"]
        self.pg_drop_before = parameters["DROPIFEXISTS"]
        dataset_list = self.getDatasets()
        feedback = QgsProcessingMultiStepFeedback(2 + len(dataset_list),
                                                  model_feedback)
        step = 0
        self.create_pk_metadata_table(context, feedback)
        step = 1
        for dataset in dataset_list:
            step += 1
            definition = self.getDatasetDef(dataset)
            if definition is not None:
                try:
                    in_layer = self.get_gpkg_vector_layer(definition[0])
                    if in_layer is not None:
                        feedback.pushInfo("Feature Class: " + definition[0])
                        try:
                            alg_params = {
                                'DATABASE': self.pg_conn_name,
                                'SQL': definition[1]
                            }
                            feedback.pushInfo(
                                "   processing (A) => qgis:postgisexecutesql")
                            processing.run('qgis:postgisexecutesql',
                                           alg_params,
                                           context=context,
                                           feedback=feedback,
                                           is_child_algorithm=True)
                        except Exception as e1:
                            feedback.reportError(
                                "Error creating table definition: \n" +
                                definition[1] + ": " + str(e1), False)
                            break

                        try:
                            # Esporta in PostgreSQL (connessioni disponibili)
                            alg_params = {
                                'ADDFIELDS': False,
                                'APPEND': False,
                                'A_SRS': None,
                                'CLIP': False,
                                'DATABASE': self.pg_conn_name,
                                'DIM': 0,
                                'GEOCOLUMN': 'geom',
                                'GT': '',
                                'GTYPE': definition[4],
                                'INDEX': False,
                                'INPUT':
                                self.get_gpkg_vector_layer(definition[0]),
                                'LAUNDER': False,
                                'OPTIONS': '',
                                'OVERWRITE': True,
                                'PK': '',
                                'PRECISION': True,
                                'PRIMARY_KEY': '',
                                'PROMOTETOMULTI': True,
                                'SCHEMA': self.pg_schema,
                                'SEGMENTIZE': '',
                                'SHAPE_ENCODING': '',
                                'SIMPLIFY': '',
                                'SKIPFAILURES': False,
                                'SPAT': None,
                                'S_SRS': None,
                                'TABLE': definition[0].lower() + '_tmp',
                                'T_SRS': None,
                                'WHERE': ''
                            }
                            feedback.pushInfo(
                                "   processing (B) => qgis:importvectorintopostgisdatabaseavailableconnections"
                            )
                            processing.run(
                                'gdal:importvectorintopostgisdatabaseavailableconnections',
                                alg_params,
                                context=context,
                                feedback=feedback,
                                is_child_algorithm=True)
                        except Exception as e2:
                            feedback.reportError(
                                "Error importing data: \n" + definition[0] +
                                ": " + str(e2), False)
                            break

                        try:
                            #Copy from TMP to FINAL table
                            sql_copy = "INSERT INTO %s.%s(%s) SELECT %s FROM %s.%s_tmp" % (
                                self.pg_schema, definition[0], definition[2],
                                definition[3], self.pg_schema,
                                definition[0]) + ";"
                            sql_drop = "DROP TABLE %s.%s_tmp" % (
                                self.pg_schema, definition[0]) + ";"
                            alg_params = {
                                'DATABASE': self.pg_conn_name,
                                'SQL': sql_copy + sql_drop
                            }
                            feedback.pushInfo(
                                "   processing (C) => qgis:postgisexecutesql")
                            processing.run('qgis:postgisexecutesql',
                                           alg_params,
                                           context=context,
                                           feedback=feedback,
                                           is_child_algorithm=True)
                        except Exception as e3:
                            feedback.reportError(
                                "Error moving data: \n" + sql_copy + sql_drop +
                                ": " + str(e3), False)
                            break
                except Exception as e:
                    feedback.reportError(
                        "Error importing domain " + definition[1] + ": " +
                        str(e), False)
            feedback.setCurrentStep(step)
        results = {}
        outputs = {}
        return results
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        #get the network handler
        layerHandler = LayerHandler()
        networkHandler = NetworkHandler()
        algRunner = AlgRunner()
        self.nodeTypeNameDict = networkHandler.nodeTypeDict
        # get network layer
        networkLayer = self.parameterAsLayer(parameters, self.NETWORK_LAYER, context)
        if networkLayer is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.NETWORK_LAYER))
        attributeBlackList = self.parameterAsFields(parameters, self.ATTRIBUTE_BLACK_LIST, context)
        ignoreVirtual = self.parameterAsBool(parameters, self.IGNORE_VIRTUAL_FIELDS, context)
        ignorePK = self.parameterAsBool(parameters, self.IGNORE_PK_FIELDS, context)
        # get network node layer
        (nodeSink, dest_id) = self.parameterAsSink(parameters, self.NETWORK_NODES,
                context, self.getFields(), QgsWkbTypes.MultiPoint, networkLayer.sourceCrs())
        #prepairs flag sink for raising errors
        self.prepareFlagSink(parameters, networkLayer, QgsWkbTypes.MultiPoint, context)
        
        waterBodyClasses = self.parameterAsLayer(parameters, self.WATER_BODY_LAYERS, context)
        waterBodyClasses = waterBodyClasses if waterBodyClasses is not None else []
        # get water sink layer
        waterSinkLayer = self.parameterAsLayer(parameters, self.SINK_LAYER, context)
        # get spillway layer
        spillwayLayer = self.parameterAsLayer(parameters, self.SPILLWAY_LAYER, context)
        # get frame layer
        frameLayer = self.parameterAsLayer(parameters, self.REF_LAYER, context)
        currStep = 0
        if frameLayer is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.REF_LAYER))
        multiStepFeedback = QgsProcessingMultiStepFeedback(3, feedback)
        multiStepFeedback.setCurrentStep(currStep)
        multiStepFeedback.pushInfo(self.tr('Preparing bounds...'))
        frame = layerHandler.getFrameOutterBounds(frameLayer, algRunner, context, feedback=multiStepFeedback)
        currStep += 1
        # get search radius
        searchRadius = self.parameterAsDouble(parameters, self.SEARCH_RADIUS, context)
        # get ditch layer
        ditchLayer = self.parameterAsLayer(parameters, self.DITCH_LAYER, context)

        #new step
        multiStepFeedback.setCurrentStep(currStep)
        multiStepFeedback.pushInfo(self.tr('Performing node identification...'))
        self.nodeDict = networkHandler.identifyAllNodes(networkLayer=networkLayer, feedback=multiStepFeedback) #zoado, mudar lógica
        multiStepFeedback.pushInfo(self.tr('{node_count} node(s) identificated...').format(node_count=len(self.nodeDict)))
        currStep += 1
        #new step
        multiStepFeedback.setCurrentStep(currStep)
        multiStepFeedback.pushInfo(self.tr('Performing node classification...'))
        networkHandler.nodeDict = self.nodeDict
        self.nodeTypeDict, nodeFlagDict = networkHandler.classifyAllNodes(
                networkLayer=networkLayer,
                frameLyrContourList=frame,
                waterBodiesLayers=waterBodyClasses,
                searchRadius=searchRadius,
                waterSinkLayer=waterSinkLayer,
                spillwayLayer=spillwayLayer,
                feedback=multiStepFeedback,
                attributeBlackList=attributeBlackList,
                excludePrimaryKeys=ignorePK,
                ignoreVirtualFields=ignoreVirtual,
                ditchLayer=ditchLayer
            )
        currStep += 1
        #new step
        multiStepFeedback.setCurrentStep(currStep)
        multiStepFeedback.pushInfo(self.tr('Writing nodes...'))
        self.fillNodeSink(
            nodeSink=nodeSink,
            networkLineLayerName=networkLayer.name(),
            nodeFlagDict=nodeFlagDict,
            feedback=multiStepFeedback)
        return {self.NETWORK_NODES : dest_id, self.FLAGS : self.flag_id}
Ejemplo n.º 13
0
    def processAlgorithm(self, params, context, feedback):
        steps = 0
        totalStpes = 6
        fieldPopulation = params['FIELD_POPULATION']
        fieldHousing = params['FIELD_HOUSING']
        DISCARD = True
        UNDISCARD = False

        feedback = QgsProcessingMultiStepFeedback(totalStpes, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        blocksWithId = calculateField(params['BLOCKS'],
                                      'id_block',
                                      '$id',
                                      context,
                                      feedback,
                                      type=1)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        pointsJoined = joinAttrByNear(params['POINTS'], blocksWithId['OUTPUT'],
                                      [], UNDISCARD, 'blk_', 5, 1, context,
                                      feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        statistics = statisticsByCategories(pointsJoined['OUTPUT'],
                                            ['blk_id_block'], None, context,
                                            feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        pointsJoinedStast = joinByAttr(pointsJoined['OUTPUT'], 'blk_id_block',
                                       statistics['OUTPUT'], 'blk_id_block',
                                       'count', DISCARD, 'st_', context,
                                       feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        formulaPopulationPerPoint = 'blk_' + fieldPopulation + ' / st_count'
        populationPerPoint = calculateField(pointsJoinedStast['OUTPUT'],
                                            'population',
                                            formulaPopulationPerPoint, context,
                                            feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        formulaHousingPerPoint = 'blk_' + fieldHousing + ' / st_count'
        housingPerPoint = calculateField(populationPerPoint['OUTPUT'],
                                         'housing', formulaHousingPerPoint,
                                         context, feedback)

        gridPopulation = joinByLocation(params['STUDY_AREA_GRID'],
                                        housingPerPoint['OUTPUT'],
                                        'population;housing', [CONTIENE],
                                        [SUM], UNDISCARD_NONMATCHING, context,
                                        feedback, params['OUTPUT'])

        return gridPopulation
Ejemplo n.º 14
0
    def processAlgorithm(self, params, context, feedback):
        steps = 0
        totalStpes = 13
        fieldPopulation = params['FIELD_POPULATION']

        feedback = QgsProcessingMultiStepFeedback(totalStpes, feedback)

        blocks = calculateArea(params['BLOCKS'], 'area_bloc', context,
                               feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        if not OPTIONAL_GRID_INPUT: params['CELL_SIZE'] = P_CELL_SIZE
        grid, isStudyArea = buildStudyArea(params['CELL_SIZE'],
                                           params['BLOCKS'],
                                           params['STUDY_AREA_GRID'], context,
                                           feedback)
        gridNeto = grid

        steps = steps + 1
        feedback.setCurrentStep(steps)
        segments = intersection(blocks['OUTPUT'], gridNeto['OUTPUT'],
                                'area_bloc;' + fieldPopulation,
                                'id_grid;area_grid', context, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        segmentsArea = calculateArea(segments['OUTPUT'], 'area_seg', context,
                                     feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        formulaPopulationSegments = '(area_seg/area_bloc) * ' + fieldPopulation
        populationForSegments = calculateField(segmentsArea['OUTPUT'],
                                               'pop_seg',
                                               formulaPopulationSegments,
                                               context, feedback)

        # Haciendo el buffer inverso aseguramos que los segmentos
        # quden dentro de la malla
        steps = steps + 1
        feedback.setCurrentStep(steps)
        segmentsFixed = makeSureInside(populationForSegments['OUTPUT'],
                                       context, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        gridNetoAndSegments = joinByLocation(gridNeto['OUTPUT'],
                                             segmentsFixed['OUTPUT'],
                                             'pop_seg', [CONTIENE], [SUM],
                                             UNDISCARD_NONMATCHING, context,
                                             feedback)
        # CALCULAR AREA VERDE
        steps = steps + 1
        feedback.setCurrentStep(steps)
        greenPerBlocks = intersection(params['GREEN'], gridNeto['OUTPUT'], [],
                                      [], context, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        greenArea = calculateArea(greenPerBlocks['OUTPUT'], 'area_green',
                                  context, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        greenAreaFixed = makeSureInside(greenArea['OUTPUT'], context, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        greenAreaAndPopulation = joinByLocation(gridNetoAndSegments['OUTPUT'],
                                                greenAreaFixed['OUTPUT'],
                                                'area_green', [CONTIENE],
                                                [SUM], UNDISCARD_NONMATCHING,
                                                context, feedback)

        steps = steps + 1
        feedback.setCurrentStep(steps)
        # formulaSurfacePerHab = 'coalesce(area_green_sum/' + fieldPopulation + '_sum,  0)'

        formulaSurfacePerHab = 'CASE WHEN pop_seg_sum = 0 THEN "" ' + \
                              'ELSE coalesce(area_green_sum/pop_seg_sum, 0) END'

        print(formulaSurfacePerHab)

        surfacePerHab = calculateField(greenAreaAndPopulation['OUTPUT'],
                                       NAMES_INDEX['IB05'][0],
                                       formulaSurfacePerHab, context, feedback,
                                       params['OUTPUT'])

        return surfacePerHab
 def processAlgorithm(self, parameters, context, feedback):
     # Parameters
     input_source, input_layer = qgsTreatments.parameterAsSourceLayer(self,
         parameters,self.INPUT,context,feedback=feedback)
     modes = self.parameterAsEnums(parameters,self.MODE,context)
     input_raster = self.parameterAsRasterLayer(parameters,self.INPUT_RASTER,context)
     band = self.parameterAsInt(parameters,self.BAND,context)
     pop_field = self.parameterAsString(parameters,self.POPULATION_FIELD,context)
     # surf_field = self.parameterAsString(parameters,self.SURFACE_FIELD,context)
     # output = self.parameterAsOutputLayer(parameters,self.OUTPUT,context)
     # Init
     input_crs = input_source.sourceCrs().authid()
     raster_crs = input_raster.dataProvider().crs().authid()
     pop_mode, surf_mode = 0 in modes, 1 in modes
     nb_feats = input_layer.featureCount()
     multi_feedback = QgsProcessingMultiStepFeedback(nb_feats * 2,feedback)
     # CRS
     if (input_crs != raster_crs):
         raster_reprojected = QgsProcessingUtils.generateTempFilename('raster_reproj.tif')
         qgsTreatments.applyWarpReproject(input_raster,raster_reprojected,
             dst_crs=input_crs,context=context,feedback=multi_feedback)
         input_raster = qgsUtils.loadRasterLayer(raster_reprojected)
         multi_feedback.setCurrentStep(1)
     pixel_size = input_raster.rasterUnitsPerPixelX() * input_raster.rasterUnitsPerPixelY()
     # Zonal stats
     prefix = 'rad_'
     zonal_stats = QgsProcessingUtils.generateTempFilename('zonal_stats.gpkg')
     qgsTreatments.rasterZonalStats(input_layer,input_raster,zonal_stats,
         prefix=prefix,band=band,context=context,feedback=multi_feedback)
     multi_feedback.setCurrentStep(nb_feats)
     # Fields
     stats_layer = qgsUtils.loadVectorLayer(zonal_stats)
     stats_fields = stats_layer.fields()
     stats_fieldnames = stats_fields.names()
     if pop_mode and pop_field not in stats_fieldnames:
         raise QgsProcessingException("No population field '" + str(pop_field) + "' in input layer")
     # if surf_field_mode and surf_field not in stats_fieldnames:
         # raise QgsProcessingException("No area field '" + str(surf_field) + "' in input layer")
     rad_pop_field = QgsField(self.RAD_POP_FIELDNAME, QVariant.Double)
     rad_surf_field = QgsField(self.RAD_SURF_FIELDNAME, QVariant.Double)
     out_fields = QgsFields(stats_fields)
     out_fields.append(rad_pop_field)
     out_fields.append(rad_surf_field)
     (sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
         context, out_fields, input_source.wkbType(), input_source.sourceCrs())
     # Division
     stats_layer = qgsUtils.loadVectorLayer(zonal_stats)
     for current, feat in enumerate(stats_layer.getFeatures()):
         new_feat = QgsFeature(out_fields)
         new_feat.setGeometry(feat.geometry())
         for field in stats_layer.fields().names():
             if field != 'fid':
                 new_feat[field] = feat[field]
         rad_sum = float(feat[prefix + 'sum'])
         rad_mean = float(feat[prefix + 'mean'])
         if (pop_mode and feat[pop_field]):
             new_feat[self.RAD_POP_FIELDNAME] = (rad_sum / feat[pop_field]) * 1000
         if surf_mode:
             new_feat[self.RAD_SURF_FIELDNAME] = (rad_mean / pixel_size) * 1000000
         sink.addFeature(new_feat, QgsFeatureSink.FastInsert)
         self.pop_mode, self.surf_mode = pop_mode, surf_mode
         multi_feedback.setCurrentStep(current + nb_feats)
         
     return { self.OUTPUT : self.dest_id }
Ejemplo n.º 16
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(5, model_feedback)
        results = {}
        outputs = {}

        # Split lines by maximum length
        alg_params = {
            'INPUT': parameters['Shapedecaminhos'],
            'LENGTH': parameters['Comprimentodossegmentos'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['SplitLinesByMaximumLength'] = processing.run('native:splitlinesbylength', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # Drape (set Z value from raster)
        alg_params = {
            'BAND': 1,
            'INPUT': outputs['SplitLinesByMaximumLength']['OUTPUT'],
            'NODATA': -9999,
            'RASTER': parameters['MDT'],
            'SCALE': 1,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['DrapeSetZValueFromRaster'] = processing.run('native:setzfromraster', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(2)
        if feedback.isCanceled():
            return {}

        # Extract Z values
        alg_params = {
            'COLUMN_PREFIX': 'z_',
            'INPUT': outputs['DrapeSetZValueFromRaster']['OUTPUT'],
            'SUMMARIES': [0,1],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['ExtractZValues'] = processing.run('native:extractzvalues', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(3)
        if feedback.isCanceled():
            return {}

        # Field calculator1
        alg_params = {
            'FIELD_LENGTH': 10,
            'FIELD_NAME': 'Length',
            'FIELD_PRECISION': 2,
            'FIELD_TYPE': 0,
            'FORMULA': ' $length ',
            'INPUT': outputs['ExtractZValues']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['FieldCalculator1'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(4)
        if feedback.isCanceled():
            return {}

        # Field calculator2
        alg_params = {
            'FIELD_LENGTH': 10,
            'FIELD_NAME': 'Slope_%',
            'FIELD_PRECISION': 3,
            'FIELD_TYPE': 0,
            'FORMULA': '(abs(\"z_first\" - \"z_last\") / \"length\" ) *100',
            'INPUT': outputs['FieldCalculator1']['OUTPUT'],
            'OUTPUT': parameters['CalculatedRoadSlopes']
        }
        outputs['FieldCalculator2'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['CalculatedRoadSlopes'] = outputs['FieldCalculator2']['OUTPUT']
        return results
Ejemplo n.º 17
0
    def processAlgorithm(self, params, context, feedback):
        steps = 0
        totalStpes = 12
        fieldPopulation = params['FIELD_POPULATION']
        # fieldHab = params['NUMBER_HABITANTS']

        feedback = QgsProcessingMultiStepFeedback(totalStpes, feedback)

        blocks = calculateArea(params['BLOCKS'], 'area_bloc', context,
                               feedback)

        steps = steps+1
        feedback.setCurrentStep(steps)
        if not OPTIONAL_GRID_INPUT: params['CELL_SIZE'] = P_CELL_SIZE
        grid, isStudyArea = buildStudyArea(params['CELL_SIZE'], params['BLOCKS'],
                                         params['STUDY_AREA_GRID'],
                                         context, feedback)
        gridNeto = grid  

        steps = steps+1
        feedback.setCurrentStep(steps)
        segments = intersection(blocks['OUTPUT'], gridNeto['OUTPUT'],
                                'area_bloc;' + fieldPopulation,
                                'id_grid;area_grid',
                                context, feedback)

        steps = steps+1
        feedback.setCurrentStep(steps)
        segmentsArea = calculateArea(segments['OUTPUT'],
                                   'area_seg',
                                   context, feedback)

        steps = steps+1
        feedback.setCurrentStep(steps)
        formulaPopulationSegments = '(area_seg/area_bloc) * ' + fieldPopulation
        housingForSegments = calculateField(segmentsArea['OUTPUT'], 'hou_seg',
                                          formulaPopulationSegments,
                                          context,
                                          feedback)




        # Haciendo el buffer inverso aseguramos que los segmentos
        # quden dentro de la malla
        steps = steps+1
        feedback.setCurrentStep(steps)
        segments = makeSureInside(housingForSegments['OUTPUT'],
                                context,
                                feedback)

        steps = steps+1
        feedback.setCurrentStep(steps)
        gridNetoAndSegments = joinByLocation(gridNeto['OUTPUT'],
                                             segments['OUTPUT'],
                                              'hou_seg',                                   
                                              [CONTIENE], [SUM],
                                              UNDISCARD_NONMATCHING,
                                              context,
                                              feedback)   


        # Calcular cuantos robos hay en cada grid

        steps = steps+1
        feedback.setCurrentStep(steps)
        thef = calculateField(params['THEFTS'], 'idx', '$id', context,
                                         feedback, type=1)


        steps = steps+1
        feedback.setCurrentStep(steps)        
        gridNetoAndSegments = joinByLocation(gridNetoAndSegments['OUTPUT'],
                                              thef['OUTPUT'],
                                              ['idx'],                                   
                                              [CONTIENE], [COUNT],
                                              UNDISCARD_NONMATCHING,
                                              context,
                                              feedback)           

        # steps = steps+1
        # feedback.setCurrentStep(steps)
        # formulaThefPerHab = 'idx_count/' + str(fieldHab)
        # thefPerHab = calculateField(gridNetoAndSegments['OUTPUT'],
        #                            NAMES_INDEX['ID09'][0],
        #                            formulaThefPerHab,
        #                            context,
        #                            feedback, params['OUTPUT'])


        steps = steps+1
        feedback.setCurrentStep(steps)
        formulaThefPerHab = 'coalesce((coalesce(idx_count, 0)/sum(idx_count)) * 100, "")'
        thefPerHab = calculateField(gridNetoAndSegments['OUTPUT'],
                                   NAMES_INDEX['ID09'][0],
                                   formulaThefPerHab,
                                   context,
                                   feedback, params['OUTPUT'])        


        return thefPerHab
Ejemplo n.º 18
0
class QualityAssuranceWorkflow(QObject):
    """
    Works as a multi-model runner. Understands all models' parameters as an
    output vector layer.
    """
    workflowFinished = pyqtSignal()
    haltedOnFlags = pyqtSignal(DsgToolsProcessingModel)
    modelStarted = pyqtSignal(DsgToolsProcessingModel)
    modelFinished = pyqtSignal(DsgToolsProcessingModel)
    modelFinishedWithFlags = pyqtSignal(DsgToolsProcessingModel)
    modelFailed = pyqtSignal(DsgToolsProcessingModel)

    def __init__(self, parameters, feedback=None):
        """
        Class constructor. Materializes an workflow set of parameters.
        :param parameters: (dict) map of workflow attributes.
        :param feedback: (QgsProcessingFeedback) task progress tracking QGIS
                         object.
        """
        super(QualityAssuranceWorkflow, self).__init__()
        msg = self.validateParameters(parameters)
        if msg:
            raise Exception(
                self.tr("Invalid workflow parameter:\n{msg}").format(msg=msg))
        self._param = parameters
        self._modelOrderMap = dict()
        self.output = dict()
        self.feedback = feedback or QgsProcessingFeedback()

    def validateParameters(self, parameters):
        """
        Validates a set of parameters for a valid Workflow.
        :param parameters: (dict) map of workflow attributes to be validated.
        :return: (str) invalidation reason.
        """
        if "displayName" not in parameters or not parameters["displayName"]:
            # this is not a mandatory item, but it defaults to a value
            parameters["displayName"] = self.tr("DSGTools Validation Workflow")
        if "models" not in parameters or not parameters["models"]:
            return self.tr(
                "Workflow seems to have no models associated with it.")
        for modelName, modelParam in parameters["models"].items():
            model = DsgToolsProcessingModel(modelParam, modelName)
            if not model.isValid():
                return self.tr("Model {model} is invalid: '{reason}'.").format(
                    model=modelName,
                    reason=model.validateParameters(modelParam))
        # if "flagLayer" not in parameters or not parameters["flagLayer"]:
        #     self.tr("No flag layer was provided.")
        # if "historyLayer" not in parameters or not parameters["historyLayer"]:
        #     self.tr("No history layer was provided.")
        return ""

    def metadata(self):
        """
        A map to Workflow's metadata.
        :return: (dict) metadata.
        """
        return self._param["metadata"] if "metadata" in self._param else dict()

    def author(self):
        """
        Retrieves Workflow's author, if available.
        :return: (str) Workflow's author.
        """
        meta = self.metadata()
        return meta["author"] if "author" in meta else ""

    def version(self):
        """
        Retrieves Workflow's version, if available.
        :return: (str) Workflow's version.
        """
        meta = self.metadata()
        return meta["version"] if "version" in meta else ""

    def lastModified(self):
        """
        Retrieves Workflow's last modification "timestamp", if available.
        :return: (str) Workflow's last modification time and date.
        """
        meta = self.metadata()
        return meta["lastModified"] if "lastModified" in meta else ""

    def metadataText(self):
        """
        Retrieves Workflow's metadata string.
        :return: (str) Workflow's metadata string.
        """
        if not self.metadata():
            return ""
        return self.tr(
            "Workflow {name} v{version} ({lastModified}) by {author}.").format(
                name=self.displayName(), **self.metadata())

    def displayName(self):
        """
        Friendly name for the workflow.
        :return: (str) display name.
        """
        return self._param["displayName"] if \
                "displayName" in self._param else ""

    def name(self):
        """
        Proxy method for displayName.
        :return: (str) display name.
        """
        return self.displayName()

    def models(self):
        """
        Model parameters defined to run in this workflow.
        :return: (dict) models maps to valid and invalid models.
        """
        models = {"valid": dict(), "invalid": dict()}
        self._multiStepFeedback = QgsProcessingMultiStepFeedback(
            len(self._param["models"]), self.feedback)
        self._multiStepFeedback.setCurrentStep(0)
        for modelName, modelParam in self._param["models"].items():
            model = DsgToolsProcessingModel(modelParam,
                                            modelName,
                                            feedback=self._multiStepFeedback)
            if not model.isValid():
                models["invalid"][modelName] = model.validateParameters(
                    modelParam)
            else:
                models["valid"][modelName] = model
        return models

    def validModels(self):
        """
        Returns all valid models from workflow parameters.
        :return: (dict) models maps to valid and invalid models.
        """
        models = dict()
        self._multiStepFeedback = QgsProcessingMultiStepFeedback(
            len(self._param["models"]), self.feedback)
        self._multiStepFeedback.setCurrentStep(0)
        for idx, (modelName,
                  modelParam) in enumerate(self._param["models"].items()):
            model = DsgToolsProcessingModel(modelParam,
                                            modelName,
                                            feedback=self._multiStepFeedback)
            if model.isValid():
                models[modelName] = model
            self._modelOrderMap[modelName] = idx
        return models

    def invalidModels(self):
        """
        Returns all valid models from workflow parameters.
        :return: (dict) models maps invalid models to their invalidation reason.
        """
        models = dict()
        self._multiStepFeedback = QgsProcessingMultiStepFeedback(
            len(self._param["models"]), self.feedback)
        self._multiStepFeedback.setCurrentStep(0)
        for modelName, modelParam in self._param["models"].items():
            model = DsgToolsProcessingModel(modelParam,
                                            modelName,
                                            feedback=self._multiStepFeedback)
            if not model.isValid():
                models[modelName] = model.validateParameters(modelParam)
        return models

    def hasInvalidModel(self):
        """
        Checks if any of the nested models is invalid.
        :return: (bool) if there are invalid models.
        """
        models = dict()
        for modelName, modelParam in self._param["models"].items():
            model = DsgToolsProcessingModel(modelParam, modelName)
            if not model.isValid():
                return True
        return False

    # def flagLayer(self):
    #     """
    #     Layer to work as a sink to flag output for all models.
    #     :return: (QgsVectorLayer) flag layer.
    #     """
    #     return self._param["flagLayer"] if "flagLayer" in self._param else ""

    # def historyLayer(self):
    #     """
    #     A table (a layer with no geometry) to store execution history.
    #     :return: (QgsVectorLayer) flag layer.
    #     """
    #     return self._param["flagLayer"] if "flagLayer" in self._param else ""

    def export(self, filepath):
        """
        Dumps workflow's parameters as a JSON file.
        :param filepath: (str) path to JSON file.
        :return: (bool) operation success.
        """
        with open(filepath, "w", encoding="utf-8") as fp:
            fp.write(json.dumps(self._param, indent=4))
        return os.path.exists(filepath)

    def asDict(self):
        """
        Dumps model parameters as a JSON file.
        :param filepath: (str) path to JSON file.
        :return: (dict) DSGTools processing model definitions.
        """
        return dict(self._param)

    def finished(self):
        """
        Executes all post-processing actions.
        """
        # Add default post-processing actions here!
        self.workflowFinished.emit()

    def runOnMainThread(self):
        """
        If, for some reason, Workflow should not be run from secondary threads,
        this method provides a 'static' execution alternative.
        :return: (dict) a map to each model's output.
        """
        self.output = dict()
        for model in self.validModels().values():
            start = time()
            mName = model.name()
            self.output[mName] = dict()
            try:
                self.output[mName]["result"] = {
                    k.split(":", 2)[-1] : v \
                        for k, v in model.runModel(model.feedback).items()
                }
                self.output[mName]["status"] = True
            except:
                self.output[mName]["result"] = None
                self.output[mName]["status"] = False
            self.output[mName]["executionTime"] = time() - start
        self.finished()
        return self.output

    def setupModelTask(self, model):
        """
        Sets model to run on QGIS task manager.
        """
        QgsApplication.taskManager().addTask(model)

    def hold(self):
        """
        Puts current active tasks/models on hold.
        """
        if not hasattr(self, "_executionOrder"):
            return
        for m in self._executionOrder.values():
            if m.status() == m.Running:
                m.hold()

    def unhold(self):
        """
        Puts current paused tasks/models back to active status.
        """
        if not hasattr(self, "_executionOrder"):
            return
        for m in self._executionOrder.values():
            if m.status() == m.OnHold:
                m.unhold()

    def currentModel(self):
        """
        Retrieves the model currently running, if any.
        :return: (DsgToolsProcessingModel) current active model.
        """
        if not hasattr(self, "_executionOrder"):
            return None
        for m in self._executionOrder.values():
            if m.status() == m.Running:
                return m
        return None

    def raiseFlagWarning(self, model):
        """
        Advises connected objects that flags were raised even though workflow
        :param model: (DsgToolsProcessingModel) model to have its flags checked.
        """
        if model.hasFlags():
            self.modelFinishedWithFlags.emit(model)
        else:
            self.modelFinished.emit(model)

    def raiseFlagError(self, model):
        """
        It stops the workflow execution if flags are identified.
        :param model: (DsgToolsProcessingModel) model to have its flags checked.
        """
        if model.hasFlags():
            self.feedback.cancel()
            self.haltedOnFlags.emit(model)
        else:
            self.modelFinished.emit(model)
        return self.feedback.isCanceled()

    def handleFlags(self, model):
        """
        Handles Workflow behaviour for a model's flag output.
        :param model: (DsgToolsProcessingModel) model to have its output handled.
        """
        onFlagsMethod = {
            "warn": partial(self.raiseFlagWarning, model),
            "halt": partial(self.raiseFlagError, model),
            "ignore": partial(self.modelFinished.emit, model)
        }[model.onFlagsRaised()]()

    def run(self, firstModelName=None, cooldown=None):
        """
        Executes all models in secondary threads.
        :param firstModelName: (str) first model's name to be executed.
        :param cooldown: (float) time to wait till next model is started.
        """
        self._executionOrder = {
            idx: model
            for idx, model in enumerate(self.validModels().values())
        }
        modelCount = len(self._executionOrder)
        if self.hasInvalidModel() or modelCount == 0:
            return None

        def modelCompleted(model, step):
            self.output[model.name()] = model.output
            self._multiStepFeedback.setCurrentStep(step)
            self.handleFlags(model)

        if firstModelName is not None:
            for idx, model in self._executionOrder.items():
                if model.name() == firstModelName:
                    initialIdx = idx
                    break
            else:
                # name was not found
                return None
        else:
            initialIdx = 0
            self.output = dict()
        for idx, currentModel in self._executionOrder.items():
            if idx < initialIdx:
                continue
            # all models MUST pass through this postprocessing method
            currentModel.taskCompleted.connect(
                partial(modelCompleted, currentModel, idx + 1))
            currentModel.begun.connect(
                partial(self.modelStarted.emit, currentModel))
            currentModel.taskTerminated.connect(
                partial(self.modelFailed.emit, currentModel))
            if idx != modelCount - 1:
                self._executionOrder[idx + 1].addSubTask(
                    currentModel,
                    subTaskDependency=currentModel.ParentDependsOnSubTask)
            else:
                # last model indicates workflow finish
                currentModel.taskCompleted.connect(self.finished)
        # last model will trigger every dependent model till the first added to
        # the task manager
        self.setupModelTask(currentModel)

    def lastModelName(self):
        """
        Gets the last model prepared to execute but has either failed or not
        run.
        :return: (str) first model's name not to run.
        """
        if not hasattr(self, "_executionOrder"):
            return None
        modelCount = len(self._executionOrder)
        for idx, model in self._executionOrder.items():
            modelName = self._executionOrder[idx].displayName()
            if modelName not in self.output or \
                self.output[modelName]["finishStatus"] != "finished":
                return modelName
        else:
            return None
Ejemplo n.º 19
0
    def processAlgorithm(self, parameters, context, feedback):
        steps = 0
        totalStpes = 17
        outputs = {}
        results = {}
        feedback = QgsProcessingMultiStepFeedback(totalStpes, feedback)

        isValid = lambda x: False if x is None or x is '' else True

        isBlocks = isValid(parameters['BLOCKS'])
        isFieldPopulation = isValid(parameters['FIELD_POPULATION'])
        isFieldHousing = isValid(parameters['FIELD_HOUSING'])
        isStudyArea = isValid(parameters['STUDY_AREA_GRID'])

        # isIcv = isValid(parameters['ICV'])
        # isValue = isValid(parameters['VALUE'])

        isCensoVivienda = isValid(parameters['CENSO_VIVIENDA'])
        isDpaMan = isValid(parameters['DPA_MAN'])

        print("Censo Vivienda")
        print(isCensoVivienda)

        if isBlocks and isCensoVivienda and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D02 Viviendas con carencias constructivas
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_VIVIENDA': parameters['CENSO_VIVIENDA'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D02']
            }
            outputs['D02ViviendasConCarenciasConstructivas'] = processing.run(
                'SISURBANO:D02 Viviendas con carencias constructivas',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D02'] = outputs[
                'D02ViviendasConCarenciasConstructivas']['OUTPUT']

        isCensoHogar = isValid(parameters['CENSO_HOGAR'])

        if isCensoVivienda and isBlocks and isCensoHogar and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}
            # D05 Acceso a internet
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_HOGAR': parameters['CENSO_HOGAR'],
                'CENSO_VIVIENDA': parameters['CENSO_VIVIENDA'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D05']
            }
            outputs['D05AccesoAInternet'] = processing.run(
                'SISURBANO:D05 Acceso a internet',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D05'] = outputs['D05AccesoAInternet']['OUTPUT']

        isThefts = isValid(parameters['THEFTS'])

        if isBlocks and isFieldPopulation and isThefts:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D09 Número de robos anuales
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'FIELD_POPULATION': parameters['FIELD_POPULATION'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'THEFTS': parameters['THEFTS'],
                'OUTPUT': parameters['OUTPUT_D09']
            }
            outputs['D09NmeroDeRobosAnuales'] = processing.run(
                'SISURBANO:D09 Número de robos anuales',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D09'] = outputs['D09NmeroDeRobosAnuales']['OUTPUT']

        isCensoPoblacion = isValid(parameters['CENSO_POBLACION'])

        if isBlocks and isCensoPoblacion and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D13 Población activa con estudios universitarios
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_POBLACION': parameters['CENSO_POBLACION'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D13']
            }
            outputs[
                'D13PoblacinActivaConEstudiosUniversitarios'] = processing.run(
                    'SISURBANO:D13 Población activa con estudios universitarios',
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True)
            results['OUTPUT_D13'] = outputs[
                'D13PoblacinActivaConEstudiosUniversitarios']['OUTPUT']

        if isBlocks and isCensoVivienda and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D01 Viviendas con cobertura total de servicios básicos
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_VIVIENDA': parameters['CENSO_VIVIENDA'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D01']
            }
            outputs[
                'D01ViviendasConCoberturaTotalDeServiciosBsicos'] = processing.run(
                    'SISURBANO:D01 Viviendas con cobertura total de servicios básicos',
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True)
            results['OUTPUT_D01'] = outputs[
                'D01ViviendasConCoberturaTotalDeServiciosBsicos']['OUTPUT']

        isDistanceOptions = isValid(parameters['DISTANCE_OPTIONS'])
        isMarket = isValid(parameters['EQUIPMENT_MARKET'])
        isRoads = isValid(parameters['ROADS'])

        if isBlocks and isDistanceOptions and isMarket and isRoads:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D08 Cercanía y asequibilidad a alimentos
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'DISTANCE_OPTIONS': parameters['DISTANCE_OPTIONS'],
                'EQUIPMENT_MARKET': parameters['EQUIPMENT_MARKET'],
                'FIELD_HOUSING': parameters['FIELD_HOUSING'],
                'ROADS': parameters['ROADS'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D08']
            }
            outputs['D08CercanaYAsequibilidadAAlimentos'] = processing.run(
                'SISURBANO:D08 Cercanía y asequibilidad a alimentos',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D08'] = outputs[
                'D08CercanaYAsequibilidadAAlimentos']['OUTPUT']

        isZonasCensales = isValid(parameters['ZONAS_CENSALES'])
        isEncuestaTiempo = isValid(parameters['ENCUESTA_TIEMPO'])
        isDpaSector = isValid(parameters['DPA_SECTOR'])

        if isZonasCensales and isDpaSector and isEncuestaTiempo:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D06 Uso del tiempo
            alg_params = {
                'BLOCKS': parameters['ZONAS_CENSALES'],
                'DPA_SECTOR': parameters['DPA_SECTOR'],
                'ENCUESTA': parameters['ENCUESTA_TIEMPO'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D06']
            }
            outputs['D06UsoDelTiempo'] = processing.run(
                'SISURBANO:D06 Uso del tiempo',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D06'] = outputs['D06UsoDelTiempo']['OUTPUT']

        isEncuestaSeguridad = isValid(parameters['ENCUESTA_SEGURIDAD'])

        if isZonasCensales and isDpaSector and isEncuestaSeguridad:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D15 Percepción de inseguridad
            alg_params = {
                'BLOCKS': parameters['ZONAS_CENSALES'],
                'DPA_SECTOR': parameters['DPA_SECTOR'],
                'ENCUESTA': parameters['ENCUESTA_SEGURIDAD'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D15']
            }
            outputs['D15PercepcinDeInseguridad'] = processing.run(
                'SISURBANO:D15 Percepción de inseguridad',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D15'] = outputs['D15PercepcinDeInseguridad'][
                'OUTPUT']

        if isBlocks and isCensoPoblacion and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D16 Índice de envejecimiento
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_POBLACION': parameters['CENSO_POBLACION'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D16']
            }
            outputs['D16NdiceDeEnvejecimiento'] = processing.run(
                'SISURBANO:D16 Índice de envejecimiento',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D16'] = outputs['D16NdiceDeEnvejecimiento'][
                'OUTPUT']

        isEncuestaDesempleo = isValid(parameters['ENCUESTA_DESEMPLEO'])

        if isZonasCensales and isDpaSector and isEncuestaDesempleo:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D11 Tasa de desempleo
            alg_params = {
                'BLOCKS': parameters['ZONAS_CENSALES'],
                'DPA_SECTOR': parameters['DPA_SECTOR'],
                'ENCUESTA': parameters['ENCUESTA_DESEMPLEO'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D11']
            }
            outputs['D11TasaDeDesempleo'] = processing.run(
                'SISURBANO:D11 Tasa de desempleo',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D11'] = outputs['D11TasaDeDesempleo']['OUTPUT']

        isOpenSpace = isValid(parameters['OPEN_SPACE'])
        isSpace2Improvement = isValid(parameters['SPACE2IMPROVEMENT'])

        if isOpenSpace and isSpace2Improvement:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D04 Espacios públicos abiertos que necesitan mejoras
            alg_params = {
                'OPEN_SPACE': parameters['OPEN_SPACE'],
                'SPACE2IMPROVEMENT': parameters['SPACE2IMPROVEMENT'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D04']
            }
            outputs[
                'D04EspaciosPblicosAbiertosQueNecesitanMejoras'] = processing.run(
                    'SISURBANO:D04 Espacios públicos abiertos que necesitan mejoras',
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True)
            results['OUTPUT_D04'] = outputs[
                'D04EspaciosPblicosAbiertosQueNecesitanMejoras']['OUTPUT']

        if isBlocks and isCensoPoblacion and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D12 Mujeres en la fuerza de trabajo remunerado
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_POBLACION': parameters['CENSO_POBLACION'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D12']
            }
            outputs[
                'D12MujeresEnLaFuerzaDeTrabajoRemunerado'] = processing.run(
                    'SISURBANO:D12 Mujeres en la fuerza de trabajo remunerado',
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True)
            results['OUTPUT_D12'] = outputs[
                'D12MujeresEnLaFuerzaDeTrabajoRemunerado']['OUTPUT']

        isRisk = isValid(parameters['RISK'])
        if isBlocks and isFieldHousing and isRisk:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D03 Viviendas emplazadas en zonas de riesgo
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'FIELD_HOUSING': parameters['FIELD_HOUSING'],
                'RISK': parameters['RISK'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D03']
            }
            outputs['D03ViviendasEmplazadasEnZonasDeRiesgo'] = processing.run(
                'SISURBANO:D03 Viviendas emplazadas en zonas de riesgo',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D03'] = outputs[
                'D03ViviendasEmplazadasEnZonasDeRiesgo']['OUTPUT']

        if isBlocks and isCensoHogar and isCensoVivienda and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D10 Seguridad de tenencia de la vivienda
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_HOGAR': parameters['CENSO_HOGAR'],
                'CENSO_VIVIENDA': parameters['CENSO_VIVIENDA'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D10']
            }
            outputs['D10SeguridadDeTenenciaDeLaVivienda'] = processing.run(
                'SISURBANO:D10 Seguridad de tenencia de la vivienda',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D10'] = outputs[
                'D10SeguridadDeTenenciaDeLaVivienda']['OUTPUT']

        if isBlocks and isCensoPoblacion and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D14 Estabilidad de la comunidad
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_POBLACION': parameters['CENSO_POBLACION'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D14']
            }
            outputs['D14EstabilidadDeLaComunidad'] = processing.run(
                'SISURBANO:D14 Estabilidad de la comunidad',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D14'] = outputs['D14EstabilidadDeLaComunidad'][
                'OUTPUT']

        if isBlocks and isCensoHogar and isCensoPoblacion and isCensoVivienda and isDpaMan:
            steps = steps + 1
            feedback.setCurrentStep(steps)
            if feedback.isCanceled():
                return {}

            # D07 Indice de calidad de vida
            alg_params = {
                'BLOCKS': parameters['BLOCKS'],
                'CENSO_HOGAR': parameters['CENSO_HOGAR'],
                'CENSO_POBLACION': parameters['CENSO_POBLACION'],
                'CENSO_VIVIENDA': parameters['CENSO_VIVIENDA'],
                'DPA_MAN': parameters['DPA_MAN'],
                'STUDY_AREA_GRID': parameters['STUDY_AREA_GRID'],
                'OUTPUT': parameters['OUTPUT_D07']
            }
            outputs['D07IndiceDeCalidadDeVida'] = processing.run(
                'SISURBANO:D07 Indice de calidad de vida',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D07'] = outputs['D07IndiceDeCalidadDeVida'][
                'OUTPUT']

        if results['OUTPUT_D07']:
            # D17 Segregación espacial
            alg_params = {
                'ICV': results['OUTPUT_D07'],
                'VALUE': 'PQ1',
                'OUTPUT': parameters['OUTPUT_D17']
            }
            outputs['D17SegregacinEspacial'] = processing.run(
                'SISURBANO:D17 Segregación espacial',
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True)
            results['OUTPUT_D17'] = outputs['D17SegregacinEspacial']['OUTPUT']

        return results
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(13, model_feedback)
        results = {}
        outputs = {}

        input_layer = self.parameterAsVectorLayer(parameters, "inputlayer",
                                                  context)
        overlay_layer = self.parameterAsVectorLayer(parameters, "overlaylayer",
                                                    context)

        input_epsg_code = input_layer.crs().authid()
        overlay_epsg_code = overlay_layer.crs().authid()

        crs_input = QgsCoordinateReferenceSystem(input_epsg_code)
        crs_overlay = QgsCoordinateReferenceSystem(overlay_epsg_code)

        if crs_input.isGeographic():
            feedback.reportError(
                "CRS of the Input Layer is Geographic. Results accuracy may get impacted. For most accurate results, both input and overlay layers should be in the same Projected CRS\n"
            )

        if crs_overlay.isGeographic():
            feedback.reportError(
                "CRS of the Input Layer is Geographic. Results accuracy may get impacted. For most accurate results, both input and overlay layers should be in the same Projected CRS\n"
            )

        if input_epsg_code == overlay_epsg_code:
            pass
        else:
            feedback.reportError(
                "Input and Overlay Layers are in different CRS. For most accurate results, both input and overlay layers should be in the same Projected CRS\n"
            )

        # add_ID_field to input layer
        alg_params = {
            "FIELD_NAME": "input_feat_id",
            "GROUP_FIELDS": [""],
            "INPUT": parameters["inputlayer"],
            "SORT_ASCENDING": True,
            "SORT_EXPRESSION": "",
            "SORT_NULLS_FIRST": False,
            "START": 1,
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["Add_id_field"] = processing.run(
            "native:addautoincrementalfield",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # add_area_field to input layer
        alg_params = {
            "FIELD_LENGTH": 0,
            "FIELD_NAME": "area_awa",
            "FIELD_PRECISION": 0,
            "FIELD_TYPE": 0,
            "FORMULA": "area($geometry)",
            "INPUT": outputs["Add_id_field"]["OUTPUT"],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["Add_area_field"] = processing.run(
            "qgis:fieldcalculator",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(2)
        if feedback.isCanceled():
            return {}

        # dissolve all overlay fields so as not to repeat record in reporting
        alg_params = {
            "FIELD": [parameters["fieldtoaverage"]] + [
                field for field in parameters["additionalfields"]
                if field != str(parameters["fieldtoaverage"])
            ],
            "INPUT":
            parameters["overlaylayer"],
            "OUTPUT":
            QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["Dissolve"] = processing.run(
            "native:dissolve",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(3)
        if feedback.isCanceled():
            return {}

        # intersection between input and overlay layer
        # delete no field in input layer and all fields in overlay layer
        # except field to average and additional fields
        alg_params = {
            "INPUT":
            outputs["Add_area_field"]["OUTPUT"],
            "INPUT_FIELDS": [""],
            "OVERLAY":
            outputs["Dissolve"]["OUTPUT"],
            "OVERLAY_FIELDS": [str(parameters["fieldtoaverage"])] +
            parameters["additionalfields"],
            "OVERLAY_FIELDS_PREFIX":
            "",
            "OUTPUT":
            QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["Intersection"] = processing.run(
            "native:intersection",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(4)
        if feedback.isCanceled():
            return {}

        # add_Weight
        alg_params = {
            "FIELD_LENGTH": 0,
            "FIELD_NAME": parameters["fieldtoaverage"] + "_area",
            "FIELD_PRECISION": 0,
            "FIELD_TYPE": 0,
            "FORMULA":
            ' "' + parameters["fieldtoaverage"] + '"  *  area($geometry)',
            "INPUT": outputs["Intersection"]["OUTPUT"],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["Add_Weight"] = processing.run(
            "qgis:fieldcalculator",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(5)
        if feedback.isCanceled():
            return {}

        # area_average
        weighted_field = "weighted_" + parameters["fieldtoaverage"]
        alg_params = {
            "FIELD_LENGTH": 0,
            "FIELD_NAME": weighted_field,
            "FIELD_PRECISION": 0,
            "FIELD_TYPE": 0,
            "FORMULA": ' sum("' + parameters["fieldtoaverage"] + "_area"
            '","input_feat_id")/"area_awa"',
            "INPUT": outputs["Add_Weight"]["OUTPUT"],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["area_average"] = processing.run(
            "qgis:fieldcalculator",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(6)
        if feedback.isCanceled():
            return {}

        # remerge input layer elements
        alg_params = {
            "FIELD": ["input_feat_id"],
            "INPUT": outputs["area_average"]["OUTPUT"],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["Dissolve2"] = processing.run(
            "native:dissolve",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(7)
        if feedback.isCanceled():
            return {}

        input_layer = self.parameterAsVectorLayer(parameters, "inputlayer",
                                                  context)
        result_name = input_layer.name() + "_" + parameters["fieldtoaverage"]
        parameters["result"].destinationName = result_name

        # drop field(s) for Result
        alg_params = {
            "COLUMN":
            ["input_feat_id", "area_awa"] + [parameters["fieldtoaverage"]] + [
                field for field in parameters["additionalfields"]
                if field != str(parameters["fieldtoaverage"])
            ] + [parameters["fieldtoaverage"] + "_area"],
            "INPUT":
            outputs["Dissolve2"]["OUTPUT"],
            "OUTPUT":
            parameters["result"],
        }
        outputs["Drop1"] = processing.run(
            "qgis:deletecolumn",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(8)
        if feedback.isCanceled():
            return {}

        results["result"] = outputs["Drop1"]["OUTPUT"]

        # Reporting

        # Drop field(s) for Report
        int_layer = context.takeResultLayer(outputs["area_average"]["OUTPUT"])
        all_fields = [f.name() for f in int_layer.fields()]
        fields_to_keep = (["input_feat_id", weighted_field] + [
            field for field in parameters["additionalfields"]
            if field != str(parameters["fieldtoaverage"])
        ] + [parameters["fieldtoaverage"]] +
                          [parameters["identifierfieldforreport"]])
        fields_to_drop = [f for f in all_fields if f not in fields_to_keep]
        alg_params = {
            "COLUMN": fields_to_drop,
            "INPUT": int_layer,
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["Drop2"] = processing.run(
            "qgis:deletecolumn",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(9)
        if feedback.isCanceled():
            return {}

        # update area
        alg_params = {
            "FIELD_LENGTH": 20,
            "FIELD_NAME": "area_crs_units",
            "FIELD_PRECISION": 5,
            "FIELD_TYPE": 0,
            "FORMULA": "round(area($geometry),5)",
            "INPUT": outputs["Drop2"]["OUTPUT"],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["update_area"] = processing.run(
            "qgis:fieldcalculator",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(10)
        if feedback.isCanceled():
            return {}

        parameters["reportaslayer"].destinationName = "Report as Layer"
        # add area %
        alg_params = {
            "FIELD_LENGTH": 9,
            "FIELD_NAME": "area_prcnt",
            "FIELD_PRECISION": 5,
            "FIELD_TYPE": 0,
            "FORMULA":
            ' round("area_crs_units" *100/  sum(  "area_crs_units" ,  "input_feat_id" ),5)',
            "INPUT": outputs["update_area"]["OUTPUT"],
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["area_prcnt"] = processing.run(
            "qgis:fieldcalculator",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(11)
        if feedback.isCanceled():
            return {}

        # Order by expression
        alg_params = {
            "ASCENDING": True,
            "EXPRESSION": ' "input_feat_id" + area_prcnt" ',
            "INPUT": outputs["area_prcnt"]["OUTPUT"],
            "NULLS_FIRST": False,
            "OUTPUT": parameters["reportaslayer"],
        }
        outputs["OrderByExpression"] = processing.run(
            "native:orderbyexpression",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        feedback.setCurrentStep(12)
        if feedback.isCanceled():
            return {}

        results["reportaslayer"] = outputs["OrderByExpression"]["OUTPUT"]

        output_file = self.parameterAsFileOutput(parameters, "reportasHTML",
                                                 context)

        # create HTML report
        if output_file:

            try:
                try:
                    import pandas as pd
                except ImportError:
                    feedback.pushInfo(
                        "Python library pandas was not found. Installing pandas to QGIS python ..."
                    )
                    import pathlib as pl
                    import subprocess

                    qgis_Path = pl.Path(sys.executable)
                    qgis_python_path = (qgis_Path.parent /
                                        "python3.exe").as_posix()

                    subprocess.check_call([
                        qgis_python_path, "-m", "pip", "install", "--user",
                        "pandas"
                    ])
                    import pandas as pd

                    feedback.pushInfo(
                        "Python library pandas was successfully installed for QGIS python"
                    )
            except:
                feedback.reportError(
                    "Failed to import pandas. Tried installing pandas but failed.\nPlease manually install pandas for the python that comes with your QGIS.",
                    True,
                )
                return results

            # Drop geometries
            alg_params = {
                "INPUT": outputs["area_prcnt"]["OUTPUT"],
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["DropGeometries"] = processing.run(
                "native:dropgeometries",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(13)
            if feedback.isCanceled():
                return {}

            with tempfile.TemporaryDirectory() as td:
                f_name = os.path.join(td, "report_df.csv")

                report_layer = context.takeResultLayer(
                    outputs["DropGeometries"]["OUTPUT"])

                QgsVectorFileWriter.writeAsVectorFormat(
                    report_layer,
                    f_name,
                    fileEncoding="utf-8",
                    driverName="CSV",
                )

                df = pd.read_csv(f_name)

            total_FIDs = df["input_feat_id"].max()
            ident_name = parameters["identifierfieldforreport"]
            html = ""
            df.sort_values(by="area_prcnt", ascending=False, inplace=True)
            pd.set_option("display.float_format", "{:.5f}".format)

            for i in range(1, total_FIDs + 1):
                df_sub = df.loc[df["input_feat_id"] == i]
                df_sub.reset_index(inplace=True, drop=True)
                avg_value = df_sub.at[0, weighted_field]
                if ident_name:
                    feature_name = df_sub.at[0, ident_name]
                    df_sub.drop(
                        columns=["input_feat_id", ident_name, weighted_field],
                        inplace=True,
                    )
                    html += f"<p><b>{i}. {feature_name}</b><br>{weighted_field}: {avg_value}<br>count of distinct intersecting features: {len(df_sub.index)}<br></p>\n"
                else:
                    df_sub.drop(columns=["input_feat_id", weighted_field],
                                inplace=True)
                    html += f"<p><b>Feature ID: {i}</b><br>{weighted_field}: {avg_value}<br>count of distinct intersecting features: {len(df_sub.index)}<br></p>\n"
                html += f"{df_sub.to_html(bold_rows=False, index=False, na_rep='Null',justify='left')}<br>\n"

                with codecs.open(output_file, "w", encoding="utf-8") as f:
                    f.write("<html><head>\n")
                    f.write(
                        '<meta http-equiv="Content-Type" content="text/html; \
                            charset=utf-8" /></head><body>\n')
                    f.write(html)
                    f.write("</body></html>\n")

                results["reportasHTML"] = output_file

        # log usage
        with open(os.path.join(cmd_folder, "usage_counter.log"), "r+") as f:
            counter = int(f.readline())
            f.seek(0)
            f.write(str(counter + 1))

        # check if counter is a milestone
        if (counter + 1) % 25 == 0:
            appeal_file = NamedTemporaryFile("w", suffix=".html", delete=False)
            self.createHTML(appeal_file.name, counter + 1)
            results["Message"] = appeal_file.name

        return results
    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}
Ejemplo n.º 22
0
    def convertFromMap(self,
                       conversionMap=None,
                       featureConversionMap=None,
                       feedback=None):
        """
        Converts all datasets from a conversion map.
        :param conversionMap: (dict) conversion map generated by Datasource Conversion tool.
        :param featureConversionMap: (dict) map of features based on given input.
        :param feedback: (QgsProcessingMultiStepFeedback) QGIS tool for progress tracking.
        :return: (tuple) successfull and failed translations lists.
        """
        if conversionMap is None:
            conversionMap = self.conversionMap
        if feedback is None:
            feedback = self.feedback
        allInputLayers = dict()
        allOutputLayers = dict()
        errors = dict()
        successfulLayers, failedLayers = None, None
        nSteps = len(
            self.getAllUniqueInputDb()) + len(self.getAllUniqueOutputDb()) * 4
        multiStepFeedback = QgsProcessingMultiStepFeedback(nSteps, feedback)
        # start log
        conversionSummary = self.getLogHeader()
        conversionStep = 1
        currentStep = 0
        for inputDb, conversionStepMaps in conversionMap.items():
            if multiStepFeedback.isCanceled() or self.isCanceled():
                break
            multiStepFeedback.setCurrentStep(currentStep)
            currentStep += 1
            # input setup
            self.conversionUpdated.emit(
                self.tr("\nConversion Step {0} started...\n\n").format(
                    conversionStep))
            self.conversionUpdated.emit(
                self.tr("[INPUT] Reading {0}'s layers...\n").format(inputDb))
            if inputDb not in allInputLayers:
                allInputLayers[inputDb] = self.readInputLayers(
                    datasourcePath=inputDb, feedback=multiStepFeedback)
            inputLayers = allInputLayers[inputDb]
            for currentOutput, conversionStepMap in enumerate(
                    conversionStepMaps):
                startTime = time.time()
                if multiStepFeedback.isCanceled() or self.isCanceled():
                    break
                # output setup
                outputDb = conversionStepMap["outDs"]
                if outputDb not in allOutputLayers:
                    if conversionStepMap["createDs"]:
                        self.conversionUpdated.emit(
                            self.tr("[OUTPUT] Creating dataset {0}...\n").
                            format(outputDb))
                        outputAbstractDb, error = self.checkAndCreateDataset(
                            conversionStepMap)
                        del outputAbstractDb
                        if error != "":
                            k = "{0} to {1}".format(inputDb, outputDb)
                            self.conversionUpdated.emit(
                                self.tr("Dataset creation error ({0}): '{1}'\n"
                                        ).format(outputDb, error))
                            errors[k] = error
                            conversionSummary += self.addConversionStepToLog(conversionStep, inputDb, outputDb, \
                                            inputLayers, errors, {}, {}, "{0:.2f} s".format(time.time() - startTime))
                            conversionStep += 1
                            continue
                    self.conversionUpdated.emit(
                        self.tr("[OUTPUT] Reading {0}'s layers...\n").format(
                            outputDb))
                    multiStepFeedback.setCurrentStep(currentStep)
                    currentStep += 1
                    allOutputLayers[outputDb] = self.readOutputLayers(
                        datasourcePath=outputDb, feedback=multiStepFeedback)
                outputLayers = allOutputLayers[outputDb]
                # now conversion starts
                self.conversionUpdated.emit(
                    self.tr("Preparing {0}'s layers for conversion...").format(
                        inputDb))
                multiStepFeedback.setCurrentStep(currentStep)
                currentStep += 1
                preparedLayers = self.prepareInputLayers(
                    inputLayers, conversionStepMap, feedback=multiStepFeedback)

                self.conversionUpdated.emit(self.tr("Mapping features..."))
                multiStepFeedback.setCurrentStep(currentStep)
                currentStep += 1
                mappedFeatures = self.mapFeatures(preparedLayers,
                                                  outputLayers,
                                                  feedback=multiStepFeedback)

                self.conversionUpdated.emit(
                    self.tr("Loading layers to {0}...").format(outputDb))
                multiStepFeedback.setCurrentStep(currentStep)
                currentStep += 1
                successfulLayers, failedLayers = self.loadToOuput(
                                                    mappedFeatures, outputLayers, conversionStepMap["conversionMode"],\
                                                    feedback=multiStepFeedback
                                                 )
                # log update
                conversionSummary += self.addConversionStepToLog(conversionStep, inputDb, outputDb, inputLayers, \
                                            errors, successfulLayers, failedLayers, "{0:.2f} s".format(time.time() - startTime))
                conversionStep += 1
        self.conversionFinished.emit()
        return {
            'creationErrors': errors,
            'successfulLayers': successfulLayers,
            'failedLayers': failedLayers,
            'status': not feedback.isCanceled(),
            'log': conversionSummary
        }
 def processAlgorithm(self, parameters, context, feedback):
     # Parameters
     reporting_mode = self.parameterAsEnum(parameters, self.REPORTING_MODE,
                                           context)
     lighting_source, lighting_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, self.LIGHTING, context, feedback=feedback)
     self.fieldname = self.parameterAsString(parameters, FDA.FLUX_FIELD,
                                             context)
     roads_source, roads_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, RE.ROADS, context, feedback=feedback)
     cadastre_source, cadastre_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, RE.CADASTRE, context, feedback=feedback)
     hydro_source, hydro_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, self.SURFACE_HYDRO, context, feedback=feedback)
     extent_source, extent_layer = qgsTreatments.parameterAsSourceLayer(
         self, parameters, RE.EXTENT_LAYER, context, feedback=feedback)
     clip_distance = self.parameterAsDouble(parameters, self.CLIP_DISTANCE,
                                            context)
     dissolve_step = self.parameterAsEnum(parameters, self.DISSOLVE_STEP,
                                          context)
     include_layers = self.parameterAsLayerList(parameters,
                                                RE.INCLUDE_LAYERS, context)
     diff_layers = self.parameterAsLayerList(parameters, RE.DIFF_LAYERS,
                                             context)
     output_surface = self.parameterAsOutputLayer(parameters,
                                                  self.OUTPUT_SURFACE,
                                                  context)
     self.output = self.parameterAsOutputLayer(parameters, self.OUTPUT,
                                               context)
     out_linear = reporting_mode == 1
     # Init steps
     nb_steps = 3 if out_linear else 2
     mf = QgsProcessingMultiStepFeedback(nb_steps, feedback)
     if out_linear:
         id_field = 'ID'
         if id_field not in roads_layer.fields().names():
             raise QgsProcessingException("No 'ID' field in roads layer")
     # Surface
     surface_params = parameters.copy()
     surface_params[RE.ROADS] = roads_layer
     surface_params[RE.CADASTRE] = cadastre_layer
     surface_params[RE.EXTENT_LAYER] = extent_layer
     surface_params[RE.INCLUDE_LAYERS] = include_layers
     surface_params[RE.DIFF_LAYERS] = diff_layers
     if hydro_source:
         surface_params[RE.DIFF_LAYERS] += [hydro_layer]
     surface_params[RE.DISSOLVE] = dissolve_step == 0
     surface_params[RE.OUTPUT] = output_surface
     surface = qgsTreatments.applyProcessingAlg('LPT',
                                                RE.ALG_NAME,
                                                surface_params,
                                                context=context,
                                                feedback=mf)
     mf.setCurrentStep(1)
     # Light surfacic density
     qgsTreatments.fixShapefileFID(surface, context=context, feedback=mf)
     density_params = parameters.copy()
     density_params[FDA.LIGHTING] = lighting_layer
     # density_params[FDA.REPORTING] = reporting_layer
     density_params[FDA.CLIP_DISTANCE] = clip_distance
     density_params[FDA.SURFACE] = surface
     density_params[RE.ROADS] = roads_layer
     density_params[FDA.DISSOLVE] = dissolve_step == 1
     density_params[FDA.SKIP_EMPTY] = True
     if out_linear:
         output_surf = QgsProcessingUtils.generateTempFilename(
             'output_surface.gpkg')
         density_params[FDA.REPORTING_FIELDS] = [id_field]
         density_params[FDA.OUTPUT] = output_surf
     else:
         density_params[FDA.OUTPUT] = self.output
     self.out_id = qgsTreatments.applyProcessingAlg('LPT',
                                                    DSFLSurface.ALG_NAME,
                                                    density_params,
                                                    context=context,
                                                    feedback=mf)
     mf.setCurrentStep(2)
     # Join if output linear
     if out_linear:
         copy_fields = [
             FDA.NB_LAMPS, FDA.FLUX_SUM, FDA.SURFACE_AREA, FDA.FLUX_DEN
         ]
         self.out_id = qgsTreatments.joinByAttribute(
             roads_layer,
             id_field,
             output_surf,
             id_field,
             copy_fields=copy_fields,
             out_layer=self.output,
             context=context,
             feedback=mf)
         mf.setCurrentStep(3)
     return {self.OUTPUT: self.output}
Ejemplo n.º 24
0
    def relateDrainagesWithContours(self, drainageLyr, contourLyr, frameLinesLyr, heightFieldName, threshold, topologyRadius, feedback=None):
        """
        Checks the conformity between directed drainages and contours.
        Drainages must be propperly directed.
        :param drainageLyr: QgsVectorLayer (line) with drainage lines.
        This must have a primary key field;
        :param contourLyr: QgsVectorLayer (line) with contour lines.
        This must have a primary key field;
        :param frameLinesLyrLyr: QgsVectorLayer (line) with frame lines;
        :param heightFieldName: (str) name of the field that stores
        contour's height;
        :param threshold: (int) equidistance between contour lines;
        :param threshold: (float) topology radius;
        Process steps:
        1- Build spatial indexes;
        2- Compute intersections between drainages and contours;
        3- Relate intersections grouping by drainages: calculate the
        distance between the start point and each intersection, then
        order the points by distance. If the height of each point does
        not follow this order, flag the intersection.
        4- After relating everything,
        """
        maxSteps = 4
        multiStepFeedback = QgsProcessingMultiStepFeedback(maxSteps, feedback) if feedback is not None else None
        currentStep = 0
        if multiStepFeedback is not None:
            if multiStepFeedback.isCanceled():
                return []
            multiStepFeedback.setCurrentStep(currentStep)
            currentStep += 1
            multiStepFeedback.pushInfo(
                self.tr('Building contour structures...')
                )
        contourSpatialIdx, contourIdDict, contourNodeDict, heightsDict = self.buildSpatialIndexAndIdDictRelateNodesAndAttributeGroupDict(
            inputLyr=contourLyr,
            attributeName=heightFieldName,
            feedback=multiStepFeedback
        )
        if multiStepFeedback is not None:
            if multiStepFeedback.isCanceled():
                return []
            multiStepFeedback.setCurrentStep(currentStep)
            currentStep += 1
            multiStepFeedback.pushInfo(
                self.tr('Validating contour structures. Check 1/4...')
                )
        invalidDict = self.validateContourRelations(
            contourNodeDict,
            feedback=multiStepFeedback
            )
        if invalidDict:
            multiStepFeedback.setCurrentStep(maxSteps-1)
            return invalidDict

        if multiStepFeedback is not None:
            if multiStepFeedback.isCanceled():
                return []
            multiStepFeedback.setCurrentStep(currentStep)
            currentStep += 1
            multiStepFeedback.pushInfo(
                self.tr('Building drainage spatial index...')
                )
        drainageSpatialIdx, drainageIdDict, drainageNodeDict = self.buildSpatialIndexAndIdDictAndRelateNodes(
            inputLyr=drainageLyr,
            feedback=multiStepFeedback
        )
        if multiStepFeedback is not None:
            if multiStepFeedback.isCanceled():
                return []
            multiStepFeedback.setCurrentStep(currentStep)
            currentStep += 1
            multiStepFeedback.pushInfo(
                self.tr('Relating contours with drainages...')
                )
        intersectionDict = self.buildIntersectionDict(
            drainageLyr,
            drainageIdDict,
            drainageSpatialIdx,
            contourIdDict,
            contourIdDict
            )
Ejemplo n.º 25
0
    def runAlgorithm(self):
        alg_parameters = []

        feedback = self.createFeedback()

        load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked()
        project = QgsProject.instance() if load_layers else None

        for row in range(self.mainWidget().tblParameters.rowCount()):
            col = 0
            parameters = {}
            for param in self.algorithm().parameterDefinitions():
                if param.flags() & QgsProcessingParameterDefinition.FlagHidden or param.isDestination():
                    continue
                wrapper = self.mainWidget().wrappers[row][col]
                parameters[param.name()] = wrapper.parameterValue()
                if not param.checkValueIsAcceptable(wrapper.parameterValue()):
                    self.messageBar().pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format(
                        param.description(), row + 1),
                        level=Qgis.Warning, duration=5)
                    return
                col += 1
            count_visible_outputs = 0
            for out in self.algorithm().destinationParameterDefinitions():
                if out.flags() & QgsProcessingParameterDefinition.FlagHidden:
                    continue

                count_visible_outputs += 1
                widget = self.mainWidget().tblParameters.cellWidget(row, col)
                text = widget.getValue()
                if out.checkValueIsAcceptable(text):
                    if isinstance(out, (QgsProcessingParameterRasterDestination,
                                        QgsProcessingParameterVectorDestination,
                                        QgsProcessingParameterFeatureSink)):
                        # load rasters and sinks on completion
                        parameters[out.name()] = QgsProcessingOutputLayerDefinition(text, project)
                    else:
                        parameters[out.name()] = text
                    col += 1
                else:
                    self.messageBar().pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format(
                        out.description(), row + 1),
                        level=Qgis.Warning, duration=5)
                    return

            alg_parameters.append(parameters)

        task = QgsScopedProxyProgressTask(self.tr('Batch Processing - {0}').format(self.algorithm().displayName()))
        multi_feedback = QgsProcessingMultiStepFeedback(len(alg_parameters), feedback)
        feedback.progressChanged.connect(task.setProgress)

        with OverrideCursor(Qt.WaitCursor):

            self.mainWidget().setEnabled(False)
            self.cancelButton().setEnabled(True)

            # Make sure the Log tab is visible before executing the algorithm
            try:
                self.showLog()
                self.repaint()
            except:
                pass

            start_time = time.time()

            algorithm_results = []
            for count, parameters in enumerate(alg_parameters):
                if feedback.isCanceled():
                    break
                self.setProgressText(QCoreApplication.translate('BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format(count + 1, len(alg_parameters)))
                self.setInfo(self.tr('<b>Algorithm {0} starting&hellip;</b>').format(self.algorithm().displayName()), escapeHtml=False)
                multi_feedback.setCurrentStep(count)

                parameters = self.algorithm().preprocessParameters(parameters)

                feedback.pushInfo(self.tr('Input parameters:'))
                feedback.pushCommandInfo(pformat(parameters))
                feedback.pushInfo('')

                # important - we create a new context for each iteration
                # this avoids holding onto resources and layers from earlier iterations,
                # and allows batch processing of many more items then is possible
                # if we hold on to these layers
                context = dataobjects.createContext(feedback)

                alg_start_time = time.time()
                ret, results = execute(self.algorithm(), parameters, context, multi_feedback)
                if ret:
                    self.setInfo(QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format(self.algorithm().displayName()), escapeHtml=False)
                    feedback.pushInfo(
                        self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - alg_start_time)))
                    feedback.pushInfo(self.tr('Results:'))
                    feedback.pushCommandInfo(pformat(results))
                    feedback.pushInfo('')
                    algorithm_results.append(results)
                else:
                    break

                handleAlgorithmResults(self.algorithm(), context, multi_feedback, False, parameters)

        feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time)))
        task = None

        self.finish(algorithm_results)
        self.cancelButton().setEnabled(False)
Ejemplo n.º 26
0
 def processAlgorithm(self, parameters, context, feedback):
     """
     Method that triggers the data processing algorithm.
     :param parameters: (dict) mapping from algorithms input's name to its
                        value.
     :param context: (QgsProcessingContext) execution's environmental info.
     :param feedback: (QgsProcessingFeedback) QGIS object to keep track of
                      algorithm's progress/status.
     :return: (dict) output mapping for identified flags.
     """
     layers, selected, silent, ratio = self.getParameters(
         parameters, context, feedback)
     if not layers:
         raise QgsProcessingException(self.tr("No layers were provided."))
     for layer in layers:
         if layer.featureCount() > 0:
             geomType = next(layer.getFeatures()).geometry().wkbType()
             break
     else:
         raise QgsProcessingException(self.tr("All layers are empty."))
     self.prepareFlagSink(parameters, layers[0], geomType, context)
     flags = dict()
     lh = LayerHandler()
     flagCount = 0
     # a step for each input + 1 for loading flags into sink
     multiStepFeedback = QgsProcessingMultiStepFeedback(
         len(layers) + 1, feedback)
     multiStepFeedback.setCurrentStep(0)
     for step, layer in enumerate(layers):
         if multiStepFeedback.isCanceled():
             break
         # running polygon slivers to purposely raise an exception if an
         # empty geometry is found
         multiStepFeedback.pushInfo(
             self.tr("Checking {0}...").format(layer.name()))
         slivers = lh.getPolygonSlivers(layer, ratio, selected, silent,
                                        multiStepFeedback)
         if slivers:
             # pushWarnign is only avalailable on 3.16.2+
             # multiStepFeedback.pushWarning(
             multiStepFeedback.pushDebugInfo(
                 self.tr("{0} slivers were found on {1}!")\
                     .format(len(slivers), layer.name())
             )
             flags[layer] = slivers
             flagCount += len(slivers)
         multiStepFeedback.setCurrentStep(step + 1)
     self.tr("Populating flags layer...")
     self.flagPolygonSlivers(flags, flagCount, multiStepFeedback)
     multiStepFeedback.setCurrentStep(step + 2)
     return {self.FLAGS: self.flag_id}
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        layerHandler = LayerHandler()
        algRunner = AlgRunner()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        tol = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        multiStepFeedback = QgsProcessingMultiStepFeedback(3, feedback)
        multiStepFeedback.setCurrentStep(0)
        multiStepFeedback.pushInfo(
            self.tr('Identifying dangles on {layer}...').format(
                layer=inputLyr.name()))
        dangleLyr = algRunner.runIdentifyDangles(inputLyr,
                                                 tol,
                                                 context,
                                                 feedback=multiStepFeedback,
                                                 onlySelected=onlySelected)

        multiStepFeedback.setCurrentStep(1)
        layerHandler.filterDangles(dangleLyr, tol, feedback=multiStepFeedback)

        multiStepFeedback.setCurrentStep(2)
        multiStepFeedback.pushInfo(
            self.tr('Snapping layer {layer} to dangles...').format(
                layer=inputLyr.name()))
        algRunner.runSnapLayerOnLayer(inputLyr,
                                      dangleLyr,
                                      tol,
                                      context,
                                      feedback=multiStepFeedback,
                                      onlySelected=onlySelected,
                                      behavior=0)

        return {self.OUTPUT: inputLyr}
Ejemplo n.º 28
0
    def runAlgorithm(self):
        alg_parameters = []

        feedback = self.createFeedback()

        load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked()
        project = QgsProject.instance() if load_layers else None

        for row in range(self.mainWidget().batchRowCount()):
            parameters = self.mainWidget().parametersForRow(
                row, destinationProject=project, warnOnInvalid=True)
            alg_parameters.append(parameters)

        task = QgsScopedProxyProgressTask(
            self.tr('Batch Processing - {0}').format(
                self.algorithm().displayName()))
        multi_feedback = QgsProcessingMultiStepFeedback(
            len(alg_parameters), feedback)
        feedback.progressChanged.connect(task.setProgress)

        with OverrideCursor(Qt.WaitCursor):

            self.mainWidget().setEnabled(False)
            self.cancelButton().setEnabled(True)

            # Make sure the Log tab is visible before executing the algorithm
            try:
                self.showLog()
                self.repaint()
            except Exception:  # FIXME which one?
                pass

            start_time = time.time()

            algorithm_results = []
            for count, parameters in enumerate(alg_parameters):
                if feedback.isCanceled():
                    break
                self.setProgressText(
                    QCoreApplication.translate(
                        'BatchAlgorithmDialog',
                        '\nProcessing algorithm {0}/{1}…').format(
                            count + 1, len(alg_parameters)))
                self.setInfo(
                    self.tr('<b>Algorithm {0} starting&hellip;</b>').format(
                        self.algorithm().displayName()),
                    escapeHtml=False)
                multi_feedback.setCurrentStep(count)

                parameters = self.algorithm().preprocessParameters(parameters)

                feedback.pushInfo(self.tr('Input parameters:'))
                feedback.pushCommandInfo(pformat(parameters))
                feedback.pushInfo('')

                # important - we create a new context for each iteration
                # this avoids holding onto resources and layers from earlier iterations,
                # and allows batch processing of many more items then is possible
                # if we hold on to these layers
                context = dataobjects.createContext(feedback)

                alg_start_time = time.time()
                ret, results = execute(self.algorithm(), parameters, context,
                                       multi_feedback)
                if ret:
                    self.setInfo(QCoreApplication.translate(
                        'BatchAlgorithmDialog',
                        'Algorithm {0} correctly executed…').format(
                            self.algorithm().displayName()),
                                 escapeHtml=False)
                    feedback.pushInfo(
                        self.tr(
                            'Execution completed in {0:0.2f} seconds'.format(
                                time.time() - alg_start_time)))
                    feedback.pushInfo(self.tr('Results:'))
                    feedback.pushCommandInfo(pformat(results))
                    feedback.pushInfo('')
                    algorithm_results.append({
                        'parameters': parameters,
                        'results': results
                    })
                else:
                    break

                handleAlgorithmResults(self.algorithm(), context,
                                       multi_feedback, False, parameters)

        feedback.pushInfo(
            self.tr('Batch execution completed in {0:0.2f} seconds'.format(
                time.time() - start_time)))
        task = None

        self.finish(algorithm_results)
        self.cancelButton().setEnabled(False)
Ejemplo n.º 29
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        layerHandler = LayerHandler()
        algRunner = AlgRunner()

        layerHandler = LayerHandler()
        inputLyr = self.parameterAsVectorLayer(
            parameters,
            self.INPUT,
            context
            )
        onlySelected = self.parameterAsBool(
            parameters,
            self.SELECTED,
            context
            )
        tol = self.parameterAsDouble(
            parameters,
            self.TOLERANCE,
            context
            )
        attributeBlackList = self.parameterAsFields(
            parameters,
            self.ATTRIBUTE_BLACK_LIST,
            context
            )
        ignoreVirtual = self.parameterAsBool(
            parameters,
            self.IGNORE_VIRTUAL_FIELDS,
            context
            )
        ignorePK = self.parameterAsBool(
            parameters,
            self.IGNORE_PK_FIELDS,
            context
            )

        layerHandler.mergeLinesOnLayer(
            inputLyr,
            feedback=feedback,
            onlySelected=onlySelected,
            ignoreVirtualFields=ignoreVirtual,
            attributeBlackList=attributeBlackList,
            excludePrimaryKeys=ignorePK
            )
        #aux layer
        multiStepFeedback = QgsProcessingMultiStepFeedback(8, feedback)
        multiStepFeedback.setCurrentStep(0)
        if onlySelected:
            multiStepFeedback.pushInfo(self.tr('Building auxiliar layer...'))
            coverage = layerHandler.createAndPopulateUnifiedVectorLayer(
                [inputLyr],
                geomType=QgsWkbTypes.MultiPolygon,
                onlySelected=onlySelected,
                feedback=multiStepFeedback
                )
        else:
            coverage = inputLyr
        #dangles
        multiStepFeedback.setCurrentStep(1)
        multiStepFeedback.pushInfo(self.tr('Identifying dangles on {layer}...').format(layer=coverage.name()))
        dangleLyr = algRunner.runIdentifyDangles(
            inputLayer=coverage,
            searchRadius=tol,
            context=context,
            feedback=multiStepFeedback,
            onlySelected=False
            )
        #filter dangles
        multiStepFeedback.setCurrentStep(2)
        layerHandler.filterDangles(
            dangleLyr,
            tol,
            feedback=multiStepFeedback
            )
        #snap layer to dangles
        multiStepFeedback.setCurrentStep(3)
        multiStepFeedback.pushInfo(self.tr('Snapping layer {layer} to dangles...').format(layer=coverage.name()))
        algRunner.runSnapLayerOnLayer(
            coverage,
            dangleLyr,
            tol,
            context,
            feedback=multiStepFeedback,
            onlySelected=False, #this is done due to the aux layer usage
            behavior=0
            )
        #inner layer snap
        multiStepFeedback.setCurrentStep(4)
        multiStepFeedback.pushInfo(self.tr('Snapping layer {layer} with {layer}...').format(layer=coverage.name()))
        algRunner.runSnapLayerOnLayer(
            coverage,
            coverage,
            tol,
            context,
            feedback=multiStepFeedback,
            onlySelected=False, #this is done due to the aux layer usage
            behavior=0
            )
        #clean to break lines
        multiStepFeedback.setCurrentStep(5)
        multiStepFeedback.pushInfo(self.tr('Running clean on {layer}...').format(layer=coverage.name()))
        multiStepFeedback.pushInfo(self.tr('Running clean on unified layer...'))
        cleanedCoverage, error = algRunner.runClean(
            coverage,
            [
                algRunner.RMSA,
                algRunner.Break,
                algRunner.RmDupl,
                algRunner.RmDangle
                ],
            context,
            returnError=True,
            snap=snap,
            minArea=minArea,
            feedback=multiStepFeedback
            )
        #remove duplicated features
        multiStepFeedback.setCurrentStep(6)
        multiStepFeedback.pushInfo(self.tr('Removing duplicated features from {layer}...').format(layer=coverage.name()))
        algRunner.runRemoveDuplicatedFeatures(
            inputLyr=cleanedCoverage,
            context=context,
            onlySelected=False,
            attributeBlackList=attributeBlackList,
            excludePrimaryKeys=excludePrimaryKeys,
            ignorePK=ignorePK,
            ignoreVirtual=ignoreVirtual
        )
        #merging lines with same attributes
        multiStepFeedback.setCurrentStep(6)
        multiStepFeedback.pushInfo(self.tr('Merging lines from {layer} with same attribute set...').format(layer=coverage.name()))

        multiStepFeedback.setCurrentStep(7)
        multiStepFeedback.pushInfo(self.tr('Updating original layers...'))
        layerHandler.updateOriginalLayersFromUnifiedLayer(
            [inputLyr],
            coverage,
            feedback=multiStepFeedback,
            onlySelected=onlySelected
            )

        return {self.INPUTLAYERS : inputLyrList}
    def processAlgorithm(self, parameters, context, model_feedback):
        # variables propres à Processing
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)
        results = {}

        # entrées
        lignes = self.parameterAsVectorLayer(parameters, 'lignes', context)
        rasters = parameters['rasters']

        # sorties
        output = self.parameterAsOutputLayer(parameters, 'OUTPUT', context)
        profils = []

        # paramètres
        echantillons_nb = parameters['echantillons_nb']

        # traitement
        if len(rasters) == 0:
            feedback.pushInfo(
                "⚠ Il est nécessaire de fournir au moins un raster en entrée.\n"
            )
            return {}
        for ligne_f in lignes.getFeatures():
            ligne_g = ligne_f.geometry()
            freq = ligne_g.length() / (echantillons_nb - 1)
            echantillons_g = [
                QgsGeometry().fromPointXY(ligne_g.asMultiPolyline()[0][0])
            ]
            for i in range(1, echantillons_nb - 1):
                echantillons_g.append(ligne_g.interpolate(freq * i))
            echantillons_g.append(QgsGeometry().fromPointXY(
                ligne_g.asMultiPolyline()[0][-1]))
            feedback.pushInfo(str(echantillons_g))
            for raster in rasters:
                elevations = []
                for echantillon_g in echantillons_g:
                    elevation = raster.dataProvider().sample(
                        echantillon_g.asPoint(), 1)[0]
                    elevations.append(elevation)
                profils.append([
                    echantillons_g,
                    ligne_f.attributes(),
                    raster.name(), elevations
                ])

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # écriture des données en sortie
        fields = lignes.fields()
        fields.append(QgsField("ordre", QVariant.Int))
        fields.append(QgsField("raster", QVariant.String))
        fields.append(QgsField("elevation", QVariant.Double))
        writer = QgsVectorFileWriter(output, "System", fields,
                                     QgsWkbTypes.Point,
                                     QgsCoordinateReferenceSystem(2154),
                                     "ESRI Shapefile")
        for echantillons_g, attributes, raster_name, elevations in profils:
            ordre = 0
            for echantillon_g, elevation in zip(echantillons_g, elevations):
                f = QgsFeature()
                f.setGeometry(echantillon_g)
                echantillon_att = attributes.copy()
                echantillon_att.append(ordre)
                echantillon_att.append(raster_name)
                echantillon_att.append(elevation)
                f.setAttributes(echantillon_att)
                feedback.pushInfo(str(f.attributes()))
                writer.addFeature(f)
                ordre += 1

        feedback.setCurrentStep(2)

        results['OUTPUT'] = output
        return results
Ejemplo n.º 31
0
    def runAlgorithm(self):
        alg_parameters = []

        feedback = self.createFeedback()

        load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked()
        project = QgsProject.instance() if load_layers else None

        for row in range(self.mainWidget().tblParameters.rowCount()):
            col = 0
            parameters = {}
            for param in self.algorithm().parameterDefinitions():
                if param.flags() & QgsProcessingParameterDefinition.FlagHidden or param.isDestination():
                    continue
                wrapper = self.mainWidget().wrappers[row][col]
                parameters[param.name()] = wrapper.parameterValue()
                if not param.checkValueIsAcceptable(wrapper.parameterValue()):
                    self.messageBar().pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format(
                        param.description(), row + 1),
                        level=Qgis.Warning, duration=5)
                    return
                col += 1
            count_visible_outputs = 0
            for out in self.algorithm().destinationParameterDefinitions():
                if out.flags() & QgsProcessingParameterDefinition.FlagHidden:
                    continue

                count_visible_outputs += 1
                widget = self.mainWidget().tblParameters.cellWidget(row, col)
                text = widget.getValue()
                if out.checkValueIsAcceptable(text):
                    if isinstance(out, (QgsProcessingParameterRasterDestination,
                                        QgsProcessingParameterVectorDestination,
                                        QgsProcessingParameterFeatureSink)):
                        # load rasters and sinks on completion
                        parameters[out.name()] = QgsProcessingOutputLayerDefinition(text, project)
                    else:
                        parameters[out.name()] = text
                    col += 1
                else:
                    self.messageBar().pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format(
                        out.description(), row + 1),
                        level=Qgis.Warning, duration=5)
                    return

            alg_parameters.append(parameters)

        task = QgsScopedProxyProgressTask(self.tr('Batch Processing - {0}').format(self.algorithm().displayName()))
        multi_feedback = QgsProcessingMultiStepFeedback(len(alg_parameters), feedback)
        feedback.progressChanged.connect(task.setProgress)

        with OverrideCursor(Qt.WaitCursor):

            self.mainWidget().setEnabled(False)
            self.cancelButton().setEnabled(True)

            # Make sure the Log tab is visible before executing the algorithm
            try:
                self.showLog()
                self.repaint()
            except:
                pass

            start_time = time.time()

            algorithm_results = []
            for count, parameters in enumerate(alg_parameters):
                if feedback.isCanceled():
                    break
                self.setProgressText(QCoreApplication.translate('BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format(count + 1, len(alg_parameters)))
                self.setInfo(self.tr('<b>Algorithm {0} starting&hellip;</b>').format(self.algorithm().displayName()), escapeHtml=False)
                multi_feedback.setCurrentStep(count)

                parameters = self.algorithm().preprocessParameters(parameters)

                feedback.pushInfo(self.tr('Input parameters:'))
                feedback.pushCommandInfo(pformat(parameters))
                feedback.pushInfo('')

                # important - we create a new context for each iteration
                # this avoids holding onto resources and layers from earlier iterations,
                # and allows batch processing of many more items then is possible
                # if we hold on to these layers
                context = dataobjects.createContext(feedback)

                alg_start_time = time.time()
                ret, results = execute(self.algorithm(), parameters, context, multi_feedback)
                if ret:
                    self.setInfo(QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format(self.algorithm().displayName()), escapeHtml=False)
                    feedback.pushInfo(
                        self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - alg_start_time)))
                    feedback.pushInfo(self.tr('Results:'))
                    feedback.pushCommandInfo(pformat(results))
                    feedback.pushInfo('')
                    algorithm_results.append(results)
                else:
                    break

                handleAlgorithmResults(self.algorithm(), context, multi_feedback, False)

        feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time)))
        task = None

        self.finish(algorithm_results)
        self.cancelButton().setEnabled(False)
Ejemplo n.º 32
0
    def runAlgorithm(self):
        alg_parameters = []

        feedback = self.createFeedback()

        load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked()
        project = QgsProject.instance() if load_layers else None

        for row in range(self.mainWidget().batchRowCount()):
            parameters = self.mainWidget().parametersForRow(row, destinationProject=project, warnOnInvalid=True)
            alg_parameters.append(parameters)

        task = QgsScopedProxyProgressTask(self.tr('Batch Processing - {0}').format(self.algorithm().displayName()))
        multi_feedback = QgsProcessingMultiStepFeedback(len(alg_parameters), feedback)
        feedback.progressChanged.connect(task.setProgress)

        with OverrideCursor(Qt.WaitCursor):

            self.mainWidget().setEnabled(False)
            self.cancelButton().setEnabled(True)

            # Make sure the Log tab is visible before executing the algorithm
            try:
                self.showLog()
                self.repaint()
            except:
                pass

            start_time = time.time()

            algorithm_results = []
            for count, parameters in enumerate(alg_parameters):
                if feedback.isCanceled():
                    break
                self.setProgressText(
                    QCoreApplication.translate('BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format(
                        count + 1, len(alg_parameters)))
                self.setInfo(self.tr('<b>Algorithm {0} starting&hellip;</b>').format(self.algorithm().displayName()),
                             escapeHtml=False)
                multi_feedback.setCurrentStep(count)

                parameters = self.algorithm().preprocessParameters(parameters)

                feedback.pushInfo(self.tr('Input parameters:'))
                feedback.pushCommandInfo(pformat(parameters))
                feedback.pushInfo('')

                # important - we create a new context for each iteration
                # this avoids holding onto resources and layers from earlier iterations,
                # and allows batch processing of many more items then is possible
                # if we hold on to these layers
                context = dataobjects.createContext(feedback)

                alg_start_time = time.time()
                ret, results = execute(self.algorithm(), parameters, context, multi_feedback)
                if ret:
                    self.setInfo(
                        QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format(
                            self.algorithm().displayName()), escapeHtml=False)
                    feedback.pushInfo(
                        self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - alg_start_time)))
                    feedback.pushInfo(self.tr('Results:'))
                    feedback.pushCommandInfo(pformat(results))
                    feedback.pushInfo('')
                    algorithm_results.append(results)
                else:
                    break

                handleAlgorithmResults(self.algorithm(), context, multi_feedback, False, parameters)

        feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time)))
        task = None

        self.finish(algorithm_results)
        self.cancelButton().setEnabled(False)