diff --git a/backend/Property.py b/backend/Property.py index 7db64773..86b48e07 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -154,18 +154,19 @@ class Property(Definitions): """ self.recommendations_scoring_data = [] + for recommendations_by_type in property_recommendations: for i, rec in enumerate(recommendations_by_type): + recommendation_record = self.base_difference_record.df.to_dict("records")[0].copy() scoring_dict = self.create_recommendation_scoring_data( - recommendation=rec, + recommendation_record=recommendation_record, recommendation=rec, ) scoring_dict['id'] = "+".join([str(self.id), str(rec["recommendation_id"])]) self.recommendations_scoring_data.append(scoring_dict) - def create_recommendation_scoring_data(self, recommendation: dict): - - recommendation_record = self.base_difference_record.df.to_dict("records")[0].copy() + @staticmethod + def create_recommendation_scoring_data(recommendation_record, recommendation: dict): for col in [ "walls_insulation_thickness", "floor_insulation_thickness", "roof_insulation_thickness" @@ -511,6 +512,9 @@ class Property(Definitions): :return: """ + # TODO: These functions should work on an EPCRecord object, so that the format is more standardised. + # They could also be added as attributes to the EPC Record + self.perimeter = estimate_perimeter( self.floor_area / self.number_of_floors, self.number_of_rooms / self.number_of_floors ) diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index a3732856..324feed9 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -136,7 +136,6 @@ async def trigger_plan(body: PlanTriggerRequest): recommendations = {} recommendations_scoring_data = [] - property_scoring_data = {} for p in input_properties: @@ -164,6 +163,7 @@ async def trigger_plan(body: PlanTriggerRequest): ) model_api = ModelApi(portfolio_id=body.portfolio_id, timestamp=created_at) + all_predictions = model_api.predict_all( df=recommendations_scoring_data, bucket=get_settings().DATA_BUCKET, @@ -278,25 +278,19 @@ async def trigger_plan(body: PlanTriggerRequest): property_instance = [p for p in input_properties if p.id == property_id][0] - property_scoring_datasets = property_scoring_data[property_id] - starting_epc_data = property_scoring_datasets["starting_epc_data"].copy() - ending_epc_data = property_scoring_datasets["ending_epc_data"].copy() - fixed_data = property_scoring_datasets["fixed_data"].copy() + recommendation_record = property_instance.base_difference_record.df.to_dict("records")[0].copy() scoring_dict = {} for rec in default_recommendations: - scoring_dict = create_recommendation_scoring_data( - property=property_instance, - recommendation=rec, - starting_epc_data=starting_epc_data, - ending_epc_data=ending_epc_data, - fixed_data=fixed_data, + scoring_dict = Property.create_recommendation_scoring_data( + recommendation_record=recommendation_record, + recommendation=rec ) - # At each iteration, we want to update the ending_epc_data, so in the end, ending_epc_data contains - # all of the updates + # At each iterations, we update the recommendation record with the changes reflectecd in the + # scoring_dict for k in scoring_dict.keys(): - if k in ending_epc_data.columns: - ending_epc_data[k] = scoring_dict[k] + if k in recommendation_record.keys(): + recommendation_record[k] = scoring_dict[k] combined_recommendations_scoring_data.append(scoring_dict) diff --git a/backend/app/plan/utils.py b/backend/app/plan/utils.py index 7672c316..e20e93ce 100644 --- a/backend/app/plan/utils.py +++ b/backend/app/plan/utils.py @@ -39,6 +39,8 @@ def create_recommendation_scoring_data( :return: """ + # TODO: This needs to be complete depracated + scoring_dict = { "UPRN": property.data["uprn"], "id": "+".join([str(property.id), str(recommendation["recommendation_id"])]), @@ -90,33 +92,33 @@ def create_recommendation_scoring_data( if recommendation["type"] in ["internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation"]: # The upgrade made here is to the u-value of the walls and the description of the # insulation thickness - scoring_dict["walls_thermal_transmittance_ENDING"] = recommendation["new_u_value"] - scoring_dict["walls_insulation_thickness_ENDING"] = "above average" - scoring_dict["WALLS_ENERGY_EFF_ENDING"] = "Good" + scoring_dict["walls_thermal_transmittance_ending"] = recommendation["new_u_value"] + scoring_dict["walls_insulation_thickness_ending"] = "above average" + scoring_dict["walls_energy_eff_ending"] = "Good" else: - if scoring_dict["walls_thermal_transmittance_ENDING"] is None: - scoring_dict["walls_thermal_transmittance_ENDING"] = get_wall_u_value( + if scoring_dict["walls_thermal_transmittance_ending"] is None: + scoring_dict["walls_thermal_transmittance_ending"] = get_wall_u_value( clean_description=property.walls["clean_description"], age_band=property.age_band, is_granite_or_whinstone=property.walls["is_granite_or_whinstone"], is_sandstone_or_limestone=property.walls["is_sandstone_or_limestone"] ) - if scoring_dict["walls_insulation_thickness_ENDING"] is None: - scoring_dict["walls_insulation_thickness_ENDING"] = "none" + if scoring_dict["walls_insulation_thickness_ending"] is None: + scoring_dict["walls_insulation_thickness_ending"] = "none" # Update description to indicate it's insulate if recommendation["type"] in ["solid_floor_insulation", "suspended_floor_insulation", "exposed_floor_insulation"]: if len(recommendation["parts"]) > 1: raise NotImplementedError("Have more than 1 floor insulation part - handle this case") - scoring_dict["floor_thermal_transmittance_ENDING"] = recommendation["new_u_value"] + scoring_dict["floor_thermal_transmittance_ending"] = recommendation["new_u_value"] # We don't really see above average for this in the training data - scoring_dict["floor_insulation_thickness_ENDING"] = "average" - scoring_dict["FLOOR_ENERGY_EFF_ENDING"] = "Good" + scoring_dict["floor_insulation_thickness_ending"] = "average" + scoring_dict["floor_energy_eff_ending"] = "Good" else: - if scoring_dict["floor_thermal_transmittance_ENDING"] is None: - scoring_dict["floor_thermal_transmittance_ENDING"] = get_floor_u_value( + if scoring_dict["floor_thermal_transmittance_ending"] is None: + scoring_dict["floor_thermal_transmittance_ending"] = get_floor_u_value( floor_type=property.floor_type, area=property.floor_area, perimeter=property.perimeter, diff --git a/etl/epc/Dataset.py b/etl/epc/Dataset.py index 82272be1..fbc7a2d2 100644 --- a/etl/epc/Dataset.py +++ b/etl/epc/Dataset.py @@ -149,13 +149,13 @@ class TrainingDataset(BaseDataset): if pd.isnull(uvalue): insulation_col_name = "floor_insulation_thickness" if not is_end else "floor_insulation_thickness_ending" - floor_area_col_name = "estimated_perimeter_starting" if not is_end else "estimated_perimeter_ending" - perimeter_col_name = "total_floor_area_starting" if not is_end else "total_floor_area_ending" + perimeter_col_name = "estimated_perimeter_starting" if not is_end else "estimated_perimeter_ending" + floor_area_col_name = "ground_floor_area_starting" if not is_end else "ground_floor_area_ending" uvalue = get_floor_u_value( floor_type=row["floor_type"], - perimeter=row[floor_area_col_name], - area=row[perimeter_col_name], + perimeter=row[perimeter_col_name], + area=row[floor_area_col_name], insulation_thickness=row[insulation_col_name], wall_type=row["wall_type"], age_band=england_wales_age_band_lookup[row["construction_age_band"]] @@ -212,13 +212,23 @@ class TrainingDataset(BaseDataset): axis=1 ) + self.df["ground_floor_area_starting"] = ( + self.df["total_floor_area_starting"] / self.df['estimated_number_of_floors'] + ) + self.df["ground_floor_area_ending"] = ( + self.df["total_floor_area_ending"] / self.df['estimated_number_of_floors'] + ) + self.df['estimated_perimeter_starting'] = self.df.apply( - lambda row: estimate_perimeter(row["total_floor_area_starting"] / row['estimated_number_of_floors'], - row["number_habitable_rooms"] / row['estimated_number_of_floors']), + lambda row: estimate_perimeter( + row["ground_floor_area_starting"], row["number_habitable_rooms"] / row['estimated_number_of_floors'] + ), axis=1 ) self.df['estimated_perimeter_ending'] = self.df.apply( - lambda row: estimate_perimeter(row["total_floor_area_ending"], row["number_habitable_rooms"]), + lambda row: estimate_perimeter( + row["ground_floor_area_starting"], row["number_habitable_rooms"] / row['estimated_number_of_floors'] + ), axis=1 ) self.df["floor_type"] = self.df["is_suspended"].replace({True: "suspended", False: "solid"}) @@ -256,7 +266,7 @@ class TrainingDataset(BaseDataset): self.df = self.df.drop( columns=["floor_type", "wall_type", "walls_clean_description", "walls_clean_description_ending", - 'estimated_number_of_floors']) + 'estimated_number_of_floors', "ground_floor_area_starting", "ground_floor_area_ending"]) def _adjust_assumed_values_in_wall_descriptions(self): """