Skip to content

Instantly share code, notes, and snippets.

@MarcoDuiker
Created June 15, 2017 06:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MarcoDuiker/2035bd38ecddbab511c320633fc01a48 to your computer and use it in GitHub Desktop.
Save MarcoDuiker/2035bd38ecddbab511c320633fc01a48 to your computer and use it in GitHub Desktop.
supersum
##clip_layer=optional vector
##filter_expression=optional string
##polygon=boolean True
##point=boolean True
##line=boolean True
##sum_expression=string
##selected_features_only=boolean True
##sum_total=output number
##sum_result_table=output table
from qgis._core import *
from qgis.utils import iface
from processing import *
import csv
# input validation
clip_lyr = None
if clip_layer:
clip_lyr = getObject(clip_layer)
if not clip_lyr.geometryType() == QGis.Polygon:
raise GeoAlgorithmExecutionException("Clip layer must be of type Polygon")
filter_exp = False
if filter_expression:
filter_exp = QgsExpression(filter_expression)
if filter_exp.hasParserError():
raise GeoAlgorithmExecutionException(filter_exp.parserErrorString())
sum_exp = QgsExpression(sum_expression)
if sum_exp.hasParserError():
raise GeoAlgorithmExecutionException(sum_exp.parserErrorString())
# where filter function
def where(layer, exp, selected_features_only):
if selected_features_only:
features = processing.features(layer)
else:
features = layer.getFeatures()
if exp:
exp.prepare(layer.pendingFields())
for feature in features:
if exp:
value = exp.evaluate(feature)
if exp.hasEvalError():
# raise GeoAlgorithmExecutionException(exp.evalErrorString())
progress.setInfo('-->' + 'Warning: ' + exp.evalErrorString())
if bool(value):
yield feature
else:
yield feature
# main
sum_result = {}
sum_total = 0
#loop al selected layers and sum using the sum expression skipping features with the where filter. Optionally clip first
for layer in iface.legendInterface().selectedLayers():
if (layer.geometryType() == 2 and polygon) or (layer.geometryType() == 1 and line) or (layer.geometryType() == 1 and point):
progress.setInfo('Processing layer: ' + layer.name() )
sum_result[layer.name()] = 0
if clip_lyr:
result = processing.runalg('qgis:clip', layer, clip_lyr, None)
layer_to_process = QgsVectorLayer(result["OUTPUT"],'layer_clipped',"ogr")
else:
layer_to_process = layer
sum_exp.prepare(layer_to_process.pendingFields())
for feat in where(layer_to_process, filter_exp, selected_features_only):
value = sum_exp.evaluate(feat)
if sum_exp.hasEvalError():
#raise GeoAlgorithmExecutionException(sum_exp.evalErrorString())
progress.setInfo('-->' + 'Warning: ' + sum_exp.evalErrorString())
elif value:
sum_total = sum_total + value
sum_result[layer.name()] = sum_result[layer.name()] + value
progress.setInfo('-->' + str(sum_result[layer.name()]) )
sum_result['Total'] = sum_total
progress.setInfo('=============================+ ' )
progress.setInfo('Total sum: ' + str(sum_total) )
progress.setInfo(' ')
with open(sum_result_table, 'wt') as f:
writer = csv.writer(f)
writer.writerow( ('Layer', 'Sum') )
for key, value in sum_result.items():
writer.writerow((key,value))
{"ALG_DESC": "Supersum sums an expression over all selected layers. \n\nOptionally the layers will first be clipped with a clip layer. Furthermore there is an option to filter the features by an expression or the type of the layer (point, line or polygon).\n\nExpressions are the usual QGIS expressions.", "sum_total": "The grand total of the sum expression over all selected layers.", "sum_expression": "A valid QGIS expression evaluating to a result which can be summed using the python + operator. Usually a float or an int will do.\n\nExample: $area\n\nTip: Use one of the selected layers and build an expression with the expression builder in the field calculator. Copy and paste the expression in the sum expression field.", "polygon": "When selected polygon layers will be summed.", "clip_layer": "An optional layer to clip the features of the selected layers which will be summed.\n\nOnly features within the clip layer will be summed.", "point": "When selected point layers will be summed.", "ALG_CREATOR": "Marco Duiker -- MD-kwadraat", "filter_expression": "A valid QGIS expression evaluating to True or False. Only records where the filter expression evaluates to True will be summed.\n\nExample: \"Field name\" = 'an interesting value'\n\nTip: Use one of the selected layers and build an expression with the expression builder in the field calculator. Copy and paste the expression in the filter expression field.\n", "ALG_VERSION": "0.3", "ALG_HELP_CREATOR": "Marco Duiker -- MD-kwadraat", "sum_result_table": "A table with layer names and the total of the sum expression for that layer.\n\nAlso a record with the grand total is included.", "line": "When selected line layers will be summed."}
@MarcoDuiker
Copy link
Author

Algorithm description

Supersum sums an expression over all selected layers.

Optionally the layers will first be clipped with a clip layer. Furthermore there is an option to filter the features by an expression or the type of the layer (point, line or polygon).

Expressions are the usual QGIS expressions.

Input parameters

clip layer

An optional layer to clip the features of the selected layers which will be summed.

Only features within the clip layer will be summed.

filter expression

A valid QGIS expression evaluating to True or False. Only records where the filter expression evaluates to True will be summed.

Example: "Field name" = 'an interesting value'

Tip: Use one of the selected layers and build an expression with the expression builder in the field calculator. Copy and paste the expression in the filter expression field.

polygon

When selected polygon layers will be summed.

point

When selected point layers will be summed.

line

When selected line layers will be summed.

sum expression

A valid QGIS expression evaluating to a result which can be summed using the python + operator. Usually a float or an int will do.

Example: $area

Tip: Use one of the selected layers and build an expression with the expression builder in the field calculator. Copy and paste the expression in the sum expression field.
selected features only

Outputs

sum total

The grand total of the sum expression over all selected layers.

sum result table

A table with layer names and the total of the sum expression for that layer.

Also a record with the grand total is included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment