Skip to main content

Open-FDD Python package (PyPI)

GitHub Pages: this README is excluded from the docs site (exclude: README.md). Published overview lives at docs/ecm/index.md / overview.md — section PyPI agent tools. ECM pages: https://bbartling.github.io/open-fdd/ecm/

open-fdd is the library AI agents install. It ships RCx/FDD reporting and ECM workbooks together.

  1. AI agent RCx/FDD report — open-fdd-anomaly report writes a Typst PDF from mapped roles. It is not a Railway-only tool. The CLI reads a local device folder (history_wide.csv + column_map.json). The same template (open_fdd.reporting.report_template) accepts a role-named frame from a Railway or self-hosted Open-FDD central (the agent supplies the reader) or from a future vendor API.
  2. ECM engineering (open_fdd.ecm_engineering) — agent-drivable HVAC spreadsheet workbooks + Python benchmarks. Guide: https://bbartling.github.io/open-fdd/ecm/
  3. Pandas oracle (open_fdd.rules, open_fdd.analytics, open_fdd.reporting) — cookbook catalog, analytics helpers, Engineering Findings.

Works with any AI agent that can read markdown skills and run the PyPI CLI. Skills live in openfdd_agent_spec/skills/ (not only .cursor/). Sync them with ./scripts/openfdd_install_agent_skills.sh --sync.

pip install "open-fdd[anomaly]" "open-fdd[reporting]"
open-fdd-anomaly report ./AHU_1 --out ./ahu1_report --month 2026-06 --compile \
  --location "AHU · ACME Office · Detroit, MI"

--compile is the only PDF path. --title overrides the default Open-FDD AI Agent Report.

The ECM API fills the same workbook input cells a human engineer would fill. It does not replace the visible spreadsheet calculations.

Production FDD (DataFusion SQL fault detection) lives in the GHCR container stack, not this wheel.

Product freeze / upsell: Engineer upsell brief — open-fdd + PyPI (vibe freeze) — after 2026-07-30, customers see ECM via PyPI → open-fdd, not vibe19/vibe20 tip churn.

Build handoff / golden example: OPENFDD_AGENT_ECM_HANDOFF.md · packaged workbook examples/liberty_dual_ahu/ECM_FULL_PARITY.xlsx.

Install

pip install open-fdd                 # ECM only (openpyxl)
pip install "open-fdd[oracle]"       # + pandas rules
pip install "open-fdd[analytics]"    # + analytics helpers (same as oracle)
pip install "open-fdd[reporting]"    # + Engineering Findings extras
pip install "open-fdd[anomaly]"      # + offline anomaly screening (STL, Isolation Forest)

For the FastAPI ECM example:

pip install "open-fdd[ecm-web]"

Oracle rules (pandas)

from open_fdd.rules import RULES, run_rule

Generate a workbook in a few lines

from open_fdd.ecm_engineering import ECMJob

job = (
    ECMJob("Lincoln Middle School")
    .set_global(
        area_ft2=85000,
        electric_rate=0.145,
        gas_rate=0.92,
    )
    .add_ecm(
        "static_pressure_reset",
        fan_kw=55.9,
        hours=4100,
        baseline_speed=0.82,
        proposed_speed=0.67,
    )
    .add_ecm(
        "boiler_reset",
        base_therms=48000,
        base_eff=0.86,
        prop_eff=0.92,
    )
)

# set_many / add_ecm already persist; save() is idempotent on the same path
# (BUG-OFDD-ECM-002) and can also copy to another path.
job.save("Lincoln_Middle_School_ECMs.xlsx")

The resulting XLSX contains the engineering inputs and formulas for human review.

Module names vs calculators

from open_fdd.ecm_engineering import list_ecm_modules, list_calculators

list_ecm_modules()   # names accepted by add_ecm (aliases included)
list_calculators()   # independent Python benchmarks (job.calc), not sheet names

New in 4.2.0: chiller_lockout, load_shed, schedule_align / ahu_sched_align.

Honesty / twin compare export (4.2.0)

job.attach_twin_compare({
    "provenance": {"idf_path": "...", "g14_pass": True},
    "inputs": [{"name": "lockout_hours", "value": 612, "provenance": "FITTED_FROM_EPLUS"}],
    "measures": [{
        "measure_id": "ECM-CHILLER-LOCKOUT",
        "name": "Chiller OAT lockout",
        "eplus_source": "cascade",
        "fitted_sheet_kwh": 101580.56,
        "eplus_kwh": 101580.56,
        "hours_provenance": "FITTED_FROM_EPLUS",
    }],
    "demand": {"july_weekday_kw": 420, "july_weekend_kw": 280, "loadshed_kw": 365},
})
job.save("honesty.xlsx")  # Contents, Measures, … (FITTED ≠ independent validation)

IPMVP change-point / G14 (4.4.3)

from open_fdd.ecm_engineering import fit_changepoint, score_g14_monthly, option_c_savings

Docs: IPMVP change-point & G14. Requires numpy (pip install "open-fdd[oracle]").

Independent benchmark

from open_fdd.ecm_engineering import ECMJob

job = ECMJob("demo")
result = job.calc(
    "fan_affinity",
    design_kw=55.9,
    hours=4100,
    baseline_speed_fraction=0.82,
    proposed_speed_fraction=0.67,
)

CLI

open-fdd-ecm calculators
open-fdd-ecm demo --out Demo_ECMs.xlsx

Anomaly screening

Offline AHU IO screen of a device folder (history_wide.csv + column_map.json). Z-score and MAD are SQL-portable rolling stats. STL and Isolation Forest are Python-only (open-fdd[anomaly]).

open-fdd-anomaly screen ./AHU_1 --out ./anomaly_out
# defaults: --top-n 5 --max-days 10 --methods zscore,mad,stl,iforest

# Single AHU FDD/RCx PDF. Only this CLI; no build_april_report.py or other local runner.
# History is mapped roles: local CSV+map, Railway or self-hosted Open-FDD, or a future vendor API.
# --compile writes report.pdf when typst is on PATH.
# --month filters every plot. --week pins the RCx window (YYYY-MM-DD, 7 days).
# Web OAT: mapped column, CSV (web_oa_t reindexed onto the BAS clock), or fetch.
# Economizer scatter: x = OAT−RAT, y = MAT−RAT, bottom-left quadrant only.
# build_economizer_delta_points (alias economizer_delta_frame).
open-fdd-anomaly report ./AHU_1 --out ./ahu1_report --month 2026-06 --compile
open-fdd-anomaly report ./AHU_1 --out ./ahu1_report --month 2026-06 --web-oat ./weather.csv --compile
# April folder (8640 rows @ 5 min). Do not fetch this in CI.
open-fdd-anomaly report ./AHU_1 --out ./april_report --month 2026-04 \
  --web-oat ./open_meteo_april.csv --week 2026-04-06 --compile
# building folder of device subfolders:
open-fdd-anomaly report ./BUILDING --scope building --out ./bldg_report --compile

Engineering posture

Prefer measured BAS, utility, TAB, nameplate and manufacturer data over defaults. Generic chiller %/°F methods are screening proxies; manufacturer performance maps or calibrated EnergyPlus should replace them when stronger estimates are needed.

Metadata

Release files for open-fdd 4.4.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for open-fdd 4.4.8
File Size Uploaded
open_fdd-4.4.8.tar.gz 378.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for open-fdd 4.4.8
File Interpreter ABI Platform
open_fdd-4.4.8-py3-none-any.whl Python 3 none any Details

Total release size: 788.5 kB

Release files / open_fdd-4.4.8.tar.gz

Download URL open_fdd-4.4.8.tar.gz
Size 378.0 kB
Tags Source
SHA-256 checksum
How to use checksums
0becd812b00701b362b4f6c22f9ed52d8d561b02deff92c9a609b7f60c06bbd8
BLAKE2b-256 checksum
How to use checksums
06ce0168108aa3c6c614d1a6f4f66d1a0fd05e1c8e226599b80e7af623363ac3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / open_fdd-4.4.8-py3-none-any.whl

Download URL open_fdd-4.4.8-py3-none-any.whl
Size 410.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d875a2e138c118769492557b434ed7918d4a6feb1b1e97a2554cebb4f65ec7a1
BLAKE2b-256 checksum
How to use checksums
fc0a3c208f2bec11d30514e866c61b5d035ecdd61f3b8b998850b18bf33c6e3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

4.4.9

2 release files

This release

4.4.8 This release

2 release files

4.4.7

2 release files

4.4.6

2 release files

4.4.5

2 release files

4.4.4

2 release files

4.4.3

2 release files

4.4.1

2 release files

4.4.0

2 release files

4.3.0

2 release files

4.2.0

2 release files

4.1.2

2 release files

4.1.1

2 release files

4.1.0

2 release files

4.0.0

2 release files

3.1.6

2 release files

3.1.5

2 release files

3.1.3

2 release files

3.1.2

2 release files

3.1.1

2 release files

3.1.0

2 release files

3.0.34

2 release files

3.0.32

2 release files

3.0.31

2 release files

3.0.30

2 release files

3.0.9

2 release files

3.0.8

2 release files

3.0.6

2 release files

3.0.5

2 release files

3.0.4

2 release files

3.0.1

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.1

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.11

2 release files

2.0.9

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page