Skip to content

Data Flow

This page is the tool pipeline view: how a Bill of Quantities becomes an EN 15978 result. It is deliberately distinct from the Module map, which shows the life-cycle stages the tool covers.

Where the tool starts

The tool's entry point is the Bill of Quantities, not raw-material extraction. The BoQ is the practitioner's artefact; everything upstream of it (quarrying, manufacturing, supply chains) enters the calculation as impact factors from EPDs, never as modelled process flows. This is what makes the tool auditable: every number upstream of the BoQ is a citation, not a simulation.

The pipeline

flowchart TD
    ENTRY["① TOOL ENTRY POINT — Bill of Quantities<br/>assemblies · MaterialCategory · quantity + UnitEnum<br/>the tool starts HERE, not at raw-material extraction"]

    QTY["② quantities — IMPLEMENTED<br/>BoQ → material explosion<br/>output: installed mass per material, one-time"]

    subgraph RES["③ EPD / impact-factor resolution"]
        SEED[("seed_epds/*.json<br/>openEPD + proxy_provenance")]
        SEEDGATE["services.seed_epd_gate — IMPLEMENTED<br/>runtime provenance gate, offline rules"]
        SEEDREG["services.seed_epd_registry — IMPLEMENTED<br/>cached loader, declared unit → factor basis<br/>(kg; m²/m³ stored as declared)<br/>4 of 18 A1-A3 factors (AR-63)"]
        PROXY["services.proxy_engine — STUB<br/>5-step proxy cascade"]
        PED["services.pedigree — STUB<br/>Weidema 5-axis DQI → GSD²"]
        INTERP["services.interpolation — STUB<br/>linear interpolation + audit trail"]
    end

    subgraph CALC["④ Per-module impact calculation"]
        A1A3["lca.a1_a3 — IMPLEMENTED<br/>E = mass × factor<br/>4 factors seed-resolved · 14 inline literals<br/>4 materials BLOCKED · 1 PROVISIONAL"]
        A4["lca.a4 — IMPLEMENTED<br/>E = Σ mass · distance · factor per t·km<br/>both transport-mode factors BLOCKED"]
        A5["lca.a5 — STUB<br/>BLOCKED on an African grid factor (decision #26)"]
        REST["lca.c1 · c2 · c3 · c4 · d — STUB"]
        B4N["lca.b4 — IMPLEMENTED (mechanism)<br/>N = ⌈RSP/RSL⌉ − 1 × f × A1-A3 row<br/>no number: every RSL BLOCKED (AR-12)"]
        B6N["lca.b6 — PARITY-VERIFIED (formula B6-F1)<br/>supplied kWh/yr + carrier + basis<br/>× EF_grid supplied in the request (never stored) × RSP<br/>no EF → BLOCKED (AR-65)"]
    end

    THERM["thermal — STUB<br/>ISO 10456 / ISO 6946"]
    ENERGY["energy — STUB<br/>EN ISO 52016-1 hourly, from first principles<br/>climate data: NASA POWER (vendored)"]

    AGG["⑤ Aggregation<br/>Σ per indicator, per EN 15978 module"]
    UNC["⑥ services.uncertainty — STUB<br/>Monte Carlo, 10 000 iterations"]
    OUT["⑦ EN 15978 results + services.reporting — STUB<br/>per-indicator · per-module · D reported separately"]

    %% --- life-cycle / pipeline sequence ---
    ENTRY ==> QTY
    QTY ==> RES
    A5 ==> AGG
    REST ==> AGG
    AGG ==> UNC
    UNC ==> OUT

    %% --- internal data dependency ---
    SEED --> SEEDGATE
    SEEDGATE --> SEEDREG
    SEEDREG -->|"factor + provenance (4 materials, live today)"| A1A3
    SEED --> PROXY
    PROXY --> PED
    PED --> INTERP
    PROXY -->|"factor + provenance"| A1A3
    PROXY -->|"factor + provenance"| A4
    PROXY -->|"factor + provenance"| A5
    QTY -->|"mass per material"| A1A3
    QTY -->|"mass per material"| A4
    QTY -->|"installed quantity"| A5
    QTY -->|"installed quantity + RSL ❸"| REST
    THERM --> ENERGY
    ENERGY -->|"cooling load"| REST

    %% --- currently emits None ---
    A1A3 -.->|"total = None — BLOCKED factors"| AGG
    A4 -.->|"total = None — BLOCKED factors"| AGG

    %% --- read-only picker source (GET /lci/materials) ---
    LCIMAT["services.lci_materials — IMPLEMENTED<br/>GET /lci/materials picker list<br/>derived from the A1-A3 factor table"]
    A1A3 -->|"factor table, read-only"| LCIMAT

    %% --- stateless compute (POST /projects/compute) ---
    PCOMP["services.project_compute — IMPLEMENTED<br/>POST /projects/compute<br/>A1-A3 computed; A4/A5 not assessed<br/>B4 via lca.b4.compute_b4: rows BLOCKED on f / RSL<br/>B6 via lca.b6.compute_b6: EF_grid enters with the request;<br/>carbon computed when supplied, else BLOCKED"]
    LCIMAT -->|"ids + selectable, validation"| PCOMP
    A1A3 -->|"compute_a1_a3_submitted"| PCOMP
    A1A3 -->|"A1-A3 rows, read-only"| B4N
    B4N -->|"compute_b4"| PCOMP
    CMP["services.comparison — IMPLEMENTED<br/>compare(): reads both variant summaries, calls no engine<br/>five gates; always pending — no delta, no band (AR-83, AR-13)"]
    PCOMP -->|"variants, read-only"| CMP

    linkStyle 0,1,2,3,4,5 stroke:#1e88e5,stroke-width:3px
    linkStyle 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 stroke:#00897b,stroke-width:2px
    linkStyle 21,22 stroke:#e53935,stroke-width:2.5px
    linkStyle 23,24,25 stroke:#00897b,stroke-width:2px

    classDef done fill:#2e7d32,stroke:#1b5e20,stroke-width:1px,color:#ffffff
    classDef todo fill:#757575,stroke:#424242,stroke-width:1px,color:#ffffff
    classDef entry fill:#5e35b1,stroke:#4527a0,stroke-width:2px,color:#ffffff
    classDef store fill:#00695c,stroke:#004d40,stroke-width:1px,color:#ffffff

    class ENTRY entry
    class QTY,A1A3,A4,LCIMAT,PCOMP,B6N,B4N,CMP done
    class PROXY,PED,INTERP,A5,REST,THERM,ENERGY,AGG,UNC,OUT todo
    class SEED store

Edge legend

Edge Meaning
Thick blue Pipeline sequence — the numbered steps ① → ⑦ in order.
Thin teal Internal data dependency — quantities mass feeding a1_a3 / a4 / a5, and resolved factors feeding the calculation modules.
Red dashed The module currently emits None. Its formula is implemented and parity-tested, but an impact factor it depends on is BLOCKED under decision #23, so no total can be reported.

Node legend

Node Meaning
Purple Tool entry point.
Green Implemented, tests green.
Grey Stub — skeleton file only.
Dark teal cylinder Data store (vendored seed-EPD library).

Two red edges, one cause

Both red edges trace back to the same class of gap: no citable impact factor on file. lca.a1_a3 is blocked on Earth, crude oil, floor tiles and antirust paint; lca.a4 is blocked on both transport factors, so it has no usable factor at all. Every one of these is a row in the Action register, which is the single place to look for what unblocks a number.

❶ The B6 engine is an EN ISO 52016-1 hourly (8760-step) kernel computed from first principles and driven by vendored NASA POWER data, not the ASHRAE CLTD/CLF table lookup originally planned. The table lookup was dropped on a licence determination that also improves accuracy (AR-31 resolved, AR-60, 2026-08-29); ASHRAE RTS / Heat-Balance was then evaluated and rejected on the functional unit — RTS sizes equipment for a design day, B6 needs annual energy (AR-64, 2026-08-29). It still carries the "simplified — indicative" disclaimer of PROJECT.md decision #17, but that disclaimer is re-anchored: EN ISO 52016-1 hourly is a full dynamic method, so "simplified" now names three specific v1 exclusions — latent loads, multi-zone thermal coupling, and detailed system part-load curves — and the pluggable EnergyPlus/IES VE import deferred to v2 is scoped to those. See the B6 operational-energy spec §1.4 and climate data licence clearance.

❷ Module D results are reported separately and must not be netted against A–C per EN 15804+A2 §6.4.3.2 and METHODOLOGY.md §9.

❸ quantities → B4 data-model seam. quantities outputs installed quantity only (one-time, 100%). Recurrence is modelled as a separate Reference Service Life (RSL) per material/assembly, stored alongside the installed quantity and consumed exclusively by lca.b4. RSL is provenance-gated under decision #24 (SOURCED / EXPERT-JUDGEMENT (attributed) / BLOCKED — raises, no "never-replaced" default). lca.b4 computes: replacements = ⌈ study period ÷ RSL ⌉ − 1 (EN 15978 §6.2.5 + ISO 15686). (Session 42: lca.b4 is implemented to the BLOCKED boundary. It reads the A1-A3 rows, not raw quantities — N · f · Impact_A1-A3 is exactly the A1-A3 of the replaced quantity — and takes f per submitted row. Every RSL is BLOCKED (AR-12); see the B4 design spec.) See PROJECT.md decision #24 and GitHub issue #11.

Where proxy_engine and pedigree are consulted

The proxy cascade is consulted when a seed EPD does not exist for the exact material in the exact regional context. The five steps are:

  1. Regional EPD (Sub-Saharan Africa)
  2. Country-adjacent EPD (EPDASA / INIES)
  3. Climate-analogue EPD
  4. Generic EPD with documented adaptation
  5. Peer-reviewed literature value

At each step, pedigree scores the data quality on Weidema's five axes and converts the score to GSD² for Monte Carlo input. interpolation is consulted when a calculation input falls between the sampled points of a reference dataset — between two tabulated rows, or between the grid nodes of a gridded climate dataset (see METHODOLOGY.md §5a for the audit-trail requirement).

Interpolation points

Module Dataset Interpolation trigger
energy NASA POWER meteorological grid (½° lat × ⅝° lon) Project coordinates ∉ a grid node — bilinear between the four surrounding points
energy NASA POWER solar grid (1° × 1°) Same, for the irradiance components
thermal ISO 10456 thermal properties Temperature / moisture state between rows
lca.b4 RSL tables (ISO 15686 / climate category) RSP or climate parameter between rows
proxy_engine IPCC EFDB grid factors Project year between annual timesteps

Stub modules

Every node marked STUB above is a skeleton file containing a docstring and a NotImplementedError. No calculation logic exists in them yet. Build status per module is tracked in the Module map status table.