diff --git a/examples/example.py b/examples/example.py index 2b928c7d..14fe07bd 100644 --- a/examples/example.py +++ b/examples/example.py @@ -8,6 +8,8 @@ def main(): site = PVSite(latitude=51.75, longitude=-1.25, capacity_kwp=1.25) ts = datetime.today() - timedelta(weeks=1) + + # User has three options for the 'nwp_source': 'icon', 'gfs', or 'ukmo'. predictions_df = run_forecast(site=site, ts=ts, nwp_source="icon") print(predictions_df) diff --git a/quartz_solar_forecast/data.py b/quartz_solar_forecast/data.py index 084f2b88..38e26c8b 100644 --- a/quartz_solar_forecast/data.py +++ b/quartz_solar_forecast/data.py @@ -21,7 +21,7 @@ def get_nwp(site: PVSite, ts: datetime, nwp_source: str = "icon") -> xr.Dataset: :param site: the PV site :param ts: the timestamp for when you want the forecast for - :param nwp_source: the nwp data source. Either "gfs" or "icon". Defaults to "icon" + :param nwp_source: the nwp data source. Either "gfs", "icon" or "ukmo". Defaults to "icon" :return: nwp forecast in xarray """ @@ -55,25 +55,31 @@ def get_nwp(site: PVSite, ts: datetime, nwp_source: str = "icon") -> xr.Dataset: url = "https://archive-api.open-meteo.com/v1/archive" else: - - # Getting NWP from open meteo weather forecast API by ICON or GFS model within the last 3 months - url_nwp_source = None + # Getting NWP from open meteo weather forecast API by ICON, GFS, or UKMO within the last 3 months if nwp_source == "icon": url_nwp_source = "dwd-icon" + url = f"https://api.open-meteo.com/v1/{url_nwp_source}" elif nwp_source == "gfs": url_nwp_source = "gfs" + url = f"https://api.open-meteo.com/v1/{url_nwp_source}" + elif nwp_source == "ukmo": + url = "https://api.open-meteo.com/v1/forecast" else: - raise Exception(f'Source ({nwp_source}) must be either "icon" or "gfs"') - - url = f"https://api.open-meteo.com/v1/{url_nwp_source}" + raise Exception(f'Source ({nwp_source}) must be either "icon", "gfs", or "ukmo"') params = { - "latitude": site.latitude, - "longitude": site.longitude, - "start_date": f"{start}", - "end_date": f"{end}", - "hourly": variables + "latitude": site.latitude, + "longitude": site.longitude, + "start_date": f"{start}", + "end_date": f"{end}", + "hourly": variables } + + # Add the "models" parameter if using "ukmo" + if nwp_source == "ukmo": + params["models"] = "ukmo_seamless" + + # Make API call to URL response = openmeteo.weather_api(url, params=params) hourly = response[0].Hourly() diff --git a/quartz_solar_forecast/forecast.py b/quartz_solar_forecast/forecast.py index 41b45336..7cc7f2dd 100644 --- a/quartz_solar_forecast/forecast.py +++ b/quartz_solar_forecast/forecast.py @@ -16,7 +16,7 @@ def predict_ocf( :param site: the PV site :param model: the model to use for prediction :param ts: the timestamp of the site. If None, defaults to the current timestamp rounded down to 15 minutes. - :param nwp_source: the nwp data source. Either "gfs" or "icon". Defaults to "icon" + :param nwp_source: the nwp data source. Either "gfs", "icon" or "ukmo". Defaults to "icon" :return: The PV forecast of the site for time (ts) for 48 hours """ if ts is None: @@ -103,7 +103,7 @@ def run_forecast( :param model: the model to use for prediction, choose between "ocf" and "tryolabs", by default "ocf" is used :param ts: the timestamp of the site. If None, defaults to the current timestamp rounded down to 15 minutes. - :param nwp_source: the nwp data source. Either "gfs" or "icon". Defaults to "icon" + :param nwp_source: the nwp data source. Either "gfs", "icon" or "ukmo". Defaults to "icon" (only relevant if model=="gb") :return: The PV forecast of the site for time (ts) for 48 hours """ diff --git a/tests/test_forecast.py b/tests/test_forecast.py index eab40ab4..975103aa 100644 --- a/tests/test_forecast.py +++ b/tests/test_forecast.py @@ -7,9 +7,10 @@ def test_run_forecast(): site = PVSite(latitude=51.75, longitude=-1.25, capacity_kwp=1.25) ts = datetime.today() - timedelta(weeks=2) - # run model with icon and gfs nwp + # run model with icon, gfs and ukmo nwp predications_df_gfs = run_forecast(site=site, model="gb", ts=ts, nwp_source="gfs") predications_df_icon = run_forecast(site=site, model="gb", ts=ts, nwp_source="icon") + predications_df_ukmo = run_forecast(site=site, model="gb", ts=ts, nwp_source="ukmo") predications_df_xgb = run_forecast(site=site, ts=ts) print("\n Prediction based on GFS NWP\n") @@ -20,6 +21,10 @@ def test_run_forecast(): print(predications_df_icon) print(f" Max: {predications_df_icon['power_kw'].max()}") + print("\n Prediction based on UKMO NWP\n") + print(predications_df_ukmo) + print(f" Max: {predications_df_ukmo['power_kw'].max()}") + print("\n Prediction based on XGB\n") print(predications_df_xgb) print(f" Max: {predications_df_xgb['power_kw'].max()}") @@ -31,9 +36,10 @@ def test_run_forecast_historical(): site = PVSite(latitude=51.75, longitude=-1.25, capacity_kwp=1.25) ts = datetime.today() - timedelta(days=200) - # run model with icon and gfs nwp + # run model with icon, gfs and ukmo nwp predications_df_gfs = run_forecast(site=site, ts=ts, model="gb", nwp_source="gfs") predications_df_icon = run_forecast(site=site, ts=ts, model="gb", nwp_source="icon") + predications_df_ukmo = run_forecast(site=site, ts=ts, model="gb", nwp_source="ukmo") predications_df_xgb = run_forecast(site=site, ts=ts, model="xgb") print("\nPrediction for a date more than 180 days in the past") @@ -45,6 +51,10 @@ def test_run_forecast_historical(): print("\n Prediction based on ICON NWP\n") print(predications_df_icon) print(f" Max: {predications_df_icon['power_kw'].max()}") + + print("\n Prediction based on UKMO NWP\n") + print(predications_df_ukmo) + print(f" Max: {predications_df_ukmo['power_kw'].max()}") print("\n Prediction based on XGB\n") print(predications_df_xgb)