mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
chore(scripts): triage PE/CO2 on the demand cascade in the corpus profilers
`profile_corpus_error.py` and `dive_cert.py` compared our PE/CO2 against
the lodged EPC figures using the UK-average RATING cascade, but the EPC
lodges CO2/PE on the postcode DEMAND cascade (SAP 10.2 Appendix U p.124,
now wired into Sap10Calculator.calculate in fc7c4d2d). That confounded the
DEMAND-vs-COST triage: a cert whose demand actually reproduced on local
weather looked "PE off" purely from the climate difference and was
mislabelled DEMAND-side. Switching the PE/CO2 lens to `cert_to_demand_
inputs` (SAP still from the rating cascade) re-classifies the corpus
outside-0.5 set 261/42 -> 211/92 DEMAND/COST — ~50 certs are genuinely
cost-side (e.g. 10091578598: SAP +7.81 but PE +1.6 / CO2 -0.04). Sharpens
the hunt for the subtle widespread SAP term.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fc7c4d2d3b
commit
6950deae06
2 changed files with 21 additions and 7 deletions
|
|
@ -17,6 +17,7 @@ from datatypes.epc.domain.mapper import EpcPropertyDataMapper
|
|||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
||||
SAP_10_2_SPEC_PRICES,
|
||||
cert_to_demand_inputs,
|
||||
cert_to_inputs,
|
||||
)
|
||||
from scripts.profile_api_error import features
|
||||
|
|
@ -40,6 +41,10 @@ def _dump(doc: dict[str, Any]) -> None:
|
|||
lodged_pe = doc.get("energy_consumption_current")
|
||||
epc = EpcPropertyDataMapper.from_api_response(doc)
|
||||
r = calculate_sap_from_inputs(cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES))
|
||||
# SAP/EI rating is the UK-average rating cascade (`r`); EPC CO2/PE use the
|
||||
# postcode demand cascade (SAP 10.2 Appendix U p.124). Display CO2/PE from
|
||||
# the demand cascade so they compare like-for-like with the lodged EPC.
|
||||
d = calculate_sap_from_inputs(cert_to_demand_inputs(epc, prices=SAP_10_2_SPEC_PRICES))
|
||||
print("=" * 90)
|
||||
print(f"CERT {cert}")
|
||||
print(
|
||||
|
|
@ -48,13 +53,13 @@ def _dump(doc: dict[str, Any]) -> None:
|
|||
)
|
||||
if lodged_co2 is not None:
|
||||
print(
|
||||
f" CO2 lodged={lodged_co2:.3f} ours={r.co2_kg_per_yr / 1000:.3f} t "
|
||||
f"d={r.co2_kg_per_yr / 1000 - lodged_co2:+.3f}"
|
||||
f" CO2 lodged={lodged_co2:.3f} ours={d.co2_kg_per_yr / 1000:.3f} t "
|
||||
f"d={d.co2_kg_per_yr / 1000 - lodged_co2:+.3f} (demand cascade)"
|
||||
)
|
||||
if lodged_pe is not None:
|
||||
print(
|
||||
f" PE lodged={lodged_pe:.1f} ours={r.primary_energy_kwh_per_m2:.1f} "
|
||||
f"d={r.primary_energy_kwh_per_m2 - lodged_pe:+.1f} kWh/m2"
|
||||
f" PE lodged={lodged_pe:.1f} ours={d.primary_energy_kwh_per_m2:.1f} "
|
||||
f"d={d.primary_energy_kwh_per_m2 - lodged_pe:+.1f} kWh/m2 (demand cascade)"
|
||||
)
|
||||
print(
|
||||
f" energy kWh/yr: spaceheat={r.space_heating_kwh_per_yr:.0f} "
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ from typing import Any, Optional
|
|||
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
||||
cert_to_demand_inputs,
|
||||
SAP_10_2_SPEC_PRICES,
|
||||
cert_to_inputs,
|
||||
)
|
||||
|
|
@ -96,6 +97,14 @@ def _compute(corpus: list[dict[str, Any]]) -> tuple[list[Row], int, int]:
|
|||
result = calculate_sap_from_inputs(
|
||||
cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES)
|
||||
)
|
||||
# SAP/EI rating is the UK-average rating cascade (`result`);
|
||||
# the EPC-displayed CO2/PE use the postcode demand cascade
|
||||
# (SAP 10.2 Appendix U p.124). Use the demand cascade for the
|
||||
# PE/CO2-vs-cost triage so it is not confounded by the climate
|
||||
# difference (UK-average vs local weather).
|
||||
demand = calculate_sap_from_inputs(
|
||||
cert_to_demand_inputs(epc, prices=SAP_10_2_SPEC_PRICES)
|
||||
)
|
||||
except Exception:
|
||||
raised += 1
|
||||
continue
|
||||
|
|
@ -110,14 +119,14 @@ def _compute(corpus: list[dict[str, Any]]) -> tuple[list[Row], int, int]:
|
|||
rows.append(Row(
|
||||
cert=cert,
|
||||
sap_err=result.sap_score_continuous - lodged_sap,
|
||||
co2_err_t=(result.co2_kg_per_yr / 1000.0 - lodged_co2_t)
|
||||
co2_err_t=(demand.co2_kg_per_yr / 1000.0 - lodged_co2_t)
|
||||
if lodged_co2_t is not None else None,
|
||||
pe_err=(result.primary_energy_kwh_per_m2 - lodged_pe)
|
||||
pe_err=(demand.primary_energy_kwh_per_m2 - lodged_pe)
|
||||
if lodged_pe is not None else None,
|
||||
lodged_sap=lodged_sap,
|
||||
our_sap=result.sap_score_continuous,
|
||||
lodged_pe=lodged_pe,
|
||||
our_pe=result.primary_energy_kwh_per_m2,
|
||||
our_pe=demand.primary_energy_kwh_per_m2,
|
||||
feats=features(doc),
|
||||
))
|
||||
return rows, skipped, raised
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue