hvx 0.5.0__py3-none-any.whl
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.
- hvx/__init__.py +27 -0
- hvx/__main__.py +7 -0
- hvx/app/__init__.py +7 -0
- hvx/app/analysis_runner.py +102 -0
- hvx/app/api.py +1030 -0
- hvx/app/main.py +345 -0
- hvx/app/state.py +270 -0
- hvx/building_csv.py +214 -0
- hvx/cli.py +349 -0
- hvx/connectors/__init__.py +3 -0
- hvx/connectors/climify.py +188 -0
- hvx/connectors/csv/__init__.py +29 -0
- hvx/connectors/csv/config.yaml +7 -0
- hvx/connectors/csv/data_loader.py +496 -0
- hvx/connectors/csv/portfolio_loader.py +850 -0
- hvx/connectors/dmi.py +124 -0
- hvx/core/__init__.py +257 -0
- hvx/core/access.py +80 -0
- hvx/core/aggregators.py +77 -0
- hvx/core/analysis.py +182 -0
- hvx/core/config/__init__.py +26 -0
- hvx/core/config/loader.py +74 -0
- hvx/core/data_quality.py +487 -0
- hvx/core/energy.py +451 -0
- hvx/core/energy_pricing.py +217 -0
- hvx/core/entities.py +2309 -0
- hvx/core/enums/__init__.py +52 -0
- hvx/core/enums/access.py +31 -0
- hvx/core/enums/analysis.py +49 -0
- hvx/core/enums/country.py +245 -0
- hvx/core/enums/energy.py +62 -0
- hvx/core/enums/rules.py +46 -0
- hvx/core/enums/sensors.py +96 -0
- hvx/core/enums/spatial.py +103 -0
- hvx/core/enums/timeseries.py +118 -0
- hvx/core/filters/__init__.py +17 -0
- hvx/core/filters/opening_hours_filter.py +117 -0
- hvx/core/filters/seasonal_filter.py +295 -0
- hvx/core/filters/time_filter.py +221 -0
- hvx/core/metering.py +310 -0
- hvx/core/py.typed +0 -0
- hvx/core/rules.py +161 -0
- hvx/core/schedules.py +322 -0
- hvx/core/semantics/__init__.py +57 -0
- hvx/core/semantics/brick.py +605 -0
- hvx/core/semantics/ieq.py +294 -0
- hvx/core/semantics/ifc.py +281 -0
- hvx/core/semantics/ifc_guid.py +69 -0
- hvx/core/semantics/mappings.py +254 -0
- hvx/core/semantics/namespaces.py +62 -0
- hvx/core/semantics/ontology/hvx_ieq.ttl +174 -0
- hvx/core/semantics/types.py +37 -0
- hvx/core/simulation.py +80 -0
- hvx/core/spacial_entity.py +1013 -0
- hvx/core/standards_registry.py +410 -0
- hvx/core/timeseries_aggregator.py +318 -0
- hvx/core/utils/calendar.py +55 -0
- hvx/live/__init__.py +41 -0
- hvx/live/base.py +106 -0
- hvx/live/bindings.py +79 -0
- hvx/live/chirpstack.py +373 -0
- hvx/live/limits.py +106 -0
- hvx/live/monitor.py +249 -0
- hvx/live/site.py +285 -0
- hvx/live/sources.py +171 -0
- hvx/mcp_server.py +421 -0
- hvx/reporting/__init__.py +77 -0
- hvx/reporting/aggregate.py +194 -0
- hvx/reporting/analysis.py +565 -0
- hvx/reporting/branding.py +102 -0
- hvx/reporting/brands/baw.yaml +18 -0
- hvx/reporting/builder.py +219 -0
- hvx/reporting/charts.py +480 -0
- hvx/reporting/config.py +158 -0
- hvx/reporting/frames.py +170 -0
- hvx/reporting/i18n.py +304 -0
- hvx/reporting/model.py +216 -0
- hvx/reporting/renderers/__init__.py +68 -0
- hvx/reporting/renderers/html.py +148 -0
- hvx/reporting/renderers/pdf.py +86 -0
- hvx/reporting/renderers/tabular.py +96 -0
- hvx/reporting/templates/report.html.j2 +531 -0
- hvx/simulations/__init__.py +50 -0
- hvx/simulations/config/__init__.py +22 -0
- hvx/simulations/config/registry.py +177 -0
- hvx/simulations/models/__init__.py +37 -0
- hvx/simulations/models/correlations/__init__.py +19 -0
- hvx/simulations/models/correlations/model.py +145 -0
- hvx/simulations/models/correlations/seasonal_thermal_analysis.py +198 -0
- hvx/simulations/models/correlations/solar_gain_analysis.py +291 -0
- hvx/simulations/models/occupancy/__init__.py +11 -0
- hvx/simulations/models/occupancy/config.yaml +77 -0
- hvx/simulations/models/occupancy/model.py +241 -0
- hvx/simulations/models/rc_thermal/__init__.py +13 -0
- hvx/simulations/models/rc_thermal/config.yaml +94 -0
- hvx/simulations/models/rc_thermal/model.py +347 -0
- hvx/simulations/models/real_epc/__init__.py +10 -0
- hvx/simulations/models/real_epc/config.yaml +57 -0
- hvx/simulations/models/real_epc/model.py +72 -0
- hvx/simulations/models/recommendations/__init__.py +20 -0
- hvx/simulations/models/recommendations/model.py +439 -0
- hvx/simulations/models/reporting/__init__.py +18 -0
- hvx/simulations/models/reporting/html_report_service.py +84 -0
- hvx/simulations/models/reporting/json_export_service.py +613 -0
- hvx/simulations/models/scenario/__init__.py +14 -0
- hvx/simulations/models/scenario/model.py +190 -0
- hvx/simulations/models/ventilation/__init__.py +11 -0
- hvx/simulations/models/ventilation/config.yaml +75 -0
- hvx/simulations/models/ventilation/model.py +198 -0
- hvx/simulations/registry.py +267 -0
- hvx/standards/__init__.py +4 -0
- hvx/standards/br18/analysis.py +288 -0
- hvx/standards/br18/config.yaml +234 -0
- hvx/standards/en16798/analysis.py +1499 -0
- hvx/standards/en16798/config.yaml +294 -0
- hvx/standards/tail/aggregate.py +83 -0
- hvx/standards/tail/analysis.py +350 -0
- hvx/standards/tail/calculator.py +1141 -0
- hvx/standards/tail/config.yaml +358 -0
- hvx/standards/tail/docs/TAIL_algorithm.txt +111 -0
- hvx/tail_label.py +303 -0
- hvx-0.5.0.dist-info/METADATA +509 -0
- hvx-0.5.0.dist-info/RECORD +127 -0
- hvx-0.5.0.dist-info/WHEEL +5 -0
- hvx-0.5.0.dist-info/entry_points.txt +2 -0
- hvx-0.5.0.dist-info/licenses/LICENSE +373 -0
- hvx-0.5.0.dist-info/top_level.txt +1 -0
hvx/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
"""
|
|
5
|
+
HVX — indoor environmental quality (IEQ) analytics for buildings.
|
|
6
|
+
|
|
7
|
+
Subpackages
|
|
8
|
+
-----------
|
|
9
|
+
``hvx.core`` data model (Portfolio / Building / Floor / Room), IFC & Brick semantics
|
|
10
|
+
``hvx.standards`` EN 16798-1, TAIL, BR18 assessments
|
|
11
|
+
``hvx.simulations`` ventilation, occupancy, correlations, scenarios, recommendations
|
|
12
|
+
``hvx.reporting`` portfolio reports (HTML / JSON / CSV)
|
|
13
|
+
``hvx.live`` live data sources (Home Assistant, HTTP, in-memory) and rolling monitoring
|
|
14
|
+
``hvx.connectors`` file loaders (CSV)
|
|
15
|
+
``hvx.app`` FastAPI backend and Streamlit UI (optional extras)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
__version__ = version("hvx")
|
|
24
|
+
except PackageNotFoundError: # running from a source checkout
|
|
25
|
+
__version__ = "0.0.0+local"
|
|
26
|
+
|
|
27
|
+
__all__ = ["__version__"]
|
hvx/__main__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
from hvx.cli import cli
|
|
5
|
+
|
|
6
|
+
if __name__ == "__main__":
|
|
7
|
+
cli()
|
hvx/app/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
"""
|
|
5
|
+
Streamlit application package for interactive portfolio management.
|
|
6
|
+
"""
|
|
7
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from typing import Dict, Iterable, Optional
|
|
7
|
+
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
from hvx.core import (
|
|
11
|
+
Room,
|
|
12
|
+
Building,
|
|
13
|
+
generate_occupancy_mask,
|
|
14
|
+
get_opening_profile_for_building_type,
|
|
15
|
+
)
|
|
16
|
+
from hvx.core.utils.calendar import get_holiday_dates
|
|
17
|
+
from hvx.standards.en16798.analysis import EN16798Calculator, VentilationType as ENVentilationType
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _room_dataframe(room: Room) -> Optional[pd.DataFrame]:
|
|
21
|
+
if not room.timeseries_data:
|
|
22
|
+
return None
|
|
23
|
+
df = pd.DataFrame(room.timeseries_data)
|
|
24
|
+
if room.timestamps and len(room.timestamps) == len(df.index):
|
|
25
|
+
idx = pd.to_datetime(room.timestamps, errors="coerce")
|
|
26
|
+
df.index = idx
|
|
27
|
+
df = df[~df.index.isna()]
|
|
28
|
+
elif "timestamp" in df.columns:
|
|
29
|
+
idx = pd.to_datetime(df["timestamp"], errors="coerce")
|
|
30
|
+
df = df.drop(columns=["timestamp"])
|
|
31
|
+
df.index = idx
|
|
32
|
+
df = df[~df.index.isna()]
|
|
33
|
+
else:
|
|
34
|
+
df.index = pd.RangeIndex(len(df))
|
|
35
|
+
if df.empty:
|
|
36
|
+
return None
|
|
37
|
+
return df
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run_en16798_for_room(
|
|
41
|
+
room: Room,
|
|
42
|
+
season: str = "heating",
|
|
43
|
+
building: Optional[Building] = None,
|
|
44
|
+
) -> Optional[Dict]:
|
|
45
|
+
df = _room_dataframe(room)
|
|
46
|
+
if df is None:
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
occupancy_mask: Optional[pd.Series] = None
|
|
50
|
+
if isinstance(df.index, pd.DatetimeIndex):
|
|
51
|
+
building_type = getattr(building, "building_type", None)
|
|
52
|
+
profile = get_opening_profile_for_building_type(
|
|
53
|
+
building_type.lower() if isinstance(building_type, str) else building_type
|
|
54
|
+
)
|
|
55
|
+
holiday_dates = get_holiday_dates(getattr(building, "country", None))
|
|
56
|
+
occupancy_mask = generate_occupancy_mask(df.index, profile, holiday_dates=holiday_dates)
|
|
57
|
+
df = df[occupancy_mask]
|
|
58
|
+
|
|
59
|
+
if df.empty:
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
temperature = df["temperature"] if "temperature" in df else None
|
|
63
|
+
co2 = df["co2"] if "co2" in df else None
|
|
64
|
+
humidity = df["humidity"] if "humidity" in df else None
|
|
65
|
+
|
|
66
|
+
ventilation_type = ENVentilationType.MECHANICAL
|
|
67
|
+
if room.ventilation_type:
|
|
68
|
+
try:
|
|
69
|
+
ventilation_type = ENVentilationType(room.ventilation_type.value)
|
|
70
|
+
except ValueError:
|
|
71
|
+
ventilation_type = ENVentilationType.MECHANICAL
|
|
72
|
+
|
|
73
|
+
results = EN16798Calculator.assess_timeseries_compliance(
|
|
74
|
+
temperature=temperature,
|
|
75
|
+
co2=co2,
|
|
76
|
+
humidity=humidity,
|
|
77
|
+
season=season,
|
|
78
|
+
ventilation_type=ventilation_type,
|
|
79
|
+
)
|
|
80
|
+
return results
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def run_en16798_for_rooms(
|
|
84
|
+
rooms: Iterable[Room],
|
|
85
|
+
season: str = "heating",
|
|
86
|
+
buildings: Optional[Dict[str, Building]] = None,
|
|
87
|
+
) -> Dict[str, Dict]:
|
|
88
|
+
summaries: Dict[str, Dict] = {}
|
|
89
|
+
for room in rooms:
|
|
90
|
+
building_obj = None
|
|
91
|
+
if buildings:
|
|
92
|
+
if room.building_id and room.building_id in buildings:
|
|
93
|
+
building_obj = buildings.get(room.building_id)
|
|
94
|
+
else:
|
|
95
|
+
for parent_id in room.parent_ids:
|
|
96
|
+
if parent_id in buildings:
|
|
97
|
+
building_obj = buildings[parent_id]
|
|
98
|
+
break
|
|
99
|
+
result = run_en16798_for_room(room, season=season, building=building_obj)
|
|
100
|
+
if result:
|
|
101
|
+
summaries[room.id] = result
|
|
102
|
+
return summaries
|