Ifcopenshell-Python beginner

edited September 2022 in General

I am a beginner and want to know related quick getting started articles about Ifcopenshell-Python, thx

Tagged:

Comments

  • Hey @shanmama - did you see some of the links and source code posted here?

    Is there a particular type of data you are trying to extract? Is it geometry? Is it an attribute? Is it a property set? If you're interested, in an online meeting I can do a screenshare and teach a bit about IfcOpenShell-python. Would you participate?

  • Dear all,
    Please Help....
    I am a beginner in using python, IFC and BlenderBim add on. I am trying to do the following;
    1. extract the quantities, material type of walls and floors and place them into a dictionary
    2. extract the quantities of external walls and group them based on their cardinal orientation (south, north, west, etc) of each wall. I do not know if it's workable.

    For the quantities I tried the sample code on https://thinkmoult.com/using-ifcopenshell-parse-ifc-files-python.html but I get an attribute error (as shown below). I just hope I am doing the right thing.

  • @polsonmila at first glance it looks as if you're getting an AttributeError because you're attempting to access quantity.lengthValue instead of quantity.LengthValue -- > the properties all use CamelCase

  • edited November 2021

    Also, you need to loop through each Wall in your Walls list before you try to access .isDefinedBy.
    something like:

    walls = [] # your list of walls
    for wall in walls:
            for definition in wall.IsDefinedBy:
    
  • @vpajic Thank you for the response. I will try to do that and give you an update.

  • BTW: if you post code do not use a screen shot but copy the code and use code tags instead. It looks like in the post of vpajic. If you post a screen shot noone can copy and test your code.

    cheers bernd

  • edited November 2021

    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.

    #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
    
    # The IFC file I am using as attached
    ifc = ifcopenshell.open('Duplex3.ifc')
    selector = Selector()
    
    # The walls and slab using the by_type function
    walls = ifc.by_type('IfcWall')
    slabs = ifc.by_type('IfcSlab')
    
    # 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.

  • edited November 2021

    @vpajic said:
    Also, you need to loop through each Wall in your Walls list before you try to access .isDefinedBy.
    something like:

        walls = [] # your list of walls
    for wall in walls:
            for definition in wall.IsDefinedBy:
    

    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.

  • @vpajic Thank you. I am relatively new to both Python and IfcOpenshell. I am now exploring my way through (as I go through the Wiki.osarch.org tutorials. I was able use the get_info and loop through (as shown below). But I as you suggested, I also observed that I could loop through the wall list from the wall.by_type function call. I will work on it so that I can try accessing the IsDefinedBy.
    Well this is how far I have gone.

    import ifcopenshell
    import pandas as pd
    m = ifcopenshell.open("data/Duplex_A.ifc")
    #m = ifcopenshell.open("../data/231110AC-11-Smiley-West-04-07-2007.ifc")
    walls = m.by_type('IfcWall')
    #print (walls)
    #count = 0
    for wall in walls:
        #count += 1
        wall_details = wall.get_info()
        #print(wall_details)
        wall_details_edit = {str(key): str(value) for key, value in wall_details.items()}
        #print(wall_details_edit)
        wall_details_edit_df = pd.DataFrame(wall_details_edit, index = [0])
        print(wall_details_edit_df)    
    #print(count)
    
  • @vpajic Thank you for your comment I still need help...
    @Moult and @bernd kindly assist.
    I am relatively new to both Python and IfcOpenshell. I am now exploring my way through (as I go through the Wiki.osarch.org tutorials. I was able use the get_info and loop through (as shown below). But I as @vpajic suggested, I also observed that I could loop through the wall list from the wall.by_type function call. I will work on it so that I can try accessing the IsDefinedBy.
    Well, this is how far I have gone.
    I have been able to have the loop through to get the property set of one wall using the IsDefinedBy procedure. But I could not access the Quantities. Please, can someone help me to identify where I am getting things wrong?

    '''I am trying to access all the propeties and quantities of the walls
    using an IFC 2x3 file format but???? please help'''
    
    ifc = ifcopenshell.open('Duplex3.ifc')
    #the walls from the model
    walls = ifc.by_type('IfcWall')
    
    #the single wall I am considering since the loop for properties has no IsDefinedBy
    wall_1 = walls[0]
    a = wall_1.IsDefinedBy
    print(a)
    
    '''the for loop I used to track the inverse IsDefineBy as in the tutorials
    all went well and I am still exploring''' 
    for i in a:
        if i.is_a('IfcRelDefinesByProperties'):
            a_property_set = i.RelatingPropertyDefinition
            #print(a_property_set.Name) # Might return Pset_WallCommon
            for property in a_property_set.HasProperties:
                if property.is_a('IfcPropertySingleValue'):
                    #print(property.Name)
                    print(property.NominalValue.wrappedValue)
    
    '''this is the point where I am stuck, I have tried many approaches but I couldn't get the Quantities of the wall following the tutorial'''
    for i in a:
        #if i.is_a('IfcRelDefinesByProperties'):
        a_property_set = i.RelatingPropertyDefinition
        if property.is_a('IfcElementQuantity'):
            print(property.Name)
            for quantity in property.Quantities:
                print(quantity.Name)
                if quantity.is_a('IfcQuantityLength'):
                    print(quantity.LengthValue)
    
  • @polsonmila - i would heartily recommend having a look at . Using the console in blender will allow you to explore the commands and structure of ifcopenshell more intuitively.

    bruno_perdigao
  • In your last example, it seems to me you are trying to access property.is_a('IfcElementQuantity'): without having first defined 'property'

  • @polsonmila

    How has progress been? :-)

  • @Coen thank you for your follow-up question. I followed the YouTube video tutorial specified by @vpajic it has been helpful. Though, I will still need help.

  • @polsonmila have you considered using the util module? To get properties and quantities you can just do it in one line of code:

    ifcopenshell.util.element.get_psets(wall)
    # Or if you want to limit it to quantities:
    ifcopenshell.util.element.get_psets(wall, qtos_only=True)
    
  • edited February 2022

    I want to extract the data from the IFC 2x3 format and place them in a data frame.
    1. I used the util.get_psets() function to get the property sets of all the walls in a particular building but I could not loop through the walls and place them into a data frame. I could only do that for one wall (as shown in the code below).
    2. I want to extract the external walls within an IFC 2x3 specifying the cardinal orientation of the external faces of the walls with respect to the Project North (e.g. North-west, North-south, North). If you have any idea on how to extract these details, I will be grateful.

    Code for question 1
    `#The IFC 2x3 model
    model_name = 'Duplex_A.ifc'
    model = ifcopenshell.open(model_name)

    The walls by_type

    walls = model.by_type('IfcWall')

    count = 0

    Iterating through the walls

    for wall in walls:
    wall_sets_dict = {}
    #count += 1

    The util.get_psets function

    wall_sets_fulldict = util.get_psets(wall, psets_only=True, qtos_only=False)
    wall_sets_dict.update(wall_sets_fulldict) # I updated the dictionary
    #print (wall_sets_dict)
    #I tried to make the dictionary into an organised pattern but this gives me an error????
    for wall_set in wall_sets_dict:
        for outerKey, innerDict in wall_sets_dict.items():
            for innerKey, values in innerDict.items():
                wall_sets_dict[(outerKey, innerKey)] = values
                #print(wall_sets_dict)
    

    `
    Question 2
    ????

    NOTE: I added a note pad for further details and the IFC 2x3 file.

  • I've never seen a dataframe before, what's the structure you need in the end? Is is a dictionary? List? What should it look like?

  • edited February 2022

    @Moult please pardon my miscommunication (I am a beginner). I meant a pandas data frame. I was able to use the util.get_psets for only one wall and derived a multi-index data frame (as shown in the code below)

    #A sample of Pset from the util.get_pset. I placed it as a dictionary
    nest_dict = {'Pset_WallCommon': {'Reference': 'Basic Wall:Interior - Partition (92mm Stud)', 'LoadBearing': False,
                                     'ExtendToStructure': False, 'IsExternal': False, 'id': 4093},
                 'PSet_Revit_Constraints': {'Location Line': 2, 'Base Constraint': 'Level 1', 'Base Offset': 0.0,
                                            'Base is Attached': False, 'Base Extension Distance': 0.0,
                                            'Top Constraint': 'Up to level: Level 2',
                                            'Unconnected Height': 2.795000000000196, 'Top Offset': -0.3050000000000001,
                                            'Top is Attached': False, 'Top Extension Distance': 0.0, 'Room Bounding': True,
                                            'Related to Mass': False, 'id': 4142},
                 'PSet_Revit_Other': {'InstallationDate': 'InstallationDate', 'SerialNumber': 'SerialNumber',
                                      'WarrantyStartDate': 'WarrantyStartDate', 'BarCode': 'BarCode',
                                      'AssetIdentifier': 'AssetIdentifier', 'TagNumber': 'TagNumber', 'id': 4144},
                 'PSet_Revit_Phasing': {'Phase Created': 'New Construction', 'id': 4146},
                 'PSet_Revit_Structural': {'Structural Usage': 0, 'id': 4148},
                 'PSet_Revit_Dimensions': {'Length': 3.791499999999996, 'Area': 10.01448500000069,
                                           'Volume': 1.241796140000085, 'id': 4150},
                 'PSet_Revit_Type_Construction': {'Wrapping at Inserts': 0, 'Wrapping at Ends': 2, 'Width': 0.124,
                                                  'Function': 0, 'id': 4152},
                 'PSet_Revit_Type_Graphics': {'Coarse Scale Fill Color': 0, 'id': 4153},
                 'PSet_Revit_Type_Identity Data': {'Manufacturer': 'Manufacturer', 'Assembly Description': '',
                                                   'Assembly Code': '', 'id': 4154},
                 'PSet_Revit_Type_Other': {'AccessibilityPerformance': 'AccessibilityPerformance',
                                           'CodePerformance': 'CodePerformance', 'Color': 'Color',
                                           'Constituents': 'Constituents', 'Features': 'Features', 'Finish': 'Finish',
                                           'Grade': 'Grade', 'Material': 'Material', 'ModelReference': 'ModelReference',
                                           'NominalHeight': 'NominalHeight', 'NominalLength': 'NominalLength',
                                           'NominalWidth': 'NominalWidth', 'ProductionYear': 'ProductionYear',
                                           'Reference': 'Reference', 'Shape': 'Shape', 'Size': 'Size',
                                           'SustainabilityPerformance': 'SustainabilityPerformance',
                                           'WarrantyDescription': 'WarrantyDescription',
                                           'WarrantyDurationLabor': 'WarrantyDurationLabor',
                                           'WarrantyDurationParts': 'WarrantyDurationParts',
                                           'WarrantyGuarantorLabor': 'WarrantyGuarantorLabor',
                                           'WarrantyGuarantorParts': 'WarrantyGuarantorParts', 'ModelNumber': 'ModelNumber',
                                           'ExpectedLife': 'ExpectedLife', 'ReplacementCost': 'ReplacementCost',
                                           'AssetAccountingType': 'FIXED', 'id': 4155}}
    ![](https://community.osarch.org/uploads/editor/x6/cs1risl99bqg.png "")
    #I used this code to generate a data frame
    reformed_dict = {}
    for outerKey, innerDict in nest_dict.items():
        for innerKey, values in innerDict.items():
            reformed_dict[(outerKey, innerKey)] = values
    df1 = pd.DataFrame.from_dict(reformed_dict, orient='index').transpose()
    df1.columns = pd.MultiIndex.from_tuples(df1.columns)
    df1
    # But I want to iterate not just one wall pset but all the walls. 
    
  • edited February 2022

    Looks like you're overwriting your dictionary for each wall, maybe you want to create a list of dictionaries and flatten it at the end ? or a dict of dicts with the guid as a key ?

  • edited February 2022

    @Gorgious I will try your suggestion. Though I tried making a list and or dict of dict (but I got error!)....may be due to beginner level in python & ifcopenshell. I think flattening might change its default structure from the util.get_pset function output.

  • @polsonmila if you manually type out a list / dict with sample data of the structure you're after for your data frame, perhaps we can help :)

  • @Moult and @Gorgious I have been able to create a list of dictionaries (nested dictionaries) from the util.get_pset(). But I still get a runtime error if I iterate through the list.

  • edited February 2022

    `
    I have the following as a list of nested dictionaries. I want to loop through it and create a multi index data frame. But I always get a runtime error.
    Here is the sample list of nested dictionaies and the code I used.

    sample_list_of_nestdict = [{'Pset_WallCommon': {'Reference': 'Basic Wall:Interior - Partition (92mm Stud)',
            'LoadBearing': False, 'ExtendToStructure': False, 'IsExternal': False, 'id': 4093},
            'PSet_Revit_Constraints': {'Location Line': 2, 'Base Constraint': 'Level 1', 
            'Base Offset': 0.0, 'Base is Attached': False, 'Base Extension Distance': 0.0, 
            'Top Constraint': 'Up to level: Level 2', 'Unconnected Height': 2.795000000000196, 
            'Top Offset': -0.3050000000000001, 'Top is Attached': False, 'Top Extension Distance': 0.0, 
            'Room Bounding': True, 'Related to Mass': False, 'id': 4142},  
            'PSet_Revit_Phasing': {'Phase Created': 'New Construction', 'id': 4146}, 
            'PSet_Revit_Structural': {'Structural Usage': 0, 'id': 4148}, 
            'PSet_Revit_Dimensions': {'Length': 3.791499999999996, 'Area': 10.01448500000069, 'Volume': 1.241796140000085, 'id': 4150}},
            {'Pset_WallCommon': {'Reference': 'Basic Wall:Party Wall - CMU Residential Unit Dimising Wall', 
            'LoadBearing': False, 'ExtendToStructure': False, 'IsExternal': True, 'id': 4246}, 
            'PSet_Revit_Constraints': {'Location Line': 0, 'Base Constraint': 'Level 1', 
            'Base Offset': 0.0, 'Base is Attached': False, 'Base Extension Distance': 0.0, 
            'Top Constraint': 'Up to level: Level 2', 'Unconnected Height': 2.795000000000196, 
            'Top Offset': -0.3050000000000002, 'Top is Attached': False, 'Top Extension Distance': 0.0, 
            'Room Bounding': True, 'Related to Mass': False, 'id': 4294}, 
            'PSet_Revit_Phasing': {'Phase Created': 'New Construction', 'id': 4298}, 
            'PSet_Revit_Structural': {'Structural Usage': 0, 'id': 4300}, 
            'PSet_Revit_Dimensions': {'Length': 4.191499999999984, 'Area': 11.74179500000078, 'Volume': 5.788704935000469, 'id': 4302}}]
    
    #The code below only works if I iterate for index[0]. I want to iterate all through the list of nested dictionary
    

    `

  • edited February 2022

    Here is the code I used to iterate only the first index item into a dataframe. But I could not iterate for all.

    reformed_dict = {}
    #Iterating over the sample_list_of_nestdict
     for outerKey, innerDict in sample_list_of_nestdict[0].items:
    for innerKey, values in innerDict.items():
    reformed_dict[(outerKey, innerKey)] = values
    print(reformed_dict)
    #the multi index pandas data frame
    df2 = pd.DataFrame.from_dict(reformed_dict, orient='index').transpose()
    df2.columns = pd.MultiIndex.from_tuples(df2.columns)
    df2
    
  • edited February 2022
    reformed_dict = {}
    #Iterating over the sample_list_of_nestdict
    for outerKey, innerDict in sample_list_of_nestdict[0].items:
        for innerKey, values in innerDict.items():
            reformed_dict[(outerKey, innerKey)] = values
    print(reformed_dict)
    #the multi index pandas data frame
    df2 = pd.DataFrame.from_dict(reformed_dict, orient='index').transpose()
    df2.columns = pd.MultiIndex.from_tuples(df2.columns)
    df2
    
  • I quickly skimmed through the Pandas documentation and perhaps pd.DataFrame.from_records(sample_list_of_nestdict) might be what you're after.

  • Thank you all. @Moult , @Gorgious, @vpajic and @Coen. I have been able to solve the problem. I extracted the wall property set and I am working on them in pandas.
    I am still trying to extract external walls coordinates in relation to the project north. If you have any suggestion, I will appreciate it.
    Thanks.

    Coen
Sign In or Register to comment.