Skip to content

Element Filter API

The element_filter module handles IFC file loading and element extraction.

Classes

IFCElementFilter

Object-oriented interface for filtering IFC elements.

from ifc_graph import IFCElementFilter

filter = IFCElementFilter(
    file_path="model.ifc",
    config={
        'include_property_sets': True,
        'include_materials': True,
        'max_properties_per_element': 50,
    }
)

# Load and extract
elements, ifc_file = filter.extract_elements(
    element_types=['IfcWall', 'IfcDoor']
)

Filter and extract elements from IFC files.

This class provides a convenient interface for loading IFC files and extracting elements with their properties.

Source code in src/ifc_graph/element_filter.py
class IFCElementFilter:
    """
    Filter and extract elements from IFC files.

    This class provides a convenient interface for loading IFC files
    and extracting elements with their properties.
    """

    def __init__(self, file_path: str, config: Optional[dict] = None):
        """
        Initialize the IFC element filter.

        Args:
            file_path: Path to the IFC file
            config: Optional extraction configuration
        """
        self.file_path = file_path
        self.config = config or {
            'include_property_sets': True,
            'include_materials': True,
            'max_properties_per_element': 50,
        }
        self._ifc_file = None

    def load(self) -> ifcopenshell.file:
        """Load the IFC file."""
        self._ifc_file = load_ifc_file(self.file_path)
        return self._ifc_file

    @property
    def ifc_file(self) -> ifcopenshell.file:
        """Get the loaded IFC file, loading it if necessary."""
        if self._ifc_file is None:
            self.load()
        return self._ifc_file

    def extract_elements(
        self, 
        element_types: Optional[list[str]] = None
    ) -> tuple[dict, ifcopenshell.file]:
        """
        Extract elements from the IFC file.

        Args:
            element_types: List of IFC element types to extract

        Returns:
            Tuple of (filtered_elements dictionary, ifc_file object)
        """
        return filter_physical_elements(
            self.file_path,
            element_types=element_types,
            config=self.config
        )

ifc_file property

Get the loaded IFC file, loading it if necessary.

__init__(file_path, config=None)

Initialize the IFC element filter.

Parameters:

Name Type Description Default
file_path str

Path to the IFC file

required
config Optional[dict]

Optional extraction configuration

None
Source code in src/ifc_graph/element_filter.py
def __init__(self, file_path: str, config: Optional[dict] = None):
    """
    Initialize the IFC element filter.

    Args:
        file_path: Path to the IFC file
        config: Optional extraction configuration
    """
    self.file_path = file_path
    self.config = config or {
        'include_property_sets': True,
        'include_materials': True,
        'max_properties_per_element': 50,
    }
    self._ifc_file = None

extract_elements(element_types=None)

Extract elements from the IFC file.

Parameters:

Name Type Description Default
element_types Optional[list[str]]

List of IFC element types to extract

None

Returns:

Type Description
tuple[dict, file]

Tuple of (filtered_elements dictionary, ifc_file object)

Source code in src/ifc_graph/element_filter.py
def extract_elements(
    self, 
    element_types: Optional[list[str]] = None
) -> tuple[dict, ifcopenshell.file]:
    """
    Extract elements from the IFC file.

    Args:
        element_types: List of IFC element types to extract

    Returns:
        Tuple of (filtered_elements dictionary, ifc_file object)
    """
    return filter_physical_elements(
        self.file_path,
        element_types=element_types,
        config=self.config
    )

load()

Load the IFC file.

Source code in src/ifc_graph/element_filter.py
def load(self) -> ifcopenshell.file:
    """Load the IFC file."""
    self._ifc_file = load_ifc_file(self.file_path)
    return self._ifc_file

Exceptions

IFCLoadError

Raised when there's an error loading an IFC file.

from ifc_graph import IFCLoadError

try:
    elements, ifc_file = filter_physical_elements("invalid.ifc")
except IFCLoadError as e:
    print(f"Failed to load file: {e}")

Bases: Exception

Raised when there's an error loading an IFC file.

Source code in src/ifc_graph/element_filter.py
class IFCLoadError(Exception):
    """Raised when there's an error loading an IFC file."""
    pass

IFCValidationError

Raised when an IFC file fails validation (doesn't exist, wrong extension, empty).

from ifc_graph import IFCValidationError

try:
    elements, ifc_file = filter_physical_elements("missing.ifc")
except IFCValidationError as e:
    print(f"Invalid file: {e}")

Bases: Exception

Raised when an IFC file fails validation.

Source code in src/ifc_graph/element_filter.py
class IFCValidationError(Exception):
    """Raised when an IFC file fails validation."""
    pass

Functions

filter_physical_elements

The main function for extracting elements from IFC files.

from ifc_graph import filter_physical_elements

elements, ifc_file = filter_physical_elements(
    ifc_file_path="model.ifc",
    element_types=['IfcWall', 'IfcDoor', 'IfcWindow'],
    config={
        'include_property_sets': True,
        'include_materials': True,
        'max_properties_per_element': 50,
    }
)

# elements is a dict: {'IfcWall': [...], 'IfcDoor': [...], ...}
# ifc_file is the loaded ifcopenshell.file object

Filters specific physical elements from an IFC file.

Parameters:

Name Type Description Default
ifc_file_path str

Path to the IFC file

required
element_types Optional[list[str]]

List of IFC element types to extract (e.g., ['IfcWall', 'IfcDoor'])

None
config Optional[dict]

Extraction configuration dictionary

None

Returns:

Type Description
tuple[dict, file]

Tuple of (filtered_elements dictionary, ifc_file object)

Raises:

Type Description
IFCLoadError

If the file cannot be loaded

IFCValidationError

If the file is invalid

Source code in src/ifc_graph/element_filter.py
def filter_physical_elements(
    ifc_file_path: str,
    element_types: Optional[list[str]] = None,
    config: Optional[dict] = None
) -> tuple[dict, ifcopenshell.file]:
    """
    Filters specific physical elements from an IFC file.

    Args:
        ifc_file_path: Path to the IFC file
        element_types: List of IFC element types to extract (e.g., ['IfcWall', 'IfcDoor'])
        config: Extraction configuration dictionary

    Returns:
        Tuple of (filtered_elements dictionary, ifc_file object)

    Raises:
        IFCLoadError: If the file cannot be loaded
        IFCValidationError: If the file is invalid
    """
    # Default element types if none provided
    if element_types is None:
        element_types = [
            'IfcWall', 
            'IfcDoor', 
            'IfcWindow', 
            'IfcStair',
            'IfcSlab',
            'IfcRoof',
            'IfcColumn',
            'IfcBeam'
        ]

    if config is None:
        config = {
            'include_property_sets': True,
            'include_materials': True,
            'max_properties_per_element': 50,
        }

    logger.info(f"Loading IFC file: {ifc_file_path}")
    start_time = time.time()

    # Load the IFC file with error handling
    ifc_file = load_ifc_file(ifc_file_path)

    # Dictionary to store elements by type
    filtered_elements = {}

    # Filter elements
    for element_type in element_types:
        try:
            elements = ifc_file.by_type(element_type)
            if elements:
                filtered_elements[element_type] = elements
                logger.info(f"Found {len(elements)} {element_type} elements")
        except Exception as e:
            logger.warning(f"Error filtering {element_type}: {e}")

    load_time = time.time() - start_time
    total_elements = sum(len(elems) for elems in filtered_elements.values())
    logger.info(f"Filtered {total_elements} elements in {load_time:.2f} seconds")

    return filtered_elements, ifc_file

load_ifc_file

Load an IFC file with validation and error handling.

from ifc_graph import load_ifc_file

ifc_file = load_ifc_file("model.ifc")
walls = ifc_file.by_type('IfcWall')

Load an IFC file with error handling.

Parameters:

Name Type Description Default
file_path str

Path to the IFC file

required

Returns:

Type Description
file

Loaded IFC file object

Raises:

Type Description
IFCLoadError

If there's an error loading the file

Source code in src/ifc_graph/element_filter.py
def load_ifc_file(file_path: str) -> ifcopenshell.file:
    """
    Load an IFC file with error handling.

    Args:
        file_path: Path to the IFC file

    Returns:
        Loaded IFC file object

    Raises:
        IFCLoadError: If there's an error loading the file
    """
    try:
        validate_ifc_file(file_path)
        logger.info(f"Loading IFC file: {file_path}")
        return ifcopenshell.open(file_path)
    except IFCValidationError:
        raise
    except Exception as e:
        raise IFCLoadError(f"Failed to load IFC file: {file_path}. Error: {e}") from e

validate_ifc_file

Validate that an IFC file exists and is accessible.

from ifc_graph.element_filter import validate_ifc_file, IFCValidationError

try:
    validate_ifc_file("model.ifc")
    print("File is valid")
except IFCValidationError as e:
    print(f"Validation failed: {e}")

Validate that an IFC file exists and is accessible.

Parameters:

Name Type Description Default
file_path str

Path to the IFC file

required

Raises:

Type Description
IFCValidationError

If the file is invalid or inaccessible

Source code in src/ifc_graph/element_filter.py
def validate_ifc_file(file_path: str) -> None:
    """
    Validate that an IFC file exists and is accessible.

    Args:
        file_path: Path to the IFC file

    Raises:
        IFCValidationError: If the file is invalid or inaccessible
    """
    from pathlib import Path

    path = Path(file_path)

    if not path.exists():
        raise IFCValidationError(f"IFC file not found: {file_path}")

    if not path.is_file():
        raise IFCValidationError(f"Path is not a file: {file_path}")

    if path.suffix.lower() not in ['.ifc', '.ifczip']:
        raise IFCValidationError(f"Invalid file extension: {path.suffix}. Expected .ifc or .ifczip")

    if path.stat().st_size == 0:
        raise IFCValidationError(f"IFC file is empty: {file_path}")

extract_element_properties

Extract properties from a single IFC element for graph storage.

from ifc_graph import extract_element_properties, load_ifc_file

ifc_file = load_ifc_file("model.ifc")
element = ifc_file.by_type('IfcWall')[0]

props = extract_element_properties(element, config={})
# Returns: {'id': '123', 'name': 'Wall', 'guid': '...', 'type': 'IfcWall', ...}

Extract properties from an IFC element for graph storage.

Parameters:

Name Type Description Default
element Any

IFC element to extract properties from

required
config dict

Extraction configuration

required

Returns:

Type Description
dict[str, Any]

Dictionary of extracted properties

Source code in src/ifc_graph/element_filter.py
def extract_element_properties(element: Any, config: dict) -> dict[str, Any]:
    """
    Extract properties from an IFC element for graph storage.

    Args:
        element: IFC element to extract properties from
        config: Extraction configuration

    Returns:
        Dictionary of extracted properties
    """
    props = {
        'id': str(element.id()),
        'name': getattr(element, 'Name', None) or 'Unnamed',
        'guid': getattr(element, 'GlobalId', '') or '',
        'type': element.is_a(),
        'object_type': getattr(element, 'ObjectType', None) or '',
        'description': getattr(element, 'Description', None) or '',
        'tag': getattr(element, 'Tag', None) or '',
    }

    return props

extract_spatial_info

Extract spatial containment information for an element.

from ifc_graph import extract_spatial_info, load_ifc_file

ifc_file = load_ifc_file("model.ifc")
element = ifc_file.by_type('IfcWall')[0]

spatial = extract_spatial_info(element)
# Returns: [{'id': '456', 'name': 'Level 1', 'type': 'IfcBuildingStorey', ...}]

Extract spatial containment information for an element.

Parameters:

Name Type Description Default
element Any

IFC element to extract spatial info from

required

Returns:

Type Description
list[dict]

List of spatial structure information dictionaries

Source code in src/ifc_graph/element_filter.py
def extract_spatial_info(element: Any) -> list[dict]:
    """
    Extract spatial containment information for an element.

    Args:
        element: IFC element to extract spatial info from

    Returns:
        List of spatial structure information dictionaries
    """
    spatial_info = []

    try:
        if hasattr(element, 'ContainedInStructure') and element.ContainedInStructure:
            for rel in element.ContainedInStructure:
                if rel.RelatingStructure:
                    structure = rel.RelatingStructure
                    spatial_info.append({
                        'id': str(structure.id()),
                        'name': getattr(structure, 'Name', None) or 'Unnamed',
                        'type': structure.is_a(),
                        'long_name': getattr(structure, 'LongName', None) or '',
                        'elevation': _get_elevation(structure),
                    })
    except Exception as e:
        logger.debug(f"Error extracting spatial info for element {element.id()}: {e}")

    return spatial_info

extract_material_info

Extract material information for an element.

from ifc_graph import extract_material_info, load_ifc_file

ifc_file = load_ifc_file("model.ifc")
element = ifc_file.by_type('IfcWall')[0]

materials = extract_material_info(element)
# Returns: [{'element_id': '123', 'material_id': '789', 'material_name': 'Concrete', ...}]

Extract material information for an element.

Parameters:

Name Type Description Default
element Any

IFC element to extract material info from

required

Returns:

Type Description
list[dict]

List of material information dictionaries

Source code in src/ifc_graph/element_filter.py
def extract_material_info(element: Any) -> list[dict]:
    """
    Extract material information for an element.

    Args:
        element: IFC element to extract material info from

    Returns:
        List of material information dictionaries
    """
    materials = []

    try:
        if hasattr(element, 'HasAssociations'):
            for association in element.HasAssociations:
                if association.is_a('IfcRelAssociatesMaterial'):
                    material_select = association.RelatingMaterial
                    materials.extend(_process_material(material_select, element))
    except Exception as e:
        logger.debug(f"Error extracting materials for element {element.id()}: {e}")

    return materials

extract_property_sets

Extract property sets for an element.

from ifc_graph import extract_property_sets, load_ifc_file

ifc_file = load_ifc_file("model.ifc")
element = ifc_file.by_type('IfcWall')[0]

psets = extract_property_sets(element, max_properties=50)
# Returns: [{'element_id': '123', 'pset_name': 'Pset_WallCommon', 'properties': {...}}]

Extract property sets for an element.

Parameters:

Name Type Description Default
element Any

IFC element to extract property sets from

required
max_properties int

Maximum number of properties to extract per element

50

Returns:

Type Description
list[dict]

List of property set information dictionaries

Source code in src/ifc_graph/element_filter.py
def extract_property_sets(element: Any, max_properties: int = 50) -> list[dict]:
    """
    Extract property sets for an element.

    Args:
        element: IFC element to extract property sets from
        max_properties: Maximum number of properties to extract per element

    Returns:
        List of property set information dictionaries
    """
    property_sets = []
    total_props = 0

    try:
        if hasattr(element, 'IsDefinedBy'):
            for definition in element.IsDefinedBy:
                if total_props >= max_properties:
                    break

                if definition.is_a('IfcRelDefinesByProperties'):
                    prop_def = definition.RelatingPropertyDefinition

                    if prop_def.is_a('IfcPropertySet'):
                        pset_data = {
                            'element_id': str(element.id()),
                            'pset_id': str(prop_def.id()),
                            'pset_name': prop_def.Name or 'Unnamed',
                            'properties': {}
                        }

                        if hasattr(prop_def, 'HasProperties'):
                            for prop in prop_def.HasProperties:
                                if total_props >= max_properties:
                                    break

                                prop_value = _get_property_value(prop)
                                if prop_value is not None:
                                    pset_data['properties'][prop.Name] = prop_value
                                    total_props += 1

                        if pset_data['properties']:
                            property_sets.append(pset_data)

    except Exception as e:
        logger.debug(f"Error extracting property sets for element {element.id()}: {e}")

    return property_sets

Configuration Options

The config parameter accepts a dictionary with these options:

Option Type Default Description
include_property_sets bool True Extract property sets
include_materials bool True Extract material info
max_properties_per_element int 50 Max properties to extract per element

Example Configuration

config = {
    'include_property_sets': True,
    'include_materials': True,
    'max_properties_per_element': 100,
}

elements, ifc_file = filter_physical_elements(
    "model.ifc",
    element_types=['IfcWall'],
    config=config
)

Default Element Types

When element_types is not provided, these types are extracted:

  • IfcWall
  • IfcDoor
  • IfcWindow
  • IfcStair
  • IfcSlab
  • IfcRoof
  • IfcColumn
  • IfcBeam

See Also