Python API¶
Use ifc-graph as a Python library for programmatic control over IFC processing and Neo4j storage.
Installation¶
Quick Start¶
from ifc_graph import filter_physical_elements, save_to_neo4j
# Extract elements from IFC file
elements, ifc_file = filter_physical_elements(
"path/to/model.ifc",
element_types=['IfcWall', 'IfcDoor', 'IfcWindow']
)
print(f"Found {sum(len(e) for e in elements.values())} elements")
# Store in Neo4j
stats = save_to_neo4j(
elements,
ifc_file,
uri="bolt://localhost:7687",
username="neo4j",
password="your_password"
)
print(f"Created {stats['elements']} elements")
print(f"Created {stats['structures']} structures")
print(f"Linked {stats['materials']} materials")
Core Functions¶
filter_physical_elements¶
Extracts building elements from an IFC file.
from ifc_graph import filter_physical_elements
elements, ifc_file = filter_physical_elements(
ifc_file_path="model.ifc",
element_types=['IfcWall', 'IfcDoor', 'IfcWindow', 'IfcColumn'],
config={
'include_property_sets': True,
'include_materials': True,
'max_properties_per_element': 50,
}
)
Parameters:
| Parameter | Type | Description |
|---|---|---|
ifc_file_path |
str |
Path to the IFC file |
element_types |
list[str] |
IFC element types to extract (optional) |
config |
dict |
Extraction configuration (optional) |
Returns:
elements: Dictionary mapping element types to lists of IFC elementsifc_file: The loaded ifcopenshell file object
Example - Extract Only Structural Elements:
elements, ifc_file = filter_physical_elements(
"building.ifc",
element_types=['IfcColumn', 'IfcBeam', 'IfcSlab', 'IfcFooting']
)
for element_type, elems in elements.items():
print(f"{element_type}: {len(elems)} elements")
save_to_neo4j¶
Saves extracted elements to a Neo4j database.
from ifc_graph import save_to_neo4j
stats = save_to_neo4j(
filtered_elements=elements,
ifc_file=ifc_file,
uri="bolt://localhost:7687",
username="neo4j",
password="password",
clear_db=False,
config={
'include_materials': True,
'include_property_sets': True,
}
)
Parameters:
| Parameter | Type | Description |
|---|---|---|
filtered_elements |
dict |
Elements from filter_physical_elements() |
ifc_file |
ifcopenshell.file |
Loaded IFC file object |
uri |
str |
Neo4j connection URI |
username |
str |
Neo4j username |
password |
str |
Neo4j password |
clear_db |
bool |
Clear database before import (default: False) |
config |
dict |
Extraction configuration (optional) |
Returns:
Dictionary with import statistics:
{
'elements': 150, # Number of element nodes created
'structures': 12, # Number of structure nodes created
'materials': 45, # Number of material relationships
'property_sets': 0, # Reserved for future use
}
Classes¶
IFCElementFilter¶
Object-oriented interface for element extraction.
from ifc_graph import IFCElementFilter
# Initialize filter
filter = IFCElementFilter(
file_path="model.ifc",
config={
'include_property_sets': True,
'include_materials': True,
}
)
# Load IFC file
ifc_file = filter.load()
# Extract elements
elements, ifc_file = filter.extract_elements(
element_types=['IfcWall', 'IfcDoor']
)
Neo4jConnection¶
Manages database connections with retry logic and proper cleanup.
from ifc_graph import Neo4jConnection
# Using context manager (recommended)
with Neo4jConnection(
uri="bolt://localhost:7687",
username="neo4j",
password="password",
max_retries=3,
retry_delay=1.0
) as conn:
with conn.session() as session:
result = session.run("MATCH (n:Element) RETURN count(n)")
print(result.single()[0])
# Manual connection management
conn = Neo4jConnection(uri, username, password)
try:
conn.connect()
with conn.session() as session:
# Use session
pass
finally:
conn.close()
QueryLoader¶
Load Cypher queries from external files.
from ifc_graph import QueryLoader
# Create loader
loader = QueryLoader(use_cache=True)
# List available queries
queries = loader.list_queries()
print(queries) # ['clear_database', 'create_elements_batch', ...]
# Load a query
query = loader.load("create_elements_batch")
print(query)
Helper Functions¶
load_ifc_file¶
Load an IFC file with validation.
from ifc_graph import load_ifc_file
ifc_file = load_ifc_file("model.ifc")
print(f"Loaded {len(ifc_file.by_type('IfcWall'))} walls")
extract_element_properties¶
Extract properties from a single IFC element.
from ifc_graph import extract_element_properties
element = ifc_file.by_type('IfcWall')[0]
props = extract_element_properties(element, config={})
print(props)
# {
# 'id': '123',
# 'name': 'Basic Wall:Generic - 200mm:456',
# 'guid': '2O2Fr$t4X7Zf8NOew3FLyT',
# 'type': 'IfcWall',
# 'object_type': 'Basic Wall:Generic - 200mm',
# 'description': '',
# 'tag': '456'
# }
extract_spatial_info¶
Get spatial containment information for an element.
from ifc_graph import extract_spatial_info
element = ifc_file.by_type('IfcWall')[0]
spatial = extract_spatial_info(element)
for info in spatial:
print(f"Contained in: {info['name']} ({info['type']})")
extract_material_info¶
Get material information for an element.
from ifc_graph import extract_material_info
element = ifc_file.by_type('IfcWall')[0]
materials = extract_material_info(element)
for mat in materials:
print(f"Material: {mat['material_name']} ({mat['material_category']})")
extract_property_sets¶
Get property sets for an element.
from ifc_graph import extract_property_sets
element = ifc_file.by_type('IfcWall')[0]
psets = extract_property_sets(element, max_properties=50)
for pset in psets:
print(f"Property Set: {pset['pset_name']}")
for name, value in pset['properties'].items():
print(f" {name}: {value}")
Exception Handling¶
The library provides specific exceptions for error handling:
from ifc_graph import (
IFCLoadError,
IFCValidationError,
DatabaseConnectionError,
DatabaseOperationError,
)
try:
elements, ifc_file = filter_physical_elements("model.ifc")
stats = save_to_neo4j(elements, ifc_file, uri, user, password)
except IFCValidationError as e:
print(f"Invalid IFC file: {e}")
# File doesn't exist, wrong extension, empty file
except IFCLoadError as e:
print(f"Failed to load IFC file: {e}")
# ifcopenshell couldn't parse the file
except DatabaseConnectionError as e:
print(f"Cannot connect to Neo4j: {e}")
# Wrong URI, credentials, or Neo4j not running
except DatabaseOperationError as e:
print(f"Database operation failed: {e}")
# Query error, constraint violation, etc.
Complete Example¶
#!/usr/bin/env python3
"""Complete example of processing an IFC file to Neo4j."""
from ifc_graph import (
filter_physical_elements,
save_to_neo4j,
IFCLoadError,
IFCValidationError,
DatabaseConnectionError,
DatabaseOperationError,
)
# Configuration
IFC_FILE = "building.ifc"
NEO4J_URI = "bolt://localhost:7687"
NEO4J_USER = "neo4j"
NEO4J_PASSWORD = "your_password"
# Element types to extract
ELEMENT_TYPES = [
'IfcWall',
'IfcWallStandardCase',
'IfcDoor',
'IfcWindow',
'IfcColumn',
'IfcBeam',
'IfcSlab',
'IfcStair',
'IfcRoof',
]
def main():
try:
# Extract elements
print(f"Loading IFC file: {IFC_FILE}")
elements, ifc_file = filter_physical_elements(
IFC_FILE,
element_types=ELEMENT_TYPES,
config={
'include_property_sets': True,
'include_materials': True,
'max_properties_per_element': 50,
}
)
total = sum(len(e) for e in elements.values())
print(f"Found {total} elements")
# Show breakdown by type
for elem_type, elems in elements.items():
print(f" {elem_type}: {len(elems)}")
# Save to Neo4j
print(f"\nSaving to Neo4j at {NEO4J_URI}")
stats = save_to_neo4j(
elements,
ifc_file,
uri=NEO4J_URI,
username=NEO4J_USER,
password=NEO4J_PASSWORD,
clear_db=True, # Start fresh
)
print("\nImport complete!")
print(f" Elements: {stats['elements']}")
print(f" Structures: {stats['structures']}")
print(f" Materials: {stats['materials']}")
except IFCValidationError as e:
print(f"Error: Invalid IFC file - {e}")
return 1
except IFCLoadError as e:
print(f"Error: Failed to load IFC file - {e}")
return 1
except DatabaseConnectionError as e:
print(f"Error: Cannot connect to Neo4j - {e}")
return 1
except DatabaseOperationError as e:
print(f"Error: Database operation failed - {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())
See Also¶
- API Reference - Detailed API documentation
- Graph Model - Understanding the Neo4j graph structure