From c77f642861f214c44a378ff46a21bb652c4cf26d Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 8 Aug 2024 11:10:21 +0100 Subject: [PATCH] inserting the kwh savings into the recommendation --- backend/Property.py | 26 +++++++------- backend/app/plan/router.py | 74 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 13 deletions(-) diff --git a/backend/Property.py b/backend/Property.py index 414d0831..d66db529 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -430,28 +430,28 @@ class Property: if self.simulation_epcs is None: raise ValueError("Simulation EPCs have not been created") - phases = sorted(list(self.simulation_epcs.keys())) + rec_ids = sorted(list(self.simulation_epcs.keys())) updated_simulation_epcs = [] - for phase in phases: - sim_epc = self.simulation_epcs[phase].copy() - phase_impact = [x for x in impact_summary if x["phase"] == phase][0] + for rec_id in rec_ids: + sim_epc = self.simulation_epcs[rec_id].copy() + rec_impact = [x for x in impact_summary if x["recommendation_id"] == rec_id][0] # We update all of the features that should have an impact on the kwh model sim_epc.update( { - "heating-cost-current": phase_impact["epc_heating_cost"], - "hot-water-cost-current": phase_impact["epc_hot_water_cost"], + "heating-cost-current": rec_impact["epc_heating_cost"], + "hot-water-cost-current": rec_impact["epc_hot_water_cost"], # CO₂ emissions per square metre floor area per year in kg/m². Since CO₂ emissions are in tonnes # per year, we multiply by 1000 to get kg/m² "co2-emiss-curr-per-floor-area": round( - 1000 * (phase_impact["carbon"] / self.data["total-floor-area"]) + 1000 * (rec_impact["carbon"] / self.data["total-floor-area"]) ), - "co2-emissions-current": phase_impact["carbon"], - "current-energy-rating": sap_to_epc(phase_impact["sap"]), - "current-energy-efficiency": int(np.floor(phase_impact["sap"])), - "energy-consumption-current": phase_impact["heat_demand"], - "lighting-cost-current": phase_impact["epc_lighting_cost"], - "phase": phase + "co2-emissions-current": rec_impact["carbon"], + "current-energy-rating": sap_to_epc(rec_impact["sap"]), + "current-energy-efficiency": int(np.floor(rec_impact["sap"])), + "energy-consumption-current": rec_impact["heat_demand"], + "lighting-cost-current": rec_impact["epc_lighting_cost"], + "id": "+".join([str(self.id), rec_id]) } ) updated_simulation_epcs.append(sim_epc) diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index 95ea7d92..47478b3c 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -874,6 +874,80 @@ async def trigger_plan(body: PlanTriggerRequest): # We call the API with the scoring epcs scoring_epcs = pd.DataFrame(scoring_epcs) + scoring_epcs = add_features_from_code(scoring_epcs) + scoring_epcs = add_estimate_annual_kwh(scoring_epcs) + # TODO: Drop all potential and env columns + kwh_simulation_predictions = model_api.predict_all( + df=scoring_epcs, + bucket=get_settings().DATA_BUCKET, + prediction_buckets=get_prediction_buckets(), + model_prefixes=["heating_kwh_predictions", "hotwater_kwh_predictions"], + extract_ids=True + ) + + # We now insert into the recommendations + for property_id in recommendations.keys(): + property_recommendations = recommendations[property_id] + property_instance = [p for p in input_properties if p.id == property_id][0] + # The predicted kwhs are without appliances + consumption = property_instance.energy_consumption_estimates["adjusted"] + # Starting consumption is the sum of the consumption values, without appliances + starting_heating = consumption["heating"] + starting_hotwater = consumption["hot_water"] + property_kwh_predictions = { + k: kwh_simulation_predictions[k][kwh_simulation_predictions[k]["property_id"] == str(property_id)] + for k in ['heating_kwh_predictions', 'hotwater_kwh_predictions'] + } + # We adjust the predictions + from backend.ml_models.AnnualBillSavings import AnnualBillSavings + for k in ["heating_kwh_predictions", "hotwater_kwh_predictions"]: + property_kwh_predictions[k]["adjusted"] = property_kwh_predictions[k]["predictions"].apply( + lambda x: AnnualBillSavings.adjust_energy_to_metered( + epc_energy=x, current_epc_rating=property_instance.data["current-energy-rating"] + ) + ) + + # For each recommendation, we difference the predictions + property_kwh_predictions["heating_kwh_predictions"]["savings"] = np.diff( + property_kwh_predictions["heating_kwh_predictions"]["adjusted"], prepend=starting_heating + ) + property_kwh_predictions["hotwater_kwh_predictions"]["savings"] = np.diff( + property_kwh_predictions["hotwater_kwh_predictions"]["adjusted"], prepend=starting_hotwater + ) + + for recommendations_by_type in property_recommendations: + for rec in recommendations_by_type: + # In the case of mechanical ventilation, there is no impact, and for low energy lighting we + # calculate the savings inside of the recommendation itself + if rec["type"] in ["mechanical_ventilation", "low_energy_lighing"]: + continue + + heating_kwh_savings = property_kwh_predictions["heating_kwh_predictions"][ + ( + property_kwh_predictions["heating_kwh_predictions"]["recommendation_id"] == + rec["recommendation_id"] + ) + ]["savings"].values[0] + # This should be negative + if heating_kwh_savings > 0: + print("Positive heating kwh savings") + # TODO: Raise an exception to investigate + # raise Exception("Positive heating kwh savings") + + hot_water_kwh_savings = property_kwh_predictions["hotwater_kwh_predictions"][ + ( + property_kwh_predictions["hotwater_kwh_predictions"]["recommendation_id"] == + rec["recommendation_id"] + ) + ]["savings"].values[0] + + # This should be negative + if hot_water_kwh_savings > 0: + print("Positive hot water kwh savings") + # TODO: Raise an exception to investigate + # raise Exception("Positive hot water kwh savings") + + rec["kwh_savings"] = abs(heating_kwh_savings + hot_water_kwh_savings) # 1) the property data # 2) the property details (epc)