diff --git a/.idea/Model.iml b/.idea/Model.iml
index ac61a988..81384fa9 100644
--- a/.idea/Model.iml
+++ b/.idea/Model.iml
@@ -6,7 +6,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 242c02bb..3b05c6ac 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py
index dbc01935..4a68e7a7 100644
--- a/backend/app/plan/router.py
+++ b/backend/app/plan/router.py
@@ -102,18 +102,52 @@ async def trigger_plan(body: PlanTriggerRequest):
logger.info("Getting components and properties recommendations")
- for p in input_properties:
+ recommendations = []
+ for property_id, p in enumerate(input_properties):
# For each property, classiy floor area decide
total_floor_area_group_decile = classify_decile_newvalues(
decile_boundaries=floors_decile_data["decile_boundaries"],
decile_labels=floors_decile_data["decile_labels"],
new_values=[float(p.data["total-floor-area"])],
)[0]
- print("hey")
- print(total_floor_area_group_decile)
- for p in input_properties:
+ # Property recommendations
p.get_components(cleaned)
- # floor_recommendations = FloorRecommendations(property_instance=p, uvalue_estimates=uvalue_estimates_floors)
+
+ # Floor recommendations
+ floor_recommender = FloorRecommendations(property_instance=p, uvalue_estimates=uvalue_estimates_floors)
+ floor_recommender.recommend()
+ floor_recommendations = floor_recommender.recommendations
+ # insert property id
+ for rec in floor_recommendations:
+ rec["property_id"] = property_id
+
+ # Wall recommendations
+ # We would make this u-value query directly to the database
+ total_floor_area_group_decile = classify_decile_newvalues(
+ decile_boundaries=walls_decile_data["decile_boundaries"],
+ decile_labels=walls_decile_data["decile_labels"],
+ new_values=[float(p.data["total-floor-area"])],
+ )[0]
+
+ # This
+ walls_u_value_estimate = [
+ x for x in uvalue_estimates_walls
+ if (x['local-authority'] == p.data["local-authority"]) &
+ (x['property-type'] == p.data["property-type"]) &
+ (x['built-form'] == p.data["built-form"]) &
+ (x['walls-energy-eff'] == p.data["walls-energy-eff"]) &
+ (x['walls-env-eff'] == p.data["walls-env-eff"]) &
+ (x['total-floor-area_group'] == total_floor_area_group_decile)
+ ]
+
+ wall_recomendations = WallRecommendations(property_instance=p, uvalue_estimates=walls_u_value_estimate)
+ wall_recomendations.recommend()
+ wall_recomendations = wall_recomendations.recommendations
+ # insert property id
+ for rec in wall_recomendations:
+ rec["property_id"] = property_id
+
+ recommendations.extend(floor_recommendations)
return {"message": "Plan complete"}
diff --git a/model_data/app.py b/model_data/app.py
index fd97ddb8..74fa5c15 100644
--- a/model_data/app.py
+++ b/model_data/app.py
@@ -341,20 +341,20 @@ def app():
)
# Production of sample data for land registry
- address_meta = [
- {
- "postcode": x["postcode"].upper(),
- "address1": x["address1"].upper(),
- "address2": x["address2"].upper(),
- "address3": x["address3"].upper(),
- "address": x["address"],
- "uprn": x["uprn"]
- } for x in data
- ]
-
- import pickle
- with open("sample_addresses.pkl", "wb") as f:
- pickle.dump(address_meta, f)
+ # address_meta = [
+ # {
+ # "postcode": x["postcode"].upper(),
+ # "address1": x["address1"].upper(),
+ # "address2": x["address2"].upper(),
+ # "address3": x["address3"].upper(),
+ # "address": x["address"],
+ # "uprn": x["uprn"]
+ # } for x in data
+ # ]
+ #
+ # import pickle
+ # with open("sample_addresses.pkl", "wb") as f:
+ # pickle.dump(address_meta, f)
# Incorporate input data into cleaning
cleaner = EpcClean(data)
diff --git a/recommendations/FloorRecommendations.py b/recommendations/FloorRecommendations.py
index acbc0ddf..6641bd28 100644
--- a/recommendations/FloorRecommendations.py
+++ b/recommendations/FloorRecommendations.py
@@ -88,7 +88,9 @@ class FloorRecommendations(BaseUtility):
"Ground": 0,
# We don't know what floor level, we just make sure it's not 0
"mid floor": 1,
- "4th": 4
+ "4th": 4,
+ # We set
+ "00": 0,
}
def __init__(self, property_instance: Property, uvalue_estimates):
@@ -253,7 +255,7 @@ class FloorRecommendations(BaseUtility):
self.recommend_floor_insulation(u_value=u_value, parts=solid_floor_insulation_parts)
def _get_floors_uvalue_estimate(self, total_floor_area_group_decile):
-
+ blah
"""
Wrapper function which contains the methodology to extract a property's walls u-value estimate
when we don't have a true value and if we can't base our assumption off of the material
diff --git a/recommendations/WallRecommendations.py b/recommendations/WallRecommendations.py
index be618433..572bdf92 100644
--- a/recommendations/WallRecommendations.py
+++ b/recommendations/WallRecommendations.py
@@ -1,5 +1,6 @@
import itertools
import math
+from statistics import mean
from model_data.Property import Property
from model_data.BaseUtility import BaseUtility
@@ -321,10 +322,12 @@ class WallRecommendations(BaseUtility):
if new_u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
lowest_selected_u_value = update_lowest_selected_u_value(lowest_selected_u_value, new_u_value)
- recommendations.append({
- "parts": [get_recommended_part(part, depth)],
- "new_u_value": new_u_value,
- })
+ recommendations.append(
+ {
+ "parts": [get_recommended_part(part, depth)],
+ "new_u_value": new_u_value,
+ }
+ )
return recommendations
@@ -405,46 +408,39 @@ class WallRecommendations(BaseUtility):
:return:
"""
- total_floor_area_group_decile = self.uvalue_estimates.classify_decile_newvalues(
- decile_boundaries=self.uvalue_estimates.walls_decile_data["decile_boundaries"],
- decile_labels=self.uvalue_estimates.walls_decile_data["decile_labels"],
- new_values=[float(self.property.data["total-floor-area"])],
- )[0]
-
- u_value_estimate = self.uvalue_estimates.walls[
- (self.uvalue_estimates.walls["local-authority"] == self.property.data["local-authority"]) &
- (self.uvalue_estimates.walls["property-type"] == self.property.data["property-type"]) &
- (self.uvalue_estimates.walls["built-form"] == self.property.data["built-form"]) &
- (self.uvalue_estimates.walls["walls-energy-eff"] == self.property.data["walls-energy-eff"]) &
- (self.uvalue_estimates.walls["walls-env-eff"] == self.property.data["walls-env-eff"]) &
- (self.uvalue_estimates.walls["total-floor-area_group"] == total_floor_area_group_decile)
- ]
-
- if u_value_estimate.empty:
+ if not self.uvalue_estimates:
raise ValueError("No U-value estimate found for the given property")
# Because of how spuriously populated the data is for number-habitable-rooms and number-heated-rooms,
# we will try and filter on these to see if we get a result
- habitable_rooms_filter = (
- self.uvalue_estimates.walls["number-habitable-rooms"] == self.property.data["number-habitable-rooms"]
+ habitable_rooms_filer = [
+ x for x in self.uvalue_estimates if
+ x["number-habitable-rooms"] == self.property.data["number-habitable-rooms"]
+ ]
+
+ if not habitable_rooms_filer:
+ # Take a mean of all the u-value estimates
+ return mean(
+ [x["median_thermal_transmittance"] for x in self.uvalue_estimates if x["median_thermal_transmittance"]]
+ )
+
+ # Try perform a filter on heated rooms
+ heated_rooms_filter = [
+ x for x in habitable_rooms_filer if
+ x["number-heated-rooms"] == self.property.data["number-heated-rooms"]
+ ]
+
+ if not heated_rooms_filter:
+ # Take a mean of all the u-value estimates
+ return mean(
+ [x["median_thermal_transmittance"] for x in habitable_rooms_filer if x["median_thermal_transmittance"]]
+ )
+
+ return mean(
+ [x["median_thermal_transmittance"] for x in heated_rooms_filter if x["median_thermal_transmittance"]]
)
- if any(habitable_rooms_filter):
- u_value_estimate = u_value_estimate[habitable_rooms_filter]
-
- heated_rooms_filter = (
- self.uvalue_estimates.walls["number-heated-rooms"] == self.property.data["number-heated-rooms"]
- )
-
- if any(heated_rooms_filter):
- u_value_estimate = u_value_estimate[heated_rooms_filter]
-
- # It's possible for us to have multiple rows if we didn't do a habitable/heated rooms filter so we
- # average
-
- return u_value_estimate["median_thermal_transmittance"].mean()
-
@staticmethod
def rvalue_per_mm(total_r_value: float, thickness_mm: float) -> float:
"""Return R-value per mm.