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
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
-
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– Soheil2022年09月01日 10:31:03 +00:00Commented 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– Soheil2022年09月01日 11:02:36 +00:00Commented 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– Soheil2022年09月02日 09:37:08 +00:00Commented 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– Soheil2022年09月02日 09:48:08 +00:00Commented Sep 2, 2022 at 9:48
-
@Soheil, no-
self.parameterAsSource
would be correct if the input was aQgsProcessingParameterFeatureSource
, but since your input is aQgsProcessingParameterVectorLayer
,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– Ben W2022年09月02日 10:26:23 +00:00Commented Sep 2, 2022 at 10:26