mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
slice 5: room, door and lighting count features
Ten flat int counts added to the transform — door_count, habitable/heated/wet/insulated_door counts, extensions, open chimneys, and the three fixed-lighting bulb counts (CFL/LED/ incandescent). All non-nullable; direct EpcPropertyData field reads. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
aa00259b1a
commit
e9b4dbbfe5
3 changed files with 139 additions and 12 deletions
|
|
@ -24,6 +24,17 @@ def make_minimal_sap10_epc(
|
|||
energy_consumption_current: Optional[int] = None,
|
||||
space_heating_kwh: float = 0.0,
|
||||
water_heating_kwh: float = 0.0,
|
||||
total_floor_area_m2: float = 70.0,
|
||||
door_count: int = 0,
|
||||
habitable_rooms_count: int = 0,
|
||||
heated_rooms_count: int = 0,
|
||||
wet_rooms_count: int = 0,
|
||||
extensions_count: int = 0,
|
||||
open_chimneys_count: int = 0,
|
||||
insulated_door_count: int = 0,
|
||||
cfl_fixed_lighting_bulbs_count: int = 0,
|
||||
led_fixed_lighting_bulbs_count: int = 0,
|
||||
incandescent_fixed_lighting_bulbs_count: int = 0,
|
||||
) -> EpcPropertyData:
|
||||
"""Construct a minimal valid SAP10 EpcPropertyData with parametrisable targets."""
|
||||
return EpcPropertyData(
|
||||
|
|
@ -38,7 +49,7 @@ def make_minimal_sap10_epc(
|
|||
walls=[],
|
||||
floors=[],
|
||||
main_heating=[],
|
||||
door_count=0,
|
||||
door_count=door_count,
|
||||
sap_heating=SapHeating(
|
||||
instantaneous_wwhrs=InstantaneousWwhrs(),
|
||||
main_heating_details=[],
|
||||
|
|
@ -59,16 +70,16 @@ def make_minimal_sap10_epc(
|
|||
solar_water_heating=False,
|
||||
has_hot_water_cylinder=False,
|
||||
has_fixed_air_conditioning=False,
|
||||
wet_rooms_count=0,
|
||||
extensions_count=0,
|
||||
heated_rooms_count=0,
|
||||
open_chimneys_count=0,
|
||||
habitable_rooms_count=0,
|
||||
insulated_door_count=0,
|
||||
cfl_fixed_lighting_bulbs_count=0,
|
||||
led_fixed_lighting_bulbs_count=0,
|
||||
incandescent_fixed_lighting_bulbs_count=0,
|
||||
total_floor_area_m2=70.0,
|
||||
wet_rooms_count=wet_rooms_count,
|
||||
extensions_count=extensions_count,
|
||||
heated_rooms_count=heated_rooms_count,
|
||||
open_chimneys_count=open_chimneys_count,
|
||||
habitable_rooms_count=habitable_rooms_count,
|
||||
insulated_door_count=insulated_door_count,
|
||||
cfl_fixed_lighting_bulbs_count=cfl_fixed_lighting_bulbs_count,
|
||||
led_fixed_lighting_bulbs_count=led_fixed_lighting_bulbs_count,
|
||||
incandescent_fixed_lighting_bulbs_count=incandescent_fixed_lighting_bulbs_count,
|
||||
total_floor_area_m2=total_floor_area_m2,
|
||||
sap_version=10.2,
|
||||
energy_rating_current=energy_rating_current,
|
||||
co2_emissions_current=co2_emissions_current,
|
||||
|
|
|
|||
|
|
@ -117,3 +117,66 @@ def test_to_row_extracts_total_floor_area_m2() -> None:
|
|||
# Assert
|
||||
# make_minimal_sap10_epc sets total_floor_area_m2=70.0 by default
|
||||
assert row["total_floor_area_m2"] == 70.0
|
||||
|
||||
|
||||
_EXPECTED_COUNT_FEATURES: dict[str, type] = {
|
||||
"door_count": int,
|
||||
"habitable_rooms_count": int,
|
||||
"heated_rooms_count": int,
|
||||
"wet_rooms_count": int,
|
||||
"extensions_count": int,
|
||||
"open_chimneys_count": int,
|
||||
"insulated_door_count": int,
|
||||
"cfl_fixed_lighting_bulbs_count": int,
|
||||
"led_fixed_lighting_bulbs_count": int,
|
||||
"incandescent_fixed_lighting_bulbs_count": int,
|
||||
}
|
||||
|
||||
|
||||
def test_schema_advertises_count_features() -> None:
|
||||
# Arrange
|
||||
transform = EpcMlTransform()
|
||||
|
||||
# Act
|
||||
schema = transform.schema()
|
||||
|
||||
# Assert
|
||||
for feature_name, expected_dtype in _EXPECTED_COUNT_FEATURES.items():
|
||||
assert feature_name in schema.feature_columns, feature_name
|
||||
column = schema.feature_columns[feature_name]
|
||||
assert isinstance(column, ColumnSpec)
|
||||
assert column.dtype is expected_dtype
|
||||
assert column.nullable is False
|
||||
|
||||
|
||||
def test_to_row_extracts_count_features() -> None:
|
||||
# Arrange
|
||||
epc = make_minimal_sap10_epc(
|
||||
energy_rating_current=82,
|
||||
door_count=3,
|
||||
habitable_rooms_count=5,
|
||||
heated_rooms_count=4,
|
||||
wet_rooms_count=1,
|
||||
extensions_count=1,
|
||||
open_chimneys_count=0,
|
||||
insulated_door_count=2,
|
||||
cfl_fixed_lighting_bulbs_count=0,
|
||||
led_fixed_lighting_bulbs_count=8,
|
||||
incandescent_fixed_lighting_bulbs_count=2,
|
||||
)
|
||||
transform = EpcMlTransform()
|
||||
|
||||
# Act
|
||||
row = transform.to_row(epc)
|
||||
|
||||
# Assert
|
||||
assert row["door_count"] == 3
|
||||
assert row["habitable_rooms_count"] == 5
|
||||
assert row["heated_rooms_count"] == 4
|
||||
assert row["wet_rooms_count"] == 1
|
||||
assert row["extensions_count"] == 1
|
||||
assert row["open_chimneys_count"] == 0
|
||||
assert row["insulated_door_count"] == 2
|
||||
assert row["cfl_fixed_lighting_bulbs_count"] == 0
|
||||
assert row["led_fixed_lighting_bulbs_count"] == 8
|
||||
assert row["incandescent_fixed_lighting_bulbs_count"] == 2
|
||||
|
|
|
|||
|
|
@ -19,11 +19,53 @@ from domain.ml.ucl import apply_ucl_correction
|
|||
|
||||
|
||||
_FEATURE_COLUMNS: dict[str, ColumnSpec] = {
|
||||
# Geometry
|
||||
"total_floor_area_m2": ColumnSpec(
|
||||
dtype=float,
|
||||
nullable=False,
|
||||
description="Total floor area in square metres, from `total_floor_area`.",
|
||||
),
|
||||
# Counts — directly populated by all SAP10 EPCs
|
||||
"door_count": ColumnSpec(
|
||||
dtype=int, nullable=False, description="Number of external doors."
|
||||
),
|
||||
"habitable_rooms_count": ColumnSpec(
|
||||
dtype=int, nullable=False, description="Number of habitable rooms."
|
||||
),
|
||||
"heated_rooms_count": ColumnSpec(
|
||||
dtype=int, nullable=False, description="Number of heated rooms."
|
||||
),
|
||||
"wet_rooms_count": ColumnSpec(
|
||||
dtype=int, nullable=False, description="Number of wet rooms (bathrooms / WCs)."
|
||||
),
|
||||
"extensions_count": ColumnSpec(
|
||||
dtype=int,
|
||||
nullable=False,
|
||||
description="Number of extensions beyond the main dwelling.",
|
||||
),
|
||||
"open_chimneys_count": ColumnSpec(
|
||||
dtype=int, nullable=False, description="Number of open chimneys."
|
||||
),
|
||||
"insulated_door_count": ColumnSpec(
|
||||
dtype=int,
|
||||
nullable=False,
|
||||
description="Number of external doors classed as insulated.",
|
||||
),
|
||||
"cfl_fixed_lighting_bulbs_count": ColumnSpec(
|
||||
dtype=int,
|
||||
nullable=False,
|
||||
description="Number of CFL bulbs in fixed lighting outlets.",
|
||||
),
|
||||
"led_fixed_lighting_bulbs_count": ColumnSpec(
|
||||
dtype=int,
|
||||
nullable=False,
|
||||
description="Number of LED bulbs in fixed lighting outlets.",
|
||||
),
|
||||
"incandescent_fixed_lighting_bulbs_count": ColumnSpec(
|
||||
dtype=int,
|
||||
nullable=False,
|
||||
description="Number of incandescent bulbs in fixed lighting outlets.",
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -99,8 +141,19 @@ class EpcMlTransform:
|
|||
"""
|
||||
rhi = epc.renewable_heat_incentive
|
||||
return {
|
||||
# Features
|
||||
# Features — geometry
|
||||
"total_floor_area_m2": epc.total_floor_area_m2,
|
||||
# Features — counts
|
||||
"door_count": epc.door_count,
|
||||
"habitable_rooms_count": epc.habitable_rooms_count,
|
||||
"heated_rooms_count": epc.heated_rooms_count,
|
||||
"wet_rooms_count": epc.wet_rooms_count,
|
||||
"extensions_count": epc.extensions_count,
|
||||
"open_chimneys_count": epc.open_chimneys_count,
|
||||
"insulated_door_count": epc.insulated_door_count,
|
||||
"cfl_fixed_lighting_bulbs_count": epc.cfl_fixed_lighting_bulbs_count,
|
||||
"led_fixed_lighting_bulbs_count": epc.led_fixed_lighting_bulbs_count,
|
||||
"incandescent_fixed_lighting_bulbs_count": epc.incandescent_fixed_lighting_bulbs_count,
|
||||
# Targets
|
||||
"sap_score": epc.energy_rating_current,
|
||||
"co2_emissions": epc.co2_emissions_current,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue