TransWikia.com

Convert scripts for processing toolbox

Geographic Information Systems Asked on March 17, 2021

Does anyone know how I can turn this console script into a script that I can integrate into the processing toolbox? I tried a few options, but I don’t do very well in python, and I always get stuck.

# Change your settings here:
layername = 'line' 
triggerfield = 'Trigger' # field must already exist
groupfieldname = 'mygroup' # will be added if does not exist
newlineindicator = 1

#####
# no changes needed below #
#####
layer = QgsProject.instance().mapLayersByName(layername)[0] # get the layer
layer.startEditing() # start editing the layer
layer.dataProvider().addAttributes([QgsField(groupfieldname,QVariant.Int)]) # add a group field
layer.commitChanges() # save new added field to prevent crash when searching for it later
layer.startEditing() # start editing the layer again
groupid = 0 # initialize groupid
fieldindex = layer.fields().indexFromName(groupfieldname) # get fieldindex of groupfield

for feat in layer.getFeatures(): # itereate over layer
    if feat[triggerfield] == newlineindicator: # if a new trigger appears, increase groupcounter
        groupid += 1
    attrs = { fieldindex : groupid } # prepare attributes
    layer.dataProvider().changeAttributeValues({ feat.id() : attrs }) # assign current groupid to current feature
layer.commitChanges() # save changes

What do you think? Can it be transformed into a function, with input and output parameters?

EDIT:

I got stuck at this point. Does anyone know how I can solve this script?
How should I define "newlineindicator = 1" and "groupid = 0"?

# -*- coding: utf-8 -*-
from PyQt5.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsProcessing,
                       QgsFeatureSink,
                       QgsFeature,
                       QgsField,
                       QgsFields,
                       QgsProcessingException,
                       QgsProcessingAlgorithm,
                       QgsProcessingParameterString,
                       QgsProcessingParameterNumber,
                       QgsProcessingParameterEnum,
                       QgsProcessingParameterFeatureSource,
                       QgsProcessingParameterFeatureSink,
                       QgsProcessingParameterField,
                       )
import processing
class MergingMultipleLinesByValueField(QgsProcessingAlgorithm):
    INPUT = 'INPUT'
    OUTPUT = 'OUTPUT'
    TRIGGER_FIELD = 'trigger_field'
    groupfieldname = 'mygrup'

    def tr(self, string):
        return QCoreApplication.translate('Processing', string)

    def createInstance(self):
        return MergingMultipleLinesByValueField()

    def name(self):
        return 'myscript'

    def displayName(self):
        return self.tr('My Script')

    def group(self):
        return self.tr('Example scripts')

    def groupId(self):
        return 'examplescripts'

    def shortHelpString(self):
        return self.tr("Example algorithm short description")

    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterFeatureSource(
                self.INPUT,
                self.tr('Input layer'),
                [QgsProcessing.TypeVectorAnyGeometry]
            )
        )

        
        self.addParameter(
            QgsProcessingParameterField(
                self.TRIGGER_FIELD,
                'Choose Trigger Field',
                '', 
                self.INPUT
            )
        )

        self.addParameter(
            QgsProcessingParameterField(
                self.groupfieldname,
                'Choose Trigger Field',
                '', 
                self.INPUT
            )
        ) 

        self.addParameter(
            QgsProcessingParameterFeatureSink(
                self.OUTPUT,
                self.tr('Output layer')
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(
            parameters,
            self.INPUT,
            context
        )
        
        trigger = self.parameterAsString(
            parameters,
            self.TRIGGER_FIELD,
            context)
            
        groupfield = self.parameterAsString(
            parameters,
            self.groupfieldname,
            context)
        
        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
            
        fields = QgsFields()
        fields.append(QgsField(trigger, QVariant.String))

        (sink, dest_id) = self.parameterAsSink(
            parameters,
            self.OUTPUT,
            context,
            source.fields(),
            source.wkbType(),
            source.sourceCrs()
        )

        feedback.pushInfo('Extracting unique values from dissolve_field and computing sum')
        features = source.getFeatures()
        groupid = set(f[trigger] for f in features)
        groupid = source.fields().indexFromName(trigger)
        fieldindex = source.fields().indexFromName(groupfieldname) # get fieldindex of groupfield
        newlineindicator = 1
        groupid = 0
        
        for feat in source.getFeatures(): # itereate over layer
            if feat[trigger] == newlineindicator: # if a new trigger appears, increase groupcounter
                    groupid += 1
            attrs = { fieldindex : groupid } # prepare attributes
            layer.dataProvider().changeAttributeValues({ feat.id() : attrs }) # assign current groupid to current feature
        layer.commitChanges() # save changes
        
        

        return {self.OUTPUT: dest_id}

One Answer

This should do it:

from PyQt5.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsField, QgsFeature, QgsProcessing, QgsExpression, QgsGeometry, QgsPoint, QgsFields, QgsWkbTypes,
                       QgsFeatureSink, QgsFeatureRequest, QgsProcessingAlgorithm,
                       QgsProcessingParameterFeatureSink, QgsProcessingParameterField, QgsProcessingParameterFeatureSource, QgsProcessingParameterEnum, QgsProcessingParameterString, QgsProcessingParameterNumber)

class AddGroupByIndicator(QgsProcessingAlgorithm):
    SOURCE_LYR = 'SOURCE_LYR'
    TRIGGER_FIELD = 'TRIGGER_FIELD'
    GROUP_IDFIELD = 'GROUP_IDFIELD'
    INDICATOR_VALUE = 'INDICATOR_VALUE'
    OUTPUT = 'OUTPUT'

    def initAlgorithm(self, config=None):
        
        self.addParameter(
            QgsProcessingParameterFeatureSource(
                self.SOURCE_LYR, self.tr('Source'))) # Take any source layer
        self.addParameter(
            QgsProcessingParameterField(
                self.TRIGGER_FIELD, self.tr('Trigger Field indicating a new Group'),'Trigger','SOURCE_LYR')) # Choose the Trigger field of the source layer, default if exists is 'Trigger'
        self.addParameter(
            QgsProcessingParameterString(
                self.GROUP_IDFIELD, self.tr('Name of new generated GroupID Field'),'groupid')) # String of the new added fieldname, default is 'groupid'
        self.addParameter(
            QgsProcessingParameterNumber(
                self.INDICATOR_VALUE, self.tr('Number indicating a new Group'),0,1)) # Indicator as number. 0=Int, 1 would be double; 1=default number
        self.addParameter(
            QgsProcessingParameterFeatureSink(
                self.OUTPUT, self.tr('SourceWithGroupID'))) # Output

    def processAlgorithm(self, parameters, context, feedback):
        # Get Parameters and assign to variable to work with
        source_layer = self.parameterAsLayer(parameters, self.SOURCE_LYR, context)
        triggerfield = self.parameterAsString(parameters, self.TRIGGER_FIELD, context)
        groupfieldname = self.parameterAsString(parameters, self.GROUP_IDFIELD, context)
        newlineindicator = self.parameterAsInt(parameters, self.INDICATOR_VALUE, context)
        
        groupid = 0 # initialize groupid counter
        
        total = 100.0 / source_layer.featureCount() if source_layer.featureCount() else 0 # Initialize progress for progressbar
        
        fields = source_layer.fields() # get all fields of the sourcelayer
        fields.append(QgsField(groupfieldname, QVariant.Int, len=20)) # add a new field to this list
        
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, source_layer.wkbType(),
                                               source_layer.sourceCrs())
                                               
        for current, feat in enumerate(source_layer.getFeatures()): # iterate over source 
            if feat[triggerfield] == newlineindicator: # if trigger appears increase groupcounter
                groupid += 1
            new_feat = QgsFeature(fields) # copy source fields + appended
            idx = 0 # reset attribute fieldindex
            for attr in feat.attributes(): # iterate over attributes of source layer for the current feature
                new_feat[idx] = attr # copy attribute values over to the new layer
                idx += 1 # increase fieldindex counter
            new_feat[groupfieldname] = groupid # assign the groupid
            new_feat.setGeometry(feat.geometry()) # copy over the geometry of the source feature
            
            sink.addFeature(new_feat, QgsFeatureSink.FastInsert) # add feature to the output
            
            if feedback.isCanceled(): # Cancel algorithm if button is pressed
                break
            
            feedback.setProgress(int(current * total)) # Set Progress in Progressbar

        return {self.OUTPUT: dest_id} # Return result of algorithm



    def tr(self, string):
        return QCoreApplication.translate('Processing', string)

    def createInstance(self):
        return AddGroupByIndicator()

    def name(self):
        return 'AddGroupByIndicator'

    def displayName(self):
        return self.tr('Add group by indicator field')

    def group(self):
        return self.tr('FROM GISSE')

    def groupId(self):
        return 'from_gisse'

    def shortHelpString(self):
        return self.tr('This Algorithm adds a new group id found by a trigger')

Correct answer by MrXsquared on March 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP