mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
commit
88407080dc
24 changed files with 1004 additions and 0 deletions
79
.gitignore
vendored
79
.gitignore
vendored
|
|
@ -158,3 +158,82 @@ cython_debug/
|
|||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
.idea/artifacts
|
||||
.idea/compiler.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/modules.xml
|
||||
.idea/*.iml
|
||||
.idea/modules
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
|
|
|
|||
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
8
.idea/Model.iml
generated
Normal file
8
.idea/Model.iml
generated
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (hestia-data)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
77
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
77
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
|
||||
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ourVersions">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="3.10" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="48">
|
||||
<item index="0" class="java.lang.String" itemvalue="click" />
|
||||
<item index="1" class="java.lang.String" itemvalue="lxml" />
|
||||
<item index="2" class="java.lang.String" itemvalue="requests" />
|
||||
<item index="3" class="java.lang.String" itemvalue="schema" />
|
||||
<item index="4" class="java.lang.String" itemvalue="levenshtein" />
|
||||
<item index="5" class="java.lang.String" itemvalue="decorator" />
|
||||
<item index="6" class="java.lang.String" itemvalue="environs" />
|
||||
<item index="7" class="java.lang.String" itemvalue="scikit-learn" />
|
||||
<item index="8" class="java.lang.String" itemvalue="tabulate" />
|
||||
<item index="9" class="java.lang.String" itemvalue="python-dateutil" />
|
||||
<item index="10" class="java.lang.String" itemvalue="python-dotenv" />
|
||||
<item index="11" class="java.lang.String" itemvalue="marshmallow" />
|
||||
<item index="12" class="java.lang.String" itemvalue="pycodestyle" />
|
||||
<item index="13" class="java.lang.String" itemvalue="cycler" />
|
||||
<item index="14" class="java.lang.String" itemvalue="numpy" />
|
||||
<item index="15" class="java.lang.String" itemvalue="currency-symbols" />
|
||||
<item index="16" class="java.lang.String" itemvalue="flake8" />
|
||||
<item index="17" class="java.lang.String" itemvalue="patsy" />
|
||||
<item index="18" class="java.lang.String" itemvalue="yfinance" />
|
||||
<item index="19" class="java.lang.String" itemvalue="contextlib2" />
|
||||
<item index="20" class="java.lang.String" itemvalue="pytest-cov" />
|
||||
<item index="21" class="java.lang.String" itemvalue="certifi" />
|
||||
<item index="22" class="java.lang.String" itemvalue="gevent" />
|
||||
<item index="23" class="java.lang.String" itemvalue="pycountry" />
|
||||
<item index="24" class="java.lang.String" itemvalue="xgboost" />
|
||||
<item index="25" class="java.lang.String" itemvalue="coverage" />
|
||||
<item index="26" class="java.lang.String" itemvalue="scipy" />
|
||||
<item index="27" class="java.lang.String" itemvalue="botocore" />
|
||||
<item index="28" class="java.lang.String" itemvalue="pytest" />
|
||||
<item index="29" class="java.lang.String" itemvalue="prospector" />
|
||||
<item index="30" class="java.lang.String" itemvalue="pandas" />
|
||||
<item index="31" class="java.lang.String" itemvalue="pyyaml" />
|
||||
<item index="32" class="java.lang.String" itemvalue="tqdm" />
|
||||
<item index="33" class="java.lang.String" itemvalue="boto3" />
|
||||
<item index="34" class="java.lang.String" itemvalue="s3transfer" />
|
||||
<item index="35" class="java.lang.String" itemvalue="scikit-optimize" />
|
||||
<item index="36" class="java.lang.String" itemvalue="pyaml" />
|
||||
<item index="37" class="java.lang.String" itemvalue="future" />
|
||||
<item index="38" class="java.lang.String" itemvalue="pylint" />
|
||||
<item index="39" class="java.lang.String" itemvalue="matplotlib" />
|
||||
<item index="40" class="java.lang.String" itemvalue="statsmodels" />
|
||||
<item index="41" class="java.lang.String" itemvalue="isort" />
|
||||
<item index="42" class="java.lang.String" itemvalue="pytz" />
|
||||
<item index="43" class="java.lang.String" itemvalue="idna" />
|
||||
<item index="44" class="java.lang.String" itemvalue="scikeras" />
|
||||
<item index="45" class="java.lang.String" itemvalue="nose" />
|
||||
<item index="46" class="java.lang.String" itemvalue="sphinx" />
|
||||
<item index="47" class="java.lang.String" itemvalue="pydantic" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (hestia-data)" project-jdk-type="Python SDK" />
|
||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Model.iml" filepath="$PROJECT_DIR$/.idea/Model.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/toolchains.xml
generated
Normal file
8
.idea/toolchains.xml
generated
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NimToolchainService">
|
||||
<option name="rootPaths">
|
||||
<list />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
15
README.md
Normal file
15
README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Model Repository
|
||||
|
||||
This repository contains the code pertaining to the development
|
||||
of the data science and machine learning products being utilised by
|
||||
Hestia.
|
||||
|
||||
The different folders in this repository relate to services
|
||||
that can be used independently, or can be imported and used as
|
||||
part of a larger application
|
||||
|
||||
# Folders
|
||||
|
||||
### epc_data/
|
||||
This folder contains related to the reading and preparation of
|
||||
epc data
|
||||
256
epc_data/EpcClean.py
Normal file
256
epc_data/EpcClean.py
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
import re
|
||||
from typing import List, Dict, Any, Union, Tuple, Optional
|
||||
from collections import Counter
|
||||
|
||||
|
||||
class EpcClean:
|
||||
"""
|
||||
Container for methods which we utilise for cleaning EPC data
|
||||
"""
|
||||
|
||||
U_VALUE_REGEX = re.compile(r"(\d+\.\d+)")
|
||||
UNIT_REGEX = re.compile(r"(w/m-¦k)")
|
||||
|
||||
CLEANING_FIELDS: List[str] = [
|
||||
"roof-description",
|
||||
"floor-description",
|
||||
"walls-description",
|
||||
"mainheat-description"
|
||||
]
|
||||
|
||||
def __init__(self, data: List[Dict[str, Any]]) -> None:
|
||||
"""
|
||||
EpcClean constructor.
|
||||
|
||||
:param data: List of dictionaries containing EPC data.
|
||||
"""
|
||||
self.data: List[Dict[str, Any]] = data
|
||||
self.unique_vals: Dict[str, Any] = {}
|
||||
self.cleaned: Dict[str, List[Any]] = {}
|
||||
|
||||
def clean(self) -> None:
|
||||
"""
|
||||
Cleans the EPC data, mapping text fields to property attributes.
|
||||
"""
|
||||
self._init_empty_cleaned_obj()
|
||||
|
||||
for field in self.CLEANING_FIELDS:
|
||||
self.unique_vals[field] = Counter([v[field] for v in self.data])
|
||||
|
||||
for description in self.unique_vals["roof-description"].keys():
|
||||
self.cleaned["roof-description"].append(
|
||||
{
|
||||
"original_description": description,
|
||||
**self.clean_roof(description)
|
||||
}
|
||||
)
|
||||
|
||||
def _init_empty_cleaned_obj(self) -> None:
|
||||
"""
|
||||
Initializes an empty object for cleaned data.
|
||||
"""
|
||||
self.cleaned = {field: [] for field in self.CLEANING_FIELDS}
|
||||
|
||||
@staticmethod
|
||||
def _search_split_roof_description(desc: str) -> str:
|
||||
"""
|
||||
Searches roof descriptions and looks for key words, determining a description about the roof's insulation.
|
||||
|
||||
:param desc: Description to be searched.
|
||||
:return: Result of the search.
|
||||
"""
|
||||
if desc == "insulated":
|
||||
return "average"
|
||||
if desc == "limited":
|
||||
return "below average"
|
||||
raise NotImplementedError("Handle me")
|
||||
|
||||
def _find_insulation_thickness(
|
||||
self, description_lower: str, is_pitched: bool, is_roof_room: bool, is_flat: bool
|
||||
) -> Union[int, str, None]:
|
||||
"""
|
||||
Finds insulation thickness in the description.
|
||||
|
||||
:param description_lower: Lowercase description.
|
||||
:param is_pitched: Whether the roof is pitched.
|
||||
:param is_roof_room: Whether there is a room in the roof.
|
||||
:param is_flat: Whether the roof is flat.
|
||||
:return: Insulation thickness if found, else None.
|
||||
"""
|
||||
if "no insulation" in description_lower:
|
||||
return 0
|
||||
|
||||
if is_pitched:
|
||||
try:
|
||||
thickness = description_lower.split("pitched,")[-1].split("mm")[0].strip()
|
||||
if "+" in thickness:
|
||||
return thickness
|
||||
try:
|
||||
return int(thickness)
|
||||
except ValueError as int_error:
|
||||
raise ValueError(int_error)
|
||||
except ValueError as _:
|
||||
if "invalid input" in description_lower:
|
||||
return None
|
||||
desc = description_lower.split("pitched,")[-1].strip().split(" ")[0]
|
||||
return self._search_split_roof_description(desc)
|
||||
|
||||
if is_roof_room:
|
||||
desc_split_lookup = {
|
||||
"ceiling insulated": "average",
|
||||
"thatched": "average",
|
||||
}
|
||||
# Just search for specific phrases
|
||||
desc_split = description_lower.split("roof room(s),")[-1].strip()
|
||||
res = desc_split_lookup.get(desc_split)
|
||||
if res:
|
||||
return res
|
||||
|
||||
desc = desc_split.split(" ")[0]
|
||||
return self._search_split_roof_description(desc)
|
||||
|
||||
if is_flat:
|
||||
# Just search for specific phrases
|
||||
desc = description_lower.split("flat,")[-1].lstrip().split(" ")[0]
|
||||
return self._search_split_roof_description(desc)
|
||||
|
||||
return None
|
||||
|
||||
def _extract_thermal_transmittence(self, description_lower: str) -> Tuple[Union[float, None], Union[str, None]]:
|
||||
"""
|
||||
Extracts thermal transmittance from the description.
|
||||
|
||||
:param description_lower: Lowercase description.
|
||||
:return: Tuple containing U-value and unit.
|
||||
"""
|
||||
# Find U-value
|
||||
u_value = re.search(self.U_VALUE_REGEX, description_lower)
|
||||
if u_value is not None:
|
||||
u_value = float(u_value.group(1))
|
||||
else:
|
||||
u_value = None
|
||||
|
||||
# Find unit
|
||||
unit = re.search(self.UNIT_REGEX, description_lower)
|
||||
if unit is not None:
|
||||
unit = unit.group(1)
|
||||
else:
|
||||
unit = None
|
||||
|
||||
return u_value, unit
|
||||
|
||||
@staticmethod
|
||||
def _make_clean_roof_output(
|
||||
is_valid: bool,
|
||||
at_rafters: bool,
|
||||
is_pitched: bool,
|
||||
is_roof_room: bool,
|
||||
has_loft: bool,
|
||||
insulation_thickness: str | int | None,
|
||||
has_dwelling_above: bool,
|
||||
assumed: bool,
|
||||
is_flat: bool,
|
||||
is_thatched: bool,
|
||||
thermal_transmittence: Optional[float],
|
||||
thermal_transmittence_unit: Optional[str]
|
||||
) -> Dict[str, Union[bool, str, None]]:
|
||||
"""
|
||||
Utility function to ensure all the keys are present in the output.
|
||||
|
||||
:param is_valid: True if the roof descrption is valid, False otherwise
|
||||
:param at_rafters: True if the insulation is at the rafters, False otherwise
|
||||
:param is_pitched: True if the roof is pitched, False otherwise
|
||||
:param is_roof_room: True if there is a room in the roof, False otherwise
|
||||
:param has_loft: True if there is a loft, False otherwise
|
||||
:param insulation_thickness: The thickness of the insulation
|
||||
:param has_dwelling_above: True if there is a dwelling above, False otherwise
|
||||
:param assumed: True if the roof type was assumed based on property age, False otherwise
|
||||
:param is_flat: True if the roof is flat, False otherwise
|
||||
:param is_thatched: True if the roof is thatched, False otherwise
|
||||
:param thermal_transmittence: The thermal transmittence value of the roof, if known
|
||||
:param thermal_transmittence_unit: The unit of thermal transmittence, if known
|
||||
:return: A dictionary containing all the information about the roof.
|
||||
"""
|
||||
|
||||
return {
|
||||
"is_valid": is_valid,
|
||||
"at_rafters": at_rafters,
|
||||
"is_pitched": is_pitched,
|
||||
"is_roof_room": is_roof_room,
|
||||
"has_loft": has_loft,
|
||||
"insulation_thickness": insulation_thickness,
|
||||
"has_dwelling_above": has_dwelling_above,
|
||||
"assumed": assumed,
|
||||
"is_flat": is_flat,
|
||||
"is_thatched": is_thatched,
|
||||
"thermal_transmittence": thermal_transmittence,
|
||||
"thermal_transmittence_unit": thermal_transmittence_unit
|
||||
}
|
||||
|
||||
def clean_roof(self, description: str) -> Dict[str, Union[str, bool, int, None]]:
|
||||
"""
|
||||
We aim to extract features about the roof, so we can characterise it. We will check:
|
||||
- If the roof is pitched
|
||||
- If there is a room roof
|
||||
- if there is a loft
|
||||
- If it has insulation
|
||||
- if so, what degree of insulation
|
||||
|
||||
:param description: Description of the roof.
|
||||
:return: Dictionary of attributes of the roof.
|
||||
"""
|
||||
description_lower = description.lower().strip()
|
||||
|
||||
if "another dwelling above" in description_lower or "other premises above" in description_lower:
|
||||
return self._make_clean_roof_output(
|
||||
is_valid="invalid" not in description_lower,
|
||||
at_rafters="at rafters" in description_lower,
|
||||
is_pitched=False,
|
||||
is_roof_room=False,
|
||||
has_loft=False,
|
||||
insulation_thickness=0,
|
||||
has_dwelling_above=True,
|
||||
assumed="assumed" in description_lower,
|
||||
is_flat="flat" in description_lower,
|
||||
is_thatched=False,
|
||||
thermal_transmittence=None,
|
||||
thermal_transmittence_unit=None
|
||||
)
|
||||
|
||||
is_pitched = "pitched" in description_lower
|
||||
is_roof_room = "roof room" in description_lower
|
||||
has_loft = "loft" in description_lower
|
||||
is_flat = "flat" in description_lower
|
||||
is_thatched = "thatched" in description_lower
|
||||
at_rafters = "at rafters" in description_lower
|
||||
|
||||
thermal_transmittence, thermal_transmittence_unit, insulation_thickness = None, None, None
|
||||
if "insulation" in description_lower or "insulated" in description_lower:
|
||||
insulation_thickness = self._find_insulation_thickness(description_lower, is_pitched, is_roof_room, is_flat)
|
||||
elif "thermal transmittance" in description_lower:
|
||||
thermal_transmittence, thermal_transmittence_unit = self._extract_thermal_transmittence(description_lower)
|
||||
elif is_thatched:
|
||||
# Search for these features:
|
||||
thermal_transmittence, thermal_transmittence_unit = self._extract_thermal_transmittence(description_lower)
|
||||
insulation_thickness = self._find_insulation_thickness(
|
||||
description_lower, is_pitched, is_roof_room, is_flat
|
||||
)
|
||||
elif description_lower == "pitched":
|
||||
thermal_transmittence, thermal_transmittence_unit, insulation_thickness = None, None, None
|
||||
else:
|
||||
raise NotImplementedError("Not handled this")
|
||||
|
||||
return self._make_clean_roof_output(
|
||||
is_valid="invalid" not in description_lower,
|
||||
at_rafters=at_rafters,
|
||||
is_pitched=is_pitched,
|
||||
is_roof_room=is_roof_room,
|
||||
has_loft=has_loft,
|
||||
insulation_thickness=insulation_thickness,
|
||||
has_dwelling_above=False,
|
||||
assumed="assumed" in description_lower,
|
||||
is_flat=is_flat,
|
||||
is_thatched=is_thatched,
|
||||
thermal_transmittence=thermal_transmittence,
|
||||
thermal_transmittence_unit=thermal_transmittence_unit
|
||||
)
|
||||
31
epc_data/Property.py
Normal file
31
epc_data/Property.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
from epc_api.client import EpcClient
|
||||
from epc_data.config import EPC_AUTH_TOKEN
|
||||
|
||||
|
||||
class Property:
|
||||
|
||||
def __init__(self, postcode, address1, epc_client=None, data=None):
|
||||
self.postcode = postcode
|
||||
self.address1 = address1
|
||||
self.data = data
|
||||
|
||||
if epc_client:
|
||||
self.epc_client = epc_client
|
||||
else:
|
||||
self.epc_client = EpcClient(auth_token=EPC_AUTH_TOKEN)
|
||||
|
||||
def search_address_epc(self):
|
||||
"""
|
||||
This method searches for an address in the EPC database and returns the first result
|
||||
:return: property data
|
||||
"""
|
||||
if self.data:
|
||||
return
|
||||
|
||||
# This will fail if a property does not have an EPC - this has been documented as a case to handle
|
||||
response = self.epc_client.domestic.search(params={"address": self.address1, "postcode": self.postcode})
|
||||
|
||||
if len(response["rows"]) > 1:
|
||||
raise Exception("More than one result found for this address - investigate me")
|
||||
|
||||
self.data = response["rows"][0]
|
||||
49
epc_data/README.md
Normal file
49
epc_data/README.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Environment setup
|
||||
|
||||
We're using conda to manage environments to circumvent the
|
||||
issues with Mac M1. This documentation will also cover Pycharm setup.
|
||||
|
||||
We're working in python 3.10 so
|
||||
|
||||
```commandline
|
||||
conda create -n hestia-data python=3.10
|
||||
```
|
||||
|
||||
Then activate the environment
|
||||
|
||||
```commandline
|
||||
conda activate hestia-data
|
||||
```
|
||||
|
||||
To set up with Pycharm, run
|
||||
|
||||
```commandline
|
||||
which python
|
||||
```
|
||||
|
||||
and grab the path to the python executable. Then in Pycharm, go to
|
||||
Settings > Project > Python Interpreter and click the gear icon
|
||||
to add a new interpreter. Select Conda and either paste the path to the python executable
|
||||
and click OK, or select the conda environment from the dropdown.
|
||||
|
||||
You may need to restart Pycharm for the new interpreter to be recognised.
|
||||
|
||||
To install project dependencies navigate to /epc_data and run
|
||||
|
||||
```commandline
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
If you are not in a virtual environment, activate it with
|
||||
|
||||
```commandline
|
||||
conda activate envName
|
||||
```
|
||||
|
||||
Then run
|
||||
|
||||
```commandline
|
||||
python -m pytest
|
||||
```
|
||||
0
epc_data/__init__.py
Normal file
0
epc_data/__init__.py
Normal file
42
epc_data/app.py
Normal file
42
epc_data/app.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
from tqdm import tqdm
|
||||
|
||||
from epc_data.temp_inputs import input_data
|
||||
from epc_data.Property import Property
|
||||
from epc_data.config import EPC_AUTH_TOKEN
|
||||
from epc_api.client import EpcClient
|
||||
from epc_data.downloader import pagenated_epc_download
|
||||
from epc_data.EpcClean import EpcClean
|
||||
|
||||
|
||||
def handler():
|
||||
# To begin with, the input data is a list of dictionaries, however we would read this file in
|
||||
|
||||
epc_client = EpcClient(auth_token=EPC_AUTH_TOKEN)
|
||||
|
||||
input_properties = [
|
||||
Property(postcode=config['postcode'], address1=config['address1'], epc_client=epc_client)
|
||||
for config in input_data
|
||||
]
|
||||
|
||||
for p in input_properties:
|
||||
p.search_address_epc()
|
||||
|
||||
local_authorities = {p.data['local-authority'] for p in input_properties}
|
||||
|
||||
data = []
|
||||
for la in tqdm(local_authorities):
|
||||
data.extend(
|
||||
pagenated_epc_download(
|
||||
client=epc_client,
|
||||
params={"local-authority": la},
|
||||
page_size=5000,
|
||||
n_pages=10,
|
||||
)
|
||||
)
|
||||
|
||||
cleaner = EpcClean(data)
|
||||
|
||||
cleaner.clean()
|
||||
|
||||
import pandas as pd
|
||||
df = pd.DataFrame(cleaner.cleaned["roof-description"])
|
||||
6
epc_data/config.py
Normal file
6
epc_data/config.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(dotenv_path='epc_data/.env')
|
||||
|
||||
EPC_AUTH_TOKEN = os.environ.get('EPC_AUTH_TOKEN')
|
||||
26
epc_data/downloader.py
Normal file
26
epc_data/downloader.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import time
|
||||
|
||||
|
||||
def pagenated_epc_download(client, params, page_size, n_pages, verbose=0, slowdown=0.1):
|
||||
offset_from = 0
|
||||
n_completed = 0
|
||||
results = []
|
||||
complete = False
|
||||
while not complete:
|
||||
if verbose:
|
||||
print("Pulling for page %s" % str(int(offset_from / page_size) + 1))
|
||||
time.sleep(slowdown)
|
||||
search_resp = client.domestic.search(params=params, offset_from=offset_from, size=page_size)
|
||||
|
||||
# Note: We can only make 10k queries for a single set of search queries.
|
||||
# It might make sense to download data via zip for machine learning since we don't need this
|
||||
# data to be perfectly up to date
|
||||
if search_resp is None:
|
||||
break
|
||||
results.extend(search_resp["rows"])
|
||||
if n_completed == n_pages:
|
||||
complete = True
|
||||
else:
|
||||
offset_from += page_size
|
||||
|
||||
return results
|
||||
6
epc_data/requirements.txt
Normal file
6
epc_data/requirements.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
epc-api-python
|
||||
python-dotenv
|
||||
tqdm
|
||||
pandas
|
||||
mypy
|
||||
pytest
|
||||
11
epc_data/temp_inputs.py
Normal file
11
epc_data/temp_inputs.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Temporary input data
|
||||
input_data = [
|
||||
{
|
||||
"address1": "28 Distillery Wharf",
|
||||
"postcode": "w6 9bf"
|
||||
},
|
||||
{
|
||||
"address1": "Flat 14 Godley V C House",
|
||||
"postcode": "E2 0LP"
|
||||
}
|
||||
]
|
||||
0
epc_data/tests/__init__.py
Normal file
0
epc_data/tests/__init__.py
Normal file
94
epc_data/tests/test_EpcClean.py
Normal file
94
epc_data/tests/test_EpcClean.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import pytest
|
||||
import pickle
|
||||
from epc_data.EpcClean import EpcClean
|
||||
from pathlib import Path
|
||||
from epc_data.tests.test_data.EpcClean_test_roof_cases import clean_roof_test_cases
|
||||
|
||||
# For local testing
|
||||
if __file__ == "<input>":
|
||||
input_data_path = Path("./epc_data/tests/test_data/EpcClean_inputs.obj")
|
||||
else:
|
||||
current_file_path = Path(__file__)
|
||||
input_data_path = current_file_path.parent / 'test_data' / 'EpcClean_inputs.obj'
|
||||
|
||||
|
||||
class TestEpcClean:
|
||||
|
||||
@staticmethod
|
||||
def load_data(path):
|
||||
with open(path, "rb") as file:
|
||||
return pickle.load(file)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_class(self):
|
||||
self.cleaner = EpcClean(self.load_data(input_data_path))
|
||||
|
||||
def test_clean(self):
|
||||
self.cleaner.clean()
|
||||
assert len(self.cleaner.cleaned["roof-description"]) == len(self.cleaner.unique_vals["roof-description"])
|
||||
|
||||
def test__init_empty_cleaned_obj(self):
|
||||
self.cleaner._init_empty_cleaned_obj()
|
||||
assert all([len(values) == 0 for values in self.cleaner.cleaned.values()])
|
||||
|
||||
def test__search_split_roof_description(self):
|
||||
assert self.cleaner._search_split_roof_description("insulated") == "average"
|
||||
assert self.cleaner._search_split_roof_description("limited") == "below average"
|
||||
with pytest.raises(NotImplementedError):
|
||||
self.cleaner._search_split_roof_description("unknown")
|
||||
|
||||
def test__find_insulation_thickness(self):
|
||||
assert self.cleaner._find_insulation_thickness("no insulation", False, False, False) == 0
|
||||
|
||||
def test__extract_thermal_transmittence(self):
|
||||
description = "U-value of 2.3 w/m-¦k"
|
||||
assert self.cleaner._extract_thermal_transmittence(description) == (2.3, "w/m-¦k")
|
||||
|
||||
def test_clean_roof(self):
|
||||
result = self.cleaner.clean_roof('Pitched, 270 mm loft insulation')
|
||||
|
||||
# change the expected output based on your requirement
|
||||
expected_output = {
|
||||
"is_valid": True,
|
||||
"at_rafters": False,
|
||||
"is_pitched": True,
|
||||
"is_roof_room": False,
|
||||
"has_loft": True,
|
||||
"insulation_thickness": 270,
|
||||
"has_dwelling_above": False,
|
||||
"assumed": False,
|
||||
"is_flat": False,
|
||||
"is_thatched": False,
|
||||
"thermal_transmittence": None,
|
||||
"thermal_transmittence_unit": None
|
||||
}
|
||||
|
||||
assert result == expected_output
|
||||
|
||||
for test_case in clean_roof_test_cases:
|
||||
result = self.cleaner.clean_roof(test_case['original_description'])
|
||||
# Ensure the output ordering is correct
|
||||
expected_result = {key: test_case[key] for key in result.keys()}
|
||||
expected_result["desc"] = test_case["original_description"]
|
||||
result["desc"] = test_case["original_description"]
|
||||
assert result == expected_result
|
||||
|
||||
def test_clean_roof_with_dwelling_above(self):
|
||||
result = self.cleaner.clean_roof('(another dwelling above)')
|
||||
|
||||
expected_output = {
|
||||
"is_valid": True,
|
||||
"at_rafters": False,
|
||||
"is_pitched": False,
|
||||
"is_roof_room": False,
|
||||
"has_loft": False,
|
||||
"insulation_thickness": 0,
|
||||
"has_dwelling_above": True,
|
||||
"assumed": False,
|
||||
"is_flat": False,
|
||||
"is_thatched": False,
|
||||
"thermal_transmittence": None,
|
||||
"thermal_transmittence_unit": None,
|
||||
}
|
||||
|
||||
assert result == expected_output
|
||||
BIN
epc_data/tests/test_data/EpcClean_inputs.obj
Normal file
BIN
epc_data/tests/test_data/EpcClean_inputs.obj
Normal file
Binary file not shown.
261
epc_data/tests/test_data/EpcClean_test_roof_cases.py
Normal file
261
epc_data/tests/test_data/EpcClean_test_roof_cases.py
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
clean_roof_test_cases = [
|
||||
{'original_description': 'Flat, limited insulation (assumed)', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': 'below average', 'has_dwelling_above': False, 'assumed': True,
|
||||
'is_flat': True, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': '(another dwelling above)', 'is_pitched': False, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': 0, 'has_dwelling_above': True, 'assumed': False, 'is_flat': False, 'is_thatched': False,
|
||||
'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Pitched, insulated (assumed)', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': True,
|
||||
'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Flat, insulated (assumed)', 'is_pitched': False, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': True, 'is_flat': True,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 200 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 200, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 50 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 50, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, no insulation (assumed)', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': 0, 'has_dwelling_above': False, 'assumed': True, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 150 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 150, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Flat, no insulation (assumed)', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': 0, 'has_dwelling_above': False, 'assumed': True, 'is_flat': True,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Roof room(s), insulated (assumed)', 'is_pitched': False, 'is_roof_room': True,
|
||||
'has_loft': False, 'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': True,
|
||||
'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Pitched, 350 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 350, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 300 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 300, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.14 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.14, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, no insulation', 'is_pitched': True, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': 0, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False, 'is_thatched': False,
|
||||
'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Pitched, 100 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 100, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': '(other premises above)', 'is_pitched': False, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': 0, 'has_dwelling_above': True, 'assumed': False, 'is_flat': False, 'is_thatched': False,
|
||||
'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Pitched, 270 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 270, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, limited insulation (assumed)', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': 'below average', 'has_dwelling_above': False, 'assumed': True,
|
||||
'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Pitched, 250 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 250, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, insulated at rafters', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': False,
|
||||
'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': True},
|
||||
{'original_description': 'Pitched', 'is_pitched': True, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Roof room(s), insulated', 'is_pitched': False, 'is_roof_room': True, 'has_loft': False,
|
||||
'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 75 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 75, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Roof room(s), no insulation (assumed)', 'is_pitched': False, 'is_roof_room': True,
|
||||
'has_loft': False, 'insulation_thickness': 0, 'has_dwelling_above': False, 'assumed': True, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Flat, insulated', 'is_pitched': False, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': False, 'is_flat': True,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.1 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.1, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, *** INVALID INPUT Code : 57 *** loft insulation', 'is_pitched': True,
|
||||
'is_roof_room': False, 'has_loft': True, 'insulation_thickness': None, 'has_dwelling_above': False,
|
||||
'assumed': False, 'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None,
|
||||
'thermal_transmittence_unit': None, 'is_valid': False, 'at_rafters': False},
|
||||
{'original_description': 'Pitched, 12 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 12, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.10 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.1, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.13 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.13, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.11 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.11, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Roof room(s), ceiling insulated', 'is_pitched': False, 'is_roof_room': True,
|
||||
'has_loft': False, 'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': False,
|
||||
'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.12 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.12, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.20 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.2, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.16 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.16, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.15 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.15, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 0 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 0, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.08 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.08, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Flat, limited insulation', 'is_pitched': False, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': 'below average', 'has_dwelling_above': False, 'assumed': False, 'is_flat': True,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Roof room(s), limited insulation (assumed)', 'is_pitched': False, 'is_roof_room': True,
|
||||
'has_loft': False, 'insulation_thickness': 'below average', 'has_dwelling_above': False, 'assumed': True,
|
||||
'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Pitched, insulated', 'is_pitched': True, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': 'average', 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.18 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.18, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, limited insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': 'below average', 'has_dwelling_above': False, 'assumed': False,
|
||||
'is_flat': False, 'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None,
|
||||
'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.19 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.19, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.17 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.17, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.48 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.48, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.42 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.42, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.58 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.58, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.45 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.45, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 1.00 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 1.0, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.2 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.2, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 400+ mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': '400+', 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 25 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 25, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.49 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.49, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.37 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.37, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Thatched', 'is_pitched': False, 'is_roof_room': False, 'has_loft': False,
|
||||
'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False, 'is_thatched': True,
|
||||
'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True, 'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.09 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.09, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.21 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.21, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.24 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.24, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Pitched, 400 mm loft insulation', 'is_pitched': True, 'is_roof_room': False,
|
||||
'has_loft': True, 'insulation_thickness': 400, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.23 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.23, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.28 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.28, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.4 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.4, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Thatched, with additional insulation', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': True, 'thermal_transmittence': None, 'thermal_transmittence_unit': None, 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.26 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.26, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False},
|
||||
{'original_description': 'Average thermal transmittance 0.22 W/m-¦K', 'is_pitched': False, 'is_roof_room': False,
|
||||
'has_loft': False, 'insulation_thickness': None, 'has_dwelling_above': False, 'assumed': False, 'is_flat': False,
|
||||
'is_thatched': False, 'thermal_transmittence': 0.22, 'thermal_transmittence_unit': 'w/m-¦k', 'is_valid': True,
|
||||
'at_rafters': False}]
|
||||
Loading…
Add table
Reference in a new issue