From 349d417ddad6dea165d3defffa7bbef1f1e305bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=2E=20M=C3=B8ller?= Date: Tue, 6 Oct 2026 09:32:17 +0200 Subject: [PATCH 1/6] Separate KNMI_MTG and KNMI_MSG configurations --- config.yaml | 15 ++++++++++++++- pyproject.toml | 2 +- sunflow/data_io.py | 18 +++++++++--------- sunflow/downloaders.py | 13 +++++++------ sunflow/main.py | 14 +++++++------- sunflow/validation.py | 8 ++++---- 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/config.yaml b/config.yaml index 70fa4c6..639d651 100644 --- a/config.yaml +++ b/config.yaml @@ -1,5 +1,5 @@ --- -KNMI: +KNMI_MSG: crs: EPSG:4326 format: NetCDF4 base_url: https://api.dataplatform.knmi.nl/wms/adaguc-server?dataset=msg_cpp_products&service=wcs&request=getcoverage& @@ -25,6 +25,19 @@ KNMI: # {second}: Two-digit second (e.g., 00) # Path separators are supported, e.g.: "{year}/{month}/{day}/{dataset_name}_{timestamp}.nc" +KNMI_MTG: + crs: EPSG:4326 + format: NetCDF4 + base_url: https://api.dataplatform.knmi.nl/wms/adaguc-server?dataset=mtg_cpp_products&service=wcs&request=getcoverage& + variables: + - surface_downwelling_shortwave_flux_in_air + - surface_downwelling_shortwave_flux_in_air_assuming_clear_sky + nc_variable_names: + sds: sds + sds_cs: sds_cs + filename_format: "NetCDF4_sds_{pds_timestamp}.nc" + input_data_frequency_minutes: 10 + DWD: base_url: https://opendata.dwd.de/weather/satellite/radiation/sis/ variables: diff --git a/pyproject.toml b/pyproject.toml index 485d61d..a693b62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "sunflow" version = "1.2.0" -description = "Solar nowcasting using probabilistic advection with KNMI/DWD satellite data" +description = "Optical flow solar nowcasting based on satellite data" authors = [ {name = "Irene Livia Kruse", email = "ikr@dmi.dk"}, {name = "Kristian Holten Møller", email = "khm@dmi.dk"}, diff --git a/sunflow/data_io.py b/sunflow/data_io.py index b487bde..5ea0aad 100644 --- a/sunflow/data_io.py +++ b/sunflow/data_io.py @@ -33,7 +33,7 @@ def fetch_current_data_with_retry( run_mode: One of 'download', 'files', or 's3' config: Dataset configuration dict domain_satellite: Domain string for required satellite input coverage - dataset_name: Name of dataset (options: KNMI, DWD) + dataset_name: Name of the dataset source. domain_satellite_name: Domain choice used in input filenames nowcast_config: NowcastConfig object s3_config: S3Config object @@ -119,7 +119,7 @@ def generate_input_filename( Args: time_step: Datetime of the data timestep. - dataset_name: Name of dataset (options: KNMI, DWD). + dataset_name: Name of the dataset source. domain_satellite_name: Satellite domain identifier. filename_format: Template string from config['filename_format']. @@ -127,7 +127,7 @@ def generate_input_filename( Filename string with all template variables substituted. Template variables supported: - {dataset_name}: Name of the dataset + {dataset_name}: Name of the dataset source {domain_satellite_name}: Satellite domain identifier {timestamp}: Compact format YYYYMMDDHHMM {pds_timestamp}: PDS format YYYY-MM-DDTHH_MM_SSZ @@ -174,7 +174,7 @@ def check_current_data_existence_file( Args: request_time: Python datetime object. - dataset_name: Name of dataset (options: KNMI, DWD). + dataset_name: Name of the dataset source. domain_satellite_name: Satellite domain identifier. satellite_data_directory: Directory containing data files. filename_format: Template string from config['filename_format']. @@ -214,7 +214,7 @@ def load_data_from_files( Args: time_steps: List of timesteps to load. - dataset_name: Name of dataset (options: KNMI, DWD). + dataset_name: Name of the dataset source. domain_satellite_name: Satellite domain identifier. satellite_data_directory: Directory containing data files. data_type: Type of data for logging (options: past data, clearsky data). @@ -273,7 +273,7 @@ def check_current_data_existence_s3( Args: request_time: Python datetime object. - dataset_name: Name of dataset (options: KNMI, DWD). + dataset_name: Name of the dataset source. domain_satellite_name: Satellite domain identifier. s3_config: S3 configuration object. filename_format: Template string from config['filename_format']. @@ -326,7 +326,7 @@ def load_data_from_s3( Args: time_steps: List of timesteps to load. - dataset_name: Name of dataset (options: KNMI, DWD). + dataset_name: Name of the dataset source. domain_satellite_name: Satellite domain identifier. s3_config: S3 configuration object. data_type: Type of data for logging (options: past data, clearsky data). @@ -395,7 +395,7 @@ def fetch_clearsky_with_fallback( filename_format: Template string for clear-sky files. config: Dataset configuration dict. bbox: Bounding box string. - dataset_name: Name of dataset (options: KNMI, DWD). + dataset_name: Name of the dataset source. domain_satellite_name: Satellite domain identifier. nowcast_config: NowcastConfig object. s3_config: S3Config object. @@ -498,7 +498,7 @@ def save_forecast( n_steps: Number of forecast time steps to write. latitudes: 1-D array of latitude values (degrees). longitudes: 1-D array of longitude values (degrees). - dataset_name: Name of the source dataset (options: KNMI, DWD). + dataset_name: Name of the dataset source. nowcast_config: NowcastConfig object supplying output directory and input data frequency. model_version: Model version string written as a global attribute. diff --git a/sunflow/downloaders.py b/sunflow/downloaders.py index 528776d..6a3f8e3 100644 --- a/sunflow/downloaders.py +++ b/sunflow/downloaders.py @@ -91,11 +91,11 @@ def download_current_data( config: Dataset configuration dict from config.yaml, including base_url, variables, format, crs, and filename_format. bbox: Bounding box string lon_min,lat_min,lon_max,lat_max. - dataset_name: Name of the dataset source (options: KNMI, DWD). + dataset_name: Name of the dataset source. domain_satellite_name: Satellite domain identifier used in the output filename. satellite_data_directory: Directory where the NetCDF file is saved. """ - if dataset_name == "KNMI": + if dataset_name in ["KNMI_MSG", "KNMI_MTG"]: datasets = [] for variable in config["variables"]: url = ( @@ -149,7 +149,7 @@ def download_past_data( time_steps: Ordered list of datetimes to download. config: Dataset configuration dict from config.yaml. bbox: Bounding box string lon_min,lat_min,lon_max,lat_max. - dataset_name: Name of the dataset source (options: KNMI, DWD). + dataset_name: Name of the dataset source. Returns: xarray Dataset concatenated along a 'time' dimension, with one @@ -160,7 +160,7 @@ def download_past_data( for time_step in time_steps: time_str = time_step.strftime("%Y-%m-%dT%H:%M:%SZ") - if dataset_name == "KNMI": + if dataset_name in ["KNMI_MSG", "KNMI_MTG"]: # Download each variable separately, then merge var_datasets: list[xr.Dataset] = [] failed_vars = [] @@ -170,6 +170,7 @@ def download_past_data( f"&CRS={config['crs']}&BBOX={bbox}&time={time_str}" ) url = f"{base_url}&coverage={var}" + logger.info(f"Downloading {var} for {time_str} from {url}") try: netcdf_file = download_netcdf_knmi(url, os.getenv("KNMI_API_KEY")) ds = xr.open_dataset(netcdf_file, engine="h5netcdf") @@ -231,7 +232,7 @@ def download_clearsky_data( (typically forecast lead times offset by one day). config: Dataset configuration dict from config.yaml. bbox: Bounding box string lon_min,lat_min,lon_max,lat_max. - dataset_name: Name of the dataset source (options: KNMI, DWD). + dataset_name: Name of the dataset source. Returns: xarray Dataset concatenated along a 'time' dimension, with one @@ -239,7 +240,7 @@ def download_clearsky_data( """ collected: list[xr.Dataset] = [] - if dataset_name == "KNMI": + if dataset_name in ["KNMI_MSG", "KNMI_MTG"]: var = config["variables"][1] # clearsky variable for time_step in time_steps: clearsky_time_str = time_step.strftime("%Y-%m-%dT%H:%M:%SZ") diff --git a/sunflow/main.py b/sunflow/main.py index 1be43f0..de6ab27 100644 --- a/sunflow/main.py +++ b/sunflow/main.py @@ -114,10 +114,11 @@ def parse_datetime_with_timezone(datetime_str: str) -> datetime: ) parser.add_argument( "--dataset", - choices=["KNMI", "DWD", "specMAGIC_MTG", "specMAGIC_MTG_pvlib"], - default="KNMI", - help="Dataset (default: KNMI): \n" - "KNMI: MSG-CPP data from KNMI\n" + choices=["KNMI_MSG", "KNMI_MTG", "DWD", "specMAGIC_MTG", "specMAGIC_MTG_pvlib"], + default="KNMI_MSG", + help="Dataset (default: KNMI_MSG): \n" + "KNMI_MSG: MSG-CPP data from KNMI\n" + "KNMI_MTG: MTG-CPP data from KNMI\n" "DWD: MSG-based data from DWD\n" "specMAGIC_MTG: MTG-based GHI data from specMAGIC\n" "specMAGIC_MTG_pvlib: MTG-based GHI data from specMAGIC with pvlib clearsky", @@ -235,7 +236,7 @@ def run_nowcast( config: Dataset configuration dict. domain_satellite: Domain string used for satellite input coverage. domain_nowcast: Domain string used for output cropping. - dataset_name: Name of dataset. + dataset_name: Name of the dataset source. domain_satellite_name: Domain identifier used for input filenames. nowcast_config: NowcastConfig object. s3_config: S3Config object. @@ -244,8 +245,7 @@ def run_nowcast( custom_time: If True, skip the retry wait loop on missing data. Returns: - Output filename on success, or None if the run was skipped - (e.g. sun too low or missing data in a time-span run). + RunResult object indicating the outcome of the nowcast. """ time_step_str = time_step.strftime("%Y-%m-%dT%H:%M:%SZ") logger.info(f"--- Running nowcast for {time_step_str} ---") diff --git a/sunflow/validation.py b/sunflow/validation.py index b32e475..7ebae7c 100644 --- a/sunflow/validation.py +++ b/sunflow/validation.py @@ -53,7 +53,7 @@ def validate_config(config: dict[str, Any], dataset_name: str) -> None: Args: config: Dataset configuration dict loaded from config.yaml. Requires the full config for the dataset to check for all required keys. - dataset_name: Name of the dataset (used in error messages). + dataset_name: Name of the dataset source. Raises: SystemExit: If any required key is absent. @@ -99,7 +99,7 @@ def validate_run_mode(run_mode: str, dataset_name: str) -> None: Args: run_mode: The requested run mode ('download', 'files', or 's3'). - dataset_name: Name of the dataset. + dataset_name: Name of the dataset source. Raises: SystemExit: If the run mode is incompatible with the dataset. @@ -119,12 +119,12 @@ def verify_environment_variables(run_mode: str, dataset_name: str) -> None: Args: run_mode: The mode in which the application is running ('download', 'files', 's3'). - dataset_name: Name of the dataset being used. + dataset_name: Name of the dataset source. Raises: SystemExit: If any required environment variable is missing. """ - if run_mode == "download" and dataset_name == "KNMI": + if run_mode == "download" and dataset_name in ["KNMI_MSG", "KNMI_MTG"]: if not os.getenv("KNMI_API_KEY"): logger.error("KNMI_API_KEY environment variable not set. Exiting.\n") sys.exit(1) From dacde97a6f802fa947399c03a01f87b0c9cce732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=2E=20M=C3=B8ller?= Date: Tue, 6 Oct 2026 09:39:28 +0200 Subject: [PATCH 2/6] Print default automatically --- sunflow/main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sunflow/main.py b/sunflow/main.py index de6ab27..1b5975b 100644 --- a/sunflow/main.py +++ b/sunflow/main.py @@ -105,7 +105,7 @@ def parse_datetime_with_timezone(datetime_str: str) -> datetime: "--run_mode", choices=["download", "files", "s3"], default="download", - help="Run mode (default: download): \n" + help="Run mode (default: %(default)s): \n" "download: fetch from API. For KNMI data, this requires " "KNMI_API_KEY environment variable\n" "files: read from local files\n" @@ -115,8 +115,8 @@ def parse_datetime_with_timezone(datetime_str: str) -> datetime: parser.add_argument( "--dataset", choices=["KNMI_MSG", "KNMI_MTG", "DWD", "specMAGIC_MTG", "specMAGIC_MTG_pvlib"], - default="KNMI_MSG", - help="Dataset (default: KNMI_MSG): \n" + default="KNMI_MTG", + help="Dataset (default: %(default)s): \n" "KNMI_MSG: MSG-CPP data from KNMI\n" "KNMI_MTG: MTG-CPP data from KNMI\n" "DWD: MSG-based data from DWD\n" @@ -127,7 +127,7 @@ def parse_datetime_with_timezone(datetime_str: str) -> datetime: "--domain_satellite", choices=DOMAIN_CHOICES, default="NW_EUROPE", - help="Domain required for satellite input coverage (default: NW_EUROPE)", + help="Domain required for satellite input coverage (default: %(default)s)", ) parser.add_argument( "--custom_domain_satellite", @@ -172,7 +172,7 @@ def parse_datetime_with_timezone(datetime_str: str) -> datetime: "--ensemble_members", type=int, default=1, - help="Number of ensemble members (default: 1)", + help="Number of ensemble members (default: %(default)s)", ) parser.add_argument( "--full_ensemble", From 8534a1e27dfe9538204ef10ad800a4c366bf6dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=2E=20M=C3=B8ller?= Date: Tue, 6 Oct 2026 10:47:38 +0200 Subject: [PATCH 3/6] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8483d79..acf1566 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `MIN_SOLAR_ELEVATION_DEGREES` (defaulting to 6 degrees) to configure the minimum maximum-corner solar elevation required to run [!15](https://github.com/dmidk/sunflow/pull/15), @JoachimKoenigslieb - Added configurations to run with MTG data with either calculated or pvlib clearsky [!23](https://github.com/dmidk/sunflow/pull/15), @KristianHMoller - Added the ability to provide more configuration parameters to config.yaml [!23](https://github.com/dmidk/sunflow/pull/15), @KristianHMoller +- Added configuration for KNMI_MTG and made it the new defualt [!26](https://github.com/dmidk/sunflow/pull/26), @KristianHMoller ### Changed - Use `.expand_dims` instead of `.assign_coords` to make sure we have both time dimension and time coordinates when loading from files [!15](https://github.com/dmidk/sunflow/pull/15), @JoachimKoenigslieb From 318c9fb0a5a9c8841561ff105d1cb6559c1046b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=2E=20M=C3=B8ller?= Date: Tue, 6 Oct 2026 11:16:23 +0200 Subject: [PATCH 4/6] Update readme --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 55b8096..7a2cce2 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Framework for real-time satellite-based solar irradiance nowcasting at the Danis ## Overview This application performs short-term solar irradiance forecasting using: -- Real-time gridded surface solar irradiance products from processed geostationary satellite-data: [KNMI MSG-CPP](https://dataplatform.knmi.nl/dataset/msg-cpp-products-1-0) and [DWD SIS](https://opendata.dwd.de/weather/satellite/radiation/sis/) +- Real-time gridded surface solar irradiance products from processed geostationary satellite-data: [KNMI MSG-CPP](https://dataplatform.knmi.nl/dataset/msg-cpp-products-1-0), [KNMI MTG-CPP](https://dataplatform.knmi.nl/dataset/mtg-cpp-products-1-0) and [DWD SIS](https://opendata.dwd.de/weather/satellite/radiation/sis/) - Optical flow motion field computation with the Lucas-Kanade method applied to computed clear-sky indices -- Probabilistic advection for forecast generation, based on [SolarSTEPS](https://github.com/EnergyWeatherAI/SolarSTEPS) in deterministic mode +- Probabilistic advection for forecast generation, based on [SolarSTEPS](https://github.com/EnergyWeatherAI/SolarSTEPS) - Solar irradiance nowcasts calculated using clear-sky data from the previous day ## Fetching the source code @@ -65,7 +65,7 @@ To start a basic run, simply type the command below. This will start the default podman run --rm sunflow ``` -To run for a specific time, specify this when calling the container in the ISO8601 format. Only multiples of 15 minutes are available. Input data from KNMI is available going back one week. Other input can be specified in the same way. +To run for a specific time, specify this when calling the container in the ISO8601 format. Input data from KNMI is available going back one week. Other input can be specified in the same way. ```shell podman run --rm sunflow --time 2025-10-27T10:00Z @@ -134,7 +134,7 @@ podman run -it --rm --entrypoint="" sunflow bash ### Arguments -- `--dataset` - Choose between KNMI or DWD data sources +- `--dataset` - Choose between input data sources - `--domain_satellite` - Domain for required satellite input coverage (DENMARK, NW_EUROPE, NW_EUROPE_SATELLITE, CUSTOM) - `--custom_domain_satellite` - Custom `domain_satellite` (lon_min,lat_min,lon_max,lat_max) - `--domain_nowcast` - Domain written to output (DENMARK, NW_EUROPE, NW_EUROPE_SATELLITE, CUSTOM, defaults to `--domain_satellite`) @@ -152,8 +152,9 @@ all members instead. ## Data Sources -- **KNMI**: MSG-CPP products — requires a free API key from the [KNMI Data Platform](https://dataplatform.knmi.nl/dataset/access/msg-cpp-products-1-0) +- **KNMI**: MSG-CPP and MTG-CPP products — requires a free API key from the [KNMI Data Platform](https://dataplatform.knmi.nl/dataset/access/msg-cpp-products-1-0) - **DWD**: Surface Incoming Shortwave radiation (SIS) — publicly available, no API key required +- **specMAGIC_\***: GHI produced using the open-source [specMAGIC](https://github.com/dmidk/specMAGIC) code ## Installing locally Building pysteps can sometimes fail if a pre-built wheel is not available for your Python version. If the environment variables `CC` and `CXX` are not set, building pysteps falls back to clang, which may only work on Intel-based macOS. To use GNU compilers instead: From d48f69de1cfb4fef0f1d2a7d9989b2e23f9de6e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=2E=20M=C3=B8ller?= Date: Mon, 26 Oct 2026 09:37:05 +0100 Subject: [PATCH 5/6] Restore accidental changes --- CHANGELOG.md | 2 ++ pyproject.toml | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c700369..02c7e0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `{second}` and `{minute}` as a filename formatting variable [!15](https://github.com/dmidk/sunflow/pull/15), @JoachimKoenigslieb - Added a `clearsky` config object which can load clear-sky data from files via `clearsky.path` or generate it with `pvlib` via the `simplified_solis` method [!15](https://github.com/dmidk/sunflow/pull/15), @JoachimKoenigslieb - Added `MIN_SOLAR_ELEVATION_DEGREES` (defaulting to 6 degrees) to configure the minimum maximum-corner solar elevation required to run [!15](https://github.com/dmidk/sunflow/pull/15), @JoachimKoenigslieb +- Added configurations to run with MTG data with either calculated or pvlib clearsky [!24](https://github.com/dmidk/sunflow/pull/24), @KristianHMoller +- Added the ability to provide more configuration parameters to config.yaml [!24](https://github.com/dmidk/sunflow/pull/24), @KristianHMoller - Added to option to bypass SSL verification in S3 reading and writing [!27](https://github.com/dmidk/sunflow/pull/27), @KristianHMoller ### Changed diff --git a/pyproject.toml b/pyproject.toml index ace0aff..0bb2caa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,6 @@ name = "sunflow" version = "1.3.0" description = "Optical flow solar nowcasting based on satellite data" - authors = [ {name = "Irene Livia Kruse", email = "ikr@dmi.dk"}, {name = "Kristian Holten Møller", email = "khm@dmi.dk"}, From 1ce8698530ef26823ce12f436a08066dfadaaf79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=2E=20M=C3=B8ller?= Date: Thu, 5 Nov 2026 10:17:31 +0100 Subject: [PATCH 6/6] Made satellite a required field in config.yaml --- CHANGELOG.md | 3 ++- config.yaml | 5 +++++ sunflow/data_io.py | 3 +++ sunflow/main.py | 3 ++- sunflow/validation.py | 2 +- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c7e0c..1b72dcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Added configuration for KNMI_MTG and made it the new defualt [!26](https://github.com/dmidk/sunflow/pull/26), @KristianHMoller +- Added configuration for KNMI_MTG [!26](https://github.com/dmidk/sunflow/pull/26), @KristianHMoller +- Added `satellite` as a required field in config.yaml to be printed in the outpt file [!26](https://github.com/dmidk/sunflow/pull/26), @KristianHMoller ## [v1.3.0] diff --git a/config.yaml b/config.yaml index 639d651..2f842aa 100644 --- a/config.yaml +++ b/config.yaml @@ -24,6 +24,7 @@ KNMI_MSG: # {hour}: Two-digit hour (e.g., 12) # {second}: Two-digit second (e.g., 00) # Path separators are supported, e.g.: "{year}/{month}/{day}/{dataset_name}_{timestamp}.nc" + satellite: Meteosat Second Generation (MSG) KNMI_MTG: crs: EPSG:4326 @@ -37,6 +38,7 @@ KNMI_MTG: sds_cs: sds_cs filename_format: "NetCDF4_sds_{pds_timestamp}.nc" input_data_frequency_minutes: 10 + satellite: Meteosat Third Generation (MTG) DWD: base_url: https://opendata.dwd.de/weather/satellite/radiation/sis/ @@ -49,6 +51,7 @@ DWD: # Required: Filename format for input data files # Supports subdirectories via path separators, e.g.: "{year}/{month}/{day}/{dataset_name}_{timestamp}_{domain_satellite_name}.nc" filename_format: "{dataset_name}_{timestamp}_{domain_satellite_name}.nc" + satellite: Meteosat Second Generation (MSG) specMAGIC_MTG: nc_variable_names: @@ -59,6 +62,7 @@ specMAGIC_MTG: clearsky: method: file path: "CSR/CSR{year}{month}{day}{hour}{minute}.nc" + satellite: Meteosat Third Generation (MTG) specMAGIC_MTG_pvlib: nc_variable_names: @@ -68,3 +72,4 @@ specMAGIC_MTG_pvlib: input_data_frequency_minutes: 10 clearsky: method: pvlib + satellite: Meteosat Third Generation (MTG) diff --git a/sunflow/data_io.py b/sunflow/data_io.py index cb076ed..e96e2cb 100644 --- a/sunflow/data_io.py +++ b/sunflow/data_io.py @@ -486,6 +486,7 @@ def save_forecast( latitudes: np.ndarray, longitudes: np.ndarray, dataset_name: str, + satellite: str, nowcast_config: NowcastConfig, model_version: str, output_mode: str, @@ -506,6 +507,7 @@ def save_forecast( latitudes: 1-D array of latitude values (degrees). longitudes: 1-D array of longitude values (degrees). dataset_name: Name of the dataset source. + satellite: Satellite platform name written as a global attribute. nowcast_config: NowcastConfig object supplying output directory and input data frequency. model_version: Model version string written as a global attribute. @@ -616,6 +618,7 @@ def save_forecast( f"using {dataset_name} data" ), "output_mode": output_mode, + "satellite": satellite, "history": ( f"Created " f"{datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S')} UTC" diff --git a/sunflow/main.py b/sunflow/main.py index 1b5975b..fb9feaa 100644 --- a/sunflow/main.py +++ b/sunflow/main.py @@ -115,7 +115,7 @@ def parse_datetime_with_timezone(datetime_str: str) -> datetime: parser.add_argument( "--dataset", choices=["KNMI_MSG", "KNMI_MTG", "DWD", "specMAGIC_MTG", "specMAGIC_MTG_pvlib"], - default="KNMI_MTG", + default="KNMI_MSG", help="Dataset (default: %(default)s): \n" "KNMI_MSG: MSG-CPP data from KNMI\n" "KNMI_MTG: MTG-CPP data from KNMI\n" @@ -509,6 +509,7 @@ def run_nowcast( latitudes, longitudes, dataset_name, + config["satellite"], nowcast_config, model_version, output_mode, diff --git a/sunflow/validation.py b/sunflow/validation.py index 7ebae7c..297950d 100644 --- a/sunflow/validation.py +++ b/sunflow/validation.py @@ -58,7 +58,7 @@ def validate_config(config: dict[str, Any], dataset_name: str) -> None: Raises: SystemExit: If any required key is absent. """ - required_keys = ["filename_format"] + required_keys = ["filename_format", "satellite"] missing = [k for k in required_keys if k not in config] if missing: logger.error(