4

I have used the graphical modeller on QGIS to build a simple model performing some processing on my input layer which would be a vector.

What I want to do is to have the name of the input layer, and then by having that, to look through my file to return some of the numbers in there.

So how do I get the name of my input layer in QGIS please?

Edit:

This is my script:

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterExtent
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterRasterDestination
import processing



import pandas as pd

df=pd.read_csv("....csv")

def score_list(namee):

    global a,b,c

    for i in range(0, df.shape[0]):
        if namee == df.iloc[i][1]:
        
            a = df.iloc[i][5]
            b = df.iloc[i][6]
            c = df.iloc[i][7]
        
        else:
            pass
        
        
class SiteSearchModel(QgsProcessingAlgorithm):


def initAlgorithm(self, config=None):
    self.addParameter(QgsProcessingParameterExtent('extent', 'extent', defaultValue=None))
    self.addParameter(QgsProcessingParameterVectorLayer('input', 'Input', types=[QgsProcessing.TypeVectorAnyGeometry], defaultValue=None))
    self.addParameter(QgsProcessingParameterRasterDestination('ReclassifiedRaster', 'Reclassified raster', createByDefault=True, defaultValue=None))
    


def processAlgorithm(self, parameters, context, feedback):
    
     source = self.parameterAsVectorLayer(parameters, 'input', context)
     source_name = source.name()
     
     score_list(source_name)


def processAlgorithm(self, parameters, context, model_feedback):
    # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
    # overall progress through the model
    feedback = QgsProcessingMultiStepFeedback(3, model_feedback)
    results = {}
    outputs = {}

    # Rasterize (vector to raster)
    alg_params = {
        'BURN': 1,
        'DATA_TYPE': 5,  # Float32
        'EXTENT': parameters['extent'],
        'EXTRA': '',
        'FIELD': '',
        'HEIGHT': 50,
        'INIT': None,
        'INPUT': parameters['input'],
        'INVERT': False,
        'NODATA': 0,
        'OPTIONS': '',
        'UNITS': 1,  # Georeferenced units
        'USE_Z': False,
        'WIDTH': 50,
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['RasterizeVectorToRaster'] = processing.run('gdal:rasterize', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

    feedback.setCurrentStep(1)
    if feedback.isCanceled():
        return {}

    # PM
    alg_params = {
        'BAND': 1,
        'DATA_TYPE': 5,  # Float32
        'EXTRA': '',
        'INPUT': outputs['RasterizeVectorToRaster']['OUTPUT'],
        'MAX_DISTANCE': None,
        'NODATA': 0,
        'OPTIONS': '',
        'REPLACE': None,
        'UNITS': 0,  # Georeferenced coordinates
        'VALUES': '1',
        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
    }
    outputs['Pm'] = processing.run('gdal:proximity', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

    feedback.setCurrentStep(2)
    if feedback.isCanceled():
        return {}
        
    
    # Reclassify by table
    alg_params = {
        'DATA_TYPE': 5,  # Float32
        'INPUT_RASTER': outputs['Pm']['OUTPUT'],
        'NODATA_FOR_MISSING': False,
        'NO_DATA': -9999,
        'RANGE_BOUNDARIES': 0,  # min < value <= max
        'RASTER_BAND': 1,
        'TABLE': ['0','0', a ,'0','10000', b ,'10000','', c],
        'OUTPUT': parameters['ReclassifiedRaster']
    }
    outputs['ReclassifyByTable'] = processing.run('native:reclassifybytable', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
    results['ReclassifiedRaster'] = outputs['ReclassifyByTable']['OUTPUT']
    return results

def name(self):
    return 'Site search model'

def displayName(self):
    return 'Site search model'

def group(self):
    return 'Site search'

def groupId(self):
    return 'Site search'

def createInstance(self):
    return SiteSearchModel()

1 Answer 1

5

To get the name of your input layer you can just do something like:

def processAlgorithm(self, parameters, context, feedback):
    source = self.parameterAsVectorLayer(parameters, 'input', context)
    source_name = source.name()

Edit: It looks like you added a second processAlogorithm() method, which is not the right way- processAlgorithm() is a re-implemented class method for overriding. I also added a file parameter so you can select the csv from the file system rather than hard-coding the path.

Edit 2: I have tested this version which runs without error and produces (I think) a reasonable output.

Edit 3 (in response to last comment):

To rename the output layer, taking the name from the input vector- the recommended way to do this is to use the QgsProcessingLayerPostProcessorInterface class. (Credit to Nyall Dawson for the original example which I have adapted here). I have edited this answer again to include this functionality. If you save the output to a permanent file, you can just call it whatever name you like, but if you leave the [Save to temporary file] default, with Open output file after running algorithm checked, the temporary output layer will be loaded with the same name as the input vector layer instead of the generic name 'Reclassified raster'.

from qgis.core import QgsRasterLayer
from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterExtent
from qgis.core import QgsProcessingParameterFile
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterRasterDestination
from qgis.core import QgsProcessingLayerPostProcessorInterface
import processing
import pandas as pd


class SiteSearchModel(QgsProcessingAlgorithm):

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFile('csv', 'Input csv', extension='csv'))
        self.addParameter(QgsProcessingParameterVectorLayer('input', 'Input', types=[QgsProcessing.TypeVectorAnyGeometry], defaultValue=None))
        self.addParameter(QgsProcessingParameterExtent('extent', 'Extent', defaultValue=None))
        self.addParameter(QgsProcessingParameterRasterDestination('ReclassifiedRaster', 'Reclassified raster', createByDefault=True, defaultValue=None))
                
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(3, model_feedback)
        results = {}
        outputs = {}
        source = self.parameterAsVectorLayer(parameters, 'input', context)
        csv = self.parameterAsFile(parameters, 'csv', context)
        
        df = pd.read_csv(csv)
        
        for i in range(0, df.shape[0]):
            if source.name() == df.iloc[i][1]:
                a = df.iloc[i][5]
                b = df.iloc[i][6]
                c = df.iloc[i][7]
            else:
                pass
        
        # Rasterize (vector to raster)
        alg_params = {
            'BURN': 1,
            'DATA_TYPE': 5,  # Float32
            'EXTENT': parameters['extent'],
            'EXTRA': '',
            'FIELD': '',
            'HEIGHT': 50,
            'INIT': None,
            'INPUT': parameters['input'],
            'INVERT': False,
            'NODATA': 0,
            'OPTIONS': '',
            'UNITS': 1,  # Georeferenced units
            'USE_Z': False,
            'WIDTH': 50,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['RasterizeVectorToRaster'] = processing.run('gdal:rasterize', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # PM
        alg_params = {
            'BAND': 1,
            'DATA_TYPE': 5,  # Float32
            'EXTRA': '',
            'INPUT': outputs['RasterizeVectorToRaster']['OUTPUT'],
            'MAX_DISTANCE': None,
            'NODATA': 0,
            'OPTIONS': '',
            'REPLACE': None,
            'UNITS': 0,  # Georeferenced coordinates
            'VALUES': '',
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['Pm'] = processing.run('gdal:proximity', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        feedback.setCurrentStep(2)
        if feedback.isCanceled():
            return {}
                    
        # Reclassify by table
        alg_params = {
            'DATA_TYPE': 5,  # Float32
            'INPUT_RASTER': outputs['Pm']['OUTPUT'],
            'NODATA_FOR_MISSING': False,
            'NO_DATA': -9999,
            'RANGE_BOUNDARIES': 0,  # min < value <= max
            'RASTER_BAND': 1,
            'TABLE': ['0','0', f'{a}' ,'0','10000', f'{b}' ,'10000','', f'{c}'],
            'OUTPUT': parameters['ReclassifiedRaster']
        }
        
        outputs['ReclassifyByTable'] = processing.run('native:reclassifybytable', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['ReclassifiedRaster'] = outputs['ReclassifyByTable']['OUTPUT']
        
        if context.willLoadLayerOnCompletion(results['ReclassifiedRaster']):
            context.layerToLoadOnCompletionDetails(results['ReclassifiedRaster']).setPostProcessor(MyLayerPostProcessor.create(source.name()))

        return results

    def name(self):
        return 'Site search model'

    def displayName(self):
        return 'Site search model'

    def group(self):
        return 'Site search'

    def groupId(self):
        return 'Site search'

    def createInstance(self):
        return SiteSearchModel()
        
class MyLayerPostProcessor(QgsProcessingLayerPostProcessorInterface):

    instance = None
    layer_name = None

    def postProcessLayer(self, layer, context, feedback):
        if not isinstance(layer, QgsRasterLayer):
            return
        # If output is a temporary layer, set layer name from input vector
        if layer.name() == 'Reclassified raster':
            layer.setName(MyLayerPostProcessor.layer_name)
        # You could load a saved style or whatever...
    
    # Hack to work around sip bug!
    @staticmethod
    def create(lyr_name) -> 'MyLayerPostProcessor':
        """
        Returns a new instance of the post processor, keeping a reference to the sip
        wrapper so that sip doesn't get confused with the Python subclass and call
        the base wrapper implementation instead... ahhh sip, you wonderful piece of sip
        """
        MyLayerPostProcessor.layer_name = lyr_name
        MyLayerPostProcessor.instance = MyLayerPostProcessor()
        return MyLayerPostProcessor.instance
11
  • thanks so much for taking your time. I was literally lost in this. I have added your piece of code, but it gives me an error that 'a' is not defined. Can you please have a look at my code and kindly give me a help of what might be wrong ? ('a' is supposed to be the output of my function defined which is used in my raster reclassification.) I will put my code in below.
    – Soheil
    Sep 1, 2022 at 10:31
  • Ben, I have edited my first post to include the script. Your help would be much appreciated. Hope you have a lovely flight btw :).
    – Soheil
    Sep 1, 2022 at 11:02
  • Hi Ben, I think I really need to take a course for PyQGIS!! :) . Thanks for the revision, I have tried it and it gives me an error of ''Invalid output value''. Just wondering where the 'source' is defined in the script as 'parameterAsVectorLayer' ~ source = self.parameterAsVectorLayer(parameters, 'input', context), shouldn't this be defined as 'parameterAsSource' ? This seems to make more sense maybe? Even though I am not sure how to define it. I have seen this here: qgis.org/pyqgis/3.2/core/Processing/…
    – Soheil
    Sep 2, 2022 at 9:37
  • I guess the problem is that source.name() is not returning the name of the vector layer. And the bad thing is that you are somehow in the dark in this environment, while on Jupyter you can check what each code is doing simply.
    – Soheil
    Sep 2, 2022 at 9:48
  • @Soheil, no- self.parameterAsSource would be correct if the input was a QgsProcessingParameterFeatureSource, but since your input is a QgsProcessingParameterVectorLayer, self.parameterAsVectorLayer is correct. The error is coming from elsewhere. Would it be possible for you to share your input files (the csv and a vector layer)? I could probably fix the problem fairly quickly if I had test data.
    – Ben W
    Sep 2, 2022 at 10:26

Your Answer

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

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