HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Speeding up a length calculation for a QGIS plugin

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
calculationlengthpluginforspeedingqgis

Problem

In a QGIS 2.0 plugin for windows, I calculate length and update a field with the values. It works, but takes a lot of time. Execution for this part only takes about ten minutes. Can anyone suggest anything to speed things up?

def calculatelength(self):
    idx = self.resLayer.fieldNameIndex('Longueur')
    caps = self.resLayer.dataProvider().capabilities()
    features = self.resLayer.getFeatures()
    for feature in features:
        if caps & QgsVectorDataProvider.ChangeAttributeValues:
            fid = feature.id()
            flen = feature.geometry().length()
            attrs = {idx : flen}
            self.resLayer.dataProvider().changeAttributeValues({fid : attrs})

Solution

I'm not familiar with the libraries in question, but it seems to me that you could take a couple of things out from the for loop:

  • The if condition does not look like it would change between iterations.



  • As changeAttributeValues takes a dictionary argument, I would expect it to handle a dictionary with multiple keys as well. Construct a dict with all fid : attrs pairs in the loop and make just one function call after.



My proposal:

def calculatelength(self):
    idx = self.resLayer.fieldNameIndex('Longueur')
    caps = self.resLayer.dataProvider().capabilities()
    if caps & QgsVectorDataProvider.ChangeAttributeValues:
        features = self.resLayer.getFeatures()
        feature_attrs = {}
        for feature in features:
            fid = feature.id()
            flen = feature.geometry().length()
            feature_attrs[fid] = {idx : flen}
        self.resLayer.dataProvider().changeAttributeValues(feature_attrs)

Code Snippets

def calculatelength(self):
    idx = self.resLayer.fieldNameIndex('Longueur')
    caps = self.resLayer.dataProvider().capabilities()
    if caps & QgsVectorDataProvider.ChangeAttributeValues:
        features = self.resLayer.getFeatures()
        feature_attrs = {}
        for feature in features:
            fid = feature.id()
            flen = feature.geometry().length()
            feature_attrs[fid] = {idx : flen}
        self.resLayer.dataProvider().changeAttributeValues(feature_attrs)

Context

StackExchange Code Review Q#64482, answer score: 2

Revisions (0)

No revisions yet.