Merge pull request #1 from Hestia-Homes/master

Master
This commit is contained in:
KhalimCK 2023-06-08 16:04:33 +01:00 committed by GitHub
commit 88407080dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 1004 additions and 0 deletions

79
.gitignore vendored
View file

@ -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
View file

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

8
.idea/Model.iml generated Normal file
View 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
View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View 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>

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

42
epc_data/app.py Normal file
View 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
View 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
View 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

View file

@ -0,0 +1,6 @@
epc-api-python
python-dotenv
tqdm
pandas
mypy
pytest

11
epc_data/temp_inputs.py Normal file
View 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"
}
]

View file

View 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

Binary file not shown.

View 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}]