Skip to main content

Fast native IFC parsing, data extraction, and geometric analytics

Project description

ifcfast

Fast native IFC parsing, data extraction and geometric analytics. Python on top, Rust underneath, no ifcopenshell.open() on the hot path.

Aimed at the "open an IFC, get the data out, run QTO / quality queries" workflow. Tier-1 parse is byte-identical to ifcopenshell and ~20-27× faster on production files.

ifcfast was extracted on 2026-05-13 from the EdvardGK/ifc-workbench scratch repo. See docs/history/origin.md for the trail back and what was renamed.

What it gives you

layer format typical latency on 200 MB IFC
Products (GUID, type, name, storey, parent, tag) dict of parallel lists tier-1 cold: 0.5–2 s
Property sets long-format pandas.DataFrame 137 ms
Element quantities long-format pandas.DataFrame 90 ms
Materials (incl. layer sets) long-format pandas.DataFrame 27 ms
Classifications long-format pandas.DataFrame 17 ms
All data layers (shared scan) bundle 1.3 s
Triangle meshes (extrusion / mapped / face sets / BREP) OBJ / glTF / CSV 2.6 s
Placement-vs-mesh drift report pandas.DataFrame 322 ms
Parquet cache (all of the above) parquet 65 ms hot reload

End-to-end cold parse of a 200 MB IFC: under 5 s. Hot reload from cache: under 100 ms. Memory peak: under 1 GB resident (mmap-based).

Audited at 234,144 products across 5 authoring tools (Tekla, Archicad, Revit IFC4, Revit IFC2X3, MagiCAD, BSProLib) with byte-level parity vs ifcopenshell. See docs/history/audit/.

Install

Needs Rust 1.95+ and Python 3.10+.

pip install maturin
maturin develop --release      # builds the Rust extension, ~30 s first time

For production: maturin build --release produces a wheel.

Quick start

import ifcfast

m = ifcfast.open("model.ifc")
print(len(m), "products,", len(m.storeys), "storeys")
print(m.authoring_app, "→", m.schema)

walls = list(m.filter(entity="IfcWall"))

# Long-format data layers (pandas DataFrames, loaded lazily).
m.psets             # 63k+ rows on a 200 MB Archicad file
m.quantities        # author-supplied Qto_*BaseQuantities
m.materials         # (guid, role, layer, name, thickness, category)
m.classifications   # NS 3451 / Uniformat / OmniClass references
m.drift             # placement-vs-mesh drift report

# Standard QTO query — external walls.
external_walls = m.psets[
    (m.psets.pset_name == "Pset_WallCommon")
    & (m.psets.prop_name == "IsExternal")
    & (m.psets.value == "True")
].guid.unique()

# Quality gate — placement bugs.
suspect = m.drift[m.drift.drift_severity == "error"]

The same model can be re-opened cheaply — the second ifcfast.open(...) returns from the parquet cache in tens of milliseconds.

CLI

ifcfast index   model.ifc           # tier-1 parse + counts
ifcfast extract model.ifc           # extract data layers (writes cache)
ifcfast drift   model.ifc --top 20  # placement / mesh drift report
ifcfast cache   model.ifc           # inspect cache for a file

The Rust binary ifcfast-mesh writes OBJ / glTF / CSV directly:

cargo build --release --bin ifcfast-mesh --no-default-features --features mesh
./target/release/ifcfast-mesh model.ifc model.glb

Cache

Parquet files live under ~/.cache/ifcfast/<cache_key>/, where cache_key is sha256(file_size + first 4 MB + last 4 MB) truncated. Any edit to the IFC invalidates the entry automatically.

Override with the IFCFAST_CACHE environment variable, e.g. IFCFAST_CACHE=/srv/cache ifcfast extract model.ifc.

Disk footprint on a 200 MB Archicad IFC: 2.4 MB total zstd-compressed.

Data schemas

All extractors return long-format (one row per fact, no nested fields). Easy to join, easy to filter, easy to flatten to Excel.

Missing values: string columns use pandas StringDtype with nan as the NULL sentinel (chosen for memory and pyarrow round-trip). Cells corresponding to a STEP $ field hold float('nan'), not Python None. Use .isna() to test, not == None or is None:

m.classifications[m.classifications.identification.isna()]   # correct
m.classifications[m.classifications.identification == None]  # always False
[r for r in m.classifications.itertuples() if r.identification is None]  # always False

If you're cross-checking against ifcopenshell (which returns None), normalise NaN→None on the comparison side.

psets

column type description
guid str IfcProduct.GlobalId
pset_name str e.g. Pset_WallCommon
prop_name str e.g. IsExternal
value str | None booleans normalised to True / False / UNKNOWN
value_type str | None IfcBoolean, IfcText, IfcReal, …

quantities

column type description
guid str IfcProduct.GlobalId
qto_name str e.g. Qto_WallBaseQuantities
quantity_name str e.g. NetVolume, GrossArea, Length
value str | None numeric value as string
quantity_type str Area / Length / Volume / Count / Weight / Time
unit_step_id int | None usually None (project default applies)

materials

column type description
guid str IfcProduct.GlobalId
role str direct / list / layer / unknown
layer_index int 0-based for layered materials, -1 otherwise
material_name str | None material label
layer_thickness_mm float | None only set for role="layer"
category str | None IFC4 only

classifications

column type description
guid str IfcProduct.GlobalId
system_name str | None NS 3451, Uniformat II, OmniClass
edition str | None e.g. 2022
identification str | None the actual code
name str | None human label
location str | None URI to spec (rarely populated)
source str | None publisher

drift

column type description
guid, entity, source str identification
triangle_count, surface_area, volume_abs int / float geometric stats
placement_x/y/z float what IfcLocalPlacement says
centroid_x/y/z float where the mesh AABB centre actually is
drift_distance float Euclidean distance, mm
max_extent float largest AABB dimension
drift_ratio float drift_distance / max_extent
drift_severity str ok / warn / error

Severity rule: ok when drift_ratio ≤ 2.0 or drift_distance < 10 mm; error when drift_ratio > 10.0 and drift_distance > 10 mm.

A 100 m wall placed at one end has ratio 0.5 (legitimate). A 50 mm sensor 100 m from its placement has ratio 2000 (clear authoring bug).

Federated floor synthesis

Multi-discipline projects have the same physical floor named differently by ARK / RIB / RIV / RIE authors. ifcfast.federated_floors clusters by elevation across discipline models and applies a project-supplied YAML rule.

# examples/projects/lbk-building-c.yaml
prefix: "C - "
overrides:
  Plan U1: Hav
  C - U1:  Hav
idempotent_labels: [Hav]
apply_drop_leading_zero: true

The module is project-agnostic — project tables live in user config.

Architecture in two paragraphs

The Rust core (crates/core) does one byte-level pass over the IFC's DATA section using a string-aware STEP tokenizer (memchr-accelerated). That pass builds an EntityTable — a step_id → byte_range map of every entity in the file. Each PyO3 entry point (index_ifc, extract_psets, etc.) walks the table once, dispatching on entity type and extracting only the fields that layer needs.

The Python cache (ifcfast.cache) writes each extractor's output as zstd-compressed parquet, keyed by sha256(size + 4 MB head + 4 MB tail) so any IFC edit invalidates automatically. Hot reads are pure pandas / pyarrow — no Rust call needed. There is no ifcopenshell.open() anywhere in the data path; ifcopenshell is an optional dev dep used only for cross-checking parity in tests.

What it doesn't do

  • Write or modify IFCs. Read-only by construction.
  • Schema validation. Trusts the file's syntax. Use bsi-validator for conformance.
  • Tessellate IfcBooleanClippingResult (walls with openings render without cutouts — gross volume correct, net volume not).
  • NURBS / advanced BREP geometry. ~0.5% of elements in typical exports.
  • Property variants beyond IfcPropertySingleValueIfcPropertyEnumeratedValue, IfcPropertyListValue, IfcPropertyBoundedValue, IfcComplexProperty are skipped. Covers ~90% of psets seen on Revit / Archicad / Tekla / MagiCAD exports.

Layout

crates/core/         Rust extension (PyO3) — tokenizer, indexer, extractors, mesh
  src/
    lib.rs           PyO3 entry points
    lexer.rs         STEP tokenizer
    indexer.rs       tier-1 product / storey index
    entity_table.rs  step_id → byte range lookup
    extractors/      psets, quantities, materials, classifications
    mesh/            extrusion, mapped, face sets, BREP, glTF writer
    bin/             ifcfast-bench, ifcfast-mesh CLIs
python/ifcfast/      Public Python API
  __init__.py        ifcfast.open(), Model, header, classify
  header.py          STEP header reader (tier-0)
  model.py           Model class + native tier-1 driver
  cache.py           parquet cache for index + data layers
  classify.py        element-mode policy (count / measure / linear / skip)
  federated_floors.py multi-discipline floor synthesiser
  cli.py             ifcfast CLI
docs/history/        origin doc + audit issues from ifc-workbench
examples/projects/   project YAMLs for federated_floors
tests/               pytest suite

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ifcfast-0.1.0a2.tar.gz (76.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ifcfast-0.1.0a2-cp310-abi3-win_amd64.whl (335.4 kB view details)

Uploaded CPython 3.10+Windows x86-64

ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (413.5 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (392.4 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

ifcfast-0.1.0a2-cp310-abi3-macosx_11_0_arm64.whl (373.6 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

ifcfast-0.1.0a2-cp310-abi3-macosx_10_12_x86_64.whl (390.5 kB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file ifcfast-0.1.0a2.tar.gz.

File metadata

  • Download URL: ifcfast-0.1.0a2.tar.gz
  • Upload date:
  • Size: 76.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ifcfast-0.1.0a2.tar.gz
Algorithm Hash digest
SHA256 61bcb60f7ac54e96508d7e223157984d47feb419816460a38e133496f0905207
MD5 bfca34ac5b648e1ac882daec28af03e3
BLAKE2b-256 e80c2a2dfdfbd6b98885733439b98f21db06faeb67e14f7bcfdf85d69fccd2c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcfast-0.1.0a2.tar.gz:

Publisher: release.yml on EdvardGK/ifcfast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifcfast-0.1.0a2-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: ifcfast-0.1.0a2-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 335.4 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ifcfast-0.1.0a2-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 17770f9c2b84997f3b33ccc1fb5d42a3a9c760e3036f9b09af7c61dc05da702e
MD5 3f7cb5c00f2c88d322a3edde9a6d5e2e
BLAKE2b-256 ff55cf11bfaa77fbcca7d5bc54d0a2422c6593d6926eba5e3a3eb579de1a69fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcfast-0.1.0a2-cp310-abi3-win_amd64.whl:

Publisher: release.yml on EdvardGK/ifcfast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9cd8682a6d876a82f06ea083c616a7c96ff17245e83a82f077a4e73940627110
MD5 9e755e1215aeea26252e95b19434207a
BLAKE2b-256 1ab0e93283ba5b90dc8ee6da603bd55d97d1ffdaa0484a3362acaa43b60854cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on EdvardGK/ifcfast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1c9b29031505db56a6c029789b8e32365be71dd9a9ef407954454aa060c3599f
MD5 0f3bdcdd112a98779f618a308bc4c032
BLAKE2b-256 63b0e88c7d2237def0e83d83fe15bbce9669e91ffd8ac0ddf515207df0ea3da4

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcfast-0.1.0a2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on EdvardGK/ifcfast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifcfast-0.1.0a2-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ifcfast-0.1.0a2-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9e8a6c0ec807013a8041012d2ab8e5a6f8afb7b3ffca884ae61ce0c73ec05c0f
MD5 d0f4a267371cddc20b4232cbecd7216c
BLAKE2b-256 d9350390cfda5f2bda60663ff7b186c2dad4f6c976e159a210acb58749acbb84

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcfast-0.1.0a2-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on EdvardGK/ifcfast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifcfast-0.1.0a2-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ifcfast-0.1.0a2-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 73d766e67a1212b7725db4676305d5156fcf0e148cf0b127f667a406b7b885c6
MD5 81da060cfb8f6a8910a09617a262ee74
BLAKE2b-256 bae3394f08c49848d4a143f6630959521aaab313e9053245699f164dace56745

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcfast-0.1.0a2-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on EdvardGK/ifcfast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page