IfcOpenShell Python - Calculate Quantities

2»

Comments

  • @Owura_qu ok... but if there was a qto pset associated to the object, it should be listed there...can you share the ifc file?

  • @Massimo said:
    @Owura_qu ok... but if there was a qto pset associated to the object, it should be listed there...can you share the ifc file?

    Kindly find attached the .ifc file for your review. Thank you.

  • @Owura_qu i searched in the file but there is no wall with defined quantities assigned to it...the only object that has quantities assigned to it is a slab named "IfcFooting/FLR250.001".
    If you see quantities in blenderbim panel with a wall selected, maybe the .blend file is not synchronized with the .ifc file so i suggest you to start a new blender session and reload the .ifc file...

  • edited June 2023

    @Massimo How could I ever know this? So what can lead to the .blend and .ifc files not being in sync? Because I saved both files. I need to know how this happens to avoid future occurrences as it is quite frustrating. Pardon me if it sounds too basic to know but it is the first time I am entering the world of BlenderBIM. So much frustration already especially model break-ups and bugs but am not giving up:) as long as a forum like this exists to help newbies. Also, how do you assign quantities to entities? I am from a Revit background and once I have a wall it comes with the quantities already assigned to it as by-products. Thank you very much for your support and attention.

  • @Owura_qu well, so i supposed you found the problem... :-)
    First things first: BBim uses .ifc as native file format so when you model it's always a best practice to save and load the .ifc file from scene properties.
    You can for sure save also the .blend file but always starts from the .ifc file as soon as you can.
    This is because the two files sometimes get asynch...

    The frustration thing is normal in a open source project like this :-) if you want an advice, it starts to disappear when you stop thinking about BBim like it was a copy of a more famous sofware (archicad, revit, etc...). You have to think about it like a software as it is (with its strength and weakness) and learn from the tutorials (the IfcArchitect ones are very clear).

    If you want to assign quantities to selected objects, you can do it from npanel -> blenderbim -> qto take off -> calculate object quantities (or with bim tool enabled just press shift+q). Please note that it follows rules to calculate quantities so maybe they are not suited for you and the resulting value could be wrong for you (also revit does assumptions but you don't know them...); in this case you can check the values and modify them by hand if you need it

    Owura_qu
  • @Massimo Thank you very much and you have saved me many hours if not days of boring Google search and troubleshooting:). I appreciate your help!

    Coen
  • edited June 2023

    Please is there any way to get quantities from IfcMaterialLayer? I have a wall with different material layer sets and need to quantify each material layer. I have searched inside the IFC4 documentation on the buildingSmart website and the only closest thing I could find is Material Thickness under the 4.4.5.2 Material Layer Set. Any help?

  • @Owura_qu hey, sorry for late reply. I don't know really the answer for your question, afaik there is no tool at the moment to do that in BBim.
    The only thing i think it's possible is to write a script to eventually calculate and exctract the quantities you need.
    Which quantities do you need for every layer? If you could send me an .ifc file i could try to write a script to do it...

  • edited June 2023

    @Massimo said:
    …, afaik there is no tool at the moment to do that in BBim.
    The only thing i think it's possible is to write a script to eventually calculate and exctract the quantities you need.

    @Massimo Okay, I need the volume of the layers of walls and I thought the functionality already existed. I have figured out a logic to do that (material layer thickness x NetSideArea of the IfcWall instance). But the challenge is how to extract the LayerThickness of IfcMaterialLayer. I tried the wall.HasAssociations but nothing shows up. Kindly find attached .ifc file for your review. Thank you.

  • @Owura_qu
    There are several methods of extracting the width of walls. What I have done is the following
    1) used BlenderBIM spreadsheet to filter out the walls
    2) Made the BIM tool active with all the walls selected and pressed Shift+Q, this will quantify all the walls
    3) Save the IFC
    4) Exported a new .ods file, with Qto_WallBaseQuantities.Width as a paramter, see screenshot:

    Now you can filter on width using the spreadsheet:

    5) Width selection of 100

    6) Visualize in the blenderbim add-on using Filter IFC elements of the blenderbim spreadsheet add-on

    @Massimo Am I correct in assuming the Shift + Q button takes the width from the IfcMaterialLayerSet width?

    AceNigel
  • @Coen I need the width of each individual material layer in the IfcMaterialLayerSet of the wall (especially for the "SLD150" wall type which has 3 material layers in the layer set). In that way, I can compute the total volume of the construction material needed for that layer. But I must say there is a lot that I have learned looking at your approach and what you achieved. I am a BBim newbie so it's fascinating to see some other possibilities from your work. Thank you very much.

    Coen
  • @Owura_qu

    Maybe this python script is what you're looking for?

    import ifcopenshell
    import blenderbim.tool as tool
    from blenderbim.bim.ifc import IfcStore
    
    
    ifc_file = ifcopenshell.open(IfcStore.path)
    
    products = ifc_file.by_type('IfcWall')
    
    for ifc_product in products:
    
        ifc_material = ifcopenshell.util.element.get_material(ifc_product)
    
        if ifc_material:               
            if ifc_material.is_a('IfcMaterialLayerSetUsage'):
    
                for material_layer in ifc_material.ForLayerSet.MaterialLayers:
                    print (material_layer.Material.Name, material_layer.LayerThickness)
    

    I think you can just run it in Blender and it should work

    After running the script you should see the output in the System Console:

    Owura_quArvemiliotasso
  • @Coen Thank you very much...exactly what I need! I really appreciate it and I hope to learn more about the IfcOpenShell documentation.

    Coen
  • @Massimo Am I correct in assuming the Shift + Q button takes the width from the IfcMaterialLayerSet width?

    @Coen no, at the moment shift+Q executes the bim.calculate_all_quantities() operator.
    In order to know how the width for a wall is calculated you have to look at the mapper here
    https://github.com/IfcOpenShell/IfcOpenShell/blob/b63b4ce326e1825dcdfdece527bb0cdd286a313e/src/blenderbim/blenderbim/bim/module/pset/calc_quantity_function_mapper.py#L381
    In this case, it uses the "get_width" function so look at here:
    https://github.com/IfcOpenShell/IfcOpenShell/blob/b63b4ce326e1825dcdfdece527bb0cdd286a313e/src/blenderbim/blenderbim/bim/module/pset/qto_calculator.py#L202
    So basically it uses the shorter bounding box dimension...

    CoenOwura_quemiliotasso
  • @Coen said:
    @Owura_qu

    Maybe this python script is what you're looking for?
    ```
    import ifcopenshell
    import blenderbim.tool as tool
    from blenderbim.bim.ifc import IfcStore
    ...

    @Coen exactly what i wanted to do :-) i little improvement would be to print also the product name and print a blank line between products, but it's just a minor thing...

    Owura_quCoen
  • edited March 14

    I am trying my hands on simple Python code to extract elements at the foundation storey to retrieve some quantities. Yet, this error has been persistent "AttributeError: entity instance of type 'IFC4.IfcPropertySet' has no attribute 'Quantities'. Eventhough I verified and all elements have their BaseQuantities. So far only three of the elements returned their values. Find the attached file and code below;

    bldg_stories = ifc_model.by_type('IfcBuildingStorey')
    storey_fnd = bldg_stories[-1]
    fnd_elements = storey_fnd.ContainsElements[0].RelatedElements 
    footing_vols = []
    for element in fnd_elements:
        if element.is_a('IfcFooting'): 
            print(element) 
            footing_qty = element.IsDefinedBy[0].RelatingPropertyDefinition.Quantities
            footing_vol = footing_qty[-1].VolumeValue
            print(footing_vol)
        else: 
            continue 
    

    Unfortunately, I don't know how to indent the code in the textbox. Any insight is appreciated.
    RESPONSE;
    Thank you @steverugi and @Massimo. I was using just one backtick previously.

  • edited March 14

    hi @Owura_qu

    I am trying my hands on simple Python code to extract elements at the foundation storey to retrieve some quantities. Yet, this error has been persistent "AttributeError: entity instance of type 'IFC4.IfcPropertySet' has no attribute 'Quantities'. Eventhough I verified and all elements have their BaseQuantities. So far only three of the elements returned their values. Find the attached file and code below;

    Unfortunately, I don't know how to indent the code in the textbox. Any insight is appreciated.

    before the code you can use 3xbackticks (above tab key) followed by python and 3 more at the end, use 4xspace for indent, as follows:

    bldg_stories = ifc_model.by_type('IfcBuildingStorey')
    storey_fnd = bldg_stories[-1]
    fnd_elements = storey_fnd.ContainsElements[0].RelatedElements 
    footing_vols = []
    for element in fnd_elements:
        if element.is_a('IfcFooting'): 
            print(element)
            footing_qty = element.IsDefinedBy[0].RelatingPropertyDefinition.Quantities
            footing_vol = footing_qty[-1].VolumeValue
            print(footing_vol)
        else: continue
    

    for the issue itself maybe @Massimo can help you?
    cheers

    Owura_qu
  • @Owura_qu
    Couple notes:

    1) You can use get_decomposition() to get elements in the IfcBuildingStorey or in other spatial elements. Using api calls usually simpler as it doesn't require to remember the IFC schema attributes exactly and ignore some caveats there might be along the way.

    2) Just to add on what steverugi said, this is what the code block below looks like from the comment when I type it:

    The code block:

    import ifcopenshell
    

    3) To debug this kind of error AttributeError: entity instance of type 'IFC4.IfcPropertySet' has no attribute 'Quantities'. you can print element.IsDefinedBy[0].RelatingPropertyDefinition - it won't be IfcElementQuantity as you expected but IfcPropertySet element that doesn't have Quantities attribute. To workaround you can skip all elements that are not IfcElementQuantity.
    But then you'll also need to handle different type of quantities that can appear in qset - e.g. IfcQuantityLength won't have VolumeValue and accessing it will result in the similar error as above. Then you can either skip them too or do some other logic.

    4) Alternatively, you can use another api method get_psets() that has argument to get only quantity sets and will return a dictionary with quantities names and their values which might make them easier to process.

    steverugiMassimobruno_perdigaoemiliotasso
  • edited March 14

    @Owura_qu in fact, the problem is there.
    As @Andrej730 suggested, it is better to use get_psets in order to avoid this kind of problems.
    The object that cause the first problem is "IfcFooting/Cube.002" that is the first object that has two pset assigned to it

    If you use

    element.IsDefinedBy[0].RelatingPropertyDefinition
    

    you will always use the first IsDefinedBy relation and it is ok if you have only one Pset assigned to it, but if there are two or more, there would be problems....
    Thanks to @Andrej730 for the detailed explanation :-)

    @Owura_qu nice model btw :-)

    steverugiOwura_qu
  • edited March 19

    @Andrej730 said:
    1) You can use get_decomposition() to get elements in the IfcBuildingStorey or in other spatial elements. Using api calls usually simpler as it doesn't require to remember the IFC schema attributes exactly and ignore some caveats there might be along the way.

    Yes, I use the api calls too. In this case I am intentionally using the vanilla IFC code as a way to understand more of the concepts of the IFC Schema especially wrt to ‘relationships’.

    3) To debug this kind of error AttributeError: entity instance of type 'IFC4.IfcPropertySet' has no attribute 'Quantities'. you can print element.IsDefinedBy[0].RelatingPropertyDefinition - it won't be IfcElementQuantity as you expected but IfcPropertySet element that doesn't have Quantities attribute. To workaround you can skip all elements that are not IfcElementQuantity.
    But then you'll also need to handle different type of quantities that can appear in qset - e.g. IfcQuantityLength won't have VolumeValue and accessing it will result in the similar error as above. Then you can either skip them too or do some other logic.

    You’re right it wasn’t ‘ IfcElementQuantity’ and just like @Massimo confirmed but it’s okay now.

    4) Alternatively, you can use another api method get_psets() that has argument to get only quantity sets and will return a dictionary with quantities names and their values which might make them easier to process.

    Noted. Btw is it possible to add the ‘Qto_BaseQuantities’ by code without adding it through BBIM UI setting (eg. SHIFT+Q).

    Pardon the delay some internet problems for the past days.

  • Noted. Btw is it possible to add the ‘Qto_BaseQuantities’ by code without adding it through BBIM UI setting (eg. SHIFT+Q).

    Yes, I was looking for a solution to that too, it would be nice to find out, thanks

  • If i understand it correctly, the question is about adding the Pset "Qto_BaseQuantities" with the code instead of through BBIM UI, right?
    In order to do that, you can use the api
    https://blenderbim.org/docs-python/autoapi/ifcopenshell/api/pset/add_qto/index.html
    Does this answer the question?

    steverugiOwura_qu
  • @Massimo said:
    If i understand it correctly, the question is about adding the Pset "Qto_BaseQuantities" with the code instead of through BBIM UI, right?

    By code I meant the vanilla IFC Schema without ifcOpenShell api. I am trying to explore the raw code to gain more insights.

  • Hi @Coen :

    import ifcopenshell
    import blenderbim.tool as tool
    from blenderbim.bim.ifc import IfcStore
    
    
    ifc_file = ifcopenshell.open(IfcStore.path)
            
    products = ifc_file.by_type('IfcWall')
    
    for ifc_product in products:
        
        ifc_material = ifcopenshell.util.element.get_material(ifc_product)
      
        if ifc_material:               
            if ifc_material.is_a('IfcMaterialLayerSetUsage'):
                
                for material_layer in ifc_material.ForLayerSet.MaterialLayers:
                    print (material_layer.Material.Name, material_layer.LayerThickness)
    

    we might have already exchanged this topic somewhere else here but can't find it atm
    how to do the same in Collaboration > Spreadsheet Import/Export ? I tried several combinations without success
    I need to create a .csv with all IfcMaterialLayerSet and relevant material & thickness, like the output in the image but in a .csv file
    thanks

  • maybe...

    {
      "query": "IfcWall",
      "attributes": [
        {
          "name": "type.Name",
          "header": "TYPE",
          "sort": "NONE",
          "group": "GROUP",
          "summary": "NONE",
          "formatting": "{{value}}"
        },
        {
          "name": "material.item.0.Material.Name",
          "header": "Name - 1st Layer",
          "sort": "NONE",
          "group": "NONE",
          "summary": "NONE",
          "formatting": "{{value}}"
        },
        {
          "name": "material.item.0.LayerThickness",
          "header": "Thickness - 1st Layer",
          "sort": "NONE",
          "group": "NONE",
          "summary": "NONE",
          "formatting": "{{value}}"
        },
        {
          "name": "material.item.1.Material.Name",
          "header": "Name - 2nd Layer",
          "sort": "NONE",
          "group": "NONE",
          "summary": "NONE",
          "formatting": "{{value}}"
        },
        {
          "name": "material.item.1.LayerThickness",
          "header": "Thickness - 2nd Layer",
          "sort": "NONE",
          "group": "NONE",
          "summary": "NONE",
          "formatting": "{{value}}"
        },
        {
          "name": "material.item.2.Material.Name",
          "header": "Name - 3rd Layer",
          "sort": "NONE",
          "group": "NONE",
          "summary": "NONE",
          "formatting": "{{value}}"
        },
        {
          "name": "material.item.2.LayerThickness",
          "header": "Thickness - 3rd Layer",
          "sort": "NONE",
          "group": "NONE",
          "summary": "NONE",
          "formatting": "{{value}}"
        }
      ],
      "settings": {
        "should_generate_svg": false,
        "should_preserve_existing": false,
        "include_global_id": false,
        "null_value": "N/A",
        "empty_value": "-",
        "true_value": "YES",
        "false_value": "NO",
        "concat_value": ", ",
        "csv_delimiter": ",",
        "format": "ods",
        "csv_custom_delimiter": ""
      }
    }
    
    

    BedsonsteverugiJohnCoenAndrej730
  • @theoryshaw said:
    maybe...

    yes, I missed the number between "material.item.X.LayerThickness"
    thank you!

    Coen
  • @steverugi
    Glad I could help 😂😂🤓

    steverugi
Sign In or Register to comment.