From 9284d6cf764d0d6a4e9b123474cada3f197b829b Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 3 Jun 2024 22:43:51 +0100 Subject: [PATCH] prepared the optimised output" --- backend/app/plan/router.py | 138 ++++++++++++++++++++++++++++++++++++- recommendations/Mds.py | 22 +++--- 2 files changed, 148 insertions(+), 12 deletions(-) diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index b8437fa2..8d7309a6 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -773,7 +773,7 @@ async def build_mds(body: MdsRequest): data = p.recommendations_scoring_data.copy() for d in data: - d["id"] = d["id"] + _id + d["id"] = d["id"] + "*" + _id recommendations_scoring_data.extend(data) @@ -823,6 +823,142 @@ async def build_mds(body: MdsRequest): if p["uprn"]: p["uprn"] = str(int(float(p["uprn"]))) + import re + from backend.ml_models.AnnualBillSavings import AnnualBillSavings + + if optimise_measures: + results = [] + for p in input_properties: + + package_comparison = [] + for _id in recommendations[p.id].keys(): + sap_prediction = all_predictions["sap_change_predictions"][ + (all_predictions["sap_change_predictions"]["property_id"] == str(p.id)) & + (all_predictions["sap_change_predictions"]["recommendation_id"].str.contains(re.escape(_id))) + ].copy().reset_index(drop=True) + sap_prediction["row_id"] = sap_prediction.index + + heat_demand_prediction = all_predictions["heat_demand_predictions"][ + (all_predictions["heat_demand_predictions"]["property_id"] == str(p.id)) & + (all_predictions["heat_demand_predictions"]["recommendation_id"].str.contains(re.escape(_id))) + ].copy().reset_index(drop=True) + heat_demand_prediction["row_id"] = heat_demand_prediction.index + + carbon_prediction = all_predictions["carbon_change_predictions"][ + (all_predictions["carbon_change_predictions"]["property_id"] == str(p.id)) & + (all_predictions["carbon_change_predictions"]["recommendation_id"].str.contains(re.escape(_id))) + ].copy().reset_index(drop=True) + carbon_prediction["row_id"] = carbon_prediction.index + + epc_target = body.goal_value + sap_target = epc_to_sap_lower_bound(epc_target) + # Define the measures + sap_threshold_barrier = sap_prediction[sap_prediction["predictions"] >= sap_target] + if sap_threshold_barrier.empty: + raise NotImplementedError("FIX ME") + sap_threshold_barrier = sap_threshold_barrier.head(1) + + sap_prediction = sap_prediction[ + sap_prediction["row_id"] <= sap_threshold_barrier["row_id"].values[0] + ] + heat_demand_prediction = heat_demand_prediction[ + heat_demand_prediction["row_id"] <= sap_threshold_barrier["row_id"].values[0] + ] + carbon_prediction = carbon_prediction[ + carbon_prediction["row_id"] <= sap_threshold_barrier["row_id"].values[0] + ] + + reverse_map = {v: k for k, v in Mds.format_map.items()} + + selected_measures = [ + reverse_map[x.split("-")[0]] for x in sap_prediction["recommendation_id"].values + ] + selected_measure_ids = [x.split("*")[0] for x in sap_prediction["recommendation_id"].values] + + costs = [ + r["total"] for r in representative_recommendations[p.id][_id] if + r["recommendation_id"] in selected_measure_ids + ] + costs = sum(costs) + + sap_before = int(p.data["current-energy-efficiency"]) + sap_after = sap_prediction["predictions"].values[-1] + + epc_before = p.data["current-energy-rating"] + epc_after = sap_to_epc(sap_after) + + heat_demand_before = p.data["energy-consumption-current"] + heat_demand_after = heat_demand_prediction["predictions"].values[-1] + + carbon_before = p.data["co2-emissions-current"] + carbon_after = carbon_prediction["predictions"].values[-1] + + current_adjusted_energy = AnnualBillSavings.adjust_energy_to_metered( + epc_energy_consumption=heat_demand_before * p.floor_area, + current_epc_rating=epc_before, + ) + + expected_adjusted_energy = AnnualBillSavings.adjust_energy_to_metered( + epc_energy_consumption=heat_demand_after * p.floor_area, + current_epc_rating=epc_before, + ) + + current_energy_bill = AnnualBillSavings.calculate_annual_bill(current_adjusted_energy) + expected_energy_bill = AnnualBillSavings.calculate_annual_bill(expected_adjusted_energy) + + bill_savings = current_energy_bill - expected_energy_bill + energy_savings = current_adjusted_energy - expected_adjusted_energy + + package_comparison.append( + { + "id": _id, + "cost": costs, + "measures": selected_measures, + "sap_before": sap_before, + "sap_after": sap_after, + "epc_before": epc_before, + "epc_after": epc_after, + "heat_demand_before": heat_demand_before, + "heat_demand_after": heat_demand_after, + "carbon_before": carbon_before, + "carbon_after": carbon_after, + "bill_savings": bill_savings, + "energy_savings": energy_savings, + } + ) + + package_comparison = pd.DataFrame(package_comparison) + # Find the smallest cost package + package_comparison = package_comparison.sort_values("cost") + package_comparison = package_comparison.head(1).to_dict("records")[0] + + config = [c for c in plan_input if c["uprn"] == str(p.uprn)] + if not config: + config = {"address": None, "postcode": None} + else: + config = config[0] + + results.append({ + "config_address": config["address"], + "config_postcode": config["postcode"], + "address": p.address, + "postcode": p.postcode, + "measures": package_comparison["measures"], + "year_of_epc": p.data['lodgement-date'], + "sap_before": package_comparison["sap_before"], + "sap_after": package_comparison["sap_after"], + "epc_before": package_comparison["epc_before"], + "epc_after": package_comparison["epc_after"], + "heat_demand_before": package_comparison["heat_demand_before"], + "heat_demand_after": package_comparison["heat_demand_after"], + "carbon_before": package_comparison["carbon_before"], + "carbon_after": package_comparison["carbon_after"], + "bill_savings": package_comparison["bill_savings"], + "energy_savings": package_comparison["energy_savings"], + }) + + results = pd.DataFrame(results) + results = [] for p in input_properties: measures = p.measures diff --git a/recommendations/Mds.py b/recommendations/Mds.py index ac80af1a..9fe3ff09 100644 --- a/recommendations/Mds.py +++ b/recommendations/Mds.py @@ -22,6 +22,16 @@ class Mds: Handles the contruction of the MDS report """ + format_map = { + "external_wall_insulation": "EWI (Trad Const)", + "internal_wall_insualtion": "IWI", + "cavity_wall_insulation": "CWI", + "loft_insulation": "LI", + "air_source_heat_pump": "ASHP Htg", + "high_heat_retention_storage_heaters": "High Heat Retention Storage Heaters", + "solar_pv": "Solar PV", + } + def __init__(self, property_instance: Property, materials, optimise_measures: bool = False): self.property_instance = property_instance @@ -55,16 +65,6 @@ class Mds: 'solar_pv' ] - format_map = { - "external_wall_insulation": "EWI (Trad Const)", - "internal_wall_insualtion": "IWI", - "cavity_wall_insulation": "CWI", - "loft_insulation": "LI", - "air_source_heat_pump": "ASHP Htg", - "high_heat_retention_storage_heaters": "High Heat Retention Storage Heaters", - "solar_pv": "Solar PV", - } - # Check if our measures are within the ones we've handled new = [m for m in measures if m not in all_considered_measures] if new: @@ -159,7 +159,7 @@ class Mds: pruned_measures_formatted = [] for pm in pruned_measures: - pruned_measures_formatted.append({pm: format_map[pm]}) + pruned_measures_formatted.append({pm: self.format_map[pm]}) pruned_combinations.append(pruned_measures_formatted)