ifcos-syntax-util

star 2

Documents ifcopenshell.util modules for common IFC operations including element utilities, selector syntax, placement helpers, date/unit conversion, cost/schedule utilities, and shape extraction. Activates when extracting data from IFC models, converting units, querying elements with selectors, or working with IFC property sets.

OpenAEC-Foundation By OpenAEC-Foundation schedule Updated 3/6/2026

name: ifcos-syntax-util description: "Documents ifcopenshell.util modules for common IFC operations including element utilities, selector syntax, placement helpers, date/unit conversion, cost/schedule utilities, and shape extraction. Activates when extracting data from IFC models, converting units, querying elements with selectors, or working with IFC property sets." license: MIT compatibility: "Designed for Claude Code. Requires IfcOpenShell Python library." metadata: author: OpenAEC-Foundation version: "1.0"

IfcOpenShell Utility Modules (ifcopenshell.util.*)

Quick Reference

Decision Tree: Choosing the Right Utility Module

What data do you need from an IFC element?
├── Property sets, types, containers, materials?
│   └── ifcopenshell.util.element
│       ├── get_psets()         → all property sets as dict
│       ├── get_pset()          → single property set or property
│       ├── get_type()          → type element (e.g., IfcWallType)
│       ├── get_container()     → spatial container (e.g., IfcBuildingStorey)
│       ├── get_material()      → material assignment
│       ├── get_materials()     → list of individual materials
│       ├── get_decomposition() → child elements
│       └── get_aggregate()     → parent aggregate
│
├── Query/filter elements by criteria?
│   └── ifcopenshell.util.selector
│       └── filter_elements()   → CSS-like query syntax
│
├── Position/coordinates?
│   └── ifcopenshell.util.placement
│       ├── get_local_placement() → 4x4 transformation matrix
│       └── get_storey_elevation() → storey Z elevation
│
├── Unit conversion?
│   └── ifcopenshell.util.unit
│       ├── calculate_unit_scale() → scale factor to SI metres
│       ├── convert()              → value between unit systems
│       └── get_project_unit()     → project's default unit
│
├── Dates, durations, timestamps?
│   └── ifcopenshell.util.date
│       ├── ifc2datetime()  → IFC date → Python datetime
│       └── datetime2ifc()  → Python datetime → IFC format
│
├── Geometry metrics (area, volume, bbox)?
│   └── ifcopenshell.util.shape (requires processed geometry)
│       ├── get_volume()    → element volume
│       ├── get_area()      → surface area
│       ├── get_bbox()      → bounding box
│       └── get_vertices()  → vertex coordinates
│
├── Classification references?
│   └── ifcopenshell.util.classification
│       ├── get_references() → classification refs for element
│       └── get_classification() → parent classification system
│
├── Cost data?
│   └── ifcopenshell.util.cost
│       ├── get_cost_items_for_product() → cost items linked to product
│       └── get_cost_values()            → cost item values
│
├── Schedule/sequence data?
│   └── ifcopenshell.util.sequence
│       ├── get_tasks_for_product() → tasks linked to product
│       └── count_working_days()    → working days between dates
│
└── Schema introspection (attribute types, enums)?
    └── ifcopenshell.util.attribute
        ├── get_primitive_type() → Python type for IFC attribute
        └── get_enum_items()    → enum options for attribute

Critical Warnings

  • ALWAYS import utility modules explicitly: import ifcopenshell.util.element, NOT from ifcopenshell.util import *.
  • ALWAYS multiply raw coordinate values by calculate_unit_scale(model) to get SI metres. IFC files store coordinates in project units (millimetres, feet, etc.).
  • ALWAYS use filter_elements() (modern API) for selector queries. NEVER use the deprecated Selector().parse() class.
  • NEVER traverse IFC inverse relationships manually when a ifcopenshell.util.element helper exists. Manual traversal is error-prone and schema-dependent.
  • NEVER assume property set names are standardized. Custom property sets vary per project. ALWAYS check for None returns.
  • ALWAYS check model.schema before using schema-specific property set names (e.g., Pset_WallCommon exists in IFC4 but attribute names differ from IFC2X3).
  • NEVER call ifcopenshell.util.shape functions without first processing geometry via ifcopenshell.geom. Shape utilities operate on processed geometry objects, NOT raw IFC entities.

Essential Patterns

Pattern 1: Extract All Properties from an Element

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.element

model = ifcopenshell.open("model.ifc")
wall = model.by_type("IfcWall")[0]

# All property sets (excludes quantity sets by default)
psets = ifcopenshell.util.element.get_psets(wall)
# Returns: {"Pset_WallCommon": {"id": 42, "IsExternal": True, ...}, ...}

# Include quantity sets
all_props = ifcopenshell.util.element.get_psets(wall, psets_only=False)

# Only quantity sets
qsets = ifcopenshell.util.element.get_psets(wall, qtos_only=True)

# Single property set by name
wall_common = ifcopenshell.util.element.get_pset(wall, "Pset_WallCommon")
# Returns dict or None

# Single property value
is_external = ifcopenshell.util.element.get_pset(
    wall, "Pset_WallCommon", "IsExternal")
# Returns value or None

Pattern 2: Navigate Element Relationships

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.element

model = ifcopenshell.open("model.ifc")
wall = model.by_type("IfcWall")[0]

# Type element (IfcWallType, IfcDoorType, etc.)
wall_type = ifcopenshell.util.element.get_type(wall)

# Spatial container (IfcBuildingStorey, IfcSpace, etc.)
container = ifcopenshell.util.element.get_container(wall)

# Material assignment
material = ifcopenshell.util.element.get_material(wall)

# Individual materials as flat list
materials = ifcopenshell.util.element.get_materials(wall)

# Parent aggregate
parent = ifcopenshell.util.element.get_aggregate(wall)

# Child elements (decomposition)
building = model.by_type("IfcBuilding")[0]
children = ifcopenshell.util.element.get_decomposition(building)

Pattern 3: Filter Elements with Selector Queries

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.selector

model = ifcopenshell.open("model.ifc")

# By IFC class
walls = ifcopenshell.util.selector.filter_elements(model, "IfcWall")

# Multiple classes
elements = ifcopenshell.util.selector.filter_elements(
    model, "IfcWall, IfcSlab")

# By attribute value
named = ifcopenshell.util.selector.filter_elements(
    model, 'IfcWall, Name="External Wall"')

# By property set value
external = ifcopenshell.util.selector.filter_elements(
    model, 'IfcWall, /Pset_WallCommon/.IsExternal = True')

# By spatial container
ground = ifcopenshell.util.selector.filter_elements(
    model, 'IfcBuildingElement, container="Ground Floor"')

# By material
concrete = ifcopenshell.util.selector.filter_elements(
    model, 'IfcElement, material="Concrete"')

# By type name
typed = ifcopenshell.util.selector.filter_elements(
    model, 'IfcWall, type="WT01"')

# Partial match (contains)
ext_walls = ifcopenshell.util.selector.filter_elements(
    model, 'IfcWall, Name *= "EXT"')

# Exclusion
non_slabs = ifcopenshell.util.selector.filter_elements(
    model, "! IfcSlab")

Pattern 4: Unit Conversion

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.unit

model = ifcopenshell.open("model.ifc")

# CRITICAL: Get scale factor from project units to SI metres
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(model)
# Millimetres → 0.001, Metres → 1.0, Feet → 0.3048

# Convert raw coordinate to metres
raw_length = 5000.0  # e.g., value from IFC file in mm
length_metres = raw_length * unit_scale

# Get project's length unit entity
length_unit = ifcopenshell.util.unit.get_project_unit(model, "LENGTHUNIT")

# Convert between specific units
value_mm = ifcopenshell.util.unit.convert(
    value=1.0,
    from_prefix=None, from_unit="METRE",
    to_prefix="MILLI", to_unit="METRE"
)  # Returns 1000.0

Pattern 5: Get Element Placement

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.placement

model = ifcopenshell.open("model.ifc")
wall = model.by_type("IfcWall")[0]

# Get absolute 4x4 transformation matrix
matrix = ifcopenshell.util.placement.get_local_placement(
    wall.ObjectPlacement)
# Returns numpy 4x4 ndarray

# Extract position
x, y, z = matrix[0][3], matrix[1][3], matrix[2][3]

# Extract rotation (3x3 submatrix)
rotation = matrix[:3, :3]

# Storey elevation
storey = model.by_type("IfcBuildingStorey")[0]
elevation = ifcopenshell.util.placement.get_storey_elevation(storey)

Pattern 6: Date Conversion

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.date
from datetime import datetime

model = ifcopenshell.open("model.ifc")

# IFC timestamp → Python datetime
owner = model.by_type("IfcOwnerHistory")[0]
if owner.CreationDate:
    dt = ifcopenshell.util.date.ifc2datetime(owner.CreationDate)

# IFC date string → Python date
py_date = ifcopenshell.util.date.ifc2datetime("2024-06-15")

# IFC duration → Python timedelta
duration = ifcopenshell.util.date.ifc2datetime("P30D")

# Python datetime → IFC format
ifc_dt = ifcopenshell.util.date.datetime2ifc(
    datetime(2024, 6, 15, 10, 30), "IfcDateTime")
# Returns "2024-06-15T10:30:00"

ifc_date = ifcopenshell.util.date.datetime2ifc(
    datetime(2024, 6, 15), "IfcDate")
# Returns "2024-06-15"

Common Operations

Classification Lookup

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.classification

model = ifcopenshell.open("model.ifc")
wall = model.by_type("IfcWall")[0]

refs = ifcopenshell.util.classification.get_references(wall)
for ref in refs:
    classification = ifcopenshell.util.classification.get_classification(ref)
    print(f"{classification.Name}: {ref.Identification} - {ref.Name}")

Cost Item Lookup

# IfcOpenShell — IFC4/IFC4X3 (cost entities not in IFC2X3)
import ifcopenshell
import ifcopenshell.util.cost

model = ifcopenshell.open("model.ifc")
wall = model.by_type("IfcWall")[0]

cost_items = ifcopenshell.util.cost.get_cost_items_for_product(wall)
for item in cost_items:
    values = ifcopenshell.util.cost.get_cost_values(item)
    schedule = ifcopenshell.util.cost.get_cost_schedule(item)

Schedule Task Lookup

# IfcOpenShell — IFC4/IFC4X3
import ifcopenshell
import ifcopenshell.util.sequence

model = ifcopenshell.open("model.ifc")

schedules = model.by_type("IfcWorkSchedule")
for schedule in schedules:
    for task in ifcopenshell.util.sequence.get_root_tasks(schedule):
        print(f"Task: {task.Name}")
        calendar = ifcopenshell.util.sequence.get_calendar(task)
        nested = ifcopenshell.util.sequence.get_nested_tasks(task)

Attribute Schema Introspection

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.attribute

# Get primitive Python type for an IFC attribute
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name("IFC4")
entity_decl = schema.declaration_by_name("IfcWall")
attr = entity_decl.all_attributes()[1]  # e.g., Name attribute
ptype = ifcopenshell.util.attribute.get_primitive_type(attr)

# Get enum options
enum_attr = entity_decl.all_attributes()[7]  # PredefinedType
items = ifcopenshell.util.attribute.get_enum_items(enum_attr)

Geometry Extraction (Requires Processed Shapes)

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.geom
import ifcopenshell.util.shape

model = ifcopenshell.open("model.ifc")
settings = ifcopenshell.geom.settings()
settings.set(settings.USE_WORLD_COORDS, True)

wall = model.by_type("IfcWall")[0]

# REQUIRED: Process geometry first
shape = ifcopenshell.geom.create_shape(settings, wall)

# Now use shape utilities
volume = ifcopenshell.util.shape.get_volume(shape.geometry)
area = ifcopenshell.util.shape.get_area(shape.geometry)
vertices = ifcopenshell.util.shape.get_vertices(shape.geometry)
bbox = ifcopenshell.util.shape.get_bbox(shape.geometry)
bottom_z = ifcopenshell.util.shape.get_bottom_elevation(shape.geometry)
top_z = ifcopenshell.util.shape.get_top_elevation(shape.geometry)

Copy/Duplicate Elements

# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.util.element

model = ifcopenshell.open("model.ifc")
wall = model.by_type("IfcWall")[0]

# Shallow copy (new GlobalId, same relationships)
new_wall = ifcopenshell.util.element.copy(model, wall)

# Deep copy (copies element + directly related subelements)
deep_wall = ifcopenshell.util.element.copy_deep(model, wall)

Selector Query Syntax Reference

Syntax Meaning Example
IfcType Select by IFC class "IfcWall"
IfcType, IfcType Multiple classes "IfcWall, IfcSlab"
, Name="X" Filter by Name equals 'IfcWall, Name="W01"'
, Name *= "X" Name contains 'IfcWall, Name *= "EXT"'
, Name != None Attribute is not null 'IfcWall, Name != None'
, /Pset/.Prop = val Filter by property value 'IfcWall, /Pset_WallCommon/.IsExternal = True'
, type="X" Filter by type name 'IfcWall, type="WT01"'
, container="X" Filter by spatial container 'IfcElement, container="Level 1"'
, material="X" Filter by material 'IfcElement, material="Concrete"'
! IfcType Exclude class "! IfcSlab"

Module Summary Table

Module Import Primary Functions Schema Sensitivity
element ifcopenshell.util.element get_psets, get_type, get_container, get_material Low — works across all schemas
selector ifcopenshell.util.selector filter_elements, get_element_value Low — query syntax is schema-agnostic
placement ifcopenshell.util.placement get_local_placement, get_storey_elevation Low — placement structure is consistent
unit ifcopenshell.util.unit calculate_unit_scale, convert, get_project_unit Low — unit types are consistent
date ifcopenshell.util.date ifc2datetime, datetime2ifc Medium — IfcCalendarDate is IFC2X3 only
shape ifcopenshell.util.shape get_volume, get_area, get_bbox, get_vertices Low — operates on processed geometry
classification ifcopenshell.util.classification get_references, get_classification Low
cost ifcopenshell.util.cost get_cost_items_for_product, get_cost_values High — IFC4+ only
sequence ifcopenshell.util.sequence get_root_tasks, count_working_days High — IFC4+ only
attribute ifcopenshell.util.attribute get_primitive_type, get_enum_items Low — schema introspection

Version Notes

IFC2X3 Limitations

  • IfcCalendarDate entity used instead of ISO 8601 date strings. Use ifc2datetime() which handles both.
  • Cost scheduling entities (IfcCostSchedule, IfcCostItem) exist but with fewer attributes.
  • IfcTask has a different attribute structure (no TaskTime in IFC2X3).

IFC4 vs IFC4X3

  • IFC4X3 adds IfcAlignment and related entities supported by ifcopenshell.util.alignment.
  • Property set names are consistent between IFC4 and IFC4X3 for building elements.

IfcOpenShell Version Notes

  • filter_elements() replaced Selector().parse(). The Selector class is deprecated.
  • get_pset() (singular) is a convenience wrapper added in recent versions. Falls back to get_psets() if unavailable.

Reference Links

Install via CLI
npx skills add https://github.com/OpenAEC-Foundation/Computational-Design-Day-Delft-March-2026 --skill ifcos-syntax-util
Repository Details
star Stars 2
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
OpenAEC-Foundation
OpenAEC-Foundation Explore all skills →