I want to create a custom processing algorithm with PyQGIS, which is able to take a vector layer as input (in this case of type point) and then do something with it's features. It's working well as long as I just choose the whole layer. But it doesn't work if I'm trying to work on selected features only.
I'm using QgsProcessingParameterFeatureSource to be able to work on selected features only. The option is shown and I can enable the checkbox. But when I'm executing the algorithm, I get NoneType as return of parameterAsVectorLayer.
Below you'll find a minimal working example to reproduce the problem:
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (
QgsProcessing,
QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource
)
name = "selectedonly"
display_name = "Selected features only example"
group = "Test"
group_id = "test"
short_help_string = "Minimal working example code for showing my problem."
class ExampleProcessingAlgorithm(QgsProcessingAlgorithm):
def tr(self, string):
return QCoreApplication.translate('Processing', string)
def createInstance(self):
return ExampleProcessingAlgorithm()
def name(self):
return name
def displayName(self):
return self.tr(display_name)
def group(self):
return self.tr(group)
def groupId(self):
return group_id
def shortHelpString(self):
return self.tr(short_help_string)
def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterFeatureSource(
'INPUT',
self.tr('Some point vector layer.'),
types=[QgsProcessing.TypeVectorPoint]
)
)
def processAlgorithm(self, parameters, context, feedback):
layer = self.parameterAsVectorLayer(
parameters,
'INPUT',
context
)
return {"OUTPUT": layer}
If I'm working on the whole layer, the output is {'OUTPUT': <QgsVectorLayer: 'Neuer Temporärlayer' (memory)>}, which is what I would expect.
If I'm working on selected features only, my output is {'OUTPUT': None}, which doesn't makes sense to me. I've selected some of the features before executing of course.
I'm using QGIS-version 3.22 LTR, if it's relevant.
Can anybody tell me what I'm doing wrong?
3 Answers 3
The methods parameterAsLayer
, parameterAsRasterLayer
, and parameterAsVectorLayer
of qgis.core.QgsProcessingAlgorithm
evaluate complete map layers of the QGIS project (or usable files from outside of it) in their original form. To only handle selected features from a layer (which includes the possibility to handle all features of the layer, of course!), the method parameterAsSource
has to be used.
The processAlgorithm()
part of the given script thus has to be changed like this (uncomment the feature count output, if you like):
def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(
parameters,
'INPUT',
context
)
# Output the number of features in "source"
# print('Number of features: ' + str(source.featureCount()))
return {"OUTPUT": source}
The problem was solved by the advice of a smart guy.
It doesn't work with parameterAsVectorLayer, but it does with parameterAsSource.
Please note: This has to be regarded as an "alternative answer". It does not answer the OP's question directly, but shows an alternative (and simple) way to solve the issue.
The easiest way to achieve what you want is to click the "Scripts" icon on top of the processing toolbox and select "Create New Script from Template". This example script does exactly what you want. No need to start from scratch.
Change the desired strings (names and so on) to what you need and maybe change
QgsProcessing.TypeVectorAnyGeometry
to
QgsProcessing.TypeVectorPoint
to only allow point layers as input.