1

How do I create a Processing script which asks the user for a layer and then conducts an operation on it?

import processing
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessingAlgorithm,
                   QgsProcessing,
                   QgsProcessingParameterFeatureSource,
                   QgsProcessingParameterFeatureSink,
                   QgsVectorLayer)

class testAlg(QgsProcessingAlgorithm):
    HEXES = 'HEXES'
    OUTPUT = 'OUTPUT'

    def tr(self, text):
        return QCoreApplication.translate('testalg', text)

    def createInstance(self):
        return type(self)()

    def group(self):
        return self.tr('Test')

    def groupId(self):
        return 'test'

     def __init__(self):
        super().__init__()

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

        self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
                                                        self.tr('Output'),
                                                        QgsProcessing.TypeVectorPolygon))

    def name(self):
        return 'testalg'

    def displayName(self):
        return self.tr('Test Algorithm')

    def processAlgorithm(self, parameters, context, feedback):
        hex_source1 = self.parameterAsSource(parameters, self.HEXES, context)
        hex_source2 = QgsVectorLayer('/Users/username/temp/hexes.shp', 'hex_source2', 'ogr')

        feedback.pushConsoleInfo(str(type(hex_source1))) # Returns QgsProcessingFeatureSource
        feedback.pushConsoleInfo(str(type(hex_source2))) # Returns QgsVectorLayer

        processing.run('qgis:fieldcalculator',
                   {'INPUT':hex_source1, # Dies here as it can't accept a QgsProcessingFeatureSource
                    'FIELD_NAME':'test',
                    'FIELD_TYPE':0,
                    'FIELD_LENGTH':10,
                    'FIELD_PRECISION':6,
                    'NEW_FIELD':True,
                    'FORMULA':'( "c" / sum(  "c" )) * 100',
                    'OUTPUT':'/Users/username/temp/hexes2.shp'},
                   feedback=feedback,
                   context=context)

        return {}

This code fails at the processing.run command as it can't accept a QgsProcessingFeatureSource (hex_source1) as an input (actual error is Incorrect parameter value for INPUT). Using hex_source2 works fine as that returns a QgsVectorLayer which is apparently fine as an input.

I have also tried QgsProcessingParameterVectorLayer which also seems to give a QgsProcessingFeatureSource result.

Should I be converting a QgsProcessingFeatureSource to a QgsVectorLayer? If so, how? Or is there a simpler way to load a layer for processing that I'm missing?

1

In this case, because the field calculator algorithm requires a vector layer input, you'll need to declare a QgsProcessingParameterVectorLayer parameter as the input for your algorithm (not a feature source).

You'll then need to change

 hex_source1 = self.parameterAsSource(parameters, self.HEXES, context)

To

 hex_source1 = self.parameterAsVectorLayer(parameters, self.HEXES, context)

This will give you a QgsVectorLayer value for hex_source1, ready for handing off to the field calculator algorithm.

  • Doesn't seem to work. Feedback gives <class 'NoneType'> and the processing.run fails due to Incorrect parameter value for INPUT. – Josh Apr 25 '18 at 15:04
0

Keep

 hex_source1 = self.parameterAsSource(parameters, self.HEXES, context)

But instead of

'INPUT':hex_source1

use

'INPUT':hex_source1.materialize(QgsFeatureRequest())

(be sur to add QgsFeatureRequest in your imports)

0

This is confusing, but As pointed out here , you can simply lookup the input layer's value from parameters

hex_source1 = parameters[self.HEXES]
0

As ndawson pointed out, the qgis:fieldcalculator algorithm needs a VectorLayer. I have modified your code accordingly (also had to change the formulae and output path, and removed hex_source2), and it works for me in QGIS 3.4.

import processing
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessingAlgorithm,
               QgsProcessing,
               QgsProcessingParameterFeatureSource,
               QgsProcessingParameterFeatureSink,
               QgsVectorLayer)

class testAlg(QgsProcessingAlgorithm):
  HEXES = 'HEXES'
  OUTPUT = 'OUTPUT'

  def tr(self, text):
    return QCoreApplication.translate('testalg', text)

  def createInstance(self):
    return type(self)()

  def group(self):
    return self.tr('Test')

  def groupId(self):
    return 'test'

  def __init__(self):
    super().__init__()

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

    self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
                                                    self.tr('Output'),
                                          QgsProcessing.TypeVectorPolygon))

  def name(self):
    return 'testalg'

  def displayName(self):
    return self.tr('Test Algorithm')

  def processAlgorithm(self, parameters, context, feedback):
    hex_source1 = self.parameterAsVectorLayer(parameters, self.HEXES, context)
    #hex_source1 = self.parameterAsSource(parameters, self.HEXES, context)
    #hex_source2 = QgsVectorLayer('/Users/username/temp/hexes.shp', 'hex_source2', 'ogr')

    feedback.pushConsoleInfo(str(type(hex_source1))) # Returns QgsProcessingFeatureSource
    #feedback.pushConsoleInfo(str(type(hex_source2))) # Returns QgsVectorLayer

    processing.run('qgis:fieldcalculator',
               {'INPUT':hex_source1, # Dies here as it can't accept a QgsProcessingFeatureSource
                'FIELD_NAME':'test',
                'FIELD_TYPE':0,
                'FIELD_LENGTH':10,
                'FIELD_PRECISION':6,
                'NEW_FIELD':True,
                'FORMULA':'( "FID" / sum(  "FID" )) * 100',
                'OUTPUT':'/tmp/test.shp'},
               feedback=feedback,
               context=context)

    return {}

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.