mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Merge pull request #666 from Hestia-Homes/portfolio-diagnostics
Added change to pass an already installed sap value, which rebaseline…
This commit is contained in:
commit
43b327e31d
4 changed files with 88 additions and 17 deletions
|
|
@ -1065,21 +1065,8 @@ async def model_engine(body: PlanTriggerRequest):
|
|||
)
|
||||
continue
|
||||
|
||||
fixed_gain = optimiser_functions.calculate_fixed_gain(
|
||||
property_required_measures, recommendations, p, needs_ventilation
|
||||
)
|
||||
gain = optimiser_functions.calculate_gain(body=body, p=p, fixed_gain=fixed_gain, eco_packages=eco_packages)
|
||||
|
||||
# We insert the innovation uplift
|
||||
measures_to_optimise_with_uplift = deepcopy(measures_to_optimise)
|
||||
|
||||
for group in measures_to_optimise_with_uplift:
|
||||
for r in group:
|
||||
(r["partial_project_score"], r["partial_project_funding"], r["innovation_uplift"],
|
||||
r["uplift_project_score"]) = (0, 0, 0, 0)
|
||||
|
||||
already_installed_measures = []
|
||||
for measures in measures_to_optimise_with_uplift:
|
||||
for measures in measures_to_optimise:
|
||||
for m in measures:
|
||||
# A) We're going to make the already installed measures default
|
||||
# B) We need to SAP points for all already installed measures to avoid double counting
|
||||
|
|
@ -1096,6 +1083,22 @@ async def model_engine(body: PlanTriggerRequest):
|
|||
default_already_installed = keep_max_sap_per_measure_type(already_installed_measures)
|
||||
already_installed_sap = float(sum(d["sap_points"] for d in default_already_installed))
|
||||
|
||||
fixed_gain = optimiser_functions.calculate_fixed_gain(
|
||||
property_required_measures, recommendations, p, needs_ventilation
|
||||
)
|
||||
gain = optimiser_functions.calculate_gain(
|
||||
body=body, p=p, fixed_gain=fixed_gain, eco_packages=eco_packages,
|
||||
already_installed_gain=already_installed_sap
|
||||
)
|
||||
|
||||
# We insert the innovation uplift
|
||||
measures_to_optimise_with_uplift = deepcopy(measures_to_optimise)
|
||||
|
||||
for group in measures_to_optimise_with_uplift:
|
||||
for r in group:
|
||||
(r["partial_project_score"], r["partial_project_funding"], r["innovation_uplift"],
|
||||
r["uplift_project_score"]) = (0, 0, 0, 0)
|
||||
|
||||
# Remove them from the optimisation pool
|
||||
finalised_measures_to_optimise = []
|
||||
for m in measures_to_optimise_with_uplift:
|
||||
|
|
|
|||
|
|
@ -231,6 +231,49 @@ properties_data, plans_data, recommendations_data = get_data(
|
|||
)
|
||||
|
||||
recommendations_df = pd.DataFrame(recommendations_data)
|
||||
properties_df = pd.DataFrame(properties_data)
|
||||
|
||||
solar_pv_recommendations = recommendations_df[recommendations_df["measure_type"] == "solar_pv"]
|
||||
average_savings = solar_pv_recommendations.groupby("scenario_id")["energy_cost_savings"].mean().reset_index()
|
||||
|
||||
# Check tenures
|
||||
initial_asset_data = pd.read_excel(
|
||||
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody "
|
||||
"- Data Extracts for Domna.xlsx",
|
||||
sheet_name="Properties"
|
||||
)
|
||||
sustainability_data = pd.read_excel(
|
||||
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody "
|
||||
"- Data Extracts for Domna.xlsx",
|
||||
sheet_name="Sustainability"
|
||||
)
|
||||
|
||||
sustainability_sample = sustainability_data[
|
||||
sustainability_data["UPRN"].isin(properties_df["uprn"].astype(int).astype(str).values)
|
||||
]
|
||||
|
||||
sustainability_sample = sustainability_sample.merge(
|
||||
initial_asset_data, left_on="Org Ref", right_on="UPRN", suffixes=("_sustainability", "_initial_asset")
|
||||
)
|
||||
|
||||
block_sizes = initial_asset_data["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False)
|
||||
block_sizes.to_excel("/Users/khalimconn-kowlessar/Downloads/peabody_block_sizes.xlsx", index=False)
|
||||
|
||||
initial_asset_data.columns
|
||||
initial_asset_data["LeaseType"].value_counts()
|
||||
|
||||
# sustainability_sample["Tenure Group"].value_counts()
|
||||
# Tenure Group
|
||||
# General Needs 57787
|
||||
# Home Ownership 25471
|
||||
# Care & Supported Housing 4239
|
||||
# Rental 2677
|
||||
# Other 188
|
||||
|
||||
df = sustainability_sample["Ownership Type"].value_counts().to_frame().reset_index()
|
||||
df.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenures.xlsx", index=False)
|
||||
|
||||
tenure_groups = sustainability_sample["Tenure Group"].value_counts().to_frame().reset_index()
|
||||
tenure_groups.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenure_groups.xlsx", index=False)
|
||||
|
||||
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Tenure Group"].value_counts()
|
||||
|
|
|
|||
|
|
@ -202,8 +202,13 @@ def calculate_fixed_gain(property_required_measures, recommendations, p, needs_v
|
|||
return fixed_gain
|
||||
|
||||
|
||||
def calculate_gain(body: PlanTriggerRequest, p: Property, fixed_gain: float,
|
||||
eco_packages: None | dict = None) -> float | None:
|
||||
def calculate_gain(
|
||||
body: PlanTriggerRequest,
|
||||
p: Property,
|
||||
fixed_gain: float,
|
||||
eco_packages: None | dict = None,
|
||||
already_installed_gain: float = 0,
|
||||
) -> float | None:
|
||||
"""
|
||||
Calculates the target gain value for optimisation based on the goal.
|
||||
|
||||
|
|
@ -221,6 +226,7 @@ def calculate_gain(body: PlanTriggerRequest, p: Property, fixed_gain: float,
|
|||
fixed_gain : float
|
||||
Total fixed gain from required measures (returned by calculate_fixed_gain).
|
||||
eco_packages : dict, optional
|
||||
already_installed_gain: float, optional
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -228,13 +234,16 @@ def calculate_gain(body: PlanTriggerRequest, p: Property, fixed_gain: float,
|
|||
Required SAP gain for EPC, or None for non-EPC goals.
|
||||
"""
|
||||
if body.goal == "Increasing EPC":
|
||||
current_sap = int(p.data["current-energy-efficiency"])
|
||||
current_sap = int(p.data["current-energy-efficiency"]) + already_installed_gain
|
||||
|
||||
target_sap = (
|
||||
eco_packages.get(p.id)[1] if eco_packages.get(p.id)[1] is not None
|
||||
else epc_to_sap_lower_bound(body.goal_value)
|
||||
)
|
||||
|
||||
if target_sap == current_sap:
|
||||
return 0
|
||||
|
||||
gain = CostOptimiser.calculate_sap_gain_with_slack(
|
||||
target_sap - current_sap
|
||||
) - fixed_gain
|
||||
|
|
|
|||
|
|
@ -85,6 +85,22 @@ class TestCalculateGain:
|
|||
gain = optimiser_functions.calculate_gain(body, prop, fixed_gain=0)
|
||||
assert gain is None
|
||||
|
||||
def test_returns_zero_for_already_installed_getting_to_target(self):
|
||||
body = SimpleNamespace(goal="Increasing EPC", goal_value="C")
|
||||
p = SimpleNamespace(data={"current-energy-efficiency": "67"}, id=1)
|
||||
fixed_gain = 0
|
||||
eco_packages = {1: (None, None, None, [])}
|
||||
already_installed_sap = 2
|
||||
gain = optimiser_functions.calculate_gain(
|
||||
body=body,
|
||||
p=p,
|
||||
fixed_gain=fixed_gain,
|
||||
eco_packages=eco_packages,
|
||||
already_installed_gain=already_installed_sap
|
||||
)
|
||||
|
||||
assert gain == 0
|
||||
|
||||
def test_calculates_gain_for_epc(self, monkeypatch):
|
||||
# patch cost optimiser calculation
|
||||
monkeypatch.setattr(optimiser_functions, "epc_to_sap_lower_bound", lambda goal_value: 69)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue