changing IfcClasses with python

Hello guys , i hope you are doing good ! I have my ifc file but when i insvistigate the ifcProduct ive found out that some elements are not appropriatly assigned to their classes , like for a 'Refrigerator' it has in Ifc Class 'IfcBuildingElementProxy' instead of 'IfcElectricAppliance'
So as i Exported all the ifc Elements in a csv file I have corrected the mistaken classes :

here is the export befor correcting

here after correcting

Now i wonder how i can now correct the ifc with python ifcopenshell lib , cause i have tried to import the csv with the BlenderBIM addon but the software shuts down whenever i click in import button hahaha (weird)

I hope someone can help with this , Thank you so much !

Comments

  • If the software shuts down after trying to import a CSV, please report a bug and attach a file (or share to [email protected] if private). That's pretty critical.

    In code, you can do:

    ifcopenshell.api.root.reassign_class(ifc_file, product=element, ifc_class="IfcElectricAppliance", predefined_type="BLAHBLAH")
    

    See https://docs.ifcopenshell.org/autoapi/ifcopenshell/api/root/reassign_class/index.html#module-ifcopenshell.api.root.reassign_class

    alaasquan
  • edited June 27

    i'll make sure to report a bug . Thank you for helping @Moult , really appreciate it !

  • Hello @Moult ,
    Sorry to interfere on this subject, but I'm trying to change an IFC Class on some of my models too.
    Is it possible to make "ifcopenshell.api.root.reassign_class" function work inside a python script after loading file with ifcopenshell. open() ? See code below

    import ifcopenshell
    model = ifcopenshell.open('model.ifc')
    wall = model.by_type("IfcWall")[0]
    slab = ifcopenshell.api.root.reassign_class(model, product=wall, ifc_class="IfcSlab")

    Last line triggers an error because "ifcopenshell.api has no attribute 'root'".
    Any advice ?
    Thanks a lot !!

  • edited August 29

    @arthur595 said:
    Hello @Moult ,
    Sorry to interfere on this subject, but I'm trying to change an IFC Class on some of my models too.

    >

    Any advice ?
    Thanks a lot !!

    did should work ( there is at least 1 x IfcWall in the model):

    import ifcopenshell
    from ifcopenshell.api import root
    path = 'model.ifc'
    model = ifcopenshell.open(path)
    wall = model.by_type("IfcWall")[0]
    slab = root.reassign_class(model, product=wall, ifc_class="IfcSlab")
    
    arthur595John
  • Omg, I'll try this this evening when I'll be home.
    If this is it, I really lack some learning. I thought calling it fully with ifcopenshell.api.root.reassign_class() would be enough.
    Thanks ! I'll keep you informed !

    steverugi
  • edited September 2

    ... I thought calling it fully with ifcopenshell.api.root.reassign_class() would be enough.

    That last line in your code is not a call but an assignment (to a ‘slab’). In Python you call a library with the import function (like Steverugi demonstrated in his line 2). So in short you didn’t call the ifcopenshell.api.root.reassign_class() and that’s why you were getting an error:)

    steverugiJohn
  • That last line in your code is not a call but an assignment (to a ‘slab’).

    It is both a call and an assignment. The issue was that ifcopenshell.api.root module wasn't imported before it's ifcopenshell.api.root.reassign_class method was called.

    steverugiOwura_qu
  • Hello again,

    I've been able to make it work for some models, but I have issues on some specific ones...
    I managed to reproduce the issue on a simple model (linked below).

    What I do is I filter some elements then I change their class from IfcBuildingElementProxy to IfcFanType (for example).
    What I get is an IFC where I can't see any of those filtered elements. When I edit IFC file and look for element by GUID, I can clearly see that they are supposed to be here, as IfcFanTypes.
    Any idea why we can't see any geometry ?

    import ifcopenshell
    import ifcopenshell.util.selector
    from ifcopenshell.api import root
    
    existingFile_path_name_extension = "C:/path/to/model.ifc"
    newFile_path_name_extension = "C:/path/to/new_model.ifc"
    
    # Opening IFC File
    model = ifcopenshell.open(existingFile_path_name_extension)
    
    # Get filtered elements
    filteredElements = ifcopenshell.util.selector.filter_elements(model, "IfcBuildingElementProxy, PSET_APIJ.Code=C1")
    
    # Change category
    for elem in filteredElements:
        root.reassign_class(model, product=elem, ifc_class="IfcFanType")
    
    # Save file
    model.write(newFile_path_name_extension)
    
    

    Thanks again <3

  • No sure if this is the same problem.
    When selecting "Object Metadata" where the same IFCType but different "Predefined Type" the selection does not distinguish the difference in IFCType.
    This was using version 240903

  • edited September 4

    @Roel
    I am not sure if this is related but to the best of my knowledge an IfcType has only one predefined type, if you change it on one instance the others using the same will update accordingly
    Any time you edit the attributes make sure they show the desired predefined, otherwise update it from the main Object Metadata at the top ,in any case it needs to show in the Attributes too as PredefinedType and in bracktes at the top next to the Ifc class (like IfcCovering[CEILING] should appear without brackets also in the Attributes below the Name)

  • Thanks for the response, due to my lack of knowledge I thought there was an selection error but if you want to select all the "main" IfcType elements then you click on the "arrow" but if you want to select the PredefinedType you press Shit and click the "arrow". - Problem solved \0/ sorry it did not help the original post.

  • edited September 5

    Hi @Roel

    Thanks for the response, due to my lack of knowledge I thought there was an selection error but if you want to select all the "main" IfcType elements then you click on the "arrow" but if you want to select the PredefinedType you press Shit and click the "arrow". - Problem solved \0/ sorry it did not help the original post.

    PredefinedType (PT) assignment in Bonsai still looks a tad shaky in my personal opinion

    • On creating a new element using its IfcTypeProduct (ITP) does not automatically inherit its PT
    • Editing the name (for example) of an element resets its PT
    • Currently you can edit the ITP from one of its selected instances, I am not sure this method is the best, if it was for me I'd allow that only by selecting the very ITP in the TypeManager (since we want to discourage the use of the Outliner ), but it might be not so popular

    Conversely

    • Once finished creating all the elements, go through their ITP and reassign the PT, in this case they all nicely update accordingly
    • Even more convenient, update names and PT using the Spreadsheet Import/Export, but it's yet to be implemented in the web output

    hopefully the above won't stir a hornet's nest among other members :))

    cheers

  • @arthur595 said:
    What I do is I filter some elements then I change their class from IfcBuildingElementProxy to IfcFanType (for example).
    What I get is an IFC where I can't see any of those filtered elements. When I edit IFC file and look for element by GUID, I can clearly see that they are supposed to be here, as IfcFanTypes.
    Any idea why we can't see any geometry ?

    We only recently started supporting reassigning class from occurrence class to type class (and vice versa) and I do see now the geometry in Bonsai after executing your script. Previously representations were not reassigned in the way they are assigned to types, so were just left orphaned.
    So it should work after this commit, to try it out you'll need the latest code from the github.

    @steverugi said:

    • On creating a new element using its IfcTypeProduct (ITP) does not automatically inherit its PT

    From IfcWindow documentation:

    Editing the name (for example) of an element resets its PT

    Sounds like a bug, please report it.

  • hi @Andrej730

    @steverugi said:

    • On creating a new element using its IfcTypeProduct (ITP) does not automatically inherit its PT

    From IfcWindow documentation:

    I read the NOTE like 10 times but couldn't figure out its actual (and practical) meaning sorry, I wish someone here could translate it in plain english for me if possible

    Editing the name (for example) of an element resets its PT

    Sounds like a bug, please report it.

    will do thanks

  • edited September 5

    @steverugi said:
    I read the NOTE like 10 times but couldn't figure out its actual (and practical) meaning sorry, I wish someone here could translate it in plain english for me if possible

    E.g. there is an IfcWindow. If it has a type IfcWindowType then IfcWindow.PredefinedType should never be taken into account as IfcWindowType.PredefinedType overrides it.
    So then we add a new occurrence of IfcWindowType then there is no need to fill IfcWindow.PredefinedType and it's fine to just keep it None.

    And from API POV if you want to get predefined_type for an element you should use https://docs.ifcopenshell.org/autoapi/ifcopenshell/util/element/index.html#ifcopenshell.util.element.get_predefined_type instead of accessing it directly.

    Massimo
  • thank you @Andrej730 for the quick reply, truly appreciated

    E.g. there is an IfcWindow. If it has a type IfcWindowType then IfcWindow.PredefinedType should never be taken into account as IfcWindowType.PredefinedType overrides it.
    So then we add a new occurrence of IfcWindowType then there is no need to fill IfcWindow.PredefinedType and it's fine to just keep it None.

    If I understand it properly:
    If a window is an istance of a type no predefined is needed since it gets it from the very type, cool

    but when I create instances from a type they do not come with their predefined as per their type unless I reassign it after
    which means if no reassignment takes place after creating them they do not have a predefined type from their type

    I noticed it by looking at their Attributes or extracting their data with the Spreadsheet

    filter = IfcWallType, result:

    filter = IfcWall, result of a newly created wall using the same IfcWallType

    And from API POV if you want to get predefined_type for an element you should use https://docs.ifcopenshell.org/autoapi/ifcopenshell/util/element/index.html#ifcopenshell.util.element.get_predefined_type instead of accessing it directly.

    noted! thanks again

  • but when I create instances from a type they do not come with their predefined as per their type unless I reassign it after

    Sounds like there is some confusion going on in this table - it's getting PredefinedType directly from the element instead of using api method.

    steverugi
  • And from API POV if you want to get predefined_type for an element you should use https://docs.ifcopenshell.org/autoapi/ifcopenshell/util/element/index.html#ifcopenshell.util.element.get_predefined_type instead of accessing it directly.

    following your advice I tried and yes, using element.get_predefined_type(element) does return the correct value of the original type, but it does not reflect in the spreadsheet or UI, is it a bug or intentional? thanks

  • edited September 5

    @steverugi it's not a bug, it is just that the command element.get_predefined_type(element) looks at the type instead of the element.

    In my opinion, btw, the problem still exists because, from a user perspective view, the export with filter=IfcWall should show the predefined type instead of N/A...it should be inherited somehow...

    steverugiOwura_qu
  • Sounds like there is some confusion going on in this table - it's getting PredefinedType directly from the element instead of using api method.

    @steverugi I've investigated a bit, there is a special keyword "predefined_type" that will ensure inheritance is taked into account (see selector syntax docs), opposing to "PredefinedType" that would actually retrieve "PredefinedType" attribute value from IFC element. It seems "predefined_type" should work for 99% of the cases.


    Though currently it's not supported loading "predefined_type" back to ifc file. Previously it would fail completely, I've changed this in this commit - now "predefined_type" just will be skipped and will give a warning, so atleast it won't get in the way until we support it.

    Editing the name (for example) of an element resets its PT

    I found where it's coming from - it's probably occured when you were editing object attributes from Object Properties and changed it's name, which was calling attribute.edit_attributes which is discarding occurrence PredefinedType if it has a type to maintain consistency, so it's not a bug.

    MassimoJohn
  • thanks @Andrej730

    Sounds like there is some confusion going on in this table - it's getting PredefinedType directly from the element instead of using api method.

    @steverugi I've investigated a bit, there is a special keyword "predefined_type" that will ensure inheritance is taked into account (see selector syntax docs), opposing to "PredefinedType" that would actually retrieve "PredefinedType" attribute value from IFC element. It seems "predefined_type" should work for 99% of the cases.

    I tried it, it does

    Though currently it's not supported loading "predefined_type" back to ifc file. Previously it would fail completely, I've changed this in this commit - now "predefined_type" just will be skipped and will give a warning, so atleast it won't get in the way until we support it.

    I found where it's coming from - it's probably occured when you were editing object attributes from Object Properties and changed it's name, which was calling attribute.edit_attributes which is discarding occurrence PredefinedType if it has a type to maintain consistency, so it's not a bug.

    well noted, cheers

  • @Andrej730 said:
    Though currently it's not supported loading "predefined_type" back to ifc file.

    Okay, it should be possible now after this commit

    steverugiJohnRoelMassimo
Sign In or Register to comment.