Metadata-Version: 2.4
Name: comfio
Version: 0.1.6
Summary: Multi-domain IEQ (Indoor Environmental Quality) and performance contract framework for smart buildings. Includes pollutant IAQ, adaptive thermal comfort, sPMV, TSV augmentation, and personalised comfort models.
Project-URL: Homepage, https://github.com/NibrasAz7/comfio
Project-URL: Documentation, https://github.com/NibrasAz7/comfio#readme
Project-URL: Repository, https://github.com/NibrasAz7/comfio.git
Project-URL: Issues, https://github.com/NibrasAz7/comfio/issues
Author: Nibras Abo Alzahab
License-Expression: MIT
License-File: LICENSE
Keywords: ASHRAE,CDF remapping,EN 12464,EN 16798,IEQ,ISO 7730,PM2.5,TSV,WELL Building Standard,adaptive comfort,air quality,building physics,indoor environmental quality,performance contracts,personalised comfort,smart buildings,thermal comfort
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: meteostat>=2.1
Requires-Dist: numba<0.67,>=0.65
Requires-Dist: numpy<2.5,>=2.2
Requires-Dist: pandas>=2.0
Requires-Dist: pythermalcomfort>=4.0
Provides-Extra: acoustics
Requires-Dist: acoustics>=0.2; extra == 'acoustics'
Requires-Dist: pyroomacoustics>=0.7; extra == 'acoustics'
Provides-Extra: agent
Requires-Dist: pydantic>=2.0; extra == 'agent'
Provides-Extra: all
Requires-Dist: acoustics>=0.2; extra == 'all'
Requires-Dist: colour-science>=0.4; extra == 'all'
Requires-Dist: psychrolib<2.6,>=2.5; extra == 'all'
Requires-Dist: pydantic>=2.0; extra == 'all'
Requires-Dist: pyradiance>=1.0; extra == 'all'
Requires-Dist: pyroomacoustics>=0.7; extra == 'all'
Requires-Dist: scikit-learn>=1.3; extra == 'all'
Requires-Dist: tensorflow>=2.15; extra == 'all'
Requires-Dist: torch>=2.0; extra == 'all'
Provides-Extra: color
Requires-Dist: colour-science>=0.4; extra == 'color'
Provides-Extra: daylighting
Requires-Dist: pyradiance>=1.0; extra == 'daylighting'
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: mkdocs-material>=9.0; extra == 'dev'
Requires-Dist: mkdocs>=1.5; extra == 'dev'
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Provides-Extra: gui
Requires-Dist: ipywidgets>=8.0; extra == 'gui'
Requires-Dist: plotly>=5.18; extra == 'gui'
Requires-Dist: pywebview>=5.0; extra == 'gui'
Requires-Dist: streamlit>=1.30; extra == 'gui'
Provides-Extra: gui-reports
Requires-Dist: python-docx>=1.1; extra == 'gui-reports'
Requires-Dist: reportlab>=4.0; extra == 'gui-reports'
Provides-Extra: keras
Requires-Dist: tensorflow>=2.15; extra == 'keras'
Provides-Extra: ml
Requires-Dist: scikit-learn>=1.3; extra == 'ml'
Provides-Extra: psychrometrics
Requires-Dist: psychrolib<2.6,>=2.5; extra == 'psychrometrics'
Provides-Extra: torch
Requires-Dist: torch>=2.0; extra == 'torch'
Description-Content-Type: text/markdown

# 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

```bash
pip install comfio
```

With ML/DL framework support:

```bash
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):

```bash
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](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/walkthrough_executed.ipynb) |
| `simple_tutorial.ipynb` | Quick start: core domains, Global IEQ Index, compliance | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/simple_tutorial.ipynb) |
| `simple_tutorial_executed.ipynb` | Same as above with pre-run outputs | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/simple_tutorial_executed.ipynb) |
| `advanced_domains_tutorial.ipynb` | Advanced physics: daylighting, CRI/CCT, RT60, STI, ventilation, psychrometrics | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/advanced_domains_tutorial.ipynb) |
| `advanced_domains_tutorial_executed.ipynb` | Same as above with pre-run outputs | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/advanced_domains_tutorial_executed.ipynb) |
| `llm_tutorial.ipynb` | LLM integration: interpreters, prompts, OpenAI/LangChain tool schemas | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/llm_tutorial.ipynb) |
| `llm_tutorial_executed.ipynb` | Same as above with pre-run outputs | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/llm_tutorial_executed.ipynb) |
| `contracts_ml_tutorial.ipynb` | Smart contracts & ML: compliance ABI, web3.py, sklearn/PyTorch/Keras forecasting | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/contracts_ml_tutorial.ipynb) |
| `contracts_ml_tutorial_executed.ipynb` | Same as above with pre-run outputs | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/examples/contracts_ml_tutorial_executed.ipynb) |

### 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](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/docs/tutorials/01_first_contract.ipynb) |
| `02_new_domains.ipynb` | New domains: IAQ pollutants, adaptive thermal comfort, sPMV, TSV augmentation | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/docs/tutorials/02_new_domains.ipynb) |
| `03_training_pcm.ipynb` | Training personal comfort models: OLS personalisation, seasonal personalisation | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/docs/tutorials/03_training_pcm.ipynb) |
| `04_llm_diagnostics.ipynb` | LLM diagnostics: interpreters, prompt templates, edge deployment | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/docs/tutorials/04_llm_diagnostics.ipynb) |
| `05_advanced_domains.ipynb` | Advanced domains: daylighting, color quality, reverberation, speech intelligibility | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/NibrasAz7/comfio/blob/main/docs/tutorials/05_advanced_domains.ipynb) |

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

## Quick Start

### 1. Evaluate Individual Domains

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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.

```python
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,
)
```

See the [User Guide](https://github.com/NibrasAz7/comfio#readme) for full documentation.

## New Domain Modules

### Pollutant IAQ

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

```python
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

```python
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)

```python
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

```python
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

```python
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

```python
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)
)
```

## v0.1.6 New Features

### Local Thermal Discomfort

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

```python
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:

```python
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()`:

```python
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:

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

## Architecture

comfio operates on a **4-layer data flow**:

```text
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 |

```python
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](https://github.com/pythermalcomfort/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

```bash
# 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:

```bibtex
@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](https://github.com/pythermalcomfort/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](https://github.com/psychrometrics/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:**

```bibtex
@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](LICENSE).
