How do I specify the input layer so it refers to the layer from which the function was called (without having to explicitly identify it by name)?
I have written a custom function to use in the expression editor. It returns the rank of each feature based on the specified attribute. For example, if I want to highlight the smallest 10 cities I can use an expression along the lines of: top_rank('citypopulation')<=10
to filter the top 10 ranked features.
The function sort of works, however, if I use it on different layers at the same time the outputs for each layer change. After some consideration, I think it might be due to using aLayer = qgis.utils.iface.activeLayer()
to specify the layer and that each time I select a new layer it changes aLayer
throughout the project.
from qgis.core import *
from qgis.gui import *
from qgis.utils import qgsfunction
from qgis.core import QGis
# this line puts function into 'Custom' group in the expression builder
@qgsfunction(args="auto", group='Custom')
# custom functions must take (fields,feature,parent as arguments)
# usage is : top_rank('attribute_name')
def top_rank(field, feature, parent):
aLayer = qgis.utils.iface.activeLayer()
target_field=feature.fieldNameIndex(field) # gets index of target field - checked
f_id=feature.id() #gets target feature id - checked
aList= [(feat[target_field], feat.id()) for feat in aLayer.getFeatures()]
aList.sort() # sort list of tuples
i = 1
row_index=0
for feat in aList:
if feat[1]==f_id:
row_index=i
i += 1
return(row_index)
(I initially asked this on Stack Overflow but I think it is more relevant here)
(Previously, I have written a function that adds a new column to the attribute table with rank based on an attribute but I don't want to have to add a new column containing the rank for each attribute individually.)
@layer_name
which returns the name of the current layer?youfunc(@layer_name, "Field")
. You will have to pass it in at this stage.