IfcOpenShell, how to add a new property and value to an object?

edited August 2021 in General

Hey guys, I'm pretty new to IfcOpenShell.
What I'm trying to achieve is to iterate through a dictionary of attributes (keys) and their corresponding values and add them to an existing object.
I know I can access an object's attributes using something like:
wall.Name
or even change the Name to something that I want:
wall.Name = 'some value'
However, I don't want to have to type the name of the attribute since I'm iterating through a dictionary of attribute names and values.
Additionally, I know it is possible to change the values inside the someobject.get_info(), although that does not update the real object's attributes.
If I try to print the object, it still has the "original" set of attributes:
print(str(someobject))
Something like:
currentObject.my_custom_attributeName = my_custom_attributeValue
does not work.
How can I achieve this?
Thank you!

Tagged:
«1

Comments

  • What about assigning a propertyset with Python IfOpenShell?


    # Create and assign property set import ifcopenshell ifc_file = 'path\to_your\ifc_file' ifcfile = ifcopenshell.open(ifc_file) products = ifcfile.by_type("IfcProduct") owner_history = ifcfile.by_type("IfcOwnerHistory")[0] walls=[] for i in products: if i.is_a("IfcWall"): walls.append(i) property_values = [ ifcfile.createIfcPropertySingleValue("Some Property Set Name ", "Some Property Name", ifcfile.create_entity("IfcText", "Some Value"), None), ] for wall in walls: property_set = ifcfile.createIfcPropertySet(wall.GlobalId, owner_history, "Some Property Set Name ", None, property_values) ifcfile.createIfcRelDefinesByProperties(wall.GlobalId, owner_history, None, None, [wall], property_set) ifcfile.write(ifc_file)
    JesusbillInformationWorkerpolsonmila
  • I just tested this little script on a simple IfcWall,

    IFC file after running this script.

  • In IFC, attributes are fixed. If you want to add arbitrary properties, use property sets, not attributes. This is as @Coen has explained. However, there is a simpler method using the IfcOpenShell API.

    import ifcopenshell
    import ifcopenshell.api
    ifc = ifcopenshell.open('path\to_your\ifc_file')
    element = ifc.by_type("IfcElement")[0] # Just as an example, you will need to select the elements you want to add properties to yourself.
    pset = ifcopenshell.api.run("pset.add_pset", ifc, product=element, name="Your Property Set Name")
    ifcopenshell.api.run("pset.edit_pset", ifc, pset=pset, properties={"foo": "foobar", "foo2": "foobaz"})
    
    polsonmilaCoen
  • @Moult
    Maybe it's convenient to mention how to install the ifcopenshell.api as you described here.

  • edited August 2021

    Thanks for your answers @Moult and @Coen!
    But what should I do in case I need to change the actual attributes of an object? I mean, I know I can type wall.Name = "Some other name", or wall.OwnerHistory = "some new value", etc. However, if I have a dictionary with a set of keys (attribute names that already exist on target object) and values (attribute values that I want to change on target object), what should I do?
    It should be something like:
    1. Select target object given an ID
    2. Iterate through a given dictionary and then change the values of target object's attributes

    Do you have any advice?
    Thank you once again.

  • @Coen indeed thanks.

    @FDinis once you have the pset element, use ifcopenshell.api.run("pset.edit_pset", ifc, pset=pset, properties={"foo": "foobar", "foo2": "foobaz"}). It will take care of editing it.

  • @Moult
    Thank you! :)

  • great code examples.

    @Moult said:
    In IFC, attributes are fixed. If you want to add arbitrary properties, use property sets, not attributes. This is as @Coen has explained. However, there is a simpler method using the IfcOpenShell API.

    import ifcopenshell
    import ifcopenshell.api
    ifc = ifcopenshell.open('path\to_your\ifc_file')
    element = ifc.by_type("IfcElement")[0] # Just as an example, you will need to select the elements you want to add properties to yourself.
    pset = ifcopenshell.api.run("pset.add_pset", ifc, product=element, name="Your Property Set Name")
    ifcopenshell.api.run("pset.edit_pset", ifc, pset=pset, properties={"foo": "foobar", "foo2": "foobaz"})
    

    asumed I do not want to add a new pset but edit a property from a existing pset. What is a simple method to retrieve the pset entities what works with IFC2x3? ifcopenshell.util.element.get_psets(e) returns the contents but not the entity.

    cheers bernd

  • @bernd - Do you want to edit a single occurrence of a property, aka for a single object, or are you trying to edit all instances of a certain property?

  • @bernd the latest IfcOpenShell util module has a fix for exactly this purpose, ifcopenshell.util.element.get_psets(e) will now return an id for each pset so you can easily grab it for editing.

  • edited November 2021

    @Moult said:
    @bernd the latest IfcOpenShell util module has a fix for exactly this purpose, ifcopenshell.util.element.get_psets(e) will now return an id for each pset so you can easily grab it for editing.

    means I need to use 0.7.0 ?

  • edited November 2021

    @vpajic said:
    @bernd - Do you want to edit a single occurrence of a property, aka for a single object, or are you trying to edit all instances of a certain property?

    both, but for the latter I just iterate over all single ones

  • @bernd you don't need to, the util module is Python only so you can just grab the latest Python files from there.

  • @Moult said:
    @bernd you don't need to, the util module is Python only so you can just grab the latest Python files from there.

    ahh sure that would work too.

    I upgraded to 0.70 anyway ...

    BTW: works great with this is it is much simpler to get the pset.

    cheers bernd

  • It does not work to access a changed property. Still the old value is used before the edit. Is there a way this is possible without writing and rereading the IFC file?

    As a workaround I do save the properties in separate dicts, but this gets complicated as more properties are involved or if a property is for some reason changed twice.

    cheers bernd

  • @bernd I don't understand. You don't need to write (serialise) and re-read the IFC file.

    import ifcopenshell
    import ifcopenshell.api
    import ifcopenshell.util.element
    ifc = ifcopenshell.api.run("project.create_file")
    element = ifc.createIfcWall()
    pset = ifcopenshell.api.run("pset.add_pset", ifc, product=element, name="Pset_Name")
    ifcopenshell.api.run("pset.edit_pset", ifc, pset=pset, properties={"foo": "foobar", "foo2": "foobaz"})
    psets = ifcopenshell.util.element.get_psets(element)
    ifcopenshell.api.run("pset.edit_pset", ifc, pset=ifc.by_id(psets["Pset_Name"]["id"]), properties={"foo": "changed"})
    print(ifcopenshell.util.element.get_psets(element))
    
    polsonmila
  • edited November 2021

    ok works great here ...

    BTW: related in the regard of property types ... https://github.com/IfcOpenShell/IfcOpenShell/issues/1889

  • @bernd have you tested dions commit related to this issue?

  • NO not yet, ATM I do not need to change the property type, but I wanted to save the link in case it is needed.
    ATM I only change property values, but I make heavy usage of this :-) works great so far.

  • By observing the problems with IfcOpenShell in recent months, in fact, I think that only one "tool" can solve more than 90% of related problems: a complete documentation. Link: https://pythonhosted.org/eppy/Main_Tutorial.html
    I came across a Python plug-in for parsing idf files, called eppy, on Sunday. I read the documentation on Monday morning and completed the development of a computing plug-in in the afternoon. There are detailed calculation examples, code examples, and even clear explanations of some algorithms and data structures in the documentation of eppy.

    Obviously IfcOpenShell does not have such a clear documentation, many functions are "fuzzy" for beginners, and the calculation examples are not very abundant.

    I hope that enthusiastic researchers can refer to the documentation of eppy to write a documentation of IfcOpenShell. This can be more friendly to beginners

    polsonmila
  • Looked exactly like what I was looking for..... Sadly it does not work on my end :-(

  • @InformationWorker

    Your screenshot confuses me, :-), what are you trying to achieve? Also I don't recognize the IDE you using.

  • edited August 2022

    @Coen said:
    @InformationWorker

    Your screenshot confuses me, :-), what are you trying to achieve? Also I don't recognize the IDE you using.

    Hi Coen, thanks for the reply.
    1) That's VScode, but the console in Blender gives thes same results. Here is the same from jupyter following your code goes well until it's time to fill/declare the properties list. I did that to rule out any issues with python.

    2) What I am after is:
    a. the ability to check the properties of every single element (agains some source, e.g. doors should be wood, color red, classified as IfcDoor)
    b. adjust the properties of elements that are non compliant (e.g. change the color of the door)

    I have been trawling the internet but have not found anything more than this page. The https://wiki.osarch.org/index.php?title=IfcOpenShell_code_examples#Crash_course gives some code to retrieve information using "Selector", which offers me some better options where it comes to retreiving information in the name, but also nothing on how to update properties.

    I have tried to find information on using the export to CSV from CLI but found nothing.

    Addition I tried @Moult suggestion on this page too. Same thing happens :-( Looking deeper into the code, I believe it's not me it's "file.py" Here are my steps:

    1) am I correct that there is no function called "ifc.createIfcWall()" and that "create_entity('IfcWall')" is to be used as mentioned in the "file.py"? Or does it strip that IfcWall of during the call.

    2) I follow the example in the "file.py" still it does not work.

    3) if I try as create_entity() the response suggests there should be a type as one would expect. But as you see under #2 that gives an err.

    Hope this helps, Edgar

    polsonmila
  • This is a great discussion. Thank you all for these wonderful contributions. It has helped me alot. I am creating working on creating a property set. Thanks for this insight.

  • @InformationWorker if you are getting errors like that, it suggests there is something fundamentally broken with your installation of IfcOpenshell. For example, does this code work for you?

    import ifcopenshell
    f = ifcopenshell.file()
    f.create_entity('IfcPerson')
    

    If not, try uninstall your IfcOpenShell and reinstall following the instructions here: https://blenderbim.org/docs-python/ifcopenshell-python/installation.html - also feel free to reach out for live help at https://osarch.org/chat where we can screenshare and solve it together.

  • How would I add an IfcWall to an existing IFC using the ifcopenshell.api? I could only find in the documentation how to create an entire IFC from scratch.

  • I believe that just like this:

    import ifcopenshell
    model = ifcopenshell.open('/path/to/your/model.ifc')
    wall = ifcopenshell.api.run('root.create_entity', model, ifc_class='IfcWall', predefined_type='SOLIDWALL')
    

    Have you had a look at the base ifcopenshell-python docs (not the API)?

    Coen
  • edited April 2023

    https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/src/blenderbim/scripts/obj2ifc.py

    line 76 - 83 does add the new object, add it to the spatial tree and sets the placement. Before line 76 the geometry is created

    Coen
  • How does one delete an entire PropertySet?

Sign In or Register to comment.