From 48f21e6edf3e65bf725d78282bf4ebf0fbb81c7e Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Wed, 7 Aug 2024 16:25:30 +0100 Subject: [PATCH] insert phase metrics into the simualation epc --- backend/Property.py | 34 ++++++++++++++++++++++++++++++ backend/app/plan/router.py | 5 +++++ recommendations/Recommendations.py | 3 +++ 3 files changed, 42 insertions(+) diff --git a/backend/Property.py b/backend/Property.py index 25068f6c..b040ffee 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -22,6 +22,7 @@ from recommendations.recommendation_utils import ( estimate_windows, ) from backend.ml_models.AnnualBillSavings import AnnualBillSavings +from backend.app.utils import sap_to_epc ENVIRONMENT = os.environ.get("ENVIRONMENT", "dev") DATA_BUCKET = os.environ.get( @@ -442,6 +443,39 @@ class Property: simulation_epc.update(phase_epc_transformation) self.simulation_epcs[phase] = simulation_epc + def update_simulation_epcs(self, impact_summary): + """ + This method will insert the high level measures, such as SAP, heat demand, carbon, etc + :return: + """ + if self.simulation_epcs is None: + raise ValueError("Simulation EPCs have not been created") + + phases = 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] + # We update all of the features that should have an impact on the kwh model + + sim_epc.update( + { + "heating-cost-current": phase_impact["unadjusted_heating_cost"], + "hot-water-cost-current": phase_impact["unadjusted_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"]) + ), + "co2-emissions-current": phase_impact["carbon"], + "current-energy-rating": sap_to_epc(phase_impact["sap"]), + "current-energy-efficiency": int(np.floor(phase_impact["sap"])), + "current-energy-cost": phase_impact["unadjusted_energy_cost"], + "energy-consumption-current": phase_impact["heat_demand"], + "lighting-cost-current": phase_impact["unadjusted_lighting_cost"], + } + ) + @staticmethod def create_recommendation_scoring_data( property_id, diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index fb4ffa14..b2c235d3 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -800,6 +800,7 @@ async def trigger_plan(body: PlanTriggerRequest): # possibility with heating system # TODO: After optimising, if there are any cheap, quick win measures (e.g. insulate water tank with hot water # cylinder jacket), we should add these to the recommendations as default + raise Exception("Add the cost impacts into the cost model") logger.info("Optimising recommendations") for property_id in recommendations.keys(): @@ -813,6 +814,10 @@ async def trigger_plan(body: PlanTriggerRequest): ) ) + # We use the impact_summary to update the simulation_epcs with the new SAP, heat demand, carbon, cost etc + # at each phase + property_instance.update_simulation_epcs(impact_summary) + input_measures = prepare_input_measures(recommendations_with_impact, body.goal) current_sap_points = int(property_instance.data["current-energy-efficiency"]) diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py index 0de8931a..c099c8a3 100644 --- a/recommendations/Recommendations.py +++ b/recommendations/Recommendations.py @@ -500,6 +500,9 @@ class Recommendations: previous_phase_values.update(previous_phase_unadjusted_costs) # We extract the values for the current phase + # TODO: For things like lighting costs for heating and hot water recommendations, we should actually + # update phase_cost since the phase cost should be the same as the previous phase + current_phase_values = { "sap": phase_energy_efficiency_metrics["sap_change"], "carbon": phase_energy_efficiency_metrics["carbon_change"],