mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
adding kwh feidls to EpcPropertyData and testing to_row
This commit is contained in:
parent
611ff24eb6
commit
a64e7e74c5
5 changed files with 136 additions and 4 deletions
|
|
@ -250,6 +250,22 @@ class SapFlatDetails:
|
|||
unheated_corridor_length_m: Optional[int] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class RenewableHeatIncentive:
|
||||
"""The RHI block on the EPC — annual baseline kWh per end-use, plus SAP-estimated
|
||||
impact of common insulation measures.
|
||||
|
||||
Mapped 1:1 from the gov EPC API's `renewable_heat_incentive` object. Source of
|
||||
baseline `space_heating_kwh` and `hot_water_kwh` for SAP10 properties (used as ML
|
||||
training targets per ADR-0007).
|
||||
"""
|
||||
space_heating_kwh: float
|
||||
water_heating_kwh: float
|
||||
impact_of_loft_insulation_kwh: Optional[float] = None
|
||||
impact_of_cavity_insulation_kwh: Optional[float] = None
|
||||
impact_of_solid_wall_insulation_kwh: Optional[float] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class EpcPropertyData:
|
||||
# General
|
||||
|
|
@ -352,7 +368,7 @@ class EpcPropertyData:
|
|||
potential_energy_efficiency_band: Optional[Epc] = (
|
||||
None # not available in site notes
|
||||
)
|
||||
# renewable_heat_incentive: Optional[Any] = None # Not sure what this is, skip for now
|
||||
renewable_heat_incentive: Optional[RenewableHeatIncentive] = None
|
||||
draughtproofed_door_count: Optional[int] = None
|
||||
mechanical_vent_duct_type: Optional[int] = None
|
||||
windows_transmission_details: Optional[WindowsTransmissionDetails] = None
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from datatypes.epc.domain.epc_property_data import (
|
|||
PhotovoltaicSupplyNoneOrNoDetails,
|
||||
PvBatteries,
|
||||
PvBattery,
|
||||
RenewableHeatIncentive,
|
||||
SapAlternativeWall,
|
||||
SapBuildingPart,
|
||||
SapEnergySource,
|
||||
|
|
@ -1249,6 +1250,27 @@ class EpcPropertyDataMapper:
|
|||
)
|
||||
for bp in schema.sap_building_parts
|
||||
],
|
||||
renewable_heat_incentive=RenewableHeatIncentive(
|
||||
space_heating_kwh=float(
|
||||
schema.renewable_heat_incentive.space_heating_existing_dwelling
|
||||
),
|
||||
water_heating_kwh=float(schema.renewable_heat_incentive.water_heating),
|
||||
impact_of_loft_insulation_kwh=(
|
||||
float(schema.renewable_heat_incentive.impact_of_loft_insulation)
|
||||
if schema.renewable_heat_incentive.impact_of_loft_insulation is not None
|
||||
else None
|
||||
),
|
||||
impact_of_cavity_insulation_kwh=(
|
||||
float(schema.renewable_heat_incentive.impact_of_cavity_insulation)
|
||||
if schema.renewable_heat_incentive.impact_of_cavity_insulation is not None
|
||||
else None
|
||||
),
|
||||
impact_of_solid_wall_insulation_kwh=(
|
||||
float(schema.renewable_heat_incentive.impact_of_solid_wall_insulation)
|
||||
if schema.renewable_heat_incentive.impact_of_solid_wall_insulation is not None
|
||||
else None
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -1485,6 +1507,27 @@ class EpcPropertyDataMapper:
|
|||
)
|
||||
for bp in schema.sap_building_parts
|
||||
],
|
||||
renewable_heat_incentive=RenewableHeatIncentive(
|
||||
space_heating_kwh=float(
|
||||
schema.renewable_heat_incentive.space_heating_existing_dwelling
|
||||
),
|
||||
water_heating_kwh=float(schema.renewable_heat_incentive.water_heating),
|
||||
impact_of_loft_insulation_kwh=(
|
||||
float(schema.renewable_heat_incentive.impact_of_loft_insulation)
|
||||
if schema.renewable_heat_incentive.impact_of_loft_insulation is not None
|
||||
else None
|
||||
),
|
||||
impact_of_cavity_insulation_kwh=(
|
||||
float(schema.renewable_heat_incentive.impact_of_cavity_insulation)
|
||||
if schema.renewable_heat_incentive.impact_of_cavity_insulation is not None
|
||||
else None
|
||||
),
|
||||
impact_of_solid_wall_insulation_kwh=(
|
||||
float(schema.renewable_heat_incentive.impact_of_solid_wall_insulation)
|
||||
if schema.renewable_heat_incentive.impact_of_solid_wall_insulation is not None
|
||||
else None
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -253,6 +253,20 @@ class TestFromRdSapSchema21_0_0:
|
|||
def test_property_type(self, result: EpcPropertyData) -> None:
|
||||
assert result.property_type == "0"
|
||||
|
||||
def test_renewable_heat_incentive(self, result: EpcPropertyData) -> None:
|
||||
# Arrange — schema-21.0.0 sample JSON loaded via fixture
|
||||
|
||||
# Act
|
||||
rhi = result.renewable_heat_incentive
|
||||
|
||||
# Assert
|
||||
assert rhi is not None
|
||||
assert rhi.space_heating_kwh == 13120.0
|
||||
assert rhi.water_heating_kwh == 2285.0
|
||||
assert rhi.impact_of_loft_insulation_kwh == -2114.0
|
||||
assert rhi.impact_of_cavity_insulation_kwh == -122.0
|
||||
assert rhi.impact_of_solid_wall_insulation_kwh == -3560.0
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Schema 21.0.1 (most comprehensive — full field coverage)
|
||||
|
|
@ -532,3 +546,20 @@ class TestFromRdSapSchema21_0_1:
|
|||
|
||||
def test_party_wall_length(self, result: EpcPropertyData) -> None:
|
||||
assert result.sap_building_parts[0].sap_floor_dimensions[0].party_wall_length_m == 7.9
|
||||
|
||||
# --- renewable heat incentive (RHI) ---
|
||||
|
||||
def test_renewable_heat_incentive(self, result: EpcPropertyData) -> None:
|
||||
# Arrange — schema-21.0.1 sample JSON loaded via fixture
|
||||
|
||||
# Act
|
||||
rhi = result.renewable_heat_incentive
|
||||
|
||||
# Assert
|
||||
assert rhi is not None
|
||||
assert rhi.space_heating_kwh == 13120.0
|
||||
assert rhi.water_heating_kwh == 2285.0
|
||||
assert rhi.impact_of_loft_insulation_kwh == -2114.0
|
||||
assert rhi.impact_of_cavity_insulation_kwh == -122.0
|
||||
assert rhi.impact_of_solid_wall_insulation_kwh == -3560.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"""Tests for EpcMlTransform v0.1.0 — schema-contract surface."""
|
||||
"""Tests for EpcMlTransform v0.1.0 — schema-contract surface and target extraction."""
|
||||
|
||||
from domain.ml.schema import ColumnSpec, TransformSchema
|
||||
from domain.ml.tests._fixtures import make_minimal_sap10_epc
|
||||
from domain.ml.transform import EpcMlTransform
|
||||
|
||||
|
||||
|
|
@ -31,3 +32,25 @@ def test_transform_advertises_version_and_target_columns() -> None:
|
|||
assert isinstance(column, ColumnSpec)
|
||||
assert column.dtype is expected_dtype
|
||||
assert schema.feature_columns == {}
|
||||
|
||||
|
||||
def test_to_row_extracts_targets_from_epc_property_data() -> None:
|
||||
# Arrange
|
||||
epc = make_minimal_sap10_epc(
|
||||
energy_rating_current=82,
|
||||
co2_emissions_current=2.7,
|
||||
energy_consumption_current=232,
|
||||
space_heating_kwh=10128.81,
|
||||
water_heating_kwh=2166.19,
|
||||
)
|
||||
transform = EpcMlTransform()
|
||||
|
||||
# Act
|
||||
row = transform.to_row(epc)
|
||||
|
||||
# Assert
|
||||
assert row["sap_score"] == 82
|
||||
assert row["co2_emissions"] == 2.7
|
||||
assert row["peui_raw"] == 232
|
||||
assert row["space_heating_kwh"] == 10128.81
|
||||
assert row["hot_water_kwh"] == 2166.19
|
||||
|
|
|
|||
|
|
@ -3,12 +3,16 @@
|
|||
The single ML-data contract between this repo and the AutoGluon training repo.
|
||||
Versioned semver-style: MAJOR on removing/renaming columns, MINOR on adding.
|
||||
|
||||
At v0.1.0 only the schema contract is implemented — no feature columns yet.
|
||||
Features are added incrementally per subsequent vertical slices.
|
||||
At v0.1.0 the schema contract is fixed and the five directly-extractable targets
|
||||
are populated by `to_row()`. The UCL-corrected PEUI target and all feature columns
|
||||
are added in subsequent slices.
|
||||
|
||||
See docs/adr/0007-kwh-as-ml-target.md for the target set and rationale.
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import EpcPropertyData
|
||||
from domain.ml.schema import ColumnSpec, TransformSchema
|
||||
|
||||
|
||||
|
|
@ -76,3 +80,18 @@ class EpcMlTransform:
|
|||
feature_columns={},
|
||||
target_columns=dict(_TARGET_COLUMNS),
|
||||
)
|
||||
|
||||
def to_row(self, epc: EpcPropertyData) -> dict[str, Any]:
|
||||
"""Map an EpcPropertyData to a single row of features + targets.
|
||||
|
||||
v0.1.0 populates the five directly-extractable targets. The UCL-corrected
|
||||
PEUI target and all feature columns land in later slices.
|
||||
"""
|
||||
rhi = epc.renewable_heat_incentive
|
||||
return {
|
||||
"sap_score": epc.energy_rating_current,
|
||||
"co2_emissions": epc.co2_emissions_current,
|
||||
"peui_raw": epc.energy_consumption_current,
|
||||
"space_heating_kwh": rhi.space_heating_kwh if rhi is not None else None,
|
||||
"hot_water_kwh": rhi.water_heating_kwh if rhi is not None else None,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue