diff --git a/model_data/simulation_system/generate_rdsap_change.py b/model_data/simulation_system/generate_rdsap_change.py index 5bf8cde8..7c4c6029 100644 --- a/model_data/simulation_system/generate_rdsap_change.py +++ b/model_data/simulation_system/generate_rdsap_change.py @@ -16,7 +16,10 @@ from model_data.simulation_system.core.Settings import ( from model_data.simulation_system.core.DataProcessor import DataProcessor from utils.s3 import save_dataframe_to_s3_parquet, read_from_s3, read_dataframe_from_s3_parquet from recommendations.rdsap_tables import england_wales_age_band_lookup -from recommendations.recommendation_utils import get_wall_u_value, get_roof_u_value +from recommendations.recommendation_utils import ( + get_wall_u_value, get_roof_u_value, get_floor_u_value, estimate_perimeter_2_rooms, estimate_perimeter, + extract_insulation_thickness, get_wall_type +) DATA_DIRECTORY = Path(__file__).parent / "model_data" / "simulation_system" / "data" / "all-domestic-certificates" @@ -220,6 +223,7 @@ def make_uvalues(df): uprn = x["UPRN"] row_index = x["row_index"] + age_band = england_wales_age_band_lookup[x["CONSTRUCTION_AGE_BAND"]] # ~~~~~~~~~~~~~~~~~~ # Walls @@ -229,7 +233,7 @@ def make_uvalues(df): if pd.isnull(starting_wall_uvalue): starting_wall_uvalue = get_wall_u_value( clean_description=x["walls_clean_description"], - age_band=england_wales_age_band_lookup[x["CONSTRUCTION_AGE_BAND"]], + age_band=age_band, is_granite_or_whinstone=x["is_granite_or_whinstone"], is_sandstone_or_limestone=x["is_sandstone_or_limestone"], ) @@ -239,7 +243,7 @@ def make_uvalues(df): if x["walls_clean_description"] != x["walls_clean_description_ENDING"]: ending_wall_uvalue = get_wall_u_value( clean_description=x["walls_clean_description_ENDING"], - age_band=england_wales_age_band_lookup[x["CONSTRUCTION_AGE_BAND"]], + age_band=age_band, is_granite_or_whinstone=x["is_granite_or_whinstone"], is_sandstone_or_limestone=x["is_sandstone_or_limestone"], ) @@ -260,7 +264,7 @@ def make_uvalues(df): is_flat=x["is_flat"], is_pitched=x["is_pitched"], is_at_rafters=x["is_at_rafters"], - age_band=england_wales_age_band_lookup[x["CONSTRUCTION_AGE_BAND"]] + age_band=age_band ) ending_roof_uvalue = x["roof_thermal_transmittance_ENDING"] @@ -275,12 +279,44 @@ def make_uvalues(df): is_flat=x["is_flat"], is_pitched=x["is_pitched"], is_at_rafters=x["is_at_rafters"], - age_band=england_wales_age_band_lookup[x["CONSTRUCTION_AGE_BAND"]] + age_band=age_band ) # ~~~~~~~~~~~~~~~~~~ # Floor # ~~~~~~~~~~~~~~~~~~ + perimeters = {} + for suffix in ["_STARTING", "_ENDING"]: + floor_area = x[f"TOTAL_FLOOR_AREA{suffix}"] + n_rooms = x["NUMBER_HABITABLE_ROOMS"] + + perimeters[f"estimated_perimeter{suffix}"] = estimate_perimeter_2_rooms(floor_area) if n_rooms <= 2 else \ + estimate_perimeter(floor_area, n_rooms) + + floor_type = "suspended" if x["is_suspended"] else "solid" + wall_type = get_wall_type(**x) + + starting_floor_uvalue = x["floor_thermal_transmittance"] + if pd.isnull(starting_floor_uvalue): + starting_floor_uvalue = get_floor_u_value( + floor_type=floor_type, + perimeter=perimeters["estimated_perimeter_STARTING"], + area=x[f"TOTAL_FLOOR_AREA_STARTING"], + insulation_thickness=extract_insulation_thickness(x["floor_insulation_thickness"]), + wall_type=wall_type, + age_band=age_band + ) + + ending_floor_uvalue = x["floor_thermal_transmittance_ENDING"] + if pd.isnull(ending_floor_uvalue): + ending_floor_uvalue = get_floor_u_value( + floor_type=floor_type, + perimeter=perimeters["estimated_perimeter_ENDING"], + area=x[f"TOTAL_FLOOR_AREA_ENDING"], + insulation_thickness=extract_insulation_thickness(x["floor_insulation_thickness_ENDING"]), + wall_type=wall_type, + age_band=age_band + ) uvalues.append( { @@ -290,6 +326,9 @@ def make_uvalues(df): "ending_wall_uvalue": ending_wall_uvalue, "starting_roof_uvalue": starting_roof_uvalue, "ending_roof_uvalue": ending_roof_uvalue, + "starting_floor_uvalue": starting_floor_uvalue, + "ending_floor_uvalue": ending_floor_uvalue, + **perimeters } ) @@ -454,13 +493,6 @@ def app(): columns=["walls_clean_description", "walls_clean_description_ENDING"] ) - - - - - - get_wall_u_value(clean_description=) - if pd.isnull(data_by_urpn_df).sum().sum(): raise ValueError("Null values found in dataset after process_and_prune_desriptions") diff --git a/recommendations/rdsap_tables.py b/recommendations/rdsap_tables.py index 748d4034..6abbea8b 100644 --- a/recommendations/rdsap_tables.py +++ b/recommendations/rdsap_tables.py @@ -438,6 +438,8 @@ table_s10 = pd.DataFrame(s10_list) # Table s11 is used for assigning the u-values of floors when the insulation thickness is unknown # which can be found on page 25 of the BRE document # https://bregroup.com/wp-content/uploads/2019/09/RdSAP_2012_9.94-20-09-2019.pdf +# +# The thickness values are in mm ######################################################################################################################## s11_list = [ @@ -446,17 +448,17 @@ s11_list = [ {"Age_band": "C to F", "Floor_construction": "solid", "England_Wales": 0, "Scotland": 0, "Northern_Ireland": 0, "Park_home": 0}, {"Age_band": "G", "Floor_construction": "solid", "England_Wales": 0, "Scotland": 0, - "Northern_Ireland": 0, "Park_home": "25"}, - {"Age_band": "H", "Floor_construction": "solid", "England_Wales": 0, "Scotland": "25", - "Northern_Ireland": "25", "Park_home": 0}, - {"Age_band": "I", "Floor_construction": "solid", "England_Wales": "25", "Scotland": "50", - "Northern_Ireland": "50", "Park_home": "50"}, - {"Age_band": "J", "Floor_construction": "solid", "England_Wales": "75", "Scotland": "75", + "Northern_Ireland": 0, "Park_home": 25}, + {"Age_band": "H", "Floor_construction": "solid", "England_Wales": 0, "Scotland": 25, + "Northern_Ireland": 25, "Park_home": 0}, + {"Age_band": "I", "Floor_construction": "solid", "England_Wales": 25, "Scotland": 50, + "Northern_Ireland": 50, "Park_home": 50}, + {"Age_band": "J", "Floor_construction": "solid", "England_Wales": 75, "Scotland": 75, "Northern_Ireland": 0, "Park_home": 0}, - {"Age_band": "K", "Floor_construction": "solid", "England_Wales": "100", "Scotland": "100", - "Northern_Ireland": "100", "Park_home": "70"}, - {"Age_band": "L", "Floor_construction": "solid", "England_Wales": "100", "Scotland": "120", - "Northern_Ireland": "100", "Park_home": 0}, + {"Age_band": "K", "Floor_construction": "solid", "England_Wales": 100, "Scotland": 100, + "Northern_Ireland": 100, "Park_home": 70}, + {"Age_band": "L", "Floor_construction": "solid", "England_Wales": 100, "Scotland": 120, + "Northern_Ireland": 100, "Park_home": 0}, ] table_s11 = pd.DataFrame(s11_list) diff --git a/recommendations/recommendation_utils.py b/recommendations/recommendation_utils.py index d1d90de9..9ffab939 100644 --- a/recommendations/recommendation_utils.py +++ b/recommendations/recommendation_utils.py @@ -369,7 +369,7 @@ def estimate_perimeter_2_rooms(floor_area): return perimeter -def calculate_floor_u_value(floor_type, area, perimeter, age_band, wall_type, insulation_thickness=None): +def get_floor_u_value(floor_type, area, perimeter, age_band, wall_type, insulation_thickness=None): """ Estimate the u-value of a suspended floor, based on RdSap methodology Default U-value for UNINSULATED suspended floor, based on RdSAP methodology @@ -458,3 +458,52 @@ def calculate_floor_u_value(floor_type, area, perimeter, age_band, wall_type, in raise ValueError("Invalid floor type. Acceptable values are 'solid' or 'suspended'.") return round(U, 2) # rounding U value to two decimal places + + +def extract_insulation_thickness(insulation_thickness_str): + """ + Converts insulation thickness to a float + :param insulation_thickness_str: + :return: + """ + if insulation_thickness_str == "none": + return 0 + + return int(insulation_thickness_str.replace("mm", "")) + + +def get_wall_type( + is_cavity_wall, + is_solid_brick, + is_granite_or_whinstone, + is_sandstone_or_limestone, + is_timber_frame, + is_cob, + is_system_built, + is_park_home, + **kwargs +): + """ + Converts booleans to a string wall type, for querying the wall thickness table + :return: + """ + if is_cavity_wall: + return "cavity" + + if is_solid_brick: + return "solid brick" + + if is_granite_or_whinstone or is_sandstone_or_limestone: + return "stone" + + if is_timber_frame: + return "timber frame" + + if is_cob: + return "cob" + + if is_system_built: + return "system build" + + if is_park_home: + return "park home"