If you're reading this, we've just migrated servers! If anything looks broken please email dion@thinkmoult.com :)

How to extract the property sets from IFC file

Hi
I have two questions regarding the attached IFC file.
1) How to extract all the property sets from IFC file?
The code I tried is
import ifcopenshell.util
import ifcopenshell.util.element
ifc_file = ifcopenshell.open(input file)
products = ifc_file.by_type('IfcFlowSegment')[0]
line1= ifcopenshell.util.element.get_psets(products)
print (line1)
The output
{'12d Model': {'Geometry': {'id': 60, 'type': 'IfcComplexProperty', 'Name': 'Geometry', 'Description': '12d_attribute_group', 'UsageName': None, 'properties': {'Justification': 'Obvert', 'Start x': 51931.177, 'Start y': 158115.545, 'Start z': 3.403, 'End x': 51923.207, 'End y': 158110.611, 'End z': 3.656}}, 'PUP': {'id': 68, 'type': 'IfcComplexProperty', 'Name': 'PUP', 'Description': '12d_attribute_group', 'UsageName': None, 'properties': {'ID': 'SBCP-L181120-00011025', 'Owner': 'BCC', 'Description': 'PIPE', 'Creator': 'B+B', 'Creation Date': '20181126', 'Creation Source': 'SURVEY', 'AS 4588 Quality': 'B', 'Comment': 'nc', 'Material': 'STEEL'}}, 'Label': {'id': 78, 'type': 'IfcComplexProperty', 'Name': 'Label', 'Description': '12d_attribute_group', 'UsageName': None, 'properties': {'PipeSize': 'Ø100'}}}}
How can I Iterate so that all the property sets are extracted?
2) How can I get the properties in the above output into a dataframe?

Comments

  • The code you've written already extracts all the property sets. I guess your question is how to iterate through the dictionary. Try this (untested):

    psets = ifcopenshell.util.element.get_psets(products)
    
    def print_properties(properties):
        for name, value in properties.items():
            if isinstance(value, dict):
                print(name, 'Complex')
                print_properties(value)
            else:
                print(name, value)
    
    for name, properties in psets.items():
        print('Pset Name', name)
        print_properties(properties)
    

    From this, hopefully you can work out how to get it into data frames.

  • I tried the above code
    Below is the error message I got:
    failed to load properties: 'list' object has no attribute 'is_a'
    Traceback (most recent call last):
    File "C:\Users\Shilpa\anaconda3\envs\myenv\lib\site-packages\ifcopenshell\util\element.py", line 4, in get_psets
    if element.is_a("IfcTypeObject"):
    AttributeError: 'list' object has no attribute 'is_a'

    It worked when I gave the index value [0]

    products = ifc_file.by_type('IfcFlowSegment')[0]
    psets = ifcopenshell.util.element.get_psets(products)

    How can I iterate through the file and extract all the property sets?

  • I could iterate using the for loop
    Thanks for sharing the code.

  • Cheers, glad you got it resolved!

  • Dear Moult and Shilpa, I have tried the codes above on IfcWall and IfcSlab (using an IFC2x3 model). I only get an error message. Please help.
    Below is my screen shot.

  • I used this IFC model

  • get_pset() expects a single element and got a list of walls. Try to get a sigle wall with something like ´get_psets(my_walls[0])´ or a loop.

  • I am grateful for the help
    After reading through the https://wiki.osarch.org/index.php?title=IfcOpenShell_code_examples
    I was able to at least use the sample code to extract the wall pset as dictionary.

    1 These are the imports I am using

    import ifcopenshell
    import ifcopenshell.util
    from ifcopenshell.util.selector import Selector
    from ifcopenshell import util
    import ifcopenshell.util.pset
    import ifcopenshell.util.element
    import pandas as pd

    2 The IFC file I am using as attached

    ifc = ifcopenshell.open('Duplex3.ifc')
    selector = Selector()

    3 The walls and slab using the by_type function

    walls = ifc.by_type('IfcWall')
    slabs = ifc.by_type('IfcSlab')

    4 The iterations for the psets I did.

    for wall in my_walls:
    wall_details = wall.get_info()
    for wall in walls:
    pset_wall = ifcopenshell.util.element.get_psets(wall)

    NOTE: I am trying to extract the quantities of Walls and Slabs and place them in a dataframe.
    I want these to have their GUID.
    I would also like to group all the Walls external walls based on their Cardinal points (south, north, etc)
    once again thank you for your anticipated responses.

  • @Shilpa said:

    I could iterate using the for loop
    Thanks for sharing the code.

    @Shilpa please kindly assist me.

  • edited January 3

    A bit outdated, but perhaps useful for someone.
    What worked for me was (not sure how to format functions here properly)

    def get_properties(inst):
    def get_recursive_props(psets):
    properties = {}
    for name, value in psets.items():
    if isinstance(value, dict):
    properties[name] = get_recursive_props(value)
    else:
    properties[name] = value
    return properties
    return get_recursive_props(ifcopenshell.util.element.get_psets(inst))

    This function can then be called with any ifcopenshell.entity_instance, e.g.

    properties = get_recursive_props(wall)

    The dictionary can then be flattened and converted to a dataframe with something like

    def flatten(d):
    items = []
    for k, v in d.items():
    if isinstance(v, dict):
    items.append((k, 'Complex'))
    for inner_key, inner_value in v.items():
    items.append((inner_key, inner_value))
    else:
    items.append((k, v))
    return dict(items)
    df = pd.DataFrame([flatten(properties])

    Gorgious
  • @ghesselink hi! you can format your code with markdown syntax:

    properties = get_recursive_props(wall)
    
    steverugi
  • I seem to not be able to edit my own post. I didn't realise you can use markdown here.
    The answer with markdown:

    A bit outdated, but perhaps useful for someone.
    What worked for me was (not sure how to format functions here properly)

    def get_properties(inst):
             def get_recursive_props(psets):
                 properties = {}
                 for name, value in psets.items():
                      if isinstance(value, dict):
                          properties[name] = get_recursive_props(value)
                      else:
                           properties[name] = value
                       return properties
                  return get_recursive_props(ifcopenshell.util.element.get_psets(inst))
    

    This function can then be called with any ifcopenshell.entity_instance, e.g.

    properties = get_recursive_props(wall)
    

    The dictionary can then be flattened and converted to a dataframe with something like

    def flatten(d):
        items = []
         for k, v in d.items():
            if isinstance(v, dict):
               items.append((k, 'Complex'))
               for inner_key, inner_value in v.items():
                    items.append((inner_key, inner_value))
            else:
                items.append((k, v))
                return dict(items)
    df = pd.DataFrame([flatten(properties])
    
Sign In or Register to comment.