3

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

2

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}
0

The problem was solved by the advice of a smart guy.

It doesn't work with parameterAsVectorLayer, but it does with parameterAsSource.

0
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.