mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
implmenting innovation uplift
This commit is contained in:
parent
e2e2e8c71c
commit
a55d2902ce
7 changed files with 391 additions and 8 deletions
|
|
@ -949,9 +949,19 @@ class AssetList:
|
||||||
|
|
||||||
if self.phase:
|
if self.phase:
|
||||||
# We filter on just the properties that have had an inspection
|
# We filter on just the properties that have had an inspection
|
||||||
self.standardised_asset_list = self.standardised_asset_list[
|
if self.new_format_non_insturives_present_v2:
|
||||||
~self.standardised_asset_list['Surveyors Name'].isin(["YET TO BE SURVEYED"])
|
self.standardised_asset_list = self.standardised_asset_list[
|
||||||
]
|
~self.standardised_asset_list['NAME OF SURVEYOR'].isin(
|
||||||
|
["YET TO BE SURVEYED", "", None]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
self.standardised_asset_list = self.standardised_asset_list[
|
||||||
|
~pd.isnull(self.standardised_asset_list["NAME OF SURVEYOR"])
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
self.standardised_asset_list = self.standardised_asset_list[
|
||||||
|
~self.standardised_asset_list['Surveyors Name'].isin(["YET TO BE SURVEYED"])
|
||||||
|
]
|
||||||
|
|
||||||
if not self.variable_mappings and not override_empty_mappings:
|
if not self.variable_mappings and not override_empty_mappings:
|
||||||
raise ValueError("Please run init_standardise first")
|
raise ValueError("Please run init_standardise first")
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,39 @@ def app():
|
||||||
EPC recommendations
|
EPC recommendations
|
||||||
Property UPRN
|
Property UPRN
|
||||||
"""
|
"""
|
||||||
|
# Freebridge
|
||||||
|
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Freebridge"
|
||||||
|
data_filename = "Domna - FCH property data May 25 copy.xlsx"
|
||||||
|
sheet_name = "EPC Data"
|
||||||
|
postcode_column = 'Post Code'
|
||||||
|
address1_column = "Address 1"
|
||||||
|
address1_method = None
|
||||||
|
fulladdress_column = None
|
||||||
|
address_cols_to_concat = ["Address 1", "Address 4"]
|
||||||
|
missing_postcodes_method = None
|
||||||
|
landlord_year_built = "Build Date"
|
||||||
|
landlord_os_uprn = None
|
||||||
|
landlord_property_type = "Property Type"
|
||||||
|
landlord_built_form = None
|
||||||
|
landlord_wall_construction = "Walls Description"
|
||||||
|
landlord_heating_system = "Heating Type"
|
||||||
|
landlord_existing_pv = None
|
||||||
|
landlord_property_id = "Place Ref"
|
||||||
|
landlord_roof_construction = "Roof Description"
|
||||||
|
landlord_sap = "Current SAP"
|
||||||
|
outcomes_filename = []
|
||||||
|
outcomes_sheetname = []
|
||||||
|
outcomes_postcode = []
|
||||||
|
outcomes_houseno = []
|
||||||
|
outcomes_address = []
|
||||||
|
outcomes_id = []
|
||||||
|
master_filepaths = []
|
||||||
|
master_to_asset_list_filepath = None
|
||||||
|
asset_list_header = 0
|
||||||
|
landlord_block_reference = None
|
||||||
|
master_id_colnames = []
|
||||||
|
phase = True # Inspections not complete, produce a partial view
|
||||||
|
ecosurv_landlords = None
|
||||||
|
|
||||||
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Broadlands"
|
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Broadlands"
|
||||||
data_filename = "Broadlands Asset List.xlsx"
|
data_filename = "Broadlands Asset List.xlsx"
|
||||||
|
|
|
||||||
|
|
@ -431,6 +431,47 @@ HEATING_MAPPINGS = {
|
||||||
'Mains Electric': 'electric fuel',
|
'Mains Electric': 'electric fuel',
|
||||||
'Unvented cylinder': 'other',
|
'Unvented cylinder': 'other',
|
||||||
'MVHR & Heat Recovery': 'other',
|
'MVHR & Heat Recovery': 'other',
|
||||||
'Solar': 'other'
|
'Solar': 'other',
|
||||||
|
|
||||||
|
'Electric storage heaters, Electric storage heaters': 'electric storage heaters',
|
||||||
|
'Room heaters, electric': 'room heaters',
|
||||||
|
'Room heaters, mains gas, Room heaters, electric': 'room heaters',
|
||||||
|
'Air source heat pump, underfloor, electric': 'air source heat pump',
|
||||||
|
'Air source heat pump, radiators, electric': 'air source heat pump',
|
||||||
|
'Air source heat pump, Systems with radiators, electric': 'air source heat pump',
|
||||||
|
'Electric storage heaters': 'electric storage heaters',
|
||||||
|
'Air source heat pump, Underfloor heating and radiators, pipes in screed above insulation, electric': 'air source '
|
||||||
|
'heat pump',
|
||||||
|
'Room heaters, coal': 'room heaters',
|
||||||
|
'Room heaters, electric, Electric storage heaters': 'electric storage heaters',
|
||||||
|
'Air source heat pump, fan coil units, electric': 'air source heat pump',
|
||||||
|
'Boiler and radiators, mains gas': 'gas boiler, radiators',
|
||||||
|
'Boiler and radiators, mains gas, Electric storage heaters': 'condensing boiler, radiators',
|
||||||
|
'Room heaters, mains gas': 'room heaters',
|
||||||
|
'Air source heat pump, radiators, electric, Air source heat pump, fan coil units, electric': 'air source heat pump',
|
||||||
|
'Air source heat pump, warm air, electric': 'air source heat pump',
|
||||||
|
'Electric ceiling heating, electric': 'electric ceiling',
|
||||||
|
'Electric storage heaters, Room heaters, electric': 'electric storage heaters',
|
||||||
|
'Room heaters, dual fuel (mineral and wood)': 'room heaters',
|
||||||
|
'Water source heat pump, radiators, electric': 'other',
|
||||||
|
'Warm air, electric': 'warm air heating',
|
||||||
|
'Boiler and radiators, wood logs': 'solid fuel',
|
||||||
|
'Boiler and radiators, dual fuel (mineral and wood)': 'solid fuel',
|
||||||
|
'Boiler & underfloor, mains gas': 'gas boiler, radiators',
|
||||||
|
'Boiler and underfloor heating, mains gas': 'gas boiler, radiators',
|
||||||
|
'Community scheme': 'communal heating',
|
||||||
|
'Warm air, Electricaire': 'warm air heating',
|
||||||
|
'Boiler and radiators, smokeless fuel': 'solid fuel',
|
||||||
|
'Warm air, mains gas': 'warm air heating',
|
||||||
|
'Warm air , electric': 'warm air heating',
|
||||||
|
'Boiler and radiators, LPG': 'boiler - other fuel',
|
||||||
|
'Boiler & underfloor, oil': 'oil boiler',
|
||||||
|
'Boiler and radiators, bottled LPG': 'boiler - other fuel',
|
||||||
|
'Boiler and underfloor heating, oil': 'oil boiler',
|
||||||
|
'SAP05:Main-Heating': 'unknown',
|
||||||
|
'Boiler and radiators, coal': 'solid fuel',
|
||||||
|
'Boiler and radiators, oil': 'oil boiler',
|
||||||
|
'Boiler and radiators, electric': 'electric boiler',
|
||||||
|
'No system present: electric heaters assumed': 'electric radiators',
|
||||||
|
'Boiler and radiators, anthracite': 'solid fuel'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,12 @@ STANDARD_ROOF_CONSTRUCTIONS = {
|
||||||
"another dwelling above",
|
"another dwelling above",
|
||||||
"flat unknown insulation",
|
"flat unknown insulation",
|
||||||
"flat insulated",
|
"flat insulated",
|
||||||
|
"flat uninsulated",
|
||||||
"unknown insulated",
|
"unknown insulated",
|
||||||
"unknown",
|
"unknown",
|
||||||
|
"room roof insulated",
|
||||||
|
"room roof uninsulated",
|
||||||
|
"average thermal transmittance",
|
||||||
}
|
}
|
||||||
|
|
||||||
ROOF_CONSTRUCTION_MAPPINGS = {
|
ROOF_CONSTRUCTION_MAPPINGS = {
|
||||||
|
|
@ -173,6 +177,73 @@ ROOF_CONSTRUCTION_MAPPINGS = {
|
||||||
|
|
||||||
'PitchedNormalNoLoftAccess: Unknown': 'pitched no access to loft',
|
'PitchedNormalNoLoftAccess: Unknown': 'pitched no access to loft',
|
||||||
'PitchedNormalLoftAccess: Unknown': 'pitched unknown insulation',
|
'PitchedNormalLoftAccess: Unknown': 'pitched unknown insulation',
|
||||||
'AnotherDwellingAbove: Unknown': 'another dwelling above'
|
'AnotherDwellingAbove: Unknown': 'another dwelling above',
|
||||||
|
|
||||||
|
'Flat, insulated': 'flat insulated',
|
||||||
|
'Pitched, insulated (assumed)': 'pitched insulated',
|
||||||
|
'Flat, insulated (assumed)': 'flat insulated',
|
||||||
|
'(another dwelling above)': 'another dwelling above',
|
||||||
|
'Pitched, insulated at rafters': 'pitched insulated',
|
||||||
|
'(other premises above)': 'another dwelling above',
|
||||||
|
'Average thermal transmittance 0.15 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Pitched, 25 mm loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Roof room(s), insulated (assumed)': 'room roof insulated',
|
||||||
|
'Pitched, limited insulation (assumed)': 'pitched less than 100mm insulation',
|
||||||
|
'Pitched, 270 mm loft insulation': 'pitched insulated',
|
||||||
|
'Pitched, 250 mm loft insulation': 'pitched insulated',
|
||||||
|
'Pitched, 200mm loft insulation': 'pitched insulated',
|
||||||
|
'Flat, no insulation': 'flat uninsulated',
|
||||||
|
|
||||||
|
'Pitched, 75 mm loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Average thermal transmittance 0.09 W/m-¦K': 'average thermal transmittance',
|
||||||
|
|
||||||
|
'SAP05:Roof': 'unknown',
|
||||||
|
'Pitched, 400 mm loft insulation': 'pitched insulated',
|
||||||
|
'Pitched, 150mm loft insulation': 'pitched insulated',
|
||||||
|
'Average thermal transmittance 0.11 W/m-¦K': 'unknown',
|
||||||
|
'Pitched, 100 mm loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Pitched, 300 mm loft insulation': 'pitched insulated',
|
||||||
|
'Pitched, 75mm loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Pitched, 300+mm loft insulation': 'pitched insulated',
|
||||||
|
'Pitched, 300+ mm loft insulation': 'pitched insulated',
|
||||||
|
'Average thermal transmittance 0.11 W/m?K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.10 W/m?K': 'average thermal transmittance',
|
||||||
|
'Pitched, 250mm loft insulation': 'pitched insulated',
|
||||||
|
'Pitched, 300+ mm loft insulation': 'pitched insulated',
|
||||||
|
'Average thermal transmittance 0.1 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Pitched, *** INVALID INPUT Code : 57 *** loft insulation': 'unknown',
|
||||||
|
'Pitched, 100mm loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Pitched, loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Average thermal transmittance 0.20 W/m?K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.1 W/m?K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.16 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.14 W/m?K': 'average thermal transmittance',
|
||||||
|
'Pitched, 50 mm loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Flat, limited insulation': 'flat uninsulated',
|
||||||
|
'Average thermal transmittance 0.12 W/m?K': 'average thermal transmittance',
|
||||||
|
'Roof room(s), ceiling insulated': 'room roof insulated',
|
||||||
|
'Average thermal transmittance 0.18 W/m?K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.10 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Pitched, 400+ mm loft insulation': 'pitched insulated',
|
||||||
|
'Average thermal transmittance 0.14 W/m²K': 'average thermal transmittance',
|
||||||
|
'Pitched, no insulation (assumed)': 'pitched less than 100mm insulation',
|
||||||
|
'Average thermal transmittance 0.16 W/m?K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.21 W/m?K': 'average thermal transmittance',
|
||||||
|
'Flat, no insulation (assumed)': 'flat uninsulated',
|
||||||
|
'Pitched, no insulation': 'pitched less than 100mm insulation',
|
||||||
|
|
||||||
|
'Average thermal transmittance 0.12 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Pitched, 12 mm loft insulation': 'pitched less than 100mm insulation',
|
||||||
|
'Average thermal transmittance 0.07 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Roof room(s), no insulation (assumed)': 'room roof uninsulated',
|
||||||
|
'Pitched, no insulation(assumed)': 'pitched less than 100mm insulation',
|
||||||
|
'Average thermal transmittance 0.13 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.08 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Average thermal transmittance 0.14 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Pitched, 350 mm loft insulation': 'pitched insulated',
|
||||||
|
'Average thermal transmittance 0 W/m-¦K': 'average thermal transmittance',
|
||||||
|
'Pitched, 200 mm loft insulation': 'pitched insulated',
|
||||||
|
'Pitched, 150 mm loft insulation': 'pitched insulated',
|
||||||
|
'Flat, limited insulation (assumed)': 'flat uninsulated',
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -334,4 +334,13 @@ WALL_CONSTRUCTION_MAPPINGS = {
|
||||||
'Cavity: FilledCavity, TimberFrame: AsBuilt': 'filled cavity',
|
'Cavity: FilledCavity, TimberFrame: AsBuilt': 'filled cavity',
|
||||||
'Cavity: FilledCavity, SolidBrick: AsBuilt, SolidBrick: Internal': 'filled cavity',
|
'Cavity: FilledCavity, SolidBrick: AsBuilt, SolidBrick: Internal': 'filled cavity',
|
||||||
'Cavity: Internal, SolidBrick: AsBuilt': 'filled cavity',
|
'Cavity: Internal, SolidBrick: AsBuilt': 'filled cavity',
|
||||||
|
|
||||||
|
'Timber frame, filled cavity': 'filled cavity',
|
||||||
|
'Cob, as built': 'cob',
|
||||||
|
'Cavity wall, filled cavity and internal insulation': 'filled cavity',
|
||||||
|
'SAP05:Walls': 'other',
|
||||||
|
'Solid brick, as built, partial insulation (assumed)': 'insulated solid brick',
|
||||||
|
'Sandstone, as built, no insulation (assumed)': 'uninsulated sandstone or limestone',
|
||||||
|
'System built, as built, partial insulation (assumed)': 'system built unknown insulation',
|
||||||
|
'Timber frame, with external insulation': 'insulated timber frame'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,9 @@ class Funding:
|
||||||
"""
|
"""
|
||||||
measure_types = [m["type"] for m in measures]
|
measure_types = [m["type"] for m in measures]
|
||||||
innovation_flags = [m.get("is_innovation", False) for m in measures]
|
innovation_flags = [m.get("is_innovation", False) for m in measures]
|
||||||
|
uplifts = [m["uplift"] for m in measures]
|
||||||
innovation_measures = [m["type"] for m in measures if m.get("is_innovation", False)]
|
innovation_measures = [m["type"] for m in measures if m.get("is_innovation", False)]
|
||||||
return measure_types, innovation_flags, innovation_measures
|
return measure_types, uplifts, innovation_flags, innovation_measures
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _meets_upgrade_target(starting_sap: int, ending_sap: int) -> bool:
|
def _meets_upgrade_target(starting_sap: int, ending_sap: int) -> bool:
|
||||||
|
|
@ -325,9 +326,104 @@ class Funding:
|
||||||
|
|
||||||
return starting_str, ending_uvalue
|
return starting_str, ending_uvalue
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff):
|
||||||
|
# We check most likely primary heating system. Because mixed systems are hard to break up, we
|
||||||
|
# check the larger, more prominent heating systems first and then the smaller ones. We aim
|
||||||
|
# to cover the case where properties have heating systems like
|
||||||
|
# "boiler radiators, mains gas, electric storage heaters" so mixed systems
|
||||||
|
if mainheating["has_air_source_heat_pump"]:
|
||||||
|
return 'Air to Water ASHP'
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "biomass"):
|
||||||
|
return 'Biomass Boiler'
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "lpg"):
|
||||||
|
return 'Bottled LPG Boiler'
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
|
||||||
|
mainheat_energy_eff in ["Good", "Very Good"]
|
||||||
|
):
|
||||||
|
# Assume higher efficiency condensing boiler
|
||||||
|
return 'Condensing Gas Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
|
||||||
|
mainheat_energy_eff in ["Average", "Poor"]
|
||||||
|
):
|
||||||
|
return 'Non Condensing Gas Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
|
||||||
|
mainheat_energy_eff in ["Very Poor"]
|
||||||
|
) and mainheating["has_radiators"]:
|
||||||
|
return 'Gas Back Boiler to Radiators'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
|
||||||
|
mainheat_energy_eff in ["Very Poor"]
|
||||||
|
) and not mainheating["has_radiators"]:
|
||||||
|
# Doesnt have radiators
|
||||||
|
return 'Gas Fire with Back Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "oil") and (
|
||||||
|
mainheat_energy_eff in ["Good", "Very Good"]
|
||||||
|
):
|
||||||
|
return 'Condensing Oil Boiler'
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "oil") and (
|
||||||
|
mainheat_energy_eff in ["Average", "Very Poor", "Poor"]
|
||||||
|
):
|
||||||
|
return 'Non Condensing Oil Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "lpg") and (
|
||||||
|
mainheat_energy_eff in ["Good", "Very Good"]
|
||||||
|
):
|
||||||
|
return 'Condensing LPG Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "lpg") and (
|
||||||
|
mainheat_energy_eff in ["Average", "Very Poor", "Poor"]
|
||||||
|
):
|
||||||
|
return 'Non Condensing LPG Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (
|
||||||
|
main_fuel["fuel_type"] in ["dual fuel appliance mineral and wood", "manufactured smokeless fuel"]
|
||||||
|
) and (mainheat_energy_eff in ["Average", "Very Poor", "Poor"]):
|
||||||
|
return 'Solid Fossil Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_ground_source_heat_pump"]:
|
||||||
|
return 'GSHP'
|
||||||
|
|
||||||
|
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "electric"):
|
||||||
|
return 'Electric Boiler'
|
||||||
|
|
||||||
|
if mainheating["has_community_scheme"] and mainheat_energy_eff in ["Good", "Very Good"]:
|
||||||
|
return 'DHS CHP'
|
||||||
|
if mainheating["has_community_scheme"] and mainheat_energy_eff in ["Average", "Very Poor", "Poor"]:
|
||||||
|
return 'DHS non-CHP'
|
||||||
|
|
||||||
|
if mainheating["has_electric_storage_heaters"] and mainheat_energy_eff == "Very Poor":
|
||||||
|
return 'Electric Storage Heaters Responsiveness <=0.2'
|
||||||
|
if mainheating["has_electric_storage_heaters"] and mainheat_energy_eff in [
|
||||||
|
"Poor", "Average", "Good", "Very Good",
|
||||||
|
]:
|
||||||
|
return 'Electric Storage Heaters Responsiveness >0.2'
|
||||||
|
|
||||||
|
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "lpg":
|
||||||
|
return 'Bottled LPG Room Heaters'
|
||||||
|
|
||||||
|
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "electricity":
|
||||||
|
return 'Electric Room Heaters'
|
||||||
|
|
||||||
|
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "mains gas":
|
||||||
|
return 'Gas Room Heaters'
|
||||||
|
|
||||||
|
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] in [
|
||||||
|
"dual fuel appliance mineral and wood", "manufactured smokeless fuel"
|
||||||
|
]:
|
||||||
|
return 'Solid Fossil Room Heaters'
|
||||||
|
|
||||||
|
raise ValueError("Invalid pre heating system")
|
||||||
|
|
||||||
def calculate_partial_project_abs(
|
def calculate_partial_project_abs(
|
||||||
self,
|
self,
|
||||||
measure_type: str,
|
measure_type: str,
|
||||||
|
mainheating: dict,
|
||||||
|
main_fuel: dict,
|
||||||
|
mainheat_energy_eff: str,
|
||||||
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,
|
||||||
|
|
@ -411,6 +507,23 @@ class Funding:
|
||||||
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":
|
||||||
|
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
|
||||||
|
solar_pps_df = df[
|
||||||
|
(df["Measure_Type"] == "Solar_PV") & (df["Pre_Main_Heating_Source"] == pre_heating_system)
|
||||||
|
]
|
||||||
|
return solar_pps_df.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
|
if measure_type == "air_source_heat_pump":
|
||||||
|
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
|
||||||
|
pps = df[
|
||||||
|
(df["Pre_Main_Heating_Source"] == pre_heating_system) &
|
||||||
|
(df["Post_Main_Heating_Source"] == "Air to Water ASHP")
|
||||||
|
]
|
||||||
|
if pps.shape[0] != 1:
|
||||||
|
raise ValueError("something went wrong, more than one pps for ashp")
|
||||||
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
raise ValueError(f"Invalid measure type for partial project ABS calculation: {measure_type}")
|
raise ValueError(f"Invalid measure type for partial project ABS calculation: {measure_type}")
|
||||||
|
|
||||||
# -----------------------
|
# -----------------------
|
||||||
|
|
@ -588,6 +701,9 @@ class Funding:
|
||||||
current_wall_uvalue: float,
|
current_wall_uvalue: float,
|
||||||
is_partial: False,
|
is_partial: False,
|
||||||
existing_li_thickness: float,
|
existing_li_thickness: float,
|
||||||
|
mainheating: dict,
|
||||||
|
main_fuel: dict,
|
||||||
|
mainheat_energy_eff: str,
|
||||||
council_tax_band: str = None,
|
council_tax_band: str = None,
|
||||||
has_wall_insulation_recommendation: bool = False,
|
has_wall_insulation_recommendation: bool = False,
|
||||||
has_roof_insulation_recommendation: bool = False,
|
has_roof_insulation_recommendation: bool = False,
|
||||||
|
|
@ -602,7 +718,7 @@ class Funding:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Normalize measures
|
# Normalize measures
|
||||||
measure_types, innovation_flags, innovation_measures = self._split_measures(measures)
|
measure_types, uplifts, innovation_flags, innovation_measures = self._split_measures(measures)
|
||||||
|
|
||||||
# If we have a heating measure, we check if we meet the pre conditions
|
# If we have a heating measure, we check if we meet the pre conditions
|
||||||
has_ftch = "first_time_central_heating" in measure_types
|
has_ftch = "first_time_central_heating" in measure_types
|
||||||
|
|
@ -666,6 +782,22 @@ class Funding:
|
||||||
if self.eco4_eligible:
|
if self.eco4_eligible:
|
||||||
# Calculate the full project ABS for ECO4
|
# Calculate the full project ABS for ECO4
|
||||||
self.full_project_abs = self.calculate_full_project_abs()
|
self.full_project_abs = self.calculate_full_project_abs()
|
||||||
|
|
||||||
|
# We calculate uplift innovation, where required
|
||||||
|
project_uplifts = []
|
||||||
|
for i, measure in enumerate(measure_types):
|
||||||
|
pps = self.calculate_partial_project_abs(
|
||||||
|
measure_type=measure,
|
||||||
|
mainheating=mainheating,
|
||||||
|
main_fuel=main_fuel,
|
||||||
|
mainheat_energy_eff=mainheat_energy_eff,
|
||||||
|
current_wall_uvalue=current_wall_uvalue,
|
||||||
|
is_partial=is_partial,
|
||||||
|
existing_li_thickness=existing_li_thickness,
|
||||||
|
)
|
||||||
|
project_uplifts.append(pps * uplifts[i])
|
||||||
|
total_uplift = sum(project_uplifts)
|
||||||
|
self.full_project_abs += total_uplift
|
||||||
self.eco4_funding = self.full_project_abs * (
|
self.eco4_funding = self.full_project_abs * (
|
||||||
self.social_cavity_abs_rate if is_cavity else self.social_solid_abs_rate
|
self.social_cavity_abs_rate if is_cavity else self.social_solid_abs_rate
|
||||||
)
|
)
|
||||||
|
|
@ -673,7 +805,13 @@ class Funding:
|
||||||
if self.gbis_eligible:
|
if self.gbis_eligible:
|
||||||
# Calculate the partial project score - this is dependent on the measure
|
# Calculate the partial project score - this is dependent on the measure
|
||||||
self.partial_project_abs = self.calculate_partial_project_abs(
|
self.partial_project_abs = self.calculate_partial_project_abs(
|
||||||
measure_types[0], current_wall_uvalue, is_partial, existing_li_thickness,
|
measure_type=measure_types[0],
|
||||||
|
mainheating=mainheating,
|
||||||
|
main_fuel=main_fuel,
|
||||||
|
mainheat_energy_eff=mainheat_energy_eff,
|
||||||
|
current_wall_uvalue=current_wall_uvalue,
|
||||||
|
is_partial=is_partial,
|
||||||
|
existing_li_thickness=existing_li_thickness,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -907,3 +907,84 @@ def test_custom_eco4_scenarios(
|
||||||
assert caveat in funding.eco4_eligibility_caveats, f"Missing caveat in: {scenario['description']}"
|
assert caveat in funding.eco4_eligibility_caveats, f"Missing caveat in: {scenario['description']}"
|
||||||
for caveat in funding.eco4_eligibility_caveats:
|
for caveat in funding.eco4_eligibility_caveats:
|
||||||
assert caveat in scenario.get("expected_caveats", []), f"Unexpected caveat in: {scenario['description']}"
|
assert caveat in scenario.get("expected_caveats", []), f"Unexpected caveat in: {scenario['description']}"
|
||||||
|
|
||||||
|
|
||||||
|
### -------------------------
|
||||||
|
### Innovation uplift scenarios
|
||||||
|
### -------------------------
|
||||||
|
|
||||||
|
def test_uplift(
|
||||||
|
mock_project_scores_matrix,
|
||||||
|
mock_partial_scores_matrix,
|
||||||
|
mock_whlg_postcodes
|
||||||
|
):
|
||||||
|
funding = Funding(
|
||||||
|
project_scores_matrix=mock_project_scores_matrix,
|
||||||
|
partial_project_scores_matrix=mock_partial_scores_matrix,
|
||||||
|
whlg_eligible_postcodes=mock_whlg_postcodes,
|
||||||
|
social_cavity_abs_rate=13.5,
|
||||||
|
social_solid_abs_rate=17,
|
||||||
|
private_cavity_abs_rate=13.5,
|
||||||
|
private_solid_abs_rate=17,
|
||||||
|
tenure="Social"
|
||||||
|
)
|
||||||
|
|
||||||
|
# # TODO: Add a scenario with multiple measures, where some are innovation, some are not and we have
|
||||||
|
# TODO: Make sure private works too
|
||||||
|
measures = [
|
||||||
|
{"type": "solar_pv", "is_innovation": True, "uplift": 0.45},
|
||||||
|
{"type": "internal_wall_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": "cavity_wall_insulation", "is_innovation": False, "uplift": 0.25},
|
||||||
|
]
|
||||||
|
|
||||||
|
mainheating = {
|
||||||
|
'original_description': 'Electric storage heaters', 'has_radiators': False,
|
||||||
|
'has_fan_coil_units': False,
|
||||||
|
'has_pipes_in_screed_above_insulation': False,
|
||||||
|
'has_pipes_in_insulated_timber_floor': False,
|
||||||
|
'has_pipes_in_concrete_slab': False, 'has_boiler': False,
|
||||||
|
'has_air_source_heat_pump': False,
|
||||||
|
'has_room_heaters': False, 'has_electric_storage_heaters': True, 'has_warm_air': False,
|
||||||
|
'has_electric_underfloor_heating': False, 'has_electric_ceiling_heating': False,
|
||||||
|
'has_community_scheme': False,
|
||||||
|
'has_ground_source_heat_pump': False, 'has_no_system_present': False,
|
||||||
|
'has_portable_electric_heaters': False,
|
||||||
|
'has_water_source_heat_pump': False, 'has_electric': True, 'has_mains_gas': False,
|
||||||
|
'has_wood_logs': False,
|
||||||
|
'has_coal': False, 'has_oil': False, 'has_wood_pellets': False, 'has_anthracite':
|
||||||
|
False,
|
||||||
|
'has_dual_fuel_mineral_and_wood': False, 'has_smokeless_fuel': False, 'has_lpg': False,
|
||||||
|
'has_assumed': False,
|
||||||
|
'has_electricaire': False, 'has_assumed_for_most_rooms': False,
|
||||||
|
'has_underfloor_heating': False,
|
||||||
|
"has_electric_heat_pumps": False,
|
||||||
|
"has_micro-cogeneration": False
|
||||||
|
}
|
||||||
|
main_fuel = {
|
||||||
|
'original_description': 'Electricity: electricity, unspecified tariff', 'fuel_type':
|
||||||
|
'electricity',
|
||||||
|
'tariff_type': 'unspecified tariff', 'is_community': False,
|
||||||
|
'no_individual_heating_or_community_network': False,
|
||||||
|
'complex_fuel_type': None
|
||||||
|
}
|
||||||
|
mainheat_energy_eff = "Good"
|
||||||
|
|
||||||
|
funding.check_funding(
|
||||||
|
measures=measures,
|
||||||
|
starting_sap=33,
|
||||||
|
ending_sap=69,
|
||||||
|
floor_area=71,
|
||||||
|
mainheat_description="Electic storage heaters",
|
||||||
|
heating_control_description="Manual charge control",
|
||||||
|
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=mainheating,
|
||||||
|
main_fuel=main_fuel,
|
||||||
|
mainheat_energy_eff=mainheat_energy_eff,
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue