Selector syntax¶
A common task in querying IFC models is to filter or search for elements which match particular criteria. For example, you might want to find all plasterboard walls with a 2 hour fire rating on level 3.
Alternatively, you might want to fetch some data about a single element. For example, you might want to fetch the fire rating property of an element, or the type description of an element, or the net volume of a list of elements.
Once you’ve retreived your data, you might want to format it in some way. You might want to ensure that all names are always uppercase. Or you might want to take length values defined in feet, and apply imperial formatting such that it shows both feet and inches including fractions.
These three usecases of filtering, getting a value, and formatting that value are common and used in many utilities, such as in Bonsai, IfcCSV, IfcDiff, IfcClash, IfcPatch, and IfcFM.
IfcOpenShell provides a custom syntax to consistently and concisely describe filters, value queries, and formatting rules.
Filtering elements¶
Filtering is typically used to select any IFC element or type.
import ifcopenshell
import ifcopenshell.util.selector
model = ifcopenshell.open("model.ifc")
# Get all concrete walls and slabs.
ifcopenshell.util.selector.filter_elements(model, "IfcWall, IfcSlab, material=concrete")
Example Query |
Description |
---|---|
|
All physical IfcElements including subclasses like walls, doors, windows, etc. Yep, that’s it! Nothing else. Literally just |
|
All walls and slabs. Technically, this is either a wall or a slab, but it’s easier to describe it as all walls and slabs |
|
All walls made out of concrete and slabs made out of concrete. The material checks any assigned IfcMaterial with a matching name or category attribute. |
|
A single element. Yep, just the GlobalId, nothing else! Easy. |
|
A bunch of arbitrary elements. |
|
All walls except that one element. |
|
All elements except for walls. |
|
Any doors named D01, notice how attributes match the IFC Attribute naming exactly |
|
Any doors with the naming scheme of D followed by two numbers: |
|
Any 2 hour fire rated wall |
|
Any load bearing structure |
|
Any element with a fire rating property |
|
Any walls of wall type WT01 on level 3 (we quote Level 3 since it has a space) |
|
Any maintainable product according to Uniclass tables |
|
Notice how there are intuitive rules that class and instance filters are OR whereas other filters are AND So here is any wall or slab except that one element that has a material of concrete and has a 2 hour fire rating |
|
Finally, you can union facet lists together. So here is all concrete slabs, as well as all doors (regardless of concrete) |
|
Here’s another example of unioning facet groups. All doors and window, and all concrete walls and slabs, plus that one random element |
|
Locations bubble up the hierarchy. So if a pump is in a space and that space is on Level 3, then you can say “all pumps on level 3” which will include that pump in the space. |
The filter elements syntax works by specifying one or more groups of filters
separated by a +
character. Each filter group will return a set of filtered
elements, and these are unioned together.
filter_group[ + filter_group]*
A filter group consists of one or more filters separated by a ,
character.
The filters are chained and apply from left to right.
filter[, filter]*
There are nine types of filters to choose from. Some of these filters will add new elements to your filter group, and some will filter previously added elements in your filter group based on their criteria.
Filter |
Type |
Usage |
Example |
---|---|---|---|
Class |
Add |
|
|
GlobalId |
Add |
|
|
Attribute |
Filter |
|
|
Property |
Filter |
|
|
Type |
Filter |
|
|
Material |
Filter |
|
|
Classification |
Filter |
|
|
Location |
Filter |
|
|
Parent |
Filter |
|
|
Query |
Filter |
|
|
When you specify a filter with a {{=}}
check, you can choose from one of
the following comparison checks:
Comparison |
Description |
---|---|
|
Must equal the value. The data type of the value is automatically converted to match. |
|
Must not equal the value. |
|
Must be greater than the value. |
|
Must be greater than or equal to the value. |
|
Must be less than the value. |
|
Must be less than or equal to the value. |
|
Must contain the value. |
|
Must not contain the value. |
When you specify a {{pset}}
, {{prop}}
, or {{value}}
, there are
three ways you can do so:
Value Type |
Example |
Description |
---|---|---|
Quoted string |
|
The value must be in double quotes. The value may contain spaces, symbols, and other characters. If you need to use a double quote, you can escape it with a backslash. This is the safest, most general way to specify a value. |
Unquoted string |
|
For convenience, if you have a simple value which contains no spaces or special characters, you are free to specify it as an unquoted string. |
Regex string |
|
You may specify a Python-compatible regex pattern delimited by forward slashes. You can learn more about regular expressions from Beginners Regex tutorial and Online Regex testing website. |
Getting element values¶
Given a single element, this syntax provides a simple way to extract a value without needing to write complex code for it.
import ifcopenshell
import ifcopenshell.util.selector
# Get the Name attribute of the wall's type.
ifcopenshell.util.selector.get_element_value(wall, "type.Name")
Example Query |
Description |
---|---|
|
Get the IFC class of the element. |
|
Get the |
|
Get the value of the |
|
Get the value of the |
|
Get the |
|
Count the number of occurrences of a type. |
|
Get the |
|
Count the number of materials assigned to an element. |
|
Get the name of the assigned material. |
|
Get the name of the first item in a material set (e.g. the first material layer) |
The element value syntax works by specifying one or more query keys separated
by a .
character. Each query key returns data based of the results of the
previous key.
key[.key]*
Valid keys are:
Key |
Description |
---|---|
|
Gets the IFC ID (equivalent to |
|
Gets the IFC class (equivalent to |
|
Gets the predefined type of the element, taking into account inheritance. |
|
Gets the value of the attribute you specify. Attributes always start with an uppercase letter. |
|
This gets the property set with the same name specified in |
|
If the previous key returns a property set, |
|
Gets the relating type of an element occurrence. |
|
Gets the related objects of an element type. |
|
Gets the immediate spatial element that an element is contained in. |
|
Gets the first IfcSpace spatial element that an element is contained in. |
|
Gets the first IfcBuildingStorey spatial element that an element is contained in. |
|
Gets the first IfcBuilding spatial element that an element is contained in. |
|
Gets the first IfcSite spatial element that an element is contained in. |
|
Gets the parent element in the spatial hierarchy. |
|
Gets the element’s classification reference(s) |
|
Gets the element’s group(s) |
|
Gets the element’s system(s). This is a subset of group(s). |
|
Gets the assigned material, which may be a material set. |
|
If the previous key returns a material set, gets the relevant material set items |
|
Gets a list of IfcMaterials assigned directly or indirectly (such as via a material set) to the element |
|
Gets a list of IfcProfileDefs assigned (such as via a material profile) or used (such as in an extrusion) in the element |
|
Gets the X coordinate of the element’s placement |
|
Gets the Y coordinate of the element’s placement |
|
Gets the Z coordinate of the element’s placement |
|
Gets the map easting of the element’s placement |
|
Gets the map northing of the element’s placement |
|
Gets the map elevation of the element’s placement |
|
If the previous key returns multiple things, count that list. Otherwise, return 1. |
|
If the previous key returns multiple things, fetch the |
When you specify a {{pset}}
or {{prop}}
, there are three ways you can
do so:
Value Type |
Example |
Description |
---|---|---|
Quoted string |
|
The value must be in double quotes. The value may contain spaces, symbols, and other characters. If you need to use a double quote, you can escape it with a backslash. This is the safest, most general way to specify a value. |
Unquoted string |
|
For convenience, if you have a simple value which contains no spaces or special characters, you are free to specify it as an unquoted string. |
Regex string |
|
You may specify a Python-compatible regex pattern delimited by forward slashes. You can learn more about regular expressions from Beginners Regex tutorial and Online Regex testing website. |
Formatting¶
Given a value, this syntax allows a simple way to specify a set of formatting rules. This is useful for configuring outputs of how data should be presented.
import ifcopenshell
import ifcopenshell.util.selector
# Get the Name attribute of the wall's type.
value = ifcopenshell.util.selector.get_element_value(wall, "type.Name")
# Always display names in uppercase.
ifcopenshell.util.selector.format(f'upper("{value}")')
Formatting queries are written similar to how you’d write functions or formulas
in spreadsheets. For example upper("foo")
will produce FOO
. You may
nest formulas, for example concat(title("foo"), lower("Bar"))
will produce
Foobar
. Strings must be double quoted.
Function |
Example |
Result |
Description |
---|---|---|---|
|
|
|
Uppercases a string. |
|
|
|
Lowercases a string. |
|
|
|
Titlecases a string. |
|
|
|
Concatenates two or more strings. |
|
|
|
Rounds |
|
|
|
Formats {{value}} with an optional custom {{decimal_separator}} and {{thousands_separator}}. The default separators are |
|
|
|
Rounds |
|
|
|
|