diff --git a/india_forecast_app/app.py b/india_forecast_app/app.py index 9889e4f..324032c 100644 --- a/india_forecast_app/app.py +++ b/india_forecast_app/app.py @@ -149,6 +149,7 @@ def get_model( hf_repo: str, hf_version: str, name: str, + smooth_blocks: Optional[int] = 0, ) -> PVNetModel: """ Instantiates and returns the forecast model ready for running inference @@ -160,6 +161,7 @@ def get_model( hf_repo: ID of the ML model used for the forecast hf_version: Version of the ML model used for the forecast name: Name of the ML model used for the forecast + smooth_blocks: Number of blocks to smooth the forecast by Returns: A forecasting model @@ -169,7 +171,13 @@ def get_model( model_cls = PVNetModel model = model_cls( - asset_type, timestamp, generation_data, hf_repo=hf_repo, hf_version=hf_version, name=name + asset_type, + timestamp, + generation_data, + hf_repo=hf_repo, + hf_version=hf_version, + name=name, + smooth_blocks=smooth_blocks, ) return model @@ -363,6 +371,7 @@ def app_run(timestamp: dt.datetime | None, write_to_db: bool = False, log_level: hf_repo=model_config.id, hf_version=model_config.version, name=model_config.name, + smooth_blocks=model_config.smooth_blocks, ) ml_model.site_uuid = site.site_uuid diff --git a/india_forecast_app/models/all_models.yaml b/india_forecast_app/models/all_models.yaml index 053224c..bbd85c1 100644 --- a/india_forecast_app/models/all_models.yaml +++ b/india_forecast_app/models/all_models.yaml @@ -7,24 +7,28 @@ models: version: ae07c15de064e1d03cf4bc02618b65c6d5b17e8e client: ruvnl asset_type: wind + smooth_blocks: 4 - name: windnet_india_mo type: pvnet id: openclimatefix/windnet_india version: 546baded3d4216736d8ee8d6798d47235bd72b08 client: ruvnl asset_type: wind + smooth_blocks: 7 - name: windnet_india_mo_v2 type: pvnet id: openclimatefix/windnet_india version: 165267d34500cf0c881ed70d9318421f4e0d10f1 client: ruvnl asset_type: wind + smooth_blocks: 4 - name: windnet_india_mo_v3 type: pvnet id: openclimatefix/windnet_india version: 990bed9ad1dbb10515f830c181609b10e72c975e client: ruvnl asset_type: wind + smooth_blocks: 7 # RU client solar - name: pvnet_india type: pvnet diff --git a/india_forecast_app/models/dummy.py b/india_forecast_app/models/dummy.py index 704cd84..39d22c6 100644 --- a/india_forecast_app/models/dummy.py +++ b/india_forecast_app/models/dummy.py @@ -5,6 +5,7 @@ import datetime as dt import math import random +from typing import Optional import pandas as pd import pytz @@ -21,13 +22,14 @@ def version(self): return "0.0.0" def __init__( - self, - asset_type: str, - timestamp: dt.datetime, - generation_data: dict[str, pd.DataFrame] = None, - hf_version: str = None, - hf_repo: str = None, - name: str = None, + self, + asset_type: str, + timestamp: dt.datetime, + generation_data: dict[str, pd.DataFrame] = None, + hf_version: str = None, + hf_repo: str = None, + name: str = None, + smooth_blocks: Optional[int] = 0, ): """Initializer for the model""" self.asset_type = asset_type diff --git a/india_forecast_app/models/pvnet/model.py b/india_forecast_app/models/pvnet/model.py index 086ecb0..fb416a1 100644 --- a/india_forecast_app/models/pvnet/model.py +++ b/india_forecast_app/models/pvnet/model.py @@ -7,6 +7,7 @@ import os import shutil import tempfile +from typing import Optional import numpy as np import pandas as pd @@ -63,6 +64,7 @@ def __init__( hf_repo: str, hf_version: str, name: str, + smooth_blocks: Optional[int] = 0, ): """Initializer for the model""" @@ -72,6 +74,7 @@ def __init__( self.name = name self.site_uuid = None self.t0 = timestamp + self.smooth_blocks = smooth_blocks log.info(f"Model initialised at t0={self.t0}") self.client = os.getenv("CLIENT_NAME", "ruvnl") @@ -181,14 +184,17 @@ def predict(self, site_id: str, timestamp: dt.datetime): ) * smooth_values[final_gen_index + idx] log.debug(f"New values are {values_df['forecast_power_kw']}") - if self.asset_type == "wind": - # Smooth with a 1 hour rolling window - # Only smooth the wind else we introduce too much of a lag in the solar - # going up and down throughout the day + if self.smooth_blocks > 0: + log.info(f"Smoothing the forecast with {self.smooth_blocks} blocks") values_df["forecast_power_kw"] = ( - values_df["forecast_power_kw"].rolling(4, min_periods=1).mean().astype(int) + values_df["forecast_power_kw"] + .rolling(window=self.smooth_blocks, min_periods=1, center=True) + .mean() ) + # convert to int + values_df["forecast_power_kw"] = values_df["forecast_power_kw"].astype(int) + # remove any negative values values_df["forecast_power_kw"] = values_df["forecast_power_kw"].clip(lower=0.0) diff --git a/india_forecast_app/models/pydantic_models.py b/india_forecast_app/models/pydantic_models.py index 1de3a50..eb95f7a 100644 --- a/india_forecast_app/models/pydantic_models.py +++ b/india_forecast_app/models/pydantic_models.py @@ -32,14 +32,22 @@ class Model(BaseModel): 60, title="Average Minutes", description="The number of minutes that results are average over when " - "calculating adjuster values. " - "For solar site with regular data, 15 should be used. " - "For wind sites, 60 minutes should be used.", + "calculating adjuster values. " + "For solar site with regular data, 15 should be used. " + "For wind sites, 60 minutes should be used.", + ) + smooth_blocks: int = Field( + 0, + title="Smooth Blocks", + description="The number of blocks to smooth the forecast by. " + "We use a central smoothing and each block is 15mins, " + "so 5 would be smoothing from 30s before and afterwards", ) class Models(BaseModel): - """ A group of ml models """ + """A group of ml models""" + models: List[Model] = Field( ..., title="Models", description="A list of models to use for the forecast" )