Get Filter Rule Information

Hello Dynamo Friends :slight_smile:

I can get the categories and the parameter of a filter rule, but how can I get the value ?

all_filters = FilteredElementCollector(doc).OfClass(FilterElement).ToElements()

for filter in all_filters:
    cateoryIds = filter.GetCategories()
    for cateoryId in cateoryIds:
        category = Category.GetCategory(doc,cateoryId)
        category_name = category.Name
            
    paras = filter.GetElementFilterParameters()
    for para in paras:
        parameter_element = doc.GetElement(para)
        parameter_name = doc.GetElement(para).Name

You have to dig deeper, it’s more convoluted than you’d expect (or certainly than I’d expect) :slight_smile:

pfes = FilteredElementCollector(doc).OfClass(ParameterFilterElement).ToElements()
pfe = pfes[0]
elFilter = pfe.GetElementFilter()
filters = elFilter.GetFilters()
filter = filters[0]
rules = filter.GetRules()
rule = rules[0]
ruleString = rule.RuleString

The code is just bare minimum, assuming I’m always interested in the very first element when there’s an array. Just to show the important stuff.

I needed to get this in order, too, so I made this diagram

Btw what Revit version are you using? I’m in 2023 and I don’t see a “Section Type” parameter, only “Family and Type”

Hello Vladimir and thanks for your reply!

Spent a lot time yesterday on apidocs and on google, but it´s all pretty confusing, and as some methods like .GetRules() did not work for me i thought there must have been a lot of changes in the api in the last years and I´m only finding old code…

Will try my luck again and see if your code and diagram will help me understand this whole filter rule stuff.

I´m in Revit 22, the parameter you mentioned is just a project parameter.

On apidocs the ElementFilter Class doesn´t even have a GetFilters() Method.

But it has the following methods:

['Dispose', 'Equals', 'GetFilters', 'GetHashCode', 'GetType', 'Inverted', 'IsValidObject', 'MemberwiseClone', 'PassesFilter', 'ReferenceEquals', 'ReleaseUnmanagedResources', 'SetFilters', 'ToString', '__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

edit:
oops sorry i read too fast
cordially
christian.stan

So this is my current status:
…
Still some things i don´t understand.
I have to get deep down to the rule to get the parameter value, but i get the parameter from the parameter filter element, that can´t be right because every rule could have a different parameter…

edit:

now also works for BuiltInParameters:

parameter_filters = FilteredElementCollector(doc).OfClass(ParameterFilterElement).ToElements()
BIPs = System.Enum.GetValues(BuiltInParameter)

if parameter_filters:
    for parameter_filter in parameter_filters:
        element_filter = parameter_filter.GetElementFilter() #Returns an ElementFilter representing the combination of rules used by this filter.
        if element_filter:
            element_parameter_filters = element_filter.GetFilters() #A filter used to match elements by one or more parameter filter rules.
            for element_parameter_filter in element_parameter_filters:
                rules = element_parameter_filter.GetRules() #Returns the set of rules contained in this filter.
                for rule in rules:
                    if isinstance(rule, Autodesk.Revit.DB.FilterStringRule):
                        value = rule.RuleString
                        evaluator = rule.GetEvaluator()
                    elif isinstance(rule, Autodesk.Revit.DB.FilterValueRule):
                        value = rule.RuleValue
                        evaluator = rule.GetEvaluator()
                    elif isinstance(rule, Autodesk.Revit.DB.FilterElementIdRule):
                        value = rule.RuleValue
                    elif isinstance(rule, Autodesk.Revit.DB.FilterInverseRule):
                        pass
        cateoryIds = parameter_filter.GetCategories()
        for cateoryId in cateoryIds:
            category = Category.GetCategory(doc,cateoryId)
            category_name = category.Name
        outlist =[]
        parameter_ids = parameter_filter.GetElementFilterParameters() #Retrieves a list of the parameters associated with each rule in the filter.
        for parameter_id in parameter_ids:
            if parameter_id.IntegerValue < 0:
                for bip in BIPs:
                    if ElementId(bip) == parameter_id:
                        parameter_element = bip
            else:
                parameter_element = doc.GetElement(parameter_id)
                parameter_name = parameter_element.Name

You can actually get the rule’s parameter, too.

ElementFilter Class doesn´t even have a GetFilters() Method

True, but the LogicalAndFilter does.

Got it all working now, but I´m confused about the ‘FilterInverseRule’.
All filters I want to collect are from the type ‘FilterInverseRule’, I had to get the InnerRule to get my desired informations.

def section_type_filter():

    parameter_filters = FilteredElementCollector(doc).OfClass(ParameterFilterElement).ToElements()

    if parameter_filters:
        for parameter_filter in parameter_filters:
            element_filter = parameter_filter.GetElementFilter() #Returns an ElementFilter representing the combination of rules used by this filter.
            if element_filter:
                element_parameter_filters = element_filter.GetFilters() #A filter used to match elements by one or more parameter filter rules.
                for element_parameter_filter in element_parameter_filters:
                    rules = element_parameter_filter.GetRules() #Returns the set of rules contained in this filter.
                    for rule in rules:
                        if isinstance(rule, Autodesk.Revit.DB.FilterInverseRule):
                            inner_rule = rule.GetInnerRule()
                            if isinstance(inner_rule, Autodesk.Revit.DB.FilterStringRule):
                                value = inner_rule.RuleString
                                parameter_id = rule.GetRuleParameter()
                                if value == section_type_value and parameter_id == section_type_parameter.Id:
                                    return parameter_filter

So far so good, but i really have no idea what this ‘FilterInverseRule’ is, can someone please explain?

This is one of them, what makes this filter to a ‘FilterInverseRule’ and how to create such a filter with the revit UI?

The FilterInverseRule basically changes a rule to its opposite. The inversed rule is defined in the InnerRule of the FilterInverseRule. As an example, the rule shown in your screenshot should be a FilterInverseRule that has a FilterStringEquals rule as its InnerRule. I’m not sure what your end goal is here, but perhaps have a look at the Python code of Clockwork’s ParameterFilterElement.FilterRuleString node. It’s a recursive function that renders the entire filter rule as a human-readable string (see below).
Regarding the second part of your question: Any time you select an operator that contains a “not” in the UI (in your example: “does not equal”), you are using a FilterInverseRule.

Hello @Andreas_Dieckmann

Thanks for taking the time to explain, this helps a lot. :slight_smile:

I see that if I create a not contains rule

parameter_filter_rule = ParameterFilterRuleFactory.CreateNotContainsRule(section_type_parameter.Id, section_type_value, False)

it is a FilterInverseRule object

<Autodesk.Revit.DB.FilterInverseRule object at 0x000000000000134A [Autodesk.Revit.DB.FilterInverseRule]>

So everything alright.