2

Note I have edited this question to make it more direct and hopefully get a response.

I am attempting to write a series of processing algorithms to automate and extend a workflow in QGIS 3.4. I have been using the processing script template and following a number of examples including.

  1. pyqgis - post-processing of layer output of QgsProcessingAlgorithm
  2. Defining fields and adding features to output layer using QGIS
  3. Python processing script with clip in QGIS 3.2

I also reference the porting_processing.dox by nyalldawson and the workshop by NathanW.

My problem is ( I think) how to properly use parameterAsSink as described by nyalldawson. Unfortunately none of the listed resources, some of which are unanswered, quite answer my question. There seem to be many variations of how to output results from a processing script. I am sure I am missing something very simple but it has me beat. My best guess is I am not properly assigning the results the output sink.

I have tested the code and the file is generated correctly if I send the result to a file it works. What I can't do is get the memory layer to work - the same as if you are usign the inbuild processing scripts

The following code is a modification of the script template attempting something simple to get started. It runs and as above the result is valid - I just can't get it to the result to the QGIS interface. At present I am just implementing the existing processing difference algorithm but I will extend this when I can get it working properly.

# -*- coding: utf-8 -*-

from PyQt5.QtCore import QCoreApplication from qgis.core import (QgsProcessing, QgsFeatureSink, QgsProcessingException, QgsProcessingAlgorithm, QgsProcessingParameterFeatureSource, QgsProcessingParameterFeatureSink) import processing

class ceaEz(QgsProcessingAlgorithm): INPUT = 'INPUT' OVERLAY= "OVERLAY" OUTPUT = 'OUTPUT'

def tr(self, string):

    return QCoreApplication.translate('Processing', string)

def createInstance(self):

    return type(self)()

def name(self):

    return self.tr('ceaez')

def displayName(self):

    return self.tr('CEA minus EZ')

def group(self):

    return self.tr('Sample plan algorithms')

def groupId(self):

    return 'sampleplanning'

def shortHelpString(self):

    return self.tr("Example algorithm short description")

def initAlgorithm(self, config=None):
    self.addParameter(
        QgsProcessingParameterFeatureSource(
            self.INPUT,
            self.tr('CEA'),
            [QgsProcessing.TypeVectorAnyGeometry]
        )
    )
    self.addParameter(
        QgsProcessingParameterFeatureSource(
            self.OVERLAY,
            self.tr('EZ'),
            [QgsProcessing.TypeVectorAnyGeometry]
        )
    )
    self.addParameter(
        QgsProcessingParameterFeatureSink(
            self.OUTPUT,
            self.tr('OUTPUT'),
            #QgsProcessing.TypeVectorAnyGeometry
        )
    )

def processAlgorithm(self, parameters, context, feedback):
    diff = processing.runAndLoadResults("native:difference", {
             'INPUT': parameters['INPUT'],
             'OVERLAY': parameters['OVERLAY'],
             'OUTPUT': 'memory:'
    }, context = context, feedback = feedback)['OUTPUT']

    return {self.OUTPUT: diff}

Can anyone show me how to get the correct output?

1

The output of the 'native:difference' algorithm is a vector layer. FeatureSink is used when you are creating features in your algorithm. To let the user specify the output which will be used in the algorithm, you should use QgsProcessingParameterVectorDestination() along with parameterAsOutputLayer()

def initAlgorithm(self, config=None):
    self.addParameter(
        QgsProcessingParameterFeatureSource(
            self.INPUT,
            self.tr('CEA'),
            [QgsProcessing.TypeVectorAnyGeometry]
        )
    )
    self.addParameter(
        QgsProcessingParameterFeatureSource(
            self.OVERLAY,
            self.tr('EZ'),
            [QgsProcessing.TypeVectorAnyGeometry]
        )
    )
    self.addParameter(
        QgsProcessingParameterVectorDestination(
            self.OUTPUT,
            self.tr('Output layer')
        )
    )

def processAlgorithm(self, parameters, context, feedback):
    output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)

    diff = processing.runAndLoadResults("native:difference", {
             'INPUT': parameters['INPUT'],
             'OVERLAY': parameters['OVERLAY'],
             'OUTPUT': output
    }, context = context, feedback = feedback)['OUTPUT']

    return {self.OUTPUT: diff}
  • thank you. It seems like the documentation on how to write processing scripts is still catching up to the latest version of QGIS. I added your suggest changes and get an error. NameError: name 'QgsProcessingParameterVectorDestination' is not defined. I don't understand why? Any suggestion? – Suitangi Feb 2 at 1:08
  • add the following at top of the script after all the imports from qgis.core import QgsProcessingParameterVectorDestination – spatialthoughts Feb 22 at 16:32
0

I have not played around much with the processing in v3 but in v2 you could get the out memory layer using getObject():

Maybe one of these will work:

diff_layer = processing.getObject(diff)

or

diff_layer = processing.getObject(diff['OUTPUT'])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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