1 votos

Uso del campo vectorial de entrada en QGIS python script

He creado un modelo gráfico de QGIS utilizando el modelador gráfico incorporado. Mi modelo se supone que pide al usuario una capa de entrada, una capa de superposición y campos de la capa de superposición.

A continuación, el modelo debe calcular la media ponderada por área de esos campos para cada característica de la capa de entrada. El resultado será una capa de entrada con campos adicionales para cada promedio ponderado por área.

enter image description here

Me he dado cuenta de que el campo de entrada no se puede utilizar en el modelador gráfico y tengo que convertirlo en un script de python para realizar esta tarea. Aquí añado el script. Lo que estoy teniendo problemas es con la forma de utilizar la entrada del usuario en mis cálculos de campo y nombres de campo.

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterField
from qgis.core import QgsProcessingParameterFeatureSink
import processing

class FutureLuHsg(QgsProcessingAlgorithm):

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterVectorLayer('luhsgexisting', 'LU HSG', types=[QgsProcessing.TypeVectorPolygon], defaultValue=None))
        self.addParameter(QgsProcessingParameterVectorLayer('parcels', 'Parcels', types=[QgsProcessing.TypeVectorPolygon], defaultValue=None))
        self.addParameter(QgsProcessingParameterField('fieldtoaverage1', 'Field to Average', type=QgsProcessingParameterField.Numeric, parentLayerParameterName='luhsgexisting', allowMultiple=True, defaultValue=None))
        self.addParameter(QgsProcessingParameterFeatureSink('Joined', 'Joined', optional=True, type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))
        self.addParameter(QgsProcessingParameterFeatureSink('Final', 'Final', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))
        self.addParameter(QgsProcessingParameterFeatureSink('Stats', 'Stats', 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(6, model_feedback)
        results = {}
        outputs = {}

        # Field calculator
        alg_params = {
            'FIELD_LENGTH': 10,
            'FIELD_NAME': 'FID_Parcels',
            'FIELD_PRECISION': 3,
            'FIELD_TYPE': 1,
            'FORMULA': '$id',
            'INPUT': parameters['parcels'],
            '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(1)
        if feedback.isCanceled():
            return {}

        # Intersection
        alg_params = {
            'INPUT': outputs['FieldCalculator']['OUTPUT'],
            'INPUT_FIELDS': None,
            'OVERLAY': parameters['luhsgexisting'],
            'OVERLAY_FIELDS': parameters['fieldtoaverage1'],
            'OVERLAY_FIELDS_PREFIX': '',
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['Intersection'] = processing.run('native:intersection', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

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

        # Field calculator 2
        alg_params = {
            'FIELD_LENGTH': 10,
            'FIELD_NAME': 'Field1*Area',
            'FIELD_PRECISION': 2,
            'FIELD_TYPE': 0,
            'FORMULA': ' \"fieldtoaverage\"  *  $area',
            'INPUT': outputs['Intersection']['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(3)
        if feedback.isCanceled():
            return {}

        # Statistics by categories
        alg_params = {
            'CATEGORIES_FIELD_NAME': 'FID_Parcels',
            'INPUT': outputs['FieldCalculator2']['OUTPUT'],
            'VALUES_FIELD_NAME': 'Field1*Area',
            'OUTPUT': parameters['Stats']
        }
        outputs['StatisticsByCategories'] = processing.run('qgis:statisticsbycategories', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['Stats'] = outputs['StatisticsByCategories']['OUTPUT']

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

        # Join attributes by field value
        alg_params = {
            'DISCARD_NONMATCHING': False,
            'FIELD': 'FID_Parcels',
            'FIELDS_TO_COPY': 'SUM',
            'FIELD_2': 'FID_Parcels',
            'INPUT': outputs['FieldCalculator']['OUTPUT'],
            'INPUT_2': outputs['StatisticsByCategories']['OUTPUT'],
            'METHOD': 1,
            'PREFIX': 'Stats_',
            'OUTPUT': parameters['Joined']
        }
        outputs['JoinAttributesByFieldValue'] = processing.run('native:joinattributestable', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['Joined'] = outputs['JoinAttributesByFieldValue']['OUTPUT']

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

        # Field calculator 3
        alg_params = {
            'FIELD_LENGTH': 10,
            'FIELD_NAME': 'Field1_Weighted',
            'FIELD_PRECISION': 3,
            'FIELD_TYPE': 0,
            'FORMULA': ' \"Statssum\" / $area',
            'INPUT': outputs['JoinAttributesByFieldValue']['OUTPUT'],
            'NEW_FIELD': True,
            'OUTPUT': parameters['Final']
        }
        outputs['FieldCalculator3'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['Final'] = outputs['FieldCalculator3']['OUTPUT']
        return results

    def name(self):
        return 'Future LU HSG'

    def displayName(self):
        return 'Future LU HSG'

    def group(self):
        return 'QGIS Tools'

    def groupId(self):
        return 'QGIS Tools'

    def createInstance(self):
        return FutureLuHsg()

2voto

Droidnoid Puntos 141

Usted dice: "Lo que estoy teniendo problemas es con la forma de utilizar la entrada del usuario en mis cálculos de campo y nombres de campo".

¿Podría explicar más sobre el problema que está experimentando?

Sobre el tratamiento de los parámetros / entradas del usuario

Se accede a la entrada del usuario mediante parameters[] y output[] . Eso está bien, pero también se puede acceder a los parámetros como se describe en el QGIS manual de usuario . Echa un vistazo a Escribir nuevos algoritmos de Processing como scripts de Python .

Algunos ejemplos de la documentación. Para obtener una fuente de características:

    input_featuresource = self.parameterAsSource(parameters,
                                                 'INPUT',
                                                 context)

Para conseguir un doble:

    doublepar = self.parameterAsDouble(parameters, 'BUFFERDIST',
                                        context)

Supongo que puedes ver el patrón :-). Lo que haces aquí es asignar los valores de tus parámetros de entrada a variables para usarlos en tu script. Colócalas al principio de tu ProcessAlgorithm (antes de que los necesite para sus cálculos).

En cuanto a su pregunta concreta

Para acceder al campo vectorial de entrada se puede utilizar parámetros['campopromedio1']. Algunos ejemplos de su código:

 'FIELD_NAME': parameters['fieldtoaverage1'] + '*Area',

 'FORMULA': parameters['fieldtoaverage1'] + ' * $area',

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X