2

I have exported this code from Graphic Modeler of QGIS as a python script. The Model is outputting the final result as CN_Grid, as it should, but the script of the same model is giving results as Remaining fields. Is there something I am doing wrong?

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterBoolean
from qgis.core import QgsProcessingParameterFeatureSource
from qgis.core import QgsProcessingParameterRasterLayer
from qgis.core import QgsProcessingParameterFeatureSink
from qgis.core import QgsProcessingParameterDefinition
import processing
class Cn_grid(QgsProcessingAlgorithm):
 def initAlgorithm(self, config=None):
 self.addParameter(QgsProcessingParameterVectorLayer('areaboundary', 'Area Boundary', types=[QgsProcessing.TypeVectorPolygon], defaultValue=None))
 self.addParameter(QgsProcessingParameterRasterLayer('nlcdlandcoverimgfile', 'NLCD Land Cover .img File', defaultValue=None))
 self.addParameter(QgsProcessingParameterVectorLayer('soilfilesoilmuaaoi', 'Soil File [soilmu_a_aoi]', types=[QgsProcessing.TypeVectorPolygon], defaultValue=None))
 self.addParameter(QgsProcessingParameterFeatureSource('hsglookupcsv2', 'HSG Lookup .csv', types=[QgsProcessing.TypeVector], defaultValue=None))
 param = QgsProcessingParameterBoolean('drainedsoilsleaveuncheckedifnotsure', 'Drained Soils? [leave unchecked if not sure]', defaultValue=False)
 param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
 self.addParameter(param)
 self.addParameter(QgsProcessingParameterFeatureSink('Cn_grid', 'CN_Grid', type=QgsProcessing.TypeVectorAnyGeometry, 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(11, model_feedback)
 results = {}
 outputs = {}
 # Buffer
 alg_params = {
 'DISSOLVE': False,
 'DISTANCE': 120,
 'END_CAP_STYLE': 0,
 'INPUT': parameters['areaboundary'],
 'JOIN_STYLE': 0,
 'MITER_LIMIT': 2,
 'SEGMENTS': 5,
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['Buffer'] = processing.run('native:buffer', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(1)
 if feedback.isCanceled():
 return {}
 # Clip raster by extent
 alg_params = {
 'DATA_TYPE': 0,
 'INPUT': parameters['nlcdlandcoverimgfile'],
 'NODATA': None,
 'OPTIONS': '',
 'PROJWIN': outputs['Buffer']['OUTPUT'],
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['ClipRasterByExtent'] = processing.run('gdal:cliprasterbyextent', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(2)
 if feedback.isCanceled():
 return {}
 # Raster pixels to polygons
 alg_params = {
 'FIELD_NAME': 'VALUE',
 'INPUT_RASTER': outputs['ClipRasterByExtent']['OUTPUT'],
 'RASTER_BAND': 1,
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['RasterPixelsToPolygons'] = processing.run('native:pixelstopolygons', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(3)
 if feedback.isCanceled():
 return {}
 # Dissolve
 alg_params = {
 'FIELD': 'Value',
 'INPUT': outputs['RasterPixelsToPolygons']['OUTPUT'],
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['Dissolve'] = processing.run('native:dissolve', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(4)
 if feedback.isCanceled():
 return {}
 # Intersection
 alg_params = {
 'INPUT': parameters['soilfilesoilmuaaoi'],
 'INPUT_FIELDS': 'MUSYM',
 'OVERLAY': outputs['Dissolve']['OUTPUT'],
 'OVERLAY_FIELDS': 'VALUE',
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['Intersection'] = processing.run('native:intersection', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(5)
 if feedback.isCanceled():
 return {}
 # Join attributes by field value
 alg_params = {
 'DISCARD_NONMATCHING': False,
 'FIELD': 'MUSYM',
 'FIELDS_TO_COPY': 'HSG',
 'FIELD_2': 'MUSYM',
 'INPUT': outputs['Intersection']['OUTPUT'],
 'INPUT_2': parameters['hsglookupcsv2'],
 'METHOD': 1,
 'PREFIX': '',
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['JoinAttributesByFieldValue'] = processing.run('native:joinattributestable', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(6)
 if feedback.isCanceled():
 return {}
 # Field calculator
 alg_params = {
 'FIELD_LENGTH': 5,
 'FIELD_NAME': 'GDCodeTemp',
 'FIELD_PRECISION': 3,
 'FIELD_TYPE': 2,
 'FORMULA': '\"Value\" || \"HSG\"',
 'INPUT': outputs['JoinAttributesByFieldValue']['OUTPUT'],
 'NEW_FIELD': True,
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['FieldCalculator'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(7)
 if feedback.isCanceled():
 return {}
 # Field calculator2
 alg_params = {
 'FIELD_LENGTH': 5,
 'FIELD_NAME': 'GDCode',
 'FIELD_PRECISION': 3,
 'FIELD_TYPE': 2,
 'FORMULA': 'if( var(\'drainedsoilsleaveuncheckedifnotsure\') = True,replace(\"GDCodeTemp\", \'/D\', \'\'),replace(\"GDCodeTemp\", map(\'A/\', \'\', \'B/\', \'\', \'C/\', \'\')))',
 'INPUT': outputs['FieldCalculator']['OUTPUT'],
 'NEW_FIELD': True,
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['FieldCalculator2'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(8)
 if feedback.isCanceled():
 return {}
 # Field calculator3
 alg_params = {
 'FIELD_LENGTH': 2,
 'FIELD_NAME': 'NLCD_LU',
 'FIELD_PRECISION': 3,
 'FIELD_TYPE': 1,
 'FORMULA': '\"Value\"',
 'INPUT': outputs['FieldCalculator2']['OUTPUT'],
 'NEW_FIELD': True,
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['FieldCalculator3'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(9)
 if feedback.isCanceled():
 return {}
 # Field calculator4
 alg_params = {
 'FIELD_LENGTH': 3,
 'FIELD_NAME': 'CN',
 'FIELD_PRECISION': 3,
 'FIELD_TYPE': 1,
 'FORMULA': 'replace(\"GDCode\", array(\'11A\', \'11B\', \'11C\', \'11D\', \'11\', \'12A\', \'12B\', \'12C\', \'12D\', \'12\', \'21A\', \'21B\', \'21C\', \'21D\', \'21\', \'22A\', \'22B\', \'22C\', \'22D\', \'22\', \'23A\', \'23B\', \'23C\', \'23D\', \'23\', \'24A\', \'24B\', \'24C\', \'24D\', \'24\', \'31A\', \'31B\', \'31C\', \'31D\', \'31\', \'41A\', \'41B\', \'41C\', \'41D\', \'41\', \'42A\', \'42B\', \'42C\', \'42D\', \'42\', \'43A\', \'43B\', \'43C\', \'43D\', \'43\', \'51A\', \'51B\', \'51C\', \'51D\', \'51\', \'52A\', \'52B\', \'52C\', \'52D\', \'52\', \'71A\', \'71B\', \'71C\', \'71D\', \'71\', \'72A\', \'72B\', \'72C\', \'72D\', \'72\', \'73A\', \'73B\', \'73C\', \'73D\', \'73\', \'74A\', \'74B\', \'74C\', \'74D\', \'74\', \'81A\', \'81B\', \'81C\', \'81D\', \'81\', \'82A\', \'82B\', \'82C\', \'82D\', \'82\', \'90A\', \'90B\', \'90C\', \'90D\', \'90\', \'95A\', \'95B\', \'95C\', \'95D\', \'95\'), array(\'100\', \'100\', \'100\', \'100\', \'100\', \'100\', \'100\', \'100\', \'100\', \'100\', \'52\', \'68\', \'78\', \'84\', \'84\', \'100\', \'88\', \'90\', \'93\', \'93\', \'84\', \'89\', \'93\', \'94\', \'94\', \'88\', \'92\', \'93\', \'94\', \'94\', \'70\', \'81\', \'88\', \'92\', \'92\', \'30\', \'30\', \'41\', \'48\', \'48\', \'30\', \'55\', \'70\', \'77\', \'77\', \'36\', \'60\', \'73\', \'79\', \'79\', \'33\', \'42\', \'55\', \'62\', \'62\', \'33\', \'42\', \'55\', \'62\', \'62\', \'47\', \'63\', \'75\', \'85\', \'85\', \'47\', \'63\', \'75\', \'85\', \'85\', \'74\', \'74\', \'74\', \'74\', \'74\', \'79\', \'79\', \'79\', \'79\', \'79\', \'40\', \'61\', \'73\', \'79\', \'79\', \'62\', \'74\', \'82\', \'86\', \'86\', \'86\', \'86\', \'86\', \'86\', \'86\', \'80\', \'80\', \'80\', \'80\', \'80\'))',
 'INPUT': outputs['FieldCalculator3']['OUTPUT'],
 'NEW_FIELD': True,
 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
 }
 outputs['FieldCalculator4'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 feedback.setCurrentStep(10)
 if feedback.isCanceled():
 return {}
 # Drop field(s)
 alg_params = {
 'COLUMN': 'VALUE;GDCodeTemp',
 'INPUT': outputs['FieldCalculator4']['OUTPUT'],
 'OUTPUT': parameters['Cn_grid']
 }
 outputs['DropFields'] = processing.run('qgis:deletecolumn', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 results['Cn_grid'] = outputs['DropFields']['OUTPUT']
 return results
 def name(self):
 return 'CN_Grid'
 def displayName(self):
 return 'CN_Grid'
 def group(self):
 return 'QGIS Tools'
 def groupId(self):
 return 'QGIS Tools'
 def shortHelpString(self):
 return """<html><body><h2>Algorithm description</h2></body></html>"""
 def createInstance(self):
 return Cn_grid()
PolyGeo
65.5k29 gold badges115 silver badges349 bronze badges
asked Dec 26, 2019 at 18:40

1 Answer 1

1

This is not a bug, the Cn_grid output parameter in the script receives the information from the outputs['DropFields'], unfortunately at this point it ignores the start settings of the script.

The last step of the script must not be a native process of type "processing.run". Otherwise will always receive the default output name of the process used.

EDIT

Answering the Someone191's comment.

Unfortunately this is where I came up with my questions Here and Here.
I couldn't create a simple process to solve the case directly in the script I'm working on.

The not-so-good solution I found was to create a second script that just gets an input and creates an identical output. Going back to the main script, I put this second basic script as the last step, so the name of the outputs will obey those that were defined in the second script.

The backing script, named InOut, basically has this:

def initAlgorithm(self, config=None):
 self.addParameter(QgsProcessingParameterVectorLayer('Atlas','Atlas',optional=True, types=[QgsProcessing.TypeVector], defaultValue=None))
 self.addParameter(QgsProcessingParameterFeatureSink('Atlas S','Atlas', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))
def processAlgorithm(self, parameters, context, feedback):
 source = self.parameterAsSource(parameters,'Atlas',context)
 (sink, dest_id) = self.parameterAsSink(parameters,'Atlas S',context,source.fields(),source.wkbType(),source.sourceCrs())
 total = 100.0 / source.featureCount() if source.featureCount() else 0
 features = source.getFeatures()
 for current, feature in enumerate(features):
 sink.addFeature(feature, QgsFeatureSink.FastInsert)
 feedback.setProgress(int(current * total))
 return {'Output':('Renamed Shapes')}

The main script is like this:

def initAlgorithm(self, config=None): 
 self.addParameter(QgsProcessingParameterFeatureSink('AtlasOutput', 'ATLAS for Maps', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))
 .
 .
 .
def processAlgorithm(self, parameters, context, model_feedback):
 .
 .
 .
 # Diferrence
 alg_params = {
 'INPUT': outputs['P29TalhesFinal']['OUTPUT'],
 'OVERLAY': outputs['BufferGG']['OUTPUT'],
 'OUTPUT': 'memory:'
 }
 outputs['2Diferena'] = processing.run('native:difference', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 # InOut
 alg_params = {
 'Atlas': outputs['2Diferena']['OUTPUT'],
 'Atlas S': parameters['AtlasOutput'],
 }
 outputs['Inout'] = processing.run('script:InOut', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 return results
 return {}

Note that the output will be named Atlas and not ATLAS for Maps, obeying the name given in the InOut script.

For now that's enough for me, but I'm still trying to solve it with just one script Here, let me know if you can make any progress with it.

answered Dec 26, 2019 at 19:10
2
  • Thanks. Can you explain this further. What do I need to change in this to make it a non native process? Commented Dec 26, 2019 at 22:18
  • @Someone191 I made the answer clearer to help you. Commented Dec 27, 2019 at 11:42

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.