4

I would like to be able to set an expression as the default value of an attribute (in layer properties-->attributes form) which uses an algorithm from the QGIS toolbox.

In this case, the algorithm I want to use is 'Zonal statistics' to calculate the average altitude of polygons (vector layer), based on a DEM (raster layer). I have copied the algorithm from the toolbox function after running it, and attempted to use it in the field calculator in various ways to see if it would work as an expression and it does not.

In other cases, I would also like to know how to use the expression editor to run other processing algorithms or plugins.

I am aware of layer actions and the graphical modeler, but I'd like to use the expression editor if possible (in order to input default values).

0

2 Answers 2

4

Basically this is possible using a custom function. You just have to rebuild the Python syntax. For my testing purposes this worked fine:

from qgis.core import *
from qgis.gui import *
import processing

@qgsfunction(args='auto', group='Custom')
def run_processing_algorithm(algorithmName, algorithmParams, feature, parent):
    algorithm_result = processing.run(algorithmName, algorithmParams)
    result_layer = algorithm_result['OUTPUT']
    result_feature = result_layer.getFeature(feature.id())
    return result_feature

While e.g. using this as expression to return a feature:

run_processing_algorithm(
    'native:zonalstatisticsfb', -- name of the algorithm to run
    map( -- dictionary of parameters
        'COLUMN_PREFIX','_', 
        'INPUT','nameofyourinputlayer',
        'INPUT_RASTER','nameofyourinputraster',
        'OUTPUT','memory:',
        'RASTER_BAND',1,
        'STATISTICS',array(0,1,2)
    )
)

With this feature you can do whatever you want. E.g. return an attribute, its geometry or whatever. To return a specific attribute, combine it with attribute() expression or attributes() to get all fields and values as dictionary/map. For example:

attribute(
    run_processing_algorithm(
        'native:zonalstatisticsfb',
        map(
            'COLUMN_PREFIX','_', 
            'INPUT','zonalstatisticpolygons',
            'INPUT_RASTER','DGM20',
            'OUTPUT','memory:',
            'RASTER_BAND',1,
            'STATISTICS',array(0,1,2)
       )
    ),
    '_sum'
)

enter image description here

Tested this with the native processing algorithms zonalstatisticsfb and buffer in QGIS 3.22. Both work fine, so I guess most algorithms should be usable this way. Note that you can not input a layer by using e.g. @layer as this will return an error; You have to write the layernames as strings.

Also you can of course adjust the custom function to your personal needs or tweak it a little. For example use default settings or add an optional expression as input to pick the feature you want instead of getting the result feature by its id. The latter would e.g. make sense when running qgis:voronoipolygons as here the resulting feature id does not match with the input feature id.

0

That's a great solution, but I think it could fail when there is a fid field with non consecutive numbers. I made this slight modification, and it works fine for me:

from qgis.core import *
from qgis.gui import *
import processing

@qgsfunction(args='auto', group='Custom')
def run_processing_algorithm(meuFeatureId, algorithmName, algorithmParams, feature, parent):
    algorithm_result = processing.run(algorithmName, algorithmParams)
    result_layer = algorithm_result['OUTPUT']
    result_feature = result_layer.getFeature(meuFeatureId)
    return result_feature

And then the expression:

attribute(
    run_processing_algorithm(  @row_number  ,
        'native:zonalstatisticsfb',
        map(
            'COLUMN_PREFIX','_', 
            'INPUT','zonalstatisticpolygons',
            'INPUT_RASTER', 'DGM20',
            'OUTPUT','memory:',
            'RASTER_BAND',1,
            'STATISTICS',array(0,1,2)
       )
    ),
    '_mean'
)

Do you think it is correct?

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.