fixed recommendations unit tests

This commit is contained in:
Khalim Conn-Kowlessar 2023-09-12 15:38:15 +01:00
parent df878007d2
commit 621696c732
3 changed files with 217 additions and 206 deletions

View file

@ -1,5 +1,6 @@
import itertools
import math
from typing import List
from datatypes.enums import QuantityUnits
from backend.Property import Property
@ -9,181 +10,6 @@ from recommendations.recommendation_utils import (
get_recommended_part, get_uvalue_estimate
)
external_wall_insulation_parts = [
{
# Example product
# https://insulationgo.co.uk/100mm-rockwool-external-wall-insulation-dual-density-slabs-a1-non-combustible
# -slab-ewi-render-fire/
"type": "external_wall_insulation",
"description": "Mineral Wool External Wall Insulation",
"depths": [30, 50, 70, 80, 90, 100, 150, 200],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.0278,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.036,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.insulationking.co.uk/products/polystyrene-eps70?variant=44156186558759
"type": "external_wall_insulation",
"description": "Expanded Polystyrene External Wall Insulation",
"depths": [25, 50, 100, 125],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.02703,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.037,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.insulationshop.co/20mm_kooltherm_k5_external_wall_kingspan.html
"type": "external_wall_insulation",
"description": "Phenolic Foam External Wall Insulation",
"depths": [20, 50, 100],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.043478260869565216,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.023,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
"type": "external_wall_insulation",
"description": "Polyisocyanurate/Polyurethane Foam External Wall Insulation",
"depths": [],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": None,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": None,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.mikewye.co.uk/product/steico-duo-dry/
"type": "external_wall_insulation",
"description": "Wood Fiber External Wall Insulation",
"depths": [40, 60],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.023255813953488375,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.043,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.thermablok.co.uk/site/wp-content/uploads/2022/09/Thermablok-Aerogel-Insulation-Blanket-TDS-AIS
# -and-Steel-Related-Details.pdf
"type": "external_wall_insulation",
"description": "Aerogel External Wall Insulation",
"depths": [10, 20, 30, 40, 50, 60, 70],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.06666666666666667,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.015,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
"type": "external_wall_insulation",
"description": "Vacuum Insulation Panels External Wall Insulation",
"depths": [45, 60],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.16666666666666666,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.006,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
}
]
internal_wall_insulation_parts = [
{
# Example product
# https://www.insulationshop.co/25mm_polystyrene_insulation_eps_70jablite.html
"type": "internal_wall_insulation",
"description": "Rigid Insulation Boards Internal Wall Insulation",
"depths": [25, 40, 50, 75, 100],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.026315789473684213,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.038,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.rockwool.com/siteassets/rw-uk/downloads/datasheets/flexi.pdf
"type": "internal_wall_insulation",
"description": "Mineral Wool Internal Wall Insulation",
"depths": [140],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.02857142857142857,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.035,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.kingspan.com/gb/en/products/insulation-boards/wall-insulation-boards/kooltherm-k118-insulated
# -plasterboard/
"type": "internal_wall_insulation",
"description": "Insulated Plasterboard Internal Wall Insulation",
"depths": [25, 80],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.02857142857142857,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.019,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
"type": "internal_wall_insulation",
"description": "Reflective Internal Wall Insulation",
"depths": [],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": None,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": None,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.insulationsuperstore.co.uk/product/vacutherm-vacupor-nt-b2-vacuum-insulated-panel-1m-x-600mm-x
# -30mm.html
"type": "internal_wall_insulation",
"description": "Vacuum Insulation Panels Wall Insulation",
"depths": [20, 30],
"depth_unit": "mm",
"cost": None,
"cost_unit": None,
"r_value_per_mm": 0.125,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.008,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
]
wall_parts = external_wall_insulation_parts + internal_wall_insulation_parts
class WallRecommendations(Definitions):
YEAR_WALLS_BUILT_WITH_INSULATION = 1990
@ -217,7 +43,12 @@ class WallRecommendations(Definitions):
"solid_brick": 2,
}
def __init__(self, property_instance: Property, uvalue_estimates, total_floor_area_group_decile, materials=None):
def __init__(
self, property_instance: Property,
uvalue_estimates: List,
total_floor_area_group_decile: str,
materials: List
):
self.property = property_instance
self.uvalue_estimates = uvalue_estimates
self.total_floor_area_group_decile = total_floor_area_group_decile
@ -227,10 +58,7 @@ class WallRecommendations(Definitions):
# Will contains a list of recommended measures
self.recommendations = []
if materials:
self.materials = materials
else:
self.materials = wall_parts
self.materials = materials
@property
def ewi_valid(self):

View file

@ -1,6 +1,7 @@
import pytest
from unittest.mock import MagicMock
from recommendations import recommendation_utils
from datatypes.enums import QuantityUnits
class TestRecommendationUtils:
@ -38,7 +39,9 @@ class TestRecommendationUtils:
def test_get_recommended_part(self):
part = {'depths': [1, 2, 3]}
assert recommendation_utils.get_recommended_part(part, 1) == {'depths': [1]}
assert recommendation_utils.get_recommended_part(
part=part, selected_depth=1, selected_total_cost=50, quantity=99, quantity_unit="m2"
) == {'depths': [1], 'estimated_cost': 50, 'quantity': 99, 'quantity_unit': QuantityUnits.m2.value}
def test_get_uvalue_estimate(self, property_mock):
uvalue_estimates = [

View file

@ -10,6 +10,192 @@ from model_data.analysis.UvalueEstimations import UvalueEstimations
from backend.Property import Property
from recommendations.recommendation_utils import is_diminishing_returns
# with open(
# os.path.abspath(os.path.dirname(__file__)) + "/recommendations/tests/test_data/input_properties.pkl", "rb"
# ) as f:
# input_properties = pickle.load(f)
#
# with open(
# os.path.abspath(os.path.dirname(__file__)) + "/recommendations/tests/test_data/uvalue_estimates.pkl", "rb"
# ) as f:
# uvalue_estimates = pickle.load(f)
external_wall_insulation_parts = [
{
# Example product
# https://insulationgo.co.uk/100mm-rockwool-external-wall-insulation-dual-density-slabs-a1-non-combustible
# -slab-ewi-render-fire/
"type": "external_wall_insulation",
"description": "Mineral Wool External Wall Insulation",
"depths": [30, 50, 70, 80, 90, 100, 150, 200],
"depth_unit": "mm",
"cost": [30, 50, 70, 80, 90, 100, 150, 200],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.0278,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.036,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.insulationking.co.uk/products/polystyrene-eps70?variant=44156186558759
"type": "external_wall_insulation",
"description": "Expanded Polystyrene External Wall Insulation",
"depths": [25, 50, 100, 125],
"depth_unit": "mm",
"cost": [25, 50, 100, 125],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.02703,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.037,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.insulationshop.co/20mm_kooltherm_k5_external_wall_kingspan.html
"type": "external_wall_insulation",
"description": "Phenolic Foam External Wall Insulation",
"depths": [20, 50, 100],
"depth_unit": "mm",
"cost": [20, 50, 100],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.043478260869565216,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.023,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
"type": "external_wall_insulation",
"description": "Polyisocyanurate/Polyurethane Foam External Wall Insulation",
"depths": [],
"depth_unit": "mm",
"cost": [],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": None,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": None,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.mikewye.co.uk/product/steico-duo-dry/
"type": "external_wall_insulation",
"description": "Wood Fiber External Wall Insulation",
"depths": [40, 60],
"depth_unit": "mm",
"cost": [40, 60],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.023255813953488375,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.043,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.thermablok.co.uk/site/wp-content/uploads/2022/09/Thermablok-Aerogel-Insulation-Blanket-TDS-AIS
# -and-Steel-Related-Details.pdf
"type": "external_wall_insulation",
"description": "Aerogel External Wall Insulation",
"depths": [10, 20, 30, 40, 50, 60, 70],
"depth_unit": "mm",
"cost": [10, 20, 30, 40, 50, 60, 70],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.06666666666666667,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.015,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
"type": "external_wall_insulation",
"description": "Vacuum Insulation Panels External Wall Insulation",
"depths": [45, 60],
"depth_unit": "mm",
"cost": [45, 60],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.16666666666666666,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.006,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
}
]
internal_wall_insulation_parts = [
{
# Example product
# https://www.insulationshop.co/25mm_polystyrene_insulation_eps_70jablite.html
"type": "internal_wall_insulation",
"description": "Rigid Insulation Boards Internal Wall Insulation",
"depths": [25, 40, 50, 75, 100],
"depth_unit": "mm",
"cost": [25, 40, 50, 75, 100],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.026315789473684213,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.038,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.rockwool.com/siteassets/rw-uk/downloads/datasheets/flexi.pdf
"type": "internal_wall_insulation",
"description": "Mineral Wool Internal Wall Insulation",
"depths": [140],
"depth_unit": "mm",
"cost": [140],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.02857142857142857,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.035,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.kingspan.com/gb/en/products/insulation-boards/wall-insulation-boards/kooltherm-k118-insulated
# -plasterboard/
"type": "internal_wall_insulation",
"description": "Insulated Plasterboard Internal Wall Insulation",
"depths": [25, 80],
"depth_unit": "mm",
"cost": [25, 80],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.02857142857142857,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.019,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
"type": "internal_wall_insulation",
"description": "Reflective Internal Wall Insulation",
"depths": [],
"depth_unit": "mm",
"cost": [],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": None,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": None,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
{
# Example product
# https://www.insulationsuperstore.co.uk/product/vacutherm-vacupor-nt-b2-vacuum-insulated-panel-1m-x-600mm-x
# -30mm.html
"type": "internal_wall_insulation",
"description": "Vacuum Insulation Panels Wall Insulation",
"depths": [20, 30],
"depth_unit": "mm",
"cost": [20, 30],
"cost_unit": "gbp_sq_meter",
"r_value_per_mm": 0.125,
"r_value_unit": "square_meter_kelvin_per_watt",
"thermal_conductivity": 0.008,
"thermal_conductivity_unit": "watt_per_meter_kelvin"
},
]
wall_parts = external_wall_insulation_parts + internal_wall_insulation_parts
class TestWallRecommendations:
@ -36,14 +222,17 @@ class TestWallRecommendations:
uvalue_estimates_mock = Mock()
mock_wall_rec_instance = WallRecommendations(property_mock, uvalue_estimates_mock, "Decile 1")
mock_wall_rec_instance = WallRecommendations(
property_mock, uvalue_estimates_mock, "Decile 1", materials=wall_parts
)
return mock_wall_rec_instance
def test_init(self, input_properties, uvalue_estimates):
obj = WallRecommendations(
property_instance=input_properties[0],
uvalue_estimates=uvalue_estimates,
total_floor_area_group_decile="Decile 1"
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
assert obj
assert obj.property
@ -63,7 +252,8 @@ class TestWallRecommendations:
recommender = WallRecommendations(
property_instance=input_properties[0],
uvalue_estimates=uvalue_estimates,
total_floor_area_group_decile="Decile 1"
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
assert recommender.property.walls["original_description"] == "Average thermal transmittance 0.16 W/m-¦K"
recommender.recommend()
@ -80,10 +270,13 @@ class TestWallRecommendations:
This property is not in a conservation area, however it's a flat so we don't recommend external wall insulation
"""
input_properties[1].year_built = 1930
input_properties[1].insulation_wall_area = 100
recommender = WallRecommendations(
property_instance=input_properties[1],
uvalue_estimates=uvalue_estimates,
total_floor_area_group_decile="Decile 1"
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
assert recommender.property.walls["original_description"] == "Solid brick, as built, no insulation (assumed)"
assert not recommender.ewi_valid
@ -110,10 +303,7 @@ class TestWallRecommendations:
However, we're told this property is solid brik so we assume no cavity.
We're also told that it has some insulation already
We'll need to estimate the u-value for this property since we don't know what the insulation is
and how thick it is. We'll estimate the u-value based on similar properties, by matching properties
with similar attributes such as the walls energy efficiency rating, the property type, the number of rooms,
etc
Since the walls are already insulated, we don't recommend further measures
This property is not in a conservation area, however it's a flat so we don't recommend external wall insulation
"""
@ -122,7 +312,8 @@ class TestWallRecommendations:
recommender = WallRecommendations(
property_instance=input_properties[6],
uvalue_estimates=uvalue_estimates.walls.to_dict("records"),
total_floor_area_group_decile="Decile 1"
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
assert recommender.property.walls["original_description"] == "Solid brick, as built, insulated (assumed)"
@ -133,21 +324,8 @@ class TestWallRecommendations:
recommender.recommend()
# We should result in some recommendations, all of which should be internal wall insulation
assert recommender.recommendations
assert recommender.estimated_u_value == 0.4115686274509804
rec_types = {part["type"] for rec in recommender.recommendations for part in rec["parts"]}
assert rec_types == {"internal_wall_insulation"}
# Check the recommendations provide a u value below the minimum
assert all(
rec["new_u_value"] < WallRecommendations.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE for rec in
recommender.recommendations
)
for rec in recommender.recommendations:
assert rec["new_u_value"] < 0.3
assert not recommender.recommendations
assert not recommender.estimated_u_value
def test_is_diminishing_returns_no_recommendations(self):
# We have no recommendations but the new u value is below the diminishing returns threshold
@ -238,7 +416,9 @@ class TestWallRecommendationsBase:
@pytest.fixture
def wall_recommendations_instance(self, property_mock, uvalue_estimations_mock):
wall_recommendations_instance = WallRecommendations(property_mock, uvalue_estimations_mock, "Decile 1")
wall_recommendations_instance = WallRecommendations(
property_mock, uvalue_estimations_mock, "Decile 1", materials=wall_parts
)
wall_recommendations_instance.uvalue_estimates.walls_decile_data = {
"decile_labels": MagicMock(),
"decile_boundaries": MagicMock()