IDS Checker
Business Case
Problem Statement
BIM data validation challenges:
- Inconsistent model information
- Missing required properties
- Non-compliant data deliveries
- Manual validation is time-consuming
Solution
Automated IDS (Information Delivery Specification) checking system to validate BIM models against defined requirements.
Technical Implementation
import pandas as pd
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
import re
class RequirementType(Enum):
PROPERTY = "property"
CLASSIFICATION = "classification"
MATERIAL = "material"
ATTRIBUTE = "attribute"
RELATION = "relation"
class Facet(Enum):
ENTITY = "entity"
PROPERTY_SET = "property_set"
PROPERTY = "property"
CLASSIFICATION = "classification"
MATERIAL = "material"
PART_OF = "part_of"
class Cardinality(Enum):
REQUIRED = "required"
OPTIONAL = "optional"
PROHIBITED = "prohibited"
class CheckResult(Enum):
PASS = "pass"
FAIL = "fail"
WARNING = "warning"
NOT_APPLICABLE = "n/a"
@dataclass
class IDSRequirement:
req_id: str
name: str
description: str
applicability: Dict[str, Any] # Which elements this applies to
requirements: List[Dict[str, Any]] # What is required
cardinality: Cardinality = Cardinality.REQUIRED
@dataclass
class ValidationResult:
element_id: str
element_type: str
requirement_id: str
result: CheckResult
message: str
details: Dict[str, Any] = field(default_factory=dict)
@dataclass
class IDSSpecification:
spec_id: str
name: str
version: str
purpose: str
requirements: List[IDSRequirement] = field(default_factory=list)
class IDSChecker:
"""Check BIM data against IDS (Information Delivery Specification)."""
def __init__(self, spec_name: str):
self.spec_name = spec_name
self.specifications: Dict[str, IDSSpecification] = {}
self.results: List[ValidationResult] = []
def create_specification(self, spec_id: str, name: str,
version: str = "1.0", purpose: str = "") -> IDSSpecification:
"""Create new IDS specification."""
spec = IDSSpecification(
spec_id=spec_id,
name=name,
version=version,
purpose=purpose
)
self.specifications[spec_id] = spec
return spec
def add_requirement(self, spec_id: str, requirement: IDSRequirement):
"""Add requirement to specification."""
if spec_id in self.specifications:
self.specifications[spec_id].requirements.append(requirement)
def add_property_requirement(self, spec_id: str, req_id: str, name: str,
entity_type: str, property_set: str,
property_name: str, data_type: str = None,
value_pattern: str = None,
cardinality: Cardinality = Cardinality.REQUIRED):
"""Add property requirement."""
requirement = IDSRequirement(
req_id=req_id,
name=name,
description=f"Property {property_name} in {property_set}",
applicability={'entity': entity_type},
requirements=[{
'type': RequirementType.PROPERTY.value,
'property_set': property_set,
'property_name': property_name,
'data_type': data_type,
'value_pattern': value_pattern
}],
cardinality=cardinality
)
self.add_requirement(spec_id, requirement)
def add_classification_requirement(self, spec_id: str, req_id: str, name: str,
entity_type: str, system: str,
value_pattern: str = None,
cardinality: Cardinality = Cardinality.REQUIRED):
"""Add classification requirement."""
requirement = IDSRequirement(
req_id=req_id,
name=name,
description=f"Classification from {system}",
applicability={'entity': entity_type},
requirements=[{
'type': RequirementType.CLASSIFICATION.value,
'system': system,
'value_pattern': value_pattern
}],
cardinality=cardinality
)
self.add_requirement(spec_id, requirement)
def create_standard_cobie_spec(self) -> str:
"""Create standard COBie specification."""
spec = self.create_specification(
"COBIE_BASIC",
"COBie Basic Requirements",
"1.0",
"Basic COBie data requirements for facility handover"
)
# Space requirements
self.add_property_requirement("COBIE_BASIC", "CB-SP-01", "Space Name",
"IfcSpace", "Pset_SpaceCommon", "Name")
self.add_property_requirement("COBIE_BASIC", "CB-SP-02", "Space Number",
"IfcSpace", "COBie_Space", "SpaceNumber")
self.add_property_requirement("COBIE_BASIC", "CB-SP-03", "Room Tag",
"IfcSpace", "COBie_Space", "RoomTag")
# Component requirements
self.add_property_requirement("COBIE_BASIC", "CB-CO-01", "Component Name",
"IfcElement", "COBie_Component", "Name")
self.add_property_requirement("COBIE_BASIC", "CB-CO-02", "Component Type",
"IfcElement", "COBie_Component", "TypeName")
self.add_property_requirement("COBIE_BASIC", "CB-CO-03", "Serial Number",
"IfcElement", "COBie_Component", "SerialNumber",
cardinality=Cardinality.OPTIONAL)
# Type requirements
self.add_property_requirement("COBIE_BASIC", "CB-TY-01", "Type Name",
"IfcTypeObject", "COBie_Type", "Name")
self.add_property_requirement("COBIE_BASIC", "CB-TY-02", "Manufacturer",
"IfcTypeObject", "COBie_Type", "Manufacturer")
self.add_property_requirement("COBIE_BASIC", "CB-TY-03", "Model Number",
"IfcTypeObject", "COBie_Type", "ModelNumber")
return "COBIE_BASIC"
def create_standard_lod_spec(self, lod_level: int = 300) -> str:
"""Create standard LOD specification."""
spec_id = f"LOD_{lod_level}"
spec = self.create_specification(
spec_id,
f"LOD {lod_level} Requirements",
"1.0",
f"Level of Development {lod_level} requirements"
)
if lod_level >= 200:
self.add_property_requirement(spec_id, f"LOD-{lod_level}-01",
"Element must have type",
"IfcElement", "Pset_ElementCommon", "Type")
if lod_level >= 300:
self.add_property_requirement(spec_id, f"LOD-{lod_level}-02",
"Element must have dimensions",
"IfcElement", "BaseQuantities", "Length")
self.add_property_requirement(spec_id, f"LOD-{lod_level}-03",
"Material assignment",
"IfcElement", "Pset_MaterialCommon", "Material")
if lod_level >= 350:
self.add_property_requirement(spec_id, f"LOD-{lod_level}-04",
"Fire rating",
"IfcElement", "Pset_ElementCommon", "FireRating",
cardinality=Cardinality.OPTIONAL)
self.add_classi