Skip to content

Repository files navigation

comfio

A multi-domain IEQ & performance contract framework for smart buildings.

comfio bridges the gap between raw building sensor data and actionable smart building management. It breaks the silos between different building physics disciplines — bringing together Thermal, Visual, Acoustic, and Indoor Air Quality (IAQ) metrics into a unified Global IEQ Index.

Designed for time-series data (IoT sensors, edge computing) and comfort-based performance contracts, comfio enables researchers and building managers to automate compliance tracking and generate smart-contract-ready outputs.

Why comfio?

  • Silo-Breaking: Unifies separated domains (Thermal, Acoustic, Visual, IAQ) under a single Python API
  • Data-Native: Built to ingest massive arrays of time-series data (Pandas/NumPy) rather than single-point calculations
  • Actionable Output: Translates physical equations into compliance rates for building performance contracts
  • Smart Contract Ready: Generates structured JSON outputs with formal ABI schemas for blockchain Oracle integration
  • ML/DL Compatible: NumPy-native core with optional adapters for scikit-learn, PyTorch, and TensorFlow/Keras
  • Advanced Physics Modules: Optional extras for Radiance daylighting, CRI/CCT color quality, RT60 reverberation, STI speech intelligibility, CO₂ decay ventilation, and full psychrometrics
  • Pollutant IAQ: PM2.5, PM10, TVOC, formaldehyde, and CO evaluation against WHO, EPA NAAQS, and WELL Building Standard v2 thresholds
  • Adaptive Thermal Comfort: ASHRAE 55-2023 and EN 16798-1:2019 adaptive models for naturally ventilated buildings
  • Simplified PMV (sPMV): Buratti et al. (2009) seasonal model requiring only temperature and humidity
  • TSV Augmentation: CDF-based remapping (quantile mapping) to augment sparse occupant votes to dense sensor timestamps while preserving the empirical distribution
  • Personalised Comfort: OLS regression-based personalisation of model predictions to match occupant feedback (TSV), with per-season support
  • Fast & Light: Core depends only on numpy, pandas, and pythermalcomfort

Installation

pip install comfio

With ML/DL framework support:

pip install comfio[ml]        # scikit-learn
pip install comfio[torch]     # PyTorch
pip install comfio[keras]     # TensorFlow/Keras
pip install comfio[all]       # All frameworks + advanced domains

Advanced physics-based domain evaluation (optional extras):

pip install comfio[daylighting]      # pyradiance (Radiance ray-tracing)
pip install comfio[color]            # colour-science (CRI, CCT)
pip install comfio[acoustics]        # python-acoustics + pyroomacoustics (RT60, STI)
pip install comfio[psychrometrics]   # PsychroLib (psychrometric properties, CO₂ decay ACH)

Try on Google Colab

Run the tutorials instantly in your browser — no local install required.

Examples

Notebook Description Open in Colab
walkthrough_executed.ipynb Complete end-to-end walkthrough: data gen, all domains, Global IEQ, compliance, ML, LLM, smart contracts, reports Open In Colab
simple_tutorial.ipynb Quick start: core domains, Global IEQ Index, compliance Open In Colab
simple_tutorial_executed.ipynb Same as above with pre-run outputs Open In Colab
advanced_domains_tutorial.ipynb Advanced physics: daylighting, CRI/CCT, RT60, STI, ventilation, psychrometrics Open In Colab
advanced_domains_tutorial_executed.ipynb Same as above with pre-run outputs Open In Colab
llm_tutorial.ipynb LLM integration: interpreters, prompts, OpenAI/LangChain tool schemas Open In Colab
llm_tutorial_executed.ipynb Same as above with pre-run outputs Open In Colab
contracts_ml_tutorial.ipynb Smart contracts & ML: compliance ABI, web3.py, sklearn/PyTorch/Keras forecasting Open In Colab
contracts_ml_tutorial_executed.ipynb Same as above with pre-run outputs Open In Colab

Docs Tutorials

Notebook Description Open in Colab
01_first_contract.ipynb First IEQ compliance contract: evaluate domains, calculate Global IEQ, generate contract JSON Open In Colab
02_new_domains.ipynb New domains: IAQ pollutants, adaptive thermal comfort, sPMV, TSV augmentation Open In Colab
03_training_pcm.ipynb Training personal comfort models: OLS personalisation, seasonal personalisation Open In Colab
04_llm_diagnostics.ipynb LLM diagnostics: interpreters, prompt templates, edge deployment Open In Colab
05_advanced_domains.ipynb Advanced domains: daylighting, color quality, reverberation, speech intelligibility Open In Colab
06_walkthrough.ipynb Complete end-to-end walkthrough: data gen, all domains, Global IEQ, compliance, ML, LLM, smart contracts, reports Open In Colab

Tip: In Colab, run !pip install comfio[all] in the first cell to install all optional dependencies.

Quick Start

1. Evaluate Individual Domains

import numpy as np
from comfio import evaluate_thermal, evaluate_visual, evaluate_acoustic, evaluate_iaq

# Thermal comfort (ISO 7730 / ASHRAE 55)
thermal = evaluate_thermal(
    tdb=np.array([24.0, 25.0, 26.0]),  # air temp °C
    tr=np.array([24.0, 25.0, 26.0]),   # radiant temp °C
    vr=np.array([0.1, 0.1, 0.1]),       # air velocity m/s
    rh=np.array([50.0, 50.0, 50.0]),    # relative humidity %
    met=1.2,                            # metabolic rate
    clo=0.5,                            # clothing insulation
    category="B",                       # ISO 7730 category
)
print(f"PMV: {thermal.pmv}, PPD: {thermal.ppd}")

# Visual comfort (EN 12464-1)
visual = evaluate_visual(
    illuminance=np.array([450.0, 500.0, 600.0]),
    task_type="office_writing",
)

# Acoustic comfort (NC curves)
acoustic = evaluate_acoustic(
    laeq=np.array([35.0, 40.0, 45.0]),
    nc_level="NC-35",
)

# IAQ (ASHRAE 62.1 indicators)
iaq = evaluate_iaq(
    co2=np.array([700.0, 900.0, 1100.0]),
    threshold_level="good",
)

2. Calculate Global IEQ Index

from comfio import calculate_global_ieq, default_weights

# Merge all domains into a single 0-100 score
ieq = calculate_global_ieq(
    thermal=thermal,
    visual=visual,
    acoustic=acoustic,
    iaq=iaq,
    weights=default_weights(),  # thermal=40%, iaq=25%, visual=20%, acoustic=15%
)
print(f"Global IEQ Index: {ieq.index}")
print(f"Domain scores: {ieq.domain_scores}")

3. Compliance Tracking & Contract Outputs

from comfio import calculate_compliance

report = calculate_compliance(ieq, threshold=80.0)
print(f"Compliance rate: {report.compliance_rate_pct:.1f}%")
print(f"Average IEQ: {report.ieq_index_avg:.1f}")

# Generate JSON for blockchain Oracle
contract_json = report.to_contract_json()
print(contract_json)

4. Time-Series Data with SensorData

import pandas as pd
from comfio import SensorData

# Load your sensor DataFrame
df = pd.read_csv("sensor_data.csv")
sensor = SensorData(df=df)

# Auto-detects column names (tdb, ta, temperature → air_temp_c, etc.)
print(sensor.available_domains())  # ['thermal', 'visual', 'acoustic', 'iaq']

# Validate data (NaN handling, physical bounds checking)
sensor.validate()
clean_temp = sensor.get_validated("air_temp_c")

ML/DL Integration

scikit-learn Pipeline

from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestRegressor
from comfio.ml.sklearn_transformers import IEQFeatureExtractor

pipe = Pipeline([
    ("ieq", IEQFeatureExtractor()),
    ("model", RandomForestRegressor()),
])
pipe.fit(train_df, train_labels)
predictions = pipe.predict(test_df)

PyTorch DataLoader

from torch.utils.data import DataLoader
from comfio.ml.torch_dataset import IEQTimeSeriesDataset

dataset = IEQTimeSeriesDataset(df, window_size=24, stride=1)
loader = DataLoader(dataset, batch_size=32, shuffle=True)
for batch in loader:
    raw = batch["raw"]           # (32, 24, n_sensors)
    ieq = batch["ieq_index"]     # (32, 24)

TensorFlow/Keras

from comfio.ml.keras_adapter import IEQPreprocessingLayer

layer = IEQPreprocessingLayer()
layer.adapt(train_df)
features = layer(train_df)  # tf.Tensor of IEQ features

Advanced Domain Evaluation

comfio offers optional physics-based modules that go beyond simple threshold checks. These require separate extras but integrate seamlessly with the Global IEQ Index.

from comfio import (
    evaluate_reverberation, evaluate_speech_intelligibility,
    evaluate_ventilation, get_psychrometrics,
    calculate_global_ieq,
)

# Reverberation time (python-acoustics)
reverb = evaluate_reverberation(surfaces, absorption, volume, room_type="office")

# Speech intelligibility from impulse response (pyroomacoustics)
sti = evaluate_speech_intelligibility(ir_signal, sample_rate=16000)

# Ventilation rate from CO₂ decay (psychrolib)
vent = evaluate_ventilation(co2_array, timestamps, occupancy_type="office")

# Psychrometric properties (psychrolib)
psych = get_psychrometrics(tdb=25.0, rh=0.50)

# Blend advanced results into Global IEQ Index
result = calculate_global_ieq(
    thermal=thermal, visual=visual, acoustic=acoustic, iaq=iaq,
    reverberation=reverb, speech_intelligibility=sti, ventilation=vent,
)

Additional Domain Modules

Pollutant IAQ

Evaluate PM2.5, PM10, TVOC, formaldehyde, and CO against health-based thresholds:

from comfio import evaluate_iaq_pollutants

pollutant = evaluate_iaq_pollutants(
    pm25=np.array([8.0, 12.0, 35.0]),
    tvoc=np.array([150.0, 300.0, 500.0]),
    formaldehyde=np.array([20.0, 27.0, 50.0]),
    co=np.array([1.5, 5.0, 10.0]),
    threshold_level="good",
)
print(f"Pollutant IAQ score: {pollutant.score}")

Adaptive Thermal Comfort

from comfio import evaluate_adaptive_ashrae, evaluate_adaptive_en

# ASHRAE 55-2023 (naturally ventilated buildings)
ashrae = evaluate_adaptive_ashrae(
    tdb=np.array([24.0, 25.0, 26.0]),
    tr=np.array([24.0, 25.0, 26.0]),
    t_prevail=20.0,       # prevailing mean outdoor temp
    acceptability=80,
)

# EN 16798-1:2019
en = evaluate_adaptive_en(
    tdb=np.array([24.0, 25.0, 26.0]),
    tr=np.array([24.0, 25.0, 26.0]),
    t_running_mean=20.0,
    category="ii",
)

Simplified PMV (sPMV)

from comfio import evaluate_spmv

spmv = evaluate_spmv(
    indoor_temp=np.array([23.0, 24.0, 25.0]),
    indoor_rh=np.array([50.0, 50.0, 50.0]),
    season="mid",  # or "winter" / "summer"
)
print(f"sPMV: {spmv.spmv}, score: {spmv.score}")

TSV Augmentation & Evaluation

from comfio import augment_tsv_cdf, evaluate_tsv

# Augment sparse occupant votes to dense sensor timestamps
augmented = augment_tsv_cdf(
    sparse_votes=np.array([-2, -1, 0, 0, 1, 1, 2, -1, 0, 1]),
    vote_timestamps=np.arange(10),
    target_timestamps=np.arange(100),  # dense sensor timestamps
)

# Evaluate TSV for compliance (ASHRAE 55-2023 Appendix L)
tsv_result = evaluate_tsv(augmented)
print(f"Mean TSV: {tsv_result.mean_tsv}")
print(f"Compliance rate: {tsv_result.compliance_rate:.1%}")

Personalised Thermal Comfort

from comfio import train_personalisation, evaluate_personalised_pmv

# Train: fit OLS regression TSV = alpha * PMV + beta
index = train_personalisation(
    pmv=historical_pmv_array,
    tsv=historical_tsv_array,
)

# Apply: personalise future PMV predictions
result = evaluate_personalised_pmv(
    tdb=tdb, tr=tr, vr=vr, rh=rh, met=1.2, clo=0.5,
    personalisation_index=index,
)
print(f"Personalised PMV: {result.personalised_pmv}")

Integration with Global IEQ Index

from comfio import calculate_global_ieq

ieq = calculate_global_ieq(
    thermal=thermal_res,
    visual=visual_res,
    acoustic=acoustic_res,
    iaq=iaq_res,
    pollutant_iaq=pollutant_res,  # blends 50/50 with IAQ score
    tsv=tsv_res,                  # overrides thermal score (occupant feedback is ground truth)
)

Newest Features

Local Thermal Discomfort

Ankle draft and vertical temperature gradient — the two local discomfort indices required for full ISO 7730 / ASHRAE 55 compliance:

from comfio import evaluate_ankle_draft, evaluate_vertical_gradient, local_discomfort_score

# Ankle draft (ASHRAE 55-2023 §5.3.3)
ad = evaluate_ankle_draft(
    tdb=np.array([24.0, 25.0]),
    tr=np.array([24.0, 25.0]),
    vr=np.array([0.1, 0.1]),
    rh=np.array([50.0, 50.0]),
    met=1.2, clo=0.5,
    v_ankle=np.array([0.15, 0.30]),
)
print(f"Ankle draft PPD: {ad.ppd_ad}")

# Vertical temperature gradient (ISO 7730 §6.1)
vg = evaluate_vertical_gradient(
    tdb=np.array([24.0, 25.0]),
    tr=np.array([24.0, 25.0]),
    vr=np.array([0.1, 0.1]),
    rh=np.array([50.0, 50.0]),
    met=1.2, clo=0.5,
    vertical_tmp_grad=np.array([2.0, 7.0]),
)

# Combined local discomfort score (0-100)
score = local_discomfort_score(ppd_ad=ad.ppd_ad, ppd_vg=vg.ppd_vg)

Weather Integration (meteostat)

Fetch historical outdoor temperature for adaptive comfort models — no more manual t_prevail / t_running_mean calculation:

from datetime import date
from comfio import fetch_prevailing_temp, fetch_running_mean

# ASHRAE 55 prevailing mean (7-day arithmetic mean)
t_prevail = fetch_prevailing_temp(
    lat=50.11, lon=8.68,          # Frankfurt
    end_date=date(2025, 6, 30),
    days=7,
)

# EN 16798-1 running mean (exponentially weighted, α=0.8)
t_rm = fetch_running_mean(
    lat=50.11, lon=8.68,
    end_date=date(2025, 6, 30),
)

# Feed directly into adaptive comfort evaluation
from comfio import evaluate_adaptive_ashrae
result = evaluate_adaptive_ashrae(
    tdb=np.array([24.0, 25.0, 26.0]),
    tr=np.array([24.0, 25.0, 26.0]),
    t_prevail=float(t_prevail),
)

Results are cached under ~/.cache/comfio/weather/ to minimize network calls.

Result Serialization

All Result dataclasses now provide to_dict(), to_json(), and to_dataframe():

from comfio import evaluate_thermal
import numpy as np

result = evaluate_thermal(
    tdb=np.array([24.0, 25.0]),
    tr=np.array([24.0, 25.0]),
    vr=np.array([0.1, 0.1]),
    rh=np.array([50.0, 50.0]),
    met=1.2, clo=0.5,
)

result.to_dict()         # → {"pmv": ..., "ppd": ..., ...}
result.to_json()         # → JSON string (numpy arrays → lists)
result.to_dataframe()    # → pandas.DataFrame

Logging

comfio now uses Python's logging module. Pipeline failures that were previously silent are now logged:

import comfio
comfio.setup_logging(level="INFO")  # see pipeline warnings in stderr

Architecture

comfio operates on a 4-layer data flow:

Layer 1: Data Ingestion (SensorData)
    ↓ Pandas/NumPy time-series arrays
Layer 2: Single-Domain Modules (domains/)
    ↓ Thermal (pythermalcomfort) | Visual (EN 12464-1) | Acoustic (NC) | IAQ (ASHRAE 62.1)
Layer 3: Multi-Domain Integration (integration/)
    ↓ Global IEQ Index (0-100) with configurable weighting
Layer 4: Application & Contracts (performance/)
    → Compliance rates, JSON reports, smart contract ABI schemas

Key design principle — Decoupling: integration/ only talks to domains/, never to pythermalcomfort directly. If pythermalcomfort releases a breaking change, only domains/thermal.py needs updating.

Weighting Presets

Preset Thermal IAQ Visual Acoustic Use Case
default 40% 25% 20% 15% General (Pierson et al. 2019)
equal 25% 25% 25% 25% Equal weighting
school 27% 26% 24% 23% School children (Yang et al. 2020)
office 45% 30% 15% 10% Office workers
healthcare 25% 40% 15% 20% Healthcare facilities
from comfio.integration.weights import preset_weights, custom_weights

weights = preset_weights("office")
weights = custom_weights(thermal=0.5, visual=0.2, acoustic=0.1, iaq=0.2)

Standards Referenced

  • ISO 7730: Thermal comfort — PMV/PPD calculation
  • ASHRAE 55: Thermal environmental conditions for human occupancy
  • ASHRAE 55-2023 Appendix L: TSV compliance threshold (|TSV| ≤ 1.5)
  • EN 16798-1:2019: Adaptive thermal comfort for naturally ventilated buildings
  • EN 12464-1: Light and lighting — lighting of work places
  • ASHRAE 62.1: Ventilation for acceptable indoor air quality
  • WHO Air Quality Guidelines (2021): PM2.5, PM10 thresholds
  • EPA NAAQS: Criteria pollutant thresholds
  • WELL Building Standard v2: Feature A01 pollutant thresholds

Academic Attribution

comfio utilizes the validated pythermalcomfort library as its core engine for thermal metrics, while focusing its novel architecture on multi-domain integration and temporal performance evaluation.

Tartarini, F., Schiavon, S., 2020. pythermalcomfort: A Python package for thermal comfort research. SoftwareX 12, 100578. https://doi.org/10.1016/j.softx.2020.100578

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Lint
ruff check src/ tests/
ruff format src/ tests/

# Type check
mypy src/comfio/

# Build
python -m build

Citation

A formal academic paper for comfio is in preparation. In the meantime, if you use comfio in your research, please cite it as:

@software{comfio,
  author       = {ABO ALZAHAB, Nibras},
  title        = {comfio: A Multi-Domain IEQ \& Performance Contract Framework for Smart Buildings},
  year         = {2026},
  url          = {https://github.com/NibrasAz7/comfio},
  version      = {0.1.6},
}

Per-function citation

comfio wraps and implements methods from multiple peer-reviewed sources. When you use a specific function, please also cite the underlying work:

comfio function Underlying method Reference
evaluate_thermal Fanger PMV/PPD Fanger (1970); ISO 7730:2005; pythermalcomfort — Tartarini & Schiavon (2020)
evaluate_spmv Simplified PMV Buratti, Ricciardi & Vergoni (2009), Building and Environment 44(3), 441–449
evaluate_adaptive_ashrae ASHRAE 55 adaptive de Dear & Brager (1998), ASHRAE RP-884; ASHRAE 55-2023 Appendix L
evaluate_adaptive_en EN 16798-1 adaptive Nicol & Humphreys (2010), Energy and Buildings 42(10), 1793–1801; EN 16798-1:2019
evaluate_visual Illuminance & UGR EN 12464-1:2021; CIE 117-1995 (UGR)
evaluate_acoustic Noise Criteria Beranek (1957), Noise Control 3(1), 19–27; ASHRAE Handbook — HVAC Applications
evaluate_iaq CO₂ ventilation indicator ASHRAE 62.1-2022; Persily (2015), Building and Environment 91, 61–69
evaluate_pollutant_iaq PM2.5/TVOC/HCHO/CO WHO (2021), Global air quality guidelines; WHO (2010), IAQ selected pollutants
evaluate_color_quality CRI / CCT / D_uv CIE 13.3-1995; CIE 015:2018
evaluate_reverberation RT60 (Sabine/Eyring) Sabine (1922); Eyring (1930), JASA 1(2A), 217–241; ISO 3382-2:2008
evaluate_speech_intelligibility STI Houtgast & Steeneken (1971), Acustica 25, 355–367; IEC 60268-16:2020
evaluate_ventilation CO₂ decay method ASHRAE 62.1-2022; ASTM D7297-14
get_psychrometrics Psychrometric properties Hyland & Wexler (1983), ASHRAE Transactions 89(2A); PsychroLib
calculate_global_ieq Weighted IEQ index Pierson et al. (2019), Building and Environment 150, 230–239
train_personalisation OLS personalisation Schweiker et al. (2020), Building and Environment 176, 106834
augment_tsv_cdf CDF remapping ASHRAE 55-2023 Appendix L

BibTeX entries for the most commonly cited works:

@book{fanger1970,
  author    = {Fanger, Povl Ole},
  title     = {Thermal Comfort},
  publisher = {Danish Technical Press},
  year      = {1970},
}

@article{tartarini2020,
  author  = {Tartarini, Federico and Schiavon, Stefano},
  title   = {pythermalcomfort: A Python package for thermal comfort research},
  journal = {SoftwareX},
  volume  = {12},
  pages   = {100578},
  year    = {2020},
  doi     = {10.1016/j.softx.2020.100578},
}

@article{buratti2009,
  author  = {Buratti, C. and Ricciardi, P. and Vergoni, M.},
  title   = {Simplified PMV model for HVAC systems control},
  journal = {Building and Environment},
  volume  = {44},
  number  = {3},
  pages   = {441--449},
  year    = {2009},
}

@article{dedear1998,
  author  = {de Dear, R. and Brager, G. S.},
  title   = {Developing an adaptive model of thermal comfort and preference},
  journal = {ASHRAE Transactions},
  volume  = {104},
  number  = {1},
  year    = {1998},
}

@article{pierson2019,
  author  = {Pierson, A. and others},
  title   = {Indoor environmental quality: Development of a weight-based scoring system},
  journal = {Building and Environment},
  volume  = {150},
  pages   = {230--239},
  year    = {2019},
}

@misc{who2021,
  author       = {{World Health Organization}},
  title        = {WHO global air quality guidelines},
  year         = {2021},
  url          = {https://www.who.int/publications/i/item/9789240034221},
}

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages