# `ifcopenshell.file` An `ifcopenshell.file` is the in-memory representation of a parsed IFC file. It is the central object in every ifcbus operation — all reading, querying, modifying, and writing go through it. --- ## Opening a file ```python import ifcopenshell model = ifcopenshell.open("input.ifc") # model is an ifcopenshell.file object ``` `ifcopenshell.open()` parses the STEP-encoded `.ifc` file and loads all entities into memory. The result is a live, mutable object graph. --- ## What it contains An IFC file is a flat list of **entity instances**, each identified by a sequential integer id (`#1`, `#2`, …). Entities reference each other by id, forming a directed graph. ``` #1 = IfcOrganization(...) #2 = IfcApplication(#1, ...) #33 = IfcOwnerHistory(#32, #2, ...) #514 = IfcSpace('0BTBFw6f90Nfh9rP1dlXrr', #33, 'A101', ...) ``` The `ifcopenshell.file` object holds: - **All entity instances** (the flat list above) - **Schema** — e.g. `IFC2X3`, `IFC4` - **Header** — file metadata (author, application, description, timestamp) --- ## Key methods ### Querying ```python # By entity id (integer) el = model.by_id(514) # By GlobalId (GUID string) el = model.by_guid("0BTBFw6f90Nfh9rP1dlXrr") # All instances of a type (includes subtypes) walls = model.by_type("IfcWall") # returns list spaces = model.by_type("IfcSpace") # Iterate over every entity in the file for entity in model: print(entity.id(), entity.is_a()) ``` ### Relationships ```python # All entities that reference this element (inverse links) refs = model.get_inverse(el) # returns set of entity instances # All entities reachable from this element (deep graph traversal) graph = model.traverse(el) # returns list, breadth-first ``` ### Modifying ```python # Create a new entity org = model.create_entity("IfcOrganization", Name="ACME") # Remove an entity and clean up its relationships model.remove(el) # Higher-level removal (cleans containment, placements, etc.) import ifcopenshell.api ifcopenshell.api.run("root.remove_product", model, product=el) ``` ### Writing ```python # Write back to a file model.write("output.ifc") # Or via ifcpatch (used when the result comes from a recipe) import ifcpatch ifcpatch.write(result, "output.ifc") ``` --- ## Schema and header ```python print(model.schema) # "IFC2X3" or "IFC4" print(model.header.file_description) # ViewDefinition, ... print(model.header.file_name.name) # original filename ``` --- ## Entity instances Each element returned by the methods above is an **entity instance** (`ifcopenshell.entity_instance`). Its attributes are accessed as properties: ```python wall = model.by_type("IfcWall")[0] wall.GlobalId # GUID string wall.Name # element name wall.is_a() # "IfcWall" — runtime type string wall.id() # integer entity id (file-local, unstable across extractions) wall.get_info() # dict of all attribute name → value ``` Entity ids are **not stable** — the same physical element will have a different id after extraction or merging. Always use `GlobalId` or `Name` to identify elements across files. --- ## Relationship to ifcpatch `ifcpatch.execute()` takes an `ifcopenshell.file` as input and returns a new one as output. The input is never modified in place. `ifcpatch.write()` is a thin wrapper around `model.write()` with some post-processing. ```python result = ifcpatch.execute({ "input": "input.ifc", "file": model, # ← ifcopenshell.file "recipe": "ExtractElements", "arguments": ["IfcWall"], }) # result is a new ifcopenshell.file ifcpatch.write(result, "output.ifc") ``` --- ## Memory model The entire file is loaded into memory as a C++ object graph (via a Python binding). This means: - Operations are fast (no re-parsing on each query). - Large files consume significant RAM. - The object is **not thread-safe** — do not share across threads. - Passing the object to `MergeProjects` as a file path string (instead of the object itself) triggers a segfault in the current version — always pass the live object.