If you’re reading this, we assume you already know IFC and just want to quickly get started with IfcOpenShell.

This crash course guides you through basic code snippets that give you a general idea of the low-level functionality that IfcOpenShell-python provides. You’ll need to have IfcOpenShell installed and a sample IFC model. To get the most out of it, try out the code yourself and see what results you get!

If you don’t have an IFC model available, here’s a small one for your convenience provided by the Institute for Automation and Applied Informatics (IAI) / Karlsruhe Institute of Technology. It’s in German, so you may need to use some creativity when reading the data :)

Let’s start with loading the model. Import the IfcOpenShell module, then use the open function to load the model into a variable called model.

import ifcopenshell
model = ifcopenshell.open('/path/to/your/model.ifc')

Let’s see what IFC schema we are using:

print(model.schema) # May return IFC2X3, IFC4, or IFC4X3.

Let’s get the first piece of data in our IFC file:

But getting data from beginning to end isn’t too meaningful to humans. What if we knew a GlobalId value instead?

print(model.by_guid('0EI0MSHbX9gg8Fxwar7lL8'))

If we’re not looking specifically for a single element, perhaps let’s see how many walls are in our file, and count them:

walls = model.by_type('IfcWall')
print(len(walls))

Once we have an element, we can see what IFC class it is:

wall = model.by_type('IfcWall')[0]
print(wall.is_a()) # Returns 'IfcWall'

You can also test if it is a certain class, as well as check for parent classes too:

print(wall.is_a('IfcWall')) # Returns True
print(wall.is_a('IfcElement')) # Returns True
print(wall.is_a('IfcWindow')) # Returns False

Let’s quickly check the STEP ID of our element:

Let’s get some attributes of an element. IFC attributes have a particular order. We can access it just like a list, so let’s get the first and third attribute:

print(wall[0]) # The first attribute is the GlobalId
print(wall[2]) # The third attribute is the Name

Knowing the order of attributes is boring and technical. We can access them by name too:

print(wall.GlobalId)
print(wall.Name)

Getting attributes one by one is tedious. Let’s grab them all:

# Gives us a dictionary of attributes, such as:
# {'id': 8, 'type': 'IfcWall', 'GlobalId': '2_qMTAIHrEYu0vYcqK8cBX', ... }
print(wall.get_info())

Let’s see all the properties and quantities associated with this wall:

import ifcopenshell.util
import ifcopenshell.util.element
print(ifcopenshell.util.element.get_psets(wall))

Some attributes are special, called “inverse attributes”. They happen when another element is referencing our element. They can reference it for many reasons, like to define a relationship, such as if they create a void in our wall, join our wall, or define a quantity take-off value for our wall, among others. Just treat them like regular attributes:

Perhaps we want to see all elements which are referencing our wall?

print(model.get_inverse(wall))

Let’s do the opposite, let’s see all the elements which our wall references instead:

print(model.traverse(wall))
# Or, let's just go down one level deep
print(model.traverse(wall, max_levels=1))

If you want to modify data, just assign it to the relevant attribute:

wall.Name = 'My new wall name'

You can also generate a new GlobalId:

wall.GlobalId = ifcopenshell.guid.new()

After modifying some IFC data, you can save it to a new IFC-SPF file:

model.write('/path/to/a/new.ifc')

You can generate a new IFC from scratch too, instead of reading an existing one:

ifc = ifcopenshell.file()
# Or if you want a particular schema:
ifc = ifcopenshell.file(schema='IFC4')

You can create new IFC elements, and add it either to an existing or newly created IFC file object:

# Will return #1=IfcWall($,$,$,$,$,$,$,$,$) - notice all of the attributes are blank!
new_wall = model.createIfcWall()
# Will return a list with our wall in it: [#1=IfcWall($,$,$,$,$,$,$,$,$)]
print(model.by_type('IfcWall'))

Alternatively, you can also use this way to create new elements:

model.create_entity('IfcWall')

Specifying more arguments lets you fill in attributes while creating the element instead of assigning them separately. You specify them in the order of the attributes.

# Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,$,$,$,$,$,$,$)
model.create_entity('IfcWall', ifcopenshell.guid.new())

Again, knowing the order of attributes is difficult, so you can use keyword arguments instead:

# Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,'Wall Name',$,$,$,$,$,$)
model.create_entity('IfcWall', GlobalId=ifcopenshell.guid.new(), Name='Wall Name')

Sometimes, it’s easier to expand a dictionary:

data = {
    'GlobalId': ifcopenshell.guid.new(),
    'Name': 'Wall Name'
}
model.create_entity('IfcWall', **data)

Some attributes of an element aren’t just text, they may be a reference to another element. Easy:

wall = model.createIfcWall()
wall.OwnerHistory = model.createIfcOwnerHistory()

What if we already have an element from one IFC file and want to add it to another?

wall = model.by_type('IfcWall')[0]
new_model = ifcopenshell.file()
new_model.add(wall)

Fed up with an object? Let’s delete it:

This is only a small sample of the basic building blocks of manipulating IFC data. IFC comes with a huge utility library and API for performing common tasks. See Code examples for more.