mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
fixed error in reference to fuel type
This commit is contained in:
parent
a9018a541e
commit
62d92f29e6
2 changed files with 56 additions and 25 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
from backend.app.plan.schemas import HousingType, WALL_INSULATION_MEASURES, ROOF_INSULATION_MEASURES, MEASURE_MAP
|
from backend.app.plan.schemas import HousingType, WALL_INSULATION_MEASURES, ROOF_INSULATION_MEASURES, MEASURE_MAP
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -38,11 +40,6 @@ class Funding:
|
||||||
self.floor_area_band = None
|
self.floor_area_band = None
|
||||||
self.project_scores_matrix = project_scores_matrix
|
self.project_scores_matrix = project_scores_matrix
|
||||||
self.partial_project_scores_matrix = partial_project_scores_matrix
|
self.partial_project_scores_matrix = partial_project_scores_matrix
|
||||||
# Filter on the starting band and floor area so we only do this once
|
|
||||||
self.partial_project_scores_matrix = self.partial_project_scores_matrix[
|
|
||||||
(self.partial_project_scores_matrix["Total Floor Area Band"] == self.floor_area_band) &
|
|
||||||
(self.partial_project_scores_matrix["Starting Band"] == self.starting_sap_band)
|
|
||||||
]
|
|
||||||
|
|
||||||
self.whlg_eligible_postcodes = whlg_eligible_postcodes
|
self.whlg_eligible_postcodes = whlg_eligible_postcodes
|
||||||
|
|
||||||
|
|
@ -408,16 +405,16 @@ class Funding:
|
||||||
]:
|
]:
|
||||||
return 'Electric Storage Heaters Responsiveness >0.2'
|
return 'Electric Storage Heaters Responsiveness >0.2'
|
||||||
|
|
||||||
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "lpg":
|
if mainheating["has_room_heaters"] and main_fuel["fuel_type"] == "lpg":
|
||||||
return 'Bottled LPG Room Heaters'
|
return 'Bottled LPG Room Heaters'
|
||||||
|
|
||||||
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "electricity":
|
if mainheating["has_room_heaters"] and main_fuel["fuel_type"] == "electricity":
|
||||||
return 'Electric Room Heaters'
|
return 'Electric Room Heaters'
|
||||||
|
|
||||||
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "mains gas":
|
if mainheating["has_room_heaters"] and main_fuel["fuel_type"] == "mains gas":
|
||||||
return 'Gas Room Heaters'
|
return 'Gas Room Heaters'
|
||||||
|
|
||||||
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] in [
|
if mainheating["has_room_heaters"] and main_fuel["fuel_type"] in [
|
||||||
"dual fuel appliance mineral and wood", "manufactured smokeless fuel"
|
"dual fuel appliance mineral and wood", "manufactured smokeless fuel"
|
||||||
]:
|
]:
|
||||||
return 'Solid Fossil Room Heaters'
|
return 'Solid Fossil Room Heaters'
|
||||||
|
|
@ -430,6 +427,7 @@ class Funding:
|
||||||
mainheating: dict,
|
mainheating: dict,
|
||||||
main_fuel: dict,
|
main_fuel: dict,
|
||||||
mainheat_energy_eff: str,
|
mainheat_energy_eff: str,
|
||||||
|
filtered_pps_matrix: pd.DataFrame,
|
||||||
current_wall_uvalue: float = None,
|
current_wall_uvalue: float = None,
|
||||||
is_partial: bool = False,
|
is_partial: bool = False,
|
||||||
existing_li_thickness: float = None,
|
existing_li_thickness: float = None,
|
||||||
|
|
@ -438,7 +436,7 @@ class Funding:
|
||||||
"""
|
"""
|
||||||
Calculate the partial project ABS score for a single measure.
|
Calculate the partial project ABS score for a single measure.
|
||||||
"""
|
"""
|
||||||
df = self.partial_project_scores_matrix
|
# Filter on the starting band and floor area so we only do this once
|
||||||
|
|
||||||
if measure_type == "internal_wall_insulation":
|
if measure_type == "internal_wall_insulation":
|
||||||
if current_wall_uvalue is None:
|
if current_wall_uvalue is None:
|
||||||
|
|
@ -446,7 +444,7 @@ class Funding:
|
||||||
|
|
||||||
starting_str, ending_str = self.get_starting_ending_uvalues(current_wall_uvalue)
|
starting_str, ending_str = self.get_starting_ending_uvalues(current_wall_uvalue)
|
||||||
measure_code = f"IWI_solid_{starting_str}_{ending_str}"
|
measure_code = f"IWI_solid_{starting_str}_{ending_str}"
|
||||||
pps = df[df["Measure_Type"] == measure_code]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == measure_code]
|
||||||
|
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError(f"Invalid IWI category: {measure_code}")
|
raise ValueError(f"Invalid IWI category: {measure_code}")
|
||||||
|
|
@ -458,7 +456,7 @@ class Funding:
|
||||||
|
|
||||||
starting_str, ending_str = self.get_starting_ending_uvalues(current_wall_uvalue)
|
starting_str, ending_str = self.get_starting_ending_uvalues(current_wall_uvalue)
|
||||||
measure_code = f"EWI_solid_{starting_str}_{ending_str}"
|
measure_code = f"EWI_solid_{starting_str}_{ending_str}"
|
||||||
pps = df[df["Measure_Type"] == measure_code]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == measure_code]
|
||||||
|
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError(f"Invalid EWI category: {measure_code}")
|
raise ValueError(f"Invalid EWI category: {measure_code}")
|
||||||
|
|
@ -466,7 +464,7 @@ class Funding:
|
||||||
|
|
||||||
if measure_type == "cavity_wall_insulation":
|
if measure_type == "cavity_wall_insulation":
|
||||||
measure_code = "CWI_partial_fill" if is_partial else "CWI_0.033"
|
measure_code = "CWI_partial_fill" if is_partial else "CWI_0.033"
|
||||||
pps = df[df["Measure_Type"] == measure_code]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == measure_code]
|
||||||
|
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError(f"Invalid CWI category: {measure_code}")
|
raise ValueError(f"Invalid CWI category: {measure_code}")
|
||||||
|
|
@ -477,14 +475,14 @@ class Funding:
|
||||||
raise ValueError("existing_li_thickness is required for LI")
|
raise ValueError("existing_li_thickness is required for LI")
|
||||||
|
|
||||||
measure_code = "LI_lessequal100" if existing_li_thickness <= 100 else "LI_greater100"
|
measure_code = "LI_lessequal100" if existing_li_thickness <= 100 else "LI_greater100"
|
||||||
pps = df[df["Measure_Type"] == measure_code]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == measure_code]
|
||||||
|
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError(f"Invalid LI category: {measure_code}")
|
raise ValueError(f"Invalid LI category: {measure_code}")
|
||||||
return pps.squeeze()["Cost Savings"]
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
if measure_type == "flat_roof_insulation":
|
if measure_type == "flat_roof_insulation":
|
||||||
pps = df[df["Measure_Type"] == "FRI"]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == "FRI"]
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError("Invalid FRI category")
|
raise ValueError("Invalid FRI category")
|
||||||
return pps.squeeze()["Cost Savings"]
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
@ -493,36 +491,38 @@ class Funding:
|
||||||
# Use the more conservative score (unin is usually lower)
|
# Use the more conservative score (unin is usually lower)
|
||||||
# code = "RIRI_res_unin" if not is_roof_insulated else "RIRI_res_in"
|
# code = "RIRI_res_unin" if not is_roof_insulated else "RIRI_res_in"
|
||||||
code = "RIRI_res_unin"
|
code = "RIRI_res_unin"
|
||||||
pps = df[df["Measure_Type"] == code]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == code]
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError(f"Invalid RIRI category: {code}")
|
raise ValueError(f"Invalid RIRI category: {code}")
|
||||||
return pps.squeeze()["Cost Savings"]
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
if measure_type == "suspended_floor_insulation":
|
if measure_type == "suspended_floor_insulation":
|
||||||
pps = df[df["Measure_Type"] == "UFI"]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == "UFI"]
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError("Invalid UFI category")
|
raise ValueError("Invalid UFI category")
|
||||||
return pps.squeeze()["Cost Savings"]
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
if measure_type == "solid_floor_insulation":
|
if measure_type == "solid_floor_insulation":
|
||||||
pps = df[df["Measure_Type"] == "SFI"]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == "SFI"]
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError("Invalid SFI category")
|
raise ValueError("Invalid SFI category")
|
||||||
return pps.squeeze()["Cost Savings"]
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
if measure_type == "solar_pv":
|
if measure_type == "solar_pv":
|
||||||
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
|
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
|
||||||
solar_pps_df = df[
|
solar_pps_df = filtered_pps_matrix[
|
||||||
(df["Measure_Type"] == "Solar_PV") & (df["Pre_Main_Heating_Source"] == pre_heating_system)
|
(filtered_pps_matrix["Measure_Type"] == "Solar_PV") &
|
||||||
|
(filtered_pps_matrix["Pre_Main_Heating_Source"] == pre_heating_system)
|
||||||
]
|
]
|
||||||
return solar_pps_df.squeeze()["Cost Savings"]
|
return solar_pps_df.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
if measure_type == "air_source_heat_pump":
|
if measure_type == "air_source_heat_pump":
|
||||||
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
|
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
|
||||||
pps = df[
|
pps = filtered_pps_matrix[
|
||||||
(df["Pre_Main_Heating_Source"] == pre_heating_system) &
|
(filtered_pps_matrix["Pre_Main_Heating_Source"] == pre_heating_system) &
|
||||||
(df["Post_Main_Heating_Source"] == "Air to Water ASHP") &
|
(filtered_pps_matrix["Post_Main_Heating_Source"] == "Air to Water ASHP") &
|
||||||
(df["Measure_Type"] == "B_Upgrade_nopreHCs") # We assume we'll be making a heating system upgrade
|
(filtered_pps_matrix["Measure_Type"] == "B_Upgrade_nopreHCs")
|
||||||
|
# We assume we'll be making a heating system upgrade
|
||||||
]
|
]
|
||||||
|
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
|
|
@ -763,6 +763,11 @@ class Funding:
|
||||||
self.ending_sap_band = self.get_sap_band(ending_sap)
|
self.ending_sap_band = self.get_sap_band(ending_sap)
|
||||||
self.floor_area_band = self.get_floor_area_band(floor_area)
|
self.floor_area_band = self.get_floor_area_band(floor_area)
|
||||||
|
|
||||||
|
filtered_pps_matrix = self.partial_project_scores_matrix[
|
||||||
|
(self.partial_project_scores_matrix["Total Floor Area Band"] == self.floor_area_band) &
|
||||||
|
(self.partial_project_scores_matrix["Starting Band"] == self.starting_sap_band)
|
||||||
|
].copy()
|
||||||
|
|
||||||
if self.tenure == "Private":
|
if self.tenure == "Private":
|
||||||
# ECO4 PRS
|
# ECO4 PRS
|
||||||
self.eco4_prs_eligibility(starting_sap, ending_sap, measure_types, has_solar, solar_eligible)
|
self.eco4_prs_eligibility(starting_sap, ending_sap, measure_types, has_solar, solar_eligible)
|
||||||
|
|
@ -774,7 +779,6 @@ class Funding:
|
||||||
self.eco4_funding = self.full_project_abs * (
|
self.eco4_funding = self.full_project_abs * (
|
||||||
self.private_cavity_abs_rate if is_cavity else self.private_solid_abs_rate)
|
self.private_cavity_abs_rate if is_cavity else self.private_solid_abs_rate)
|
||||||
|
|
||||||
|
|
||||||
elif self.tenure == "Social":
|
elif self.tenure == "Social":
|
||||||
# ECO4 Social
|
# ECO4 Social
|
||||||
self.eco4_sh_eligibility(
|
self.eco4_sh_eligibility(
|
||||||
|
|
@ -791,6 +795,11 @@ class Funding:
|
||||||
# We calculate uplift innovation, where required
|
# We calculate uplift innovation, where required
|
||||||
project_uplifts = []
|
project_uplifts = []
|
||||||
for i, measure in enumerate(measure_types):
|
for i, measure in enumerate(measure_types):
|
||||||
|
if not innovation_flags[i]:
|
||||||
|
# Capture 0 innovation uplift for debugging
|
||||||
|
project_uplifts.append(0)
|
||||||
|
continue
|
||||||
|
|
||||||
pps = self.calculate_partial_project_abs(
|
pps = self.calculate_partial_project_abs(
|
||||||
measure_type=measure,
|
measure_type=measure,
|
||||||
mainheating=mainheating,
|
mainheating=mainheating,
|
||||||
|
|
@ -799,6 +808,7 @@ class Funding:
|
||||||
current_wall_uvalue=current_wall_uvalue,
|
current_wall_uvalue=current_wall_uvalue,
|
||||||
is_partial=is_partial,
|
is_partial=is_partial,
|
||||||
existing_li_thickness=existing_li_thickness,
|
existing_li_thickness=existing_li_thickness,
|
||||||
|
filtered_pps_matrix=filtered_pps_matrix,
|
||||||
)
|
)
|
||||||
project_uplifts.append(pps * uplifts[i])
|
project_uplifts.append(pps * uplifts[i])
|
||||||
total_uplift = sum(project_uplifts)
|
total_uplift = sum(project_uplifts)
|
||||||
|
|
@ -817,6 +827,7 @@ class Funding:
|
||||||
current_wall_uvalue=current_wall_uvalue,
|
current_wall_uvalue=current_wall_uvalue,
|
||||||
is_partial=is_partial,
|
is_partial=is_partial,
|
||||||
existing_li_thickness=existing_li_thickness,
|
existing_li_thickness=existing_li_thickness,
|
||||||
|
filtered_pps_matrix=filtered_pps_matrix
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -994,8 +994,11 @@ def test_uplift(
|
||||||
measures = [
|
measures = [
|
||||||
{"type": "solar_pv", "is_innovation": True, "uplift": 0.45},
|
{"type": "solar_pv", "is_innovation": True, "uplift": 0.45},
|
||||||
{"type": "internal_wall_insulation", "is_innovation": False, "uplift": 0},
|
{"type": "internal_wall_insulation", "is_innovation": False, "uplift": 0},
|
||||||
|
{"type": "cavity_wall_insulation", "is_innovation": False, "uplift": 0},
|
||||||
|
{"type": "external_wall_insulation", "is_innovation": False, "uplift": 0},
|
||||||
{"type": "loft_insulation", "is_innovation": False, "uplift": 0},
|
{"type": "loft_insulation", "is_innovation": False, "uplift": 0},
|
||||||
{"type": "air_source_heat_pump", "is_innovation": False, "uplift": 0},
|
{"type": "air_source_heat_pump", "is_innovation": False, "uplift": 0},
|
||||||
|
{"type": "double_glazing", "is_innovation": False, "uplift": 0},
|
||||||
{"type": "cavity_wall_insulation", "is_innovation": True, "uplift": 0.25},
|
{"type": "cavity_wall_insulation", "is_innovation": True, "uplift": 0.25},
|
||||||
{"type": "high_heat_retention_storage_heaters", "is_innovation": False, "uplift": 0},
|
{"type": "high_heat_retention_storage_heaters", "is_innovation": False, "uplift": 0},
|
||||||
]
|
]
|
||||||
|
|
@ -1030,6 +1033,23 @@ for _, x in tqdm(epc_df.iterrows(), total=len(epc_df)):
|
||||||
tenure="Social"
|
tenure="Social"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self = funding
|
||||||
|
measures = measures
|
||||||
|
starting_sap = 33
|
||||||
|
ending_sap = 69
|
||||||
|
floor_area = 71
|
||||||
|
mainheat_description = x["MAINHEAT_DESCRIPTION"]
|
||||||
|
heating_control_description = x["MAINHEATCONT_DESCRIPTION"]
|
||||||
|
is_cavity = True
|
||||||
|
current_wall_uvalue = 2
|
||||||
|
is_partial = False
|
||||||
|
existing_li_thickness = 0
|
||||||
|
has_wall_insulation_recommendation = True
|
||||||
|
has_roof_insulation_recommendation = True
|
||||||
|
mainheating = h
|
||||||
|
main_fuel = f
|
||||||
|
mainheat_energy_eff = mainheat_energy_eff
|
||||||
|
|
||||||
funding.check_funding(
|
funding.check_funding(
|
||||||
measures=measures,
|
measures=measures,
|
||||||
starting_sap=33,
|
starting_sap=33,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue