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
1 Like

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ā€

2 Likes

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.

1 Like

ElementFilter Class doesnĀ“t even have a GetFilters() Method

True, but the LogicalAndFilter does.

1 Like

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.

1 Like

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.