revising scenarios, fixing setting of energy sources

This commit is contained in:
Khalim Conn-Kowlessar 2024-08-12 15:15:56 +01:00
parent 30c28754b7
commit 3920ad4132
5 changed files with 58 additions and 34 deletions

View file

@ -1171,7 +1171,9 @@ class Property:
'has_exhaust_source_heat_pump': 'Electricity', 'has_exhaust_source_heat_pump': 'Electricity',
'has_community_heat_pump': 'Electricity', 'has_community_heat_pump': 'Electricity',
'has_wood_pellets': 'Wood Pellets', 'has_wood_pellets': 'Wood Pellets',
'has_community_scheme': 'Varied (Community Scheme)' 'has_community_scheme': 'Varied (Community Scheme)',
"has_dual_fuel_mineral_and_wood": 'Wood Logs',
"has_electricaire": 'Electricity',
} }
# Hot water # Hot water
@ -1197,9 +1199,9 @@ class Property:
'community scheme': 'Community Scheme' 'community scheme': 'Community Scheme'
} }
self.heating_energy_source = [ self.heating_energy_source = list({
fuel for key, fuel in heating_fuel_mapping.items() if self.main_heating.get(key, False) fuel for key, fuel in heating_fuel_mapping.items() if self.main_heating.get(key, False)
] })
if len(self.heating_energy_source) == 0 or len(self.heating_energy_source) > 1: if len(self.heating_energy_source) == 0 or len(self.heating_energy_source) > 1:
raise Exception("Investigate me") raise Exception("Investigate me")

View file

@ -320,11 +320,11 @@ def extract_propert_on_site_recommendations(config, already_installed, non_invas
# Because we have some non-invasive recommendations that match on address and postcode, but not UPRN # Because we have some non-invasive recommendations that match on address and postcode, but not UPRN
# we need to check existence of uprn # we need to check existence of uprn
has_uprn = "non_invasive_recommendations" in non_invasive_recommendations[0] has_uprn = "uprn" in non_invasive_recommendations[0]
if has_uprn: if has_uprn:
property_non_invasive_recommendations = next(( property_non_invasive_recommendations = next((
x for x in non_invasive_recommendations if x for x in non_invasive_recommendations if
(x["uprn"] == uprn) (str(x["uprn"]) == str(uprn))
), {}) ), {})
# We patch the non-invasive recs that are ['cavity_extract_and_refill'] # We patch the non-invasive recs that are ['cavity_extract_and_refill']
@ -334,7 +334,7 @@ def extract_propert_on_site_recommendations(config, already_installed, non_invas
(x["address"] == config["address"]) and (x["postcode"] == config["postcode"]) (x["address"] == config["address"]) and (x["postcode"] == config["postcode"])
), {}) ), {})
if isinstance(property_non_invasive_recommendations["recommendations"], str): if isinstance(property_non_invasive_recommendations.get("recommendations"), str):
import ast import ast
property_non_invasive_recommendations["recommendations"] = ast.literal_eval( property_non_invasive_recommendations["recommendations"] = ast.literal_eval(
property_non_invasive_recommendations["recommendations"] property_non_invasive_recommendations["recommendations"]
@ -498,8 +498,8 @@ async def trigger_plan(body: PlanTriggerRequest):
logger.info("Setting property features") logger.info("Setting property features")
[p.set_features(cleaned=cleaned, kwh_client=kwh_client, kwh_predictions=kwh_preds) for p in input_properties] [p.set_features(cleaned=cleaned, kwh_client=kwh_client, kwh_predictions=kwh_preds) for p in input_properties]
logger.info("Performing solar analysis") logger.info("Performing solar analysis")
# TODO: Tidy this up # TODO: Tidy this up
# TODO: If a property is semi-detached, we might get roof surfaces for the main building + the neighbour # TODO: If a property is semi-detached, we might get roof surfaces for the main building + the neighbour
# TODO: If we can't get high image quality, should we use the solar API? Maybe just for semi-detached units with # TODO: If we can't get high image quality, should we use the solar API? Maybe just for semi-detached units with

View file

@ -34,7 +34,7 @@ class PlanTriggerRequest(BaseModel):
# Specific measures # Specific measures
"air_source_heat_pump", "air_source_heat_pump",
"internal_wall_insulation", "internal_wall_insulation",
"external_wall_insulation" "external_wall_insulation",
} }
_allowed_goals = {"Increasing EPC"} _allowed_goals = {"Increasing EPC"}

View file

@ -25,7 +25,8 @@ class KwhData:
"county", "county",
"windows-description", "windows-energy-eff", "flat-top-storey", "windows-description", "windows-energy-eff", "flat-top-storey",
"flat-storey-count", "unheated-corridor-length", "solar-water-heating-flag", "mechanical-ventilation", "flat-storey-count", "unheated-corridor-length", "solar-water-heating-flag", "mechanical-ventilation",
"low-energy-lighting", "environment-impact-current", "energy-tariff", "current-energy-rating" "low-energy-lighting", "environment-impact-current", "energy-tariff", "current-energy-rating",
"floor-level"
] ]
NUMERICAL_COLUMNS = [ NUMERICAL_COLUMNS = [

View file

@ -11,7 +11,7 @@ EPC_DIRECTORY = Path(src_file_path).parent / "local_data" / "all-domestic-certif
CUSTOMER_DATA_DIRECTORY = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Newhaven/Data" CUSTOMER_DATA_DIRECTORY = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Newhaven/Data"
USER_ID = 8 USER_ID = 8
PORTFOLIO_ID = 88 PORTFOLIO_ID = 89
def make_asset_list(): def make_asset_list():
@ -88,20 +88,20 @@ def make_asset_list():
columns={"Wall Area [m^2]": "insulation_wall_area", "Building Area [m^2]": "floor_area"} columns={"Wall Area [m^2]": "insulation_wall_area", "Building Area [m^2]": "floor_area"}
) )
had_an_epc = asset_list[~pd.isnull(asset_list["current-energy-efficiency"])] # had_an_epc = asset_list[~pd.isnull(asset_list["current-energy-efficiency"])]
below_b = asset_list[asset_list["current-energy-efficiency"].astype(float) <= 80].shape # below_b = asset_list[asset_list["current-energy-efficiency"].astype(float) <= 80].shape
below_c = asset_list[asset_list["current-energy-efficiency"].astype(float) <= 69].shape # below_c = asset_list[asset_list["current-energy-efficiency"].astype(float) <= 69].shape
had_an_epc["energy-efficiency-rating"].value_counts() # had_an_epc["energy-efficiency-rating"].value_counts()
asset_list["current-energy-rating"].value_counts() # asset_list["current-energy-rating"].value_counts()
asset_list["co2-emissions-current"].mean() # asset_list["co2-emissions-current"].mean()
# Get the underlying data of a histograme # # Get the underlying data of a histograme
import matplotlib.pyplot as plt # import matplotlib.pyplot as plt
n, bins, patches = plt.hist(asset_list["co2-emissions-current"], bins=100, color="blue", alpha=0.7) # n, bins, patches = plt.hist(asset_list["co2-emissions-current"], bins=100, color="blue", alpha=0.7)
#
bins = np.arange(0, asset_list["co2-emissions-current"].max(), 1) # Bins from 50 to 150 with a step of 10 # bins = np.arange(0, asset_list["co2-emissions-current"].max(), 1) # Bins from 50 to 150 with a step of 10
#
# Step 3: Calculate the frequency of data in each bin # # Step 3: Calculate the frequency of data in each bin
hist, bin_edges = np.histogram(asset_list["co2-emissions-current"], bins=bins) # hist, bin_edges = np.histogram(asset_list["co2-emissions-current"], bins=bins)
# Take properties below a B - there are 2844 units # Take properties below a B - there are 2844 units
asset_list = asset_list[asset_list["current-energy-efficiency"].astype(float) <= 80] asset_list = asset_list[asset_list["current-energy-efficiency"].astype(float) <= 80]
@ -110,7 +110,7 @@ def make_asset_list():
asset_list = asset_list[~pd.isnull(asset_list["current-energy-efficiency"])] asset_list = asset_list[~pd.isnull(asset_list["current-energy-efficiency"])]
# Take a 10% sample, for properties that have an EPC, with a seed # Take a 10% sample, for properties that have an EPC, with a seed
asset_list = asset_list.sample(frac=0.1, random_state=42) asset_list = asset_list.sample(frac=0.25, random_state=42)
AVG_FLOOR_HEIGHT = asset_list["floor-height"].median() AVG_FLOOR_HEIGHT = asset_list["floor-height"].median()
@ -119,11 +119,11 @@ def make_asset_list():
): ):
if address_base_property_description == "Self Contained Flat (Includes Maisonette / Apartment)": if address_base_property_description == "Self Contained Flat (Includes Maisonette / Apartment)":
if epc_property_type == "Flat": if epc_property_type in ["Flat"]:
return 1 return 1
if epc_property_type == "Maisonette": if epc_property_type == "Maisonette":
return 2 return 2
raise NotImplementedError("Implement me") return None
if pd.isnull(floor_height): if pd.isnull(floor_height):
return np.round(building_height / AVG_FLOOR_HEIGHT) return np.round(building_height / AVG_FLOOR_HEIGHT)
@ -140,6 +140,8 @@ def make_asset_list():
), ),
axis=1 axis=1
) )
# Drop any entires with null floors because that means the ordnance survey data doesn't align with the epc data
asset_list = asset_list[~pd.isnull(asset_list["number_of_floors"])]
# D 0.419929 # D 0.419929
# C 0.391459 # C 0.391459
@ -262,16 +264,16 @@ def make_asset_list():
"already_installed_file_path": "", "already_installed_file_path": "",
"patches_file_path": "", "patches_file_path": "",
"non_invasive_recommendations_file_path": non_invasive_recommendations_filename, "non_invasive_recommendations_file_path": non_invasive_recommendations_filename,
"scenario_name": "Demand Reduction - no solid wall", "scenario_name": "Demand Reduction - no solid wall, windows, LEDs",
"multi_plan": True, "multi_plan": True,
"exclusions": [ "exclusions": [
"internal_wall_insulation", "external_wall_insulation", "floor_insulation", "heating", "solar_pv" "internal_wall_insulation", "external_wall_insulation", "floor_insulation", "heating", "solar_pv",
"lighting", "windows"
], ],
"budget": None, "budget": None,
} }
print(body1) print(body1)
# Scenario B
body2 = { body2 = {
"portfolio_id": str(PORTFOLIO_ID), "portfolio_id": str(PORTFOLIO_ID),
"housing_type": "Private", "housing_type": "Private",
@ -281,15 +283,34 @@ def make_asset_list():
"already_installed_file_path": "", "already_installed_file_path": "",
"patches_file_path": "", "patches_file_path": "",
"non_invasive_recommendations_file_path": non_invasive_recommendations_filename, "non_invasive_recommendations_file_path": non_invasive_recommendations_filename,
"scenario_name": "Demand Reduction, Heating Systems, Solar PV - no solid wall", "scenario_name": "Demand Reduction - no solid wall, floors or heating",
"multi_plan": True, "multi_plan": True,
"exclusions": ["internal_wall_insulation", "external_wall_insulation", "floor_insulation"], "exclusions": [
"internal_wall_insulation", "external_wall_insulation", "floor_insulation", "heating", "solar_pv",
],
"budget": None, "budget": None,
} }
print(body2) print(body2)
# Scenario C - deep fabric, no exclusions # Scenario B
body3 = { body3 = {
"portfolio_id": str(PORTFOLIO_ID),
"housing_type": "Private",
"goal": "Increasing EPC",
"goal_value": "A",
"trigger_file_path": filename,
"already_installed_file_path": "",
"patches_file_path": "",
"non_invasive_recommendations_file_path": non_invasive_recommendations_filename,
"scenario_name": "Demand Reduction, Heating Systems, Solar PV - no solid wall or floors",
"multi_plan": True,
"exclusions": ["internal_wall_insulation", "external_wall_insulation", "floor_insulation"],
"budget": None,
}
print(body3)
# Scenario 4 - deep fabric, no IWI, floor
body4 = {
"portfolio_id": str(PORTFOLIO_ID), "portfolio_id": str(PORTFOLIO_ID),
"housing_type": "Private", "housing_type": "Private",
"goal": "Increasing EPC", "goal": "Increasing EPC",
@ -302,4 +323,4 @@ def make_asset_list():
"multi_plan": True, "multi_plan": True,
"budget": None, "budget": None,
} }
print(body3) print(body4)