mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Merge pull request #247 from Hestia-Homes/wall-recommendations
Wall recommendations
This commit is contained in:
commit
b938285009
7 changed files with 267 additions and 127 deletions
|
|
@ -122,6 +122,12 @@ async def trigger_plan(body: PlanTriggerRequest):
|
||||||
# import pickle
|
# import pickle
|
||||||
# with open("input_properties.pickle", "rb") as f:
|
# with open("input_properties.pickle", "rb") as f:
|
||||||
# input_properties = pickle.load(f)
|
# input_properties = pickle.load(f)
|
||||||
|
#
|
||||||
|
# with open("cleaned.pickle", "rb") as f:
|
||||||
|
# cleaned = pickle.load(f)
|
||||||
|
#
|
||||||
|
# with open("materials_by_type.pickle", "wb") as f:
|
||||||
|
# materials_by_type = pickle.load(f)
|
||||||
|
|
||||||
recommendations = {}
|
recommendations = {}
|
||||||
recommendations_scoring_data = []
|
recommendations_scoring_data = []
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ def create_recommendation_scoring_data(
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set staring u-values if we don't have them
|
# Set staring u-values if we don't have them
|
||||||
if not scoring_dict["walls_thermal_transmittance"]:
|
if scoring_dict["walls_thermal_transmittance"] is None:
|
||||||
scoring_dict["walls_thermal_transmittance"] = get_wall_u_value(
|
scoring_dict["walls_thermal_transmittance"] = get_wall_u_value(
|
||||||
clean_description=property.walls["clean_description"],
|
clean_description=property.walls["clean_description"],
|
||||||
age_band=property.age_band,
|
age_band=property.age_band,
|
||||||
|
|
@ -94,7 +94,7 @@ def create_recommendation_scoring_data(
|
||||||
is_sandstone_or_limestone=property.walls["is_sandstone_or_limestone"]
|
is_sandstone_or_limestone=property.walls["is_sandstone_or_limestone"]
|
||||||
)
|
)
|
||||||
|
|
||||||
if not scoring_dict["floor_thermal_transmittance"]:
|
if scoring_dict["floor_thermal_transmittance"] is None:
|
||||||
scoring_dict["floor_thermal_transmittance"] = get_floor_u_value(
|
scoring_dict["floor_thermal_transmittance"] = get_floor_u_value(
|
||||||
floor_type=property.floor_type,
|
floor_type=property.floor_type,
|
||||||
area=property.floor_area,
|
area=property.floor_area,
|
||||||
|
|
@ -104,7 +104,7 @@ def create_recommendation_scoring_data(
|
||||||
age_band=property.age_band,
|
age_band=property.age_band,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not scoring_dict["roof_thermal_transmittance"]:
|
if scoring_dict["roof_thermal_transmittance"] is None:
|
||||||
scoring_dict["roof_thermal_transmittance"] = get_roof_u_value(
|
scoring_dict["roof_thermal_transmittance"] = get_roof_u_value(
|
||||||
insulation_thickness=property.roof["insulation_thickness"],
|
insulation_thickness=property.roof["insulation_thickness"],
|
||||||
has_dwelling_above=property.roof["has_dwelling_above"],
|
has_dwelling_above=property.roof["has_dwelling_above"],
|
||||||
|
|
@ -130,7 +130,7 @@ def create_recommendation_scoring_data(
|
||||||
scoring_dict["walls_thermal_transmittance_ENDING"] = recommendation["new_u_value"]
|
scoring_dict["walls_thermal_transmittance_ENDING"] = recommendation["new_u_value"]
|
||||||
scoring_dict["walls_insulation_thickness_ENDING"] = "above average"
|
scoring_dict["walls_insulation_thickness_ENDING"] = "above average"
|
||||||
else:
|
else:
|
||||||
if not scoring_dict["walls_thermal_transmittance_ENDING"]:
|
if scoring_dict["walls_thermal_transmittance_ENDING"] is None:
|
||||||
scoring_dict["walls_thermal_transmittance_ENDING"] = get_wall_u_value(
|
scoring_dict["walls_thermal_transmittance_ENDING"] = get_wall_u_value(
|
||||||
clean_description=property.walls["clean_description"],
|
clean_description=property.walls["clean_description"],
|
||||||
age_band=property.age_band,
|
age_band=property.age_band,
|
||||||
|
|
@ -151,7 +151,7 @@ def create_recommendation_scoring_data(
|
||||||
# We don't really see above average for this in the training data
|
# We don't really see above average for this in the training data
|
||||||
scoring_dict["floor_insulation_thickness_ENDING"] = "average"
|
scoring_dict["floor_insulation_thickness_ENDING"] = "average"
|
||||||
else:
|
else:
|
||||||
if not scoring_dict["floor_thermal_transmittance_ENDING"]:
|
if scoring_dict["floor_thermal_transmittance_ENDING"] is None:
|
||||||
scoring_dict["floor_thermal_transmittance_ENDING"] = get_floor_u_value(
|
scoring_dict["floor_thermal_transmittance_ENDING"] = get_floor_u_value(
|
||||||
floor_type=property.floor_type,
|
floor_type=property.floor_type,
|
||||||
area=property.floor_area,
|
area=property.floor_area,
|
||||||
|
|
@ -167,7 +167,7 @@ def create_recommendation_scoring_data(
|
||||||
if recommendation["type"] not in ["wall_insulation", "floor_insulation"]:
|
if recommendation["type"] not in ["wall_insulation", "floor_insulation"]:
|
||||||
raise NotImplementedError("Implement me")
|
raise NotImplementedError("Implement me")
|
||||||
|
|
||||||
if not scoring_dict["roof_thermal_transmittance_ENDING"]:
|
if scoring_dict["roof_thermal_transmittance_ENDING"] is None:
|
||||||
scoring_dict["roof_thermal_transmittance_ENDING"] = get_roof_u_value(
|
scoring_dict["roof_thermal_transmittance_ENDING"] = get_roof_u_value(
|
||||||
insulation_thickness=property.roof["insulation_thickness"],
|
insulation_thickness=property.roof["insulation_thickness"],
|
||||||
has_dwelling_above=property.roof["has_dwelling_above"],
|
has_dwelling_above=property.roof["has_dwelling_above"],
|
||||||
|
|
@ -180,7 +180,7 @@ def create_recommendation_scoring_data(
|
||||||
is_at_rafters=property.roof["is_at_rafters"],
|
is_at_rafters=property.roof["is_at_rafters"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if scoring_dict["roof_insulation_thickness_ENDING"] is None:
|
if scoring_dict["roof_insulation_thickness_ENDING"] is None:
|
||||||
scoring_dict["roof_insulation_thickness_ENDING"] = "none"
|
scoring_dict["roof_insulation_thickness_ENDING"] = "none"
|
||||||
|
|
||||||
return scoring_dict
|
return scoring_dict
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
from backend.Property import Property
|
from backend.Property import Property
|
||||||
from etl.epc.DataProcessor import DataProcessor
|
from etl.epc.DataProcessor import DataProcessor
|
||||||
from backend.app.plan.utils import create_recommendation_scoring_data
|
from backend.app.plan.utils import create_recommendation_scoring_data, get_cleaned
|
||||||
from etl.epc.settings import COLUMNS_TO_MERGE_ON
|
from etl.epc.settings import COLUMNS_TO_MERGE_ON
|
||||||
from epc_api.client import EpcClient
|
from epc_api.client import EpcClient
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import os
|
|
||||||
import pytest
|
import pytest
|
||||||
import pickle
|
|
||||||
|
from utils.s3 import read_dataframe_from_s3_parquet
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
|
# import pickle
|
||||||
# with open("sap_change_dataset.pickle", "rb") as f:
|
# with open("sap_change_dataset.pickle", "rb") as f:
|
||||||
# sap_change_dataset = pickle.load(f)
|
# sap_change_dataset = pickle.load(f)
|
||||||
#
|
#
|
||||||
|
|
@ -109,18 +110,14 @@ from tqdm import tqdm
|
||||||
class TestSapModelPrep:
|
class TestSapModelPrep:
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def cleaned(self):
|
def cleaning_data(self):
|
||||||
with open(
|
return read_dataframe_from_s3_parquet(
|
||||||
os.path.abspath(os.path.dirname(__file__)) + "/test_data/cleaned.pickle", "rb"
|
bucket_name="retrofit-data-dev", file_key="sap_change_model/cleaning_dataset.parquet",
|
||||||
) as f:
|
)
|
||||||
return pickle.load(f)
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def cleaning_data(self):
|
def cleaned(self):
|
||||||
with open(
|
return get_cleaned()
|
||||||
os.path.abspath(os.path.dirname(__file__)) + "/test_data/cleaning_data.pickle", "rb"
|
|
||||||
) as f:
|
|
||||||
return pickle.load(f)
|
|
||||||
|
|
||||||
def test_fill_cavity_wall(self, cleaned, cleaning_data):
|
def test_fill_cavity_wall(self, cleaned, cleaning_data):
|
||||||
"""
|
"""
|
||||||
|
|
@ -395,7 +392,7 @@ class TestSapModelPrep:
|
||||||
'MULTI_GLAZE_PROPORTION_ENDING': 61.0, 'LOW_ENERGY_LIGHTING_ENDING': 17.0,
|
'MULTI_GLAZE_PROPORTION_ENDING': 61.0, 'LOW_ENERGY_LIGHTING_ENDING': 17.0,
|
||||||
'NUMBER_OPEN_FIREPLACES_ENDING': 0.0, 'EXTENSION_COUNT_ENDING': 0.0, 'TOTAL_FLOOR_AREA_ENDING': 70.0,
|
'NUMBER_OPEN_FIREPLACES_ENDING': 0.0, 'EXTENSION_COUNT_ENDING': 0.0, 'TOTAL_FLOOR_AREA_ENDING': 70.0,
|
||||||
'FLOOR_HEIGHT_ENDING': 3.64, 'DAYS_TO_STARTING': 2266, 'DAYS_TO_ENDING': 2307,
|
'FLOOR_HEIGHT_ENDING': 3.64, 'DAYS_TO_STARTING': 2266, 'DAYS_TO_ENDING': 2307,
|
||||||
'walls_thermal_transmittance': 0.45, 'is_cavity_wall': False, 'is_filled_cavity': False,
|
'walls_thermal_transmittance': 1.7, 'is_cavity_wall': False, 'is_filled_cavity': False,
|
||||||
'is_solid_brick': True, 'is_system_built': False, 'is_timber_frame': False,
|
'is_solid_brick': True, 'is_system_built': False, 'is_timber_frame': False,
|
||||||
'is_granite_or_whinstone': False, 'is_as_built': True, 'is_cob': False,
|
'is_granite_or_whinstone': False, 'is_as_built': True, 'is_cob': False,
|
||||||
'is_sandstone_or_limestone': False, 'is_park_home': False, 'walls_insulation_thickness': 'none',
|
'is_sandstone_or_limestone': False, 'is_park_home': False, 'walls_insulation_thickness': 'none',
|
||||||
|
|
@ -482,7 +479,7 @@ class TestSapModelPrep:
|
||||||
|
|
||||||
ending_lodgement_date2 = '2020-11-24'
|
ending_lodgement_date2 = '2020-11-24'
|
||||||
|
|
||||||
starting_epc_data2["DAYS_TO_ENDING"] = data_processor2.calculate_days_to(ending_lodgement_date2)
|
ending_epc_data2["DAYS_TO_ENDING"] = data_processor2.calculate_days_to(ending_lodgement_date2)
|
||||||
|
|
||||||
recommendation2 = {
|
recommendation2 = {
|
||||||
"recommendation_id": 0,
|
"recommendation_id": 0,
|
||||||
|
|
|
||||||
|
|
@ -112,15 +112,6 @@ class WallRecommendations(Definitions):
|
||||||
|
|
||||||
self.estimated_u_value = u_value
|
self.estimated_u_value = u_value
|
||||||
|
|
||||||
if self.property.walls["is_solid_brick"]:
|
|
||||||
|
|
||||||
if u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
|
||||||
self.find_insulation(u_value)
|
|
||||||
return
|
|
||||||
|
|
||||||
# If the u-value is within regulations, we don't do anything
|
|
||||||
return
|
|
||||||
|
|
||||||
if is_cavity_wall:
|
if is_cavity_wall:
|
||||||
if u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
if u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
||||||
# Test filling cavity
|
# Test filling cavity
|
||||||
|
|
@ -128,9 +119,13 @@ class WallRecommendations(Definitions):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.error("Not implemented yet")
|
# Remaining wall types are treated with IWI or EWI
|
||||||
|
if u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
||||||
|
self.find_insulation(u_value)
|
||||||
|
return
|
||||||
|
|
||||||
|
# If the u-value is within regulations, we don't do anything
|
||||||
return
|
return
|
||||||
# NotImplementedError("Not implemented yet")
|
|
||||||
|
|
||||||
def find_cavity_insulation(self, u_value, insulation_thickness):
|
def find_cavity_insulation(self, u_value, insulation_thickness):
|
||||||
"""
|
"""
|
||||||
|
|
@ -273,63 +268,6 @@ class WallRecommendations(Definitions):
|
||||||
|
|
||||||
self.recommendations += ewi_recommendations + iwi_recommendations
|
self.recommendations += ewi_recommendations + iwi_recommendations
|
||||||
|
|
||||||
# We also can recommend both internal and external wall insulation together
|
|
||||||
# By looping through ewi first, if there is nothing there, that ensures not combinations are tested
|
|
||||||
for ewi_part in ewi_parts:
|
|
||||||
for iwi_part in iwi_parts:
|
|
||||||
for (ewi_depth, ewi_cost_per_unit), (iwi_depth, iwi_cost_per_unit) in itertools.product(
|
|
||||||
zip(ewi_part["depths"], ewi_part["cost"]),
|
|
||||||
zip(iwi_part["depths"], iwi_part["cost"])
|
|
||||||
):
|
|
||||||
ewi_part_u_value = r_value_per_mm_to_u_value(ewi_depth, ewi_part["r_value_per_mm"])
|
|
||||||
iwi_part_u_value = r_value_per_mm_to_u_value(iwi_depth, iwi_part["r_value_per_mm"])
|
|
||||||
|
|
||||||
# First calculate the new U-value after applying external wall insulation
|
|
||||||
_, ewi_new_u_value = calculate_u_value_uplift(u_value, ewi_part_u_value)
|
|
||||||
# Then calculate the new U-value after applying internal wall insulation
|
|
||||||
_, combined_new_u_value = calculate_u_value_uplift(ewi_new_u_value, iwi_part_u_value)
|
|
||||||
combined_new_u_value = round(combined_new_u_value, 2)
|
|
||||||
|
|
||||||
if combined_new_u_value < self.DIMINISHING_RETURNS_U_VALUE:
|
|
||||||
# We don't recommend an overkill solution
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Check if the combined new U-value meets the requirement
|
|
||||||
if combined_new_u_value - self.U_VALUE_ERROR <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
|
||||||
# Here you might want to define a way to add both recommendations together.
|
|
||||||
# For now, I'm adding them as separate items in the list
|
|
||||||
ewi_esimtated_cost = ewi_cost_per_unit * self.property.insulation_wall_area
|
|
||||||
iwi_esimtated_cost = iwi_cost_per_unit * self.property.insulation_wall_area
|
|
||||||
|
|
||||||
recommendation = {
|
|
||||||
"parts": [
|
|
||||||
get_recommended_part(
|
|
||||||
part=ewi_part,
|
|
||||||
selected_depth=ewi_depth,
|
|
||||||
quantity=self.property.insulation_wall_area,
|
|
||||||
quantity_unit=QuantityUnits.m2.value,
|
|
||||||
selected_total_cost=ewi_esimtated_cost
|
|
||||||
),
|
|
||||||
get_recommended_part(
|
|
||||||
part=iwi_part,
|
|
||||||
selected_depth=iwi_depth,
|
|
||||||
quantity=self.property.insulation_wall_area,
|
|
||||||
quantity_unit=QuantityUnits.m2.value,
|
|
||||||
selected_total_cost=iwi_esimtated_cost
|
|
||||||
)
|
|
||||||
],
|
|
||||||
"type": "wall_insulation",
|
|
||||||
"description": (
|
|
||||||
"Install " + self._make_description(ewi_part, ewi_depth) + " and " +
|
|
||||||
self._make_description(iwi_part, iwi_depth)
|
|
||||||
),
|
|
||||||
"starting_u_value": u_value,
|
|
||||||
"new_u_value": combined_new_u_value,
|
|
||||||
"sap_points": None,
|
|
||||||
"cost": ewi_esimtated_cost + iwi_esimtated_cost,
|
|
||||||
}
|
|
||||||
self.recommendations.append(recommendation)
|
|
||||||
|
|
||||||
self.prune_diminishing_recommendations()
|
self.prune_diminishing_recommendations()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,21 @@ wall_uvalue_test_cases = [
|
||||||
"age_band": "A",
|
"age_band": "A",
|
||||||
"is_granite_or_whinstone": False,
|
"is_granite_or_whinstone": False,
|
||||||
"is_sandstone_or_limestone": False,
|
"is_sandstone_or_limestone": False,
|
||||||
"uvalue": 0.7
|
"uvalue": 1.3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"clean_description": "Cavity wall, as built, partial insulation",
|
"clean_description": "Cavity wall, as built, partial insulation",
|
||||||
"age_band": "F",
|
"age_band": "F",
|
||||||
"is_granite_or_whinstone": False,
|
"is_granite_or_whinstone": False,
|
||||||
"is_sandstone_or_limestone": False,
|
"is_sandstone_or_limestone": False,
|
||||||
"uvalue": 0.4
|
"uvalue": 0.85
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"clean_description": "Cavity wall, as built, partial insulation",
|
"clean_description": "Cavity wall, as built, partial insulation",
|
||||||
"age_band": "F",
|
"age_band": "G",
|
||||||
"is_granite_or_whinstone": False,
|
"is_granite_or_whinstone": False,
|
||||||
"is_sandstone_or_limestone": False,
|
"is_sandstone_or_limestone": False,
|
||||||
"uvalue": 0.4
|
"uvalue": 0.5375
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ class TestFloorRecommendations:
|
||||||
input_properties[2].age_band = "A"
|
input_properties[2].age_band = "A"
|
||||||
input_properties[2].perimeter = 20
|
input_properties[2].perimeter = 20
|
||||||
input_properties[2].wall_type = "solid brick"
|
input_properties[2].wall_type = "solid brick"
|
||||||
|
input_properties[2].floor_type = "suspended"
|
||||||
|
|
||||||
recommender = FloorRecommendations(
|
recommender = FloorRecommendations(
|
||||||
property_instance=input_properties[2],
|
property_instance=input_properties[2],
|
||||||
|
|
@ -160,6 +161,7 @@ class TestFloorRecommendations:
|
||||||
input_properties[4].age_band = "B"
|
input_properties[4].age_band = "B"
|
||||||
input_properties[4].perimeter = 50
|
input_properties[4].perimeter = 50
|
||||||
input_properties[4].wall_type = "solid brick"
|
input_properties[4].wall_type = "solid brick"
|
||||||
|
input_properties[4].floor_type = "solid"
|
||||||
|
|
||||||
recommender = FloorRecommendations(
|
recommender = FloorRecommendations(
|
||||||
property_instance=input_properties[4],
|
property_instance=input_properties[4],
|
||||||
|
|
|
||||||
|
|
@ -407,36 +407,8 @@ class TestWallRecommendationsBase:
|
||||||
wall_recommendations_instance.property.data = {"property-type": "house"}
|
wall_recommendations_instance.property.data = {"property-type": "house"}
|
||||||
assert wall_recommendations_instance.ewi_valid is True
|
assert wall_recommendations_instance.ewi_valid is True
|
||||||
|
|
||||||
def test_recommend_without_u_value(self, wall_recommendations_instance):
|
|
||||||
wall_recommendations_instance.property.walls = {
|
|
||||||
"thermal_transmittance": None,
|
|
||||||
"is_solid_brick": False,
|
|
||||||
"is_cavity_wall": False,
|
|
||||||
"insulation_thickness": "none",
|
|
||||||
"clean_description": "Solid brick, as built, no insulation",
|
|
||||||
"is_granite_or_whinstone": False,
|
|
||||||
"is_sandstone_or_limestone": False,
|
|
||||||
}
|
|
||||||
wall_recommendations_instance.property.age_band = "A"
|
|
||||||
with pytest.raises(NotImplementedError):
|
|
||||||
wall_recommendations_instance.recommend()
|
|
||||||
|
|
||||||
|
|
||||||
class TestCavityWallRecommensations:
|
class TestCavityWallRecommensations:
|
||||||
data = {
|
|
||||||
'low-energy-fixed-light-count': '', 'address': '123 Fake Street',
|
|
||||||
'floor-height': '', 'construction-age-band': 'England and Wales: 1950-1966',
|
|
||||||
'address3': '', 'property-type': 'House', 'local-authority-label': 'Melton',
|
|
||||||
'county': 'Leicestershire', 'postcode': 'LE14 2QH',
|
|
||||||
'solar-water-heating-flag': 'N', 'constituency': 'E14000909',
|
|
||||||
'number-heated-rooms': '5', 'local-authority': 'E07000133', 'built-form': 'End-Terrace',
|
|
||||||
'address1': '1, 23 fake', 'total-floor-area': '85.0', 'environment-impact-current': '49',
|
|
||||||
'number-habitable-rooms': 3, 'address2': 'Fake', 'posttown': 'IDK',
|
|
||||||
'walls-energy-eff': 'Poor', 'current-energy-rating': 'D',
|
|
||||||
'transaction-type': 'ECO assessment', 'uprn': '999', 'current-energy-efficiency': '57',
|
|
||||||
'lodgement-date': '2019-07-10', 'lmk-key': '999', 'tenure': 'rental (private)', 'floor-level': 'NODATA!',
|
|
||||||
'walls-description': 'Cavity wall, as built, no insulation (assumed)',
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_fill_empty_cavity(self):
|
def test_fill_empty_cavity(self):
|
||||||
input_property = Property(id=1, postcode="F4k3", address1="123 fake street", epc_client=Mock())
|
input_property = Property(id=1, postcode="F4k3", address1="123 fake street", epc_client=Mock())
|
||||||
|
|
@ -465,10 +437,10 @@ class TestCavityWallRecommensations:
|
||||||
|
|
||||||
assert recommender.recommendations
|
assert recommender.recommendations
|
||||||
assert recommender.estimated_u_value == 1.5
|
assert recommender.estimated_u_value == 1.5
|
||||||
assert np.isclose(recommender.recommendations[0]["new_u_value"], 0.25)
|
assert np.isclose(recommender.recommendations[0]["new_u_value"], 0.37)
|
||||||
assert np.isclose(recommender.recommendations[0]["cost"], 1000)
|
assert np.isclose(recommender.recommendations[0]["cost"], 1000)
|
||||||
|
|
||||||
assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.26)
|
assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.38)
|
||||||
assert np.isclose(recommender.recommendations[1]["cost"], 1250)
|
assert np.isclose(recommender.recommendations[1]["cost"], 1250)
|
||||||
|
|
||||||
def test_fill_partial_filled_cavity(self):
|
def test_fill_partial_filled_cavity(self):
|
||||||
|
|
@ -498,8 +470,233 @@ class TestCavityWallRecommensations:
|
||||||
|
|
||||||
assert recommender.recommendations
|
assert recommender.recommendations
|
||||||
assert recommender.estimated_u_value == 1.3
|
assert recommender.estimated_u_value == 1.3
|
||||||
assert np.isclose(recommender.recommendations[0]["new_u_value"], 0.56)
|
assert np.isclose(recommender.recommendations[0]["new_u_value"], 0.43)
|
||||||
assert np.isclose(recommender.recommendations[0]["cost"], 1000)
|
assert np.isclose(recommender.recommendations[0]["cost"], 1000)
|
||||||
|
|
||||||
assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.57)
|
assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.45)
|
||||||
assert np.isclose(recommender.recommendations[1]["cost"], 1250)
|
assert np.isclose(recommender.recommendations[1]["cost"], 1250)
|
||||||
|
|
||||||
|
def test_system_built_wall(self):
|
||||||
|
input_property2 = Property(id=1, postcode="F4k3 2", address1="223 fake street", epc_client=Mock())
|
||||||
|
input_property2.walls = {
|
||||||
|
'original_description': 'System built, as built, no insulation (assumed)',
|
||||||
|
'clean_description': 'System built, as built, no insulation',
|
||||||
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
|
||||||
|
'is_cavity_wall': False, 'is_filled_cavity': False, 'is_solid_brick': False,
|
||||||
|
'is_system_built': True, 'is_timber_frame': False, 'is_granite_or_whinstone': False,
|
||||||
|
'is_as_built': True, 'is_cob': False, 'is_assumed': True,
|
||||||
|
'is_sandstone_or_limestone': False, 'is_park_home': False,
|
||||||
|
'insulation_thickness': 'none', 'external_insulation': False,
|
||||||
|
'internal_insulation': False
|
||||||
|
}
|
||||||
|
input_property2.age_band = "F"
|
||||||
|
input_property2.insulation_wall_area = 120
|
||||||
|
input_property2.restricted_measures = False
|
||||||
|
input_property2.data = {"property-type": "house"}
|
||||||
|
|
||||||
|
assert input_property2.walls["is_system_built"]
|
||||||
|
|
||||||
|
recommender2 = WallRecommendations(
|
||||||
|
property_instance=input_property2,
|
||||||
|
materials=internal_wall_insulation_parts + external_wall_insulation_parts
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not recommender2.recommendations
|
||||||
|
|
||||||
|
recommender2.recommend()
|
||||||
|
|
||||||
|
assert recommender2.recommendations
|
||||||
|
assert len(recommender2.recommendations) == 6
|
||||||
|
assert recommender2.estimated_u_value == 1
|
||||||
|
assert np.isclose(recommender2.recommendations[0]["new_u_value"], 0.29)
|
||||||
|
assert np.isclose(recommender2.recommendations[0]["cost"], 10800)
|
||||||
|
assert recommender2.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender2.recommendations[0]["parts"][0]["depths"] == [90]
|
||||||
|
|
||||||
|
assert np.isclose(recommender2.recommendations[5]["new_u_value"], 0.29)
|
||||||
|
assert np.isclose(recommender2.recommendations[5]["cost"], 2400)
|
||||||
|
assert recommender2.recommendations[5]["parts"][0]["type"] == "internal_wall_insulation"
|
||||||
|
assert recommender2.recommendations[5]["parts"][0]["depths"] == [20]
|
||||||
|
|
||||||
|
assert np.isclose(recommender2.recommendations[3]["new_u_value"], 0.28)
|
||||||
|
assert np.isclose(recommender2.recommendations[3]["cost"], 4800)
|
||||||
|
assert recommender2.recommendations[3]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender2.recommendations[3]["parts"][0]["depths"] == [40]
|
||||||
|
|
||||||
|
def test_timber_frame_wall(self):
|
||||||
|
input_property3 = Property(id=1, postcode="F4k3 2", address1="223 fake street", epc_client=Mock())
|
||||||
|
input_property3.walls = {
|
||||||
|
'original_description': 'Timber frame, as built, no insulation (assumed)',
|
||||||
|
'clean_description': 'Timber frame, as built, no insulation',
|
||||||
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
|
||||||
|
'is_cavity_wall': False, 'is_filled_cavity': False, 'is_solid_brick': False,
|
||||||
|
'is_system_built': False, 'is_timber_frame': True, 'is_granite_or_whinstone': False,
|
||||||
|
'is_as_built': True, 'is_cob': False, 'is_assumed': True,
|
||||||
|
'is_sandstone_or_limestone': False, 'is_park_home': False,
|
||||||
|
'insulation_thickness': 'none', 'external_insulation': False,
|
||||||
|
'internal_insulation': False
|
||||||
|
}
|
||||||
|
input_property3.age_band = "B"
|
||||||
|
input_property3.insulation_wall_area = 99
|
||||||
|
input_property3.restricted_measures = False
|
||||||
|
input_property3.data = {"property-type": "house"}
|
||||||
|
|
||||||
|
assert input_property3.walls["is_timber_frame"]
|
||||||
|
|
||||||
|
recommender3 = WallRecommendations(
|
||||||
|
property_instance=input_property3,
|
||||||
|
materials=internal_wall_insulation_parts + external_wall_insulation_parts
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not recommender3.recommendations
|
||||||
|
|
||||||
|
recommender3.recommend()
|
||||||
|
|
||||||
|
assert recommender3.recommendations
|
||||||
|
assert len(recommender3.recommendations) == 2
|
||||||
|
assert recommender3.estimated_u_value == 1.9
|
||||||
|
assert np.isclose(recommender3.recommendations[0]["new_u_value"], 0.26)
|
||||||
|
assert np.isclose(recommender3.recommendations[0]["cost"], 12375)
|
||||||
|
assert recommender3.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender3.recommendations[0]["parts"][0]["depths"] == [125]
|
||||||
|
|
||||||
|
assert np.isclose(recommender3.recommendations[1]["new_u_value"], 0.26)
|
||||||
|
assert np.isclose(recommender3.recommendations[1]["cost"], 4950)
|
||||||
|
assert recommender3.recommendations[1]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender3.recommendations[1]["parts"][0]["depths"] == [50]
|
||||||
|
|
||||||
|
def test_granite_or_whinstone_wall(self):
|
||||||
|
input_property4 = Property(id=1, postcode="F4k3 2", address1="223 fake street", epc_client=Mock())
|
||||||
|
input_property4.walls = {
|
||||||
|
'original_description': 'Granite or whinstone, as built, no insulation (assumed)',
|
||||||
|
'clean_description': 'Granite or whinstone, as built, no insulation',
|
||||||
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
|
||||||
|
'is_cavity_wall': False, 'is_filled_cavity': False, 'is_solid_brick': False,
|
||||||
|
'is_system_built': False, 'is_timber_frame': False, 'is_granite_or_whinstone': True,
|
||||||
|
'is_as_built': True, 'is_cob': False, 'is_assumed': True,
|
||||||
|
'is_sandstone_or_limestone': False, 'is_park_home': False,
|
||||||
|
'insulation_thickness': 'none', 'external_insulation': False,
|
||||||
|
'internal_insulation': False
|
||||||
|
}
|
||||||
|
input_property4.age_band = "A"
|
||||||
|
input_property4.insulation_wall_area = 223
|
||||||
|
input_property4.restricted_measures = False
|
||||||
|
input_property4.data = {"property-type": "Bungalow"}
|
||||||
|
|
||||||
|
assert input_property4.walls["is_granite_or_whinstone"]
|
||||||
|
|
||||||
|
recommender4 = WallRecommendations(
|
||||||
|
property_instance=input_property4,
|
||||||
|
materials=internal_wall_insulation_parts + external_wall_insulation_parts
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not recommender4.recommendations
|
||||||
|
|
||||||
|
recommender4.recommend()
|
||||||
|
|
||||||
|
assert recommender4.recommendations
|
||||||
|
assert len(recommender4.recommendations) == 2
|
||||||
|
assert recommender4.estimated_u_value == 2.3
|
||||||
|
assert np.isclose(recommender4.recommendations[0]["new_u_value"], 0.27)
|
||||||
|
assert np.isclose(recommender4.recommendations[0]["cost"], 27875)
|
||||||
|
assert recommender4.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender4.recommendations[0]["parts"][0]["depths"] == [125]
|
||||||
|
|
||||||
|
assert np.isclose(recommender4.recommendations[1]["new_u_value"], 0.27)
|
||||||
|
assert np.isclose(recommender4.recommendations[1]["cost"], 11150)
|
||||||
|
assert recommender4.recommendations[1]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender4.recommendations[1]["parts"][0]["depths"] == [50]
|
||||||
|
|
||||||
|
def test_cob_wall(self):
|
||||||
|
input_property5 = Property(id=1, postcode="F4k3 2", address1="223 fake street", epc_client=Mock())
|
||||||
|
input_property5.walls = {
|
||||||
|
'original_description': 'Cob, as built',
|
||||||
|
'clean_description': 'Cob, as built',
|
||||||
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
|
||||||
|
'is_cavity_wall': False, 'is_filled_cavity': False, 'is_solid_brick': False,
|
||||||
|
'is_system_built': False, 'is_timber_frame': False, 'is_granite_or_whinstone': False,
|
||||||
|
'is_as_built': False, 'is_cob': True, 'is_assumed': False,
|
||||||
|
'is_sandstone_or_limestone': False, 'is_park_home': False,
|
||||||
|
'insulation_thickness': 'none', 'external_insulation': False,
|
||||||
|
'internal_insulation': False
|
||||||
|
}
|
||||||
|
input_property5.age_band = "E"
|
||||||
|
input_property5.insulation_wall_area = 77
|
||||||
|
input_property5.restricted_measures = False
|
||||||
|
input_property5.data = {"property-type": "Bungalow"}
|
||||||
|
|
||||||
|
assert input_property5.walls["is_cob"]
|
||||||
|
|
||||||
|
recommender5 = WallRecommendations(
|
||||||
|
property_instance=input_property5,
|
||||||
|
materials=internal_wall_insulation_parts + external_wall_insulation_parts
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not recommender5.recommendations
|
||||||
|
|
||||||
|
recommender5.recommend()
|
||||||
|
|
||||||
|
assert recommender5.recommendations
|
||||||
|
assert len(recommender5.recommendations) == 9
|
||||||
|
assert recommender5.estimated_u_value == 0.8
|
||||||
|
assert np.isclose(recommender5.recommendations[0]["new_u_value"], 0.29)
|
||||||
|
assert np.isclose(recommender5.recommendations[0]["cost"], 6160)
|
||||||
|
assert recommender5.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender5.recommendations[0]["parts"][0]["depths"] == [80]
|
||||||
|
|
||||||
|
assert np.isclose(recommender5.recommendations[3]["new_u_value"], 0.26)
|
||||||
|
assert np.isclose(recommender5.recommendations[3]["cost"], 7700)
|
||||||
|
assert recommender5.recommendations[3]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender5.recommendations[3]["parts"][0]["depths"] == [100]
|
||||||
|
|
||||||
|
assert np.isclose(recommender5.recommendations[6]["new_u_value"], 0.26)
|
||||||
|
assert np.isclose(recommender5.recommendations[6]["cost"], 7700)
|
||||||
|
assert recommender5.recommendations[6]["parts"][0]["type"] == "internal_wall_insulation"
|
||||||
|
assert recommender5.recommendations[6]["parts"][0]["depths"] == [100]
|
||||||
|
|
||||||
|
def test_sandstone_or_limestone_wall(self):
|
||||||
|
input_property6 = Property(id=1, postcode="F4k3 6", address1="623 fake street", epc_client=Mock())
|
||||||
|
input_property6.walls = {
|
||||||
|
'original_description': 'Sandstone or limestone, as built, no insulation (assumed)',
|
||||||
|
'clean_description': 'Sandstone or limestone, as built, no insulation',
|
||||||
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
|
||||||
|
'is_cavity_wall': False, 'is_filled_cavity': False, 'is_solid_brick': False,
|
||||||
|
'is_system_built': False, 'is_timber_frame': False, 'is_granite_or_whinstone': False,
|
||||||
|
'is_as_built': False, 'is_cob': False, 'is_assumed': False,
|
||||||
|
'is_sandstone_or_limestone': True, 'is_park_home': False,
|
||||||
|
'insulation_thickness': 'none', 'external_insulation': False,
|
||||||
|
'internal_insulation': False
|
||||||
|
}
|
||||||
|
input_property6.age_band = "F"
|
||||||
|
input_property6.insulation_wall_area = 350
|
||||||
|
input_property6.restricted_measures = False
|
||||||
|
input_property6.data = {"property-type": "House"}
|
||||||
|
|
||||||
|
assert input_property6.walls["is_sandstone_or_limestone"]
|
||||||
|
|
||||||
|
recommender6 = WallRecommendations(
|
||||||
|
property_instance=input_property6,
|
||||||
|
materials=internal_wall_insulation_parts + external_wall_insulation_parts
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not recommender6.recommendations
|
||||||
|
|
||||||
|
recommender6.recommend()
|
||||||
|
|
||||||
|
assert recommender6.recommendations
|
||||||
|
assert len(recommender6.recommendations) == 6
|
||||||
|
assert recommender6.estimated_u_value == 1
|
||||||
|
assert np.isclose(recommender6.recommendations[0]["new_u_value"], 0.29)
|
||||||
|
assert np.isclose(recommender6.recommendations[0]["cost"], 31500)
|
||||||
|
assert recommender6.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender6.recommendations[0]["parts"][0]["depths"] == [90]
|
||||||
|
|
||||||
|
assert np.isclose(recommender6.recommendations[2]["new_u_value"], 0.28)
|
||||||
|
assert np.isclose(recommender6.recommendations[2]["cost"], 35000)
|
||||||
|
assert recommender6.recommendations[2]["parts"][0]["type"] == "external_wall_insulation"
|
||||||
|
assert recommender6.recommendations[2]["parts"][0]["depths"] == [100]
|
||||||
|
|
||||||
|
assert np.isclose(recommender6.recommendations[4]["new_u_value"], 0.28)
|
||||||
|
assert np.isclose(recommender6.recommendations[4]["cost"], 35000)
|
||||||
|
assert recommender6.recommendations[4]["parts"][0]["type"] == "internal_wall_insulation"
|
||||||
|
assert recommender6.recommendations[4]["parts"][0]["depths"] == [100]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue