OSArch Community

How to extract the property sets from IFC file

  1. S

    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?

    1. How can I get the properties in the above output into a dataframe?
  2. M

    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.

  3. S

    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?

  4. S

    I could iterate using the for loop

    Thanks for sharing the code.

  5. M

    Cheers, glad you got it resolved!

  6. P

    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.

  7. P

    I used this IFC model

  8. E

    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.

  9. P

    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.

  10. P

    @Shilpa said:

    I could iterate using the for loop

    Thanks for sharing the code.

    @Shilpa please kindly assist me.

  11. G

    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])
  12. A

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

    
    properties = get_recursive_props(wall)
    
  13. G

    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])
    

Login or Register to reply.