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}
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
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP