adding measures into individual measures classes wip

This commit is contained in:
Khalim Conn-Kowlessar 2024-09-05 13:36:27 +01:00
parent 85eaeccad8
commit efbcd0f0b8
5 changed files with 43 additions and 37 deletions

View file

@ -37,12 +37,15 @@ SPECIFIC_MEASURES = [
"trickle_vents", "trickle_vents",
"draught_proofing", "draught_proofing",
"mixed_glazing", # This covers partial double glazing and secondary glazing "mixed_glazing", # This covers partial double glazing and secondary glazing
"cavity_extract_and_refill",
] ]
# This allows us to extend high level categories for measures such as "wall_insulation" to the specific measures # This allows us to extend high level categories for measures such as "wall_insulation" to the specific measures
# such as "external_wall_insulation", "internal_wall_insulation", "cavity_wall_insulation" # such as "external_wall_insulation", "internal_wall_insulation", "cavity_wall_insulation"
MEASURE_MAP = { MEASURE_MAP = {
"wall_insulation": ["internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation"], "wall_insulation": [
"internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation", "cavity_extract_and_refill"
],
"roof_insulation": ["loft_insulation", "flat_roof_insulation", "room_roof_insulation"], "roof_insulation": ["loft_insulation", "flat_roof_insulation", "room_roof_insulation"],
"floor_insulation": ["suspended_floor_insulation", "solid_floor_insulation"], "floor_insulation": ["suspended_floor_insulation", "solid_floor_insulation"],
"heating": ["boiler_upgrade", "high_heat_retention_storage_heater", "air_source_heat_pump"], "heating": ["boiler_upgrade", "high_heat_retention_storage_heater", "air_source_heat_pump"],

View file

@ -71,6 +71,9 @@ class Recommendations:
Determines the set of measures to be included in recommendations Determines the set of measures to be included in recommendations
""" """
if self.property_instance.non_invasive_recommendations:
raise Exception("IMPLEMENT ME")
inclusions_full = [MEASURE_MAP[x] if x in MEASURE_MAP else x for x in self.inclusions] inclusions_full = [MEASURE_MAP[x] if x in MEASURE_MAP else x for x in self.inclusions]
exclusions_full = [MEASURE_MAP[x] if x in MEASURE_MAP else x for x in self.exclusions] exclusions_full = [MEASURE_MAP[x] if x in MEASURE_MAP else x for x in self.exclusions]
@ -96,24 +99,19 @@ class Recommendations:
property_recommendations = [] property_recommendations = []
phase = 0 phase = 0
# TODO: We should form measures form non-intrusive recommendations too
measures = self.find_included_measures() measures = self.find_included_measures()
# Building Fabric # Building Fabric
if ( self.wall_recomender.recommend(phase=phase, measures=measures)
("wall_insulation" in measures) or if self.wall_recomender.recommendations:
("internal_wall_insulation" in measures) or property_recommendations.append(self.wall_recomender.recommendations)
("external_wall_insulation" in measures) phase += 1
):
self.wall_recomender.recommend(phase=phase, measures=measures)
if self.wall_recomender.recommendations:
property_recommendations.append(self.wall_recomender.recommendations)
phase += 1
if "roof_insulation" in measures: self.roof_recommender.recommend(phase=phase, measures=measures)
self.roof_recommender.recommend(phase=phase) if self.roof_recommender.recommendations:
if self.roof_recommender.recommendations: property_recommendations.append(self.roof_recommender.recommendations)
property_recommendations.append(self.roof_recommender.recommendations) phase += 1
phase += 1
# Ventilation recommendations # Ventilation recommendations
# We only produce a ventilation recommendation if the property is recommended to have wall or roof # We only produce a ventilation recommendation if the property is recommended to have wall or roof
@ -123,11 +121,10 @@ class Recommendations:
# real impact on the SAP score. Therefore, we don't need to include phasing for ventilation. If we # real impact on the SAP score. Therefore, we don't need to include phasing for ventilation. If we
# have any # have any
# wall or roof recommendations, we will ensure that ventilation is included in the simulation # wall or roof recommendations, we will ensure that ventilation is included in the simulation
if "ventilation" in measures: if self.wall_recomender.recommendations or self.roof_recommender.recommendations:
if self.wall_recomender.recommendations or self.roof_recommender.recommendations: self.ventilation_recomender.recommend(measures=measures)
self.ventilation_recomender.recommend() if self.ventilation_recomender.recommendation:
if self.ventilation_recomender.recommendation: property_recommendations.append(self.ventilation_recomender.recommendation)
property_recommendations.append(self.ventilation_recomender.recommendation)
if "floor_insulation" in measures: if "floor_insulation" in measures:
self.floor_recommender.recommend(phase=phase) self.floor_recommender.recommend(phase=phase)

View file

@ -1,6 +1,7 @@
import math import math
import pandas as pd import pandas as pd
from backend.Property import Property from backend.Property import Property
from backend.app.plan.schemas import MEASURE_MAP
from typing import List from typing import List
from datatypes.enums import QuantityUnits from datatypes.enums import QuantityUnits
from recommendations.recommendation_utils import ( from recommendations.recommendation_utils import (
@ -108,11 +109,13 @@ class RoofRecommendations:
return full_insulated_room_roof or room_roof_insulated_at_rafters return full_insulated_room_roof or room_roof_insulated_at_rafters
def recommend(self, phase): def recommend(self, phase, measures=None):
if self.property.roof["has_dwelling_above"]: if self.property.roof["has_dwelling_above"]:
return return
measures = MEASURE_MAP["roof_insulation"] if measures is None else measures
u_value = self.property.roof["thermal_transmittance"] u_value = self.property.roof["thermal_transmittance"]
# We check if the roof is already insulated and if so, we exit # We check if the roof is already insulated and if so, we exit
@ -153,19 +156,19 @@ class RoofRecommendations:
self.estimated_u_value = u_value self.estimated_u_value = u_value
if (u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE) and ( if (u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE) and (
"loft_insulation" not in self.property.non_invasive_recommendations "loft_insulation" not in measures
): ):
# The Roof is already compliant # The Roof is already compliant
return return
if self.property.roof["is_pitched"] or self.property.roof["is_flat"]: if (self.property.roof["is_pitched"] and "loft_insulation" in measures) or (
insulation_thickness = ( self.property.roof["is_flat"] and "flat_roof_insulation"
0 if "loft_insulation" not in self.property.non_invasive_recommendations else self.insulation_thickness ):
) insulation_thickness = 0 if "loft_insulation" not in measures else self.insulation_thickness
self.recommend_roof_insulation(u_value, insulation_thickness, self.property.roof, phase) self.recommend_roof_insulation(u_value, insulation_thickness, self.property.roof, phase)
return return
if self.property.roof["is_roof_room"]: if self.property.roof["is_roof_room"] and ("room_roof_insulation" in measures):
self.recommend_room_roof_insulation(u_value, phase) self.recommend_room_roof_insulation(u_value, phase)
return return

View file

@ -29,7 +29,7 @@ class VentilationRecommendations(Definitions):
def identify_ventilation(self): def identify_ventilation(self):
self.has_ventilaion = self.property.data["mechanical-ventilation"] in self.VENTILATION_DESCRIPTIONS self.has_ventilaion = self.property.data["mechanical-ventilation"] in self.VENTILATION_DESCRIPTIONS
def recommend(self): def recommend(self, measures=None):
""" """
If there is no ventilation, we recommend installing ventilation If there is no ventilation, we recommend installing ventilation
@ -37,6 +37,9 @@ class VentilationRecommendations(Definitions):
ventilation if there is natural ventilation ventilation if there is natural ventilation
:return: :return:
""" """
measures = ["ventilation"] if measures is None else measures
if "ventilation" not in measures:
return
self.identify_ventilation() self.identify_ventilation()
if self.has_ventilaion: if self.has_ventilaion:

View file

@ -5,6 +5,7 @@ import pandas as pd
from datatypes.enums import QuantityUnits from datatypes.enums import QuantityUnits
from backend.Property import Property from backend.Property import Property
from backend.app.plan.schemas import MEASURE_MAP
from BaseUtility import Definitions from BaseUtility import Definitions
from etl.epc_clean.epc_attributes.WallAttributes import WallAttributes from etl.epc_clean.epc_attributes.WallAttributes import WallAttributes
from recommendations.recommendation_utils import ( from recommendations.recommendation_utils import (
@ -195,6 +196,10 @@ class WallRecommendations(Definitions):
# U-value less than 0.18 and if in or close to a conversation area, # U-value less than 0.18 and if in or close to a conversation area,
# recommend internal wall insulation as a possible measure # recommend internal wall insulation as a possible measure
measures = MEASURE_MAP["wall_insulation"] if measures is None else measures
if not measures:
return
u_value = self.property.walls["thermal_transmittance"] u_value = self.property.walls["thermal_transmittance"]
u_value = None if pd.isnull(u_value) else u_value u_value = None if pd.isnull(u_value) else u_value
@ -235,7 +240,7 @@ class WallRecommendations(Definitions):
and (u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE) and (u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE)
): ):
# Recommend insulation # Recommend insulation
self.find_insulation(u_value, phase) self.find_insulation(u_value, phase, measures)
return return
# We can't detect it's a cavity wall, but it was built after 1990 so likely built with insulation already # We can't detect it's a cavity wall, but it was built after 1990 so likely built with insulation already
@ -259,7 +264,7 @@ class WallRecommendations(Definitions):
self.estimated_u_value = u_value self.estimated_u_value = u_value
if is_cavity_wall or "cavity_extract_and_refill" in self.property.non_invasive_recommendations: if (is_cavity_wall and "cavity_wall_insulation" in measures) or "cavity_extract_and_refill" in measures:
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
self.find_cavity_insulation(u_value, insulation_thickness, phase) self.find_cavity_insulation(u_value, insulation_thickness, phase)
@ -558,7 +563,7 @@ class WallRecommendations(Definitions):
return recommendations return recommendations
def find_insulation(self, u_value, phase, measures=None): def find_insulation(self, u_value, phase, measures):
""" """
This function contains the logic for finding potential insulation measures for a property, depending This function contains the logic for finding potential insulation measures for a property, depending
on the parts available and whether the property can have external wall insulation installed on the parts available and whether the property can have external wall insulation installed
@ -570,13 +575,8 @@ class WallRecommendations(Definitions):
# we separate the logic for for recommending them, therefore we don't # we separate the logic for for recommending them, therefore we don't
# consider diminishing returns between the two as they are considered to be separate measures # consider diminishing returns between the two as they are considered to be separate measures
if measures is None:
ewi_valid = self.ewi_valid()
else:
ewi_valid = self.ewi_valid() and "external_wall_insulation" in measures
ewi_recommendations = [] ewi_recommendations = []
if ewi_valid: if self.ewi_valid() and "external_wall_insulation" in measures:
ewi_recommendations = self._find_insulation( ewi_recommendations = self._find_insulation(
u_value=u_value, u_value=u_value,
insulation_materials=pd.DataFrame( insulation_materials=pd.DataFrame(