fixing wall recommendations testss

This commit is contained in:
Khalim Conn-Kowlessar 2023-09-22 14:08:49 +01:00
parent f288d47e38
commit 5146e6e0b4
6 changed files with 44 additions and 73 deletions

View file

@ -3,6 +3,7 @@ import re
from epc_api.client import EpcClient
from model_data.config import EPC_AUTH_TOKEN
from model_data.BaseUtility import Definitions
from recommendations.rdsap_tables import england_wales_age_band_lookup
class Property(Definitions):
@ -29,6 +30,7 @@ class Property(Definitions):
lighting = None
coordinates = None
age_band = None
def __init__(self, id, postcode, address1, epc_client=None, data=None):
self.id = id
@ -245,6 +247,7 @@ class Property(Definitions):
self.set_floor_height()
self.set_wall_area()
self.set_floor_area()
self.set_age_band()
for description, attribute in cleaned.items():
@ -263,6 +266,17 @@ class Property(Definitions):
raise ValueError("Either No attributes or multiple found for %s" % description)
setattr(self, self.ATTRIBUTE_MAP[description], attributes[0])
def set_age_band(self):
"""
Sets a cleaned version of the age band of the property given the EPC data
:return:
"""
if not self.data:
raise ValueError("Property does not contain data")
self.age_band = england_wales_age_band_lookup[self.data["construction-age-band"]]
def set_is_in_conservation_area(self, in_conservation_area):
"""
Sets whether the property is in a conservation area given the output of the ConservationAreaClient

View file

@ -539,8 +539,6 @@ def app():
if pd.isnull(data_by_urpn_df).sum().sum():
raise ValueError("Null values found in dataset after process_and_prune_desriptions")
data_by_urpn_df = DataProcessor.difference_data(data_by_urpn_df)
dataset.append(data_by_urpn_df)
cleaning_averages["LOCAL_AUTHORITY"] = df["LOCAL_AUTHORITY"].values[0]
@ -555,6 +553,9 @@ def app():
)
output = pd.concat(dataset)
output = DataProcessor.difference_data(output)
save_dataframe_to_s3_parquet(
df=output,
bucket_name="retrofit-data-dev",

View file

@ -3,7 +3,6 @@ from typing import List
from model_data.BaseUtility import Definitions
from datatypes.enums import QuantityUnits
from backend.Property import Property
from recommendations.rdsap_tables import england_wales_age_band_lookup
from recommendations.recommendation_utils import (
r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns, update_lowest_selected_u_value,
get_recommended_part, estimate_perimeter, estimate_perimeter_2_rooms, get_wall_type,
@ -40,12 +39,10 @@ class FloorRecommendations(Definitions):
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
# For audit purposes, when estimating u values we'll store it
self.estimated_u_value = None
@ -119,14 +116,13 @@ class FloorRecommendations(Definitions):
else:
estimated_perimeter = estimate_perimeter(total_floor_area / num_floors, scaled_num_rooms)
age_band = england_wales_age_band_lookup[self.property.data["construction-age-band"]]
wall_type = get_wall_type(**self.property.walls)
self.estimated_u_value = get_floor_u_value(
floor_type="suspended" if is_suspended else "solid",
area=total_floor_area,
perimeter=estimated_perimeter,
age_band=age_band,
age_band=self.property.age_band,
insulation_thickness=insulation_thickness,
wall_type=wall_type
)

View file

@ -7,7 +7,7 @@ from backend.Property import Property
from model_data.BaseUtility import Definitions
from recommendations.recommendation_utils import (
r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns, update_lowest_selected_u_value,
get_recommended_part, get_uvalue_estimate
get_recommended_part, get_wall_u_value
)
@ -44,13 +44,12 @@ class WallRecommendations(Definitions):
}
def __init__(
self, property_instance: Property,
uvalue_estimates: List,
self,
property_instance: Property,
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
# For audit purposes, when estimating u values we'll store it
self.estimated_u_value = None
@ -116,18 +115,15 @@ class WallRecommendations(Definitions):
raise NotImplementedError("Not implemented yet")
if is_solid_brick:
u_value = get_wall_u_value(
clean_description=self.property.walls["clean_description"],
age_band=self.property.age_band,
is_granite_or_whinstone=self.property.walls["is_granite_or_whinstone"],
is_sandstone_or_limestone=self.property.walls["is_sandstone_or_limestone"],
)
self.estimated_u_value = u_value
if insulation_thickness == "none":
# This is an estimated figure based on industry standards
u_value = self.DEFAULT_U_VALUES["solid_brick"]
else:
u_value = get_uvalue_estimate(
uvalue_estimates=self.uvalue_estimates,
property=self.property,
total_floor_area_group_decile=self.total_floor_area_group_decile
)
self.estimated_u_value = u_value
if is_solid_brick:
if u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
self.find_insulation(u_value)

View file

@ -206,13 +206,6 @@ class TestWallRecommendations:
) as f:
return pickle.load(f)
@pytest.fixture
def uvalue_estimates(self):
with open(
os.path.abspath(os.path.dirname(__file__)) + "/test_data/uvalue_estimates.pkl", "rb"
) as f:
return pickle.load(f)
@pytest.fixture
def mock_wall_rec_instance(self):
# Creating a mock instance of WallRecommendations with the necessary attributes
@ -220,26 +213,22 @@ class TestWallRecommendations:
property_mock.full_sap_epc = {"lodgement-date": "2000-01-01"} # or any date you want
property_mock.data = {"construction-age-band": "1950"} # or any other data that fits your tests
uvalue_estimates_mock = Mock()
mock_wall_rec_instance = WallRecommendations(
property_mock, uvalue_estimates_mock, "Decile 1", materials=wall_parts
property_mock, "Decile 1", materials=wall_parts
)
return mock_wall_rec_instance
def test_init(self, input_properties, uvalue_estimates):
def test_init(self, input_properties):
obj = WallRecommendations(
property_instance=input_properties[0],
uvalue_estimates=uvalue_estimates,
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
assert obj
assert obj.property
assert obj.uvalue_estimates
assert obj.total_floor_area_group_decile == "Decile 1"
def test_uvalue_0_16(self, input_properties, uvalue_estimates):
def test_uvalue_0_16(self, input_properties):
"""
This tests the wall description Average thermal transmittance 0.16 W/m-¦K
The important data for this recommendation is:
@ -251,7 +240,6 @@ class TestWallRecommendations:
input_properties[0].year_built = 2014
recommender = WallRecommendations(
property_instance=input_properties[0],
uvalue_estimates=uvalue_estimates,
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
@ -260,7 +248,7 @@ class TestWallRecommendations:
# This should be empty
assert recommender.recommendations == []
def test_solid_brick_no_insulation(self, input_properties, uvalue_estimates):
def test_solid_brick_no_insulation(self, input_properties):
"""
This tests a property with a wall description of Solid brick, as built, no insulation (assumed)
The property was built in 1930, right on the threshold for when cavity walls were introduced
@ -271,10 +259,12 @@ class TestWallRecommendations:
"""
input_properties[1].year_built = 1930
input_properties[1].insulation_wall_area = 100
input_properties[1].walls["clean_description"] = "Solid brick, as built, no insulation"
input_properties[1].walls["is_sandstone_or_limestone"] = False
input_properties[1].age_band = "A"
recommender = WallRecommendations(
property_instance=input_properties[1],
uvalue_estimates=uvalue_estimates,
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
@ -296,7 +286,7 @@ class TestWallRecommendations:
recommender.recommendations
)
def test_solid_brick_insulation(self, input_properties, uvalue_estimates):
def test_solid_brick_insulation(self, input_properties):
"""
This tests a property with a wall description of Solid brick, as built, insulation (assumed)
The property was built in 1991, after cavity walls were introduced
@ -311,7 +301,6 @@ class TestWallRecommendations:
input_properties[6].year_built = 1991
recommender = WallRecommendations(
property_instance=input_properties[6],
uvalue_estimates=uvalue_estimates.walls.to_dict("records"),
total_floor_area_group_decile="Decile 1",
materials=wall_parts
)
@ -390,39 +379,10 @@ class TestWallRecommendationsBase:
return property_mock
@pytest.fixture
def uvalue_estimations_mock(self):
uvalue_estimations_mock = MagicMock(spec=UvalueEstimations)
uvalue_estimations_mock.walls = pd.DataFrame([
{
'local-authority': 'E09000012',
'property-type': 'Bungalow',
'walls-energy-eff': 'Very Good',
'walls-env-eff': 'Very Good',
'built-form': 'End-Terrace',
'number-habitable-rooms': '', 'number-heated-rooms': '', 'total-floor-area_group': 'Decile 1',
'median_thermal_transmittance': 0.15, 'n_samples': 1
}
])
uvalue_estimations_mock.walls_decile_data = {
'decile_labels': ['Decile 1', 'Decile 2', 'Decile 3', 'Decile 4', 'Decile 5', 'Decile 6', 'Decile 7',
'Decile 8', 'Decile 9', 'Decile 10'],
'decile_boundaries': np.array([11., 49., 52., 56., 63., 70., 74., 79.,
90., 103.8, 1936.])}
uvalue_estimations_mock.classify_decile_newvalues.return_value = ["Decile 1"]
return uvalue_estimations_mock
@pytest.fixture
def wall_recommendations_instance(self, property_mock, uvalue_estimations_mock):
def wall_recommendations_instance(self, property_mock):
wall_recommendations_instance = WallRecommendations(
property_mock, uvalue_estimations_mock, "Decile 1", materials=wall_parts
property_mock, "Decile 1", materials=wall_parts
)
wall_recommendations_instance.uvalue_estimates.walls_decile_data = {
"decile_labels": MagicMock(),
"decile_boundaries": MagicMock()
}
return wall_recommendations_instance
def test_ewi_valid_in_conservation_area(self, wall_recommendations_instance):
@ -443,7 +403,11 @@ class TestWallRecommendationsBase:
"thermal_transmittance": None,
"is_solid_brick": False,
"is_cavity_wall": False,
"insulation_thickness": "none"
"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()