mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
set up the rest of the solar recommendation
This commit is contained in:
parent
fcc4dc6b51
commit
c3dbec6703
5 changed files with 69 additions and 9 deletions
|
|
@ -221,11 +221,15 @@ class Property(Definitions):
|
||||||
|
|
||||||
setattr(self, attribute, value)
|
setattr(self, attribute, value)
|
||||||
|
|
||||||
def get_components(self, cleaned):
|
def get_components(self, cleaned, photo_supply_lookup, floor_area_decile_thresholds):
|
||||||
"""
|
"""
|
||||||
Given the cleaning that has been performed, we'll use this to identify the property
|
Given the cleaning that has been performed, we'll use this to identify the property
|
||||||
components, from roof to walls to windows, heating and hot water
|
components, from roof to walls to windows, heating and hot water
|
||||||
:param cleaned: This is the dictionary of components found in cleaner.cleaned
|
:param cleaned: This is the dictionary of components found in cleaner.cleaned
|
||||||
|
:param photo_supply_lookup: This is the lookup table for the photo supply, used to estimate the percentage
|
||||||
|
of the roof that is suitable for solar panels
|
||||||
|
:param floor_area_decile_thresholds: This is the decile thresholds for the floor area, used in estimating the
|
||||||
|
solar pv roof area
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -295,6 +299,9 @@ class Property(Definitions):
|
||||||
self.set_floor_type()
|
self.set_floor_type()
|
||||||
self.set_floor_level()
|
self.set_floor_level()
|
||||||
self.set_windows_count()
|
self.set_windows_count()
|
||||||
|
self.set_solar_panel_area(
|
||||||
|
photo_supply_lookup=photo_supply_lookup, floor_area_decile_thresholds=floor_area_decile_thresholds
|
||||||
|
)
|
||||||
|
|
||||||
def set_age_band(self):
|
def set_age_band(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -849,7 +856,9 @@ class Property(Definitions):
|
||||||
return i # Returns the decile index (0 to 9)
|
return i # Returns the decile index (0 to 9)
|
||||||
return len(thresholds)
|
return len(thresholds)
|
||||||
|
|
||||||
floor_area_decile = classify_floor_area(self.floor_area, floor_area_decile_thresholds)
|
floor_area_decile = classify_floor_area(
|
||||||
|
self.floor_area, floor_area_decile_thresholds["floor_area_decile_thresholds"].values
|
||||||
|
)
|
||||||
|
|
||||||
# Given the photo_supply_lookup, we esimate the percentage of the roof that is suitable for solar panels
|
# Given the photo_supply_lookup, we esimate the percentage of the roof that is suitable for solar panels
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,12 @@ async def trigger_plan(body: PlanTriggerRequest):
|
||||||
cleaning_data = read_parquet_from_s3(
|
cleaning_data = read_parquet_from_s3(
|
||||||
bucket_name=get_settings().DATA_BUCKET, file_key="sap_change_model/cleaning_dataset.parquet",
|
bucket_name=get_settings().DATA_BUCKET, file_key="sap_change_model/cleaning_dataset.parquet",
|
||||||
)
|
)
|
||||||
|
photo_supply_lookup = read_parquet_from_s3(
|
||||||
|
bucket_name=get_settings().DATA_BUCKET, file_key="solar_pv_supply/photo_supply_lookup.parquet",
|
||||||
|
)
|
||||||
|
floor_area_decile_thresholds = read_parquet_from_s3(
|
||||||
|
bucket_name=get_settings().DATA_BUCKET, file_key="solar_pv_supply/floor_area_decile_thresholds.parquet",
|
||||||
|
)
|
||||||
|
|
||||||
input_properties = []
|
input_properties = []
|
||||||
for config in plan_input:
|
for config in plan_input:
|
||||||
|
|
@ -129,7 +135,7 @@ async def trigger_plan(body: PlanTriggerRequest):
|
||||||
for p in input_properties:
|
for p in input_properties:
|
||||||
|
|
||||||
# Property recommendations
|
# Property recommendations
|
||||||
p.get_components(cleaned)
|
p.get_components(cleaned, photo_supply_lookup, floor_area_decile_thresholds)
|
||||||
|
|
||||||
# This is temp - this should happen after scoring
|
# This is temp - this should happen after scoring
|
||||||
cleaned_property_data = DataProcessor.apply_averages_cleaning(
|
cleaned_property_data = DataProcessor.apply_averages_cleaning(
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ def app():
|
||||||
save_dataframe_to_s3_parquet(
|
save_dataframe_to_s3_parquet(
|
||||||
df=aggregated,
|
df=aggregated,
|
||||||
bucket_name="retrofit-data-dev",
|
bucket_name="retrofit-data-dev",
|
||||||
file_key=f"solar_pv_supply/photo_supply_lookup.parquet",
|
file_key="solar_pv_supply/photo_supply_lookup.parquet",
|
||||||
)
|
)
|
||||||
|
|
||||||
floor_area_decile_thresholds = pd.DataFrame(decile_thresholds, columns=["floor_area_decile_thresholds"])
|
floor_area_decile_thresholds = pd.DataFrame(decile_thresholds, columns=["floor_area_decile_thresholds"])
|
||||||
|
|
|
||||||
|
|
@ -831,5 +831,35 @@ class Costs:
|
||||||
"labour_days": labour_days
|
"labour_days": labour_days
|
||||||
}
|
}
|
||||||
|
|
||||||
def solar_pv(self, wattage):
|
def solar_pv(self, wattage: float):
|
||||||
pass
|
|
||||||
|
"""
|
||||||
|
Calculates the total cost for solar PV based data provided by the MCS dashboard, which contains
|
||||||
|
costing data for installations of renewable and clean energy measures.
|
||||||
|
|
||||||
|
The data in the dashboard is filtered on domestic building installations and then the data across the
|
||||||
|
various regions is manually collected. There is currently no automated way to get the data from the MCS
|
||||||
|
dashboard
|
||||||
|
:param wattage:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Get the cost data relevant to the region
|
||||||
|
regional_cost = MCS_SOLAR_PV_COST_DATA["-".join(["average_cost_per_kwh", self.region])]
|
||||||
|
|
||||||
|
kw = wattage / 1000
|
||||||
|
total_cost = kw * regional_cost
|
||||||
|
|
||||||
|
subtotal_before_vat = total_cost / (1 + self.VAT_RATE)
|
||||||
|
vat = total_cost - subtotal_before_vat
|
||||||
|
|
||||||
|
# Labour hours are based on estimates from online research but an average team seems to consist of 3 people
|
||||||
|
# and most jobs take around 2 days. Assuming an 8 hour day for 3 people across 2 days, gives us 72 hours of
|
||||||
|
# labour
|
||||||
|
return {
|
||||||
|
"total": total_cost,
|
||||||
|
"subtotal": subtotal_before_vat,
|
||||||
|
"vat": vat,
|
||||||
|
"labour_hours": 72,
|
||||||
|
"labour_days": 2,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class SolarPvRecommendations:
|
||||||
self.property = property_instance
|
self.property = property_instance
|
||||||
self.costs = Costs(self.property)
|
self.costs = Costs(self.property)
|
||||||
|
|
||||||
self.recommendations = []
|
self.recommendation = []
|
||||||
|
|
||||||
def recommend(self):
|
def recommend(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -35,12 +35,27 @@ class SolarPvRecommendations:
|
||||||
None, 0, self.property.DATA_ANOMALY_MATCHES
|
None, 0, self.property.DATA_ANOMALY_MATCHES
|
||||||
]
|
]
|
||||||
|
|
||||||
if not is_valid_property_type or not is_valid_roof_type or has_no_existing_solar_pv:
|
if not is_valid_property_type or not is_valid_roof_type or not has_no_existing_solar_pv:
|
||||||
return
|
return
|
||||||
|
|
||||||
# We now have a property which is potentially suitable for solar PV
|
# We now have a property which is potentially suitable for solar PV
|
||||||
number_solar_panels = np.floor(self.property.solar_pv_roof_area / self.SOLAR_PANEL_AREA)
|
number_solar_panels = np.floor(self.property.solar_pv_roof_area / self.SOLAR_PANEL_AREA)
|
||||||
solar_panel_capacity = number_solar_panels * self.SOLAR_PANEL_WATTAGE
|
solar_panel_wattage = number_solar_panels * self.SOLAR_PANEL_WATTAGE
|
||||||
|
|
||||||
# Given the wattage, we estimate the cost of the solar PV system. This is based on the MCS database
|
# Given the wattage, we estimate the cost of the solar PV system. This is based on the MCS database
|
||||||
# of solar PV installations
|
# of solar PV installations
|
||||||
|
cost_result = self.costs.solar_pv(wattage=solar_panel_wattage)
|
||||||
|
|
||||||
|
kw = int(np.round(solar_panel_wattage / 1000))
|
||||||
|
|
||||||
|
self.recommendation = [
|
||||||
|
{
|
||||||
|
"parts": [],
|
||||||
|
"type": "solar_pv",
|
||||||
|
"description": f"Install a {kw} kilowatt-peak (kWp) solar photovoltaic (PV) panel system on the roof",
|
||||||
|
"starting_u_value": None,
|
||||||
|
"new_u_value": None,
|
||||||
|
"sap_points": None,
|
||||||
|
**cost_result,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue