diff --git a/.idea/Model.iml b/.idea/Model.iml index c6561970..09f2e496 100644 --- a/.idea/Model.iml +++ b/.idea/Model.iml @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 50cad4ca..fb10c6b0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/asset_list/AssetList.py b/asset_list/AssetList.py index 3731fc77..eca4ae1f 100644 --- a/asset_list/AssetList.py +++ b/asset_list/AssetList.py @@ -860,7 +860,7 @@ class AssetList: return date_str.year # Handle numeric year (float or int) - if isinstance(date_str, (int, float)): + if isinstance(date_str, (int, float, np.int_)): if 1000 <= int(date_str) <= 2100: return int(date_str) @@ -887,9 +887,6 @@ class AssetList: self.landlord_year_built ].apply(extract_year) - for x in self.standardised_asset_list[self.landlord_year_built].values: - extract_year(x) - # We now create standard lookups to_remap = { self.landlord_property_type: { @@ -1346,7 +1343,9 @@ class AssetList: if self.new_format_non_insturives_present_v2: existing_solar_non_intrusives_check = ( - self.standardised_asset_list["non-intrusives: ROOF ORIENTATION"] == "ALREADY HAS SOLAR PV" + self.standardised_asset_list["non-intrusives: ROOF ORIENTATION"].str.strip().isin( + ["ALREADY HAS SOLAR PV"] + ) ) else: existing_solar_non_intrusives_check = ( diff --git a/asset_list/app.py b/asset_list/app.py index 8af23f38..763f245f 100644 --- a/asset_list/app.py +++ b/asset_list/app.py @@ -58,6 +58,40 @@ def app(): EPC recommendations Property UPRN """ + # Abri + data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Abri/Post Inspections" + data_filename = "Desktop ABRI data - Standardised After Programmes (2).xlsx" + sheet_name = "Reviewed List" + postcode_column = 'domna_postcode' + address1_column = "domna_address_1" + address1_method = None + fulladdress_column = "domna_full_address" + address_cols_to_concat = [] + missing_postcodes_method = None + landlord_year_built = "landlord_year_built" + landlord_os_uprn = None + landlord_property_type = "PropertyType_original_from_landlord" + landlord_built_form = "BuildForm_original_from_landlord" + landlord_wall_construction = "Wall Construction_original_from_landlord" + landlord_roof_construction = None + landlord_heating_system = "HeatingType_original_from_landlord" + landlord_existing_pv = None + landlord_property_id = "landlord_property_id" + landlord_sap = None + outcomes_filename = None + outcomes_sheetname = None + outcomes_postcode = None + outcomes_houseno = None + outcomes_id = None + outcomes_address = None + master_filepaths = [] + master_id_colnames = [] + master_to_asset_list_filepath = None + phase = False + ecosurv_landlords = None + asset_list_header = 0 + landlord_block_reference = None + # Freebridge data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Freebridge" data_filename = "Domna - FCH property data May 25 copy.xlsx" diff --git a/backend/Funding.py b/backend/Funding.py index cab11899..18e77713 100644 --- a/backend/Funding.py +++ b/backend/Funding.py @@ -38,6 +38,12 @@ class Funding: self.floor_area_band = None self.project_scores_matrix = 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.eco4_eligible = False @@ -432,10 +438,7 @@ class Funding: """ Calculate the partial project ABS score for a single measure. """ - df = 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) - ] + df = self.partial_project_scores_matrix if measure_type == "internal_wall_insulation": if current_wall_uvalue is None: @@ -518,8 +521,10 @@ class Funding: 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") + (df["Post_Main_Heating_Source"] == "Air to Water ASHP") & + (df["Measure_Type"] == "B_Upgrade_nopreHCs") # We assume we'll be making a heating system upgrade ] + if pps.shape[0] != 1: raise ValueError("something went wrong, more than one pps for ashp") return pps.squeeze()["Cost Savings"] diff --git a/backend/tests/test_funding.py b/backend/tests/test_funding.py index 45e26dc8..7758de5f 100644 --- a/backend/tests/test_funding.py +++ b/backend/tests/test_funding.py @@ -988,3 +988,62 @@ def test_uplift( main_fuel=main_fuel, mainheat_energy_eff=mainheat_energy_eff, ) + + +# Large scale testing for various measures +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": True, "uplift": 0.25}, + {"type": "high_heat_retention_storage_heaters", "is_innovation": False, "uplift": 0}, +] +epc_df = pd.read_csv( + "/Users/khalimconn-kowlessar/Downloads/domestic-E08000025-Birmingham/certificates.csv" +) +from tqdm import tqdm +from etl.epc_clean.epc_attributes.MainheatAttributes import MainHeatAttributes +from etl.epc_clean.epc_attributes.MainFuelAttributes import MainFuelAttributes + +mock_project_scores_matrix = mock_project_scores_matrix() +mock_whlg_postcodes = mock_whlg_postcodes() +mock_partial_scores_matrix = mock_partial_scores_matrix() + +for _, x in tqdm(epc_df.iterrows(), total=len(epc_df)): + # inputs + mainheat_energy_eff = x["MAINHEAT_ENERGY_EFF"] + heating_cleaner = MainHeatAttributes(description=x["MAINHEAT_DESCRIPTION"]) + fuel_cleaner = MainFuelAttributes(description=x["MAIN_FUEL"]) + + h = heating_cleaner.process() + f = fuel_cleaner.process() + + 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" + ) + + funding.check_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, + )