OSArch Community

Ifcopenshell-Python beginner

  1. S

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

  2. M

    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?

  3. P

    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.

  4. V

    @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

  5. V

    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:
  6. P

    @vpajic Thank you for the response. I will try to do that and give you an update.

  7. B

    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

  8. P

    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.

  9. P

    @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.

  10. P

    @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)
  11. P

    @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)
  12. V

    @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.

  13. V

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

  14. C

    @polsonmila

    How has progress been? :-)

  15. P

    @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.

  16. M

    @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)
    
  17. P

    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.

  18. M

    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?

  19. P

    @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. 
    
  20. G

    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 ?

  21. P

    @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.

  22. M

    @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 :)

  23. P

    @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.

  24. P

    `

    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

    `

  25. P

    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
    
  1. Page 1
  2. 2

Login or Register to reply.