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
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
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}
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)
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
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
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}
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
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 }
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
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
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
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}
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}
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 )
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…</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)
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}
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…</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)
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
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…</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)
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…</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)