diff --git a/conf/archive_seasonal.yml b/conf/archive_seasonal.yml index 03ed1636bc3ff5f6d03d7701afd5d83d75c4e3e8..b98d92786d296642e8c7cb71fce049b04dc25f30 100644 --- a/conf/archive_seasonal.yml +++ b/conf/archive_seasonal.yml @@ -24,6 +24,13 @@ gpfs: name: "ECMWF SEAS5 (v5.1)" institution: "European Centre for Medium-Range Weather Forecasts" src: "exp/ecmwf/system51c3s/" + daily_mean: {"tas":"daily_mean/tas_f6h/", "rsds":"daily/rsds_s0-24h/", + "prlr":"daily/prlr_s0-24h/", "tasmin":"daily/tasmin/", + "tasmax":"daily/tasmax/", "sfcWind":"daily_mean/sfcWind_f6h/", + "ta300":"daily_mean/ta300_f12h/", "ta500":"daily_mean/ta500_f12h/", + "ta850":"daily_mean/ta850_f12h/", "g300":"daily_mean/g300_f12h/", + "g500":"daily_mean/g500_f12h/", "g850":"daily_mean/g850_f12h/", + "tdps":"daily_mean/tdps_f6h/", "hurs":"daily_mean/hurs_f6h/"} monthly_mean: {"tas":"monthly_mean/tas_f6h/", "tasmax":"monthly_mean/tasmax_f24h/", "tasmin":"monthly_mean/tasmin_f24h/", diff --git a/conf/archive_subseasonal.yml b/conf/archive_subseasonal.yml index a0ec9bf1a5d140ab04a04756d8720dca599d8bc9..ecfe9bcf601286e6b886c33dad5e1f582d8f8c9f 100644 --- a/conf/archive_subseasonal.yml +++ b/conf/archive_subseasonal.yml @@ -16,9 +16,9 @@ gpfs: NCEP-CFSv2: name: "NCEP CFSv2" institution: "NOAA NCEP" #? + src: "exp/ncep/cfs-v2/" srchc: "exp/ncep/cfs-v2/" srcfc: "exp/ncep/cfs-v2/" - src: "exp/ncep/cfs-v2/" weekly_mean: {"tas":"weekly_mean/s2s/tas_f24h/", "prlr":"weekly_mean/s2s/prlr_f24h/", "tasmax":"weekly_mean/s2s/tasmax_f24h/", @@ -26,7 +26,7 @@ gpfs: "sfcWind":"weekly_mean/s2s/sfcWind_f24h/", "rsds":"weekly_mean/s2s/rsds_f24h/", "psl":"weekly_mean/s2s/psl_f24h/"} - daily_mean: {"tas":"daily_mean/s2s/tas_f6h", + daily_mean: {"tas":"daily_mean/s2s/tas_f6h/", "prlr":"daily_mean/s2s/prlr_f6h/", "psl":"daily_mean/s2s/psl_f6h/"} nmember: diff --git a/modules/Loading/R/dates2load.R b/modules/Loading/R/dates2load.R index a21795865d00baae7e14e9c8b378a1341ea5a4bb..16e24647338c60eaf93d62ef41b58b34b84e387f 100644 --- a/modules/Loading/R/dates2load.R +++ b/modules/Loading/R/dates2load.R @@ -23,6 +23,11 @@ dates2load <- function(recipe, logger) { temp_freq <- recipe$Analysis$Variables$freq system_name <- recipe$Analysis$Datasets$System$name recipe <- recipe$Analysis$Time + + ## TODO: May be needed for subseasonal daily + # if (nchar(recipe$sdate) == 8 &&) { + # recipe$sdate <- substr(recipe$sdate, 5, 8) + # } if (temp_freq == "monthly_mean") { # hcst dates file_dates <- paste0(strtoi(recipe$hcst_start):strtoi(recipe$hcst_end), @@ -37,7 +42,6 @@ dates2load <- function(recipe, logger) { paste("January 1993 start date is not available for", system_name, "and has been removed from the list of start dates.")) } - ## TODO: Add dims? file_dates <- .add_dims(file_dates) } else if (temp_freq == "weekly_mean") { sday <- recipe$sday_window @@ -71,23 +75,24 @@ dates2load <- function(recipe, logger) { ftime_max = recipe$ftime_max, out = 'hcst') } else { file_dates <- paste0(strtoi(recipe$hcst_start):strtoi(recipe$hcst_end), - recipe$sdate) + recipe$sdate) + file_dates <- .add_dims(file_dates) } # fcst dates (if fcst_year empty it creates an empty object) - if (! is.null(recipe$fcst_year)) { - if (temp_freq == "monthly_mean") { + if (!is.null(recipe$fcst_year)) { + if (temp_freq == "monthly_mean" || temp_freq == "daily_mean") { file_dates.fcst <- paste0(recipe$fcst_year, recipe$sdate) file_dates.fcst <- .add_dims(file_dates.fcst) } else if (temp_freq == "weekly_mean") { file_dates.fcst <- subseas_file_dates(startdate = fcst.sdate_to_start, - n.skill.weeks = n.skill.weeks, - n.days = sday, - hcst.start = as.numeric(recipe$hcst_start), - hcst.end = as.numeric(recipe$hcst_end), - ftime_min = recipe$ftime_min, - ftime_max = recipe$ftime_max, out = 'fcst') + n.skill.weeks = n.skill.weeks, + n.days = sday, + hcst.start = as.numeric(recipe$hcst_start), + hcst.end = as.numeric(recipe$hcst_end), + ftime_min = recipe$ftime_min, + ftime_max = recipe$ftime_max, out = 'fcst') } else { - file_dates.fcst <- paste0(recipe$fcst_year, recipe$sdate) + stop("Unknown temporal frequency.") } } else { # if no fcst year is requested: diff --git a/modules/Loading/R/load_subseasonal.R b/modules/Loading/R/load_subseasonal.R index dba21ee1e868fab210e4158377b31c32a216ba2d..97623b0212e69b04d29eebf2577b82becb0f1b00 100644 --- a/modules/Loading/R/load_subseasonal.R +++ b/modules/Loading/R/load_subseasonal.R @@ -57,6 +57,10 @@ load_subseasonal <- function(recipe) { if (store.freq %in% c("daily", "daily_mean")) { frequency <- "daily_mean" + ## TODO: In subseasonal, number of members may be different depending on + ## frequency. Code needs to be adjusted + fcst.nmember <- fcst.nmember/3 + hcst.nmember <- hcst.nmember/3 } else if (store.freq == "weekly_mean") { frequency <- "weekly_mean" } @@ -142,8 +146,7 @@ load_subseasonal <- function(recipe) { } # Convert hcst to s2dv_cube object - ## TODO: Give correct dimensions to $Dates - ## (sday, sweek, syear instead of file_date) + hcst_dates <- attr(hcst, "Variables")$common$time hcst <- as.s2dv_cube(hcst) # Adjust dates for models where the time stamp goes into the next month if (recipe$Analysis$Variables$freq == "monthly_mean") { @@ -163,7 +166,6 @@ load_subseasonal <- function(recipe) { var_dir_depends = 'var', file_date = sdates$fcst, time = recipe$Analysis$Time$ftime_min:recipe$Analysis$Time$ftime_max, - latitude = values(list(lats.min, lats.max)), latitude_reorder = Sort(), longitude = values(list(lons.min, lons.max)), @@ -223,21 +225,38 @@ load_subseasonal <- function(recipe) { # Obtain dates and date dimensions from the loaded hcst data to make sure # the corresponding observations are loaded correctly. - dates <- as.POSIXlt(hcst$attrs$Dates) - # Hcst files metadata are 3 days ahead of Obs files names: - ## TODO: Is this true in general, or only for a specific case (NCEPv2 + ERA5)? - dates$mday <- dates$mday - 3 - dates <- as.POSIXct(dates) - dim(dates) <- hcst$dims[c("sday", "sweek", "syear", "time")] - # Separate Start() call for monthly vs daily data + ## TODO: Generalize to other models + dates <- Apply(sdates$hcst, + margins = list(x = c("syear", "sweek", "sday")), + fun = function(x, idx_min, idx_max) { + x <- as.POSIXct(x, format = "%Y%m%d", tz = "UTC") %m+% weeks(idx_min:idx_max) %m+% days(4) + return(as.array(x)) + }, + output_dims = c("time"), + idx_min = recipe$Analysis$Time$ftime_min - 1, + idx_max = recipe$Analysis$Time$ftime_max - 1, + ncores = 1)[[1]] + dates <- Reorder(dates, c("sday", "sweek", "syear", "time")) + dates_dims <- dim(dates) + dates <- as.POSIXct(dates, origin = "1970-01-01", tz = "UTC") + dates <- format(dates, "%Y%m%d") + dim(dates) <- dates_dims + + if (any(is.na(hcst_dates))) { + warn(recipe$Run$logger, + paste("Missing files found for the hindcast, the corresponding", + "observations will be filled with NA values.")) + dates[is.na(hcst_dates)] <- NA + } + + ## Separate Start() call for monthly vs daily data if (store.freq == "weekly_mean") { - dates_file <- format(as.Date(dates, '%Y%m%d'), "%Y%m%d") - dim(dates_file) <- dim(dates) + ## Is this needed...? obs <- Start(dat = obs.path, var = variable, var_dir = var_dir_obs, var_dir_depends = 'var', - file_date = dates_file, + file_date = dates, latitude = values(list(lats.min, lats.max)), latitude_reorder = Sort(), longitude = values(list(lons.min, lons.max)), @@ -266,7 +285,7 @@ load_subseasonal <- function(recipe) { lubridate::minute(dates) <- 00 # Restore correct dimensions dim(idxs$hcst) <- dim(dates_file) - + obs <- Start(dat = obs.path, var = variable, var_dir = var_dir_obs, diff --git a/tests/testthat/test-subseasonal_weekly.R b/tests/testthat/test-subseasonal_weekly.R index 6e565e76ec53568f85d38156c49491d61d7d6780..bb0759ac1572a2e0c006b61507ac918a68c1ff44 100644 --- a/tests/testthat/test-subseasonal_weekly.R +++ b/tests/testthat/test-subseasonal_weekly.R @@ -96,6 +96,7 @@ expect_equal( dim(data$obs$attrs$Dates), dim(data$obs$attrs$load_parameters$dat1$file_date[[1]]) ) +# Dims are: c("sday", "sweek", "syear", "time") expect_equal( data$obs$attrs$load_parameters$dat1$file_date[[1]][2, 3, , 1], c("19990108", "20000108", "20010108", "20020108", "20030108") diff --git a/tests/testthat/test-subseasonal_weekly_crossval.R b/tests/testthat/test-subseasonal_weekly_crossval.R index f7d9e8125f527f26f2831526a3609e4fbb7d7f56..1d65ce1a23b5d31e48ca354f1b3b0202c605e2bf 100644 --- a/tests/testthat/test-subseasonal_weekly_crossval.R +++ b/tests/testthat/test-subseasonal_weekly_crossval.R @@ -94,7 +94,7 @@ expect_equal(as.vector(skill_metrics[['rpss-set1']][, , 2, 3]), tolerance = 0.0001) expect_equal(as.vector(skill_metrics[['rpss-set1_significance']][, , 2, 3]), - c(0,0,0,0)) + c(0, 0, 0, 0)) })