diff --git a/backend/Property.py b/backend/Property.py index 45c7b3e5..497d976a 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -384,8 +384,9 @@ class Property: types = [x["type"] for x in previous_phase_representatives] if "external_wall_insulation" in types and "internal_wall_insulation" in types: raise Exception("We shouldn't have this in the representative recommendations") + # We include previous phases + the recommendation itself in the EPC transformations epc_transformations = [ - x["description_simulation"] for x in previous_phase_representatives + x["description_simulation"] for x in previous_phase_representatives + [rec] ] # It is possible that we could have two simulations applied to the same descriptions @@ -439,8 +440,6 @@ class Property: sim_epc.update( { - "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( @@ -450,7 +449,6 @@ class Property: "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]) } ) @@ -594,8 +592,7 @@ class Property: Given the cleaning that has been performed, we'll use this to identify the property components, from roof to walls to windows, heating and hot water :param cleaned: This is the dictionary of components found in cleaner.cleaned - :param energy_consumption_client: Contains the heating and hot water kwh models - used to predict current - energy annual consumption in kWh + :param energy_consumption_client: The client that will be used to convert the energy costs to today's costs :param kwh_predictions: Contains the kwh predictions for heating and hot water :return: """ @@ -686,14 +683,6 @@ class Property: # 2) Predicted KwH # Today's costs - todays_heating_cost = energy_consumption_client.convert_cost_to_today( - original_cost=float(self.data["heating-cost-current"]), - lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"]).tz_localize(None) - ) - todays_hot_water_cost = energy_consumption_client.convert_cost_to_today( - original_cost=float(self.data["hot-water-cost-current"]), - lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"]).tz_localize(None) - ) todays_lighting_cost = energy_consumption_client.convert_cost_to_today( original_cost=float(self.data["lighting-cost-current"]), lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"]).tz_localize(None) @@ -702,15 +691,6 @@ class Property: # If we have the kwh figures, we don't need to predict them condition_data = self.energy_assessment_condition_data.copy() - # scoring_df = pd.DataFrame([self.epc_record.prepared_epc]) - # # Change columns from underscores to hyphens - # scoring_df.columns = [ - # x.lower().replace("_", "-") for x in scoring_df.columns - # ] - # for col in ["heating_kwh", "hot_water_kwh"]: - # scoring_df[col] = None - # - # energy_consumption_client.data = None heating_kwh_predictions = kwh_predictions["heating_kwh_predictions"] hotwater_kwh_predictions = kwh_predictions["hotwater_kwh_predictions"] diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index 05f8f88f..02e669a5 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -588,7 +588,7 @@ async def trigger_plan(body: PlanTriggerRequest): raise Exception("Missed setting of spatial data for a property") p.get_components( cleaned=cleaned, - energy_consumption_client=energy_consumption_client, # TODO: Full remove me + energy_consumption_client=energy_consumption_client, kwh_predictions=kwh_predictions ) @@ -799,7 +799,6 @@ async def trigger_plan(body: PlanTriggerRequest): logger.info("Optimising recommendations") scoring_epcs = [] # For scoring the kwh models for property_id in recommendations.keys(): - property_instance = [p for p in input_properties if p.id == property_id][0] recommendations_with_impact, impact_summary = ( @@ -880,6 +879,8 @@ async def trigger_plan(body: PlanTriggerRequest): extract_ids=True ) + # TODO: Costing model, which should include today's costs! + # We now insert into the recommendations for property_id in recommendations.keys(): property_recommendations = recommendations[property_id] diff --git a/backend/ml_models/api.py b/backend/ml_models/api.py index 0de7977f..c401e0f4 100644 --- a/backend/ml_models/api.py +++ b/backend/ml_models/api.py @@ -12,20 +12,20 @@ class ModelApi: "sap_change_predictions", "heat_demand_predictions", "carbon_change_predictions", - "lighting_cost_predictions", - "heating_cost_predictions", - "hot_water_cost_predictions", + # "lighting_cost_predictions", + # "heating_cost_predictions", + # "hot_water_cost_predictions", ] MODEL_URLS = { "sap_change_predictions": "sapmodel", "heat_demand_predictions": "heatmodel", "carbon_change_predictions": "carbonmodel", - "lighting_cost_predictions": "lightingmodel", - "heating_cost_predictions": "heatingmodel", - "hot_water_cost_predictions": "hotwatermodel", "hotwater_kwh_predictions": "hotwaterkwhmodel", "heating_kwh_predictions": "heatingkwhmodel", + # "lighting_cost_predictions": "lightingmodel", + # "heating_cost_predictions": "heatingmodel", + # "hot_water_cost_predictions": "hotwatermodel", } def __init__( diff --git a/etl/bill_savings/data_collection.py b/etl/bill_savings/data_collection.py index df95f8e2..0341b885 100644 --- a/etl/bill_savings/data_collection.py +++ b/etl/bill_savings/data_collection.py @@ -134,8 +134,8 @@ def app(): for i, directory in tqdm(enumerate(epc_directories), total=len(epc_directories)): # Skip the first 50 - # if i < 57: - # continue + if i < 18: + continue data = pd.read_csv(directory / "certificates.csv", low_memory=False) # Rename the columns to the same format as the api returns diff --git a/etl/testing_data/bills_model_testing.py b/etl/testing_data/bills_model_testing.py index c10bbd8a..ea13f796 100644 --- a/etl/testing_data/bills_model_testing.py +++ b/etl/testing_data/bills_model_testing.py @@ -226,16 +226,18 @@ base_prediction = model_api.predict_all( extract_ids=False ) -cwi_epc = epcs_for_scoring.copy() -cwi_epc["walls-description"] = "Cavity wall, filled cavity" -cwi_epc["walls-energy-eff"] = "Good" -cwi_epc["heating-cost-current"] = 1650 -cwi_epc["current-energy-efficiency"] = 72 -cwi_epc["current-energy-rating"] = "C" -cwi_epc["co2-emissions-current"] = 3.7 -cwi_epc["energy-consumption-current"] = 121 -cwi_epc["co2-emiss-curr-per-floor-area"] = 19 -cwi_epc["photo-supply"] = 0 +cwi_epc = pd.DataFrame([property_scoring_epcs[1].copy()]) +cwi_epc = add_features_from_code(cwi_epc) +cwi_epc = add_estimate_annual_kwh(cwi_epc) +# cwi_epc["walls-description"] = "Cavity wall, filled cavity" +# cwi_epc["walls-energy-eff"] = "Good" +# cwi_epc["heating-cost-current"] = 1650 +# cwi_epc["current-energy-efficiency"] = 72 +# cwi_epc["current-energy-rating"] = "C" +# cwi_epc["co2-emissions-current"] = 3.7 +# cwi_epc["energy-consumption-current"] = 121 +# cwi_epc["co2-emiss-curr-per-floor-area"] = 19 +# cwi_epc["photo-supply"] = 0 # cwi_epc["energy-consumption-current"] = # cwi_epc["roof-description"] = "Pitched, 300 mm loft insulation" # cwi_epc["roof-energy-eff"] = "Very Good" @@ -259,7 +261,27 @@ cwi_prediction = model_api.predict_all( df=cwi_epc, bucket=get_settings().DATA_BUCKET, prediction_buckets=get_prediction_buckets(), - model_prefixes=["heating_kwh_predictions"], + model_prefixes=["heating_kwh_predictions", "hotwater_kwh_predictions"], extract_ids=False ) -2344 - 2060 + +# 77 perryn +starting_heating = 19837.2 +starting_hot_water = 2974.1 + +ending_heating = 17041.1 +ending_hot_water = 2735.3 + +# 44 lindlings +starting_heating = 13327.1 +starting_hot_water = 2349.5 + +ending_heating = 9672.3 +ending_hot_water = 2030.2 + +ending_heating = 8695.1 +ending_hot_water = 2437.0 + +heating_impact = starting_heating - ending_heating +hot_water_impact = starting_hot_water - ending_hot_water +total_impact = heating_impact + hot_water_impact diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py index 9d709639..b8174ae0 100644 --- a/recommendations/Recommendations.py +++ b/recommendations/Recommendations.py @@ -379,26 +379,13 @@ class Recommendations: property_predictions = { prefix + "_predictions": all_predictions[prefix + "_predictions"][ all_predictions[prefix + "_predictions"]["property_id"] == str(property_instance.id) - ].copy() for prefix in [ - "sap_change", "heat_demand", "carbon_change", "lighting_cost", "heating_cost", "hot_water_cost" - ] + ].copy() for prefix in ["sap_change", "heat_demand", "carbon_change"] } - # We apply adjustments to each of the heating costs - for prefix in ["lighting_cost", "heating_cost", "hot_water_cost"]: - property_predictions[f"{prefix}_predictions"]["adjusted_cost"] = ( - property_predictions[f"{prefix}_predictions"]["predictions"].apply( - lambda x: AnnualBillSavings.adjust_energy_to_metered( - x, current_epc_rating=property_instance.data["current-energy-rating"] - ) - ) - ) - property_recommendations = recommendations[property_instance.id].copy() - # TODO: should fabric upgrades have an impact on hot water costs/kwh? - # TODO: Generally, the costing models are just increasing. Maybe they're including something in the model - # that they shouldn't e.g. SAP, carbon, heat demand etc? + increasing_variables = ["sap"] + decreasing_variables = ["carbon", "heat_demand"] impact_summary = [] for recommendations_by_type in property_recommendations: @@ -414,14 +401,6 @@ class Recommendations: )]["predictions"].values[0] for prefix in ["sap_change", "heat_demand", "carbon_change"] } - # For phase costs, we need adusted and unadjusted values - phase_cost = { - prefix: property_predictions[prefix + "_predictions"][ - property_predictions[prefix + "_predictions"]["recommendation_id"] == - str(rec["recommendation_id"]) - ] for prefix in ["lighting_cost", "heating_cost", "hot_water_cost"] - } - # We structure this so that depending on the phase, we capture the previous phase impacts and # then just have one piece of code to calculate the difference if rec["phase"] == 0: @@ -433,9 +412,6 @@ class Recommendations: "sap": float(property_instance.data["current-energy-efficiency"]), "carbon": float(property_instance.data["co2-emissions-current"]), "heat_demand": float(property_instance.data["energy-consumption-current"]), - "epc_heating_cost": float(property_instance.data["heating-cost-current"]), - "epc_hot_water_cost": float(property_instance.data["hot-water-cost-current"]), - "epc_lighting_cost": float(property_instance.data["lighting-cost-current"]) } else: @@ -463,26 +439,6 @@ class Recommendations: "heat_demand": phase_energy_efficiency_metrics["heat_demand"], } - static_cost_variables = ( - ["epc_heating_cost", "epc_hot_water_cost"] if - rec["type"] == "low_energy_lighting" else ["epc_lighting_cost"] - ) - dynamic_cost_variables = [ - v for v in ["epc_heating_cost", "epc_hot_water_cost", "epc_lighting_cost"] - if v not in static_cost_variables - ] - # Take the static variables from the previous phase - current_phase_costs = {k: v for k, v in previous_phase_values.items() if k in static_cost_variables} - # Insert the dynamic variables from the current phase - for v in dynamic_cost_variables: - current_phase_costs[v] = phase_cost[v.split("epc_")[1]]["adjusted_cost"].values[0] - - current_phase_values.update(current_phase_costs) - - increasing_variables = ["sap"] - decreasing_variables = [ - "carbon", "heat_demand", "epc_heating_cost", "epc_hot_water_cost", "epc_lighting_cost" - ] # For increasing variables, the new value needs to be higher than the previous, otherwise we set it to # the previous # For decreasing variables, the new value should be lower than the previous, otherwise we set it to @@ -507,21 +463,6 @@ class Recommendations: "carbon": previous_phase_values["carbon"] - current_phase_values["carbon"], # Decreasing "heat_demand": previous_phase_values["heat_demand"] - current_phase_values["heat_demand"], - # Decreasing - "epc_heating_cost": ( - previous_phase_values["epc_heating_cost"] - - current_phase_values["epc_heating_cost"] - ), - # Decreasing - "epc_hot_water_cost": ( - previous_phase_values["epc_hot_water_cost"] - - current_phase_values["epc_hot_water_cost"] - ), - # Decreasing - "epc_lighting_cost": ( - previous_phase_values["epc_lighting_cost"] - - current_phase_values["epc_lighting_cost"] - ) } # Prevent from being negative