mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
2148 lines
151 KiB
Python
2148 lines
151 KiB
Python
import json
|
||
|
||
import pandas as pd
|
||
from tqdm import tqdm
|
||
from utils.s3 import read_dataframe_from_s3_parquet, save_data_to_s3, save_dataframe_to_s3_parquet
|
||
from backend.Property import Property
|
||
|
||
# This is the github pr number
|
||
MODEL_VERSION = "101"
|
||
|
||
|
||
def app():
|
||
dataset = read_dataframe_from_s3_parquet(
|
||
bucket_name="retrofit-data-dev",
|
||
file_key="sap_change_model/dataset.parquet"
|
||
)
|
||
|
||
thresholds = dataset["total_floor_area_starting"].quantile(
|
||
[0.3, 0.6, 0.9]
|
||
).values
|
||
|
||
dataset["floor_area_quantile"] = pd.cut(
|
||
dataset["total_floor_area_starting"],
|
||
bins=[0] + list(thresholds) + [float('inf')],
|
||
labels=False,
|
||
include_lowest=True
|
||
)
|
||
|
||
# We want to set up some tests to deduce the following:
|
||
# For different property types, of various sizes, what is the impact of the various measures that we recommend
|
||
# 1) Insulating the loft. We test the impact of bringing the loft to 270mm insulation and 300mm insulation
|
||
property_types = dataset[
|
||
["property_type", "built_form", "floor_area_quantile", "construction_age_band"]
|
||
].drop_duplicates()
|
||
|
||
property_types = property_types.sort_values(
|
||
["property_type", "built_form", "floor_area_quantile", "construction_age_band"]
|
||
)
|
||
|
||
# For each property type congifuration, we take an example property with different starting loft thresholds. We take
|
||
# the value with the lowest U-value, since when simulating, we often work with particularly low u-values
|
||
|
||
# TODOS
|
||
# 1) When simulating with loft insulation, make sure is_loft is definitely true, because the roof could start as
|
||
# pitched, but is_loft false
|
||
|
||
# TODO: We have a description: "Pitched, loft insulation", which seems to have its insulation thickness set to
|
||
# "none"
|
||
# Example UPRN: 100021359753, 10001204228
|
||
|
||
# TODO: For windows, we have glazing_type and glazed_type. When simulating, we don't set glazed_type_ending which
|
||
# could be set to "double glazing installed during or after 2002" (THIS HAS BEEN ADDED!)
|
||
|
||
# TODO: When simulating external wall insulation vs internal wall insulation, I need to set the external_insulation
|
||
# or internal_insulation boolean values to true (THIS HAS BEEN ADDED!)
|
||
|
||
# TODO: We could probably re-map some of the values of glazed_type_ending
|
||
|
||
# For simulating
|
||
# 1) loft insulation - we take the lowest u-value when loft insulation is 270mm and 300mm, the values we most
|
||
# commonly simulate to - For loft insulation, these values are in-line with
|
||
best_270mm_uvalue = dataset[dataset["roof_insulation_thickness"] == "270"]["roof_thermal_transmittance"].min()
|
||
best_300mm_uvalue = dataset[dataset["roof_insulation_thickness"] == "300"]["roof_thermal_transmittance"].min()
|
||
|
||
# 2) Intenal wall insulation - we take the lowest u-value when simulating internal wall insulation
|
||
best_internal_wall_uvalue = dataset[
|
||
dataset["internal_insulation"] & dataset["is_solid_brick"]
|
||
]["walls_thermal_transmittance"].min()
|
||
|
||
# 3) External wall insulation - we take the lowest u-value when simulating external wall insulation
|
||
best_external_wall_uvalue = dataset[
|
||
dataset["external_insulation"] & dataset["is_solid_brick"]
|
||
]["walls_thermal_transmittance"].min()
|
||
|
||
# 4) Cavity wall insulation - we take the lowest u-value when simulating cavity wall insulation
|
||
# This is 0.28, which is a sufficiently low value
|
||
best_cavity_wall_uvalue = dataset[
|
||
dataset["is_cavity_wall"] & dataset["is_filled_cavity"] & (~dataset["external_insulation"]) & (
|
||
~dataset["internal_insulation"])
|
||
]["walls_thermal_transmittance"].min()
|
||
|
||
ending_colums = [col for col in dataset.columns if col.endswith("_ending")]
|
||
# For the purpose of scoring, we want to simulate JUST the impact of the measure we're testing. We therefore
|
||
# need to make sure that every "_ending" column is equal to its starting value
|
||
column_config = {}
|
||
for ending_col in ending_colums:
|
||
base_col = ending_col.replace("_ending", "")
|
||
# We check if the starting column ends with _starting or is just the base col
|
||
if base_col + "_starting" in dataset.columns:
|
||
column_config[ending_col] = base_col + "_starting"
|
||
elif base_col in dataset.columns:
|
||
column_config[ending_col] = base_col
|
||
else:
|
||
raise ValueError("something went wrong")
|
||
|
||
loft_insulation_testing_data = []
|
||
solid_wall_testing_data = []
|
||
cavity_wall_testing_data = []
|
||
solid_floor_testing_data = []
|
||
suspended_floor_testing_data = []
|
||
single_glazed_testing_data = []
|
||
partial_double_glazed_testing_data = []
|
||
partial_secondary_glazed_testing_data = []
|
||
pitched_roof_solar = []
|
||
flat_roof_solar = []
|
||
for property_config in tqdm(property_types.itertuples(), total=property_types.shape[0]):
|
||
|
||
config_hash = hash(str(property_config))
|
||
|
||
# Take a sample row
|
||
population = dataset[
|
||
(dataset["property_type"] == property_config.property_type) &
|
||
(dataset["built_form"] == property_config.built_form) &
|
||
(dataset["floor_area_quantile"] == property_config.floor_area_quantile) &
|
||
(dataset["construction_age_band"] == property_config.construction_age_band)
|
||
].copy()
|
||
|
||
# Re-set all of the ending columns
|
||
for col in ending_colums:
|
||
population[col] = population[column_config[col]]
|
||
|
||
# 1) Loft insulation
|
||
|
||
# For loft insulation, there are two scenarios we test.
|
||
# 1) Loft insulation to 270mm
|
||
# 2) Lost insulation to 300mm
|
||
|
||
for insulation_thickness in ["none", "12", "50", "75", "100", "150", "200", "250"]:
|
||
if insulation_thickness == "none":
|
||
row = population[
|
||
(population["roof_insulation_thickness"] == "none") &
|
||
(population["is_pitched"])
|
||
]
|
||
|
||
else:
|
||
row = population[
|
||
(population["roof_insulation_thickness"] == insulation_thickness) &
|
||
(population["is_pitched"])
|
||
]
|
||
|
||
if row.empty:
|
||
continue
|
||
|
||
row = row.sample(1)
|
||
|
||
loft_insulation_270mm_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=row["uprn"].values[0],
|
||
recommendation_record=row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"loft_insulation_{insulation_thickness}_270mm_{config_hash}",
|
||
"type": "loft_insulation",
|
||
"new_u_value": best_270mm_uvalue,
|
||
"parts": [
|
||
{"depth": 270}
|
||
]
|
||
}
|
||
)
|
||
|
||
loft_insulation_300mm_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=row["uprn"].values[0],
|
||
recommendation_record=row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"loft_insulation_{insulation_thickness}_300mm_{config_hash}",
|
||
"type": "loft_insulation",
|
||
"new_u_value": best_300mm_uvalue,
|
||
"parts": [
|
||
{"depth": 300}
|
||
]
|
||
}
|
||
)
|
||
|
||
# Insert simulation specific configuration details
|
||
loft_insulation_270mm_simulation = {
|
||
"simulation_ending_insulation_thickness": "270",
|
||
"simulation_starting_insulation_thickness": insulation_thickness,
|
||
**loft_insulation_270mm_simulation
|
||
}
|
||
|
||
loft_insulation_300mm_simulation = {
|
||
"simulation_ending_insulation_thickness": "300",
|
||
"simulation_starting_insulation_thickness": insulation_thickness,
|
||
**loft_insulation_300mm_simulation
|
||
}
|
||
|
||
loft_insulation_testing_data.append(loft_insulation_270mm_simulation)
|
||
loft_insulation_testing_data.append(loft_insulation_300mm_simulation)
|
||
|
||
# 2) Solid wall insulation
|
||
solid_wall_sample = population[
|
||
population["is_solid_brick"] & (population["walls_insulation_thickness"] == "none")
|
||
]
|
||
|
||
# We take 1 sample for each value of walls_thermal_transmittance
|
||
for uvalue in solid_wall_sample["walls_thermal_transmittance"].unique():
|
||
row = solid_wall_sample[
|
||
solid_wall_sample["walls_thermal_transmittance"] == uvalue
|
||
].sample(1)
|
||
|
||
# Simulated IWI
|
||
internal_wall_insulation_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=row["uprn"].values[0],
|
||
recommendation_record=row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"internal_wall_insulation_uvalue_{uvalue}_{config_hash}",
|
||
"type": "internal_wall_insulation",
|
||
"new_u_value": best_internal_wall_uvalue,
|
||
"parts": []
|
||
}
|
||
)
|
||
|
||
# Simulated EWI
|
||
external_wall_insulation_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=row["uprn"].values[0],
|
||
recommendation_record=row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"external_wall_insulation_uvalue_{uvalue}_{config_hash}",
|
||
"type": "external_wall_insulation",
|
||
"new_u_value": best_external_wall_uvalue,
|
||
"parts": []
|
||
}
|
||
)
|
||
|
||
# The iww/ewi simulations will be next to each other, so we can see how they differ for the same property
|
||
solid_wall_testing_data.append(internal_wall_insulation_simulation)
|
||
solid_wall_testing_data.append(external_wall_insulation_simulation)
|
||
|
||
# 3) Cavity wall insulation
|
||
cavity_wall_sample = population[
|
||
population["is_cavity_wall"] & (~population["is_filled_cavity"]) & (
|
||
~population["external_insulation"]
|
||
) & (~population["internal_insulation"])
|
||
]
|
||
|
||
# We take 1 sample for each value of walls_thermal_transmittance
|
||
for uvalue in cavity_wall_sample["walls_thermal_transmittance"].unique():
|
||
row = cavity_wall_sample[
|
||
cavity_wall_sample["walls_thermal_transmittance"] == uvalue
|
||
].sample(1)
|
||
|
||
# Simulated filled cavity
|
||
filled_cavity_wall_insulation_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=row["uprn"].values[0],
|
||
recommendation_record=row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"cavity_wall_insulation_uvalue_{uvalue}_{config_hash}",
|
||
"type": "cavity_wall_insulation",
|
||
"new_u_value": best_cavity_wall_uvalue,
|
||
"parts": []
|
||
}
|
||
)
|
||
|
||
cavity_wall_testing_data.append(filled_cavity_wall_insulation_simulation)
|
||
|
||
# 4) Solid floor insulation
|
||
solid_floor_sample = population[
|
||
population["is_solid"] & (population["floor_insulation_thickness"] == "none")
|
||
]
|
||
|
||
solid_floor_uvalues = solid_floor_sample["floor_thermal_transmittance"].quantile([0.25, 0.5, 0.75]).values
|
||
solid_floor_uvalues = {v for v in solid_floor_uvalues if not pd.isnull(v)}
|
||
|
||
# We have many different values of u-value for solid floors, we we'll take a sample at the 25%, 50% and 75%
|
||
# values
|
||
# We must take a value that is in one of the unique values for floor_thermal_transmittance
|
||
for uvalue in solid_floor_uvalues:
|
||
nearest_value = solid_floor_sample['floor_thermal_transmittance'].sub(uvalue).abs().idxmin()
|
||
nearest_row = solid_floor_sample.loc[[nearest_value]].sample(1)
|
||
|
||
# Simulated solid floor insulation
|
||
solid_floor_insulation_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=nearest_row["uprn"].values[0],
|
||
recommendation_record=nearest_row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"solid_floor_insulation_uvalue_{uvalue}_{config_hash}",
|
||
"type": "solid_floor_insulation",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": []
|
||
}
|
||
)
|
||
|
||
solid_floor_testing_data.append(solid_floor_insulation_simulation)
|
||
|
||
# 5) Suspended floor insulation
|
||
suspended_floor_sample = population[
|
||
population["is_suspended"] & (population["floor_insulation_thickness"] == "none")
|
||
]
|
||
|
||
suspended_floor_uvalues = suspended_floor_sample["floor_thermal_transmittance"].quantile(
|
||
[0.25, 0.5, 0.75]
|
||
).values
|
||
suspended_floor_uvalues = {v for v in suspended_floor_uvalues if not pd.isnull(v)}
|
||
|
||
# We take the same approach as for solid floors
|
||
for uvalue in suspended_floor_uvalues:
|
||
nearest_value = suspended_floor_sample['floor_thermal_transmittance'].sub(uvalue).abs().idxmin()
|
||
nearest_row = suspended_floor_sample.loc[[nearest_value]].sample(1)
|
||
|
||
# Simulated suspended floor insulation
|
||
suspended_floor_insulation_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=nearest_row["uprn"].values[0],
|
||
recommendation_record=nearest_row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"suspended_floor_insulation_uvalue_{uvalue}_{config_hash}",
|
||
"type": "suspended_floor_insulation",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": []
|
||
}
|
||
)
|
||
|
||
suspended_floor_testing_data.append(suspended_floor_insulation_simulation)
|
||
|
||
# 6) Windows - single glazing
|
||
single_glazing_sample = population[
|
||
(population["glazing_type"] == "single")
|
||
]
|
||
|
||
if not single_glazing_sample.empty:
|
||
row = single_glazing_sample.sample(1)
|
||
|
||
# For single glazed windows, we can recommend double glazing or secondary glazing
|
||
|
||
# Simulated double glazing
|
||
double_glazing_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=row["uprn"].values[0],
|
||
recommendation_record=row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"windows_glazing_single_to_double_{config_hash}",
|
||
"type": "windows_glazing",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": [],
|
||
"is_secondary_glazing": False
|
||
}
|
||
)
|
||
|
||
# Simulated secondary glazing
|
||
secondary_glazing_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=row["uprn"].values[0],
|
||
recommendation_record=row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"windows_glazing_single_to_secondary_{config_hash}",
|
||
"type": "windows_glazing",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": [],
|
||
"is_secondary_glazing": True
|
||
}
|
||
)
|
||
|
||
# Add in simulation specific details
|
||
# Add to the beginning of the dictionary
|
||
double_glazing_simulation = {
|
||
"simulation_ending_window_finish": "double",
|
||
**double_glazing_simulation
|
||
}
|
||
secondary_glazing_simulation = {
|
||
"simulation_ending_window_finish": "secondary",
|
||
**secondary_glazing_simulation
|
||
}
|
||
|
||
single_glazed_testing_data.append(double_glazing_simulation)
|
||
single_glazed_testing_data.append(secondary_glazing_simulation)
|
||
|
||
# 7) Windows - partial double glazed
|
||
partial_double_glazing_sample = population[
|
||
(population["glazing_type"] == "double") & (population["multi_glaze_proportion_starting"] > 0) & (
|
||
population["multi_glaze_proportion_starting"] < 100
|
||
)
|
||
]
|
||
|
||
partial_double_glazed_values = partial_double_glazing_sample["multi_glaze_proportion_starting"].quantile(
|
||
[0.25, 0.5, 0.75]
|
||
).values
|
||
# Take non-null values
|
||
partial_double_glazed_values = [v for v in partial_double_glazed_values if not pd.isnull(v)]
|
||
partial_double_glazed_values = set(partial_double_glazed_values)
|
||
|
||
for value in partial_double_glazed_values:
|
||
nearest_value = partial_double_glazing_sample['multi_glaze_proportion_starting'].sub(value).abs().idxmin()
|
||
nearest_row = partial_double_glazing_sample.loc[[nearest_value]].sample(1)
|
||
# If we start with partial double glazing, we recommend completing the job
|
||
# Simulated double glazing
|
||
double_glazing_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=nearest_row["uprn"].values[0],
|
||
recommendation_record=nearest_row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"windows_glazing_partial_double_to_double_{value}_{config_hash}",
|
||
"type": "windows_glazing",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": [],
|
||
"is_secondary_glazing": False
|
||
}
|
||
)
|
||
|
||
partial_double_glazed_testing_data.append(double_glazing_simulation)
|
||
|
||
# 8) Windows - partial secondary glazed
|
||
partial_secondary_glazing_sample = population[
|
||
(population["glazing_type"] == "secondary") & (population["multi_glaze_proportion_starting"] > 0) & (
|
||
population["multi_glaze_proportion_starting"] < 100
|
||
)
|
||
]
|
||
|
||
partial_secondary_glazed_values = partial_secondary_glazing_sample["multi_glaze_proportion_starting"].quantile(
|
||
[0.25, 0.5, 0.75]
|
||
).values
|
||
# Take non-null values
|
||
partial_secondary_glazed_values = [v for v in partial_secondary_glazed_values if not pd.isnull(v)]
|
||
partial_secondary_glazed_values = set(partial_secondary_glazed_values)
|
||
|
||
for value in partial_secondary_glazed_values:
|
||
nearest_value = partial_secondary_glazing_sample['multi_glaze_proportion_starting'].sub(
|
||
value).abs().idxmin()
|
||
nearest_row = partial_secondary_glazing_sample.loc[[nearest_value]].sample(1)
|
||
|
||
# If we start with partial secondary glazing, we recommend completing the job
|
||
# Simulated secondary glazing
|
||
secondary_glazing_simulation = Property.create_recommendation_scoring_data(
|
||
property_id=nearest_row["uprn"].values[0],
|
||
recommendation_record=nearest_row.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"windows_glazing_partial_secondary_to_secondary_{value}_{config_hash}",
|
||
"type": "windows_glazing",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": [],
|
||
"is_secondary_glazing": True
|
||
}
|
||
)
|
||
|
||
partial_secondary_glazed_testing_data.append(secondary_glazing_simulation)
|
||
|
||
# 9) Solar PV
|
||
|
||
# We only recommend solar for properties that have flat or pitched roofs, and no existing solar
|
||
pitched_roof_no_solar = population[
|
||
(population["is_pitched"]) & (population["photo_supply_starting"] == 0)
|
||
]
|
||
|
||
if not pitched_roof_no_solar.empty:
|
||
pitched_roof_no_solar = pitched_roof_no_solar.sample(1)
|
||
|
||
flat_roof_no_solar = population[
|
||
(population["is_flat"]) & (population["photo_supply_starting"] == 0)
|
||
]
|
||
|
||
if not flat_roof_no_solar.empty:
|
||
flat_roof_no_solar = flat_roof_no_solar.sample(1)
|
||
|
||
# We simulate 30%, 40% and 50% coverage
|
||
for coverage in [30, 40, 50]:
|
||
|
||
if not pitched_roof_no_solar.empty:
|
||
solar_simulation_pitched = Property.create_recommendation_scoring_data(
|
||
property_id=pitched_roof_no_solar["uprn"].values[0],
|
||
recommendation_record=pitched_roof_no_solar.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"pitched_solar_pv_coverage_{coverage}_percent_{config_hash}",
|
||
"type": "solar_pv",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": [],
|
||
"photo_supply": coverage
|
||
}
|
||
)
|
||
pitched_roof_solar.append(solar_simulation_pitched)
|
||
|
||
if not flat_roof_no_solar.empty:
|
||
solar_simulation_flat = Property.create_recommendation_scoring_data(
|
||
property_id=flat_roof_no_solar["uprn"].values[0],
|
||
recommendation_record=flat_roof_no_solar.copy().to_dict("records")[0],
|
||
recommendation={
|
||
"recommendation_id": f"flat_solar_pv_coverage_{coverage}_percent_{config_hash}",
|
||
"type": "solar_pv",
|
||
"new_u_value": None, # This doesn't matter at the moment
|
||
"parts": [],
|
||
"photo_supply": coverage
|
||
}
|
||
)
|
||
flat_roof_solar.append(solar_simulation_flat)
|
||
|
||
# We store all of this data in s3, as it is
|
||
save_data_to_s3(
|
||
bucket_name="retrofit-datalake-dev",
|
||
s3_file_name="sap_change_model/simulation-pipeline-data.json",
|
||
data=json.dumps(
|
||
{
|
||
"loft_insulation_testing_data": loft_insulation_testing_data,
|
||
"solid_wall_testing_data": solid_wall_testing_data,
|
||
"cavity_wall_testing_data": cavity_wall_testing_data,
|
||
"solid_floor_testing_data": solid_floor_testing_data,
|
||
"suspended_floor_testing_data": suspended_floor_testing_data,
|
||
"single_glazed_testing_data": single_glazed_testing_data,
|
||
"partial_double_glazed_testing_data": partial_double_glazed_testing_data,
|
||
"partial_secondary_glazed_testing_data": partial_secondary_glazed_testing_data,
|
||
"pitched_roof_solar": pitched_roof_solar,
|
||
"flat_roof_solar": flat_roof_solar
|
||
}
|
||
)
|
||
)
|
||
|
||
# For each simulation type, we score against the model
|
||
from backend.ml_models.api import ModelApi
|
||
from datetime import datetime
|
||
|
||
created_at = datetime.now().isoformat()
|
||
model_api = ModelApi(portfolio_id="simulation-testing-pipeline", timestamp=created_at)
|
||
model_api.MODEL_PREFIXES = ["sap_change_predictions"]
|
||
|
||
# 1) Loft insulation
|
||
# We chunk up the data into 200 rows
|
||
loft_insulation_testing_df = pd.DataFrame(loft_insulation_testing_data)
|
||
|
||
loft_insulation_predictions = []
|
||
loft_to_loop_over = range(0, loft_insulation_testing_df.shape[0], 200)
|
||
for chunk in tqdm(loft_to_loop_over, total=len(loft_to_loop_over)):
|
||
loft_insulation_predictions_dict = model_api.predict_all(
|
||
df=loft_insulation_testing_df.iloc[chunk:chunk + 200],
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
loft_insulation_predictions.append(loft_insulation_predictions_dict["sap_change_predictions"])
|
||
|
||
loft_insulation_predictions = pd.concat(loft_insulation_predictions)
|
||
# Store final parquet in s3
|
||
save_dataframe_to_s3_parquet(
|
||
df=loft_insulation_predictions,
|
||
bucket_name="retrofit-datalake-dev",
|
||
file_key=f"sap_change_model/simulation-pipeline-loft-insulation-predictions_{MODEL_VERSION}.parquet"
|
||
)
|
||
|
||
# We now merge the loft insulation predictions onto the scoring data and calculate exactly how much the insulation
|
||
# is worth
|
||
|
||
loft_insulation_comparison_matrix = loft_insulation_testing_df[
|
||
["simulation_starting_insulation_thickness", "simulation_ending_insulation_thickness", "uprn", "id",
|
||
"sap_starting"]
|
||
].merge(
|
||
loft_insulation_predictions.drop(columns=["recommendation_id"]),
|
||
left_on="id",
|
||
right_on="id",
|
||
how="left"
|
||
)
|
||
|
||
loft_insulation_comparison_matrix["measure_impact"] = loft_insulation_comparison_matrix["predictions"] - \
|
||
loft_insulation_comparison_matrix["sap_starting"]
|
||
|
||
# We create a sap band grouping, for every 10 points of sap. So 1-10, 11-20, 21-30 etc
|
||
loft_insulation_comparison_matrix["sap_band"] = pd.cut(
|
||
loft_insulation_comparison_matrix["sap_starting"],
|
||
bins=range(0, 101, 10),
|
||
labels=range(1, 11)
|
||
)
|
||
|
||
# Perform a group by describe
|
||
loft_insulation_describe = loft_insulation_comparison_matrix.groupby(
|
||
["sap_band", "simulation_starting_insulation_thickness", "simulation_ending_insulation_thickness"]
|
||
)[["measure_impact"]].describe().reset_index()
|
||
|
||
for col in ["simulation_starting_insulation_thickness", "simulation_ending_insulation_thickness"]:
|
||
loft_insulation_describe[col] = loft_insulation_describe[col].str.replace('none', "0")
|
||
loft_insulation_describe[col] = loft_insulation_describe[col].astype(int)
|
||
|
||
loft_insulation_describe = loft_insulation_describe.sort_values(
|
||
["simulation_ending_insulation_thickness", "simulation_starting_insulation_thickness"], ascending=True
|
||
)
|
||
|
||
# In the training data, try and get just the rows that are loft insulation only
|
||
# Things that change:
|
||
# 1) roof_insulation_thickness
|
||
# 3) roof_thermal_transmittance
|
||
# 4) roof_energy_eff_ending
|
||
loft_insulation_training_data = dataset.copy()
|
||
loft_insulation_columns_we_need_the_same = [c for c in column_config.keys() if c not in [
|
||
"roof_insulation_thickness_ending", "roof_thermal_transmittance_ending", "roof_energy_eff_ending",
|
||
"transaction_type_ending", "days_to_ending", "sap_ending", "heat_demand_ending", "carbon_ending",
|
||
"total_floor_area_ending", "floor_height_ending", "estimated_perimeter_ending"
|
||
]]
|
||
|
||
for ending_col in tqdm(loft_insulation_columns_we_need_the_same):
|
||
starting_col = column_config[ending_col]
|
||
loft_insulation_training_data = loft_insulation_training_data[
|
||
loft_insulation_training_data[ending_col] == loft_insulation_training_data[starting_col]
|
||
]
|
||
|
||
# We get rows where the insulation starts at 200mm
|
||
insulation_200mm_starting = loft_insulation_training_data[
|
||
(loft_insulation_training_data["roof_insulation_thickness"] == "200") &
|
||
(loft_insulation_training_data["roof_insulation_thickness_ending"] == "300")
|
||
]
|
||
|
||
# Let's use the API to find exactly the record
|
||
from backend.SearchEpc import SearchEpc
|
||
|
||
testing_model_api = ModelApi(portfolio_id="simulation-testing-loft-example", timestamp=created_at)
|
||
testing_model_api.MODEL_PREFIXES = ["sap_change_predictions"]
|
||
|
||
############################################################################################################
|
||
# TODO:!
|
||
# Findings:
|
||
# 1) For uprn 10009320092, the number of rooms and number of heated rooms has changed and can change from
|
||
# epc to epc. We should therefore include a starting and ending value for this
|
||
# 2) Maybe we should include tenure??? Owner occupied homes are going to be a lot more unusual. Both investigation
|
||
# 2 and 3 were owner occupied
|
||
# 3) Maybe we should treat photo_supply missing differently than 0?
|
||
|
||
################################################################################################
|
||
# Investigation 1)
|
||
|
||
searcher = SearchEpc(
|
||
address1="2 Darkfield Way",
|
||
postcode="TA7 8HY",
|
||
auth_token="a2Nvbm5rb3dsZXNzYXJAZ21haWwuY29tOjY5MGJiMWM0NmIyOGI5ZDUxYzAxMzQzYzNiZGNlZGJjZDNmODQwMzA=",
|
||
os_api_key=""
|
||
)
|
||
searcher.uprn = "10009320092"
|
||
searcher.find_property(skip_os=True)
|
||
|
||
newest_epc = searcher.newest_epc
|
||
older_epc = [epc for epc in searcher.older_epcs if
|
||
epc["lmk-key"] == "5ae2f073004839510f9eeb1886160776a05697f8518b8b3b63d45f65686c4757"][0]
|
||
# Iterate through the keys in the newest_epc and find the values in older epc that are different to the newest epc
|
||
|
||
differences = {}
|
||
for k, v in newest_epc.items():
|
||
if v != older_epc[k]:
|
||
differences[k] = (v, older_epc[k])
|
||
|
||
testing_row = insulation_200mm_starting[insulation_200mm_starting["uprn"] == "10009320092"].copy()
|
||
testing_row["id"] = "testing-200mm-loft-insulation-starting-baseline+recommendation_id_baseline"
|
||
testing_row["recommendation_id"] = "recommendation_id_baseline"
|
||
# The testing row has 4 rooms
|
||
# Score in the model to see what we get
|
||
|
||
baseline_prediction = testing_model_api.predict_all(
|
||
df=testing_row,
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
baseline_pred_df = baseline_prediction["sap_change_predictions"]
|
||
impact = baseline_pred_df["predictions"].values[0] - testing_row["sap_starting"].values[0]
|
||
|
||
# Changing this from 4 rooms to 5 rooms has NO impact!!
|
||
testing_row_5_rooms = testing_row.copy()
|
||
testing_row_5_rooms["id"] = "testing-200mm-loft-insulation-starting-baseline+recommendation_id_5_rooms"
|
||
testing_row_5_rooms["recommendation_id"] = "recommendation_id_5_rooms"
|
||
testing_row_5_rooms["number_habitable_rooms"] = float(5)
|
||
testing_row_5_rooms["number_heated_rooms"] = float(5)
|
||
|
||
prediction_5_rooms = testing_model_api.predict_all(
|
||
df=testing_row_5_rooms,
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
pred_df_5_rooms = prediction_5_rooms["sap_change_predictions"]
|
||
impact_5_rooms = pred_df_5_rooms["predictions"].values[0] - testing_row_5_rooms["sap_starting"].values[0]
|
||
|
||
################################################################################################
|
||
# Investigation 2
|
||
|
||
searcher = SearchEpc(
|
||
address1="19 Rossal Place",
|
||
postcode="MK12 6JE",
|
||
auth_token="a2Nvbm5rb3dsZXNzYXJAZ21haWwuY29tOjY5MGJiMWM0NmIyOGI5ZDUxYzAxMzQzYzNiZGNlZGJjZDNmODQwMzA=",
|
||
os_api_key=""
|
||
)
|
||
searcher.uprn = "25006966"
|
||
searcher.find_property(skip_os=True)
|
||
|
||
newest_epc = searcher.newest_epc
|
||
older_epc = [epc for epc in searcher.older_epcs if
|
||
epc["lmk-key"] == "fe23917ac59fbf3a608c76431941011ab4c7938546a432fc6212182caab31d73"][0]
|
||
# Iterate through the keys in the newest_epc and find the values in older epc that are different to the newest epc
|
||
|
||
differences = {}
|
||
for k, v in newest_epc.items():
|
||
if v != older_epc[k]:
|
||
differences[k] = (v, older_epc[k])
|
||
|
||
testing_row2 = insulation_200mm_starting[insulation_200mm_starting["uprn"] == "25006966"].copy()
|
||
# THERE IS NOTHING CLEAR THAT IS CHANGING IN THIS RECORD THAT INDICATES SUGGESTS WE'RE MISSING INFORMATION
|
||
|
||
################################################################################################
|
||
# Investigation 3
|
||
|
||
insulation_200mm_starting[
|
||
insulation_200mm_starting["rdsap_change"] == insulation_200mm_starting["rdsap_change"].max()
|
||
]["uprn"].values[0]
|
||
# This UPRN: 100060350521
|
||
|
||
searcher = SearchEpc(
|
||
address1="138 Nicholas Crescent",
|
||
postcode="PO15 5AN",
|
||
auth_token="a2Nvbm5rb3dsZXNzYXJAZ21haWwuY29tOjY5MGJiMWM0NmIyOGI5ZDUxYzAxMzQzYzNiZGNlZGJjZDNmODQwMzA=",
|
||
os_api_key=""
|
||
)
|
||
searcher.uprn = "100060350521"
|
||
searcher.find_property(skip_os=True)
|
||
|
||
newest_epc = searcher.newest_epc
|
||
older_epc = [epc for epc in searcher.older_epcs if
|
||
epc["lmk-key"] == "9c4059762189b451191c98d2ef980a5364b8b7e0be3f064f681abcd4a0da681b"][0]
|
||
# Iterate through the keys in the newest_epc and find the values in older epc that are different to the newest epc
|
||
|
||
differences = {}
|
||
for k, v in newest_epc.items():
|
||
if v != older_epc[k]:
|
||
differences[k] = (v, older_epc[k])
|
||
|
||
# Nothing looks amiss about this record - let's score it in the model
|
||
testing_row_3 = insulation_200mm_starting[insulation_200mm_starting["uprn"] == "100060350521"].copy()
|
||
|
||
testing_row_3["id"] = "testing-200mm-loft-insulation-starting-baseline+recommendation_id_baseline"
|
||
testing_row_3["recommendation_id"] = "recommendation_id_baseline"
|
||
# The testing row has 4 rooms
|
||
# Score in the model to see what we get
|
||
|
||
baseline_prediction3 = testing_model_api.predict_all(
|
||
df=testing_row_3,
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
baseline_pred_df3 = baseline_prediction3["sap_change_predictions"]
|
||
impact3 = baseline_pred_df3["predictions"].values[0] - testing_row_3["sap_starting"].values[0]
|
||
|
||
# TODO: Look at some of the example properties we have, and test using the model to score the impact of the
|
||
# different measures when multiple measures are scored together e.g. cavity + loft together vs individually
|
||
|
||
# Look at performance on loft only rows
|
||
loft_insulation_training_data["id"] = (loft_insulation_training_data["uprn"] +
|
||
"_loft_insulation + recommendation_id_placeholder")
|
||
|
||
loft_only_predictions = []
|
||
loft_to_loop_over = range(0, loft_insulation_training_data.shape[0], 400)
|
||
for chunk in tqdm(loft_to_loop_over, total=len(loft_to_loop_over)):
|
||
loft_insulation_predictions_dict = model_api.predict_all(
|
||
df=loft_insulation_training_data.iloc[chunk:chunk + 400],
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
loft_only_predictions.append(loft_insulation_predictions_dict["sap_change_predictions"])
|
||
|
||
loft_only_predictions = pd.concat(loft_only_predictions)
|
||
|
||
def calculate_mape(actuals, predictions):
|
||
"""
|
||
Calculate the Mean Absolute Percentage Error (MAPE).
|
||
|
||
Parameters:
|
||
- actuals: A list or array of actual values.
|
||
- predictions: A list or array of predicted values, corresponding to actuals.
|
||
|
||
Returns:
|
||
- mape: The MAPE score as a float.
|
||
|
||
Note: This function assumes actuals and predictions are of the same length and
|
||
does not contain zeros in the actuals (to avoid division by zero).
|
||
"""
|
||
# Convert inputs to numpy arrays for vectorized operations
|
||
import numpy as np
|
||
actuals = np.array(actuals)
|
||
predictions = np.array(predictions)
|
||
|
||
# Calculate the absolute percentage errors
|
||
ape = np.abs((actuals - predictions) / actuals) * 100
|
||
|
||
# Calculate the mean of these percentage errors
|
||
mape = np.mean(ape)
|
||
|
||
return mape
|
||
|
||
calculate_mape(actuals=loft_insulation_training_data["sap_ending"],
|
||
predictions=loft_only_predictions["predictions"])
|
||
|
||
comparison_df = pd.DataFrame(
|
||
{
|
||
"sap_starting": loft_insulation_training_data["sap_starting"].values,
|
||
"actual_sap_ending": loft_insulation_training_data["sap_ending"].values,
|
||
"predicted_sap_ending": loft_only_predictions["predictions"].values
|
||
}
|
||
)
|
||
|
||
comparison_df["residual"] = abs(comparison_df["actual_sap_ending"] - comparison_df["predicted_sap_ending"])
|
||
comparison_df["residual"].describe()
|
||
|
||
comparison_df[comparison_df["residual"] == comparison_df["residual"].max()]
|
||
|
||
# TODO: Test scoring separately vs combined
|
||
from etl.epc.Record import EPCRecord
|
||
from etl.solar.SolarPhotoSupply import SolarPhotoSupply
|
||
from utils.s3 import read_from_s3
|
||
import msgpack
|
||
from recommendations.Recommendations import Recommendations
|
||
import datetime
|
||
from numpy import nan
|
||
cleaning_data = read_dataframe_from_s3_parquet(
|
||
bucket_name="retrofit-data-dev", file_key="sap_change_model/cleaning_dataset.parquet",
|
||
)
|
||
uprn_filenames = read_dataframe_from_s3_parquet(
|
||
bucket_name="retrofit-data-dev", file_key="spatial/filename_meta.parquet"
|
||
)
|
||
photo_supply_lookup, floor_area_decile_thresholds = SolarPhotoSupply.load(bucket="retrofit-data-dev")
|
||
cleaned = read_from_s3(
|
||
s3_file_name="cleaned_epc_data/cleaned.bson",
|
||
bucket_name="retrofit-data-dev".format(environment="retrofit-data-dev")
|
||
)
|
||
cleaned = msgpack.unpackb(cleaned, raw=False)
|
||
materials = [
|
||
{'id': 17, 'type': 'mechanical_ventilation', 'description': 'Mechanical Extract Ventilation', 'depth': None,
|
||
'depth_unit': None, 'cost': 500, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': None, 'r_value_unit': None,
|
||
'thermal_conductivity': None, 'thermal_conductivity_unit': None, 'link': None,
|
||
'created_at': datetime.datetime(2023, 10, 18, 16, 39, 9, 827188), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': None, 'labour_cost': None, 'labour_hours_per_unit': None,
|
||
'plant_cost': None, 'total_cost': None, 'notes': None},
|
||
{'id': 1221, 'type': 'flat_roof_preparation', 'description': 'clean surface to receive new damp-proof membrane',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 4.36, 'labour_hours_per_unit': 0.14,
|
||
'plant_cost': 0.0, 'total_cost': 4.36,
|
||
'notes': 'This data is based on concrete however forms a decent baseline for a Bituminous Felt flat roof'},
|
||
{'id': 1223, 'type': 'flat_roof_preparation',
|
||
'description': 'One coat primer; on wood surfaces before fixing; General surfaces; over 300 mm girth',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 2.49, 'labour_cost': 1.5, 'labour_hours_per_unit': 0.08,
|
||
'plant_cost': 0.0, 'total_cost': 3.99, 'notes': 'SPONs data gives us a baseline for a wood surface'},
|
||
{'id': 1224, 'type': 'flat_roof_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, 'labour_hours_per_unit': 0.02,
|
||
'plant_cost': 0.0, 'total_cost': 1.69, 'notes': None},
|
||
{'id': 1226, 'type': 'flat_roof_insulation', 'description': 'Ravatherm XPS × 500 SL', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.03125,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.032,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 22.14, 'labour_cost': 10.66, 'labour_hours_per_unit': 0.48,
|
||
'plant_cost': 0.0, 'total_cost': 32.8, 'notes': None},
|
||
{'id': 1227, 'type': 'flat_roof_insulation', 'description': 'Ravatherm XPS × 500 SL', 'depth': 120.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.03125,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.032,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://www.panelsystems.co.uk/product/floormate-ravatherm-sb?attribute_pa_group=floormate-500a'
|
||
'&attribute_pa_product-name=ravatherm-xps-x-500-sl&attribute_pa_length=1250&attribute_pa_width=600'
|
||
'&attribute_pa_thickness=120&attribute_pa_unit-of-sale=pack-3-brds&attribute_pa_min-order-qty=10'
|
||
'&gclid=CjwKCAiAjrarBhAWEiwA2qWdCKJK2iqlzUZ-mBFOfCLy2f5TldAbOj7G3LrvYw5JLaigplJAajzYpRoCtB8QAvD_BwE',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 26.187656, 'labour_cost': 10.66, 'labour_hours_per_unit': 0.48,
|
||
'plant_cost': 0.0, 'total_cost': 36.847656,
|
||
'notes': "SPONs didn't have this thickness, so the material price is based on the fact that on the link, "
|
||
"the 120mm thickness is 18% more expensive per board than the 100mm thickness"},
|
||
{'id': 1228, 'type': 'flat_roof_insulation', 'description': 'Ravatherm XPS × 500 SL', 'depth': 140.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.03125,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.032,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://www.panelsystems.co.uk/product/floormate-ravatherm-sb?attribute_pa_group=floormate-500a'
|
||
'&attribute_pa_product-name=ravatherm-xps-x-500-sl&attribute_pa_length=1250&attribute_pa_width=600'
|
||
'&attribute_pa_thickness=120&attribute_pa_unit-of-sale=pack-3-brds&attribute_pa_min-order-qty=10'
|
||
'&gclid=CjwKCAiAjrarBhAWEiwA2qWdCKJK2iqlzUZ-mBFOfCLy2f5TldAbOj7G3LrvYw5JLaigplJAajzYpRoCtB8QAvD_BwE',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 31.114737, 'labour_cost': 10.66, 'labour_hours_per_unit': 0.48,
|
||
'plant_cost': 0.0, 'total_cost': 41.77474,
|
||
'notes': "SPONs didn't have this thickness, so the material price is based on the fact that on the link, "
|
||
"the 140mm thickness is 40% more expensive per board than the 100mm thickness"},
|
||
{'id': 1229, 'type': 'flat_roof_insulation', 'description': 'Foamglas T3+ Flat Roof Insulation', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.027777778,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.036,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': 95.83, 'material_cost': 109.09, 'labour_cost': 30.7, 'labour_hours_per_unit': 1.3,
|
||
'plant_cost': 0.0, 'total_cost': 139.79, 'notes': None},
|
||
{'id': 1230, 'type': 'flat_roof_insulation', 'description': 'Foamglas T4+ Flat Roof Insulation', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.024390243,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.041,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': 63.89, 'material_cost': 76.19, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 104.53, 'notes': None}, {'id': 1231, 'type': 'flat_roof_insulation',
|
||
'description': 'Ecotherm Eco-Versal General '
|
||
'Purpose Insulation Board',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1,
|
||
49, 298076),
|
||
'is_active': True, 'prime_material_cost': 15.12,
|
||
'material_cost': 25.96, 'labour_cost': 30.7,
|
||
'labour_hours_per_unit': 1.3, 'plant_cost': 0.0,
|
||
'total_cost': 56.66, 'notes': None},
|
||
{'id': 1232, 'type': 'flat_roof_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose Insulation Board', 'depth': 120.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': 20.16, 'material_cost': 34.613335, 'labour_cost': 30.7, 'labour_hours_per_unit': 1.3,
|
||
'plant_cost': 0.0, 'total_cost': 65.31333,
|
||
'notes': "SPONs didn't have this thickness, so the material price is based on the fact that on the link, "
|
||
"the 120mm thickness is 33% more expensive than the 100mm thickness"},
|
||
{'id': 1233, 'type': 'flat_roof_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose Insulation Board', 'depth': 150.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': 23.53, 'material_cost': 34.62, 'labour_cost': 33.06, 'labour_hours_per_unit': 1.4,
|
||
'plant_cost': 0.0, 'total_cost': 67.68, 'notes': None}, {'id': 1234, 'type': 'flat_roof_waterproofing',
|
||
'description': '20 mm thick two coat coverings; '
|
||
'felt isolating membrane; to '
|
||
'concrete (or timber) base; flat or '
|
||
'to falls or slopes not exceeding '
|
||
'10° from horizontal',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': 'gbp_per_m2', 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1,
|
||
49, 298076),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 0.0, 'labour_cost': 0.0,
|
||
'labour_hours_per_unit': 0.5, 'plant_cost': 0.0,
|
||
'total_cost': 31.13, 'notes': None},
|
||
{'id': 1225, 'type': 'flat_roof_insulation',
|
||
'description': 'Kingspan Thermaroof TR21 zero OPD urethene insulation board', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.04,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.025,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 4, 20, 1, 49, 298076), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 50.95, 'labour_cost': 10.66, 'labour_hours_per_unit': 0.48,
|
||
'plant_cost': 0.0, 'total_cost': 61.61,
|
||
'notes': "SPONs didn't have a labour hours so we use 0.48 which is similar to other materials"},
|
||
{'id': 1235, 'type': 'windows_glazing',
|
||
'description': 'uPVC windows; Profile 22 or other equal and approved; reinforced where appropriate with '
|
||
'aluminium alloy; in refurbishment work, including standard ironmongery; sills and factory '
|
||
'glazed with low-e 24 mm double glazing; removing existing windows and fixing new in '
|
||
'position; including lugs plugged and screwed to brickwork or blockwork; Casement/fixed '
|
||
'light; including vents; e.p.d.m. glazing gaskets and weather seals; 1770 mm × 1200 mm; ref '
|
||
'P312WW',
|
||
'depth': 0, 'depth_unit': None, 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': None,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 12, 20, 14, 37, 51, 728866), 'is_active': True,
|
||
'prime_material_cost': 176.55, 'material_cost': 182.25, 'labour_cost': 163.36, 'labour_hours_per_unit': 6.5,
|
||
'plant_cost': 0.0, 'total_cost': 345.61,
|
||
'notes': 'This is the cost of removal of existing windows and installation of new windows. This is a '
|
||
'casement style window, which is the most common but also the cheapest style. In the cost '
|
||
'estimation framework, we can inflate prices for different finishes, to be conservative on price. '},
|
||
{'id': 1109, 'type': 'cavity_wall_insulation',
|
||
'description': 'Expanded Polystyrene Beads cavity wall insulation', 'depth': 75.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://www.styrene.co.uk/downloads/Datasheets'
|
||
'/Stylite_Cavity_Loose_Fill_Insulation_Datasheet_v20211.pdf',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 18.875, 'labour_cost': 1.125, 'labour_hours_per_unit': 0.065,
|
||
'plant_cost': 0.0, 'total_cost': 20.0,
|
||
'notes': "It is hard to find materials online. To price this, we've used this article: "
|
||
"https://www.greenmatch.co.uk/blog/cavity-wall-insulation-cost It puts EPS beads at around £22 per "
|
||
"meter squared, blowing wool insulation at £18 per meter squared and Polyurethane Foam at £26 per "
|
||
"meter squared, when taking the most pessimistic prices. These rates have been used to adjust the "
|
||
"price of the mineral wool insulation to give us the other forms of insulation"},
|
||
{'id': 1110, 'type': 'cavity_wall_insulation',
|
||
'description': 'Injected Polyurthane Foam cavity wall insulation', 'depth': 75.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://www.foaminstall.co.uk/wp-content/uploads/2017/04/Lapolla-Cavity-Fill-BBA-certificate-sheet1'
|
||
'.pdf',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 22.875, 'labour_cost': 1.125, 'labour_hours_per_unit': 0.065,
|
||
'plant_cost': 0.0, 'total_cost': 24.0, 'notes': None},
|
||
{'id': 1111, 'type': 'loft_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 2.03, 'material_cost': 2.1, 'labour_cost': 1.56, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 3.66, 'notes': None},
|
||
{'id': 1112, 'type': 'loft_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll', 'depth': 150.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 3.06, 'material_cost': 3.16, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1,
|
||
'plant_cost': 0.0, 'total_cost': 4.94, 'notes': None},
|
||
{'id': 1113, 'type': 'loft_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll', 'depth': 170.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://insulation4less.co.uk/products/knauf-170mm-combi-cut?variant=31671561257013&dfw_tracker'
|
||
'=77750-31671561257013&utm_source=google&utm_medium=shopping&utm_campaign=shoptimised&gad_source=1'
|
||
'&gclid=CjwKCAiAx_GqBhBQEiwAlDNAZi1LiTWKVn0W1vktOYAPPQU3hss5Tq2qNn6GNhodCQoRD_tvqCLdxhoCKnIQAvD_BwE',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 3.81938, 'labour_cost': 1.71304, 'labour_hours_per_unit': 0.11,
|
||
'plant_cost': 0.0, 'total_cost': 5.53242,
|
||
'notes': "We don't have a 170mm in SPONs so the material cost is based on the fact that the 170mm insulation "
|
||
"is 87.4% of the cost of the 200mm insulation"},
|
||
{'id': 1114, 'type': 'loft_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll', 'depth': 200.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 4.25, 'material_cost': 4.37, 'labour_cost': 1.96, 'labour_hours_per_unit': 0.11,
|
||
'plant_cost': 0.0, 'total_cost': 6.33, 'notes': None},
|
||
{'id': 1115, 'type': 'loft_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll', 'depth': 270.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 5.91938, 'labour_cost': 1.96, 'labour_hours_per_unit': 0.11,
|
||
'plant_cost': 0.0, 'total_cost': 7.87938, 'notes': 'This is the 100mm product + the 170mm product'},
|
||
{'id': 1116, 'type': 'loft_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll', 'depth': 300.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 6.47, 'labour_cost': 1.96, 'labour_hours_per_unit': 0.11,
|
||
'plant_cost': 0.0, 'total_cost': 8.43, 'notes': 'This is the 100mm product + the 200mm product'},
|
||
{'id': 1117, 'type': 'loft_insulation', 'description': 'Isover Mineral Wool Modular Roll', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 1.99, 'material_cost': 2.05, 'labour_cost': 1.6, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 3.65, 'notes': None},
|
||
{'id': 1118, 'type': 'loft_insulation', 'description': 'Isover Mineral Wool Modular Roll', 'depth': 150.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 2.96, 'material_cost': 3.05, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1,
|
||
'plant_cost': 0.0, 'total_cost': 4.83, 'notes': None},
|
||
{'id': 1119, 'type': 'loft_insulation', 'description': 'Isover Mineral Wool Modular Roll', 'depth': 170.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://flooringwarehousedirect.co.uk/product/isover-spacesaver-roll-170mm-x-1160mm-x-7-03m-8-15m2/',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 3.8706238, 'labour_cost': 2.281361,
|
||
'labour_hours_per_unit': 0.12816635, 'plant_cost': 0.0, 'total_cost': 6.1519847,
|
||
'notes': "We don't have a 170mm in SPONs so the material cost is based on the fact that the 170mm insulation "
|
||
"is 85.4% of the cost of the 200mm insulation"},
|
||
{'id': 1120, 'type': 'loft_insulation', 'description': 'Isover Mineral Wool Modular Roll', 'depth': 200.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 4.4, 'material_cost': 4.53, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 7.2, 'notes': None},
|
||
{'id': 1121, 'type': 'loft_insulation', 'description': 'Isover Mineral Wool Modular Roll', 'depth': 270.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 5.920624, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 8.590624, 'notes': 'This is the 100mm product + the 170mm product'},
|
||
{'id': 1122, 'type': 'loft_insulation', 'description': 'Isover Mineral Wool Modular Roll', 'depth': 300.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 6.58, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 9.25, 'notes': 'This is the 100mm product + the 200mm product'},
|
||
{'id': 1123, 'type': 'loft_insulation', 'description': 'Isover Acoustic Partition Roll', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 5.93, 'material_cost': 6.4, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 9.07, 'notes': 'This provides acoustic insulation as well'},
|
||
{'id': 1124, 'type': 'loft_insulation', 'description': 'Isover Acoustic Partition Roll', 'depth': 300.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 17.79, 'material_cost': 19.2, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 21.87, 'notes': 'This provides acoustic insulation as well'},
|
||
{'id': 1125, 'type': 'loft_insulation', 'description': 'Thermafleece EcoRoll Insulation', 'depth': 300.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 24.78, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 27.45,
|
||
'notes': 'This material is based on installing 3 layers of the 100mm product'},
|
||
{'id': 1126, 'type': 'loft_insulation', 'description': 'Thermafleece EcoRoll Insulation', 'depth': 280.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 23.36, 'labour_cost': 3.12, 'labour_hours_per_unit': 0.18,
|
||
'plant_cost': 0.0, 'total_cost': 26.48,
|
||
'notes': 'This material is based on installed 2 layers of the 140mm product'},
|
||
{'id': 1127, 'type': 'iwi_wall_demolition',
|
||
'description': 'Solid & Dry Lined walls: Hack of wall finishes with chipping hammer; plaster to walls.',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 10.27, 'labour_hours_per_unit': 0.33,
|
||
'plant_cost': 1.28, 'total_cost': 11.55, 'notes': None}, {'id': 1128, 'type': 'iwi_wall_demolition',
|
||
'description': 'Stud walls: Remove wall linings '
|
||
'including battening behind; '
|
||
'plasterboard and skim',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': 'gbp_per_m2', 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 0.0, 'labour_cost': 6.23,
|
||
'labour_hours_per_unit': 0.2, 'plant_cost': 1.25,
|
||
'total_cost': 7.48, 'notes': None},
|
||
{'id': 1129, 'type': 'iwi_wall_demolition',
|
||
'description': 'Lathe and Plaster walls: Remove wall linings including battening behind; wood lath and '
|
||
'plaster',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 6.85, 'labour_hours_per_unit': 0.22,
|
||
'plant_cost': 2.09, 'total_cost': 8.94, 'notes': None},
|
||
{'id': 1130, 'type': 'internal_wall_insulation', 'description': 'Foamglas Grade F Wall Insulation Slabs',
|
||
'depth': 60.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.02631579,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.038,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 41.69, 'material_cost': 53.33, 'labour_cost': 29.52, 'labour_hours_per_unit': 1.25,
|
||
'plant_cost': 0.0, 'total_cost': 82.85, 'notes': None},
|
||
{'id': 1131, 'type': 'internal_wall_insulation', 'description': 'Foamglas Grade F Wall Insulation Slabs',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.02631579,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.038,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 86.86, 'material_cost': 99.85, 'labour_cost': 29.52, 'labour_hours_per_unit': 1.25,
|
||
'plant_cost': 0.0, 'total_cost': 129.37, 'notes': None},
|
||
{'id': 1132, 'type': 'internal_wall_insulation', 'description': 'Foamglas Grade F Wall Insulation Slabs',
|
||
'depth': 150.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.02631579,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.038,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 130.29, 'material_cost': 144.58, 'labour_cost': 29.52, 'labour_hours_per_unit': 1.25,
|
||
'plant_cost': 0.0, 'total_cost': 174.1, 'notes': None},
|
||
{'id': 1133, 'type': 'internal_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board',
|
||
'depth': 30.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 6.16, 'material_cost': 16.73, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 45.07, 'notes': None},
|
||
{'id': 1134, 'type': 'internal_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 8.46, 'material_cost': 19.1, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 47.44, 'notes': None},
|
||
{'id': 1135, 'type': 'internal_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 15.12, 'material_cost': 25.96, 'labour_cost': 30.7, 'labour_hours_per_unit': 1.3,
|
||
'plant_cost': 0.0, 'total_cost': 56.66, 'notes': None},
|
||
{'id': 1136, 'type': 'internal_wall_insulation', 'description': 'Kingspan Kooltherm K18 insulated plasterboard',
|
||
'depth': 37.5, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.04761905,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.021,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 26.86, 'labour_cost': 5.21, 'labour_hours_per_unit': 0.23,
|
||
'plant_cost': 0.0, 'total_cost': 32.07, 'notes': None},
|
||
{'id': 1137, 'type': 'internal_wall_insulation', 'description': 'Kingspan Kooltherm K18 insulated plasterboard',
|
||
'depth': 42.5, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.04761905,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.021,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 17.37, 'labour_cost': 5.21, 'labour_hours_per_unit': 0.23,
|
||
'plant_cost': 0.0, 'total_cost': 22.58, 'notes': None},
|
||
{'id': 1138, 'type': 'internal_wall_insulation', 'description': 'Kingspan Kooltherm K18 insulated plasterboard',
|
||
'depth': 52.5, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.04761905,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.021,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 21.74, 'labour_cost': 5.79, 'labour_hours_per_unit': 0.25,
|
||
'plant_cost': 0.0, 'total_cost': 27.53, 'notes': None},
|
||
{'id': 1139, 'type': 'internal_wall_insulation', 'description': 'Kingspan Kooltherm K18 insulated plasterboard',
|
||
'depth': 62.5, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.04761905,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.021,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 19.3, 'labour_cost': 5.79, 'labour_hours_per_unit': 0.25,
|
||
'plant_cost': 0.0, 'total_cost': 25.09, 'notes': None},
|
||
{'id': 1140, 'type': 'internal_wall_insulation', 'description': 'Kingspan Kooltherm K18 insulated plasterboard',
|
||
'depth': 72.5, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.04761905,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.021,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 23.15, 'labour_cost': 5.79, 'labour_hours_per_unit': 0.25,
|
||
'plant_cost': 0.0, 'total_cost': 28.94, 'notes': None},
|
||
{'id': 1141, 'type': 'iwi_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, 'labour_hours_per_unit': 0.02,
|
||
'plant_cost': 0.0, 'total_cost': 1.69, 'notes': None}, {'id': 1142, 'type': 'iwi_redecoration',
|
||
'description': 'Plaster; one coat Thistle board '
|
||
'finish or other equal; steel '
|
||
'trowelled; 3 mm thick work to walls '
|
||
'or ceilings; one coat; to '
|
||
'plasterboard base; over 600mm wide',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 0.06, 'labour_cost': 6.58,
|
||
'labour_hours_per_unit': 0.25, 'plant_cost': 0.0,
|
||
'total_cost': 6.64, 'notes': None},
|
||
{'id': 1143, 'type': 'iwi_redecoration',
|
||
'description': 'Two coats emulsion paint on plaster, over 40mm girth; 3.5m - 5m high', 'depth': 0.0,
|
||
'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.41, 'labour_cost': 3.93, 'labour_hours_per_unit': 0.21,
|
||
'plant_cost': 0.0, 'total_cost': 4.34, 'notes': None}, {'id': 1144, 'type': 'iwi_redecoration',
|
||
'description': 'Fitting existing softwood skirting '
|
||
'or architrave to new frames; 150mm '
|
||
'high',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 0.01, 'labour_cost': 4.87,
|
||
'labour_hours_per_unit': 0.12, 'plant_cost': 0.0,
|
||
'total_cost': 4.88, 'notes': None},
|
||
{'id': 1145, 'type': 'suspended_floor_demolition', 'description': 'Removal of carpet and underfelt',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 3.32, 'labour_hours_per_unit': 0.11,
|
||
'plant_cost': 0.0, 'total_cost': 3.32,
|
||
'notes': 'We ignore the plant cost that is in SPONs because we assume the carpet is not scrapped and '
|
||
'therefore there is no need for a skip'},
|
||
{'id': 1146, 'type': 'suspended_floor_demolition',
|
||
'description': 'Remove boarding; withdraw nails; set aside for reuse; ground level', 'depth': 0.0,
|
||
'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 9.34, 'labour_hours_per_unit': 0.3,
|
||
'plant_cost': 0.0, 'total_cost': 9.34, 'notes': None}, {'id': 1147, 'type': 'suspended_floor_vapour_barrier',
|
||
'description': 'Visqueen High Performance Vapour '
|
||
'Barrier',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': 0.58,
|
||
'material_cost': 1.21, 'labour_cost': 0.48,
|
||
'labour_hours_per_unit': 0.02, 'plant_cost': 0.0,
|
||
'total_cost': 1.69, 'notes': None},
|
||
{'id': 1148, 'type': 'suspended_floor_insulation', 'description': 'Thermafleece CosyWool Roll', 'depth': 50.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 4.24, 'labour_cost': 1.56, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 5.8,
|
||
'notes': 'Spons did not contain labour costs so we use values for similar insulations. We use the same '
|
||
'values as in Crown loft roll 44, since it is also an insulation roll'},
|
||
{'id': 1149, 'type': 'suspended_floor_insulation', 'description': 'Thermafleece CosyWool Roll', 'depth': 75.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 6.31, 'labour_cost': 1.56, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 7.87,
|
||
'notes': 'Spons did not contain labour costs so we use values for similar insulations. We use the same '
|
||
'values as in Crown loft roll 44, since it is also an insulation roll'},
|
||
{'id': 1150, 'type': 'suspended_floor_insulation', 'description': 'Thermafleece CosyWool Roll', 'depth': 100.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 8.26, 'labour_cost': 1.56, 'labour_hours_per_unit': 0.1,
|
||
'plant_cost': 0.0, 'total_cost': 9.82,
|
||
'notes': 'Spons did not contain labour costs so we use values for similar insulations. We use the same '
|
||
'values as in Crown loft roll 44, since it is also an insulation roll'},
|
||
{'id': 1151, 'type': 'suspended_floor_insulation', 'description': 'Thermafleece CosyWool Roll', 'depth': 140.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 11.68, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1,
|
||
'plant_cost': 0.0, 'total_cost': 13.46,
|
||
'notes': 'Spons did not contain labour costs so we use values for similar insulations. We use the same '
|
||
'values as in Crown loft roll 44, since it is also an insulation roll'},
|
||
{'id': 1152, 'type': 'suspended_floor_insulation',
|
||
'description': 'Thermafleece TF35 high density wool insulating batts', 'depth': 50.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.028571429,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.035,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 6.63, 'labour_cost': 1.56, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 8.19,
|
||
'notes': 'Spons did not contain labour costs so we use values for similar insulations. We use the same '
|
||
'values as in Crown loft roll 44, since it is also an insulation roll'},
|
||
{'id': 1153, 'type': 'suspended_floor_insulation',
|
||
'description': 'Thermafleece TF35 high density wool insulating batts', 'depth': 75.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.028571429,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.035,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 10.31, 'labour_cost': 1.56, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 11.87,
|
||
'notes': 'Spons did not contain labour costs so we use values for similar insulations. We use the same '
|
||
'values as in Crown loft roll 44, since it is also an insulation roll'},
|
||
{'id': 1154, 'type': 'suspended_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose Insulation Board', 'depth': 30.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 6.16, 'material_cost': 16.73, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 45.07, 'notes': None}, {'id': 1155, 'type': 'suspended_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose '
|
||
'Insulation Board',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': 8.46,
|
||
'material_cost': 19.1, 'labour_cost': 28.34,
|
||
'labour_hours_per_unit': 1.2, 'plant_cost': 0.0,
|
||
'total_cost': 47.44, 'notes': None},
|
||
{'id': 1156, 'type': 'suspended_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose Insulation Board', 'depth': 100.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 15.12, 'material_cost': 25.96, 'labour_cost': 30.7, 'labour_hours_per_unit': 1.3,
|
||
'plant_cost': 0.0, 'total_cost': 56.66, 'notes': None}, {'id': 1157, 'type': 'suspended_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose '
|
||
'Insulation Board',
|
||
'depth': 150.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': 23.53,
|
||
'material_cost': 34.62, 'labour_cost': 33.06,
|
||
'labour_hours_per_unit': 1.4, 'plant_cost': 0.0,
|
||
'total_cost': 67.68, 'notes': None},
|
||
{'id': 1158, 'type': 'suspended_floor_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 2.03, 'material_cost': 2.1, 'labour_cost': 1.56, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 3.66, 'notes': None},
|
||
{'id': 1159, 'type': 'suspended_floor_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll',
|
||
'depth': 150.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 3.06, 'material_cost': 3.16, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1,
|
||
'plant_cost': 0.0, 'total_cost': 4.94, 'notes': None},
|
||
{'id': 1160, 'type': 'suspended_floor_insulation', 'description': 'Crown Loft Roll 44 glass fibre roll',
|
||
'depth': 200.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.022727273,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.044,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 4.25, 'material_cost': 4.37, 'labour_cost': 1.96, 'labour_hours_per_unit': 0.11,
|
||
'plant_cost': 0.0, 'total_cost': 6.33, 'notes': None},
|
||
{'id': 1161, 'type': 'suspended_floor_insulation', 'description': 'Isover Mineral Wool Modular Roll',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 1.99, 'material_cost': 2.05, 'labour_cost': 1.6, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 3.65, 'notes': None},
|
||
{'id': 1162, 'type': 'suspended_floor_insulation', 'description': 'Isover Mineral Wool Modular Roll',
|
||
'depth': 150.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 2.96, 'material_cost': 3.05, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1,
|
||
'plant_cost': 0.0, 'total_cost': 4.83, 'notes': None},
|
||
{'id': 1163, 'type': 'suspended_floor_insulation', 'description': 'Isover Mineral Wool Modular Roll',
|
||
'depth': 200.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 4.4, 'material_cost': 4.53, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 7.2, 'notes': None},
|
||
{'id': 1164, 'type': 'suspended_floor_insulation', 'description': 'Isover Acoustic Partition Roll',
|
||
'depth': 25.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 1.67, 'material_cost': 2.01, 'labour_cost': 1.43, 'labour_hours_per_unit': 0.08,
|
||
'plant_cost': 0.0, 'total_cost': 3.44, 'notes': None},
|
||
{'id': 1165, 'type': 'suspended_floor_insulation', 'description': 'Isover Acoustic Partition Roll',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.025641026,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.039,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 2.74, 'material_cost': 3.11, 'labour_cost': 1.6, 'labour_hours_per_unit': 0.09,
|
||
'plant_cost': 0.0, 'total_cost': 4.71, 'notes': None},
|
||
{'id': 1166, 'type': 'suspended_floor_insulation', 'description': 'Isover Acoustic Partition Roll',
|
||
'depth': 75.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 4.57, 'material_cost': 5.01, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1,
|
||
'plant_cost': 0.0, 'total_cost': 6.79, 'notes': None},
|
||
{'id': 1167, 'type': 'suspended_floor_insulation', 'description': 'Isover Acoustic Partition Roll',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_unit', 'r_value_per_mm': 0.023255814,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.043,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 5.93, 'material_cost': 6.4, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15,
|
||
'plant_cost': 0.0, 'total_cost': 9.07, 'notes': None},
|
||
{'id': 1168, 'type': 'suspended_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board',
|
||
'depth': 25.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 3.88, 'labour_cost': 3.24, 'labour_hours_per_unit': 0.14,
|
||
'plant_cost': 0.0, 'total_cost': 7.12, 'notes': None},
|
||
{'id': 1169, 'type': 'suspended_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 6.62, 'labour_cost': 3.71, 'labour_hours_per_unit': 0.16,
|
||
'plant_cost': 0.0, 'total_cost': 10.33, 'notes': None},
|
||
{'id': 1170, 'type': 'suspended_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board',
|
||
'depth': 75.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 9.3, 'labour_cost': 4.17, 'labour_hours_per_unit': 0.18,
|
||
'plant_cost': 0.0, 'total_cost': 13.47, 'notes': None},
|
||
{'id': 1171, 'type': 'suspended_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 12.02, 'labour_cost': 4.4, 'labour_hours_per_unit': 0.19,
|
||
'plant_cost': 0.0, 'total_cost': 16.42, 'notes': None}, {'id': 1172, 'type': 'suspended_floor_insulation',
|
||
'description': 'Kingspan Thermafloor TF70 High '
|
||
'Performance Rigid Floor Insulation',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 10.36, 'labour_cost': 4.06,
|
||
'labour_hours_per_unit': 0.18, 'plant_cost': 0.0,
|
||
'total_cost': 14.42, 'notes': None},
|
||
{'id': 1173, 'type': 'suspended_floor_insulation',
|
||
'description': 'Kingspan Thermafloor TF70 High Performance Rigid Floor Insulation', 'depth': 75.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 15.35, 'labour_cost': 4.06, 'labour_hours_per_unit': 0.18,
|
||
'plant_cost': 0.0, 'total_cost': 19.41, 'notes': None}, {'id': 1174, 'type': 'suspended_floor_insulation',
|
||
'description': 'Kingspan Thermafloor TF70 High '
|
||
'Performance Rigid Floor Insulation',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 19.17, 'labour_cost': 4.06,
|
||
'labour_hours_per_unit': 0.18, 'plant_cost': 0.0,
|
||
'total_cost': 23.23, 'notes': None},
|
||
{'id': 1175, 'type': 'suspended_floor_insulation',
|
||
'description': 'Kingspan Thermafloor TF70 High Performance Rigid Floor Insulation', 'depth': 125.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 26.59, 'labour_cost': 4.06, 'labour_hours_per_unit': 0.18,
|
||
'plant_cost': 0.0, 'total_cost': 30.65, 'notes': None}, {'id': 1176, 'type': 'suspended_floor_insulation',
|
||
'description': 'Kingspan Thermafloor TF70 High '
|
||
'Performance Rigid Floor Insulation',
|
||
'depth': 150.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 31.13, 'labour_cost': 4.64,
|
||
'labour_hours_per_unit': 0.2, 'plant_cost': 0.0,
|
||
'total_cost': 35.77, 'notes': None},
|
||
{'id': 1177, 'type': 'suspended_floor_redecoration', 'description': 'refix floorboards previously set aside',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 1.54, 'labour_cost': 24.98, 'labour_hours_per_unit': 0.74,
|
||
'plant_cost': 0.0, 'total_cost': 26.52, 'notes': None},
|
||
{'id': 1178, 'type': 'suspended_floor_redecoration', 'description': 'Fitting carpet', 'depth': 0.0,
|
||
'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 6.59, 'labour_hours_per_unit': 0.37,
|
||
'plant_cost': 0.0, 'total_cost': 6.59,
|
||
'notes': 'SPONs does not have data on re-fitting the carpet so we use the data in Fitted carpeting; Gradus '
|
||
'woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, therefore we need '
|
||
'just labour rates'},
|
||
{'id': 1179, 'type': 'solid_floor_demolition', 'description': 'Removal of carpet and underfelt', 'depth': 0.0,
|
||
'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 3.32, 'labour_hours_per_unit': 0.11,
|
||
'plant_cost': 0.0, 'total_cost': 3.32,
|
||
'notes': 'We ignore the plant cost that is in SPONs because we assume the carpet is not scrapped and '
|
||
'therefore there is no need for a skip'},
|
||
{'id': 1180, 'type': 'solid_floor_preparation',
|
||
'description': 'clean surface of concrete to receive new damp-proof membrane', 'depth': 0.0,
|
||
'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': None,
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 4.36, 'labour_hours_per_unit': 0.14,
|
||
'plant_cost': 0.0, 'total_cost': 4.36, 'notes': None}, {'id': 1181, 'type': 'solid_floor_preparation',
|
||
'description': 'Clean out crack to form a 20mm×20mm '
|
||
'groove and fill with cement: mortar '
|
||
'mixed with bonding agent',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': None,
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 6.91, 'labour_cost': 18.99,
|
||
'labour_hours_per_unit': 0.61, 'plant_cost': 0.16,
|
||
'total_cost': 26.06,
|
||
'notes': 'This step is the assessment and repair of '
|
||
'any damage to the concrete floor such as '
|
||
'filling cracks or levelling uneven areas'},
|
||
{'id': 1182, 'type': 'solid_floor_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, 'labour_hours_per_unit': 0.02,
|
||
'plant_cost': 0.0, 'total_cost': 1.69, 'notes': None},
|
||
{'id': 1183, 'type': 'solid_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board',
|
||
'depth': 25.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 3.88, 'labour_cost': 3.24, 'labour_hours_per_unit': 0.14,
|
||
'plant_cost': 0.0, 'total_cost': 7.12, 'notes': None},
|
||
{'id': 1184, 'type': 'solid_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 6.62, 'labour_cost': 3.71, 'labour_hours_per_unit': 0.16,
|
||
'plant_cost': 0.0, 'total_cost': 10.33, 'notes': None},
|
||
{'id': 1185, 'type': 'solid_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board',
|
||
'depth': 75.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.030303031,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.033,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 9.3, 'labour_cost': 4.17, 'labour_hours_per_unit': 0.18,
|
||
'plant_cost': 0.0, 'total_cost': 13.47, 'notes': None}, {'id': 1186, 'type': 'solid_floor_insulation',
|
||
'description': 'Kingspan Thermafloor TF70 High '
|
||
'Performance Rigid Floor Insulation',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 10.36, 'labour_cost': 4.06,
|
||
'labour_hours_per_unit': 0.18, 'plant_cost': 0.0,
|
||
'total_cost': 14.42, 'notes': None},
|
||
{'id': 1187, 'type': 'solid_floor_insulation',
|
||
'description': 'Kingspan Thermafloor TF70 High Performance Rigid Floor Insulation', 'depth': 75.0,
|
||
'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 15.35, 'labour_cost': 4.06, 'labour_hours_per_unit': 0.18,
|
||
'plant_cost': 0.0, 'total_cost': 19.41, 'notes': None}, {'id': 1188, 'type': 'solid_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose '
|
||
'Insulation Board',
|
||
'depth': 30.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': 6.16,
|
||
'material_cost': 16.73, 'labour_cost': 28.34,
|
||
'labour_hours_per_unit': 1.2, 'plant_cost': 0.0,
|
||
'total_cost': 45.07, 'notes': None},
|
||
{'id': 1189, 'type': 'solid_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose Insulation Board', 'depth': 50.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 8.46, 'material_cost': 19.1, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 47.44, 'notes': None}, {'id': 1190, 'type': 'solid_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose '
|
||
'Insulation Board',
|
||
'depth': 60.0, 'depth_unit': 'mm', 'cost': None,
|
||
'cost_unit': 'gbp_per_m2',
|
||
'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://londonbuildingsupplies.co.uk/products/60mm--ecotherm-eco-versal-general-purpose-pir-insulation-board---2.4m-x-1.2m-x-60mm.html',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 24.081198, 'labour_cost': 28.34,
|
||
'labour_hours_per_unit': 1.2, 'plant_cost': 0.0,
|
||
'total_cost': 52.421196,
|
||
'notes': "This material isn't in SPONs but checking"
|
||
" online, is around 92% of the cost of the"
|
||
" 100mm"},
|
||
{'id': 1191, 'type': 'solid_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose Insulation Board', 'depth': 70.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin',
|
||
'link': 'https://londonbuildingsupplies.co.uk/products/70mm--ecotherm-eco-versal-general-purpose-pir'
|
||
'-insulation-board---2.4m-x-1.2m-x-70mm.html',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 27.089088, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 55.42909,
|
||
'notes': "This material isn't in SPONs but checking online, is around 104% of the cost of the 100mm (more "
|
||
"expensive than 100mm)"},
|
||
{'id': 1192, 'type': 'solid_floor_insulation',
|
||
'description': 'Ecotherm Eco-Versal General Purpose Insulation Board', 'depth': 100.0, 'depth_unit': 'mm',
|
||
'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 15.12, 'material_cost': 25.96, 'labour_cost': 30.7, 'labour_hours_per_unit': 1.3,
|
||
'plant_cost': 0.0, 'total_cost': 56.66, 'notes': None},
|
||
{'id': 1193, 'type': 'solid_floor_insulation', 'description': 'Ravatherm XPS X 500 SL Polystyrene Foam',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.032258064,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.031,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 11.07, 'labour_cost': 10.66, 'labour_hours_per_unit': 0.46,
|
||
'plant_cost': 0.0, 'total_cost': 21.73,
|
||
'notes': "In Spons, the thermal conductivity is 0.033 however the datasheet indicates it's 0.32: "
|
||
"https://ravagobuildingsolutions.com/uk/wp-content/uploads/sites/30/2022/08/ravatherm-xps-x-500-sl"
|
||
"-tds-version-1-20210901.pdf"},
|
||
{'id': 1194, 'type': 'solid_floor_insulation', 'description': 'Ravatherm XPS X 500 SL Polystyrene Foam',
|
||
'depth': 75.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.03125,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.032,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 16.28, 'labour_cost': 10.66, 'labour_hours_per_unit': 0.46,
|
||
'plant_cost': 0.0, 'total_cost': 26.94, 'notes': None}, {'id': 1195, 'type': 'solid_floor_redecoration',
|
||
'description': 'Screeded beds; protection to '
|
||
'compressible formwork exceeding '
|
||
'600mm wide',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': 9.6,
|
||
'material_cost': 9.89, 'labour_cost': 2.67,
|
||
'labour_hours_per_unit': 0.15, 'plant_cost': 0.0,
|
||
'total_cost': 12.56,
|
||
'notes': 'This is the screed layer, placed on top '
|
||
'of the insulation'},
|
||
{'id': 1196, 'type': 'solid_floor_redecoration', 'description': 'Fitting carpet', 'depth': 0.0,
|
||
'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 6.59, 'labour_hours_per_unit': 0.37,
|
||
'plant_cost': 0.0, 'total_cost': 6.59,
|
||
'notes': 'SPONs does not have data on re-fitting the carpet so we use the data in Fitted carpeting; Gradus '
|
||
'woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, therefore we need '
|
||
'just labour rates'},
|
||
{'id': 1197, 'type': 'solid_floor_redecoration',
|
||
'description': 'Fitting existing softwood skirting or architrave to new frames; 150mm high', 'depth': 0.0,
|
||
'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.01, 'labour_cost': 4.87, 'labour_hours_per_unit': 0.12,
|
||
'plant_cost': 0.0, 'total_cost': 4.88, 'notes': None}, {'id': 1198, 'type': 'ewi_wall_demolition',
|
||
'description': 'Solid & Dry Lined walls: Hack of '
|
||
'wall finishes with chipping hammer; '
|
||
'plaster to walls.',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 0.0, 'labour_cost': 10.27,
|
||
'labour_hours_per_unit': 0.33, 'plant_cost': 1.28,
|
||
'total_cost': 11.55, 'notes': None},
|
||
{'id': 1199, 'type': 'ewi_wall_demolition',
|
||
'description': 'Stud walls: Remove wall linings including battening behind; plasterboard and skim',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 0.0, 'labour_cost': 6.23, 'labour_hours_per_unit': 0.2,
|
||
'plant_cost': 1.25, 'total_cost': 7.48, 'notes': None}, {'id': 1200, 'type': 'ewi_wall_demolition',
|
||
'description': 'Lathe and Plaster walls: Remove '
|
||
'wall linings including battening '
|
||
'behind; wood lath and plaster',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 0.0, 'labour_cost': 6.85,
|
||
'labour_hours_per_unit': 0.22, 'plant_cost': 2.09,
|
||
'total_cost': 8.94, 'notes': None},
|
||
{'id': 1201, 'type': 'ewi_wall_preparation',
|
||
'description': 'Clean and prepare surfaces, one coat Keim dilution, one coat primer and two coats of Keim '
|
||
'Ecosil paint; Brick or block walls; over 300 mm girth',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None, 'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 7.3, 'labour_cost': 5.62, 'labour_hours_per_unit': 0.3,
|
||
'plant_cost': 0.0, 'total_cost': 12.92,
|
||
'notes': 'This work covers the preparation and priming of the wall before insulating'},
|
||
{'id': 1202, 'type': 'external_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board',
|
||
'depth': 30.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 6.16, 'material_cost': 16.73, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 45.07, 'notes': None},
|
||
{'id': 1203, 'type': 'external_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board',
|
||
'depth': 50.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 8.46, 'material_cost': 19.1, 'labour_cost': 28.34, 'labour_hours_per_unit': 1.2,
|
||
'plant_cost': 0.0, 'total_cost': 47.44, 'notes': None},
|
||
{'id': 1204, 'type': 'external_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 15.12, 'material_cost': 25.96, 'labour_cost': 30.7, 'labour_hours_per_unit': 1.3,
|
||
'plant_cost': 0.0, 'total_cost': 56.66, 'notes': None},
|
||
{'id': 1205, 'type': 'external_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board',
|
||
'depth': 150.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.045454547,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.022,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 23.53, 'material_cost': 34.62, 'labour_cost': 33.06, 'labour_hours_per_unit': 1.4,
|
||
'plant_cost': 0.0, 'total_cost': 67.68, 'notes': None},
|
||
{'id': 1206, 'type': 'external_wall_insulation', 'description': 'Foamglas Grade F Wall Insulation Slabs',
|
||
'depth': 60.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.02631579,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.038,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 41.69, 'material_cost': 53.33, 'labour_cost': 29.52, 'labour_hours_per_unit': 1.25,
|
||
'plant_cost': 0.0, 'total_cost': 82.85, 'notes': None},
|
||
{'id': 1207, 'type': 'external_wall_insulation', 'description': 'Foamglas Grade F Wall Insulation Slabs',
|
||
'depth': 100.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.02631579,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.038,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 86.86, 'material_cost': 99.85, 'labour_cost': 29.52, 'labour_hours_per_unit': 1.25,
|
||
'plant_cost': 0.0, 'total_cost': 129.37, 'notes': None},
|
||
{'id': 1208, 'type': 'external_wall_insulation', 'description': 'Foamglas Grade F Wall Insulation Slabs',
|
||
'depth': 150.0, 'depth_unit': 'mm', 'cost': None, 'cost_unit': 'gbp_per_m2', 'r_value_per_mm': 0.02631579,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt', 'thermal_conductivity': 0.038,
|
||
'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': 130.29, 'material_cost': 144.58, 'labour_cost': 29.52, 'labour_hours_per_unit': 1.25,
|
||
'plant_cost': 0.0, 'total_cost': 174.1, 'notes': None}, {'id': 1209, 'type': 'ewi_wall_redecoration',
|
||
'description': 'EPS insulation fixed with adhesive '
|
||
'to SFS structure (measured '
|
||
'separately) with horizontal PVC '
|
||
'intermediate track and vertical '
|
||
'T-spines; with glassfibre mesh '
|
||
'reinforcement embedded in Sto Armat '
|
||
'Classic Basecoat Render and Stolit '
|
||
'K 1.5 Decorative Topcoat Render ('
|
||
'white)',
|
||
'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': None, 'r_value_per_mm': nan,
|
||
'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None,
|
||
'thermal_conductivity_unit': None, 'link': 'SPONs',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49,
|
||
12, 244907),
|
||
'is_active': True, 'prime_material_cost': None,
|
||
'material_cost': 0.0, 'labour_cost': 0.0,
|
||
'labour_hours_per_unit': 0.0, 'plant_cost': 0.0,
|
||
'total_cost': 69.94,
|
||
'notes': 'This material in SPONs is for 70mm EPS '
|
||
'insulation, which comes in at a cost of '
|
||
'99.17 per meter square. This includes the '
|
||
'cost of insulation. To get the costing '
|
||
'for just the works and not the '
|
||
'insulation, we subtract the cost of EPS '
|
||
'insulation, using Ravathem 75mm '
|
||
'insulation as an example, which costs '
|
||
'£29.23 per meter square, giving us the '
|
||
'cost of the remaining works without '
|
||
'insulation. This material gives us a cost '
|
||
'for basecoat, mesh application and a '
|
||
'render finish'},
|
||
{'id': 1210, 'type': 'low_energy_lighting_installation',
|
||
'description': 'Installation of fittings and cost of bub', 'depth': 0.0, 'depth_unit': None, 'cost': None,
|
||
'cost_unit': 'gbp_per_unit', 'r_value_per_mm': nan, 'r_value_unit': 'square_meter_kelvin_per_watt',
|
||
'thermal_conductivity': None, 'thermal_conductivity_unit': None,
|
||
'link': 'https://www.checkatrade.com/blog/cost-guides/cost-install-downlights/ '
|
||
'https://www.hamuch.com/cost/led-spot-light#:~:text=It%20costs%20an%20average%20of,'
|
||
'will%20drive%20up%20the%20cost.',
|
||
'created_at': datetime.datetime(2023, 11, 28, 22, 49, 12, 244907), 'is_active': True,
|
||
'prime_material_cost': None, 'material_cost': 20.0, 'labour_cost': 15.0, 'labour_hours_per_unit': 0.8,
|
||
'plant_cost': 0.0, 'total_cost': 66.0,
|
||
'notes': 'We estimate the unit economics from the checkatrade article. We assume that the average job '
|
||
'consists of installing 6 lights based on the hamuch article. We use the median value of 400 for a '
|
||
'job of 6 lights'}]
|
||
|
||
testing_properties = [
|
||
{
|
||
"address": "2 South Terrace",
|
||
"postcode": "NN1 5JY"
|
||
},
|
||
{
|
||
"address": "8 Lindlings",
|
||
"postcode": "HP1 2HA",
|
||
},
|
||
{
|
||
"address": "44 Lindlings",
|
||
"postcode": "HP1 2HE",
|
||
},
|
||
{
|
||
"address": "46 Chaulden Terrace",
|
||
"postcode": "HP1 2AN",
|
||
},
|
||
{
|
||
"address": "73 Long Chaulden",
|
||
"postcode": "HP1 2HX",
|
||
},
|
||
{
|
||
"address": "77 Simmons Drive",
|
||
"postcode": "B32 1SL",
|
||
},
|
||
{
|
||
"address": "139 School Road",
|
||
"postcode": "B28 8JF",
|
||
},
|
||
]
|
||
|
||
testing_properties_results = []
|
||
for testing_property_config in testing_properties:
|
||
|
||
searcher = SearchEpc(
|
||
address1=testing_property_config["address"],
|
||
postcode=testing_property_config["postcode"],
|
||
auth_token="a2Nvbm5rb3dsZXNzYXJAZ21haWwuY29tOjY5MGJiMWM0NmIyOGI5ZDUxYzAxMzQzYzNiZGNlZGJjZDNmODQwMzA=",
|
||
os_api_key=""
|
||
)
|
||
searcher.find_property(skip_os=True)
|
||
epc_records = {
|
||
'original_epc': searcher.newest_epc.copy(),
|
||
'full_sap_epc': searcher.full_sap_epc.copy(),
|
||
'old_data': searcher.older_epcs.copy(),
|
||
}
|
||
|
||
prepared_epc = EPCRecord(
|
||
epc_records=epc_records,
|
||
run_mode="newdata",
|
||
cleaning_data=cleaning_data
|
||
)
|
||
|
||
p = Property(
|
||
id=prepared_epc.uprn,
|
||
address=searcher.address_clean,
|
||
postcode=searcher.postcode_clean,
|
||
epc_record=prepared_epc,
|
||
)
|
||
p.get_spatial_data(uprn_filenames)
|
||
p.get_components(cleaned, photo_supply_lookup, floor_area_decile_thresholds)
|
||
|
||
recommender = Recommendations(property_instance=p, materials=materials)
|
||
recommender.recommend()
|
||
|
||
wall_recommendations = recommender.wall_recomender.recommendations
|
||
loft_recommendations = recommender.roof_recommender.recommendations
|
||
floor_recommendations = recommender.floor_recommender.recommendations
|
||
solar_recommendations = recommender.solar_recommender.recommendation
|
||
|
||
# TODO: TEMP!
|
||
solar_recommendations[0]["photo_supply"] = 50
|
||
|
||
# Take just the cavity wall and loft recommendations
|
||
p.create_base_difference_epc_record(cleaned_lookup=cleaned)
|
||
|
||
wall_scoring_data = []
|
||
for wall_rec in wall_recommendations:
|
||
recommendation_record = p.base_difference_record.df.to_dict("records")[0].copy()
|
||
scoring_dict = p.create_recommendation_scoring_data(
|
||
property_id=p.id, recommendation_record=recommendation_record, recommendation=wall_rec,
|
||
)
|
||
wall_scoring_data.append(scoring_dict)
|
||
|
||
roof_scoring_data = []
|
||
for roof_rec in loft_recommendations:
|
||
recommendation_record = p.base_difference_record.df.to_dict("records")[0].copy()
|
||
scoring_dict = p.create_recommendation_scoring_data(
|
||
property_id=p.id, recommendation_record=recommendation_record, recommendation=roof_rec,
|
||
)
|
||
roof_scoring_data.append(scoring_dict)
|
||
|
||
floor_scoring_data = []
|
||
for floor_rec in floor_recommendations:
|
||
recommendation_record = p.base_difference_record.df.to_dict("records")[0].copy()
|
||
scoring_dict = p.create_recommendation_scoring_data(
|
||
property_id=p.id, recommendation_record=recommendation_record, recommendation=floor_rec,
|
||
)
|
||
floor_scoring_data.append(scoring_dict)
|
||
|
||
solar_scoring_data = []
|
||
for solar_rec in solar_recommendations:
|
||
recommendation_record = p.base_difference_record.df.to_dict("records")[0].copy()
|
||
scoring_dict = p.create_recommendation_scoring_data(
|
||
property_id=p.id, recommendation_record=recommendation_record, recommendation=solar_rec,
|
||
)
|
||
solar_scoring_data.append(scoring_dict)
|
||
|
||
# We now produce a combined, applying just the first roof recommendation to the first wall recommendation
|
||
|
||
# Firstly apply the wall
|
||
starting_record = p.base_difference_record.df.to_dict("records")[0].copy()
|
||
scoring_dict_with_wall = p.create_recommendation_scoring_data(
|
||
property_id=p.id,
|
||
recommendation_record=starting_record.copy(),
|
||
recommendation=wall_recommendations[0],
|
||
) if wall_recommendations else starting_record.copy()
|
||
|
||
scoring_dict_with_wall_and_roof = p.create_recommendation_scoring_data(
|
||
property_id=p.id,
|
||
recommendation_record=scoring_dict_with_wall.copy(),
|
||
recommendation=loft_recommendations[0],
|
||
) if loft_recommendations else scoring_dict_with_wall.copy()
|
||
|
||
scoring_dict_with_wall_roof_floor = p.create_recommendation_scoring_data(
|
||
property_id=p.id,
|
||
recommendation_record=scoring_dict_with_wall_and_roof.copy(),
|
||
recommendation=floor_recommendations[0],
|
||
) if floor_recommendations else scoring_dict_with_wall_and_roof.copy()
|
||
|
||
scoring_dict_with_wall_roof_floor_solar = p.create_recommendation_scoring_data(
|
||
property_id=p.id,
|
||
recommendation_record=scoring_dict_with_wall_roof_floor.copy(),
|
||
recommendation=solar_recommendations[0],
|
||
) if solar_recommendations else scoring_dict_with_wall_roof_floor.copy()
|
||
|
||
# We score each dataset with the model
|
||
wall_only_predictions_dict = model_api.predict_all(
|
||
df=pd.DataFrame(wall_scoring_data),
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
) if wall_scoring_data else {"sap_change_predictions": pd.DataFrame()}
|
||
|
||
roof_only_predictions_dict = model_api.predict_all(
|
||
df=pd.DataFrame(roof_scoring_data),
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
) if roof_scoring_data else {"sap_change_predictions": pd.DataFrame()}
|
||
|
||
floor_only_predictions_dict = model_api.predict_all(
|
||
df=pd.DataFrame(floor_scoring_data),
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
) if floor_scoring_data else {"sap_change_predictions": pd.DataFrame()}
|
||
|
||
solar_only_predictions_dict = model_api.predict_all(
|
||
df=pd.DataFrame(solar_scoring_data),
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
) if solar_scoring_data else {"sap_change_predictions": pd.DataFrame()}
|
||
|
||
wall_roof_predictions_dict = model_api.predict_all(
|
||
df=pd.DataFrame([scoring_dict_with_wall_and_roof]),
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
wall_roof_floor_predictions_dict = model_api.predict_all(
|
||
df=pd.DataFrame([scoring_dict_with_wall_roof_floor]),
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
wall_roof_floor_solar_predictions_dict = model_api.predict_all(
|
||
df=pd.DataFrame([scoring_dict_with_wall_roof_floor_solar]),
|
||
bucket="retrofit-data-dev",
|
||
prediction_buckets={
|
||
"sap_change_predictions": "retrofit-sap-predictions-dev",
|
||
}
|
||
)
|
||
|
||
wall_only_predictions = wall_only_predictions_dict["sap_change_predictions"].copy()
|
||
wall_only_predictions["type"] = "wall_only"
|
||
|
||
roof_only_predictions = roof_only_predictions_dict["sap_change_predictions"].copy()
|
||
roof_only_predictions["type"] = "roof_only"
|
||
|
||
floor_only_predictions = floor_only_predictions_dict["sap_change_predictions"].copy()
|
||
floor_only_predictions["type"] = "floor_only"
|
||
|
||
solar_only_predictions = solar_only_predictions_dict["sap_change_predictions"].copy()
|
||
solar_only_predictions["type"] = "solar_only"
|
||
|
||
wall_and_roof_predictions = wall_roof_predictions_dict["sap_change_predictions"].copy()
|
||
wall_and_roof_predictions["type"] = "wall_and_roof"
|
||
|
||
wall_roof_floor_predictions = wall_roof_floor_predictions_dict["sap_change_predictions"].copy()
|
||
wall_roof_floor_predictions["type"] = "wall_roof_floor"
|
||
|
||
wall_roof_floor_solar_predictions = wall_roof_floor_solar_predictions_dict["sap_change_predictions"].copy()
|
||
wall_roof_floor_solar_predictions["type"] = "wall_roof_floor_solar"
|
||
|
||
# We collate the results
|
||
results = pd.concat(
|
||
[
|
||
wall_only_predictions,
|
||
roof_only_predictions,
|
||
floor_only_predictions,
|
||
solar_only_predictions,
|
||
wall_and_roof_predictions,
|
||
wall_roof_floor_predictions,
|
||
wall_roof_floor_solar_predictions
|
||
]
|
||
)
|
||
results["gain"] = results["predictions"] - int(p.data["current-energy-efficiency"])
|
||
results["address"] = p.address
|
||
|
||
testing_properties_results.append(results)
|
||
|
||
testing_properties_results = pd.concat(testing_properties_results)
|