diff --git a/conf/output_dictionaries/scorecards.yml b/conf/output_dictionaries/scorecards.yml new file mode 100644 index 0000000000000000000000000000000000000000..c5071987a3cca3120c665e06bd0247994eca7f8f --- /dev/null +++ b/conf/output_dictionaries/scorecards.yml @@ -0,0 +1,37 @@ +System: + system5c3s: + short_name: "ecmwfs5" + display_name: "ECMWF System 5" + system7c3s: + short_name: "meteofrances7" + display_name: "Meteo-France System 7" + system21_m1: + short_name: "dwds21" + display_name: "DWD System 21" + system35c3s: + short_name: "cmccs35" + display_name: "CMCC System 35" + system2c3s: + short_name: "jmas2" + display_name: "JMA System 2" + eccc1: + short_name: "ecccs1" + display_name: "ECCC System 1" + glosea6_system600-c3s: + short_name: "ukmos600" + display_name: "UK Met Office System 600" + ncep-cfsv2: + short_name: "nceps2" + display_name: "NCEP System 2" +Reference: + era5: + short_name: "era5" + display_name: "ERA5" + era5land: + short_name: "era5land" + display_name: "ERA5-Land" + uerra: + short_name: "uerra_mescan" + display_name: "UERRA MESCAN" + + diff --git a/modules/Loading/testing_recipes/recipe_seasonal-tests.yml b/modules/Loading/testing_recipes/recipe_seasonal-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..e1c3b56d671ee9302d604b55c59b73e05fb00a32 --- /dev/null +++ b/modules/Loading/testing_recipes/recipe_seasonal-tests.yml @@ -0,0 +1,46 @@ +Description: + Author: V. Agudetse + +Analysis: + Horizon: Seasonal + Variables: + name: tas + freq: monthly_mean + Datasets: + System: + name: system7c3s + Multimodel: False + Reference: + name: era5 + Time: + sdate: '1101' + fcst_year: '2020' + hcst_start: '2000' + hcst_end: '2015' + ftime_min: 1 + ftime_max: 2 + Region: + latmin: -10 + latmax: 10 + lonmin: 0 + lonmax: 20 + Regrid: + method: bilinear + type: to_system + Workflow: + Calibration: + method: mse_min + Skill: + metric: RPS RPSS CRPS CRPSS FRPSS BSS10 BSS90 EnsCorr Corr mean_bias mean_bias_SS + Probabilities: + percentiles: [[1/3, 2/3], [1/10, 9/10], [1/4, 2/4, 3/4]] + Indicators: + index: no + ncores: 7 + remove_NAs: yes + Output_format: Scorecards +Run: + Loglevel: INFO + Terminal: yes + output_dir: /esarchive/scratch/vagudets/repos/auto-s2s/out-logs/ + code_dir: /esarchive/scratch/vagudets/repos/auto-s2s/ diff --git a/modules/Saving/Saving.R b/modules/Saving/Saving.R index ed0933f2a6c053b0e2a51880a072213789310292..961baceebdfeec3de44635a034b1ba080d476893 100644 --- a/modules/Saving/Saving.R +++ b/modules/Saving/Saving.R @@ -273,9 +273,8 @@ save_forecast <- function(data_cube, time <- times$time # Generate name of output file - outfile <- get_filename(outdir, data_cube$Variable$varName, - fcst.sdate, fcst.sdate, - agg, fcst.horizon, "exp") + outfile <- get_filename(outdir, recipe, data_cube$Variable$varName, + fcst.sdate, agg, "exp") # Get grid data and metadata and export to netCDF if (tolower(agg) == "country") { @@ -409,9 +408,8 @@ save_observations <- function(data_cube, time <- times$time # Generate name of output file - outfile <- get_filename(outdir, data_cube$Variable$varName, - fcst.sdate, fcst.sdate, - agg, fcst.horizon, "obs") + outfile <- get_filename(outdir, recipe, data_cube$Variable$varName, + fcst.sdate, agg, "obs") # Get grid data and metadata and export to netCDF if (tolower(agg) == "country") { @@ -527,9 +525,8 @@ save_metrics <- function(skill, time <- times$time # Generate name of output file - outfile <- get_filename(outdir, data_cube$Variable$varName, - fcst.sdate, fcst.sdate, - agg, fcst.horizon, "skill") + outfile <- get_filename(outdir, recipe, data_cube$Variable$varName, + fcst.sdate, agg, "skill") # Get grid data and metadata and export to netCDF if (tolower(agg) == "country") { @@ -634,9 +631,8 @@ save_corr <- function(skill, time <- times$time # Generate name of output file - outfile <- get_filename(outdir, data_cube$Variable$varName, - fcst.sdate, fcst.sdate, - agg, fcst.horizon, "corr") + outfile <- get_filename(outdir, recipe, data_cube$Variable$varName, + fcst.sdate, agg, "corr") # Get grid data and metadata and export to netCDF if (tolower(agg) == "country") { @@ -734,9 +730,8 @@ save_percentiles <- function(percentiles, time <- times$time # Generate name of output file - outfile <- get_filename(outdir, data_cube$Variable$varName, - fcst.sdate, fcst.sdate, - agg, fcst.horizon, "percentiles") + outfile <- get_filename(outdir, recipe, data_cube$Variable$varName, + fcst.sdate, agg, "percentiles") # Get grid data and metadata and export to netCDF if (tolower(agg) == "country") { @@ -842,9 +837,8 @@ save_probabilities <- function(probs, time <- times$time # Generate name of output file - outfile <- get_filename(outdir, data_cube$Variable$varName, - fcst.sdate, fcst.sdate, - agg, fcst.horizon, "probs") + outfile <- get_filename(outdir, recipe, data_cube$Variable$varName, + fcst.sdate, agg, "probs") # Get grid data and metadata and export to netCDF if (tolower(agg) == "country") { diff --git a/modules/Saving/paths2save.R b/modules/Saving/paths2save.R index f48ebe7b058969568bee2c14d47394de18664c0e..2d6353fe67c78a78531ba80e3b953be064c81959 100644 --- a/modules/Saving/paths2save.R +++ b/modules/Saving/paths2save.R @@ -1,31 +1,54 @@ ## TODO: Separate by time aggregation -get_filename <- function(dir, var, date, fcst.sdate, agg, horizon, file.type) { +get_filename <- function(dir, recipe, var, date, agg, file.type) { # This function builds the path of the output file based on directory, # variable, forecast date, startdate, aggregation, forecast horizon and # type of metric/forecast/probability. - - if (horizon == "subseasonal") { - shortdate <- format(as.Date(as.character(fcst.sdate), "%Y%m%d"), "%V") + + if (recipe$Analysis$Horizon == "subseasonal") { + shortdate <- format(as.Date(as.character(date), "%Y%m%d"), "%V") dd <- "week" } else { - shortdate <- format(as.Date(as.character(fcst.sdate), "%Y%m%d"), "%m") + shortdate <- format(as.Date(as.character(date), "%Y%m%d"), "%m") dd <- "month" } - + switch(tolower(agg), "country" = {gg <- "-country"}, "global" = {gg <- ""}) - switch(file.type, - "skill" = {file <- paste0(var, gg, "-skill_", dd, shortdate)}, - "corr" = {file <- paste0(var, gg, "-corr_", dd, shortdate)}, - "exp" = {file <- paste0(var, gg, "_", date)}, - "obs" = {file <- paste0(var, gg, "-obs_", date)}, - "percentiles" = {file <- paste0(var, gg, "-percentiles_", dd, - shortdate)}, - "probs" = {file <- paste0(var, gg, "-probs_", date)}, - "bias" = {file <- paste0(var, gg, "-bias_", date)}) + if (tolower(recipe$Analysis$Output_format) == 'scorecards') { + # Define output dir name accordint to Scorecards format + dict <- read_yaml("conf/output_dictionaries/scorecards.yml") + # Get necessary names + system <- dict$System[[recipe$Analysis$Datasets$System$name]]$short_name + reference <- dict$Reference[[recipe$Analysis$Datasets$Reference$name]]$short_name + hcst_start <- recipe$Analysis$Time$hcst_start + hcst_end <- recipe$Analysis$Time$hcst_end + + switch(file.type, + "skill" = {type_info <- "-skill_"}, + "corr" = {type_info <- "-corr_"}, + "exp" = {type_info <- paste0("_", date, "_")}, + "obs" = {type_info <- paste0("-obs_", date, "_")}, + "percentiles" = {type_info <- "-percentiles_"}, + "probs" = {type_info <- paste0("-probs_", date, "_")}, + "bias" = {type_info <- paste0("-bias_", date, "_")}) + + # Build file name + file <- paste0("scorecards_", system, "_", reference, "_", + var, type_info, hcst_start, "-", hcst_end, "_s", shortdate) + } else { + switch(file.type, + "skill" = {file <- paste0(var, gg, "-skill_", dd, shortdate)}, + "corr" = {file <- paste0(var, gg, "-corr_", dd, shortdate)}, + "exp" = {file <- paste0(var, gg, "_", date)}, + "obs" = {file <- paste0(var, gg, "-obs_", date)}, + "percentiles" = {file <- paste0(var, gg, "-percentiles_", dd, + shortdate)}, + "probs" = {file <- paste0(var, gg, "-probs_", date)}, + "bias" = {file <- paste0(var, gg, "-bias_", date)}) + } return(paste0(dir, file, ".nc")) @@ -37,38 +60,49 @@ get_dir <- function(recipe, agg = "global") { # startdate, and aggregation. ## TODO: Get aggregation from recipe - ## TODO: Add time frequency outdir <- paste0(recipe$Run$output_dir, "/outputs/") + ## TODO: multivar case variable <- recipe$Analysis$Variables$name - if (!is.null(recipe$Analysis$Time$fcst_year)) { - if (tolower(recipe$Analysis$Horizon) == 'decadal') { - #PROBLEM: decadal doesn't have sdate - fcst.sdate <- paste0(recipe$Analysis$Time$fcst_year, collapse = '_') - } else { - fcst.sdate <- paste0(recipe$Analysis$Time$fcst_year, - recipe$Analysis$Time$sdate) - } + + if (tolower(recipe$Analysis$Output_format) == 'scorecards') { + # Define output dir name accordint to Scorecards format + dict <- read_yaml("conf/output_dictionaries/scorecards.yml") + system <- dict$System[[recipe$Analysis$Datasets$System$name]]$short_name + dir <- paste0(outdir, "/", system, "/", variable, "/") + } else { - if (tolower(recipe$Analysis$Horizon) == 'decadal') { - #PROBLEM: decadal doesn't have sdate - fcst.sdate <- paste0("hcst-", paste(recipe$Analysis$Time$hcst_start, recipe$Analysis$Time$hcst_end, sep = '_')) + # Default generic output format based on FOCUS + if (!is.null(recipe$Analysis$Time$fcst_year)) { + if (tolower(recipe$Analysis$Horizon) == 'decadal') { + #PROBLEM: decadal doesn't have sdate + fcst.sdate <- paste0(recipe$Analysis$Time$fcst_year, collapse = '_') + } else { + fcst.sdate <- paste0(recipe$Analysis$Time$fcst_year, + recipe$Analysis$Time$sdate) + } } else { - fcst.sdate <- paste0("hcst-", recipe$Analysis$Time$sdate) + if (tolower(recipe$Analysis$Horizon) == 'decadal') { + #PROBLEM: decadal doesn't have sdate + fcst.sdate <- paste0("hcst-", paste(recipe$Analysis$Time$hcst_start, + recipe$Analysis$Time$hcst_end, + sep = '_')) + } else { + fcst.sdate <- paste0("hcst-", recipe$Analysis$Time$sdate) + } } - } - - calib.method <- tolower(recipe$Analysis$Workflow$Calibration$method) - store.freq <- recipe$Analysis$Variables$freq - switch(tolower(agg), - "country" = {dir <- paste0(outdir, "/", calib.method, "-", - store.freq, "/", variable, - "_country/", fcst.sdate, "/")}, - "global" = {dir <- paste0(outdir, "/", calib.method, "-", - store.freq, "/", variable, "/", - fcst.sdate, "/")}) - + calib.method <- tolower(recipe$Analysis$Workflow$Calibration$method) + store.freq <- recipe$Analysis$Variables$freq + + switch(tolower(agg), + "country" = {dir <- paste0(outdir, "/", calib.method, "-", + store.freq, "/", variable, + "_country/", fcst.sdate, "/")}, + "global" = {dir <- paste0(outdir, "/", calib.method, "-", + store.freq, "/", variable, "/", + fcst.sdate, "/")}) + } return(dir) } diff --git a/modules/test_seasonal.R b/modules/test_seasonal.R index d8eb5c4eba48b064ad463dc52b6e863d02b0589e..fba75bfeefe3753ab331737c7d1e5361a730d554 100644 --- a/modules/test_seasonal.R +++ b/modules/test_seasonal.R @@ -4,7 +4,7 @@ source("modules/Skill/Skill.R") source("modules/Saving/Saving.R") source("modules/Visualization/Visualization.R") -recipe_file <- "modules/Loading/testing_recipes/recipe_system7c3s-tas.yml" +recipe_file <- "modules/Loading/testing_recipes/recipe_seasonal-tests.yml" recipe <- prepare_outputs(recipe_file) # archive <- read_yaml(paste0(recipe$Run$code_dir, "conf/archive.yml"))$archive