comfio 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- comfio-0.1.0/.gitignore +35 -0
- comfio-0.1.0/CHANGELOG.md +33 -0
- comfio-0.1.0/CITATION.cff +27 -0
- comfio-0.1.0/LICENSE +21 -0
- comfio-0.1.0/PKG-INFO +482 -0
- comfio-0.1.0/README.md +416 -0
- comfio-0.1.0/pyproject.toml +139 -0
- comfio-0.1.0/src/comfio/__init__.py +155 -0
- comfio-0.1.0/src/comfio/core/__init__.py +1 -0
- comfio-0.1.0/src/comfio/core/data_handler.py +297 -0
- comfio-0.1.0/src/comfio/core/exceptions.py +32 -0
- comfio-0.1.0/src/comfio/domains/__init__.py +21 -0
- comfio-0.1.0/src/comfio/domains/acoustic.py +153 -0
- comfio-0.1.0/src/comfio/domains/acoustic_advanced.py +304 -0
- comfio-0.1.0/src/comfio/domains/iaq.py +175 -0
- comfio-0.1.0/src/comfio/domains/iaq_advanced.py +347 -0
- comfio-0.1.0/src/comfio/domains/iaq_pollutants.py +312 -0
- comfio-0.1.0/src/comfio/domains/thermal.py +239 -0
- comfio-0.1.0/src/comfio/domains/thermal_adaptive.py +365 -0
- comfio-0.1.0/src/comfio/domains/thermal_personal.py +570 -0
- comfio-0.1.0/src/comfio/domains/thermal_spmv.py +233 -0
- comfio-0.1.0/src/comfio/domains/thermal_tsv.py +306 -0
- comfio-0.1.0/src/comfio/domains/visual.py +230 -0
- comfio-0.1.0/src/comfio/domains/visual_advanced.py +382 -0
- comfio-0.1.0/src/comfio/integration/__init__.py +1 -0
- comfio-0.1.0/src/comfio/integration/global_ieq.py +290 -0
- comfio-0.1.0/src/comfio/integration/weights.py +173 -0
- comfio-0.1.0/src/comfio/llm/__init__.py +30 -0
- comfio-0.1.0/src/comfio/llm/interpreters.py +259 -0
- comfio-0.1.0/src/comfio/llm/prompts.py +71 -0
- comfio-0.1.0/src/comfio/llm/tools.py +708 -0
- comfio-0.1.0/src/comfio/ml/__init__.py +1 -0
- comfio-0.1.0/src/comfio/ml/keras_adapter.py +206 -0
- comfio-0.1.0/src/comfio/ml/sklearn_transformers.py +197 -0
- comfio-0.1.0/src/comfio/ml/torch_dataset.py +197 -0
- comfio-0.1.0/src/comfio/performance/__init__.py +1 -0
- comfio-0.1.0/src/comfio/performance/contract_schema.py +190 -0
- comfio-0.1.0/src/comfio/performance/contracts.py +263 -0
- comfio-0.1.0/src/comfio/utils/__init__.py +1 -0
- comfio-0.1.0/src/comfio/utils/units.py +168 -0
- comfio-0.1.0/src/comfio/utils/validation.py +313 -0
- comfio-0.1.0/tests/conftest.py +178 -0
- comfio-0.1.0/tests/test_core/test_data_handler.py +101 -0
- comfio-0.1.0/tests/test_domains/test_acoustic.py +62 -0
- comfio-0.1.0/tests/test_domains/test_acoustic_advanced.py +181 -0
- comfio-0.1.0/tests/test_domains/test_iaq.py +60 -0
- comfio-0.1.0/tests/test_domains/test_iaq_advanced.py +158 -0
- comfio-0.1.0/tests/test_domains/test_iaq_pollutants.py +67 -0
- comfio-0.1.0/tests/test_domains/test_thermal.py +123 -0
- comfio-0.1.0/tests/test_domains/test_thermal_adaptive.py +128 -0
- comfio-0.1.0/tests/test_domains/test_thermal_personal.py +146 -0
- comfio-0.1.0/tests/test_domains/test_thermal_spmv.py +86 -0
- comfio-0.1.0/tests/test_domains/test_thermal_tsv.py +116 -0
- comfio-0.1.0/tests/test_domains/test_visual.py +81 -0
- comfio-0.1.0/tests/test_domains/test_visual_advanced.py +132 -0
- comfio-0.1.0/tests/test_integration/test_global_ieq.py +114 -0
- comfio-0.1.0/tests/test_integration/test_global_ieq_new.py +52 -0
- comfio-0.1.0/tests/test_llm/test_interpreters.py +127 -0
- comfio-0.1.0/tests/test_llm/test_prompts.py +51 -0
- comfio-0.1.0/tests/test_llm/test_tools.py +125 -0
- comfio-0.1.0/tests/test_ml/test_keras.py +51 -0
- comfio-0.1.0/tests/test_ml/test_sklearn.py +57 -0
- comfio-0.1.0/tests/test_ml/test_torch.py +76 -0
- comfio-0.1.0/tests/test_performance/test_contracts.py +123 -0
- comfio-0.1.0/tests/test_utils/test_units.py +75 -0
- comfio-0.1.0/tests/test_utils/test_validation.py +133 -0
comfio-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# IDE
|
|
18
|
+
.idea/
|
|
19
|
+
.vscode/
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
|
|
23
|
+
# Testing
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.coverage
|
|
26
|
+
htmlcov/
|
|
27
|
+
.mypy_cache/
|
|
28
|
+
.ruff_cache/
|
|
29
|
+
|
|
30
|
+
# Documentation
|
|
31
|
+
site/
|
|
32
|
+
|
|
33
|
+
# OS
|
|
34
|
+
.DS_Store
|
|
35
|
+
Thumbs.db
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to comfio will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2025-07-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Multi-domain IEQ framework: thermal, visual, acoustic, IAQ
|
|
13
|
+
- Thermal comfort scoring via PMV/PPD (ISO 7730, ASHRAE 55)
|
|
14
|
+
- Simplified PMV (sPMV) with seasonal Buratti model
|
|
15
|
+
- Adaptive thermal comfort (ASHRAE 55-2023, EN 16798-1:2019)
|
|
16
|
+
- Personalised thermal comfort via OLS regression
|
|
17
|
+
- TSV augmentation with CDF remapping
|
|
18
|
+
- IAQ pollutant scoring (PM2.5, PM10, TVOC, formaldehyde, CO)
|
|
19
|
+
- Advanced psychrometrics via psychrolib
|
|
20
|
+
- Ventilation rate estimation from CO₂ decay
|
|
21
|
+
- Global IEQ Index with configurable weighting schemas
|
|
22
|
+
- Performance contract compliance reporting with JSON export
|
|
23
|
+
- LLM-native tool schemas (OpenAI function calling, LangChain)
|
|
24
|
+
- scikit-learn transformer for IEQ feature extraction
|
|
25
|
+
- PyTorch dataset and Keras preprocessing layer for ML pipelines
|
|
26
|
+
- Sensor data handler with unit validation
|
|
27
|
+
- Comprehensive doctests across all domain modules
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Psychrolib 2.5.0 + numba 0.65 compatibility (pure Python fallback)
|
|
32
|
+
- Doctest expected values corrected for thermal, adaptive, sPMV, and IAQ scores
|
|
33
|
+
- ML adapter doctests marked `+SKIP` for optional dependencies
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use comfio in your research, please cite it as below. A formal academic paper is in preparation."
|
|
3
|
+
title: "comfio: A Multi-Domain IEQ & Performance Contract Framework for Smart Buildings"
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- name: "comfio Contributors"
|
|
7
|
+
repository-code: "https://github.com/NibrasAz7/Comfio"
|
|
8
|
+
url: "https://github.com/NibrasAz7/Comfio"
|
|
9
|
+
version: "0.1.0"
|
|
10
|
+
date-released: "2025-07-05"
|
|
11
|
+
license: MIT
|
|
12
|
+
keywords:
|
|
13
|
+
- thermal comfort
|
|
14
|
+
- indoor environmental quality
|
|
15
|
+
- IEQ
|
|
16
|
+
- smart buildings
|
|
17
|
+
- performance contracts
|
|
18
|
+
- ASHRAE
|
|
19
|
+
- ISO 7730
|
|
20
|
+
- adaptive comfort
|
|
21
|
+
preferred-citation:
|
|
22
|
+
type: software
|
|
23
|
+
title: "comfio: A Multi-Domain IEQ & Performance Contract Framework for Smart Buildings"
|
|
24
|
+
authors:
|
|
25
|
+
- name: "comfio Contributors"
|
|
26
|
+
year: 2025
|
|
27
|
+
url: "https://github.com/NibrasAz7/Comfio"
|
comfio-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ComfortPy Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
comfio-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: comfio
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
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.
|
|
5
|
+
Project-URL: Homepage, https://github.com/NibrasAz7/Comfio
|
|
6
|
+
Project-URL: Documentation, https://github.com/NibrasAz7/Comfio#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/NibrasAz7/Comfio.git
|
|
8
|
+
Project-URL: Issues, https://github.com/NibrasAz7/Comfio/issues
|
|
9
|
+
Author: comfio Contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
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
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: numba<0.66,>=0.65
|
|
26
|
+
Requires-Dist: numpy<2.3,>=2.2
|
|
27
|
+
Requires-Dist: pandas>=2.0
|
|
28
|
+
Requires-Dist: pythermalcomfort>=4.0
|
|
29
|
+
Provides-Extra: acoustics
|
|
30
|
+
Requires-Dist: acoustics>=0.2; extra == 'acoustics'
|
|
31
|
+
Requires-Dist: pyroomacoustics>=0.7; extra == 'acoustics'
|
|
32
|
+
Provides-Extra: agent
|
|
33
|
+
Requires-Dist: pydantic>=2.0; extra == 'agent'
|
|
34
|
+
Provides-Extra: all
|
|
35
|
+
Requires-Dist: acoustics>=0.2; extra == 'all'
|
|
36
|
+
Requires-Dist: colour-science>=0.4; extra == 'all'
|
|
37
|
+
Requires-Dist: psychrolib<2.6,>=2.5; extra == 'all'
|
|
38
|
+
Requires-Dist: pydantic>=2.0; extra == 'all'
|
|
39
|
+
Requires-Dist: pyradiance>=1.0; extra == 'all'
|
|
40
|
+
Requires-Dist: pyroomacoustics>=0.7; extra == 'all'
|
|
41
|
+
Requires-Dist: scikit-learn>=1.3; extra == 'all'
|
|
42
|
+
Requires-Dist: tensorflow>=2.15; extra == 'all'
|
|
43
|
+
Requires-Dist: torch>=2.0; extra == 'all'
|
|
44
|
+
Provides-Extra: color
|
|
45
|
+
Requires-Dist: colour-science>=0.4; extra == 'color'
|
|
46
|
+
Provides-Extra: daylighting
|
|
47
|
+
Requires-Dist: pyradiance>=1.0; extra == 'daylighting'
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
50
|
+
Requires-Dist: mkdocs-material>=9.0; extra == 'dev'
|
|
51
|
+
Requires-Dist: mkdocs>=1.5; extra == 'dev'
|
|
52
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
53
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
54
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
55
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
56
|
+
Requires-Dist: twine>=4.0; extra == 'dev'
|
|
57
|
+
Provides-Extra: keras
|
|
58
|
+
Requires-Dist: tensorflow>=2.15; extra == 'keras'
|
|
59
|
+
Provides-Extra: ml
|
|
60
|
+
Requires-Dist: scikit-learn>=1.3; extra == 'ml'
|
|
61
|
+
Provides-Extra: psychrometrics
|
|
62
|
+
Requires-Dist: psychrolib<2.6,>=2.5; extra == 'psychrometrics'
|
|
63
|
+
Provides-Extra: torch
|
|
64
|
+
Requires-Dist: torch>=2.0; extra == 'torch'
|
|
65
|
+
Description-Content-Type: text/markdown
|
|
66
|
+
|
|
67
|
+
# comfio
|
|
68
|
+
|
|
69
|
+
**A multi-domain IEQ & performance contract framework for smart buildings.**
|
|
70
|
+
|
|
71
|
+
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**.
|
|
72
|
+
|
|
73
|
+
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.
|
|
74
|
+
|
|
75
|
+
## Why comfio?
|
|
76
|
+
|
|
77
|
+
- **Silo-Breaking**: Unifies separated domains (Thermal, Acoustic, Visual, IAQ) under a single Python API
|
|
78
|
+
- **Data-Native**: Built to ingest massive arrays of time-series data (Pandas/NumPy) rather than single-point calculations
|
|
79
|
+
- **Actionable Output**: Translates physical equations into compliance rates for building performance contracts
|
|
80
|
+
- **Smart Contract Ready**: Generates structured JSON outputs with formal ABI schemas for blockchain Oracle integration
|
|
81
|
+
- **ML/DL Compatible**: NumPy-native core with optional adapters for scikit-learn, PyTorch, and TensorFlow/Keras
|
|
82
|
+
- **Advanced Physics Modules**: Optional extras for Radiance daylighting, CRI/CCT color quality, RT60 reverberation, STI speech intelligibility, CO₂ decay ventilation, and full psychrometrics
|
|
83
|
+
- **Pollutant IAQ**: PM2.5, PM10, TVOC, formaldehyde, and CO evaluation against WHO, EPA NAAQS, and WELL Building Standard v2 thresholds
|
|
84
|
+
- **Adaptive Thermal Comfort**: ASHRAE 55-2023 and EN 16798-1:2019 adaptive models for naturally ventilated buildings
|
|
85
|
+
- **Simplified PMV (sPMV)**: Buratti et al. (2009) seasonal model requiring only temperature and humidity
|
|
86
|
+
- **TSV Augmentation**: CDF-based remapping (quantile mapping) to augment sparse occupant votes to dense sensor timestamps while preserving the empirical distribution
|
|
87
|
+
- **Personalised Comfort**: OLS regression-based personalisation of model predictions to match occupant feedback (TSV), with per-season support
|
|
88
|
+
- **Fast & Light**: Core depends only on numpy, pandas, and pythermalcomfort
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pip install comfio
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
With ML/DL framework support:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install comfio[ml] # scikit-learn
|
|
100
|
+
pip install comfio[torch] # PyTorch
|
|
101
|
+
pip install comfio[keras] # TensorFlow/Keras
|
|
102
|
+
pip install comfio[all] # All frameworks + advanced domains
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Advanced physics-based domain evaluation (optional extras):
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pip install comfio[daylighting] # pyradiance (Radiance ray-tracing)
|
|
109
|
+
pip install comfio[color] # colour-science (CRI, CCT)
|
|
110
|
+
pip install comfio[acoustics] # python-acoustics + pyroomacoustics (RT60, STI)
|
|
111
|
+
pip install comfio[psychrometrics] # PsychroLib (psychrometric properties, CO₂ decay ACH)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Quick Start
|
|
115
|
+
|
|
116
|
+
### 1. Evaluate Individual Domains
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
import numpy as np
|
|
120
|
+
from comfio import evaluate_thermal, evaluate_visual, evaluate_acoustic, evaluate_iaq
|
|
121
|
+
|
|
122
|
+
# Thermal comfort (ISO 7730 / ASHRAE 55)
|
|
123
|
+
thermal = evaluate_thermal(
|
|
124
|
+
tdb=np.array([24.0, 25.0, 26.0]), # air temp °C
|
|
125
|
+
tr=np.array([24.0, 25.0, 26.0]), # radiant temp °C
|
|
126
|
+
vr=np.array([0.1, 0.1, 0.1]), # air velocity m/s
|
|
127
|
+
rh=np.array([50.0, 50.0, 50.0]), # relative humidity %
|
|
128
|
+
met=1.2, # metabolic rate
|
|
129
|
+
clo=0.5, # clothing insulation
|
|
130
|
+
category="B", # ISO 7730 category
|
|
131
|
+
)
|
|
132
|
+
print(f"PMV: {thermal.pmv}, PPD: {thermal.ppd}")
|
|
133
|
+
|
|
134
|
+
# Visual comfort (EN 12464-1)
|
|
135
|
+
visual = evaluate_visual(
|
|
136
|
+
illuminance=np.array([450.0, 500.0, 600.0]),
|
|
137
|
+
task_type="office_writing",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Acoustic comfort (NC curves)
|
|
141
|
+
acoustic = evaluate_acoustic(
|
|
142
|
+
laeq=np.array([35.0, 40.0, 45.0]),
|
|
143
|
+
nc_level="NC-35",
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# IAQ (ASHRAE 62.1 indicators)
|
|
147
|
+
iaq = evaluate_iaq(
|
|
148
|
+
co2=np.array([700.0, 900.0, 1100.0]),
|
|
149
|
+
threshold_level="good",
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 2. Calculate Global IEQ Index
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from comfio import calculate_global_ieq, default_weights
|
|
157
|
+
|
|
158
|
+
# Merge all domains into a single 0-100 score
|
|
159
|
+
ieq = calculate_global_ieq(
|
|
160
|
+
thermal=thermal,
|
|
161
|
+
visual=visual,
|
|
162
|
+
acoustic=acoustic,
|
|
163
|
+
iaq=iaq,
|
|
164
|
+
weights=default_weights(), # thermal=40%, iaq=25%, visual=20%, acoustic=15%
|
|
165
|
+
)
|
|
166
|
+
print(f"Global IEQ Index: {ieq.index}")
|
|
167
|
+
print(f"Domain scores: {ieq.domain_scores}")
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 3. Compliance Tracking & Contract Outputs
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
from comfio import calculate_compliance
|
|
174
|
+
|
|
175
|
+
report = calculate_compliance(ieq, threshold=80.0)
|
|
176
|
+
print(f"Compliance rate: {report.compliance_rate_pct:.1f}%")
|
|
177
|
+
print(f"Average IEQ: {report.ieq_index_avg:.1f}")
|
|
178
|
+
|
|
179
|
+
# Generate JSON for blockchain Oracle
|
|
180
|
+
contract_json = report.to_contract_json()
|
|
181
|
+
print(contract_json)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 4. Time-Series Data with SensorData
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
import pandas as pd
|
|
188
|
+
from comfio import SensorData
|
|
189
|
+
|
|
190
|
+
# Load your sensor DataFrame
|
|
191
|
+
df = pd.read_csv("sensor_data.csv")
|
|
192
|
+
sensor = SensorData(df=df)
|
|
193
|
+
|
|
194
|
+
# Auto-detects column names (tdb, ta, temperature → air_temp_c, etc.)
|
|
195
|
+
print(sensor.available_domains()) # ['thermal', 'visual', 'acoustic', 'iaq']
|
|
196
|
+
|
|
197
|
+
# Validate data (NaN handling, physical bounds checking)
|
|
198
|
+
sensor.validate()
|
|
199
|
+
clean_temp = sensor.get_validated("air_temp_c")
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## ML/DL Integration
|
|
203
|
+
|
|
204
|
+
### scikit-learn Pipeline
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from sklearn.pipeline import Pipeline
|
|
208
|
+
from sklearn.ensemble import RandomForestRegressor
|
|
209
|
+
from comfio.ml.sklearn_transformers import IEQFeatureExtractor
|
|
210
|
+
|
|
211
|
+
pipe = Pipeline([
|
|
212
|
+
("ieq", IEQFeatureExtractor()),
|
|
213
|
+
("model", RandomForestRegressor()),
|
|
214
|
+
])
|
|
215
|
+
pipe.fit(train_df, train_labels)
|
|
216
|
+
predictions = pipe.predict(test_df)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### PyTorch DataLoader
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from torch.utils.data import DataLoader
|
|
223
|
+
from comfio.ml.torch_dataset import IEQTimeSeriesDataset
|
|
224
|
+
|
|
225
|
+
dataset = IEQTimeSeriesDataset(df, window_size=24, stride=1)
|
|
226
|
+
loader = DataLoader(dataset, batch_size=32, shuffle=True)
|
|
227
|
+
for batch in loader:
|
|
228
|
+
raw = batch["raw"] # (32, 24, n_sensors)
|
|
229
|
+
ieq = batch["ieq_index"] # (32, 24)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### TensorFlow/Keras
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
from comfio.ml.keras_adapter import IEQPreprocessingLayer
|
|
236
|
+
|
|
237
|
+
layer = IEQPreprocessingLayer()
|
|
238
|
+
layer.adapt(train_df)
|
|
239
|
+
features = layer(train_df) # tf.Tensor of IEQ features
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Advanced Domain Evaluation
|
|
243
|
+
|
|
244
|
+
comfio offers optional physics-based modules that go beyond simple threshold checks. These require separate extras but integrate seamlessly with the Global IEQ Index.
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
from comfio import (
|
|
248
|
+
evaluate_reverberation, evaluate_speech_intelligibility,
|
|
249
|
+
evaluate_ventilation, get_psychrometrics,
|
|
250
|
+
calculate_global_ieq,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
# Reverberation time (python-acoustics)
|
|
254
|
+
reverb = evaluate_reverberation(surfaces, absorption, volume, room_type="office")
|
|
255
|
+
|
|
256
|
+
# Speech intelligibility from impulse response (pyroomacoustics)
|
|
257
|
+
sti = evaluate_speech_intelligibility(ir_signal, sample_rate=16000)
|
|
258
|
+
|
|
259
|
+
# Ventilation rate from CO₂ decay (psychrolib)
|
|
260
|
+
vent = evaluate_ventilation(co2_array, timestamps, occupancy_type="office")
|
|
261
|
+
|
|
262
|
+
# Psychrometric properties (psychrolib)
|
|
263
|
+
psych = get_psychrometrics(tdb=25.0, rh=0.50)
|
|
264
|
+
|
|
265
|
+
# Blend advanced results into Global IEQ Index
|
|
266
|
+
result = calculate_global_ieq(
|
|
267
|
+
thermal=thermal, visual=visual, acoustic=acoustic, iaq=iaq,
|
|
268
|
+
reverberation=reverb, speech_intelligibility=sti, ventilation=vent,
|
|
269
|
+
)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
See the [User Guide](https://github.com/NibrasAz7/Comfio#readme) for full documentation.
|
|
273
|
+
|
|
274
|
+
## New Domain Modules
|
|
275
|
+
|
|
276
|
+
### Pollutant IAQ
|
|
277
|
+
|
|
278
|
+
Evaluate PM2.5, PM10, TVOC, formaldehyde, and CO against health-based thresholds:
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
from comfio import evaluate_iaq_pollutants
|
|
282
|
+
|
|
283
|
+
pollutant = evaluate_iaq_pollutants(
|
|
284
|
+
pm25=np.array([8.0, 12.0, 35.0]),
|
|
285
|
+
tvoc=np.array([150.0, 300.0, 500.0]),
|
|
286
|
+
formaldehyde=np.array([20.0, 27.0, 50.0]),
|
|
287
|
+
co=np.array([1.5, 5.0, 10.0]),
|
|
288
|
+
threshold_level="good",
|
|
289
|
+
)
|
|
290
|
+
print(f"Pollutant IAQ score: {pollutant.score}")
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Adaptive Thermal Comfort
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
from comfio import evaluate_adaptive_ashrae, evaluate_adaptive_en
|
|
297
|
+
|
|
298
|
+
# ASHRAE 55-2023 (naturally ventilated buildings)
|
|
299
|
+
ashrae = evaluate_adaptive_ashrae(
|
|
300
|
+
tdb=np.array([24.0, 25.0, 26.0]),
|
|
301
|
+
tr=np.array([24.0, 25.0, 26.0]),
|
|
302
|
+
t_prevail=20.0, # prevailing mean outdoor temp
|
|
303
|
+
acceptability=80,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
# EN 16798-1:2019
|
|
307
|
+
en = evaluate_adaptive_en(
|
|
308
|
+
tdb=np.array([24.0, 25.0, 26.0]),
|
|
309
|
+
tr=np.array([24.0, 25.0, 26.0]),
|
|
310
|
+
t_running_mean=20.0,
|
|
311
|
+
category="ii",
|
|
312
|
+
)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Simplified PMV (sPMV)
|
|
316
|
+
|
|
317
|
+
```python
|
|
318
|
+
from comfio import evaluate_spmv
|
|
319
|
+
|
|
320
|
+
spmv = evaluate_spmv(
|
|
321
|
+
indoor_temp=np.array([23.0, 24.0, 25.0]),
|
|
322
|
+
indoor_rh=np.array([50.0, 50.0, 50.0]),
|
|
323
|
+
season="mid", # or "winter" / "summer"
|
|
324
|
+
)
|
|
325
|
+
print(f"sPMV: {spmv.spmv}, score: {spmv.score}")
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### TSV Augmentation & Evaluation
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
from comfio import augment_tsv_cdf, evaluate_tsv
|
|
332
|
+
|
|
333
|
+
# Augment sparse occupant votes to dense sensor timestamps
|
|
334
|
+
augmented = augment_tsv_cdf(
|
|
335
|
+
sparse_votes=np.array([-2, -1, 0, 0, 1, 1, 2, -1, 0, 1]),
|
|
336
|
+
vote_timestamps=np.arange(10),
|
|
337
|
+
target_timestamps=np.arange(100), # dense sensor timestamps
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
# Evaluate TSV for compliance (ASHRAE 55-2023 Appendix L)
|
|
341
|
+
tsv_result = evaluate_tsv(augmented)
|
|
342
|
+
print(f"Mean TSV: {tsv_result.mean_tsv}")
|
|
343
|
+
print(f"Compliance rate: {tsv_result.compliance_rate:.1%}")
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Personalised Thermal Comfort
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
from comfio import train_personalisation, evaluate_personalised_pmv
|
|
350
|
+
|
|
351
|
+
# Train: fit OLS regression TSV = alpha * PMV + beta
|
|
352
|
+
index = train_personalisation(
|
|
353
|
+
pmv=historical_pmv_array,
|
|
354
|
+
tsv=historical_tsv_array,
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
# Apply: personalise future PMV predictions
|
|
358
|
+
result = evaluate_personalised_pmv(
|
|
359
|
+
tdb=tdb, tr=tr, vr=vr, rh=rh, met=1.2, clo=0.5,
|
|
360
|
+
personalisation_index=index,
|
|
361
|
+
)
|
|
362
|
+
print(f"Personalised PMV: {result.personalised_pmv}")
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Integration with Global IEQ Index
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
from comfio import calculate_global_ieq
|
|
369
|
+
|
|
370
|
+
ieq = calculate_global_ieq(
|
|
371
|
+
thermal=thermal_res,
|
|
372
|
+
visual=visual_res,
|
|
373
|
+
acoustic=acoustic_res,
|
|
374
|
+
iaq=iaq_res,
|
|
375
|
+
pollutant_iaq=pollutant_res, # blends 50/50 with IAQ score
|
|
376
|
+
tsv=tsv_res, # overrides thermal score (occupant feedback is ground truth)
|
|
377
|
+
)
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Architecture
|
|
381
|
+
|
|
382
|
+
comfio operates on a **4-layer data flow**:
|
|
383
|
+
|
|
384
|
+
```text
|
|
385
|
+
Layer 1: Data Ingestion (SensorData)
|
|
386
|
+
↓ Pandas/NumPy time-series arrays
|
|
387
|
+
Layer 2: Single-Domain Modules (domains/)
|
|
388
|
+
↓ Thermal (pythermalcomfort) | Visual (EN 12464-1) | Acoustic (NC) | IAQ (ASHRAE 62.1)
|
|
389
|
+
Layer 3: Multi-Domain Integration (integration/)
|
|
390
|
+
↓ Global IEQ Index (0-100) with configurable weighting
|
|
391
|
+
Layer 4: Application & Contracts (performance/)
|
|
392
|
+
→ Compliance rates, JSON reports, smart contract ABI schemas
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**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.
|
|
396
|
+
|
|
397
|
+
## Weighting Presets
|
|
398
|
+
|
|
399
|
+
| Preset | Thermal | IAQ | Visual | Acoustic | Use Case |
|
|
400
|
+
|---|---|---|---|---|---|
|
|
401
|
+
| `default` | 40% | 25% | 20% | 15% | General (Pierson et al. 2019) |
|
|
402
|
+
| `equal` | 25% | 25% | 25% | 25% | Equal weighting |
|
|
403
|
+
| `school` | 27% | 26% | 24% | 23% | School children (Yang et al. 2020) |
|
|
404
|
+
| `office` | 45% | 30% | 15% | 10% | Office workers |
|
|
405
|
+
| `healthcare` | 25% | 40% | 15% | 20% | Healthcare facilities |
|
|
406
|
+
|
|
407
|
+
```python
|
|
408
|
+
from comfio.integration.weights import preset_weights, custom_weights
|
|
409
|
+
|
|
410
|
+
weights = preset_weights("office")
|
|
411
|
+
weights = custom_weights(thermal=0.5, visual=0.2, acoustic=0.1, iaq=0.2)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Standards Referenced
|
|
415
|
+
|
|
416
|
+
- **ISO 7730**: Thermal comfort — PMV/PPD calculation
|
|
417
|
+
- **ASHRAE 55**: Thermal environmental conditions for human occupancy
|
|
418
|
+
- **ASHRAE 55-2023 Appendix L**: TSV compliance threshold (|TSV| ≤ 1.5)
|
|
419
|
+
- **EN 16798-1:2019**: Adaptive thermal comfort for naturally ventilated buildings
|
|
420
|
+
- **EN 12464-1**: Light and lighting — lighting of work places
|
|
421
|
+
- **ASHRAE 62.1**: Ventilation for acceptable indoor air quality
|
|
422
|
+
- **WHO Air Quality Guidelines (2021)**: PM2.5, PM10 thresholds
|
|
423
|
+
- **EPA NAAQS**: Criteria pollutant thresholds
|
|
424
|
+
- **WELL Building Standard v2**: Feature A01 pollutant thresholds
|
|
425
|
+
|
|
426
|
+
## Academic Attribution
|
|
427
|
+
|
|
428
|
+
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.
|
|
429
|
+
|
|
430
|
+
> 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>
|
|
431
|
+
|
|
432
|
+
## Development
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
# Install with dev dependencies
|
|
436
|
+
pip install -e ".[dev]"
|
|
437
|
+
|
|
438
|
+
# Run tests
|
|
439
|
+
pytest
|
|
440
|
+
|
|
441
|
+
# Lint
|
|
442
|
+
ruff check src/ tests/
|
|
443
|
+
ruff format src/ tests/
|
|
444
|
+
|
|
445
|
+
# Type check
|
|
446
|
+
mypy src/comfio/
|
|
447
|
+
|
|
448
|
+
# Build
|
|
449
|
+
python -m build
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## Citation
|
|
453
|
+
|
|
454
|
+
A formal academic paper for comfio is in preparation. In the meantime, if you use comfio in your research, please cite it as:
|
|
455
|
+
|
|
456
|
+
```bibtex
|
|
457
|
+
@software{comfio,
|
|
458
|
+
author = {comfio Contributors},
|
|
459
|
+
title = {comfio: A Multi-Domain IEQ \& Performance Contract Framework for Smart Buildings},
|
|
460
|
+
year = {2025},
|
|
461
|
+
url = {https://github.com/NibrasAz7/Comfio},
|
|
462
|
+
version = {0.1.0},
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Please also cite the underlying [pythermalcomfort](https://github.com/pythermalcomfort/pythermalcomfort) library:
|
|
467
|
+
|
|
468
|
+
```bibtex
|
|
469
|
+
@article{tartarini2020,
|
|
470
|
+
author = {Tartarini, Federico and Schiavon, Stefano},
|
|
471
|
+
title = {pythermalcomfort: A Python package for thermal comfort research},
|
|
472
|
+
journal = {SoftwareX},
|
|
473
|
+
volume = {12},
|
|
474
|
+
pages = {100578},
|
|
475
|
+
year = {2020},
|
|
476
|
+
doi = {10.1016/j.softx.2020.100578},
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## License
|
|
481
|
+
|
|
482
|
+
MIT — see [LICENSE](LICENSE).
|