2

I have a workflow where a raster should be polygonized and afterwards simplified. The simplified vector should be saved as a shapefile. I am using the template script from QGIS to create a processing tool.

I am getting the following error:

Could not load source layer for INPUT: memory: not found

There might be other errors as well. I don't understand what to write in OUTPUT: in any of the processing.run tools.

Furthermore, I am not sure when it is necessary to instance variables (e.g. in_raster = self.parameterAsRasterLayer(...) and I am not sure about the return at the end of the script.

class ExampleProcessingAlgorithm(QgsProcessingAlgorithm):
    INPUT_RASTER = 'INPUT_RASTER'
    OUTPUT_POLYGON = 'OUTPUT_POLYGON'

    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterRasterLayer(
                self.INPUT_RASTER,
                self.tr('Input raster')
            )
        )

        self.addParameter(
            QgsProcessingParameterVectorDestination(
                self.OUTPUT_POLYGON,
                self.tr('Output layer')
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        in_raster = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
        #in_fs_limit = self.parameterAsDouble(parameters, self.THRESHOLD, context)
        #out_polygon = self.parameterAsOutputLayer(parameters, self.OUTPUT_POLYGON, context)
        
        polygonized_output = processing.run(
            "gdal:polygonize", 
            {
                'INPUT':in_raster,
                'BAND':1,
                'FIELD':'DN',
                'EIGHT_CONNECTEDNESS':False,
                'EXTRA':'',
                'OUTPUT':'memory:'
            }
        )['OUTPUT']

        simplified = processing.run(
            "native:simplifygeometries", 
            {
                'INPUT':polygonized_output,
                'METHOD':0,
                'TOLERANCE':350,
                'OUTPUT':parameters['OUTPUT_POLYGON']
            },
            context=context,
            feedback=feedback
        )['OUTPUT']

        return {self.OUTPUT_POLYGON: simplified}

1 Answer 1

3

The error occurs because the intermediate results stored in memory are not being handled properly. QGIS sometimes has trouble managing layers in memory between processing steps.

To fix this, you can either use temporary files for intermediate outputs instead of relying on in-memory storage, something like:

temp_polygonized_output = os.path.join(tempfile.gettempdir(), 'polygonized_output.shp')
temp_simplified_output = os.path.join(tempfile.gettempdir(), 'simplified_output.shp')
    

or do 'OUTPUT': 'TEMPORARY_OUTPUT' as I did below:

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


class ExampleProcessingAlgorithm(QgsProcessingAlgorithm):
    """
    This is an example algorithm that takes a vector layer and
    creates a new identical one.

    It is meant to be used as an example of how to create your own
    algorithms and explain the methods and variables used to do it. An
    algorithm like this will be available in all elements, and there
    is no need for additional work.

    All Processing algorithms should extend the QgsProcessingAlgorithm
    class.
    """

    # Constants are used to refer to parameters and outputs. They will be
    # used when calling the algorithm from another algorithm, or when
    # calling from the QGIS console.

    INPUT_RASTER = 'INPUT'
    OUTPUT_POLYGON = 'OUTPUT'

    def tr(self, string):
        """
        Returns a translatable string with the self.tr() function.
        """
        return QCoreApplication.translate('Processing', string)
        
    def createInstance(self):
        """
        Returns a new instance of the algorithm. This is necessary for
        creating the algorithm from within QGIS.
        """
        return ExampleProcessingAlgorithm()
    def name(self):
        """
        Returns the algorithm name, used for identifying the algorithm. This
        string should be fixed for the algorithm, and must not be localised.
        The name should be unique within each provider. Names should contain
        lowercase alphanumeric characters only and no spaces or other
        formatting characters.
        """
        return 'myscript'

    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterRasterLayer(
                self.INPUT_RASTER,
                self.tr('Input raster')
            )
        )

        self.addParameter(
            QgsProcessingParameterVectorDestination(
                self.OUTPUT_POLYGON,
                self.tr('Output layer')
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        in_raster = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
        # in_fs_limit = self.parameterAsDouble(parameters, self.THRESHOLD, context)
        out_polygon = self.parameterAsOutputLayer(parameters, self.OUTPUT_POLYGON, context)

        polygonized_output = processing.run(
            "gdal:polygonize",
            {
                'INPUT': in_raster,
                'BAND': 1,
                'FIELD': 'DN',
                'EIGHT_CONNECTEDNESS': False,
                'EXTRA': '',
                'OUTPUT': 'TEMPORARY_OUTPUT'
            }
        )['OUTPUT']

        simplified = processing.run(
            "native:simplifygeometries",
            {
                'INPUT': polygonized_output,
                'METHOD': 0,
                'TOLERANCE': 350,
                'OUTPUT': out_polygon
            },
            context=context,
            feedback=feedback
        )['OUTPUT']

        return {self.OUTPUT_POLYGON: simplified}
1
  • That works, thank you very much!
    – Freddy94
    Commented May 22 at 11:32

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.