mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Updating logic for extracting heat loss perimeter and party walls from xml data
This commit is contained in:
parent
bdd6171626
commit
2c931b4383
5 changed files with 74 additions and 19 deletions
|
|
@ -76,6 +76,7 @@ class Property:
|
|||
already_installed=None,
|
||||
non_invasive_recommendations=None,
|
||||
measures=None,
|
||||
energy_assessment=None,
|
||||
**kwargs
|
||||
):
|
||||
|
||||
|
|
@ -178,6 +179,11 @@ class Property:
|
|||
self.recommendations_scoring_data = []
|
||||
self.simulation_epcs = {}
|
||||
|
||||
# This additional condition data should change how we pass kwargs to this. We should no longer need to pass
|
||||
# kwargs to this class, but instead, we should pass the energy assessment condition data
|
||||
self.energy_assessment_condition_data = energy_assessment["condition"]
|
||||
|
||||
# TODO: We keep this but only temporarily until we add bathrooms, bedrooms, building id to the condition data
|
||||
self.parse_kwargs(kwargs)
|
||||
|
||||
@classmethod
|
||||
|
|
@ -188,6 +194,10 @@ class Property:
|
|||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
|
||||
# Note - none of this data is contained in an energy asssessment, but we should consider how this is done
|
||||
# as we collect more data from the energy assessment
|
||||
|
||||
n_bathrooms = kwargs.get("n_bathrooms", None)
|
||||
if n_bathrooms not in [None, ""]:
|
||||
# We add on a small value to ensure that the number of bathrooms is rounded up, in case the value is 0.5
|
||||
|
|
@ -1034,9 +1044,14 @@ class Property:
|
|||
# TODO: These functions should work on an EPCRecord object, so that the format is more standardised.
|
||||
# They could also be added as attributes to the EPC Record
|
||||
|
||||
self.perimeter = estimate_perimeter(
|
||||
self.floor_area / self.number_of_floors,
|
||||
self.number_of_rooms / self.number_of_floors,
|
||||
# Many of these pieces of information are now contained in the condition data
|
||||
condition_data = self.energy_assessment_condition_data.copy()
|
||||
|
||||
self.perimeter = float(self.energy_assessment_condition_data["perimeter"]) \
|
||||
if condition_data["perimeter"] is not None \
|
||||
else estimate_perimeter(
|
||||
floor_area=self.floor_area / self.number_of_floors,
|
||||
num_rooms=self.number_of_rooms / self.number_of_floors
|
||||
)
|
||||
|
||||
self.insulation_wall_area = estimate_external_wall_area(
|
||||
|
|
|
|||
|
|
@ -150,13 +150,13 @@ class EnergyAssessment(Base):
|
|||
|
||||
epc = {key.replace("_", "-"): getattr(self, key) for key in self.EPC_KEYS}
|
||||
# Get everything else
|
||||
additional = {
|
||||
condition = {
|
||||
column.name: getattr(self, column.name)
|
||||
for column in self.__table__.columns if column.name not in self.EPC_KEYS
|
||||
}
|
||||
|
||||
return {"epc": epc, "additional": additional}
|
||||
return {"epc": epc, "condition": condition}
|
||||
|
||||
@staticmethod
|
||||
def empty_response():
|
||||
return {"epc": {}, "additional": {}}
|
||||
return {"epc": {}, "condition": {}}
|
||||
|
|
|
|||
|
|
@ -360,6 +360,27 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
# Otherwise, we use the newest EPC
|
||||
epc_records = create_epc_records(epc_searcher, energy_assessment)
|
||||
|
||||
patch = next((
|
||||
x for x in patches if (x["address"] == config["address"]) and (x["postcode"] == config["postcode"])
|
||||
), {})
|
||||
epc_records = patch_epc(patch, epc_records)
|
||||
|
||||
prepared_epc = EPCRecord(
|
||||
epc_records=epc_records,
|
||||
run_mode="newdata",
|
||||
cleaning_data=cleaning_data
|
||||
)
|
||||
|
||||
property_already_installed = next((
|
||||
x for x in already_installed if
|
||||
(x["address"] == config["address"]) and (x["postcode"] == config["postcode"])
|
||||
), {})
|
||||
|
||||
property_non_invasive_recommendations = next((
|
||||
x for x in non_invasive_recommendations if
|
||||
(x["address"] == config["address"]) and (x["postcode"] == config["postcode"])
|
||||
), {})
|
||||
|
||||
input_properties.append(
|
||||
Property(
|
||||
id=property_id,
|
||||
|
|
@ -368,7 +389,8 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
epc_record=prepared_epc,
|
||||
already_installed=property_already_installed,
|
||||
non_invasive_recommendations=property_non_invasive_recommendations,
|
||||
**Property.extract_kwargs(config)
|
||||
energy_assessment=energy_assessment,
|
||||
**Property.extract_kwargs(config), # TODO: Depraecate this
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -645,19 +645,25 @@ class XmlParser:
|
|||
self.number_of_floors = len(
|
||||
[f for f in self.floor_dimensions if f["building_part_identifier"] == "Main Dwelling"]
|
||||
)
|
||||
self.heat_loss_perimeter = max(
|
||||
[
|
||||
float(f["heat_loss_perimeter"]) for f in self.floor_dimensions
|
||||
if f["building_part_identifier"] == "Main Dwelling" and not f["room_roof"]
|
||||
]
|
||||
)
|
||||
|
||||
self.party_wall_length = max(
|
||||
[
|
||||
float(f["party_wall_length"]) for f in self.floor_dimensions
|
||||
if f["building_part_identifier"] == "Main Dwelling" and not f["room_roof"]
|
||||
]
|
||||
)
|
||||
# We extract the maximum heat loss perimeter, per building part
|
||||
max_heat_loss_perimeters = {d['building_part_identifier']: max(
|
||||
(float(x['heat_loss_perimeter']) for x in self.floor_dimensions if
|
||||
x['building_part_identifier'] == d['building_part_identifier'] and x['heat_loss_perimeter']),
|
||||
default=float('-inf')
|
||||
) for d in self.floor_dimensions}
|
||||
|
||||
self.heat_loss_perimeter = sum(max_heat_loss_perimeters.values())
|
||||
|
||||
max_party_walls = {
|
||||
d['building_part_identifier']: max(
|
||||
(float(x['party_wall_length']) for x in self.floor_dimensions if
|
||||
x['building_part_identifier'] == d['building_part_identifier'] and x['party_wall_length']),
|
||||
default=float('-inf')
|
||||
) for d in self.floor_dimensions
|
||||
}
|
||||
|
||||
self.party_wall_length = sum(max_party_walls.values())
|
||||
|
||||
self.perimeter = self.heat_loss_perimeter + self.party_wall_length
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ def main():
|
|||
# TODO: IF we have many uploads, we can do them in a batch so we don't try and upload huge amounts of data to
|
||||
# the database at onece
|
||||
|
||||
# TODO: We now have detailed information about primary and secondary walls, so we should use this information
|
||||
# in our recommendations when we have it
|
||||
|
||||
# For each property, we download the xmls and extract the data
|
||||
database_data = []
|
||||
for uprn, xmls in assessments_map.items():
|
||||
|
|
@ -117,3 +120,12 @@ def main():
|
|||
# https://www.ncm-pcdb.org.uk/sap/download
|
||||
# However retrieving this data is not a priority, so we can leave this for now as parsing the database
|
||||
# is a non-trivial task
|
||||
|
||||
# TODO: The condition report contains additional data such as the number of bedrooms and the number of bathrooms
|
||||
# We can extract this data and store it in the database as well. We can then update our kwargs methodology
|
||||
# that is passed to the property class, where instead we store this additional data in our database (it could
|
||||
# be stored in the energy assessment table, or in a separate table) and then when we're passed additional data
|
||||
# we can query the database for this data and use it to update the property object, instead of storing it
|
||||
# in the asset list and pulling it out of the asset list
|
||||
# 1) Bathrooms
|
||||
# 2) Bedrooms
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue