From f67668eb417d1f4077498afb792bc681020b2f99 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 7 Oct 2024 12:43:40 +0100 Subject: [PATCH] tweaking google solar api ranking algorithm --- backend/apis/GoogleSolarApi.py | 20 +++++++------------- backend/app/assumptions.py | 3 +++ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/backend/apis/GoogleSolarApi.py b/backend/apis/GoogleSolarApi.py index 606b6970..f6e1b96d 100644 --- a/backend/apis/GoogleSolarApi.py +++ b/backend/apis/GoogleSolarApi.py @@ -69,7 +69,7 @@ class GoogleSolarApi: self.floor_area = None self.roof_area = None self.roof_segment_indexes = None - self.panel_area = None + self.panel_area = assumptions.RDSAP_AREA_PER_PANEL self.panel_wattage = None self.panel_performance = None @@ -166,10 +166,6 @@ class GoogleSolarApi: self.roof_area = self.insights_data["solarPotential"]["wholeRoofStats"]['areaMeters2'] self.floor_area = self.insights_data["solarPotential"]["wholeRoofStats"]['groundAreaMeters2'] - self.panel_area = ( - self.insights_data["solarPotential"]["panelHeightMeters"] * - self.insights_data["solarPotential"]["panelWidthMeters"] - ) self.panel_wattage = self.insights_data["solarPotential"]["panelCapacityWatts"] if self.panel_wattage != 400: # In the API documentation, it claims that the default output is 250W, however we've only seen 400W, so if @@ -450,8 +446,8 @@ class GoogleSolarApi: # We want max roi, minimal generation deficit, and max generation value - we create a ranking score # Assign equal weights to each metric - weights = {'roi': 0.6, 'generation_value': 0.2, 'generation_deficit': 0.2} - metrics = panel_performance[['roi', 'generation_value', 'generation_deficit']] + weights = {'roi': 0.8, 'generation_value': 0.2} + metrics = panel_performance[['roi', 'generation_value']].copy() # Normalize the columns (0 to 1 scale) scaler = MinMaxScaler() @@ -459,12 +455,11 @@ class GoogleSolarApi: # Convert normalized metrics back to a dataframe normalized_metrics_df = pd.DataFrame( - normalized_metrics, columns=['roi', 'generation_value', 'generation_deficit'] + normalized_metrics, columns=['roi', 'generation_value'] ) normalized_metrics_df['combined_score'] = ( normalized_metrics_df['roi'] * weights['roi'] + - normalized_metrics_df['generation_value'] * weights['generation_value'] + - (1 - normalized_metrics_df['generation_deficit']) * weights['generation_deficit'] + normalized_metrics_df['generation_value'] * weights['generation_value'] ) panel_performance['combined_score'] = normalized_metrics_df['combined_score'].values @@ -799,7 +794,6 @@ class GoogleSolarApi: "panel_performance": solar_api_client.panel_performance, "unit_share_of_energy": 1 }, - roof_area=solar_api_client.roof_area ) return input_properties @@ -825,7 +819,7 @@ class GoogleSolarApi: n_panels=10, has_battery=False, n_floors=property_instance.number_of_floors )["total"], 'weighted_ratio': None, - 'panneled_roof_area': 10 * 1.8, + 'panneled_roof_area': 10 * assumptions.RDSAP_AREA_PER_PANEL, 'array_wattage': 4000, 'initial_ac_kwh_per_year': 4000 * 0.95, # Assumed 95% efficient wattage -> ac 'lifetime_ac_kwh': None, @@ -845,7 +839,7 @@ class GoogleSolarApi: n_panels=6, has_battery=False, n_floors=property_instance.number_of_floors )["total"], 'weighted_ratio': None, - 'panneled_roof_area': 6 * 1.8, + 'panneled_roof_area': 6 * assumptions.RDSAP_AREA_PER_PANEL, 'array_wattage': 2400, 'initial_ac_kwh_per_year': 2400 * 0.95, # Assumed 95% efficient wattage -> ac 'lifetime_ac_kwh': None, diff --git a/backend/app/assumptions.py b/backend/app/assumptions.py index 80baa69f..371b226d 100644 --- a/backend/app/assumptions.py +++ b/backend/app/assumptions.py @@ -7,6 +7,9 @@ AVERAGE_ASHP_EFFICIENCY = 250 # be exported SOLAR_CONSUMPTION_PROPORTION = 0.5 +# Typically, each solar panel takes up around 3.4 m2 of roof space under RdSAP. This was been verified in Elmhurst +RDSAP_AREA_PER_PANEL = 3.4 + DESCRIPTIONS_TO_FUEL_TYPES = { "Air source heat pump, radiators, electric": { "fuel": "Electricity", "cop": AVERAGE_ASHP_EFFICIENCY / 100