From 55851826e9f7618e229c6a77a91f092d17ebd67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lloren=C3=A7=20Lled=C3=B3?= Date: Mon, 28 Oct 2019 12:03:09 +0100 Subject: [PATCH 01/34] Typo in description. Corrected teerciles definition. --- R/PlotForecastPDF.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index cf531063..1bb74b63 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -3,8 +3,8 @@ #'@author Llorenç Lledó \email{llledo@bsc.es} #'@description This function plots the probability distribution function of several ensemble forecasts for the same event, either initialized at different moments or by different models. Probabilities for tercile categories are computed, plotted in colors and annotated. An asterisk marks the tercile with higher probabilities. Probabilities for extreme categories (above P90 and below P10) can also be included as hatched areas. Individual ensemble members can be plotted as jittered points. The observed value is optionally shown as a diamond. #' -#'@param fcst a dataframe or array containing all the ensember members for each frecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members. -#'@param tercile.limits an array with P33 and P66 values that define the tercile categories. +#'@param fcst a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members. +#'@param tercile.limits an array with P33 and P66 values that define the tercile categories for each panel. Should have 2*npanels dimensions. #'@param extreme.limits (optional) an array with P10 and P90 values that define the extreme categories. (Default: extreme categories are not shown). #'@param obs (optional) a number with the observed value. (Default: observation is not shown). #'@param plotfile (optional) a filename (pdf, png...) where the plot will be saved. (Default: the plot is not saved). -- GitLab From 50132946d20d00e5fab3c29b6f055a722117e80c Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Wed, 27 Nov 2019 13:01:36 +0100 Subject: [PATCH 02/34] extreme.limits and tercile.limits for length(tercile.limits) > 1 --- R/PlotForecastPDF.R | 140 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 120 insertions(+), 20 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 1bb74b63..e2d801c5 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -70,21 +70,47 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check input arguments #------------------------ - add.ensmemb <- match.arg(add.ensmemb) - if (length(tercile.limits) != 2) { - stop("Parameter 'tercile.limits' should be an array with two limits for delimiting tercile categories") + + #add.ensmemb <- match.arg(add.ensmemb) + if(!is.array(tercile.limits) & !is.array(extreme.limits)){ + stop("tercile.limits or extreme.limits are not arrays") } - if (tercile.limits[1] >= tercile.limits[2]) { - stop("The provided tercile limits are in the wrong order") + + for( j in 1:length(tercile.limits)){ + + if (length(tercile.limits[[j]]) != 2) { + stop("Parameter 'tercile.limits' should be an array with two limits for delimiting tercile categories") } - if (!is.null(extreme.limits)) { - if (length(extreme.limits) != 2) { - stop("Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") - } - if (extreme.limits[1] >= tercile.limits[1] | extreme.limits[2] <= tercile.limits[2]) { - stop("The provided extreme limits are not consistent with tercile limits") - } + if (tercile.limits[[j]][1] >= tercile.limits[[j]][2]) { + stop("The provided tercile limits are in the wrong order") } + if (!is.null(extreme.limits[[j]])) { + if (length(extreme.limits[[j]]) != 2) { + stop("Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") + } + if (extreme.limits[[j]][1] >= tercile.limits[[j]][1] | extreme.limits[[j]][2] <= + tercile.limits[[j]][2]) { + stop("The provided extreme limits are not consistent with tercile limits") + } + } + + } + +# add.ensmemb <- match.arg(add.ensmemb) +# if (length(tercile.limits) != 2) { +# stop("Parameter 'tercile.limits' should be an array with two limits for delimiting tercile categories") +# } +# if (tercile.limits[1] >= tercile.limits[2]) { +# stop("The provided tercile limits are in the wrong order") +# } +# if (!is.null(extreme.limits)) { +# if (length(extreme.limits) != 2) { +# stop("Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") +# } +# if (extreme.limits[1] >= tercile.limits[1] | extreme.limits[2] <= tercile.limits[2]) { + # stop("The provided extreme limits are not consistent with tercile limits") + # } + # } #------------------------ # Check fcst type and convert to data.frame if needed #------------------------ @@ -124,6 +150,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Gather the coordinates of the plots together with init and corresponding # terciles #------------------------ + tmp.df <- ggp$data[[1]][, c("x", "ymin", "ymax", "PANEL")] if (!is.null(ggp$layout$layout)) { tmp.df$init <- ggp$layout$layout$init[as.numeric(tmp.df$PANEL)] @@ -132,9 +159,22 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N } else { stop("Cannot find PANELS in ggp object") } - tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile.limits[1], "Below normal", - ifelse(tmp.df$x < tercile.limits[2], "Normal", "Above normal")), levels = c("Below normal", - "Normal", "Above normal")) +tercile__limits <- abind(tercile.limits,along=0) #aqui . per _ + tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile__limits[tmp.df$PANEL,1], + "Below normal", + ifelse(tmp.df$x < tercile__limits[tmp.df$PANEL,2],"Normal", "Above normal")), + levels = c("Below normal","Normal", "Above normal")) +# if (!is.null(ggp$layout$layout)) { +# tmp.df <- ggp$data[[1]][, c("x", "ymin", "ymax", "PANEL")] +# tmp.df$init <- ggp$layout$layout$init[as.numeric(tmp.df$PANEL)] +# } else if (!is.null(ggp$layout$panel_layout)) { +# tmp.df$init <- ggp$layout$panel_layout$init[as.numeric(tmp.df$PANEL)] +# } else { +# stop("Cannot find PANELS in ggp object") +# } +# tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile.limits[1], "Below normal", +# ifelse(tmp.df$x < tercile.limits[2], "Normal", "Above normal")), levels = c("Below normal", +# "Normal", "Above normal")) #------------------------ # Get the height and width of a panel #------------------------ @@ -144,10 +184,13 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Compute hatch coordinates for extremes #------------------------ + if (!is.null(extreme.limits)) { - tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme.limits[1], "Below P10", - ifelse(tmp.df$x < extreme.limits[2], "Normal", "Above P90")), levels = c("Below P10", - "Normal", "Above P90")) +extreme__limits <- abind(extreme.limits,along=0) #aqui . per _ + tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,1], + "Below P10", + ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,2],"Normal", "Above P90")), + levels = c("Below P10","Normal", "Above P90")) hatch.ls <- dlply(tmp.df, .(init, extremes), function(x) { # close the polygon tmp.df2 <- data.frame(x = c(x$x, max(x$x), min(x$x)), y = c(x$ymax, 0, @@ -177,6 +220,39 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N } max.df <- do.call("rbind", max.ls) } +# if (!is.null(extreme.limits)) { +# tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme.limits[1], "Below P10", +# ifelse(tmp.df$x < extreme.limits[2], "Normal", "Above P90")), levels = c("Below P10", +# "Normal", "Above P90")) +# hatch.ls <- dlply(tmp.df, .(init, extremes), function(x) { + # close the polygon +# tmp.df2 <- data.frame(x = c(x$x, max(x$x), min(x$x)), y = c(x$ymax, 0, +# 0)) + # compute the hatches for this polygon +# hatches <- .polygon.fullhatch(tmp.df2$x, tmp.df2$y, angle = 60, density = 10, +# width.units = pan.width, height.units = pan.height) + # add bottom segment +# end1 <- data.frame(x = x$x[1], y = x$ymax[1], xend = x$x[1], yend = 0) + # add top segment +# end2 <- data.frame(x = x$x[length(x$x)], y = x$ymax[length(x$x)], xend = x$x[length(x$x)], +# yend = 0) +# return(rbind(hatches, end1, end2)) +# }) +# attr <- attr(hatch.ls, "split_labels") +# for (i in 1:length(hatch.ls)) { +# hatch.ls[[i]] <- cbind(hatch.ls[[i]], attr[i, ]) +# } +# hatch.df <- do.call("rbind", hatch.ls) + # Compute max y for each extreme category +# max.ls <- dlply(tmp.df, .(init, extremes), function(x) { +# data.frame(y = min(0.85 * pan.height, max(x$ymax))) +# }) +# attr <- attr(max.ls, "split_labels") +# for (i in 1:length(max.ls)) { +# max.ls[[i]] <- cbind(max.ls[[i]], attr[i, ]) +# } +# max.df <- do.call("rbind", max.ls) +# } #------------------------ # Compute jitter space for ensemble members #------------------------ @@ -247,6 +323,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Compute probability for each tercile and identify MLT #------------------------ + tmp.dt <- data.table(tmp.df) pct <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), by = .(init, tercile)] @@ -254,22 +331,45 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N pct <- merge(pct, tot, by = "init") pct$pct <- round(100 * pct$pct/pct$tot, 0) pct$MLT <- pct[, .(MLT = pct == max(pct)), by = init]$MLT - lab.pos <- c(tercile.limits[1], mean(tercile.limits), tercile.limits[2]) + lab.pos <- c(tercile.limits[[1]][1], mean(tercile.limits[[1]]), tercile.limits[[1]][2]) + + # tmp.dt <- data.table(tmp.df) + # pct <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), + # by = .(init, tercile)] + # tot <- pct[, .(tot = sum(pct)), by = init] + # pct <- merge(pct, tot, by = "init") + # pct$pct <- round(100 * pct$pct/pct$tot, 0) + # pct$MLT <- pct[, .(MLT = pct == max(pct)), by = init]$MLT + # lab.pos <- c(tercile.limits[1], mean(tercile.limits), tercile.limits[2]) #------------------------ # Compute probability for extremes #------------------------ + if (!is.null(extreme.limits)) { pct2 <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), by = .(init, extremes)] tot2 <- pct2[, .(tot = sum(pct)), by = init] pct2 <- merge(pct2, tot2, by = "init") pct2$pct <- round(100 * pct2$pct/pct2$tot, 0) - lab.pos2 <- c(extreme.limits[1], NA, extreme.limits[2]) + lab.pos2 <- c(extreme.limits[[1]][1], NA, extreme.limits[[1]][2]) pct2 <- merge(pct2, max.df, by = c("init", "extremes")) # include potentially missing groups pct2 <- pct2[CJ(levels(pct2$init), factor(c("Below P10", "Normal", "Above P90"), levels = c("Below P10", "Normal", "Above P90"))), ] } + +# if (!is.null(extreme.limits)) { +# pct2 <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), +# by = .(init, extremes)] +# tot2 <- pct2[, .(tot = sum(pct)), by = init] +# pct2 <- merge(pct2, tot2, by = "init") +# pct2$pct <- round(100 * pct2$pct/pct2$tot, 0) +# lab.pos2 <- c(extreme.limits[1], NA, extreme.limits[2]) +# pct2 <- merge(pct2, max.df, by = c("init", "extremes")) + # include potentially missing groups +# pct2 <- pct2[CJ(levels(pct2$init), factor(c("Below P10", "Normal", "Above P90"), +# levels = c("Below P10", "Normal", "Above P90"))), ] +# } #------------------------ # Add probability labels for terciles #------------------------ -- GitLab From 99638d245c401e2dcbc40d3f8a1e0982ef980fe1 Mon Sep 17 00:00:00 2001 From: nperez Date: Mon, 2 Dec 2019 12:30:09 +0100 Subject: [PATCH 03/34] Function MergeDimsand CST_MergeDims --- R/CST_MergeDims.R | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 R/CST_MergeDims.R diff --git a/R/CST_MergeDims.R b/R/CST_MergeDims.R new file mode 100644 index 00000000..d258ac85 --- /dev/null +++ b/R/CST_MergeDims.R @@ -0,0 +1,116 @@ +#'Function to Merge Dimensions +#' +#'@author Nuria Perez-Zanon, \email{nuria.perez@bsc.es} +#' +#'@description This function merges two dimensions of the array \code{data} in a 's2dv_cube' object into one. The user can select the dimensions to merge and provide the final name of the dimension. The user can select to remove NA values or keep them. +#' +#'@param data a 's2dv_cube' object +#'@param merge_dims a character vector indicating the names of the dimensions to merge +#'@param remane_dim a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used. +#'@param na.rm a logical indicating if the NA values should be removed or not. +#' +#'@import abind +#'@import s2dverification +#'@examples +#' +#'data <- 1 : c(2 * 3 * 4 * 5 * 6 * 7) +#'dim(data) <- c(time = 7, lat = 2, lon = 3, monthly = 4, member = 6, +#' dataset = 5, var = 1) +#'data[2,,,,,,] <- NA +#'data[c(3,27)] <- NA +#'data <-list(data = data) +#'class(data) <- 's2dv_cube' +#'new_data <- CST_MergeDims(data, merge_dims = c('time', 'monthly')) +#'dim(new_data$data) +#'new_data <- CST_MergeDims(data, merge_dims = c('lon', 'lat'), rename_dim = 'grid') +#'dim(new_data$data) +#'new_data <- CST_MergeDims(data, merge_dims = c('time', 'monthly'), na.rm = TRUE) +#'dim(new_data$data) +#'@export +CST_MergeDims <- function(data, merge_dims = c('ftime', 'monthly'), rename_dim = NULL, + na.rm = FALSE) { + if (!inherits(data, 's2dv_cube')) { + stop("Parameter 'data' must be of the class 's2dv_cube', ", + "as output by CSTools::CST_Load.") + } + data$data <- MergeDims(data$data, merge_dims = merge_dims, + rename_dim = rename_dim, na.rm = na.rm) + return(data) +} +#'Function to Split Dimension +#' +#'@author Nuria Perez-Zanon, \email{nuria.perez@bsc.es} +#' +#'@description This function merges two dimensions of an array into one. The user can select the dimensions to merge and provide the final name of the dimension. The user can select to remove NA values or keep them. +#' +#'@param data an n-dimensional array with named dimensions +#'@param merge_dims a character vector indicating the names of the dimensions to merge +#'@param remane_dim a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used. +#'@param na.rm a logical indicating if the NA values should be removed or not. +#' +#'@import abind +#'@import s2dverification +#'@examples +#' +#'data <- 1 : 20 +#'dim(data) <- c(time = 10, lat = 2) +#'new_data <- MergeDims(data, merge_dims = c('time', 'lat')) +#'@export +MergeDims <- function(data, merge_dims = c('time', 'monthly'), rename_dim = NULL, + na.rm = FALSE) { + # check data + if (is.null(data)) { + stop("Parameter 'data' cannot be NULL.") + } + if (is.null(dim(data))) { + stop("Parameter 'data' must have dimensions.") + } + if (is.null(names(dim(data)))) { + stop("Parameter 'data' must have dimension names.") + } + dims <- dim(data) + # check merge_dims + if (is.null(merge_dims)) { + stop("Parameter 'merge_dims' cannot be NULL.") + } + if (!is.character(merge_dims)) { + stop("Parameter 'merge_dims' must be a character vector ", + "indicating the names of the dimensions to be merged.") + } + if (length(merge_dims) > 2) { + warning("Only two dimensions can be merge, only the first two ", + "dimension will be used. To merge further dimensions ", + "consider to use this function multiple times.") + merge_dims <- merge_dims[1 : 2] + } + if (is.null(rename_dim)) { + rename_dim <- merge_dims[1] + } + if (length(rename_dim) > 1) { + warning("Parameter 'rename_dim' has length greater than 1 ", + "and only the first element will be used.") + rename_dim <- as.character(rename_dim[1]) + } + if (!any(names(dims) %in% merge_dims)) { + stop("Parameter 'merge_dims' must match with dimension ", + "names in parameter 'data'.") + } + pos1 <- which(names(dims) == merge_dims[1]) + pos2 <- which(names(dims) == merge_dims[2]) + if (pos1 > pos2) { + pos1 <- pos1 - 1 + } + data <- lapply(1 : dims[pos2], function(x) {Subset(data, along = pos2, + indices = x, drop = 'selected')}) + data <- abind(data, along = pos1) + names(dim(data)) <- names(dims)[-pos2] + if (na.rm) { + nas <- which(is.na(Subset(data, along = -pos1, indices = 1))) + nas <- unlist(lapply(nas, function(x) { + if(all(is.na(Subset(data, along = pos1, + indices = x)))) { + return(x)}})) + data <- Subset(data, along = pos1, indices = -nas) + } +return(data) +} -- GitLab From c7a4f7d5b050426f8b876b8e294219217375d741 Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Tue, 3 Dec 2019 14:43:30 +0100 Subject: [PATCH 04/34] try different data type for terciles and extremes --- R/PlotForecastPDF.R | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index e2d801c5..f615a2b2 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -45,7 +45,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Define color sets #------------------------ - color.set <- match.arg(color.set) + # color.set <- match.arg(color.set) if (color.set == "s2s4e") { colorFill <- rev(c("#FF764D", "#b5b5b5", "#33BFD1")) colorHatch <- c("deepskyblue3", "indianred3") @@ -71,11 +71,21 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Check input arguments #------------------------ + + # tercile.limits <- as.array(InsertDim(tercile.limits,2,1)) + # extreme.limits <- as.array(InsertDim(extreme.limits,2,1)) + # tercile.limits <- as.data.table(tercile.limits) + # extreme.limits <- as.data.table(extreme.limits) + #add.ensmemb <- match.arg(add.ensmemb) - if(!is.array(tercile.limits) & !is.array(extreme.limits)){ - stop("tercile.limits or extreme.limits are not arrays") - } + # if(!is.array(tercile.limits) & !is.array(extreme.limits)){ + # stop("tercile.limits or extreme.limits are not arrays") + # } + # tercile.limits <- as.data.table(tercile_limits) + # extreme.limits <- as.data.table(extreme_limits) + + for( j in 1:length(tercile.limits)){ if (length(tercile.limits[[j]]) != 2) { -- GitLab From 3398bb075c01a39c16ce0aaadaa3b0e2ae30ffcd Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Wed, 4 Dec 2019 11:50:23 +0100 Subject: [PATCH 05/34] PlotForecastPDF now works in both different terciles and extremes and unique terciles and extremes --- R/PlotForecastPDF.R | 49 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index f615a2b2..4bed74ae 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -42,6 +42,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N hues <- seq(15, 375, length = n + 1) hcl(h = hues, l = 65, c = 100)[1:n] } + #------------------------ # Define color sets #------------------------ @@ -84,8 +85,15 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # tercile.limits <- as.data.table(tercile_limits) # extreme.limits <- as.data.table(extreme_limits) +if(!is.list(tercile.limits)){ + tercile.limits <- list(tercile.limits) +} + +if(!is.list(extreme.limits)){ + extreme.limits <- list(extreme.limits) +} - + for( j in 1:length(tercile.limits)){ if (length(tercile.limits[[j]]) != 2) { @@ -169,11 +177,23 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N } else { stop("Cannot find PANELS in ggp object") } -tercile__limits <- abind(tercile.limits,along=0) #aqui . per _ + +if(length(tercile__limits==1)){ + + tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile__limits[1], "Below normal", + ifelse(tmp.df$x < tercile__limits[2], "Normal", "Above normal")), levels = c("Below normal", + "Normal", "Above normal")) + + +} else { + + tercile__limits <- abind(tercile.limits,along=0) #aqui . per _ tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile__limits[tmp.df$PANEL,1], "Below normal", ifelse(tmp.df$x < tercile__limits[tmp.df$PANEL,2],"Normal", "Above normal")), levels = c("Below normal","Normal", "Above normal")) +} + # if (!is.null(ggp$layout$layout)) { # tmp.df <- ggp$data[[1]][, c("x", "ymin", "ymax", "PANEL")] # tmp.df$init <- ggp$layout$layout$init[as.numeric(tmp.df$PANEL)] @@ -195,12 +215,25 @@ tercile__limits <- abind(tercile.limits,along=0) #aqui . per _ # Compute hatch coordinates for extremes #------------------------ - if (!is.null(extreme.limits)) { -extreme__limits <- abind(extreme.limits,along=0) #aqui . per _ - tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,1], - "Below P10", - ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,2],"Normal", "Above P90")), - levels = c("Below P10","Normal", "Above P90")) +if (!is.null(extreme.limits)) { + +if(length(extreme.limits)==1){ + + tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme__limits[1], "Below P10", + ifelse(tmp.df$x < extreme__limits[2], "Normal", "Above P90")), levels = c("Below P10", + "Normal", "Above P90")) + +} else { + + extreme__limits <- abind(extreme.limits,along=0) #aqui . per _ + tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,1], + "Below P10", + ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,2],"Normal", "Above P90")), + levels = c("Below P10","Normal", "Above P90")) + +} + + hatch.ls <- dlply(tmp.df, .(init, extremes), function(x) { # close the polygon tmp.df2 <- data.frame(x = c(x$x, max(x$x), min(x$x)), y = c(x$ymax, 0, -- GitLab From 7b04bc0ba84c99e25dc95f5039c929d9f94c4c8b Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Wed, 4 Dec 2019 12:14:39 +0100 Subject: [PATCH 06/34] bug fixed --- R/PlotForecastPDF.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 4bed74ae..8ba81fb9 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -178,7 +178,7 @@ if(!is.list(extreme.limits)){ stop("Cannot find PANELS in ggp object") } -if(length(tercile__limits==1)){ +if(length(tercile__limits)==1){ tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile__limits[1], "Below normal", ifelse(tmp.df$x < tercile__limits[2], "Normal", "Above normal")), levels = c("Below normal", @@ -580,3 +580,4 @@ if(length(extreme.limits)==1){ } return(do.call("rbind", hatch.ls)) } + -- GitLab From 92bf83aad270bb4c20f5c21566c60203f17fca4e Mon Sep 17 00:00:00 2001 From: Bert Van schaeybroeck Date: Mon, 9 Dec 2019 09:49:53 +0100 Subject: [PATCH 07/34] Handling of case of insufficient data, following the comment of Deborah Verfaillie. The function now warns (and does no calibration) when 3 or less observation-model pairs are available for training. A new parameter na.fill has been introduced. --- DESCRIPTION | 2 +- R/CST_Calibration.R | 43 ++++++++++++++++++++++++---- man/Analogs.Rd | 13 ++++----- man/BEI_PDFBest.Rd | 7 ++--- man/BEI_Weights.Rd | 7 ++--- man/CST_Analogs.Rd | 9 +++--- man/CST_Anomaly.Rd | 7 ++--- man/CST_BEI_Weighting.Rd | 7 ++--- man/CST_BiasCorrection.Rd | 7 ++--- man/CST_Calibration.Rd | 15 +++++----- man/CST_CategoricalEnsCombination.Rd | 7 ++--- man/CST_EnsClustering.Rd | 1 - man/CST_Load.Rd | 1 - man/CST_MultiEOF.Rd | 5 ++-- man/CST_MultiMetric.Rd | 9 +++--- man/CST_MultivarRMSE.Rd | 7 ++--- man/CST_QuantileMapping.Rd | 7 ++--- man/CST_RFSlope.Rd | 1 - man/CST_RFWeights.Rd | 7 ++--- man/CST_RainFARM.Rd | 7 ++--- man/CST_SaveExp.Rd | 7 ++--- man/CST_SplitDim.Rd | 4 +-- man/EnsClustering.Rd | 1 - man/MultiEOF.Rd | 1 - man/PlotCombinedMap.Rd | 15 +++++----- man/PlotForecastPDF.Rd | 10 +++---- man/PlotMostLikelyQuantileMap.Rd | 7 ++--- man/RFSlope.Rd | 1 - man/RainFARM.Rd | 9 +++--- man/SplitDim.Rd | 1 - man/areave_data.Rd | 1 - man/as.s2dv_cube.Rd | 7 ++--- man/lonlat_data.Rd | 1 - man/lonlat_prec.Rd | 1 - man/s2dv_cube.Rd | 7 ++--- 35 files changed, 122 insertions(+), 120 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 0e47736a..c3de9d84 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -70,4 +70,4 @@ VignetteBuilder: knitr License: Apache License 2.0 Encoding: UTF-8 LazyData: true -RoxygenNote: 5.0.0 +RoxygenNote: 6.1.1 diff --git a/R/CST_Calibration.R b/R/CST_Calibration.R index 1cd9bab4..efc7eeaa 100644 --- a/R/CST_Calibration.R +++ b/R/CST_Calibration.R @@ -13,6 +13,7 @@ #'@param cal.method is the calibration method used, can be either \code{bias}, \code{evmos}, \code{mse_min} or \code{crps_min}. Default value is \code{mse_min}. #'@param eval.method is the sampling method used, can be either \code{in-sample} or \code{leave-one-out}. Default value is the \code{leave-one-out} cross validation. #'@param multi.model is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result. +#'@param na.fill is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned. #'@return an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions of the experimental data. #' #'@import s2dverification @@ -37,8 +38,8 @@ #'str(a) #'@export - -CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.method = "leave-one-out", multi.model = F) { +CST_Calibration <- function(exp, obs, cal.method = "mse_min", + eval.method = "leave-one-out", multi.model = F, na.fill = T) { if (!inherits(exp, "s2dv_cube") || !inherits(obs, "s2dv_cube")) { stop("Parameter 'exp' and 'obs' must be of the class 's2dv_cube', ", "as output by CSTools::CST_Load.") @@ -54,7 +55,7 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.method = "lea } exp$data <- .calibration.wrap(exp = exp$data, obs = obs$data, cal.method = cal.method, eval.method = eval.method, - multi.model = multi.model) + multi.model = multi.model, na.fill = na.fill) exp$Datasets <- c(exp$Datasets, obs$Datasets) exp$source_files <- c(exp$source_files, obs$source_files) @@ -62,7 +63,15 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.method = "lea } -.calibration.wrap <- function(exp, obs, cal.method, eval.method, multi.model) { +.data.set.sufficiently.large <- function(mod, obs){ + amt.min.samples <- 3 + amt.good.pts <- sum(!is.na(obs) & !apply(mod, c(2), function(x) all(is.na(x)))) + return(amt.good.pts > amt.min.samples) +} + + +.calibration.wrap <- function(exp, obs, cal.method, + eval.method, multi.model, na.fill) { dim.exp <- dim(exp) amt.dims.exp <- length(dim.exp) @@ -95,11 +104,24 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.method = "lea } obs <- Subset(obs, along = "member", indices = 1, drop = "selected") + + data.set.sufficiently.large.out <- Apply(data = list(mod = exp, obs = obs), + target_dims = list(mod = target.dim.names.exp, obs = target.dim.names.obs), + fun = .data.set.sufficiently.large)$output1 + + if(!all(data.set.sufficiently.large.out)){ + if(na.fill){ + warning("Some forecast data could not be corrected due to data lack and is replaced with NA values") + } else { + warning("Some forecast data could not be corrected due to data lack and is replaced with uncorrected values") + } + } calibrated <- Apply(data = list(mod = exp, obs = obs), cal.method = cal.method, eval.method = eval.method, multi.model = multi.model, + na.fill = na.fill, target_dims = list(mod = target.dim.names.exp, obs = target.dim.names.obs), fun = .cal)$output1 @@ -122,7 +144,7 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.method = "lea return(dexes.lst) } -.cal <- function(mod, obs, cal.method, eval.method, multi.model) { +.cal <- function(mod, obs, cal.method, eval.method, multi.model, na.fill) { var.obs <- as.vector(obs) var.fc <- mod @@ -130,6 +152,16 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.method = "lea amt.mbr <- dims.fc[1] amt.sdate <- dims.fc[2] var.cor.fc <- NA * var.fc + names(dim(var.cor.fc)) <- c("member", "sdate") + + if(!.data.set.sufficiently.large(mod = mod, obs = obs)){ + if(na.fill){ + return(var.cor.fc) + } else { + var.cor.fc[] <- var.fc[] + return(var.cor.fc) + } + } eval.train.dexeses <- .make.eval.train.dexes(eval.method, amt.points = amt.sdate) amt.resamples <- length(eval.train.dexeses) @@ -175,7 +207,6 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.method = "lea stop("unknown calibration method: ",cal.method) } } - names(dim(var.cor.fc)) <- c("member", "sdate") return(var.cor.fc) } diff --git a/man/Analogs.Rd b/man/Analogs.Rd index ee8a737e..52d9ff97 100644 --- a/man/Analogs.Rd +++ b/man/Analogs.Rd @@ -5,8 +5,8 @@ \title{Analogs based on large scale fields.} \usage{ Analogs(expL, obsL, time_obsL, expVar = NULL, obsVar = NULL, - criteria = "Large_dist", lonVar = NULL, latVar = NULL, region = NULL, - nAnalogs = NULL, return_list = FALSE) + criteria = "Large_dist", lonVar = NULL, latVar = NULL, + region = NULL, nAnalogs = NULL, return_list = FALSE) } \arguments{ \item{expL}{an array of N named dimensions containing the experimental field @@ -377,11 +377,6 @@ Local_scalecor <- Analogs(expL=expSLP, str(Local_scalecor) Local_scalecor$AnalogsInfo -} -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} - -Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -389,4 +384,8 @@ and M. Vrac, 2013 : Ensemble reconstruction of the atmospheric column from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. \email{pascal.yiou@lsce.ipsl.fr} } +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} +Nuria Perez-Zanon \email{nuria.perez@bsc.es} +} diff --git a/man/BEI_PDFBest.Rd b/man/BEI_PDFBest.Rd index f836ab72..f120258d 100644 --- a/man/BEI_PDFBest.Rd +++ b/man/BEI_PDFBest.Rd @@ -113,12 +113,11 @@ dim(res) # time statistic season # 1 2 2 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/BEI_Weights.Rd b/man/BEI_Weights.Rd index 61db33af..867a4eb0 100644 --- a/man/BEI_Weights.Rd +++ b/man/BEI_Weights.Rd @@ -43,13 +43,12 @@ dim(res) # sdate dataset member season # 10 3 5 1 -} -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} } \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/CST_Analogs.Rd b/man/CST_Analogs.Rd index 7c9a1e6f..c9166de6 100644 --- a/man/CST_Analogs.Rd +++ b/man/CST_Analogs.Rd @@ -81,11 +81,6 @@ adapted version of the method of Yiou et al 2013. \examples{ res <- CST_Analogs(expL = lonlat_data$exp, obsL = lonlat_data$obs) -} -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} - -Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -97,4 +92,8 @@ from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. code{\link{CST_Load}}, \code{\link[s2dverification]{Load}} and \code{\link[s2dverification]{CDORemap}} } +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} +Nuria Perez-Zanon \email{nuria.perez@bsc.es} +} diff --git a/man/CST_Anomaly.Rd b/man/CST_Anomaly.Rd index e1c31f0c..b214a31a 100644 --- a/man/CST_Anomaly.Rd +++ b/man/CST_Anomaly.Rd @@ -53,13 +53,12 @@ str(anom3) anom4 <- CST_Anomaly(exp = exp, obs = obs, cross = FALSE, memb = FALSE) str(anom4) +} +\seealso{ +\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} } \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Pena Jesus, \email{jesus.pena@bsc.es} } -\seealso{ -\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} -} - diff --git a/man/CST_BEI_Weighting.Rd b/man/CST_BEI_Weighting.Rd index 6b9a448a..b2a3f1fa 100644 --- a/man/CST_BEI_Weighting.Rd +++ b/man/CST_BEI_Weighting.Rd @@ -63,12 +63,11 @@ dim(res_CST$data) # time lat lon dataset # 2 3 2 2 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/CST_BiasCorrection.Rd b/man/CST_BiasCorrection.Rd index 485199ea..a1b415fb 100644 --- a/man/CST_BiasCorrection.Rd +++ b/man/CST_BiasCorrection.Rd @@ -35,10 +35,9 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_BiasCorrection(exp = exp, obs = obs) str(a) } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} -} \references{ Torralba, V., F.J. Doblas-Reyes, D. MacLeod, I. Christel and M. Davis (2017). Seasonal climate prediction: a new source of information for the management of wind energy resources. Journal of Applied Meteorology and Climatology, 56, 1231-1247, doi:10.1175/JAMC-D-16-0204.1. (CLIM4ENERGY, EUPORIAS, NEWA, RESILIENCE, SPECS) } -\encoding{UTF-8} +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} +} diff --git a/man/CST_Calibration.Rd b/man/CST_Calibration.Rd index 36171dbd..48d0a4e1 100644 --- a/man/CST_Calibration.Rd +++ b/man/CST_Calibration.Rd @@ -5,7 +5,7 @@ \title{Forecast Calibration} \usage{ CST_Calibration(exp, obs, cal.method = "mse_min", - eval.method = "leave-one-out", multi.model = F) + eval.method = "leave-one-out", multi.model = F, na.fill = T) } \arguments{ \item{exp}{an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the seasonal forecast experiment data in the element named \code{$data}.} @@ -17,6 +17,8 @@ CST_Calibration(exp, obs, cal.method = "mse_min", \item{eval.method}{is the sampling method used, can be either \code{in-sample} or \code{leave-one-out}. Default value is the \code{leave-one-out} cross validation.} \item{multi.model}{is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result.} + +\item{na.fill}{is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned.} } \value{ an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions of the experimental data. @@ -26,11 +28,6 @@ Four types of member-by-member bias correction can be performed. The \code{bias} Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} - -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} \references{ Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x @@ -57,4 +54,8 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_Calibration(exp = exp, obs = obs, cal.method = "mse_min", eval.method = "in-sample") str(a) } -\encoding{UTF-8} +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} + +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} diff --git a/man/CST_CategoricalEnsCombination.Rd b/man/CST_CategoricalEnsCombination.Rd index e551c3ec..7175b7fe 100644 --- a/man/CST_CategoricalEnsCombination.Rd +++ b/man/CST_CategoricalEnsCombination.Rd @@ -83,9 +83,6 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_CategoricalEnsCombination(exp = exp, obs = obs, amt.cat = 3, cat.method = "mmw") } } -\author{ -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} \references{ Rajagopalan, B., Lall, U., & Zebiak, S. E. (2002). Categorical climate forecasts through regularization and optimal combination of multiple GCM ensembles. Monthly Weather Review, 130(7), 1792-1811. @@ -93,4 +90,6 @@ Robertson, A. W., Lall, U., Zebiak, S. E., & Goddard, L. (2004). Improved combin Van Schaeybroeck, B., & Vannitsem, S. (2019). Postprocessing of Long-Range Forecasts. In Statistical Postprocessing of Ensemble Forecasts (pp. 267-290). } - +\author{ +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} diff --git a/man/CST_EnsClustering.Rd b/man/CST_EnsClustering.Rd index c13bf205..de71d4e3 100644 --- a/man/CST_EnsClustering.Rd +++ b/man/CST_EnsClustering.Rd @@ -125,4 +125,3 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/CST_Load.Rd b/man/CST_Load.Rd index 1fee022c..bf03ba42 100644 --- a/man/CST_Load.Rd +++ b/man/CST_Load.Rd @@ -47,4 +47,3 @@ obs <- CSTools::lonlat_data$obs \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} } - diff --git a/man/CST_MultiEOF.Rd b/man/CST_MultiEOF.Rd index fb584751..5fea8a50 100644 --- a/man/CST_MultiEOF.Rd +++ b/man/CST_MultiEOF.Rd @@ -4,8 +4,8 @@ \alias{CST_MultiEOF} \title{EOF analysis of multiple variables} \usage{ -CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, minvar = 0.6, - lon_lim = NULL, lat_lim = NULL) +CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, + minvar = 0.6, lon_lim = NULL, lat_lim = NULL) } \arguments{ \item{datalist}{A list of objects of the class 's2dv_cube', containing the variables to be analysed. @@ -69,4 +69,3 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } - diff --git a/man/CST_MultiMetric.Rd b/man/CST_MultiMetric.Rd index 079a5588..8e3ce593 100644 --- a/man/CST_MultiMetric.Rd +++ b/man/CST_MultiMetric.Rd @@ -37,15 +37,14 @@ c(ano_exp, ano_obs) \%<-\% CST_Anomaly(exp = exp, obs = obs, cross = TRUE, memb a <- CST_MultiMetric(exp = ano_exp, obs = ano_obs) str(a) } -\author{ -Mishra Niti, \email{niti.mishra@bsc.es} - -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} \references{ Mishra, N., Prodhomme, C., & Guemas, V. (n.d.). Multi-Model Skill Assessment of Seasonal Temperature and Precipitation Forecasts over Europe, 29-31.\url{http://link.springer.com/10.1007/s00382-018-4404-z} } \seealso{ \code{\link[s2dverification]{Corr}}, \code{\link[s2dverification]{RMS}}, \code{\link[s2dverification]{RMSSS}} and \code{\link{CST_Load}} } +\author{ +Mishra Niti, \email{niti.mishra@bsc.es} +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_MultivarRMSE.Rd b/man/CST_MultivarRMSE.Rd index 685eaf77..24af608c 100644 --- a/man/CST_MultivarRMSE.Rd +++ b/man/CST_MultivarRMSE.Rd @@ -56,10 +56,9 @@ weight <- c(1, 2) a <- CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, weight = weight) str(a) } -\author{ -Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} -} \seealso{ \code{\link[s2dverification]{RMS}} and \code{\link{CST_Load}} } - +\author{ +Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} +} diff --git a/man/CST_QuantileMapping.Rd b/man/CST_QuantileMapping.Rd index 1c93843e..90319622 100644 --- a/man/CST_QuantileMapping.Rd +++ b/man/CST_QuantileMapping.Rd @@ -77,10 +77,9 @@ res <- CST_QuantileMapping(exp = exp, obs = obs, sample_dims = 'time', method = 'DIST') } } -\author{ -Nuria Perez-Zanon, \email{nuria.perez@bsc.es} -} \seealso{ \code{\link[qmap]{fitQmap}} and \code{\link[qmap]{doQmap}} } - +\author{ +Nuria Perez-Zanon, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_RFSlope.Rd b/man/CST_RFSlope.Rd index d2b5aec0..0c4e1671 100644 --- a/man/CST_RFSlope.Rd +++ b/man/CST_RFSlope.Rd @@ -50,4 +50,3 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/CST_RFWeights.Rd b/man/CST_RFWeights.Rd index 08a7b850..ef5ebe4d 100644 --- a/man/CST_RFWeights.Rd +++ b/man/CST_RFWeights.Rd @@ -47,9 +47,6 @@ nf <- 8 ww <- CST_RFWeights("./worldclim.nc", nf, lon, lat, fsmooth = TRUE) } } -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} -} \references{ Terzago, S., Palazzi, E., & von Hardenberg, J. (2018). Stochastic downscaling of precipitation in complex orography: @@ -57,4 +54,6 @@ A simple method to reproduce a realistic fine-scale climatology. Natural Hazards and Earth System Sciences, 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 . } - +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} diff --git a/man/CST_RainFARM.Rd b/man/CST_RainFARM.Rd index 4a667f9a..0ed45f49 100644 --- a/man/CST_RainFARM.Rd +++ b/man/CST_RainFARM.Rd @@ -95,13 +95,12 @@ dim(res$data) # dataset member realization sdate ftime lat lon # 1 2 3 3 4 64 64 -} -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } \references{ Terzago, S. et al. (2018). NHESS 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 ; D'Onofrio et al. (2014), J of Hydrometeorology 15, 830-843; Rebora et. al. (2006), JHM 7, 724. } - +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} diff --git a/man/CST_SaveExp.Rd b/man/CST_SaveExp.Rd index 17537205..0e49c119 100644 --- a/man/CST_SaveExp.Rd +++ b/man/CST_SaveExp.Rd @@ -29,11 +29,10 @@ destination <- "./path/" CST_SaveExp(data = data, destination = destination) } -} -\author{ -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} } \seealso{ \code{\link{CST_Load}}, \code{\link{as.s2dv_cube}} and \code{\link{s2dv_cube}} } - +\author{ +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_SplitDim.Rd b/man/CST_SplitDim.Rd index 2019ea7b..8ce20c97 100644 --- a/man/CST_SplitDim.Rd +++ b/man/CST_SplitDim.Rd @@ -4,7 +4,8 @@ \alias{CST_SplitDim} \title{Function to Split Dimension} \usage{ -CST_SplitDim(data, split_dim = "time", indices = NULL, freq = "monthly") +CST_SplitDim(data, split_dim = "time", indices = NULL, + freq = "monthly") } \arguments{ \item{data}{a 's2dv_cube' object} @@ -43,4 +44,3 @@ dim(new_data$data) \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/EnsClustering.Rd b/man/EnsClustering.Rd index 27aca453..d7284ef5 100644 --- a/man/EnsClustering.Rd +++ b/man/EnsClustering.Rd @@ -67,4 +67,3 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/MultiEOF.Rd b/man/MultiEOF.Rd index 1e822fc4..c38116de 100644 --- a/man/MultiEOF.Rd +++ b/man/MultiEOF.Rd @@ -46,4 +46,3 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } - diff --git a/man/PlotCombinedMap.Rd b/man/PlotCombinedMap.Rd index 6857c64d..62e26904 100644 --- a/man/PlotCombinedMap.Rd +++ b/man/PlotCombinedMap.Rd @@ -5,10 +5,10 @@ \title{Plot Multiple Lon-Lat Variables In a Single Map According to a Decision Function} \usage{ PlotCombinedMap(maps, lon, lat, map_select_fun, display_range, - map_dim = "map", brks = NULL, cols = NULL, col_unknown_map = "white", - mask = NULL, col_mask = "grey", bar_titles = NULL, legend_scale = 1, - fileout = NULL, width = 8, height = 5, size_units = "in", res = 100, - ...) + map_dim = "map", brks = NULL, cols = NULL, + col_unknown_map = "white", mask = NULL, col_mask = "grey", + bar_titles = NULL, legend_scale = 1, fileout = NULL, width = 8, + height = 5, size_units = "in", res = 100, ...) } \arguments{ \item{maps}{List of matrices to plot, each with (longitude, latitude) dimensions, or 3-dimensional array with the dimensions (longitude, latitude, map). Dimension names are required.} @@ -67,12 +67,11 @@ PlotCombinedMap(list(a, b, c), lons, lats, bar_titles = paste('\% of belonging to', c('a', 'b', 'c')), brks = 20, width = 10, height = 8) } +\seealso{ +\code{PlotCombinedMap} and \code{PlotEquiMap} +} \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} Veronica Torralba, \email{veronica.torralba@bsc.es} } -\seealso{ -\code{PlotCombinedMap} and \code{PlotEquiMap} -} - diff --git a/man/PlotForecastPDF.Rd b/man/PlotForecastPDF.Rd index bed0bd31..c1959ee8 100644 --- a/man/PlotForecastPDF.Rd +++ b/man/PlotForecastPDF.Rd @@ -4,10 +4,11 @@ \alias{PlotForecastPDF} \title{Plot one or multiple ensemble forecast pdfs for the same event} \usage{ -PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, - plotfile = NULL, title = "Set a title", var.name = "Varname (units)", - fcst.names = NULL, add.ensmemb = c("above", "below", "no"), - color.set = c("ggplot", "s2s4e", "hydro")) +PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, + obs = NULL, plotfile = NULL, title = "Set a title", + var.name = "Varname (units)", fcst.names = NULL, + add.ensmemb = c("above", "below", "no"), color.set = c("ggplot", + "s2s4e", "hydro")) } \arguments{ \item{fcst}{a dataframe or array containing all the ensember members for each frecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members.} @@ -49,4 +50,3 @@ PlotForecastPDF(fcsts2, c(-0.66, 0.66), extreme.limits = c(-1.2, 1.2), \author{ Llorenç Lledó \email{llledo@bsc.es} } -\encoding{UTF-8} diff --git a/man/PlotMostLikelyQuantileMap.Rd b/man/PlotMostLikelyQuantileMap.Rd index 6c92850e..0d984ede 100644 --- a/man/PlotMostLikelyQuantileMap.Rd +++ b/man/PlotMostLikelyQuantileMap.Rd @@ -109,11 +109,10 @@ PlotMostLikelyQuantileMap(bins, lons, lats, mask = 1 - (w1 + w2 / max(c(w1, w2))), brks = 20, width = 10, height = 8) -} -\author{ -Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} } \seealso{ \code{PlotCombinedMap} and \code{PlotEquiMap} } - +\author{ +Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} +} diff --git a/man/RFSlope.Rd b/man/RFSlope.Rd index 09a24ff5..5308ef8c 100644 --- a/man/RFSlope.Rd +++ b/man/RFSlope.Rd @@ -60,4 +60,3 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/RainFARM.Rd b/man/RainFARM.Rd index 984dcd42..e0fa9a10 100644 --- a/man/RainFARM.Rd +++ b/man/RainFARM.Rd @@ -4,10 +4,10 @@ \alias{RainFARM} \title{RainFARM stochastic precipitation downscaling (reduced version)} \usage{ -RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, kmin = 1, - fglob = FALSE, fsmooth = TRUE, nprocs = 1, time_dim = NULL, - lon_dim = "lon", lat_dim = "lat", drop_realization_dim = FALSE, - verbose = FALSE) +RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, + kmin = 1, fglob = FALSE, fsmooth = TRUE, nprocs = 1, + time_dim = NULL, lon_dim = "lon", lat_dim = "lat", + drop_realization_dim = FALSE, verbose = FALSE) } \arguments{ \item{data}{Precipitation array to downscale. @@ -117,4 +117,3 @@ dim(res$data) \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/SplitDim.Rd b/man/SplitDim.Rd index e36aa8a5..f07e4756 100644 --- a/man/SplitDim.Rd +++ b/man/SplitDim.Rd @@ -35,4 +35,3 @@ new_data <- SplitDim(data, indices = time, freq = 'year') \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/areave_data.Rd b/man/areave_data.Rd index cc79c85c..a772220a 100644 --- a/man/areave_data.Rd +++ b/man/areave_data.Rd @@ -41,4 +41,3 @@ areave_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} - diff --git a/man/as.s2dv_cube.Rd b/man/as.s2dv_cube.Rd index 13a2a296..c2b8f3a8 100644 --- a/man/as.s2dv_cube.Rd +++ b/man/as.s2dv_cube.Rd @@ -40,12 +40,11 @@ data <- as.s2dv_cube(data) class(data) } } +\seealso{ +\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} +} \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Nicolau Manubens, \email{nicolau.manubens@bsc.es} } -\seealso{ -\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} -} - diff --git a/man/lonlat_data.Rd b/man/lonlat_data.Rd index eca7abac..0c6ee30f 100644 --- a/man/lonlat_data.Rd +++ b/man/lonlat_data.Rd @@ -41,4 +41,3 @@ lonlat_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} - diff --git a/man/lonlat_prec.Rd b/man/lonlat_prec.Rd index 69cb94e8..345e3cab 100644 --- a/man/lonlat_prec.Rd +++ b/man/lonlat_prec.Rd @@ -29,4 +29,3 @@ lonlat_prec <- CST_Load('prlr', exp = list(infile), obs = NULL, Jost von Hardenberg \email{j.vonhardenberg@isac.cnr.it} } \keyword{data} - diff --git a/man/s2dv_cube.Rd b/man/s2dv_cube.Rd index 48af7bbb..f57d5ed3 100644 --- a/man/s2dv_cube.Rd +++ b/man/s2dv_cube.Rd @@ -75,10 +75,9 @@ exp8 <- s2dv_cube(data = exp_original, lon = seq(-10, 10, 5), lat = c(45, 50), end = paste0(rep("31", 10), rep("01", 10), 1990:1999))) class(exp8) } -\author{ -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} \seealso{ \code{\link[s2dverification]{Load}} and \code{\link{CST_Load}} } - +\author{ +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} -- GitLab From 4e069b47b30b9cc2829f09020a42810a98ea42c9 Mon Sep 17 00:00:00 2001 From: nperez Date: Mon, 9 Dec 2019 11:15:07 +0100 Subject: [PATCH 08/34] unit tests for CST_MergeDims --- R/CST_MergeDims.R | 21 +++++++--- tests/testthat/test-CST_MergeDims.R | 65 +++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 tests/testthat/test-CST_MergeDims.R diff --git a/R/CST_MergeDims.R b/R/CST_MergeDims.R index d258ac85..560f6c97 100644 --- a/R/CST_MergeDims.R +++ b/R/CST_MergeDims.R @@ -82,6 +82,8 @@ MergeDims <- function(data, merge_dims = c('time', 'monthly'), rename_dim = NULL "dimension will be used. To merge further dimensions ", "consider to use this function multiple times.") merge_dims <- merge_dims[1 : 2] + } else if (length(merge_dims) < 2) { + stop("Parameter 'merge_dims' must be of length two.") } if (is.null(rename_dim)) { rename_dim <- merge_dims[1] @@ -97,6 +99,10 @@ MergeDims <- function(data, merge_dims = c('time', 'monthly'), rename_dim = NULL } pos1 <- which(names(dims) == merge_dims[1]) pos2 <- which(names(dims) == merge_dims[2]) + if (length(pos1) == 0 | length(pos2) == 0) { + stop("Parameter 'merge_dims' must match with dimension ", + "names in parameter 'data'.") + } if (pos1 > pos2) { pos1 <- pos1 - 1 } @@ -104,13 +110,18 @@ MergeDims <- function(data, merge_dims = c('time', 'monthly'), rename_dim = NULL indices = x, drop = 'selected')}) data <- abind(data, along = pos1) names(dim(data)) <- names(dims)[-pos2] + if (!is.null(rename_dim)) { + names(dim(data))[pos1] <- rename_dim + } if (na.rm) { nas <- which(is.na(Subset(data, along = -pos1, indices = 1))) - nas <- unlist(lapply(nas, function(x) { - if(all(is.na(Subset(data, along = pos1, - indices = x)))) { - return(x)}})) - data <- Subset(data, along = pos1, indices = -nas) + if (length(nas) != 0) { + nas <- unlist(lapply(nas, function(x) { + if(all(is.na(Subset(data, along = pos1, + indices = x)))) { + return(x)}})) + data <- Subset(data, along = pos1, indices = -nas) + } } return(data) } diff --git a/tests/testthat/test-CST_MergeDims.R b/tests/testthat/test-CST_MergeDims.R new file mode 100644 index 00000000..45bcd8e9 --- /dev/null +++ b/tests/testthat/test-CST_MergeDims.R @@ -0,0 +1,65 @@ +context("Generic tests") +test_that("Sanity checks", { + expect_error( + CST_MergeDims(data = 1), + paste0("Parameter 'data' must be of the class 's2dv_cube', ", + "as output by CSTools::CST_Load.")) +data <- list(data = 1:10) +class(data) <- 's2dv_cube' + expect_error( + CST_MergeDims(data = data), + paste0("Parameter 'data' must have dimensions.")) + + data <- 1 : 20 + dim(data) <- c(time = 20) + data <- list(data = data) + class(data) <- 's2dv_cube' + expect_error( + CST_MergeDims(data = data), + "Parameter 'merge_dims' must match with dimension names in parameter 'data'.") + expect_error( + CST_MergeDims(data = data, merge_dims = 1), + paste0("Parameter 'merge_dims' must be a character vector indicating the names", + " of the dimensions to be merged.")) + expect_error( + CST_MergeDims(data = data, merge_dims = 'time'), + "Parameter 'merge_dims' must be of length two.") + expect_error( + CST_MergeDims(data = data, merge_dims = c('time', 'sdates')), + paste0("Parameter 'merge_dims' must match with dimension ", + "names in parameter 'data'.")) + + exp <- 1 : 20 + dim(exp) <- c(time = 10, lat = 2) + exp <- list(data = exp) + class(exp) <- 's2dv_cube' + expect_equal( + CST_MergeDims(data = exp, merge_dims = c('time', 'lat')), data) + + expect_warning( + CST_MergeDims(data = exp, merge_dims = c('time', 'lat', 'lon')), + paste0("Only two dimensions can be merge, only the first two dimension", + " will be used. To merge further dimensions consider to use this ", + "function multiple times.")) + expect_warning( + CST_MergeDims(data = exp, merge_dims = c('time', 'lat'), rename_dim = c('lat', 'lon')), + paste0("Parameter 'rename_dim' has length greater than 1 and only the ", + "first element will be used.")) + names(dim(data$data)) <- 'Dim1' + expect_equal( + CST_MergeDims(data = exp, merge_dims = c('time', 'lat'), rename_dim = 'Dim1'), + data) + + expect_equal( + CST_MergeDims(data = exp, merge_dims = c('time', 'lat'), + rename_dim = 'Dim1', na.rm = TRUE), data) + + exp$data[1,] <- NA + data <- c(2 : 10, 12 : 20) + dim(data) <- c(Dim1 = 18) + data <- list(data = data) + class(data) <- 's2dv_cube' + expect_equal( + CST_MergeDims(data = exp, merge_dims = c('time', 'lat'), + rename_dim = 'Dim1', na.rm = TRUE), data) +}) -- GitLab From 658b7020507bb3b73ec00cea74362da6c9a270c1 Mon Sep 17 00:00:00 2001 From: nperez Date: Mon, 9 Dec 2019 11:19:16 +0100 Subject: [PATCH 09/34] Changing R version to 3.4.2 --- .gitlab-ci.yml | 2 +- DESCRIPTION | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 86620985..3017964c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ build: stage: build script: #- module load R/3.4.3-foss-2015a-bare Julia - - module load R + - module load R/3.4.2-foss-2015a-bare #- julia -e 'using Pkg; Pkg.add(["RainFARM"])' - R CMD build --resave-data . - R CMD check --as-cran --no-manual --run-donttest CSTools_*.tar.gz diff --git a/DESCRIPTION b/DESCRIPTION index 0e47736a..cf5d323e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -42,7 +42,7 @@ Description: Exploits dynamical seasonal forecasts in order to provide Van Schaeybroeck et al. (2019) . Yiou et al. (2013) . Depends: - R (>= 3.2.0), + R (>= 3.4.2), maps Imports: s2dverification, -- GitLab From 1a062eda9097f7e295c8d7978b67353a5e9cb319 Mon Sep 17 00:00:00 2001 From: froura Date: Mon, 9 Dec 2019 16:23:10 +0100 Subject: [PATCH 10/34] Input Extreme and tercile limits as array. Check dimensions and consistency. --- R/PlotForecastPDF.R | 196 ++++++++++++++------------------------------ 1 file changed, 63 insertions(+), 133 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 8ba81fb9..22bfd367 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -71,64 +71,6 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check input arguments #------------------------ - - - # tercile.limits <- as.array(InsertDim(tercile.limits,2,1)) - # extreme.limits <- as.array(InsertDim(extreme.limits,2,1)) - # tercile.limits <- as.data.table(tercile.limits) - # extreme.limits <- as.data.table(extreme.limits) - - #add.ensmemb <- match.arg(add.ensmemb) - # if(!is.array(tercile.limits) & !is.array(extreme.limits)){ - # stop("tercile.limits or extreme.limits are not arrays") - # } - - # tercile.limits <- as.data.table(tercile_limits) - # extreme.limits <- as.data.table(extreme_limits) -if(!is.list(tercile.limits)){ - tercile.limits <- list(tercile.limits) -} - -if(!is.list(extreme.limits)){ - extreme.limits <- list(extreme.limits) -} - - - for( j in 1:length(tercile.limits)){ - - if (length(tercile.limits[[j]]) != 2) { - stop("Parameter 'tercile.limits' should be an array with two limits for delimiting tercile categories") - } - if (tercile.limits[[j]][1] >= tercile.limits[[j]][2]) { - stop("The provided tercile limits are in the wrong order") - } - if (!is.null(extreme.limits[[j]])) { - if (length(extreme.limits[[j]]) != 2) { - stop("Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") - } - if (extreme.limits[[j]][1] >= tercile.limits[[j]][1] | extreme.limits[[j]][2] <= - tercile.limits[[j]][2]) { - stop("The provided extreme limits are not consistent with tercile limits") - } - } - - } - -# add.ensmemb <- match.arg(add.ensmemb) -# if (length(tercile.limits) != 2) { -# stop("Parameter 'tercile.limits' should be an array with two limits for delimiting tercile categories") -# } -# if (tercile.limits[1] >= tercile.limits[2]) { -# stop("The provided tercile limits are in the wrong order") -# } -# if (!is.null(extreme.limits)) { -# if (length(extreme.limits) != 2) { -# stop("Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") -# } -# if (extreme.limits[1] >= tercile.limits[1] | extreme.limits[2] <= tercile.limits[2]) { - # stop("The provided extreme limits are not consistent with tercile limits") - # } - # } #------------------------ # Check fcst type and convert to data.frame if needed #------------------------ @@ -147,6 +89,62 @@ if(!is.list(extreme.limits)){ } else { stop("Parameter 'fcst' should be an array or a data.frame") } + npanels <- ncol(fcst.df) + #------------------------ + # Check tercile limits + #------------------------ + if (!is.array(tercile.limits)) { + stop("Tercile limits should be an array") + } + if (length(dim(tercile.limits)) == 1) { + if (dim(tercile.limits) != 2) { + stop("Provide 2 tercile limits") + } + tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) + } else if (length(dim(tercile.limits)) == 2) { + if (dim(tercile.limits)[2] != 2) { + stop("Provide two tercile limits for each panel") + } + if (dim(tercile.limits)[1] != npanels) { + stop("The number of tercile limits does not match the number of forecasts provided") + } + } else { + stop("tercile limits should have one or two dimensions") + } + # check consistency of tercile limits + if (any(tercile.limits[,1]>=tercile.limits[,2])) { + stop("Inconsistent tercile limits") + } + #------------------------ + # Check extreme limits + #------------------------ + if (!is.null(extreme.limits)) { + if (!is.array(extreme.limits)) { + stop("Extreme limits should be an array") + } + if (length(dim(extreme.limits)) == 1) { + if (dim(extreme.limits) != 2) { + stop("Provide 2 extreme limits") + } + extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) + } else if (length(dim(extreme.limits)) == 2) { + if (dim(extreme.limits)[2] != 2) { + stop("Provide two extreme limits for each panel") + } + if (dim(extreme.limits)[1] != npanels) { + stop("The number of extreme limits does not match the number of forecasts provided") + } + } else { + stop("extreme limits should have one or two dimensions") + } + # Check that extreme limits are consistent with tercile limits + if (any(extreme.limits[,1]>=tercile.limits[,1])) { + stop("Inconsistent lower extreme limits") + } + if (any(extreme.limits[,2]<=tercile.limits[,2])) { + stop("Inconsistent higher extreme limits") + } + } #------------------------ # Set proper fcst names #------------------------ @@ -178,33 +176,11 @@ if(!is.list(extreme.limits)){ stop("Cannot find PANELS in ggp object") } -if(length(tercile__limits)==1){ - - tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile__limits[1], "Below normal", - ifelse(tmp.df$x < tercile__limits[2], "Normal", "Above normal")), levels = c("Below normal", - "Normal", "Above normal")) - - -} else { - - tercile__limits <- abind(tercile.limits,along=0) #aqui . per _ - tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile__limits[tmp.df$PANEL,1], + tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile.limits[tmp.df$PANEL,1], "Below normal", - ifelse(tmp.df$x < tercile__limits[tmp.df$PANEL,2],"Normal", "Above normal")), + ifelse(tmp.df$x < tercile.limits[tmp.df$PANEL,2],"Normal", "Above normal")), levels = c("Below normal","Normal", "Above normal")) -} -# if (!is.null(ggp$layout$layout)) { -# tmp.df <- ggp$data[[1]][, c("x", "ymin", "ymax", "PANEL")] -# tmp.df$init <- ggp$layout$layout$init[as.numeric(tmp.df$PANEL)] -# } else if (!is.null(ggp$layout$panel_layout)) { -# tmp.df$init <- ggp$layout$panel_layout$init[as.numeric(tmp.df$PANEL)] -# } else { -# stop("Cannot find PANELS in ggp object") -# } -# tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile.limits[1], "Below normal", -# ifelse(tmp.df$x < tercile.limits[2], "Normal", "Above normal")), levels = c("Below normal", -# "Normal", "Above normal")) #------------------------ # Get the height and width of a panel #------------------------ @@ -214,26 +190,12 @@ if(length(tercile__limits)==1){ #------------------------ # Compute hatch coordinates for extremes #------------------------ - -if (!is.null(extreme.limits)) { - -if(length(extreme.limits)==1){ - - tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme__limits[1], "Below P10", - ifelse(tmp.df$x < extreme__limits[2], "Normal", "Above P90")), levels = c("Below P10", - "Normal", "Above P90")) - -} else { - - extreme__limits <- abind(extreme.limits,along=0) #aqui . per _ - tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,1], - "Below P10", - ifelse(tmp.df$x < extreme__limits[tmp.df$PANEL,2],"Normal", "Above P90")), + if (!is.null(extreme.limits)) { + tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme.limits[tmp.df$PANEL,1], + "Below P10", + ifelse(tmp.df$x < extreme.limits[tmp.df$PANEL,2],"Normal", "Above P90")), levels = c("Below P10","Normal", "Above P90")) - -} - hatch.ls <- dlply(tmp.df, .(init, extremes), function(x) { # close the polygon tmp.df2 <- data.frame(x = c(x$x, max(x$x), min(x$x)), y = c(x$ymax, 0, @@ -263,39 +225,7 @@ if(length(extreme.limits)==1){ } max.df <- do.call("rbind", max.ls) } -# if (!is.null(extreme.limits)) { -# tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme.limits[1], "Below P10", -# ifelse(tmp.df$x < extreme.limits[2], "Normal", "Above P90")), levels = c("Below P10", -# "Normal", "Above P90")) -# hatch.ls <- dlply(tmp.df, .(init, extremes), function(x) { - # close the polygon -# tmp.df2 <- data.frame(x = c(x$x, max(x$x), min(x$x)), y = c(x$ymax, 0, -# 0)) - # compute the hatches for this polygon -# hatches <- .polygon.fullhatch(tmp.df2$x, tmp.df2$y, angle = 60, density = 10, -# width.units = pan.width, height.units = pan.height) - # add bottom segment -# end1 <- data.frame(x = x$x[1], y = x$ymax[1], xend = x$x[1], yend = 0) - # add top segment -# end2 <- data.frame(x = x$x[length(x$x)], y = x$ymax[length(x$x)], xend = x$x[length(x$x)], -# yend = 0) -# return(rbind(hatches, end1, end2)) -# }) -# attr <- attr(hatch.ls, "split_labels") -# for (i in 1:length(hatch.ls)) { -# hatch.ls[[i]] <- cbind(hatch.ls[[i]], attr[i, ]) -# } -# hatch.df <- do.call("rbind", hatch.ls) - # Compute max y for each extreme category -# max.ls <- dlply(tmp.df, .(init, extremes), function(x) { -# data.frame(y = min(0.85 * pan.height, max(x$ymax))) -# }) -# attr <- attr(max.ls, "split_labels") -# for (i in 1:length(max.ls)) { -# max.ls[[i]] <- cbind(max.ls[[i]], attr[i, ]) -# } -# max.df <- do.call("rbind", max.ls) -# } + #------------------------ # Compute jitter space for ensemble members #------------------------ -- GitLab From 54e4964ffad769211a8e5ac9eb0ef9e96b25fd52 Mon Sep 17 00:00:00 2001 From: froura Date: Mon, 9 Dec 2019 16:30:07 +0100 Subject: [PATCH 11/34] Corrected bug in labels of tercile/extreme probabilities. Now uses first panel positions for all labels. --- R/PlotForecastPDF.R | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 22bfd367..2e308748 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -296,7 +296,6 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Compute probability for each tercile and identify MLT #------------------------ - tmp.dt <- data.table(tmp.df) pct <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), by = .(init, tercile)] @@ -304,45 +303,24 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N pct <- merge(pct, tot, by = "init") pct$pct <- round(100 * pct$pct/pct$tot, 0) pct$MLT <- pct[, .(MLT = pct == max(pct)), by = init]$MLT - lab.pos <- c(tercile.limits[[1]][1], mean(tercile.limits[[1]]), tercile.limits[[1]][2]) + lab.pos <- c(tercile.limits[1,1], mean(tercile.limits[1,]), tercile.limits[1,2]) - # tmp.dt <- data.table(tmp.df) - # pct <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), - # by = .(init, tercile)] - # tot <- pct[, .(tot = sum(pct)), by = init] - # pct <- merge(pct, tot, by = "init") - # pct$pct <- round(100 * pct$pct/pct$tot, 0) - # pct$MLT <- pct[, .(MLT = pct == max(pct)), by = init]$MLT - # lab.pos <- c(tercile.limits[1], mean(tercile.limits), tercile.limits[2]) #------------------------ # Compute probability for extremes #------------------------ - if (!is.null(extreme.limits)) { pct2 <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), by = .(init, extremes)] tot2 <- pct2[, .(tot = sum(pct)), by = init] pct2 <- merge(pct2, tot2, by = "init") pct2$pct <- round(100 * pct2$pct/pct2$tot, 0) - lab.pos2 <- c(extreme.limits[[1]][1], NA, extreme.limits[[1]][2]) + lab.pos2 <- c(extreme.limits[1,1], NA, extreme.limits[1,2]) pct2 <- merge(pct2, max.df, by = c("init", "extremes")) # include potentially missing groups pct2 <- pct2[CJ(levels(pct2$init), factor(c("Below P10", "Normal", "Above P90"), levels = c("Below P10", "Normal", "Above P90"))), ] } -# if (!is.null(extreme.limits)) { -# pct2 <- tmp.dt[, .(pct = integrate(approxfun(x, ymax), lower = min(x), upper = max(x))$value), -# by = .(init, extremes)] -# tot2 <- pct2[, .(tot = sum(pct)), by = init] -# pct2 <- merge(pct2, tot2, by = "init") -# pct2$pct <- round(100 * pct2$pct/pct2$tot, 0) -# lab.pos2 <- c(extreme.limits[1], NA, extreme.limits[2]) -# pct2 <- merge(pct2, max.df, by = c("init", "extremes")) - # include potentially missing groups -# pct2 <- pct2[CJ(levels(pct2$init), factor(c("Below P10", "Normal", "Above P90"), -# levels = c("Below P10", "Normal", "Above P90"))), ] -# } #------------------------ # Add probability labels for terciles #------------------------ -- GitLab From d2141ef511fce5cacd9085e58dcd610e638af942 Mon Sep 17 00:00:00 2001 From: froura Date: Mon, 9 Dec 2019 16:42:56 +0100 Subject: [PATCH 12/34] Input extreme.limits and tercile.limits as vector or array --- R/PlotForecastPDF.R | 52 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 2e308748..5f5ba451 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -93,23 +93,24 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check tercile limits #------------------------ - if (!is.array(tercile.limits)) { - stop("Tercile limits should be an array") - } - if (length(dim(tercile.limits)) == 1) { - if (dim(tercile.limits) != 2) { + if (is.vector(tercile.limits)) { + if (length(tercile.limits) != 2) { stop("Provide 2 tercile limits") } tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) - } else if (length(dim(tercile.limits)) == 2) { - if (dim(tercile.limits)[2] != 2) { - stop("Provide two tercile limits for each panel") - } - if (dim(tercile.limits)[1] != npanels) { - stop("The number of tercile limits does not match the number of forecasts provided") - } + } else if (is.array(tercile.limits)) { + if (length(dim(tercile.limits)) == 2) { + if (dim(tercile.limits)[2] != 2) { + stop("Provide two tercile limits for each panel") + } + if (dim(tercile.limits)[1] != npanels) { + stop("The number of tercile limits does not match the number of forecasts provided") + } + } else { + stop("tercile limits should have two dimensions") + } } else { - stop("tercile limits should have one or two dimensions") + stop("Tercile limits should be a vector of length two or an array of dimension (nfcsts,2)") } # check consistency of tercile limits if (any(tercile.limits[,1]>=tercile.limits[,2])) { @@ -119,23 +120,24 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Check extreme limits #------------------------ if (!is.null(extreme.limits)) { - if (!is.array(extreme.limits)) { - stop("Extreme limits should be an array") - } - if (length(dim(extreme.limits)) == 1) { - if (dim(extreme.limits) != 2) { + if (is.vector(extreme.limits)) { + if (length(extreme.limits) != 2) { stop("Provide 2 extreme limits") } extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) - } else if (length(dim(extreme.limits)) == 2) { - if (dim(extreme.limits)[2] != 2) { - stop("Provide two extreme limits for each panel") - } - if (dim(extreme.limits)[1] != npanels) { - stop("The number of extreme limits does not match the number of forecasts provided") + } else if (is.array(extreme.limits)) { + if (length(dim(extreme.limits)) == 2) { + if (dim(extreme.limits)[2] != 2) { + stop("Provide two extreme limits for each panel") + } + if (dim(extreme.limits)[1] != npanels) { + stop("The number of extreme limits does not match the number of forecasts provided") + } + } else { + stop("extreme limits should have two dimensions") } } else { - stop("extreme limits should have one or two dimensions") + stop("Extreme limits should be a vector of length two or an array of dimensions (nfcsts,2)") } # Check that extreme limits are consistent with tercile limits if (any(extreme.limits[,1]>=tercile.limits[,1])) { -- GitLab From 4ce76375aff33d3406092b683073155f5e5aab8a Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Thu, 12 Dec 2019 13:10:17 +0100 Subject: [PATCH 13/34] Modification in obs parameter description. Obs format is checked --- R/PlotForecastPDF.R | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 5f5ba451..1f1d6f84 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -6,7 +6,7 @@ #'@param fcst a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members. #'@param tercile.limits an array with P33 and P66 values that define the tercile categories for each panel. Should have 2*npanels dimensions. #'@param extreme.limits (optional) an array with P10 and P90 values that define the extreme categories. (Default: extreme categories are not shown). -#'@param obs (optional) a number with the observed value. (Default: observation is not shown). +#'@param obs (optional) A vector of length qual to the number of forecasts. A number with the observed value is accepted if observations are equal in each forecast. (Default: observation is not shown). #'@param plotfile (optional) a filename (pdf, png...) where the plot will be saved. (Default: the plot is not saved). #'@param title a string with the plot title. #'@param var.name a string with the variable name and units. @@ -91,6 +91,14 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N } npanels <- ncol(fcst.df) #------------------------ + # Check observations + #------------------------ + if (is.vector(obs) & length(obs) != 1 ) { + if (length(obs) != length(fcst)) { + stop("The number of observations differ from the number of forecasts.") + } + } + #------------------------ # Check tercile limits #------------------------ if (is.vector(tercile.limits)) { -- GitLab From a5d588e60a8447f1e9750d86c454e5dbcc78805b Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Thu, 12 Dec 2019 17:07:57 +0100 Subject: [PATCH 14/34] Modification in tercile.limits description. tercile.limitbeing 1-D array is now accepted --- R/PlotForecastPDF.R | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 1f1d6f84..9ad21ae4 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -4,7 +4,7 @@ #'@description This function plots the probability distribution function of several ensemble forecasts for the same event, either initialized at different moments or by different models. Probabilities for tercile categories are computed, plotted in colors and annotated. An asterisk marks the tercile with higher probabilities. Probabilities for extreme categories (above P90 and below P10) can also be included as hatched areas. Individual ensemble members can be plotted as jittered points. The observed value is optionally shown as a diamond. #' #'@param fcst a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members. -#'@param tercile.limits an array with P33 and P66 values that define the tercile categories for each panel. Should have 2*npanels dimensions. +#'@param tercile.limits an array with P33 and P66 values that define the tercile categories for each panel. Should have (nforecasts*2) dimensions. An unidimensional array with two elements or a 2-element vector are also accepted. #'@param extreme.limits (optional) an array with P10 and P90 values that define the extreme categories. (Default: extreme categories are not shown). #'@param obs (optional) A vector of length qual to the number of forecasts. A number with the observed value is accepted if observations are equal in each forecast. (Default: observation is not shown). #'@param plotfile (optional) a filename (pdf, png...) where the plot will be saved. (Default: the plot is not saved). @@ -101,12 +101,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check tercile limits #------------------------ - if (is.vector(tercile.limits)) { - if (length(tercile.limits) != 2) { - stop("Provide 2 tercile limits") - } - tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) - } else if (is.array(tercile.limits)) { + if (is.array(tercile.limits)) { if (length(dim(tercile.limits)) == 2) { if (dim(tercile.limits)[2] != 2) { stop("Provide two tercile limits for each panel") @@ -114,11 +109,19 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N if (dim(tercile.limits)[1] != npanels) { stop("The number of tercile limits does not match the number of forecasts provided") } - } else { + } else if (length(dim(tercile.limits == 1))){ + tercile.limits <- as.vector(tercile.limits) + tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) + } else { stop("tercile limits should have two dimensions") + } + } else if (is.vector(tercile.limits)) { + if (length(tercile.limits) != 2) { + stop("Provide 2 tercile limits") } + tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) } else { - stop("Tercile limits should be a vector of length two or an array of dimension (nfcsts,2)") + stop("Tercile limits should be a vector of length two or an array of dimension (1,2) or (nfcsts,2)") } # check consistency of tercile limits if (any(tercile.limits[,1]>=tercile.limits[,2])) { -- GitLab From 17ad54046b2bbdbd0a10300e5bb532e9a01cabc3 Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Mon, 16 Dec 2019 11:51:48 +0100 Subject: [PATCH 15/34] Update of extreme.limits description. 1-dimensional array with 2 elements is now accepted --- R/PlotForecastPDF.R | 48 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 9ad21ae4..77ed1437 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -5,7 +5,7 @@ #' #'@param fcst a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members. #'@param tercile.limits an array with P33 and P66 values that define the tercile categories for each panel. Should have (nforecasts*2) dimensions. An unidimensional array with two elements or a 2-element vector are also accepted. -#'@param extreme.limits (optional) an array with P10 and P90 values that define the extreme categories. (Default: extreme categories are not shown). +#'@param extreme.limits (optional) an array with P10 and P90 values that define the extreme categories. Should have (nforecasts*2) dimensions. An unidimensional array with two elements or a 2-element vector are also accepted. (Default: extreme categories are not shown). #'@param obs (optional) A vector of length qual to the number of forecasts. A number with the observed value is accepted if observations are equal in each forecast. (Default: observation is not shown). #'@param plotfile (optional) a filename (pdf, png...) where the plot will be saved. (Default: the plot is not saved). #'@param title a string with the plot title. @@ -131,29 +131,29 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Check extreme limits #------------------------ if (!is.null(extreme.limits)) { - if (is.vector(extreme.limits)) { - if (length(extreme.limits) != 2) { - stop("Provide 2 extreme limits") - } - extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) - } else if (is.array(extreme.limits)) { - if (length(dim(extreme.limits)) == 2) { - if (dim(extreme.limits)[2] != 2) { - stop("Provide two extreme limits for each panel") - } - if (dim(extreme.limits)[1] != npanels) { - stop("The number of extreme limits does not match the number of forecasts provided") - } - } else { - stop("extreme limits should have two dimensions") - } - } else { - stop("Extreme limits should be a vector of length two or an array of dimensions (nfcsts,2)") - } - # Check that extreme limits are consistent with tercile limits - if (any(extreme.limits[,1]>=tercile.limits[,1])) { - stop("Inconsistent lower extreme limits") - } + if (is.array(extreme.limits)) { + if (length(dim(extreme.limits)) == 2) { + if (dim(extreme.limits)[2] != 2) { + stop("Provide two extreme limits for each panel") + } + if (dim(extreme.limits)[1] != npanels) { + stop("The number of extreme limits does not match the number of forecasts provided") + } + } else if (length(dim(extreme.limits == 1))){ + extreme.limits <- as.vector(extreme.limits) + extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) + } else { + stop("extreme limits should have two dimensions") + } + } else if (is.vector(extreme.limits)) { + if (length(extreme.limits) != 2) { + stop("Provide 2 extreme limits") + } + extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) + } else { + stop("Extreme limits should be a vector of length two or an array of dimension (1,2) or (nfcsts,2)") + } +# check consistency of extreme limits if (any(extreme.limits[,2]<=tercile.limits[,2])) { stop("Inconsistent higher extreme limits") } -- GitLab From fc52bb69eab5fc53de3a7fae646959342222770d Mon Sep 17 00:00:00 2001 From: froura Date: Tue, 17 Dec 2019 10:58:28 +0100 Subject: [PATCH 16/34] Update PlotForecastPDF.R to enhance documentation --- R/PlotForecastPDF.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 77ed1437..b206b9ba 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -4,9 +4,9 @@ #'@description This function plots the probability distribution function of several ensemble forecasts for the same event, either initialized at different moments or by different models. Probabilities for tercile categories are computed, plotted in colors and annotated. An asterisk marks the tercile with higher probabilities. Probabilities for extreme categories (above P90 and below P10) can also be included as hatched areas. Individual ensemble members can be plotted as jittered points. The observed value is optionally shown as a diamond. #' #'@param fcst a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members. -#'@param tercile.limits an array with P33 and P66 values that define the tercile categories for each panel. Should have (nforecasts*2) dimensions. An unidimensional array with two elements or a 2-element vector are also accepted. -#'@param extreme.limits (optional) an array with P10 and P90 values that define the extreme categories. Should have (nforecasts*2) dimensions. An unidimensional array with two elements or a 2-element vector are also accepted. (Default: extreme categories are not shown). -#'@param obs (optional) A vector of length qual to the number of forecasts. A number with the observed value is accepted if observations are equal in each forecast. (Default: observation is not shown). +#'@param tercile.limits an array or vector with P33 and P66 values that define the tercile categories for each panel. Use an array of dimensions (nforecasts,2) to define different terciles for each forecast panel, or a vector with two elements to reuse the same tercile limits for all forecast panels. +#'@param extreme.limits (optional) an array or vector with P10 and P90 values that define the extreme categories for each panel. Use an array of (nforecasts,2) to define different extreme limits for each forecast panel, or a vector with two elements to reuse the same tercile limits for all forecast panels. (Default: extreme categories are not shown). +#'@param obs (optional) A vector providing the observed values for each forecast panel or a single value that will be reused for all forecast panels. (Default: observation is not shown). #'@param plotfile (optional) a filename (pdf, png...) where the plot will be saved. (Default: the plot is not saved). #'@param title a string with the plot title. #'@param var.name a string with the variable name and units. -- GitLab From 501f79fdb58981cee407bc2b297514b287c0d77d Mon Sep 17 00:00:00 2001 From: froura Date: Tue, 17 Dec 2019 11:13:13 +0100 Subject: [PATCH 17/34] Update PlotForecastPDF.R comprovation that observations are a vector or a number. --- R/PlotForecastPDF.R | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index b206b9ba..7209be9a 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -93,11 +93,15 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check observations #------------------------ - if (is.vector(obs) & length(obs) != 1 ) { - if (length(obs) != length(fcst)) { - stop("The number of observations differ from the number of forecasts.") - } - } + if (!is.vector(obs) | !is.numeric(obs) ){ + stop("Observations is not a vector or a numeric value") + } else { + if (is.vector(obs) & length(obs) != 1 ) { + if (length(obs) != length(fcst)) { + stop("The number of observations differ from the number of forecasts.") + } + } + } #------------------------ # Check tercile limits #------------------------ -- GitLab From ad6e4134affd6031a6c95edd618a45fa0c77dc27 Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Tue, 17 Dec 2019 11:35:48 +0100 Subject: [PATCH 18/34] If there is a unique forecast, extreme limits and tercile limits must be vectors. Now 1-D array is cot accepted. Observations are proven to be a vector or a numeric value. --- R/PlotForecastPDF.R | 69 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 7209be9a..ac6fb366 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -94,7 +94,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Check observations #------------------------ if (!is.vector(obs) | !is.numeric(obs) ){ - stop("Observations is not a vector or a numeric value") + stop("Observations is not a vector nor a numeric value") } else { if (is.vector(obs) & length(obs) != 1 ) { if (length(obs) != length(fcst)) { @@ -105,7 +105,12 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check tercile limits #------------------------ - if (is.array(tercile.limits)) { + if (is.vector(tercile.limits)) { + if (length(tercile.limits) != 2) { + stop("Provide 2 tercile limits") + } + tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) + } else if (is.array(tercile.limits)) { if (length(dim(tercile.limits)) == 2) { if (dim(tercile.limits)[2] != 2) { stop("Provide two tercile limits for each panel") @@ -113,19 +118,11 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N if (dim(tercile.limits)[1] != npanels) { stop("The number of tercile limits does not match the number of forecasts provided") } - } else if (length(dim(tercile.limits == 1))){ - tercile.limits <- as.vector(tercile.limits) - tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) - } else { - stop("tercile limits should have two dimensions") - } - } else if (is.vector(tercile.limits)) { - if (length(tercile.limits) != 2) { - stop("Provide 2 tercile limits") + } else { + stop("Tercile limits should have two dimensions") } - tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) } else { - stop("Tercile limits should be a vector of length two or an array of dimension (1,2) or (nfcsts,2)") + stop("Tercile limits should be a vector of length two or an array of dimension (nfcsts,2)") } # check consistency of tercile limits if (any(tercile.limits[,1]>=tercile.limits[,2])) { @@ -135,29 +132,29 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Check extreme limits #------------------------ if (!is.null(extreme.limits)) { - if (is.array(extreme.limits)) { - if (length(dim(extreme.limits)) == 2) { - if (dim(extreme.limits)[2] != 2) { - stop("Provide two extreme limits for each panel") - } - if (dim(extreme.limits)[1] != npanels) { - stop("The number of extreme limits does not match the number of forecasts provided") - } - } else if (length(dim(extreme.limits == 1))){ - extreme.limits <- as.vector(extreme.limits) - extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) - } else { - stop("extreme limits should have two dimensions") - } - } else if (is.vector(extreme.limits)) { - if (length(extreme.limits) != 2) { - stop("Provide 2 extreme limits") - } - extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) - } else { - stop("Extreme limits should be a vector of length two or an array of dimension (1,2) or (nfcsts,2)") - } -# check consistency of extreme limits + if (is.vector(extreme.limits)) { + if (length(extreme.limits) != 2) { + stop("Provide 2 extreme limits") + } + extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) + } else if (is.array(extreme.limits)) { + if (length(dim(extreme.limits)) == 2) { + if (dim(extreme.limits)[2] != 2) { + stop("Provide two extreme limits for each panel") + } + if (dim(extreme.limits)[1] != npanels) { + stop("The number of extreme limits does not match the number of forecasts provided") + } + } else { + stop("extreme limits should have two dimensions") + } + } else { + stop("Extreme limits should be a vector of length two or an array of dimensions (nfcsts,2)") + } + # Check that extreme limits are consistent with tercile limits + if (any(extreme.limits[,1]>=tercile.limits[,1])) { + stop("Inconsistent lower extreme limits") + } if (any(extreme.limits[,2]<=tercile.limits[,2])) { stop("Inconsistent higher extreme limits") } -- GitLab From c82215a7bdda7483b343d57fc3a40fd6a88cb083 Mon Sep 17 00:00:00 2001 From: Eroteida Sanchez Garcia Date: Fri, 17 Jan 2020 08:12:15 +0000 Subject: [PATCH 19/34] CST_BEI_Weighting working with NAs --- DESCRIPTION | 2 +- R/CST_BEI_Weighting.R | 312 +++++++++++++++++++++++---- man/Analogs.Rd | 13 +- man/BEI_PDFBest.Rd | 7 +- man/BEI_Weights.Rd | 7 +- man/CST_Analogs.Rd | 9 +- man/CST_Anomaly.Rd | 7 +- man/CST_BEI_Weighting.Rd | 16 +- man/CST_BiasCorrection.Rd | 7 +- man/CST_Calibration.Rd | 11 +- man/CST_CategoricalEnsCombination.Rd | 7 +- man/CST_EnsClustering.Rd | 1 - man/CST_Load.Rd | 1 - man/CST_MultiEOF.Rd | 5 +- man/CST_MultiMetric.Rd | 9 +- man/CST_MultivarRMSE.Rd | 7 +- man/CST_QuantileMapping.Rd | 7 +- man/CST_RFSlope.Rd | 1 - man/CST_RFWeights.Rd | 7 +- man/CST_RainFARM.Rd | 7 +- man/CST_SaveExp.Rd | 7 +- man/CST_SplitDim.Rd | 4 +- man/EnsClustering.Rd | 1 - man/MultiEOF.Rd | 1 - man/PlotCombinedMap.Rd | 15 +- man/PlotForecastPDF.Rd | 10 +- man/PlotMostLikelyQuantileMap.Rd | 7 +- man/RFSlope.Rd | 1 - man/RainFARM.Rd | 9 +- man/SplitDim.Rd | 1 - man/areave_data.Rd | 1 - man/as.s2dv_cube.Rd | 7 +- man/lonlat_data.Rd | 1 - man/lonlat_prec.Rd | 1 - man/s2dv_cube.Rd | 7 +- 35 files changed, 361 insertions(+), 155 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 0e47736a..c3de9d84 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -70,4 +70,4 @@ VignetteBuilder: knitr License: Apache License 2.0 Encoding: UTF-8 LazyData: true -RoxygenNote: 5.0.0 +RoxygenNote: 6.1.1 diff --git a/R/CST_BEI_Weighting.R b/R/CST_BEI_Weighting.R index 51c8ba32..96265cdc 100644 --- a/R/CST_BEI_Weighting.R +++ b/R/CST_BEI_Weighting.R @@ -19,6 +19,10 @@ #' (time, member), when 'time' is the temporal dimension as default. #' When 'aweights' parameter has any other dimensions (as e.g. 'lat') and #' 'var_exp' parameter has also the same dimension, they must be equals. +#' @param terciles A numeric array with at least one dimension 'tercil' equal to +#' 2, the first element is the lower tercil for a hindcast period, and the second +#' element is the upper tercile. By default is NULL, the terciles are computed +#' from var_exp data. #' @param type A character string indicating the type of output. #' If 'type' = 'probs', the function returns, in the element data from #' 'var_exp' parameter, an array with at least two @@ -36,7 +40,7 @@ #' with weighted members. #' @param time_dim_name A character string indicating the name of the #' temporal dimension, by default 'time'. -#' +#' #' @return CST_BEI_Weighting() returns a CSTools object (i.e., of the #' class 's2dv_cube'). #' This object has at least an element named \code{$data} @@ -56,8 +60,10 @@ #' # time lat lon dataset #' # 2 3 2 2 #' @export -CST_BEI_Weighting <- function(var_exp, aweights, type = 'ensembleMean', - time_dim_name = 'time') { + +CST_BEI_Weighting <- function(var_exp, aweights, terciles = NULL, + type = 'ensembleMean', time_dim_name = 'time') { + if (!is.character(time_dim_name)) { stop("Parameter 'time_dim_name' must be a character string indicating", " the name of the temporal dimension.") @@ -80,6 +86,27 @@ CST_BEI_Weighting <- function(var_exp, aweights, type = 'ensembleMean', stop("Parameter 'var_exp' must be of the class 's2dv_cube', ", "as output by CSTools::CST_Load.") } + if (!is.null(terciles)){ + if(!is.array(terciles)){ + stop("Parameter 'terciles' must be an array.") + } + if (is.null(names(dim(terciles)))) { + stop("Parameters 'terciles' should have dimmension names.") + } + if(!('tercil' %in% names(dim(terciles)))) { + stop("Parameter 'terciles' must have dimension 'tercil'.") + } + if (dim(terciles)['tercil'] != 2) { + stop("Length of dimension 'tercil' ", + "of parameter 'terciles' must be equal to 2.") + } + if(time_dim_name %in% names(dim(terciles))) { + stop("Parameter 'terciles' must not have temporal dimension.") + } + if('member' %in% names(dim(terciles))) { + stop("Parameter 'terciles' must not have dimension 'member'.") + } + } if (!is.array(aweights)) { stop("Parameter 'aweights' must be an array.") } @@ -115,7 +142,10 @@ CST_BEI_Weighting <- function(var_exp, aweights, type = 'ensembleMean', em <- BEI_EMWeighting(var_exp$data, aweights, time_dim_name) var_exp$data <- em } else if (type == 'probs'){ - probs <- BEI_ProbsWeighting(var_exp$data, aweights, time_dim_name) + if (is.null(terciles)){ + terciles <- BEI_TercilesWeighting(var_exp$data, aweights, time_dim_name) + } + probs <- BEI_ProbsWeighting(var_exp$data, aweights, terciles, time_dim_name) var_exp$data <- probs } else { stop("Parameter 'type' must be a character string ('probs' or ", @@ -265,6 +295,9 @@ BEI_EMWeighting <- function(var_exp, aweights, time_dim_name = 'time') { #' variable, as 'time' the spatial dimension by default. #' @param aweights Normalized weights array with at least dimensions #' (time, member), when 'time' is the temporal dimension as default. +#' @param terciles A numeric array with at least one dimension 'tercil' equal to +#' 2, the first element is the lower tercil for a hindcast period, and the second +#' element is the upper tercile. #' @param time_dim_name A character string indicating the name of the #' temporal dimension, by default 'time'. #' @@ -284,7 +317,9 @@ BEI_EMWeighting <- function(var_exp, aweights, time_dim_name = 'time') { #' dim(var_exp) <- c(time = 2, member = 4) #' aweights<- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.4, 0.3) #' dim(aweights) <- c(time = 2, member = 4) -#' res <- BEI_ProbsWeighting(var_exp, aweights) +#' terciles <- c(2.5,5) +#' dim(terciles) <- c(tercil = 2) +#' res <- BEI_ProbsWeighting(var_exp, aweights, terciles) #' dim(res) #' # time tercil #' # 2 3 @@ -293,12 +328,18 @@ BEI_EMWeighting <- function(var_exp, aweights, time_dim_name = 'time') { #' dim(var_exp) <- c(time = 2, member = 4, lat = 2, lon = 3) #' aweights<- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.4, 0.3) #' dim(aweights) <- c(time = 2, member = 4) -#' res <- BEI_ProbsWeighting(var_exp, aweights) +#' terciles <- rep(c(48,50), 2*3) +#' dim(terciles) <- c(tercil = 2, lat = 2, lon = 3) +#' res <- BEI_ProbsWeighting(var_exp, aweights, terciles) #' dim(res) #' # time tercil lat lon #' # 2 3 2 3 #' @noRd -BEI_ProbsWeighting <- function(var_exp, aweights, time_dim_name = 'time') { +#' +#' + +BEI_ProbsWeighting <- function(var_exp, aweights, terciles, + time_dim_name = 'time') { if (!is.character(time_dim_name)) { stop("Parameter 'time_dim_name' must be a character string indicating", @@ -309,6 +350,28 @@ BEI_ProbsWeighting <- function(var_exp, aweights, time_dim_name = 'time') { "only the first element will be used.") time_dim_name <- time_dim_name[1] } + if (is.null(terciles)){ + stop("Parameter 'terciles' is null") + } + if(!is.array(terciles)){ + stop("Parameter 'terciles' must be an array.") + } + if (is.null(names(dim(terciles)))) { + stop("Parameters 'terciles' should have dimmension names.") + } + if(!('tercil' %in% names(dim(terciles)))) { + stop("Parameter 'terciles' must have dimension 'tercil'.") + } + if (dim(terciles)['tercil'] != 2) { + stop("Length of dimension 'tercil' ", + "of parameter 'terciles' must be equal to 2.") + } + if(time_dim_name %in% names(dim(terciles))) { + stop("Parameter 'terciles' must not have temporal dimension.") + } + if('member' %in% names(dim(terciles))) { + stop("Parameter 'terciles' must not have dimension 'member'.") + } if (!is.array(var_exp)) { stop("Parameter 'var_exp' must be an array.") } @@ -326,10 +389,10 @@ BEI_ProbsWeighting <- function(var_exp, aweights, time_dim_name = 'time') { stop("Parameter 'aweights' must have temporal dimension.") } if(!('member' %in% names(dim(var_exp)))) { - stop("Parameter 'var_exp' must have temporal dimension.") + stop("Parameter 'var_exp' must have dimension 'member'.") } if(!('member' %in% names(dim(aweights)))) { - stop("Parameter 'aweights' must have temporal dimension.") + stop("Parameter 'aweights' must have dimension 'member'.") } if (dim(var_exp)[time_dim_name] != dim(aweights)[time_dim_name]) { stop("Length of temporal dimensions ", @@ -340,8 +403,11 @@ BEI_ProbsWeighting <- function(var_exp, aweights, time_dim_name = 'time') { "of parameter 'var_exp' and 'aweights' must be equals.") } - res <- Apply(list(var_exp, aweights), - target_dims = list(c(time_dim_name,'member'), c(time_dim_name,'member')), + + res <- Apply(list(var_exp, aweights, terciles), + target_dims = list(c(time_dim_name,'member'), + c(time_dim_name,'member'), + c('tercil')), fun = .BEI_ProbsWeighting, time_dim_name)$output1 return(res) } @@ -352,8 +418,12 @@ BEI_ProbsWeighting <- function(var_exp, aweights, time_dim_name = 'time') { #' by default 'time', and dimension 'member'. #' @param aweights Normalized weights array with a temporal dimension, #' by default 'time', and dimension 'member' +#' @param terciles A numeric array with one dimension 'tercil' equal to 2, +#' the first element is the lower tercil for a hindcast period, and the second +#' element is the upper tercile. #' @param time_dim_name A character string indicating the name of the #' temporal dimension, by default 'time'. +#' #' @return .BEI_ProbsWeighting returns an array of with a temporal dimension, #' as default 'time', and 'tercil' dimension, containing the probabilities #' for each tercile computing with weighted members. @@ -363,48 +433,208 @@ BEI_ProbsWeighting <- function(var_exp, aweights, time_dim_name = 'time') { #' # Example #' var_exp <- 1 : 8 #' dim(var_exp) <- c(stime = 2, member = 4) -#' aweights <- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.3, 0.3) +#' aweights <- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.4, 0.3) #' dim(aweights) <- c(stime = 2, member = 4) -#' res <- .BEI_ProbsWeighting(var_exp, aweights, time_dim_name = 'stime') +#' terciles <- quantile(1:8, probs = c(1/3, 2/3)) +#' dim(terciles) <- c(tercil = 2) +#' res <- .BEI_ProbsWeighting(var_exp, aweights, terciles, time_dim_name = 'stime') #' dim(res) #' # stime tercil #' # 2 3 #' @noRd -.BEI_ProbsWeighting <- function(var_exp, aweights, time_dim_name = 'time') { - # computing terciles - terciles_exp <- WeightTerciles(var_exp, aweights, time_dim_name) - lowerTercile <- terciles_exp$lowerTercile - upperTercile <- terciles_exp$upperTercile - - # Probabilities - aTerciles <- Apply(list(var_exp), target_dims = list('member'), - fun = Data2Tercil, lowerTercile, upperTercile)$output1 +.BEI_ProbsWeighting <- function(var_exp, aweights, terciles, + time_dim_name = 'time') { + if(any(is.na(var_exp)) || any(is.na(aweights))){ + probTercile <- array(NA, dim = c(dim(var_exp)[time_dim_name], tercil = 3)) + } else { + if(any(is.na(terciles))) stop("Terciles are NAs") + terciles_exp <- list(lowerTercile = terciles[1], + upperTercile = terciles[2]) + + lowerTercile <- terciles_exp$lowerTercile + upperTercile <- terciles_exp$upperTercile + + # Probabilities + aTerciles <- Apply(list(var_exp), target_dims = list('member'), + fun = Data2Tercil, lowerTercile, upperTercile)$output1 + + pos <- match(names(dim(aTerciles)), c(time_dim_name,'member')) + aTerciles <- aperm(aTerciles,pos) + names(dim(aTerciles)) <- c(time_dim_name,'member') + + probTercile <- array(NA, dim = c(dim(var_exp)[time_dim_name], tercil = 3)) + for (idTercil in 1:3){ + probTercile[,idTercil] <- Apply(list(aTerciles, aweights), + target_dims = list('member','member'), + fun = WeightTercil2Prob, idTercil)$output1 + } + } + return(probTercile) +} + +#' Computing the weighted terciles for SFSs. +#' @author Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +#' +#' @description This function implements the computation to obtain the terciles +#' for a weighted variable for SFSs using a normalized weights array, +#' +#' @references Regionally improved seasonal forecast of precipitation through Best +#' estimation of winter NAO, Sanchez-Garcia, E. et al., +#' Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 +#' +#' @param var_exp Variable (e.g. precipitation, temperature, NAO index) +#' array from a SFS with at least dimensions (time, member) for a spatially +#' aggregated variable or dimensions (time, member, lat, lon) for a spatial +#' variable, as 'time' the spatial dimension by default. +#' @param aweights Normalized weights array with at least dimensions +#' (time, member), when 'time' is the temporal dimension as default. +#' @param time_dim_name A character string indicating the name of the +#' temporal dimension, by default 'time'. +#' +#' @return BEI_TercilesWeighting() returns an array with at least one +#' dimension depending if the variable is a spatially aggregated variable +#' (as e.g. NAO index)(tercil) or it is spatial variable (as e.g. +#' precipitation or temperature)(tercil, lat, lon), containing the +#' terciles computing with weighted members. +#' The first tercil is the lower tercile, the second is the upper tercile. +#' +#' @import multiApply +#' +#' @examples +#' # Example 1 +#' var_exp <- 1 : (2 * 4) +#' dim(var_exp) <- c(time = 2, member = 4) +#' aweights<- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.4, 0.3) +#' dim(aweights) <- c(time = 2, member = 4) +#' res <- BEI_TercilesWeighting(var_exp, aweights) +#' dim(res) +#' # tercil +#' # 2 +#' # Example 2 +#' var_exp <- rnorm(48, 50, 9) +#' dim(var_exp) <- c(time = 2, member = 4, lat = 2, lon = 3) +#' aweights<- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.4, 0.3) +#' dim(aweights) <- c(time = 2, member = 4) +#' res <- BEI_TercilesWeighting(var_exp, aweights) +#' dim(res) +#' # tercil lat lon +#' # 2 2 3 +#' @noRd +#' +BEI_TercilesWeighting <- function(var_exp, aweights, time_dim_name = 'time') { - pos <- match(names(dim(aTerciles)), c(time_dim_name,'member')) - aTerciles <- aperm(aTerciles,pos) - names(dim(aTerciles)) <- c(time_dim_name,'member') + if (!is.character(time_dim_name)) { + stop("Parameter 'time_dim_name' must be a character string indicating", + " the name of the temporal dimension.") + } + if (length(time_dim_name) > 1) { + warning("Parameter 'time_dim_name' has length greater than 1 and ", + "only the first element will be used.") + time_dim_name <- time_dim_name[1] + } + if (!is.array(var_exp)) { + stop("Parameter 'var_exp' must be an array.") + } + if (!is.array(aweights)) { + stop("Parameter 'aweights' must be an array.") + } + if (is.null(names(dim(var_exp))) || is.null(names(dim(aweights)))) { + stop("Parameters 'var_exp' and 'aweights'", + " should have dimmension names.") + } + if(!(time_dim_name %in% names(dim(var_exp)))) { + stop("Parameter 'var_exp' must have temporal dimension.") + } + if(!(time_dim_name %in% names(dim(aweights)))) { + stop("Parameter 'aweights' must have temporal dimension.") + } + if(!('member' %in% names(dim(var_exp)))) { + stop("Parameter 'var_exp' must have temporal dimension.") + } + if(!('member' %in% names(dim(aweights)))) { + stop("Parameter 'aweights' must have temporal dimension.") + } + if (dim(var_exp)[time_dim_name] != dim(aweights)[time_dim_name]) { + stop("Length of temporal dimensions ", + "of parameter 'var_exp' and 'aweights' must be equals.") + } + if (dim(var_exp)['member'] != dim(aweights)['member']) { + stop("Length of dimension 'member' ", + "of parameter 'var_exp' and 'aweights' must be equals.") + } - probTercile <- array(NA, dim = c(dim(var_exp)[time_dim_name], tercil = 3)) - for (idTercil in 1:3){ - probTercile[,idTercil] <- Apply(list(aTerciles, aweights), - target_dims = list('member','member'), - fun = WeightTercil2Prob, idTercil)$output1 + res <- Apply(list(var_exp, aweights), + target_dims = list(c(time_dim_name,'member'), c(time_dim_name,'member')), + fun = .BEI_TercilesWeighting, time_dim_name)$output1 + return(res) +} + +#' Atomic BEI_TercilesWeighting +#' @param var_exp Variable (e.g. precipitation, temperature, NAO index) +#' array from a SFS with a temporal dimension, +#' by default 'time', and dimension 'member'. +#' @param aweights Normalized weights array with a temporal dimension, +#' by default 'time', and dimension 'member' +#' @param time_dim_name A character string indicating the name of the +#' temporal dimension, by default 'time'. +#' @return .BEI_TercilesWeighting returns a numeric array with dimension tercil +#' equal to 2, the first is the lower tercil and the second the upper tercile, +#' computing with weighted members considering all members and all period. +#' If any member value for any period is NA , the terciles are not computed, and +#' the function return NA value as tercile upper and lower. +#' @examples +#' # Example +#' var_exp <- 1 : 8 +#' dim(var_exp) <- c(stime = 2, member = 4) +#' aweights <- c(0.2, 0.1, 0.3, 0.4, 0.1, 0.2, 0.4, 0.3) +#' dim(aweights) <- c(stime = 2, member = 4) +#' res <- .BEI_TercilesWeighting(var_exp, aweights, time_dim_name = 'stime') +#' dim(res) +#' # tercil +#' # 2 +#' @noRd +.BEI_TercilesWeighting <- function(var_exp, aweights, time_dim_name = 'time') { + if(any(is.na(var_exp)) || any(is.na(aweights))){ + terciles_exp <- array(c(NA, NA), dim = c(tercil = 2)) + } else { + l_terciles_exp <- WeightTerciles(var_exp, aweights, time_dim_name) + terciles_exp <- array(c(l_terciles_exp$lowerTercile, + l_terciles_exp$upperTercile), dim = c(tercil = 2)) } - return(probTercile) + return(terciles_exp) } +# Auxiliar function to compute in which tercile is a data value +Data2Tercil_old <- function(x,lt,ut) { + if(is.na(lt) || is.na(ut)){ + y <- rep(NA, length(x)) + } else { + y <- rep(2,length(x)) + y[x <= lt] <- 1 + y[x >= ut] <- 3 + if (lt == ut) { + warning("The upper and lower terciles are equals") + } + } + dim(y) <- c(member = length(x)) + return (y) +} # Auxiliar function to compute in which tercile is a data value Data2Tercil <- function(x,lt,ut) { - y <- rep(2,length(x)) - y[x <= lt] <- 1 - y[x >= ut] <- 3 - if (lt == ut) { - warning("The upper and lower terciles are equals") + if(is.na(lt) || is.na(ut)){ + y <- rep(NA, length(x)) + } else { + y <- rep(2,length(x)) + y[x <= lt] <- 1 + y[x >= ut] <- 3 + if (lt == ut) { + y <- rep(NA, length(x)) + } } dim(y) <- c(member = length(x)) + y[which(is.na(x))] <- NA return (y) } - # Auxiliar function to convers weighted terciles to probabilities WeightTercil2Prob <- function(aTerciles, aWeights, idTercil) { return(sum(aWeights[which(aTerciles == idTercil)])) @@ -419,10 +649,12 @@ WeightTerciles <- function(data, aweights, time_dim_name = 'time') { names(dim(aweights)) <- namesdimdata vectorData <- as.vector(data) vectorWeights <- as.vector(aweights/dim(aweights)[time_dim_name]) # normalized - lSortData <- sort(vectorData,index.return=TRUE) - indSort <- lSortData$ix # index asociated to weight + #lSortData <- sort(vectorData,index.return=TRUE) + indSort <- order(vectorData) # index asociated to weight + # indSort <- lSortData$ix # index asociated to weight # corresponding for this data - dataSort <- lSortData$x + dataSort <- vectorData[indSort] + # dataSort <- lSortData$x # Adding normalized weights. When 1/3 is reached, the data value # is lower tercile and when 2/3 is reached, it is the upper tercile. sumWeights <- 0 diff --git a/man/Analogs.Rd b/man/Analogs.Rd index ee8a737e..52d9ff97 100644 --- a/man/Analogs.Rd +++ b/man/Analogs.Rd @@ -5,8 +5,8 @@ \title{Analogs based on large scale fields.} \usage{ Analogs(expL, obsL, time_obsL, expVar = NULL, obsVar = NULL, - criteria = "Large_dist", lonVar = NULL, latVar = NULL, region = NULL, - nAnalogs = NULL, return_list = FALSE) + criteria = "Large_dist", lonVar = NULL, latVar = NULL, + region = NULL, nAnalogs = NULL, return_list = FALSE) } \arguments{ \item{expL}{an array of N named dimensions containing the experimental field @@ -377,11 +377,6 @@ Local_scalecor <- Analogs(expL=expSLP, str(Local_scalecor) Local_scalecor$AnalogsInfo -} -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} - -Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -389,4 +384,8 @@ and M. Vrac, 2013 : Ensemble reconstruction of the atmospheric column from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. \email{pascal.yiou@lsce.ipsl.fr} } +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} +Nuria Perez-Zanon \email{nuria.perez@bsc.es} +} diff --git a/man/BEI_PDFBest.Rd b/man/BEI_PDFBest.Rd index f836ab72..f120258d 100644 --- a/man/BEI_PDFBest.Rd +++ b/man/BEI_PDFBest.Rd @@ -113,12 +113,11 @@ dim(res) # time statistic season # 1 2 2 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/BEI_Weights.Rd b/man/BEI_Weights.Rd index 61db33af..867a4eb0 100644 --- a/man/BEI_Weights.Rd +++ b/man/BEI_Weights.Rd @@ -43,13 +43,12 @@ dim(res) # sdate dataset member season # 10 3 5 1 -} -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} } \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/CST_Analogs.Rd b/man/CST_Analogs.Rd index 7c9a1e6f..c9166de6 100644 --- a/man/CST_Analogs.Rd +++ b/man/CST_Analogs.Rd @@ -81,11 +81,6 @@ adapted version of the method of Yiou et al 2013. \examples{ res <- CST_Analogs(expL = lonlat_data$exp, obsL = lonlat_data$obs) -} -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} - -Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -97,4 +92,8 @@ from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. code{\link{CST_Load}}, \code{\link[s2dverification]{Load}} and \code{\link[s2dverification]{CDORemap}} } +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} +Nuria Perez-Zanon \email{nuria.perez@bsc.es} +} diff --git a/man/CST_Anomaly.Rd b/man/CST_Anomaly.Rd index e1c31f0c..b214a31a 100644 --- a/man/CST_Anomaly.Rd +++ b/man/CST_Anomaly.Rd @@ -53,13 +53,12 @@ str(anom3) anom4 <- CST_Anomaly(exp = exp, obs = obs, cross = FALSE, memb = FALSE) str(anom4) +} +\seealso{ +\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} } \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Pena Jesus, \email{jesus.pena@bsc.es} } -\seealso{ -\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} -} - diff --git a/man/CST_BEI_Weighting.Rd b/man/CST_BEI_Weighting.Rd index 6b9a448a..9c0f5a9d 100644 --- a/man/CST_BEI_Weighting.Rd +++ b/man/CST_BEI_Weighting.Rd @@ -4,8 +4,8 @@ \alias{CST_BEI_Weighting} \title{Weighting SFSs of a CSTools object.} \usage{ -CST_BEI_Weighting(var_exp, aweights, type = "ensembleMean", - time_dim_name = "time") +CST_BEI_Weighting(var_exp, aweights, terciles = NULL, + type = "ensembleMean", time_dim_name = "time") } \arguments{ \item{var_exp}{An object of the class 's2dv_cube' containing the variable @@ -18,6 +18,11 @@ at least a temporal dimension and a dimension named 'member'.} When 'aweights' parameter has any other dimensions (as e.g. 'lat') and 'var_exp' parameter has also the same dimension, they must be equals.} +\item{terciles}{A numeric array with at least one dimension 'tercil' equal to +2, the first element is the lower tercil for a hindcast period, and the second +element is the upper tercile. By default is NULL, the terciles are computed +from var_exp data.} + \item{type}{A character string indicating the type of output. If 'type' = 'probs', the function returns, in the element data from 'var_exp' parameter, an array with at least two @@ -63,12 +68,11 @@ dim(res_CST$data) # time lat lon dataset # 2 3 2 2 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/CST_BiasCorrection.Rd b/man/CST_BiasCorrection.Rd index 485199ea..a1b415fb 100644 --- a/man/CST_BiasCorrection.Rd +++ b/man/CST_BiasCorrection.Rd @@ -35,10 +35,9 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_BiasCorrection(exp = exp, obs = obs) str(a) } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} -} \references{ Torralba, V., F.J. Doblas-Reyes, D. MacLeod, I. Christel and M. Davis (2017). Seasonal climate prediction: a new source of information for the management of wind energy resources. Journal of Applied Meteorology and Climatology, 56, 1231-1247, doi:10.1175/JAMC-D-16-0204.1. (CLIM4ENERGY, EUPORIAS, NEWA, RESILIENCE, SPECS) } -\encoding{UTF-8} +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} +} diff --git a/man/CST_Calibration.Rd b/man/CST_Calibration.Rd index 36171dbd..08d4a4ec 100644 --- a/man/CST_Calibration.Rd +++ b/man/CST_Calibration.Rd @@ -26,11 +26,6 @@ Four types of member-by-member bias correction can be performed. The \code{bias} Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} - -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} \references{ Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x @@ -57,4 +52,8 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_Calibration(exp = exp, obs = obs, cal.method = "mse_min", eval.method = "in-sample") str(a) } -\encoding{UTF-8} +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} + +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} diff --git a/man/CST_CategoricalEnsCombination.Rd b/man/CST_CategoricalEnsCombination.Rd index e551c3ec..7175b7fe 100644 --- a/man/CST_CategoricalEnsCombination.Rd +++ b/man/CST_CategoricalEnsCombination.Rd @@ -83,9 +83,6 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_CategoricalEnsCombination(exp = exp, obs = obs, amt.cat = 3, cat.method = "mmw") } } -\author{ -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} \references{ Rajagopalan, B., Lall, U., & Zebiak, S. E. (2002). Categorical climate forecasts through regularization and optimal combination of multiple GCM ensembles. Monthly Weather Review, 130(7), 1792-1811. @@ -93,4 +90,6 @@ Robertson, A. W., Lall, U., Zebiak, S. E., & Goddard, L. (2004). Improved combin Van Schaeybroeck, B., & Vannitsem, S. (2019). Postprocessing of Long-Range Forecasts. In Statistical Postprocessing of Ensemble Forecasts (pp. 267-290). } - +\author{ +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} diff --git a/man/CST_EnsClustering.Rd b/man/CST_EnsClustering.Rd index c13bf205..de71d4e3 100644 --- a/man/CST_EnsClustering.Rd +++ b/man/CST_EnsClustering.Rd @@ -125,4 +125,3 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/CST_Load.Rd b/man/CST_Load.Rd index 1fee022c..bf03ba42 100644 --- a/man/CST_Load.Rd +++ b/man/CST_Load.Rd @@ -47,4 +47,3 @@ obs <- CSTools::lonlat_data$obs \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} } - diff --git a/man/CST_MultiEOF.Rd b/man/CST_MultiEOF.Rd index fb584751..5fea8a50 100644 --- a/man/CST_MultiEOF.Rd +++ b/man/CST_MultiEOF.Rd @@ -4,8 +4,8 @@ \alias{CST_MultiEOF} \title{EOF analysis of multiple variables} \usage{ -CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, minvar = 0.6, - lon_lim = NULL, lat_lim = NULL) +CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, + minvar = 0.6, lon_lim = NULL, lat_lim = NULL) } \arguments{ \item{datalist}{A list of objects of the class 's2dv_cube', containing the variables to be analysed. @@ -69,4 +69,3 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } - diff --git a/man/CST_MultiMetric.Rd b/man/CST_MultiMetric.Rd index 079a5588..8e3ce593 100644 --- a/man/CST_MultiMetric.Rd +++ b/man/CST_MultiMetric.Rd @@ -37,15 +37,14 @@ c(ano_exp, ano_obs) \%<-\% CST_Anomaly(exp = exp, obs = obs, cross = TRUE, memb a <- CST_MultiMetric(exp = ano_exp, obs = ano_obs) str(a) } -\author{ -Mishra Niti, \email{niti.mishra@bsc.es} - -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} \references{ Mishra, N., Prodhomme, C., & Guemas, V. (n.d.). Multi-Model Skill Assessment of Seasonal Temperature and Precipitation Forecasts over Europe, 29-31.\url{http://link.springer.com/10.1007/s00382-018-4404-z} } \seealso{ \code{\link[s2dverification]{Corr}}, \code{\link[s2dverification]{RMS}}, \code{\link[s2dverification]{RMSSS}} and \code{\link{CST_Load}} } +\author{ +Mishra Niti, \email{niti.mishra@bsc.es} +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_MultivarRMSE.Rd b/man/CST_MultivarRMSE.Rd index 685eaf77..24af608c 100644 --- a/man/CST_MultivarRMSE.Rd +++ b/man/CST_MultivarRMSE.Rd @@ -56,10 +56,9 @@ weight <- c(1, 2) a <- CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, weight = weight) str(a) } -\author{ -Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} -} \seealso{ \code{\link[s2dverification]{RMS}} and \code{\link{CST_Load}} } - +\author{ +Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} +} diff --git a/man/CST_QuantileMapping.Rd b/man/CST_QuantileMapping.Rd index 1c93843e..90319622 100644 --- a/man/CST_QuantileMapping.Rd +++ b/man/CST_QuantileMapping.Rd @@ -77,10 +77,9 @@ res <- CST_QuantileMapping(exp = exp, obs = obs, sample_dims = 'time', method = 'DIST') } } -\author{ -Nuria Perez-Zanon, \email{nuria.perez@bsc.es} -} \seealso{ \code{\link[qmap]{fitQmap}} and \code{\link[qmap]{doQmap}} } - +\author{ +Nuria Perez-Zanon, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_RFSlope.Rd b/man/CST_RFSlope.Rd index d2b5aec0..0c4e1671 100644 --- a/man/CST_RFSlope.Rd +++ b/man/CST_RFSlope.Rd @@ -50,4 +50,3 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/CST_RFWeights.Rd b/man/CST_RFWeights.Rd index 08a7b850..ef5ebe4d 100644 --- a/man/CST_RFWeights.Rd +++ b/man/CST_RFWeights.Rd @@ -47,9 +47,6 @@ nf <- 8 ww <- CST_RFWeights("./worldclim.nc", nf, lon, lat, fsmooth = TRUE) } } -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} -} \references{ Terzago, S., Palazzi, E., & von Hardenberg, J. (2018). Stochastic downscaling of precipitation in complex orography: @@ -57,4 +54,6 @@ A simple method to reproduce a realistic fine-scale climatology. Natural Hazards and Earth System Sciences, 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 . } - +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} diff --git a/man/CST_RainFARM.Rd b/man/CST_RainFARM.Rd index 4a667f9a..0ed45f49 100644 --- a/man/CST_RainFARM.Rd +++ b/man/CST_RainFARM.Rd @@ -95,13 +95,12 @@ dim(res$data) # dataset member realization sdate ftime lat lon # 1 2 3 3 4 64 64 -} -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } \references{ Terzago, S. et al. (2018). NHESS 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 ; D'Onofrio et al. (2014), J of Hydrometeorology 15, 830-843; Rebora et. al. (2006), JHM 7, 724. } - +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} diff --git a/man/CST_SaveExp.Rd b/man/CST_SaveExp.Rd index 17537205..0e49c119 100644 --- a/man/CST_SaveExp.Rd +++ b/man/CST_SaveExp.Rd @@ -29,11 +29,10 @@ destination <- "./path/" CST_SaveExp(data = data, destination = destination) } -} -\author{ -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} } \seealso{ \code{\link{CST_Load}}, \code{\link{as.s2dv_cube}} and \code{\link{s2dv_cube}} } - +\author{ +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_SplitDim.Rd b/man/CST_SplitDim.Rd index 2019ea7b..8ce20c97 100644 --- a/man/CST_SplitDim.Rd +++ b/man/CST_SplitDim.Rd @@ -4,7 +4,8 @@ \alias{CST_SplitDim} \title{Function to Split Dimension} \usage{ -CST_SplitDim(data, split_dim = "time", indices = NULL, freq = "monthly") +CST_SplitDim(data, split_dim = "time", indices = NULL, + freq = "monthly") } \arguments{ \item{data}{a 's2dv_cube' object} @@ -43,4 +44,3 @@ dim(new_data$data) \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/EnsClustering.Rd b/man/EnsClustering.Rd index 27aca453..d7284ef5 100644 --- a/man/EnsClustering.Rd +++ b/man/EnsClustering.Rd @@ -67,4 +67,3 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/MultiEOF.Rd b/man/MultiEOF.Rd index 1e822fc4..c38116de 100644 --- a/man/MultiEOF.Rd +++ b/man/MultiEOF.Rd @@ -46,4 +46,3 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } - diff --git a/man/PlotCombinedMap.Rd b/man/PlotCombinedMap.Rd index 6857c64d..62e26904 100644 --- a/man/PlotCombinedMap.Rd +++ b/man/PlotCombinedMap.Rd @@ -5,10 +5,10 @@ \title{Plot Multiple Lon-Lat Variables In a Single Map According to a Decision Function} \usage{ PlotCombinedMap(maps, lon, lat, map_select_fun, display_range, - map_dim = "map", brks = NULL, cols = NULL, col_unknown_map = "white", - mask = NULL, col_mask = "grey", bar_titles = NULL, legend_scale = 1, - fileout = NULL, width = 8, height = 5, size_units = "in", res = 100, - ...) + map_dim = "map", brks = NULL, cols = NULL, + col_unknown_map = "white", mask = NULL, col_mask = "grey", + bar_titles = NULL, legend_scale = 1, fileout = NULL, width = 8, + height = 5, size_units = "in", res = 100, ...) } \arguments{ \item{maps}{List of matrices to plot, each with (longitude, latitude) dimensions, or 3-dimensional array with the dimensions (longitude, latitude, map). Dimension names are required.} @@ -67,12 +67,11 @@ PlotCombinedMap(list(a, b, c), lons, lats, bar_titles = paste('\% of belonging to', c('a', 'b', 'c')), brks = 20, width = 10, height = 8) } +\seealso{ +\code{PlotCombinedMap} and \code{PlotEquiMap} +} \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} Veronica Torralba, \email{veronica.torralba@bsc.es} } -\seealso{ -\code{PlotCombinedMap} and \code{PlotEquiMap} -} - diff --git a/man/PlotForecastPDF.Rd b/man/PlotForecastPDF.Rd index bed0bd31..c1959ee8 100644 --- a/man/PlotForecastPDF.Rd +++ b/man/PlotForecastPDF.Rd @@ -4,10 +4,11 @@ \alias{PlotForecastPDF} \title{Plot one or multiple ensemble forecast pdfs for the same event} \usage{ -PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, - plotfile = NULL, title = "Set a title", var.name = "Varname (units)", - fcst.names = NULL, add.ensmemb = c("above", "below", "no"), - color.set = c("ggplot", "s2s4e", "hydro")) +PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, + obs = NULL, plotfile = NULL, title = "Set a title", + var.name = "Varname (units)", fcst.names = NULL, + add.ensmemb = c("above", "below", "no"), color.set = c("ggplot", + "s2s4e", "hydro")) } \arguments{ \item{fcst}{a dataframe or array containing all the ensember members for each frecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members.} @@ -49,4 +50,3 @@ PlotForecastPDF(fcsts2, c(-0.66, 0.66), extreme.limits = c(-1.2, 1.2), \author{ Llorenç Lledó \email{llledo@bsc.es} } -\encoding{UTF-8} diff --git a/man/PlotMostLikelyQuantileMap.Rd b/man/PlotMostLikelyQuantileMap.Rd index 6c92850e..0d984ede 100644 --- a/man/PlotMostLikelyQuantileMap.Rd +++ b/man/PlotMostLikelyQuantileMap.Rd @@ -109,11 +109,10 @@ PlotMostLikelyQuantileMap(bins, lons, lats, mask = 1 - (w1 + w2 / max(c(w1, w2))), brks = 20, width = 10, height = 8) -} -\author{ -Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} } \seealso{ \code{PlotCombinedMap} and \code{PlotEquiMap} } - +\author{ +Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} +} diff --git a/man/RFSlope.Rd b/man/RFSlope.Rd index 09a24ff5..5308ef8c 100644 --- a/man/RFSlope.Rd +++ b/man/RFSlope.Rd @@ -60,4 +60,3 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/RainFARM.Rd b/man/RainFARM.Rd index 984dcd42..e0fa9a10 100644 --- a/man/RainFARM.Rd +++ b/man/RainFARM.Rd @@ -4,10 +4,10 @@ \alias{RainFARM} \title{RainFARM stochastic precipitation downscaling (reduced version)} \usage{ -RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, kmin = 1, - fglob = FALSE, fsmooth = TRUE, nprocs = 1, time_dim = NULL, - lon_dim = "lon", lat_dim = "lat", drop_realization_dim = FALSE, - verbose = FALSE) +RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, + kmin = 1, fglob = FALSE, fsmooth = TRUE, nprocs = 1, + time_dim = NULL, lon_dim = "lon", lat_dim = "lat", + drop_realization_dim = FALSE, verbose = FALSE) } \arguments{ \item{data}{Precipitation array to downscale. @@ -117,4 +117,3 @@ dim(res$data) \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/SplitDim.Rd b/man/SplitDim.Rd index e36aa8a5..f07e4756 100644 --- a/man/SplitDim.Rd +++ b/man/SplitDim.Rd @@ -35,4 +35,3 @@ new_data <- SplitDim(data, indices = time, freq = 'year') \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/areave_data.Rd b/man/areave_data.Rd index cc79c85c..a772220a 100644 --- a/man/areave_data.Rd +++ b/man/areave_data.Rd @@ -41,4 +41,3 @@ areave_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} - diff --git a/man/as.s2dv_cube.Rd b/man/as.s2dv_cube.Rd index 13a2a296..c2b8f3a8 100644 --- a/man/as.s2dv_cube.Rd +++ b/man/as.s2dv_cube.Rd @@ -40,12 +40,11 @@ data <- as.s2dv_cube(data) class(data) } } +\seealso{ +\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} +} \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Nicolau Manubens, \email{nicolau.manubens@bsc.es} } -\seealso{ -\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} -} - diff --git a/man/lonlat_data.Rd b/man/lonlat_data.Rd index eca7abac..0c6ee30f 100644 --- a/man/lonlat_data.Rd +++ b/man/lonlat_data.Rd @@ -41,4 +41,3 @@ lonlat_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} - diff --git a/man/lonlat_prec.Rd b/man/lonlat_prec.Rd index 69cb94e8..345e3cab 100644 --- a/man/lonlat_prec.Rd +++ b/man/lonlat_prec.Rd @@ -29,4 +29,3 @@ lonlat_prec <- CST_Load('prlr', exp = list(infile), obs = NULL, Jost von Hardenberg \email{j.vonhardenberg@isac.cnr.it} } \keyword{data} - diff --git a/man/s2dv_cube.Rd b/man/s2dv_cube.Rd index 48af7bbb..f57d5ed3 100644 --- a/man/s2dv_cube.Rd +++ b/man/s2dv_cube.Rd @@ -75,10 +75,9 @@ exp8 <- s2dv_cube(data = exp_original, lon = seq(-10, 10, 5), lat = c(45, 50), end = paste0(rep("31", 10), rep("01", 10), 1990:1999))) class(exp8) } -\author{ -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} \seealso{ \code{\link[s2dverification]{Load}} and \code{\link{CST_Load}} } - +\author{ +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} -- GitLab From f245d5d46b6021413ce0e47b7fee160a19cbf091 Mon Sep 17 00:00:00 2001 From: Eroteida Sanchez Garcia Date: Fri, 17 Jan 2020 08:38:32 +0000 Subject: [PATCH 20/34] Fixing title in the vignette's figure BestEstimateIndex_fig2.png --- vignettes/Figures/BestEstimateIndex_fig2.png | Bin 43513 -> 45558 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/vignettes/Figures/BestEstimateIndex_fig2.png b/vignettes/Figures/BestEstimateIndex_fig2.png index e10333a577d1a2cba98d4efa702af3f6e8c14bab..24dbceb26d63f9c71765efd849130f0302780e04 100644 GIT binary patch literal 45558 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

Kx*%oL9QobCtI0pTKe#K?WRw2Hl?@iH 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℞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 KPj*JSG~rK)kV)zQ -- GitLab From 4bd71da50b3968335c807c7070c21c597d55d51d Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Mon, 20 Jan 2020 12:13:30 +0100 Subject: [PATCH 21/34] error message has been changed --- R/PlotForecastPDF.R | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index ac6fb366..5514dce3 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -93,8 +93,8 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check observations #------------------------ - if (!is.vector(obs) | !is.numeric(obs) ){ - stop("Observations is not a vector nor a numeric value") + if (is.array(obs)){ + stop("Observations can not be an array.") } else { if (is.vector(obs) & length(obs) != 1 ) { if (length(obs) != length(fcst)) { @@ -107,7 +107,8 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ if (is.vector(tercile.limits)) { if (length(tercile.limits) != 2) { - stop("Provide 2 tercile limits") + stop("Parameter 'tercile.limits' should be an array with two limits for delimiting extreme categories") + # stop("Provide 2 tercile limits") } tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) } else if (is.array(tercile.limits)) { @@ -134,7 +135,8 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N if (!is.null(extreme.limits)) { if (is.vector(extreme.limits)) { if (length(extreme.limits) != 2) { - stop("Provide 2 extreme limits") + stop("Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") + #stop("Provide 2 extreme limits") } extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) } else if (is.array(extreme.limits)) { -- GitLab From 08b1c532b7af46ce62fbfff656aab638ba18c8c1 Mon Sep 17 00:00:00 2001 From: Bert Van schaeybroeck Date: Fri, 24 Jan 2020 12:28:34 +0100 Subject: [PATCH 22/34] 1) Introduction of ncores as extra parameter. 2) Introduction of Calibration as a new function (replacement of .calibration.wrap). 3) removal of var.fc --- R/CST_Calibration.R | 108 ++++++++++++++++++++++++++++------------- man/CST_Calibration.Rd | 29 +++++------ man/Calibration.Rd | 48 ++++++++++++++++++ 3 files changed, 132 insertions(+), 53 deletions(-) create mode 100644 man/Calibration.Rd diff --git a/R/CST_Calibration.R b/R/CST_Calibration.R index efc7eeaa..59aff385 100644 --- a/R/CST_Calibration.R +++ b/R/CST_Calibration.R @@ -2,11 +2,7 @@ #' #'@author Verónica Torralba, \email{veronica.torralba@bsc.es} #'@author Bert Van Schaeybroeck, \email{bertvs@meteo.be} -#'@description Four types of member-by-member bias correction can be performed. The \code{bias} method corrects the bias only, the \code{evmos} method applies a variance inflation technique to ensure the correction of the bias and the correspondence of variance between forecast and observation (Van Schaeybroeck and Vannitsem, 2011). The ensemble calibration methods \code{"mse_min"} and \code{"crps_min"} correct the bias, the overall forecast variance and the ensemble spread as described in Doblas-Reyes et al. (2005) and Van Schaeybroeck and Vannitsem (2015), respectively. While the \code{"mse_min"} method minimizes a constrained mean-squared error using three parameters, the \code{"crps_min"} method features four parameters and minimizes the Continuous Ranked Probability Score (CRPS). -#'@description Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. -#'@references Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x -#'@references Van Schaeybroeck, B., & Vannitsem, S. (2011). Post-processing through linear regression. Nonlinear Processes in Geophysics, 18(2), 147. doi:10.5194/npg-18-147-2011 -#'@references Van Schaeybroeck, B., & Vannitsem, S. (2015). Ensemble post-processing using member-by-member approaches: theoretical aspects. Quarterly Journal of the Royal Meteorological Society, 141(688), 807-818. doi:10.1002/qj.2397 +#'@description Equivalent to function \code{Calibration} but for objects of class \code{s2dv_cube}. #' #'@param exp an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the seasonal forecast experiment data in the element named \code{$data}. #'@param obs an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the observed data in the element named \code{$data}. @@ -14,16 +10,16 @@ #'@param eval.method is the sampling method used, can be either \code{in-sample} or \code{leave-one-out}. Default value is the \code{leave-one-out} cross validation. #'@param multi.model is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result. #'@param na.fill is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned. -#'@return an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions of the experimental data. +#'@param ncores is an integer that indicates the number of cores for parallel computations using multiApply function. +#'@return an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions as the one in the exp object. #' #'@import s2dverification #'@import abind #' #'@seealso \code{\link{CST_Load}} #' -#'# Example -#'# Creation of sample s2dverification objects. These are not complete -#'# s2dverification objects though. The Load function returns complete objects. +#'@examples +#'# Example 1: #'mod1 <- 1 : (1 * 3 * 4 * 5 * 6 * 7) #'dim(mod1) <- c(dataset = 1, member = 3, sdate = 4, ftime = 5, lat = 6, lon = 7) #'obs1 <- 1 : (1 * 1 * 4 * 5 * 6 * 7) @@ -38,8 +34,12 @@ #'str(a) #'@export -CST_Calibration <- function(exp, obs, cal.method = "mse_min", - eval.method = "leave-one-out", multi.model = F, na.fill = T) { +CST_Calibration <- function(exp, obs, + cal.method = "mse_min", + eval.method = "leave-one-out", + multi.model = F, + na.fill = T, + ncores = NULL) { if (!inherits(exp, "s2dv_cube") || !inherits(obs, "s2dv_cube")) { stop("Parameter 'exp' and 'obs' must be of the class 's2dv_cube', ", "as output by CSTools::CST_Load.") @@ -53,9 +53,12 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", if(!missing(multi.model) & !(cal.method == "mse_min")){ warning(paste0("The multi.model parameter is ignored when using the calibration method ", cal.method)) } - exp$data <- .calibration.wrap(exp = exp$data, obs = obs$data, - cal.method = cal.method, eval.method = eval.method, - multi.model = multi.model, na.fill = na.fill) + exp$data <- Calibration(exp = exp$data, obs = obs$data, + cal.method = cal.method, + eval.method = eval.method, + multi.model = multi.model, + na.fill = na.fill, + ncores = ncores) exp$Datasets <- c(exp$Datasets, obs$Datasets) exp$source_files <- c(exp$source_files, obs$source_files) @@ -63,15 +66,39 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", } -.data.set.sufficiently.large <- function(mod, obs){ - amt.min.samples <- 3 - amt.good.pts <- sum(!is.na(obs) & !apply(mod, c(2), function(x) all(is.na(x)))) - return(amt.good.pts > amt.min.samples) -} -.calibration.wrap <- function(exp, obs, cal.method, - eval.method, multi.model, na.fill) { +#'Forecast Calibration +#' +#'@author Verónica Torralba, \email{veronica.torralba@bsc.es} +#'@author Bert Van Schaeybroeck, \email{bertvs@meteo.be} +#'@description Four types of member-by-member bias correction can be performed. The \code{bias} method corrects the bias only, the \code{evmos} method applies a variance inflation technique to ensure the correction of the bias and the correspondence of variance between forecast and observation (Van Schaeybroeck and Vannitsem, 2011). The ensemble calibration methods \code{"mse_min"} and \code{"crps_min"} correct the bias, the overall forecast variance and the ensemble spread as described in Doblas-Reyes et al. (2005) and Van Schaeybroeck and Vannitsem (2015), respectively. While the \code{"mse_min"} method minimizes a constrained mean-squared error using three parameters, the \code{"crps_min"} method features four parameters and minimizes the Continuous Ranked Probability Score (CRPS). +#'@description Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. +#'@references Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x +#'@references Van Schaeybroeck, B., & Vannitsem, S. (2011). Post-processing through linear regression. Nonlinear Processes in Geophysics, 18(2), 147. doi:10.5194/npg-18-147-2011 +#'@references Van Schaeybroeck, B., & Vannitsem, S. (2015). Ensemble post-processing using member-by-member approaches: theoretical aspects. Quarterly Journal of the Royal Meteorological Society, 141(688), 807-818. doi:10.1002/qj.2397 +#' +#'@param exp an array containing the seasonal forecast experiment data. +#'@param obs an array containing the observed data. +#'@param cal.method is the calibration method used, can be either \code{bias}, \code{evmos}, \code{mse_min} or \code{crps_min}. Default value is \code{mse_min}. +#'@param eval.method is the sampling method used, can be either \code{in-sample} or \code{leave-one-out}. Default value is the \code{leave-one-out} cross validation. +#'@param multi.model is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result. +#'@param na.fill is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned. +#'@param ncores is an integer that indicates the number of cores for parallel computations using multiApply function. +#'@return an array containing the calibrated forecasts with the same dimensions as the \code{exp} array. +#' +#'@import s2dverification +#'@import abind +#' +#'@seealso \code{\link{CST_Load}} +#' + +Calibration <- function(exp, obs, + cal.method = "mse_min", + eval.method = "leave-one-out", + multi.model = F, + na.fill = T, + ncores = NULL) { dim.exp <- dim(exp) amt.dims.exp <- length(dim.exp) @@ -103,10 +130,14 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", stop("Parameter 'obs' must have a member dimension with length=1") } + ncores.to.use <- ifelse(is.null(ncores), 1, ncores) + obs <- Subset(obs, along = "member", indices = 1, drop = "selected") - data.set.sufficiently.large.out <- Apply(data = list(mod = exp, obs = obs), - target_dims = list(mod = target.dim.names.exp, obs = target.dim.names.obs), + data.set.sufficiently.large.out <- + Apply(data = list(exp = exp, obs = obs), + target_dims = list(exp = target.dim.names.exp, obs = target.dim.names.obs), + ncores = ncores.to.use, fun = .data.set.sufficiently.large)$output1 if(!all(data.set.sufficiently.large.out)){ @@ -117,12 +148,13 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", } } - calibrated <- Apply(data = list(mod = exp, obs = obs), + calibrated <- Apply(data = list(exp = exp, obs = obs), cal.method = cal.method, eval.method = eval.method, multi.model = multi.model, na.fill = na.fill, - target_dims = list(mod = target.dim.names.exp, obs = target.dim.names.obs), + target_dims = list(exp = target.dim.names.exp, obs = target.dim.names.obs), + ncores = ncores.to.use, fun = .cal)$output1 dexes <- match(names(dim(exp)), names(dim(calibrated))) @@ -133,6 +165,13 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", return(calibrated) } + +.data.set.sufficiently.large <- function(exp, obs){ + amt.min.samples <- 3 + amt.good.pts <- sum(!is.na(obs) & !apply(exp, c(2), function(x) all(is.na(x)))) + return(amt.good.pts > amt.min.samples) +} + .make.eval.train.dexes <- function(eval.method, amt.points){ if(eval.method == "leave-one-out"){ dexes.lst <- lapply(seq(1, amt.points), function(x) return(list(eval.dexes = x, train.dexes = seq(1, amt.points)[-x]))) @@ -144,21 +183,20 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", return(dexes.lst) } -.cal <- function(mod, obs, cal.method, eval.method, multi.model, na.fill) { +.cal <- function(exp, obs, cal.method, eval.method, multi.model, na.fill) { - var.obs <- as.vector(obs) - var.fc <- mod - dims.fc <- dim(var.fc) + obs <- as.vector(obs) + dims.fc <- dim(exp) amt.mbr <- dims.fc[1] amt.sdate <- dims.fc[2] - var.cor.fc <- NA * var.fc + var.cor.fc <- NA * exp names(dim(var.cor.fc)) <- c("member", "sdate") - if(!.data.set.sufficiently.large(mod = mod, obs = obs)){ + if(!.data.set.sufficiently.large(exp = exp, obs = obs)){ if(na.fill){ return(var.cor.fc) } else { - var.cor.fc[] <- var.fc[] + var.cor.fc[] <- exp[] return(var.cor.fc) } } @@ -170,9 +208,9 @@ CST_Calibration <- function(exp, obs, cal.method = "mse_min", eval.dexes <- eval.train.dexeses[[i.sample]]$eval.dexes train.dexes <- eval.train.dexeses[[i.sample]]$train.dexes - fc.ev <- var.fc[ , eval.dexes, drop = FALSE] - fc.tr <- var.fc[ , train.dexes] - obs.tr <- var.obs[train.dexes , drop = FALSE] + fc.ev <- exp[ , eval.dexes, drop = FALSE] + fc.tr <- exp[ , train.dexes] + obs.tr <- obs[train.dexes , drop = FALSE] if(cal.method == "bias"){ var.cor.fc[ , eval.dexes] <- fc.ev + mean(obs.tr, na.rm = TRUE) - mean(fc.tr, na.rm = TRUE) diff --git a/man/CST_Calibration.Rd b/man/CST_Calibration.Rd index 48d0a4e1..9fa594b6 100644 --- a/man/CST_Calibration.Rd +++ b/man/CST_Calibration.Rd @@ -5,7 +5,8 @@ \title{Forecast Calibration} \usage{ CST_Calibration(exp, obs, cal.method = "mse_min", - eval.method = "leave-one-out", multi.model = F, na.fill = T) + eval.method = "leave-one-out", multi.model = F, na.fill = T, + ncores = NULL) } \arguments{ \item{exp}{an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the seasonal forecast experiment data in the element named \code{$data}.} @@ -19,28 +20,17 @@ CST_Calibration(exp, obs, cal.method = "mse_min", \item{multi.model}{is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result.} \item{na.fill}{is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned.} + +\item{ncores}{is an integer that indicates the number of cores for parallel computations using multiApply function.} } \value{ -an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions of the experimental data. +an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions of the exp data. } \description{ -Four types of member-by-member bias correction can be performed. The \code{bias} method corrects the bias only, the \code{evmos} method applies a variance inflation technique to ensure the correction of the bias and the correspondence of variance between forecast and observation (Van Schaeybroeck and Vannitsem, 2011). The ensemble calibration methods \code{"mse_min"} and \code{"crps_min"} correct the bias, the overall forecast variance and the ensemble spread as described in Doblas-Reyes et al. (2005) and Van Schaeybroeck and Vannitsem (2015), respectively. While the \code{"mse_min"} method minimizes a constrained mean-squared error using three parameters, the \code{"crps_min"} method features four parameters and minimizes the Continuous Ranked Probability Score (CRPS). - -Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. -} -\references{ -Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x - -Van Schaeybroeck, B., & Vannitsem, S. (2011). Post-processing through linear regression. Nonlinear Processes in Geophysics, 18(2), 147. doi:10.5194/npg-18-147-2011 - -Van Schaeybroeck, B., & Vannitsem, S. (2015). Ensemble post-processing using member-by-member approaches: theoretical aspects. Quarterly Journal of the Royal Meteorological Society, 141(688), 807-818. doi:10.1002/qj.2397 +Equivalent to function \code{Calibration} but for objects of class \code{s2dv_cube}. } -\seealso{ -\code{\link{CST_Load}} - -# Example -# Creation of sample s2dverification objects. These are not complete -# s2dverification objects though. The Load function returns complete objects. +\examples{ +# Example 1: mod1 <- 1 : (1 * 3 * 4 * 5 * 6 * 7) dim(mod1) <- c(dataset = 1, member = 3, sdate = 4, ftime = 5, lat = 6, lon = 7) obs1 <- 1 : (1 * 1 * 4 * 5 * 6 * 7) @@ -54,6 +44,9 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_Calibration(exp = exp, obs = obs, cal.method = "mse_min", eval.method = "in-sample") str(a) } +\seealso{ +\code{\link{CST_Load}} +} \author{ Verónica Torralba, \email{veronica.torralba@bsc.es} diff --git a/man/Calibration.Rd b/man/Calibration.Rd new file mode 100644 index 00000000..2f7ddeac --- /dev/null +++ b/man/Calibration.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/CST_Calibration.R +\name{Calibration} +\alias{Calibration} +\title{Forecast Calibration} +\usage{ +Calibration(exp, obs, cal.method = "mse_min", + eval.method = "leave-one-out", multi.model = F, na.fill = T, + ncores = NULL) +} +\arguments{ +\item{exp}{an array containing the seasonal forecast experiment data in the element named \code{$data}.} + +\item{obs}{an array containing the observed data in the element named \code{$data}.} + +\item{cal.method}{is the calibration method used, can be either \code{bias}, \code{evmos}, \code{mse_min} or \code{crps_min}. Default value is \code{mse_min}.} + +\item{eval.method}{is the sampling method used, can be either \code{in-sample} or \code{leave-one-out}. Default value is the \code{leave-one-out} cross validation.} + +\item{multi.model}{is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result.} + +\item{na.fill}{is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned.} + +\item{ncores}{is an integer that indicates the number of cores for parallel computations using multiApply function.} +} +\value{ +an array containing the calibrated forecasts with the same dimensions of the exp data. +} +\description{ +Four types of member-by-member bias correction can be performed. The \code{bias} method corrects the bias only, the \code{evmos} method applies a variance inflation technique to ensure the correction of the bias and the correspondence of variance between forecast and observation (Van Schaeybroeck and Vannitsem, 2011). The ensemble calibration methods \code{"mse_min"} and \code{"crps_min"} correct the bias, the overall forecast variance and the ensemble spread as described in Doblas-Reyes et al. (2005) and Van Schaeybroeck and Vannitsem (2015), respectively. While the \code{"mse_min"} method minimizes a constrained mean-squared error using three parameters, the \code{"crps_min"} method features four parameters and minimizes the Continuous Ranked Probability Score (CRPS). + +Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. +} +\references{ +Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x + +Van Schaeybroeck, B., & Vannitsem, S. (2011). Post-processing through linear regression. Nonlinear Processes in Geophysics, 18(2), 147. doi:10.5194/npg-18-147-2011 + +Van Schaeybroeck, B., & Vannitsem, S. (2015). Ensemble post-processing using member-by-member approaches: theoretical aspects. Quarterly Journal of the Royal Meteorological Society, 141(688), 807-818. doi:10.1002/qj.2397 +} +\seealso{ +\code{\link{CST_Load}} +} +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} + +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} -- GitLab From d3996e4535b9e3a83e91bce0cf52cad23ecaab17 Mon Sep 17 00:00:00 2001 From: Bert Van schaeybroeck Date: Fri, 24 Jan 2020 12:51:29 +0100 Subject: [PATCH 23/34] Additional change: 4)introduce BFGS method for the crps_min method --- NAMESPACE | 1 + R/CST_Calibration.R | 40 +++++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index e7d7c003..ce1737bc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ export(CST_Anomaly) export(CST_BEI_Weighting) export(CST_BiasCorrection) export(CST_Calibration) +export(Calibration) export(CST_CategoricalEnsCombination) export(CST_EnsClustering) export(CST_Load) diff --git a/R/CST_Calibration.R b/R/CST_Calibration.R index 59aff385..a7f1924b 100644 --- a/R/CST_Calibration.R +++ b/R/CST_Calibration.R @@ -10,7 +10,7 @@ #'@param eval.method is the sampling method used, can be either \code{in-sample} or \code{leave-one-out}. Default value is the \code{leave-one-out} cross validation. #'@param multi.model is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result. #'@param na.fill is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned. -#'@param ncores is an integer that indicates the number of cores for parallel computations using multiApply function. +#'@param ncores is an integer that indicates the number of cores for parallel computations using multiApply function. The default value is one. #'@return an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions as the one in the exp object. #' #'@import s2dverification @@ -39,7 +39,7 @@ CST_Calibration <- function(exp, obs, eval.method = "leave-one-out", multi.model = F, na.fill = T, - ncores = NULL) { + ncores = 1) { if (!inherits(exp, "s2dv_cube") || !inherits(obs, "s2dv_cube")) { stop("Parameter 'exp' and 'obs' must be of the class 's2dv_cube', ", "as output by CSTools::CST_Load.") @@ -84,7 +84,7 @@ CST_Calibration <- function(exp, obs, #'@param eval.method is the sampling method used, can be either \code{in-sample} or \code{leave-one-out}. Default value is the \code{leave-one-out} cross validation. #'@param multi.model is a boolean that is used only for the \code{mse_min} method. If multi-model ensembles or ensembles of different sizes are used, it must be set to \code{TRUE}. By default it is \code{FALSE}. Differences between the two approaches are generally small but may become large when using small ensemble sizes. Using multi.model when the calibration method is \code{bias}, \code{evmos} or \code{crps_min} will not affect the result. #'@param na.fill is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned. -#'@param ncores is an integer that indicates the number of cores for parallel computations using multiApply function. +#'@param ncores is an integer that indicates the number of cores for parallel computations using multiApply function. The default value is one. #'@return an array containing the calibrated forecasts with the same dimensions as the \code{exp} array. #' #'@import s2dverification @@ -98,7 +98,7 @@ Calibration <- function(exp, obs, eval.method = "leave-one-out", multi.model = F, na.fill = T, - ncores = NULL) { + ncores = 1) { dim.exp <- dim(exp) amt.dims.exp <- length(dim.exp) @@ -129,15 +129,13 @@ Calibration <- function(exp, obs, if (dim(obs)['member']!=1){ stop("Parameter 'obs' must have a member dimension with length=1") } - - ncores.to.use <- ifelse(is.null(ncores), 1, ncores) - + obs <- Subset(obs, along = "member", indices = 1, drop = "selected") data.set.sufficiently.large.out <- Apply(data = list(exp = exp, obs = obs), target_dims = list(exp = target.dim.names.exp, obs = target.dim.names.obs), - ncores = ncores.to.use, + ncores = ncores, fun = .data.set.sufficiently.large)$output1 if(!all(data.set.sufficiently.large.out)){ @@ -154,7 +152,7 @@ Calibration <- function(exp, obs, multi.model = multi.model, na.fill = na.fill, target_dims = list(exp = target.dim.names.exp, obs = target.dim.names.obs), - ncores = ncores.to.use, + ncores = ncores, fun = .cal)$output1 dexes <- match(names(dim(exp)), names(dim(calibrated))) @@ -235,8 +233,11 @@ Calibration <- function(exp, obs, init.par <- c(.calc.mse.min.par(quant.obs.fc.tr), 0.001) init.par[3] <- sqrt(init.par[3]) #calculate regression parameters on training dataset - optim.tmp <- optim(par = init.par, fn = .calc.crps.opt, - quant.obs.fc = quant.obs.fc.tr, method = "Nelder-Mead") + optim.tmp <- optim(par = init.par, + fn = .calc.crps.opt, + gr = .calc.crps.grad.opt, + quant.obs.fc = quant.obs.fc.tr, + method = "BFGS") mbm.par <- optim.tmp$par #correct evaluation subset @@ -363,6 +364,23 @@ Calibration <- function(exp, obs, ) } +.calc.crps.grad.opt <- function(par, quant.obs.fc){ + sgn1 <- with(quant.obs.fc,sign(obs.per.ens - + (par[1] + par[2] * fc.ens.av.per.ens + + ((par[3])^2 + par[4] / spr.abs.per.ens) * fc.dev))) + sgn2 <- with(quant.obs.fc, sign((par[3])^2 + par[4] / spr.abs.per.ens)) + sgn3 <- with(quant.obs.fc,sign((par[3])^2 * spr.abs + par[4])) + deriv.par1 <- mean(sgn1, na.rm = TRUE) + deriv.par2 <- with(quant.obs.fc, mean(sgn1 * fc.dev, na.rm = TRUE)) + deriv.par3 <- with(quant.obs.fc, + mean(2* par[3] * sgn1 * sgn2 * fc.ens.av.per.ens, na.rm = TRUE) - + mean(spr.abs * sgn3, na.rm = TRUE) / 2.) + deriv.par4 <- with(quant.obs.fc, + mean(sgn1 * sgn2 * fc.ens.av.per.ens / spr.abs.per.ens, na.rm = TRUE) - + mean(sgn3, na.rm = TRUE) / 2.) + return(c(deriv.par1, deriv.par2, deriv.par3, deriv.par4)) +} + #Below are the core or elementary functions to correct the evaluation set based on the regression parameters .correct.evmos.fc <- function(fc, par){ quant.fc.mp <- .calc.fc.quant(fc = fc) -- GitLab From 117eaa0f062e97ad5c92dd89bde7fb7da02b62da Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Tue, 28 Jan 2020 16:15:19 +0100 Subject: [PATCH 24/34] changed testthat error messages for PlotForecastPDF --- R/PlotForecastPDF.R | 8 +++----- tests/testthat/test-PlotForecastPDF.R | 6 +++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 5514dce3..07781b2f 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -107,8 +107,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ if (is.vector(tercile.limits)) { if (length(tercile.limits) != 2) { - stop("Parameter 'tercile.limits' should be an array with two limits for delimiting extreme categories") - # stop("Provide 2 tercile limits") + stop("Provide two tercile limits") } tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) } else if (is.array(tercile.limits)) { @@ -134,9 +133,8 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ if (!is.null(extreme.limits)) { if (is.vector(extreme.limits)) { - if (length(extreme.limits) != 2) { - stop("Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") - #stop("Provide 2 extreme limits") + if (length(extreme.limits) != 2) { + stop("Provide two extreme limits") } extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) } else if (is.array(extreme.limits)) { diff --git a/tests/testthat/test-PlotForecastPDF.R b/tests/testthat/test-PlotForecastPDF.R index dfc35c4d..f9926324 100644 --- a/tests/testthat/test-PlotForecastPDF.R +++ b/tests/testthat/test-PlotForecastPDF.R @@ -2,13 +2,13 @@ context("Generic tests") test_that("Sanity checks", { expect_error( PlotForecastPDF(fcst, tercile.limits), - "object 'tercile.limits' not found") + "object 'fcst' not found") expect_error( PlotForecastPDF(fcst, tercile.limits = c(0.25, 0.55)), "object 'fcst' not found") expect_error( PlotForecastPDF(fcst, tercile.limits = 10), - "Parameter 'tercile.limits' should be an array with two limits for delimiting tercile categories") + "object 'fcst' not found") expect_error( PlotForecastPDF(fcst, tercile.limits = c(10, 20)), "object 'fcst' not found") @@ -18,5 +18,5 @@ test_that("Sanity checks", { "object 'tercile.limits' not found") expect_error( PlotForecastPDF(fcst = fcsts2, tercile.limits = c(-0.5, 0.5), extreme.limits = NA), - "Parameter 'extreme.limits' should be an array with two limits for delimiting extreme categories") + "Provide two extreme limits") }) -- GitLab From 57d0a7a9105bf05dd98389d11d4fcdf1f4f94659 Mon Sep 17 00:00:00 2001 From: froura Date: Tue, 28 Jan 2020 16:22:33 +0100 Subject: [PATCH 25/34] Prova RMD vs MD --- vignettes/{MultivarRMSE_vignette.Rmd => MultivarRMSE_vignette.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vignettes/{MultivarRMSE_vignette.Rmd => MultivarRMSE_vignette.md} (100%) diff --git a/vignettes/MultivarRMSE_vignette.Rmd b/vignettes/MultivarRMSE_vignette.md similarity index 100% rename from vignettes/MultivarRMSE_vignette.Rmd rename to vignettes/MultivarRMSE_vignette.md -- GitLab From 512c198d89134eaa726c381fd50812086ea4d1cb Mon Sep 17 00:00:00 2001 From: froura Date: Tue, 28 Jan 2020 16:24:10 +0100 Subject: [PATCH 26/34] Desfer prova chungui --- vignettes/{MultivarRMSE_vignette.md => MultivarRMSE_vignette.Rmd} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vignettes/{MultivarRMSE_vignette.md => MultivarRMSE_vignette.Rmd} (100%) diff --git a/vignettes/MultivarRMSE_vignette.md b/vignettes/MultivarRMSE_vignette.Rmd similarity index 100% rename from vignettes/MultivarRMSE_vignette.md rename to vignettes/MultivarRMSE_vignette.Rmd -- GitLab From 9ec5d7ceadac41fa414298afd2087f5555f9c4c7 Mon Sep 17 00:00:00 2001 From: FRANCESC ROURA ADSERIAS Date: Tue, 28 Jan 2020 17:32:01 +0100 Subject: [PATCH 27/34] Added a vignette with three examples --- vignettes/PlotForecastPDF.Rmd | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 vignettes/PlotForecastPDF.Rmd diff --git a/vignettes/PlotForecastPDF.Rmd b/vignettes/PlotForecastPDF.Rmd new file mode 100644 index 00000000..c6d89618 --- /dev/null +++ b/vignettes/PlotForecastPDF.Rmd @@ -0,0 +1,47 @@ +--- +author: "Francesc Roura and Llorenç Lledó" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteEngine{knitr::knitr} + %\VignetteIndexEntry{Plot Forecast PDFs} + %\usepackage[utf8]{inputenc} +--- + +Plot Forecast PDFs (Probability Distibution Functions) +------------------------------------------ + +Library *CSTools*, should be installed from CRAN and loaded: + + +```{r,warning=FALSE,message=FALSE,error=FALSE} +library(CSTools) +``` + +### 1.- A simple example + +The first step is to put your forecasts in an appropriate format. For this vignette we generate some random values from two normal distributions. The PlotForecastPDF by default will plot the ensemble members, the estimated density distributions and the tercile probabilities. + +```{r,fig.show = 'hide',warning=F} +fcst <- data.frame(fcst1=rnorm(mean=25,sd=3,n=30),fcst2=rnorm(mean=23,sd=4.5,n=30)) +PlotForecastPDF(fcst,tercile.limits=c(20,26)) +``` + +![Example 1](./Figures/PlotForecastPDF_ex1.png) + +### 2.- Some useful parameters +Changing the title, the forecast labels or the units will be needed in most cases. + +```{r,fig.show = 'hide',warning=F} +fcst <- data.frame(fcst1=rnorm(mean=25,sd=3,n=30),fcst2=rnorm(mean=23,sd=4.5,n=30)) +PlotForecastPDF(fcst,tercile.limits=c(20,26),var.name="Temperature (ºC)",title="Forecasts valid on 2019-01-01 at Sunny Hills",fcst.names = c("model a","model b")) +``` +![Example 2](./Figures/PlotForecastPDF_ex2.png) + +### 3.- Adding extremes and observed values +We can add the probability of extreme values and the observed values. The tercile and extreme limits can be specified for each panel separately, as well as the observed values. +```{r,fig.show = 'hide',warning=F} +fcst <- data.frame(fcst1=rnorm(mean=25,sd=3,n=30),fcst2=rnorm(mean=28,sd=4.5,n=30),fcst3=rnorm(mean=17,sd=3,n=30)) +PlotForecastPDF(fcst,tercile.limits=rbind(c(20,26),c(22,28),c(15,22)),var.name="Temperature (ºC)",title="Forecasts at Sunny Hills",fcst.names = c("January","February","March"),obs=c(21,24,17),extreme.limits = rbind(c(18,28),c(20,30),c(12,24))) +``` +![Example 3](./Figures/PlotForecastPDF_ex3.png) -- GitLab From cf29303d046399a760e16fe7b104041f52050180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lloren=C3=A7=20Lled=C3=B3?= Date: Fri, 31 Jan 2020 15:34:56 +0100 Subject: [PATCH 28/34] Fromatting and cleanining issues --- R/PlotForecastPDF.R | 69 +++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 07781b2f..78ea53c2 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -1,10 +1,10 @@ #'Plot one or multiple ensemble forecast pdfs for the same event #' #'@author Llorenç Lledó \email{llledo@bsc.es} -#'@description This function plots the probability distribution function of several ensemble forecasts for the same event, either initialized at different moments or by different models. Probabilities for tercile categories are computed, plotted in colors and annotated. An asterisk marks the tercile with higher probabilities. Probabilities for extreme categories (above P90 and below P10) can also be included as hatched areas. Individual ensemble members can be plotted as jittered points. The observed value is optionally shown as a diamond. +#'@description This function plots the probability distribution function of several ensemble forecasts. Separate panels are used to plot forecasts valid or initialized at different times or by different models or even at different locations. Probabilities for tercile categories are computed, plotted in colors and annotated. An asterisk marks the tercile with higher probabilities. Probabilities for extreme categories (above P90 and below P10) can also be included as hatched areas. Individual ensemble members can be plotted as jittered points. The observed value is optionally shown as a diamond. #' #'@param fcst a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members. -#'@param tercile.limits an array or vector with P33 and P66 values that define the tercile categories for each panel. Use an array of dimensions (nforecasts,2) to define different terciles for each forecast panel, or a vector with two elements to reuse the same tercile limits for all forecast panels. +#'@param tercile.limits an array or vector with P33 and P66 values that define the tercile categories for each panel. Use an array of dimensions (nforecasts,2) to define different terciles for each forecast panel, or a vector with two elements to reuse the same tercile limits for all forecast panels. #'@param extreme.limits (optional) an array or vector with P10 and P90 values that define the extreme categories for each panel. Use an array of (nforecasts,2) to define different extreme limits for each forecast panel, or a vector with two elements to reuse the same tercile limits for all forecast panels. (Default: extreme categories are not shown). #'@param obs (optional) A vector providing the observed values for each forecast panel or a single value that will be reused for all forecast panels. (Default: observation is not shown). #'@param plotfile (optional) a filename (pdf, png...) where the plot will be saved. (Default: the plot is not saved). @@ -23,6 +23,7 @@ #'@importFrom reshape2 melt #'@importFrom plyr . #'@importFrom plyr dlply +#'@importFrom s2dverification InsertDim #' #'@examples #'fcsts <- data.frame(fcst1 = rnorm(10), fcst2 = rnorm(10, 0.5, 1.2), @@ -42,11 +43,10 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N hues <- seq(15, 375, length = n + 1) hcl(h = hues, l = 65, c = 100)[1:n] } - #------------------------ # Define color sets #------------------------ - # color.set <- match.arg(color.set) + color.set <- match.arg(color.set) if (color.set == "s2s4e") { colorFill <- rev(c("#FF764D", "#b5b5b5", "#33BFD1")) colorHatch <- c("deepskyblue3", "indianred3") @@ -71,6 +71,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check input arguments #------------------------ + add.ensmemb <- match.arg(add.ensmemb) #------------------------ # Check fcst type and convert to data.frame if needed #------------------------ @@ -93,13 +94,11 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ # Check observations #------------------------ - if (is.array(obs)){ - stop("Observations can not be an array.") - } else { - if (is.vector(obs) & length(obs) != 1 ) { - if (length(obs) != length(fcst)) { - stop("The number of observations differ from the number of forecasts.") - } + if (!is.null(obs)) { + if (!is.vector(obs)){ + stop("Observations should be a vector") + } else if (!length(obs) %in% c(1, npanels)) { + stop("The number of observations should equal one or the number of forecasts") } } #------------------------ @@ -107,9 +106,9 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ if (is.vector(tercile.limits)) { if (length(tercile.limits) != 2) { - stop("Provide two tercile limits") + stop("Provide two tercile limits") } - tercile.limits <- s2dverification::InsertDim(tercile.limits,1,npanels) + tercile.limits <- InsertDim(tercile.limits, 1, npanels) } else if (is.array(tercile.limits)) { if (length(dim(tercile.limits)) == 2) { if (dim(tercile.limits)[2] != 2) { @@ -125,7 +124,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N stop("Tercile limits should be a vector of length two or an array of dimension (nfcsts,2)") } # check consistency of tercile limits - if (any(tercile.limits[,1]>=tercile.limits[,2])) { + if (any(tercile.limits[, 1] >= tercile.limits[, 2])) { stop("Inconsistent tercile limits") } #------------------------ @@ -133,10 +132,10 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N #------------------------ if (!is.null(extreme.limits)) { if (is.vector(extreme.limits)) { - if (length(extreme.limits) != 2) { - stop("Provide two extreme limits") + if (length(extreme.limits) != 2) { + stop("Provide two extreme limits") } - extreme.limits <- s2dverification::InsertDim(extreme.limits,1,npanels) + extreme.limits <- InsertDim(extreme.limits, 1, npanels) } else if (is.array(extreme.limits)) { if (length(dim(extreme.limits)) == 2) { if (dim(extreme.limits)[2] != 2) { @@ -152,10 +151,10 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N stop("Extreme limits should be a vector of length two or an array of dimensions (nfcsts,2)") } # Check that extreme limits are consistent with tercile limits - if (any(extreme.limits[,1]>=tercile.limits[,1])) { + if (any(extreme.limits[, 1] >= tercile.limits[, 1])) { stop("Inconsistent lower extreme limits") } - if (any(extreme.limits[,2]<=tercile.limits[,2])) { + if (any(extreme.limits[, 2] <= tercile.limits[, 2])) { stop("Inconsistent higher extreme limits") } } @@ -180,7 +179,6 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Gather the coordinates of the plots together with init and corresponding # terciles #------------------------ - tmp.df <- ggp$data[[1]][, c("x", "ymin", "ymax", "PANEL")] if (!is.null(ggp$layout$layout)) { tmp.df$init <- ggp$layout$layout$init[as.numeric(tmp.df$PANEL)] @@ -189,12 +187,9 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N } else { stop("Cannot find PANELS in ggp object") } - - tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile.limits[tmp.df$PANEL,1], - "Below normal", - ifelse(tmp.df$x < tercile.limits[tmp.df$PANEL,2],"Normal", "Above normal")), - levels = c("Below normal","Normal", "Above normal")) - + tmp.df$tercile <- factor(ifelse(tmp.df$x < tercile.limits[tmp.df$PANEL, 1], "Below normal", + ifelse(tmp.df$x < tercile.limits[tmp.df$PANEL, 2], "Normal", "Above normal")), levels = c("Below normal", + "Normal", "Above normal")) #------------------------ # Get the height and width of a panel #------------------------ @@ -205,11 +200,9 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N # Compute hatch coordinates for extremes #------------------------ if (!is.null(extreme.limits)) { - tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme.limits[tmp.df$PANEL,1], - "Below P10", - ifelse(tmp.df$x < extreme.limits[tmp.df$PANEL,2],"Normal", "Above P90")), - levels = c("Below P10","Normal", "Above P90")) - + tmp.df$extremes <- factor(ifelse(tmp.df$x < extreme.limits[tmp.df$PANEL, 1], "Below P10", + ifelse(tmp.df$x < extreme.limits[tmp.df$PANEL, 2], "Normal", "Above P90")), levels = c("Below P10", + "Normal", "Above P90")) hatch.ls <- dlply(tmp.df, .(init, extremes), function(x) { # close the polygon tmp.df2 <- data.frame(x = c(x$x, max(x$x), min(x$x)), y = c(x$ymax, 0, @@ -239,7 +232,6 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N } max.df <- do.call("rbind", max.ls) } - #------------------------ # Compute jitter space for ensemble members #------------------------ @@ -317,8 +309,7 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N pct <- merge(pct, tot, by = "init") pct$pct <- round(100 * pct$pct/pct$tot, 0) pct$MLT <- pct[, .(MLT = pct == max(pct)), by = init]$MLT - lab.pos <- c(tercile.limits[1,1], mean(tercile.limits[1,]), tercile.limits[1,2]) - + pct$lab.pos <- as.vector(apply(tercile.limits, 1, function(x) {c(min(x), mean(x), max(x))})) #------------------------ # Compute probability for extremes #------------------------ @@ -328,13 +319,12 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N tot2 <- pct2[, .(tot = sum(pct)), by = init] pct2 <- merge(pct2, tot2, by = "init") pct2$pct <- round(100 * pct2$pct/pct2$tot, 0) - lab.pos2 <- c(extreme.limits[1,1], NA, extreme.limits[1,2]) + pct2$lab.pos <- as.vector(apply(extreme.limits, 1, function(x) {c(x[1], NA, x[2])})) pct2 <- merge(pct2, max.df, by = c("init", "extremes")) # include potentially missing groups pct2 <- pct2[CJ(levels(pct2$init), factor(c("Below P10", "Normal", "Above P90"), levels = c("Below P10", "Normal", "Above P90"))), ] } - #------------------------ # Add probability labels for terciles #------------------------ @@ -345,16 +335,16 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N labpos <- 0 vjust <- -0.5 } - plot <- plot + geom_text(data = pct, aes(x = lab.pos[as.integer(tercile)], y = labpos, + plot <- plot + geom_text(data = pct, aes(x = lab.pos, y = labpos, label = paste0(pct, "%"), hjust = as.integer(tercile) * 1.5 - 2.5), vjust = vjust, - angle = -90, size = 3.2) + geom_text(data = pct[MLT == T, ], aes(x = lab.pos[as.integer(tercile)], + angle = -90, size = 3.2) + geom_text(data = pct[MLT == T, ], aes(x = lab.pos, y = labpos, label = "*", hjust = as.integer(tercile) * 3.5 - 5), vjust = 0.1, angle = -90, size = 7, color = "black") #------------------------ # Add probability labels for extremes #------------------------ if (!is.null(extreme.limits)) { - plot <- plot + geom_text(data = pct2[extremes != "Normal", ], aes(x = lab.pos2[as.integer(extremes)], + plot <- plot + geom_text(data = pct2[extremes != "Normal", ], aes(x = lab.pos, y = 0.9 * y, label = paste0(pct, "%"), hjust = as.integer(extremes) * 1.5 - 2.5), vjust = -0.5, angle = -90, size = 3.2, color = rep(colorLab, dim(fcst.df)[2])) @@ -502,4 +492,3 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = N } return(do.call("rbind", hatch.ls)) } - -- GitLab From dd1385fed7610c673b78aebe96bd0a2baf8038c9 Mon Sep 17 00:00:00 2001 From: nperez Date: Fri, 7 Feb 2020 16:40:20 +0100 Subject: [PATCH 29/34] removing empty lines for noRd to fix documentation --- DESCRIPTION | 2 +- NAMESPACE | 2 ++ R/CST_BEI_Weighting.R | 4 --- man/Analogs.Rd | 13 +++++---- man/BEI_PDFBest.Rd | 7 +++-- man/BEI_Weights.Rd | 7 +++-- man/CST_Analogs.Rd | 9 +++--- man/CST_Anomaly.Rd | 7 +++-- man/CST_BEI_Weighting.Rd | 11 ++++---- man/CST_BiasCorrection.Rd | 7 +++-- man/CST_Calibration.Rd | 9 +++--- man/CST_CategoricalEnsCombination.Rd | 7 +++-- man/CST_EnsClustering.Rd | 1 + man/CST_Load.Rd | 1 + man/CST_MergeDims.Rd | 41 ++++++++++++++++++++++++++++ man/CST_MultiEOF.Rd | 5 ++-- man/CST_MultiMetric.Rd | 9 +++--- man/CST_MultivarRMSE.Rd | 7 +++-- man/CST_QuantileMapping.Rd | 7 +++-- man/CST_RFSlope.Rd | 1 + man/CST_RFWeights.Rd | 7 +++-- man/CST_RainFARM.Rd | 7 +++-- man/CST_SaveExp.Rd | 7 +++-- man/CST_SplitDim.Rd | 4 +-- man/EnsClustering.Rd | 1 + man/MergeDims.Rd | 31 +++++++++++++++++++++ man/MultiEOF.Rd | 1 + man/PlotCombinedMap.Rd | 15 +++++----- man/PlotForecastPDF.Rd | 10 +++---- man/PlotMostLikelyQuantileMap.Rd | 7 +++-- man/RFSlope.Rd | 1 + man/RainFARM.Rd | 9 +++--- man/SplitDim.Rd | 1 + man/areave_data.Rd | 1 + man/as.s2dv_cube.Rd | 7 +++-- man/lonlat_data.Rd | 1 + man/lonlat_prec.Rd | 1 + man/s2dv_cube.Rd | 7 +++-- 38 files changed, 188 insertions(+), 87 deletions(-) create mode 100644 man/CST_MergeDims.Rd create mode 100644 man/MergeDims.Rd diff --git a/DESCRIPTION b/DESCRIPTION index c3de9d84..0e47736a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -70,4 +70,4 @@ VignetteBuilder: knitr License: Apache License 2.0 Encoding: UTF-8 LazyData: true -RoxygenNote: 6.1.1 +RoxygenNote: 5.0.0 diff --git a/NAMESPACE b/NAMESPACE index e7d7c003..bd5d0f16 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -11,6 +11,7 @@ export(CST_Calibration) export(CST_CategoricalEnsCombination) export(CST_EnsClustering) export(CST_Load) +export(CST_MergeDims) export(CST_MultiEOF) export(CST_MultiMetric) export(CST_MultivarRMSE) @@ -21,6 +22,7 @@ export(CST_RainFARM) export(CST_SaveExp) export(CST_SplitDim) export(EnsClustering) +export(MergeDims) export(MultiEOF) export(PlotCombinedMap) export(PlotForecastPDF) diff --git a/R/CST_BEI_Weighting.R b/R/CST_BEI_Weighting.R index 96265cdc..de747011 100644 --- a/R/CST_BEI_Weighting.R +++ b/R/CST_BEI_Weighting.R @@ -335,9 +335,6 @@ BEI_EMWeighting <- function(var_exp, aweights, time_dim_name = 'time') { #' # time tercil lat lon #' # 2 3 2 3 #' @noRd -#' -#' - BEI_ProbsWeighting <- function(var_exp, aweights, terciles, time_dim_name = 'time') { @@ -520,7 +517,6 @@ BEI_ProbsWeighting <- function(var_exp, aweights, terciles, #' # tercil lat lon #' # 2 2 3 #' @noRd -#' BEI_TercilesWeighting <- function(var_exp, aweights, time_dim_name = 'time') { if (!is.character(time_dim_name)) { diff --git a/man/Analogs.Rd b/man/Analogs.Rd index 52d9ff97..ee8a737e 100644 --- a/man/Analogs.Rd +++ b/man/Analogs.Rd @@ -5,8 +5,8 @@ \title{Analogs based on large scale fields.} \usage{ Analogs(expL, obsL, time_obsL, expVar = NULL, obsVar = NULL, - criteria = "Large_dist", lonVar = NULL, latVar = NULL, - region = NULL, nAnalogs = NULL, return_list = FALSE) + criteria = "Large_dist", lonVar = NULL, latVar = NULL, region = NULL, + nAnalogs = NULL, return_list = FALSE) } \arguments{ \item{expL}{an array of N named dimensions containing the experimental field @@ -377,6 +377,11 @@ Local_scalecor <- Analogs(expL=expSLP, str(Local_scalecor) Local_scalecor$AnalogsInfo +} +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} + +Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -384,8 +389,4 @@ and M. Vrac, 2013 : Ensemble reconstruction of the atmospheric column from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. \email{pascal.yiou@lsce.ipsl.fr} } -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} -Nuria Perez-Zanon \email{nuria.perez@bsc.es} -} diff --git a/man/BEI_PDFBest.Rd b/man/BEI_PDFBest.Rd index f120258d..f836ab72 100644 --- a/man/BEI_PDFBest.Rd +++ b/man/BEI_PDFBest.Rd @@ -113,11 +113,12 @@ dim(res) # time statistic season # 1 2 2 } +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} + diff --git a/man/BEI_Weights.Rd b/man/BEI_Weights.Rd index 867a4eb0..61db33af 100644 --- a/man/BEI_Weights.Rd +++ b/man/BEI_Weights.Rd @@ -43,12 +43,13 @@ dim(res) # sdate dataset member season # 10 3 5 1 +} +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} } \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} + diff --git a/man/CST_Analogs.Rd b/man/CST_Analogs.Rd index c9166de6..7c9a1e6f 100644 --- a/man/CST_Analogs.Rd +++ b/man/CST_Analogs.Rd @@ -81,6 +81,11 @@ adapted version of the method of Yiou et al 2013. \examples{ res <- CST_Analogs(expL = lonlat_data$exp, obsL = lonlat_data$obs) +} +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} + +Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -92,8 +97,4 @@ from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. code{\link{CST_Load}}, \code{\link[s2dverification]{Load}} and \code{\link[s2dverification]{CDORemap}} } -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} -Nuria Perez-Zanon \email{nuria.perez@bsc.es} -} diff --git a/man/CST_Anomaly.Rd b/man/CST_Anomaly.Rd index b214a31a..e1c31f0c 100644 --- a/man/CST_Anomaly.Rd +++ b/man/CST_Anomaly.Rd @@ -53,12 +53,13 @@ str(anom3) anom4 <- CST_Anomaly(exp = exp, obs = obs, cross = FALSE, memb = FALSE) str(anom4) -} -\seealso{ -\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} } \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Pena Jesus, \email{jesus.pena@bsc.es} } +\seealso{ +\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} +} + diff --git a/man/CST_BEI_Weighting.Rd b/man/CST_BEI_Weighting.Rd index 9c0f5a9d..0e60a356 100644 --- a/man/CST_BEI_Weighting.Rd +++ b/man/CST_BEI_Weighting.Rd @@ -4,8 +4,8 @@ \alias{CST_BEI_Weighting} \title{Weighting SFSs of a CSTools object.} \usage{ -CST_BEI_Weighting(var_exp, aweights, terciles = NULL, - type = "ensembleMean", time_dim_name = "time") +CST_BEI_Weighting(var_exp, aweights, terciles = NULL, type = "ensembleMean", + time_dim_name = "time") } \arguments{ \item{var_exp}{An object of the class 's2dv_cube' containing the variable @@ -68,11 +68,12 @@ dim(res_CST$data) # time lat lon dataset # 2 3 2 2 } +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} + diff --git a/man/CST_BiasCorrection.Rd b/man/CST_BiasCorrection.Rd index a1b415fb..e8a82af0 100644 --- a/man/CST_BiasCorrection.Rd +++ b/man/CST_BiasCorrection.Rd @@ -35,9 +35,10 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_BiasCorrection(exp = exp, obs = obs) str(a) } -\references{ -Torralba, V., F.J. Doblas-Reyes, D. MacLeod, I. Christel and M. Davis (2017). Seasonal climate prediction: a new source of information for the management of wind energy resources. Journal of Applied Meteorology and Climatology, 56, 1231-1247, doi:10.1175/JAMC-D-16-0204.1. (CLIM4ENERGY, EUPORIAS, NEWA, RESILIENCE, SPECS) -} \author{ Verónica Torralba, \email{veronica.torralba@bsc.es} } +\references{ +Torralba, V., F.J. Doblas-Reyes, D. MacLeod, I. Christel and M. Davis (2017). Seasonal climate prediction: a new source of information for the management of wind energy resources. Journal of Applied Meteorology and Climatology, 56, 1231-1247, doi:10.1175/JAMC-D-16-0204.1. (CLIM4ENERGY, EUPORIAS, NEWA, RESILIENCE, SPECS) +} + diff --git a/man/CST_Calibration.Rd b/man/CST_Calibration.Rd index 08d4a4ec..210c080f 100644 --- a/man/CST_Calibration.Rd +++ b/man/CST_Calibration.Rd @@ -26,6 +26,11 @@ Four types of member-by-member bias correction can be performed. The \code{bias} Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. } +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} + +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} \references{ Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x @@ -52,8 +57,4 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_Calibration(exp = exp, obs = obs, cal.method = "mse_min", eval.method = "in-sample") str(a) } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} diff --git a/man/CST_CategoricalEnsCombination.Rd b/man/CST_CategoricalEnsCombination.Rd index 7175b7fe..e551c3ec 100644 --- a/man/CST_CategoricalEnsCombination.Rd +++ b/man/CST_CategoricalEnsCombination.Rd @@ -83,6 +83,9 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_CategoricalEnsCombination(exp = exp, obs = obs, amt.cat = 3, cat.method = "mmw") } } +\author{ +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} \references{ Rajagopalan, B., Lall, U., & Zebiak, S. E. (2002). Categorical climate forecasts through regularization and optimal combination of multiple GCM ensembles. Monthly Weather Review, 130(7), 1792-1811. @@ -90,6 +93,4 @@ Robertson, A. W., Lall, U., Zebiak, S. E., & Goddard, L. (2004). Improved combin Van Schaeybroeck, B., & Vannitsem, S. (2019). Postprocessing of Long-Range Forecasts. In Statistical Postprocessing of Ensemble Forecasts (pp. 267-290). } -\author{ -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} + diff --git a/man/CST_EnsClustering.Rd b/man/CST_EnsClustering.Rd index de71d4e3..c13bf205 100644 --- a/man/CST_EnsClustering.Rd +++ b/man/CST_EnsClustering.Rd @@ -125,3 +125,4 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/CST_Load.Rd b/man/CST_Load.Rd index bf03ba42..1fee022c 100644 --- a/man/CST_Load.Rd +++ b/man/CST_Load.Rd @@ -47,3 +47,4 @@ obs <- CSTools::lonlat_data$obs \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} } + diff --git a/man/CST_MergeDims.Rd b/man/CST_MergeDims.Rd new file mode 100644 index 00000000..7ec6b18b --- /dev/null +++ b/man/CST_MergeDims.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/CST_MergeDims.R +\name{CST_MergeDims} +\alias{CST_MergeDims} +\title{Function to Merge Dimensions} +\usage{ +CST_MergeDims(data, merge_dims = c("ftime", "monthly"), rename_dim = NULL, + na.rm = FALSE) +} +\arguments{ +\item{data}{a 's2dv_cube' object} + +\item{merge_dims}{a character vector indicating the names of the dimensions to merge} + +\item{na.rm}{a logical indicating if the NA values should be removed or not.} + +\item{remane_dim}{a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used.} +} +\description{ +This function merges two dimensions of the array \code{data} in a 's2dv_cube' object into one. The user can select the dimensions to merge and provide the final name of the dimension. The user can select to remove NA values or keep them. +} +\examples{ + +data <- 1 : c(2 * 3 * 4 * 5 * 6 * 7) +dim(data) <- c(time = 7, lat = 2, lon = 3, monthly = 4, member = 6, + dataset = 5, var = 1) +data[2,,,,,,] <- NA +data[c(3,27)] <- NA +data <-list(data = data) +class(data) <- 's2dv_cube' +new_data <- CST_MergeDims(data, merge_dims = c('time', 'monthly')) +dim(new_data$data) +new_data <- CST_MergeDims(data, merge_dims = c('lon', 'lat'), rename_dim = 'grid') +dim(new_data$data) +new_data <- CST_MergeDims(data, merge_dims = c('time', 'monthly'), na.rm = TRUE) +dim(new_data$data) +} +\author{ +Nuria Perez-Zanon, \email{nuria.perez@bsc.es} +} + diff --git a/man/CST_MultiEOF.Rd b/man/CST_MultiEOF.Rd index 5fea8a50..fb584751 100644 --- a/man/CST_MultiEOF.Rd +++ b/man/CST_MultiEOF.Rd @@ -4,8 +4,8 @@ \alias{CST_MultiEOF} \title{EOF analysis of multiple variables} \usage{ -CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, - minvar = 0.6, lon_lim = NULL, lat_lim = NULL) +CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, minvar = 0.6, + lon_lim = NULL, lat_lim = NULL) } \arguments{ \item{datalist}{A list of objects of the class 's2dv_cube', containing the variables to be analysed. @@ -69,3 +69,4 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } + diff --git a/man/CST_MultiMetric.Rd b/man/CST_MultiMetric.Rd index 8e3ce593..079a5588 100644 --- a/man/CST_MultiMetric.Rd +++ b/man/CST_MultiMetric.Rd @@ -37,14 +37,15 @@ c(ano_exp, ano_obs) \%<-\% CST_Anomaly(exp = exp, obs = obs, cross = TRUE, memb a <- CST_MultiMetric(exp = ano_exp, obs = ano_obs) str(a) } +\author{ +Mishra Niti, \email{niti.mishra@bsc.es} + +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} \references{ Mishra, N., Prodhomme, C., & Guemas, V. (n.d.). Multi-Model Skill Assessment of Seasonal Temperature and Precipitation Forecasts over Europe, 29-31.\url{http://link.springer.com/10.1007/s00382-018-4404-z} } \seealso{ \code{\link[s2dverification]{Corr}}, \code{\link[s2dverification]{RMS}}, \code{\link[s2dverification]{RMSSS}} and \code{\link{CST_Load}} } -\author{ -Mishra Niti, \email{niti.mishra@bsc.es} -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} diff --git a/man/CST_MultivarRMSE.Rd b/man/CST_MultivarRMSE.Rd index 24af608c..685eaf77 100644 --- a/man/CST_MultivarRMSE.Rd +++ b/man/CST_MultivarRMSE.Rd @@ -56,9 +56,10 @@ weight <- c(1, 2) a <- CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, weight = weight) str(a) } -\seealso{ -\code{\link[s2dverification]{RMS}} and \code{\link{CST_Load}} -} \author{ Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} } +\seealso{ +\code{\link[s2dverification]{RMS}} and \code{\link{CST_Load}} +} + diff --git a/man/CST_QuantileMapping.Rd b/man/CST_QuantileMapping.Rd index 90319622..1c93843e 100644 --- a/man/CST_QuantileMapping.Rd +++ b/man/CST_QuantileMapping.Rd @@ -77,9 +77,10 @@ res <- CST_QuantileMapping(exp = exp, obs = obs, sample_dims = 'time', method = 'DIST') } } -\seealso{ -\code{\link[qmap]{fitQmap}} and \code{\link[qmap]{doQmap}} -} \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } +\seealso{ +\code{\link[qmap]{fitQmap}} and \code{\link[qmap]{doQmap}} +} + diff --git a/man/CST_RFSlope.Rd b/man/CST_RFSlope.Rd index 0c4e1671..d2b5aec0 100644 --- a/man/CST_RFSlope.Rd +++ b/man/CST_RFSlope.Rd @@ -50,3 +50,4 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/CST_RFWeights.Rd b/man/CST_RFWeights.Rd index ef5ebe4d..08a7b850 100644 --- a/man/CST_RFWeights.Rd +++ b/man/CST_RFWeights.Rd @@ -47,6 +47,9 @@ nf <- 8 ww <- CST_RFWeights("./worldclim.nc", nf, lon, lat, fsmooth = TRUE) } } +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} \references{ Terzago, S., Palazzi, E., & von Hardenberg, J. (2018). Stochastic downscaling of precipitation in complex orography: @@ -54,6 +57,4 @@ A simple method to reproduce a realistic fine-scale climatology. Natural Hazards and Earth System Sciences, 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 . } -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} -} + diff --git a/man/CST_RainFARM.Rd b/man/CST_RainFARM.Rd index 0ed45f49..4a667f9a 100644 --- a/man/CST_RainFARM.Rd +++ b/man/CST_RainFARM.Rd @@ -95,12 +95,13 @@ dim(res$data) # dataset member realization sdate ftime lat lon # 1 2 3 3 4 64 64 +} +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } \references{ Terzago, S. et al. (2018). NHESS 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 ; D'Onofrio et al. (2014), J of Hydrometeorology 15, 830-843; Rebora et. al. (2006), JHM 7, 724. } -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} -} + diff --git a/man/CST_SaveExp.Rd b/man/CST_SaveExp.Rd index 0e49c119..17537205 100644 --- a/man/CST_SaveExp.Rd +++ b/man/CST_SaveExp.Rd @@ -29,10 +29,11 @@ destination <- "./path/" CST_SaveExp(data = data, destination = destination) } -} -\seealso{ -\code{\link{CST_Load}}, \code{\link{as.s2dv_cube}} and \code{\link{s2dv_cube}} } \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} } +\seealso{ +\code{\link{CST_Load}}, \code{\link{as.s2dv_cube}} and \code{\link{s2dv_cube}} +} + diff --git a/man/CST_SplitDim.Rd b/man/CST_SplitDim.Rd index 8ce20c97..2019ea7b 100644 --- a/man/CST_SplitDim.Rd +++ b/man/CST_SplitDim.Rd @@ -4,8 +4,7 @@ \alias{CST_SplitDim} \title{Function to Split Dimension} \usage{ -CST_SplitDim(data, split_dim = "time", indices = NULL, - freq = "monthly") +CST_SplitDim(data, split_dim = "time", indices = NULL, freq = "monthly") } \arguments{ \item{data}{a 's2dv_cube' object} @@ -44,3 +43,4 @@ dim(new_data$data) \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } + diff --git a/man/EnsClustering.Rd b/man/EnsClustering.Rd index d7284ef5..27aca453 100644 --- a/man/EnsClustering.Rd +++ b/man/EnsClustering.Rd @@ -67,3 +67,4 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/MergeDims.Rd b/man/MergeDims.Rd new file mode 100644 index 00000000..67029e40 --- /dev/null +++ b/man/MergeDims.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/CST_MergeDims.R +\name{MergeDims} +\alias{MergeDims} +\title{Function to Split Dimension} +\usage{ +MergeDims(data, merge_dims = c("time", "monthly"), rename_dim = NULL, + na.rm = FALSE) +} +\arguments{ +\item{data}{an n-dimensional array with named dimensions} + +\item{merge_dims}{a character vector indicating the names of the dimensions to merge} + +\item{na.rm}{a logical indicating if the NA values should be removed or not.} + +\item{remane_dim}{a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used.} +} +\description{ +This function merges two dimensions of an array into one. The user can select the dimensions to merge and provide the final name of the dimension. The user can select to remove NA values or keep them. +} +\examples{ + +data <- 1 : 20 +dim(data) <- c(time = 10, lat = 2) +new_data <- MergeDims(data, merge_dims = c('time', 'lat')) +} +\author{ +Nuria Perez-Zanon, \email{nuria.perez@bsc.es} +} + diff --git a/man/MultiEOF.Rd b/man/MultiEOF.Rd index c38116de..1e822fc4 100644 --- a/man/MultiEOF.Rd +++ b/man/MultiEOF.Rd @@ -46,3 +46,4 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } + diff --git a/man/PlotCombinedMap.Rd b/man/PlotCombinedMap.Rd index 62e26904..6857c64d 100644 --- a/man/PlotCombinedMap.Rd +++ b/man/PlotCombinedMap.Rd @@ -5,10 +5,10 @@ \title{Plot Multiple Lon-Lat Variables In a Single Map According to a Decision Function} \usage{ PlotCombinedMap(maps, lon, lat, map_select_fun, display_range, - map_dim = "map", brks = NULL, cols = NULL, - col_unknown_map = "white", mask = NULL, col_mask = "grey", - bar_titles = NULL, legend_scale = 1, fileout = NULL, width = 8, - height = 5, size_units = "in", res = 100, ...) + map_dim = "map", brks = NULL, cols = NULL, col_unknown_map = "white", + mask = NULL, col_mask = "grey", bar_titles = NULL, legend_scale = 1, + fileout = NULL, width = 8, height = 5, size_units = "in", res = 100, + ...) } \arguments{ \item{maps}{List of matrices to plot, each with (longitude, latitude) dimensions, or 3-dimensional array with the dimensions (longitude, latitude, map). Dimension names are required.} @@ -67,11 +67,12 @@ PlotCombinedMap(list(a, b, c), lons, lats, bar_titles = paste('\% of belonging to', c('a', 'b', 'c')), brks = 20, width = 10, height = 8) } -\seealso{ -\code{PlotCombinedMap} and \code{PlotEquiMap} -} \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} Veronica Torralba, \email{veronica.torralba@bsc.es} } +\seealso{ +\code{PlotCombinedMap} and \code{PlotEquiMap} +} + diff --git a/man/PlotForecastPDF.Rd b/man/PlotForecastPDF.Rd index c1959ee8..3d1d65c3 100644 --- a/man/PlotForecastPDF.Rd +++ b/man/PlotForecastPDF.Rd @@ -4,11 +4,10 @@ \alias{PlotForecastPDF} \title{Plot one or multiple ensemble forecast pdfs for the same event} \usage{ -PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, - obs = NULL, plotfile = NULL, title = "Set a title", - var.name = "Varname (units)", fcst.names = NULL, - add.ensmemb = c("above", "below", "no"), color.set = c("ggplot", - "s2s4e", "hydro")) +PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, + plotfile = NULL, title = "Set a title", var.name = "Varname (units)", + fcst.names = NULL, add.ensmemb = c("above", "below", "no"), + color.set = c("ggplot", "s2s4e", "hydro")) } \arguments{ \item{fcst}{a dataframe or array containing all the ensember members for each frecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members.} @@ -50,3 +49,4 @@ PlotForecastPDF(fcsts2, c(-0.66, 0.66), extreme.limits = c(-1.2, 1.2), \author{ Llorenç Lledó \email{llledo@bsc.es} } + diff --git a/man/PlotMostLikelyQuantileMap.Rd b/man/PlotMostLikelyQuantileMap.Rd index 0d984ede..6c92850e 100644 --- a/man/PlotMostLikelyQuantileMap.Rd +++ b/man/PlotMostLikelyQuantileMap.Rd @@ -109,10 +109,11 @@ PlotMostLikelyQuantileMap(bins, lons, lats, mask = 1 - (w1 + w2 / max(c(w1, w2))), brks = 20, width = 10, height = 8) -} -\seealso{ -\code{PlotCombinedMap} and \code{PlotEquiMap} } \author{ Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} } +\seealso{ +\code{PlotCombinedMap} and \code{PlotEquiMap} +} + diff --git a/man/RFSlope.Rd b/man/RFSlope.Rd index 5308ef8c..09a24ff5 100644 --- a/man/RFSlope.Rd +++ b/man/RFSlope.Rd @@ -60,3 +60,4 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/RainFARM.Rd b/man/RainFARM.Rd index e0fa9a10..984dcd42 100644 --- a/man/RainFARM.Rd +++ b/man/RainFARM.Rd @@ -4,10 +4,10 @@ \alias{RainFARM} \title{RainFARM stochastic precipitation downscaling (reduced version)} \usage{ -RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, - kmin = 1, fglob = FALSE, fsmooth = TRUE, nprocs = 1, - time_dim = NULL, lon_dim = "lon", lat_dim = "lat", - drop_realization_dim = FALSE, verbose = FALSE) +RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, kmin = 1, + fglob = FALSE, fsmooth = TRUE, nprocs = 1, time_dim = NULL, + lon_dim = "lon", lat_dim = "lat", drop_realization_dim = FALSE, + verbose = FALSE) } \arguments{ \item{data}{Precipitation array to downscale. @@ -117,3 +117,4 @@ dim(res$data) \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/SplitDim.Rd b/man/SplitDim.Rd index f07e4756..e36aa8a5 100644 --- a/man/SplitDim.Rd +++ b/man/SplitDim.Rd @@ -35,3 +35,4 @@ new_data <- SplitDim(data, indices = time, freq = 'year') \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } + diff --git a/man/areave_data.Rd b/man/areave_data.Rd index a772220a..cc79c85c 100644 --- a/man/areave_data.Rd +++ b/man/areave_data.Rd @@ -41,3 +41,4 @@ areave_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} + diff --git a/man/as.s2dv_cube.Rd b/man/as.s2dv_cube.Rd index c2b8f3a8..13a2a296 100644 --- a/man/as.s2dv_cube.Rd +++ b/man/as.s2dv_cube.Rd @@ -40,11 +40,12 @@ data <- as.s2dv_cube(data) class(data) } } -\seealso{ -\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} -} \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Nicolau Manubens, \email{nicolau.manubens@bsc.es} } +\seealso{ +\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} +} + diff --git a/man/lonlat_data.Rd b/man/lonlat_data.Rd index 0c6ee30f..eca7abac 100644 --- a/man/lonlat_data.Rd +++ b/man/lonlat_data.Rd @@ -41,3 +41,4 @@ lonlat_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} + diff --git a/man/lonlat_prec.Rd b/man/lonlat_prec.Rd index 345e3cab..69cb94e8 100644 --- a/man/lonlat_prec.Rd +++ b/man/lonlat_prec.Rd @@ -29,3 +29,4 @@ lonlat_prec <- CST_Load('prlr', exp = list(infile), obs = NULL, Jost von Hardenberg \email{j.vonhardenberg@isac.cnr.it} } \keyword{data} + diff --git a/man/s2dv_cube.Rd b/man/s2dv_cube.Rd index f57d5ed3..48af7bbb 100644 --- a/man/s2dv_cube.Rd +++ b/man/s2dv_cube.Rd @@ -75,9 +75,10 @@ exp8 <- s2dv_cube(data = exp_original, lon = seq(-10, 10, 5), lat = c(45, 50), end = paste0(rep("31", 10), rep("01", 10), 1990:1999))) class(exp8) } -\seealso{ -\code{\link[s2dverification]{Load}} and \code{\link{CST_Load}} -} \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} } +\seealso{ +\code{\link[s2dverification]{Load}} and \code{\link{CST_Load}} +} + -- GitLab From 502482bb13048212341af62cc09c297e53b39605 Mon Sep 17 00:00:00 2001 From: nperez Date: Fri, 7 Feb 2020 16:58:33 +0100 Subject: [PATCH 30/34] Fix typo in parameter name MergeDims --- R/CST_MergeDims.R | 4 ++-- man/CST_MergeDims.Rd | 4 ++-- man/MergeDims.Rd | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/R/CST_MergeDims.R b/R/CST_MergeDims.R index 560f6c97..a9923c58 100644 --- a/R/CST_MergeDims.R +++ b/R/CST_MergeDims.R @@ -6,7 +6,7 @@ #' #'@param data a 's2dv_cube' object #'@param merge_dims a character vector indicating the names of the dimensions to merge -#'@param remane_dim a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used. +#'@param rename_dim a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used. #'@param na.rm a logical indicating if the NA values should be removed or not. #' #'@import abind @@ -45,7 +45,7 @@ CST_MergeDims <- function(data, merge_dims = c('ftime', 'monthly'), rename_dim = #' #'@param data an n-dimensional array with named dimensions #'@param merge_dims a character vector indicating the names of the dimensions to merge -#'@param remane_dim a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used. +#'@param rename_dim a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used. #'@param na.rm a logical indicating if the NA values should be removed or not. #' #'@import abind diff --git a/man/CST_MergeDims.Rd b/man/CST_MergeDims.Rd index 7ec6b18b..449e011e 100644 --- a/man/CST_MergeDims.Rd +++ b/man/CST_MergeDims.Rd @@ -12,9 +12,9 @@ CST_MergeDims(data, merge_dims = c("ftime", "monthly"), rename_dim = NULL, \item{merge_dims}{a character vector indicating the names of the dimensions to merge} -\item{na.rm}{a logical indicating if the NA values should be removed or not.} +\item{rename_dim}{a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used.} -\item{remane_dim}{a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used.} +\item{na.rm}{a logical indicating if the NA values should be removed or not.} } \description{ This function merges two dimensions of the array \code{data} in a 's2dv_cube' object into one. The user can select the dimensions to merge and provide the final name of the dimension. The user can select to remove NA values or keep them. diff --git a/man/MergeDims.Rd b/man/MergeDims.Rd index 67029e40..585049e8 100644 --- a/man/MergeDims.Rd +++ b/man/MergeDims.Rd @@ -12,9 +12,9 @@ MergeDims(data, merge_dims = c("time", "monthly"), rename_dim = NULL, \item{merge_dims}{a character vector indicating the names of the dimensions to merge} -\item{na.rm}{a logical indicating if the NA values should be removed or not.} +\item{rename_dim}{a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used.} -\item{remane_dim}{a character string indicating the name of the output dimension. If left at NULL, the first dimension name provided in parameter \code{merge_dims} will be used.} +\item{na.rm}{a logical indicating if the NA values should be removed or not.} } \description{ This function merges two dimensions of an array into one. The user can select the dimensions to merge and provide the final name of the dimension. The user can select to remove NA values or keep them. -- GitLab From 24a31d2d35497989c41e49dd9482ac7b5cf530ce Mon Sep 17 00:00:00 2001 From: nperez Date: Fri, 7 Feb 2020 18:05:21 +0100 Subject: [PATCH 31/34] defining global variables andfixing dependency declaration with s2dverification --- R/PlotForecastPDF.R | 5 +++-- man/PlotForecastPDF.Rd | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/R/PlotForecastPDF.R b/R/PlotForecastPDF.R index 78ea53c2..c40cc32c 100644 --- a/R/PlotForecastPDF.R +++ b/R/PlotForecastPDF.R @@ -23,7 +23,7 @@ #'@importFrom reshape2 melt #'@importFrom plyr . #'@importFrom plyr dlply -#'@importFrom s2dverification InsertDim +#'@import s2dverification #' #'@examples #'fcsts <- data.frame(fcst1 = rnorm(10), fcst2 = rnorm(10, 0.5, 1.2), @@ -38,7 +38,8 @@ PlotForecastPDF <- function(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, plotfile = NULL, title = "Set a title", var.name = "Varname (units)", fcst.names = NULL, add.ensmemb = c("above", "below", "no"), color.set = c("ggplot", "s2s4e", "hydro")) { - value <- init <- extremes <- x <- ymin <- ymax <- tercile <- y <- xend <- yend <- yjitter <- MLT <- NULL + value <- init <- extremes <- x <- ymin <- ymax <- tercile <- NULL + y <- xend <- yend <- yjitter <- MLT <- lab.pos <- NULL ggColorHue <- function(n) { hues <- seq(15, 375, length = n + 1) hcl(h = hues, l = 65, c = 100)[1:n] diff --git a/man/PlotForecastPDF.Rd b/man/PlotForecastPDF.Rd index 3d1d65c3..d7b95b08 100644 --- a/man/PlotForecastPDF.Rd +++ b/man/PlotForecastPDF.Rd @@ -10,13 +10,13 @@ PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, color.set = c("ggplot", "s2s4e", "hydro")) } \arguments{ -\item{fcst}{a dataframe or array containing all the ensember members for each frecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members.} +\item{fcst}{a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members.} -\item{tercile.limits}{an array with P33 and P66 values that define the tercile categories.} +\item{tercile.limits}{an array or vector with P33 and P66 values that define the tercile categories for each panel. Use an array of dimensions (nforecasts,2) to define different terciles for each forecast panel, or a vector with two elements to reuse the same tercile limits for all forecast panels.} -\item{extreme.limits}{(optional) an array with P10 and P90 values that define the extreme categories. (Default: extreme categories are not shown).} +\item{extreme.limits}{(optional) an array or vector with P10 and P90 values that define the extreme categories for each panel. Use an array of (nforecasts,2) to define different extreme limits for each forecast panel, or a vector with two elements to reuse the same tercile limits for all forecast panels. (Default: extreme categories are not shown).} -\item{obs}{(optional) a number with the observed value. (Default: observation is not shown).} +\item{obs}{(optional) A vector providing the observed values for each forecast panel or a single value that will be reused for all forecast panels. (Default: observation is not shown).} \item{plotfile}{(optional) a filename (pdf, png...) where the plot will be saved. (Default: the plot is not saved).} @@ -34,7 +34,7 @@ PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, a ggplot object containing the plot. } \description{ -This function plots the probability distribution function of several ensemble forecasts for the same event, either initialized at different moments or by different models. Probabilities for tercile categories are computed, plotted in colors and annotated. An asterisk marks the tercile with higher probabilities. Probabilities for extreme categories (above P90 and below P10) can also be included as hatched areas. Individual ensemble members can be plotted as jittered points. The observed value is optionally shown as a diamond. +This function plots the probability distribution function of several ensemble forecasts. Separate panels are used to plot forecasts valid or initialized at different times or by different models or even at different locations. Probabilities for tercile categories are computed, plotted in colors and annotated. An asterisk marks the tercile with higher probabilities. Probabilities for extreme categories (above P90 and below P10) can also be included as hatched areas. Individual ensemble members can be plotted as jittered points. The observed value is optionally shown as a diamond. } \examples{ fcsts <- data.frame(fcst1 = rnorm(10), fcst2 = rnorm(10, 0.5, 1.2), -- GitLab From 1c403ccfb3f3c9bf4abefde19da8329d4911b227 Mon Sep 17 00:00:00 2001 From: nperez Date: Fri, 7 Feb 2020 18:46:32 +0100 Subject: [PATCH 32/34] automatic documentation generated with devtools --- DESCRIPTION | 2 +- NAMESPACE | 1 - man/Analogs.Rd | 13 +++++++------ man/BEI_PDFBest.Rd | 7 ++++--- man/BEI_Weights.Rd | 7 ++++--- man/CST_Analogs.Rd | 9 +++++---- man/CST_Anomaly.Rd | 7 ++++--- man/CST_BEI_Weighting.Rd | 7 ++++--- man/CST_BiasCorrection.Rd | 7 ++++--- man/CST_Calibration.Rd | 13 +++++++------ man/CST_CategoricalEnsCombination.Rd | 7 ++++--- man/CST_EnsClustering.Rd | 1 + man/CST_Load.Rd | 1 + man/CST_MultiEOF.Rd | 5 +++-- man/CST_MultiMetric.Rd | 9 +++++---- man/CST_MultivarRMSE.Rd | 7 ++++--- man/CST_QuantileMapping.Rd | 7 ++++--- man/CST_RFSlope.Rd | 1 + man/CST_RFWeights.Rd | 7 ++++--- man/CST_RainFARM.Rd | 7 ++++--- man/CST_SaveExp.Rd | 7 ++++--- man/CST_SplitDim.Rd | 4 ++-- man/Calibration.Rd | 22 +++++++++++----------- man/EnsClustering.Rd | 1 + man/MultiEOF.Rd | 1 + man/PlotCombinedMap.Rd | 15 ++++++++------- man/PlotForecastPDF.Rd | 10 +++++----- man/PlotMostLikelyQuantileMap.Rd | 7 ++++--- man/RFSlope.Rd | 1 + man/RainFARM.Rd | 9 +++++---- man/SplitDim.Rd | 1 + man/areave_data.Rd | 1 + man/as.s2dv_cube.Rd | 7 ++++--- man/lonlat_data.Rd | 1 + man/lonlat_prec.Rd | 1 + man/s2dv_cube.Rd | 7 ++++--- 36 files changed, 125 insertions(+), 95 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index c3de9d84..0e47736a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -70,4 +70,4 @@ VignetteBuilder: knitr License: Apache License 2.0 Encoding: UTF-8 LazyData: true -RoxygenNote: 6.1.1 +RoxygenNote: 5.0.0 diff --git a/NAMESPACE b/NAMESPACE index 9c766759..bd5d0f16 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,7 +8,6 @@ export(CST_Anomaly) export(CST_BEI_Weighting) export(CST_BiasCorrection) export(CST_Calibration) -export(Calibration) export(CST_CategoricalEnsCombination) export(CST_EnsClustering) export(CST_Load) diff --git a/man/Analogs.Rd b/man/Analogs.Rd index 52d9ff97..ee8a737e 100644 --- a/man/Analogs.Rd +++ b/man/Analogs.Rd @@ -5,8 +5,8 @@ \title{Analogs based on large scale fields.} \usage{ Analogs(expL, obsL, time_obsL, expVar = NULL, obsVar = NULL, - criteria = "Large_dist", lonVar = NULL, latVar = NULL, - region = NULL, nAnalogs = NULL, return_list = FALSE) + criteria = "Large_dist", lonVar = NULL, latVar = NULL, region = NULL, + nAnalogs = NULL, return_list = FALSE) } \arguments{ \item{expL}{an array of N named dimensions containing the experimental field @@ -377,6 +377,11 @@ Local_scalecor <- Analogs(expL=expSLP, str(Local_scalecor) Local_scalecor$AnalogsInfo +} +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} + +Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -384,8 +389,4 @@ and M. Vrac, 2013 : Ensemble reconstruction of the atmospheric column from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. \email{pascal.yiou@lsce.ipsl.fr} } -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} -Nuria Perez-Zanon \email{nuria.perez@bsc.es} -} diff --git a/man/BEI_PDFBest.Rd b/man/BEI_PDFBest.Rd index f120258d..f836ab72 100644 --- a/man/BEI_PDFBest.Rd +++ b/man/BEI_PDFBest.Rd @@ -113,11 +113,12 @@ dim(res) # time statistic season # 1 2 2 } +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} + diff --git a/man/BEI_Weights.Rd b/man/BEI_Weights.Rd index 867a4eb0..61db33af 100644 --- a/man/BEI_Weights.Rd +++ b/man/BEI_Weights.Rd @@ -43,12 +43,13 @@ dim(res) # sdate dataset member season # 10 3 5 1 +} +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} } \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} + diff --git a/man/CST_Analogs.Rd b/man/CST_Analogs.Rd index c9166de6..7c9a1e6f 100644 --- a/man/CST_Analogs.Rd +++ b/man/CST_Analogs.Rd @@ -81,6 +81,11 @@ adapted version of the method of Yiou et al 2013. \examples{ res <- CST_Analogs(expL = lonlat_data$exp, obsL = lonlat_data$obs) +} +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} + +Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -92,8 +97,4 @@ from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. code{\link{CST_Load}}, \code{\link[s2dverification]{Load}} and \code{\link[s2dverification]{CDORemap}} } -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} -Nuria Perez-Zanon \email{nuria.perez@bsc.es} -} diff --git a/man/CST_Anomaly.Rd b/man/CST_Anomaly.Rd index b214a31a..e1c31f0c 100644 --- a/man/CST_Anomaly.Rd +++ b/man/CST_Anomaly.Rd @@ -53,12 +53,13 @@ str(anom3) anom4 <- CST_Anomaly(exp = exp, obs = obs, cross = FALSE, memb = FALSE) str(anom4) -} -\seealso{ -\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} } \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Pena Jesus, \email{jesus.pena@bsc.es} } +\seealso{ +\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} +} + diff --git a/man/CST_BEI_Weighting.Rd b/man/CST_BEI_Weighting.Rd index 8cb4522a..0e60a356 100644 --- a/man/CST_BEI_Weighting.Rd +++ b/man/CST_BEI_Weighting.Rd @@ -68,11 +68,12 @@ dim(res_CST$data) # time lat lon dataset # 2 3 2 2 } +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} + diff --git a/man/CST_BiasCorrection.Rd b/man/CST_BiasCorrection.Rd index a1b415fb..e8a82af0 100644 --- a/man/CST_BiasCorrection.Rd +++ b/man/CST_BiasCorrection.Rd @@ -35,9 +35,10 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_BiasCorrection(exp = exp, obs = obs) str(a) } -\references{ -Torralba, V., F.J. Doblas-Reyes, D. MacLeod, I. Christel and M. Davis (2017). Seasonal climate prediction: a new source of information for the management of wind energy resources. Journal of Applied Meteorology and Climatology, 56, 1231-1247, doi:10.1175/JAMC-D-16-0204.1. (CLIM4ENERGY, EUPORIAS, NEWA, RESILIENCE, SPECS) -} \author{ Verónica Torralba, \email{veronica.torralba@bsc.es} } +\references{ +Torralba, V., F.J. Doblas-Reyes, D. MacLeod, I. Christel and M. Davis (2017). Seasonal climate prediction: a new source of information for the management of wind energy resources. Journal of Applied Meteorology and Climatology, 56, 1231-1247, doi:10.1175/JAMC-D-16-0204.1. (CLIM4ENERGY, EUPORIAS, NEWA, RESILIENCE, SPECS) +} + diff --git a/man/CST_Calibration.Rd b/man/CST_Calibration.Rd index 9fa594b6..ed880aab 100644 --- a/man/CST_Calibration.Rd +++ b/man/CST_Calibration.Rd @@ -6,7 +6,7 @@ \usage{ CST_Calibration(exp, obs, cal.method = "mse_min", eval.method = "leave-one-out", multi.model = F, na.fill = T, - ncores = NULL) + ncores = 1) } \arguments{ \item{exp}{an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the seasonal forecast experiment data in the element named \code{$data}.} @@ -21,10 +21,10 @@ CST_Calibration(exp, obs, cal.method = "mse_min", \item{na.fill}{is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned.} -\item{ncores}{is an integer that indicates the number of cores for parallel computations using multiApply function.} +\item{ncores}{is an integer that indicates the number of cores for parallel computations using multiApply function. The default value is one.} } \value{ -an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions of the exp data. +an object of class \code{s2dv_cube} containing the calibrated forecasts in the element \code{$data} with the same dimensions as the one in the exp object. } \description{ Equivalent to function \code{Calibration} but for objects of class \code{s2dv_cube}. @@ -44,11 +44,12 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_Calibration(exp = exp, obs = obs, cal.method = "mse_min", eval.method = "in-sample") str(a) } -\seealso{ -\code{\link{CST_Load}} -} \author{ Verónica Torralba, \email{veronica.torralba@bsc.es} Bert Van Schaeybroeck, \email{bertvs@meteo.be} } +\seealso{ +\code{\link{CST_Load}} +} + diff --git a/man/CST_CategoricalEnsCombination.Rd b/man/CST_CategoricalEnsCombination.Rd index 7175b7fe..e551c3ec 100644 --- a/man/CST_CategoricalEnsCombination.Rd +++ b/man/CST_CategoricalEnsCombination.Rd @@ -83,6 +83,9 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_CategoricalEnsCombination(exp = exp, obs = obs, amt.cat = 3, cat.method = "mmw") } } +\author{ +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} \references{ Rajagopalan, B., Lall, U., & Zebiak, S. E. (2002). Categorical climate forecasts through regularization and optimal combination of multiple GCM ensembles. Monthly Weather Review, 130(7), 1792-1811. @@ -90,6 +93,4 @@ Robertson, A. W., Lall, U., Zebiak, S. E., & Goddard, L. (2004). Improved combin Van Schaeybroeck, B., & Vannitsem, S. (2019). Postprocessing of Long-Range Forecasts. In Statistical Postprocessing of Ensemble Forecasts (pp. 267-290). } -\author{ -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} + diff --git a/man/CST_EnsClustering.Rd b/man/CST_EnsClustering.Rd index de71d4e3..c13bf205 100644 --- a/man/CST_EnsClustering.Rd +++ b/man/CST_EnsClustering.Rd @@ -125,3 +125,4 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/CST_Load.Rd b/man/CST_Load.Rd index bf03ba42..1fee022c 100644 --- a/man/CST_Load.Rd +++ b/man/CST_Load.Rd @@ -47,3 +47,4 @@ obs <- CSTools::lonlat_data$obs \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} } + diff --git a/man/CST_MultiEOF.Rd b/man/CST_MultiEOF.Rd index 5fea8a50..fb584751 100644 --- a/man/CST_MultiEOF.Rd +++ b/man/CST_MultiEOF.Rd @@ -4,8 +4,8 @@ \alias{CST_MultiEOF} \title{EOF analysis of multiple variables} \usage{ -CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, - minvar = 0.6, lon_lim = NULL, lat_lim = NULL) +CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, minvar = 0.6, + lon_lim = NULL, lat_lim = NULL) } \arguments{ \item{datalist}{A list of objects of the class 's2dv_cube', containing the variables to be analysed. @@ -69,3 +69,4 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } + diff --git a/man/CST_MultiMetric.Rd b/man/CST_MultiMetric.Rd index 8e3ce593..079a5588 100644 --- a/man/CST_MultiMetric.Rd +++ b/man/CST_MultiMetric.Rd @@ -37,14 +37,15 @@ c(ano_exp, ano_obs) \%<-\% CST_Anomaly(exp = exp, obs = obs, cross = TRUE, memb a <- CST_MultiMetric(exp = ano_exp, obs = ano_obs) str(a) } +\author{ +Mishra Niti, \email{niti.mishra@bsc.es} + +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} \references{ Mishra, N., Prodhomme, C., & Guemas, V. (n.d.). Multi-Model Skill Assessment of Seasonal Temperature and Precipitation Forecasts over Europe, 29-31.\url{http://link.springer.com/10.1007/s00382-018-4404-z} } \seealso{ \code{\link[s2dverification]{Corr}}, \code{\link[s2dverification]{RMS}}, \code{\link[s2dverification]{RMSSS}} and \code{\link{CST_Load}} } -\author{ -Mishra Niti, \email{niti.mishra@bsc.es} -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} diff --git a/man/CST_MultivarRMSE.Rd b/man/CST_MultivarRMSE.Rd index 24af608c..685eaf77 100644 --- a/man/CST_MultivarRMSE.Rd +++ b/man/CST_MultivarRMSE.Rd @@ -56,9 +56,10 @@ weight <- c(1, 2) a <- CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, weight = weight) str(a) } -\seealso{ -\code{\link[s2dverification]{RMS}} and \code{\link{CST_Load}} -} \author{ Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} } +\seealso{ +\code{\link[s2dverification]{RMS}} and \code{\link{CST_Load}} +} + diff --git a/man/CST_QuantileMapping.Rd b/man/CST_QuantileMapping.Rd index 90319622..1c93843e 100644 --- a/man/CST_QuantileMapping.Rd +++ b/man/CST_QuantileMapping.Rd @@ -77,9 +77,10 @@ res <- CST_QuantileMapping(exp = exp, obs = obs, sample_dims = 'time', method = 'DIST') } } -\seealso{ -\code{\link[qmap]{fitQmap}} and \code{\link[qmap]{doQmap}} -} \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } +\seealso{ +\code{\link[qmap]{fitQmap}} and \code{\link[qmap]{doQmap}} +} + diff --git a/man/CST_RFSlope.Rd b/man/CST_RFSlope.Rd index 0c4e1671..d2b5aec0 100644 --- a/man/CST_RFSlope.Rd +++ b/man/CST_RFSlope.Rd @@ -50,3 +50,4 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/CST_RFWeights.Rd b/man/CST_RFWeights.Rd index ef5ebe4d..08a7b850 100644 --- a/man/CST_RFWeights.Rd +++ b/man/CST_RFWeights.Rd @@ -47,6 +47,9 @@ nf <- 8 ww <- CST_RFWeights("./worldclim.nc", nf, lon, lat, fsmooth = TRUE) } } +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} \references{ Terzago, S., Palazzi, E., & von Hardenberg, J. (2018). Stochastic downscaling of precipitation in complex orography: @@ -54,6 +57,4 @@ A simple method to reproduce a realistic fine-scale climatology. Natural Hazards and Earth System Sciences, 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 . } -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} -} + diff --git a/man/CST_RainFARM.Rd b/man/CST_RainFARM.Rd index 0ed45f49..4a667f9a 100644 --- a/man/CST_RainFARM.Rd +++ b/man/CST_RainFARM.Rd @@ -95,12 +95,13 @@ dim(res$data) # dataset member realization sdate ftime lat lon # 1 2 3 3 4 64 64 +} +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } \references{ Terzago, S. et al. (2018). NHESS 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 ; D'Onofrio et al. (2014), J of Hydrometeorology 15, 830-843; Rebora et. al. (2006), JHM 7, 724. } -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} -} + diff --git a/man/CST_SaveExp.Rd b/man/CST_SaveExp.Rd index 0e49c119..17537205 100644 --- a/man/CST_SaveExp.Rd +++ b/man/CST_SaveExp.Rd @@ -29,10 +29,11 @@ destination <- "./path/" CST_SaveExp(data = data, destination = destination) } -} -\seealso{ -\code{\link{CST_Load}}, \code{\link{as.s2dv_cube}} and \code{\link{s2dv_cube}} } \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} } +\seealso{ +\code{\link{CST_Load}}, \code{\link{as.s2dv_cube}} and \code{\link{s2dv_cube}} +} + diff --git a/man/CST_SplitDim.Rd b/man/CST_SplitDim.Rd index 8ce20c97..2019ea7b 100644 --- a/man/CST_SplitDim.Rd +++ b/man/CST_SplitDim.Rd @@ -4,8 +4,7 @@ \alias{CST_SplitDim} \title{Function to Split Dimension} \usage{ -CST_SplitDim(data, split_dim = "time", indices = NULL, - freq = "monthly") +CST_SplitDim(data, split_dim = "time", indices = NULL, freq = "monthly") } \arguments{ \item{data}{a 's2dv_cube' object} @@ -44,3 +43,4 @@ dim(new_data$data) \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } + diff --git a/man/Calibration.Rd b/man/Calibration.Rd index 2f7ddeac..4290abd7 100644 --- a/man/Calibration.Rd +++ b/man/Calibration.Rd @@ -4,14 +4,13 @@ \alias{Calibration} \title{Forecast Calibration} \usage{ -Calibration(exp, obs, cal.method = "mse_min", - eval.method = "leave-one-out", multi.model = F, na.fill = T, - ncores = NULL) +Calibration(exp, obs, cal.method = "mse_min", eval.method = "leave-one-out", + multi.model = F, na.fill = T, ncores = 1) } \arguments{ -\item{exp}{an array containing the seasonal forecast experiment data in the element named \code{$data}.} +\item{exp}{an array containing the seasonal forecast experiment data.} -\item{obs}{an array containing the observed data in the element named \code{$data}.} +\item{obs}{an array containing the observed data.} \item{cal.method}{is the calibration method used, can be either \code{bias}, \code{evmos}, \code{mse_min} or \code{crps_min}. Default value is \code{mse_min}.} @@ -21,16 +20,21 @@ Calibration(exp, obs, cal.method = "mse_min", \item{na.fill}{is a boolean that indicates what happens in case calibration is not possible or will yield unreliable results. This happens when three or less forecasts-observation pairs are available to perform the training phase of the calibration. By default \code{na.fill} is set to true such that NA values will be returned. If \code{na.fill} is set to false, the uncorrected data will be returned.} -\item{ncores}{is an integer that indicates the number of cores for parallel computations using multiApply function.} +\item{ncores}{is an integer that indicates the number of cores for parallel computations using multiApply function. The default value is one.} } \value{ -an array containing the calibrated forecasts with the same dimensions of the exp data. +an array containing the calibrated forecasts with the same dimensions as the \code{exp} array. } \description{ Four types of member-by-member bias correction can be performed. The \code{bias} method corrects the bias only, the \code{evmos} method applies a variance inflation technique to ensure the correction of the bias and the correspondence of variance between forecast and observation (Van Schaeybroeck and Vannitsem, 2011). The ensemble calibration methods \code{"mse_min"} and \code{"crps_min"} correct the bias, the overall forecast variance and the ensemble spread as described in Doblas-Reyes et al. (2005) and Van Schaeybroeck and Vannitsem (2015), respectively. While the \code{"mse_min"} method minimizes a constrained mean-squared error using three parameters, the \code{"crps_min"} method features four parameters and minimizes the Continuous Ranked Probability Score (CRPS). Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. } +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} + +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} \references{ Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x @@ -41,8 +45,4 @@ Van Schaeybroeck, B., & Vannitsem, S. (2015). Ensemble post-processing using mem \seealso{ \code{\link{CST_Load}} } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} diff --git a/man/EnsClustering.Rd b/man/EnsClustering.Rd index d7284ef5..27aca453 100644 --- a/man/EnsClustering.Rd +++ b/man/EnsClustering.Rd @@ -67,3 +67,4 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/MultiEOF.Rd b/man/MultiEOF.Rd index c38116de..1e822fc4 100644 --- a/man/MultiEOF.Rd +++ b/man/MultiEOF.Rd @@ -46,3 +46,4 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } + diff --git a/man/PlotCombinedMap.Rd b/man/PlotCombinedMap.Rd index 62e26904..6857c64d 100644 --- a/man/PlotCombinedMap.Rd +++ b/man/PlotCombinedMap.Rd @@ -5,10 +5,10 @@ \title{Plot Multiple Lon-Lat Variables In a Single Map According to a Decision Function} \usage{ PlotCombinedMap(maps, lon, lat, map_select_fun, display_range, - map_dim = "map", brks = NULL, cols = NULL, - col_unknown_map = "white", mask = NULL, col_mask = "grey", - bar_titles = NULL, legend_scale = 1, fileout = NULL, width = 8, - height = 5, size_units = "in", res = 100, ...) + map_dim = "map", brks = NULL, cols = NULL, col_unknown_map = "white", + mask = NULL, col_mask = "grey", bar_titles = NULL, legend_scale = 1, + fileout = NULL, width = 8, height = 5, size_units = "in", res = 100, + ...) } \arguments{ \item{maps}{List of matrices to plot, each with (longitude, latitude) dimensions, or 3-dimensional array with the dimensions (longitude, latitude, map). Dimension names are required.} @@ -67,11 +67,12 @@ PlotCombinedMap(list(a, b, c), lons, lats, bar_titles = paste('\% of belonging to', c('a', 'b', 'c')), brks = 20, width = 10, height = 8) } -\seealso{ -\code{PlotCombinedMap} and \code{PlotEquiMap} -} \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} Veronica Torralba, \email{veronica.torralba@bsc.es} } +\seealso{ +\code{PlotCombinedMap} and \code{PlotEquiMap} +} + diff --git a/man/PlotForecastPDF.Rd b/man/PlotForecastPDF.Rd index 3eee4e33..d7b95b08 100644 --- a/man/PlotForecastPDF.Rd +++ b/man/PlotForecastPDF.Rd @@ -4,11 +4,10 @@ \alias{PlotForecastPDF} \title{Plot one or multiple ensemble forecast pdfs for the same event} \usage{ -PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, - obs = NULL, plotfile = NULL, title = "Set a title", - var.name = "Varname (units)", fcst.names = NULL, - add.ensmemb = c("above", "below", "no"), color.set = c("ggplot", - "s2s4e", "hydro")) +PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, + plotfile = NULL, title = "Set a title", var.name = "Varname (units)", + fcst.names = NULL, add.ensmemb = c("above", "below", "no"), + color.set = c("ggplot", "s2s4e", "hydro")) } \arguments{ \item{fcst}{a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members.} @@ -50,3 +49,4 @@ PlotForecastPDF(fcsts2, c(-0.66, 0.66), extreme.limits = c(-1.2, 1.2), \author{ Llorenç Lledó \email{llledo@bsc.es} } + diff --git a/man/PlotMostLikelyQuantileMap.Rd b/man/PlotMostLikelyQuantileMap.Rd index 0d984ede..6c92850e 100644 --- a/man/PlotMostLikelyQuantileMap.Rd +++ b/man/PlotMostLikelyQuantileMap.Rd @@ -109,10 +109,11 @@ PlotMostLikelyQuantileMap(bins, lons, lats, mask = 1 - (w1 + w2 / max(c(w1, w2))), brks = 20, width = 10, height = 8) -} -\seealso{ -\code{PlotCombinedMap} and \code{PlotEquiMap} } \author{ Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} } +\seealso{ +\code{PlotCombinedMap} and \code{PlotEquiMap} +} + diff --git a/man/RFSlope.Rd b/man/RFSlope.Rd index 5308ef8c..09a24ff5 100644 --- a/man/RFSlope.Rd +++ b/man/RFSlope.Rd @@ -60,3 +60,4 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/RainFARM.Rd b/man/RainFARM.Rd index e0fa9a10..984dcd42 100644 --- a/man/RainFARM.Rd +++ b/man/RainFARM.Rd @@ -4,10 +4,10 @@ \alias{RainFARM} \title{RainFARM stochastic precipitation downscaling (reduced version)} \usage{ -RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, - kmin = 1, fglob = FALSE, fsmooth = TRUE, nprocs = 1, - time_dim = NULL, lon_dim = "lon", lat_dim = "lat", - drop_realization_dim = FALSE, verbose = FALSE) +RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, kmin = 1, + fglob = FALSE, fsmooth = TRUE, nprocs = 1, time_dim = NULL, + lon_dim = "lon", lat_dim = "lat", drop_realization_dim = FALSE, + verbose = FALSE) } \arguments{ \item{data}{Precipitation array to downscale. @@ -117,3 +117,4 @@ dim(res$data) \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } + diff --git a/man/SplitDim.Rd b/man/SplitDim.Rd index f07e4756..e36aa8a5 100644 --- a/man/SplitDim.Rd +++ b/man/SplitDim.Rd @@ -35,3 +35,4 @@ new_data <- SplitDim(data, indices = time, freq = 'year') \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } + diff --git a/man/areave_data.Rd b/man/areave_data.Rd index a772220a..cc79c85c 100644 --- a/man/areave_data.Rd +++ b/man/areave_data.Rd @@ -41,3 +41,4 @@ areave_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} + diff --git a/man/as.s2dv_cube.Rd b/man/as.s2dv_cube.Rd index c2b8f3a8..13a2a296 100644 --- a/man/as.s2dv_cube.Rd +++ b/man/as.s2dv_cube.Rd @@ -40,11 +40,12 @@ data <- as.s2dv_cube(data) class(data) } } -\seealso{ -\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} -} \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Nicolau Manubens, \email{nicolau.manubens@bsc.es} } +\seealso{ +\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} +} + diff --git a/man/lonlat_data.Rd b/man/lonlat_data.Rd index 0c6ee30f..eca7abac 100644 --- a/man/lonlat_data.Rd +++ b/man/lonlat_data.Rd @@ -41,3 +41,4 @@ lonlat_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} + diff --git a/man/lonlat_prec.Rd b/man/lonlat_prec.Rd index 345e3cab..69cb94e8 100644 --- a/man/lonlat_prec.Rd +++ b/man/lonlat_prec.Rd @@ -29,3 +29,4 @@ lonlat_prec <- CST_Load('prlr', exp = list(infile), obs = NULL, Jost von Hardenberg \email{j.vonhardenberg@isac.cnr.it} } \keyword{data} + diff --git a/man/s2dv_cube.Rd b/man/s2dv_cube.Rd index f57d5ed3..48af7bbb 100644 --- a/man/s2dv_cube.Rd +++ b/man/s2dv_cube.Rd @@ -75,9 +75,10 @@ exp8 <- s2dv_cube(data = exp_original, lon = seq(-10, 10, 5), lat = c(45, 50), end = paste0(rep("31", 10), rep("01", 10), 1990:1999))) class(exp8) } -\seealso{ -\code{\link[s2dverification]{Load}} and \code{\link{CST_Load}} -} \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} } +\seealso{ +\code{\link[s2dverification]{Load}} and \code{\link{CST_Load}} +} + -- GitLab From a96b04947a88dec2f831c688938d3ea12f3697ed Mon Sep 17 00:00:00 2001 From: nperez Date: Fri, 7 Feb 2020 19:13:33 +0100 Subject: [PATCH 33/34] update documentation to R 3.4.2 --- DESCRIPTION | 2 +- man/Analogs.Rd | 25 ++++++++++++++------- man/BEI_PDFBest.Rd | 20 +++++++++++------ man/BEI_Weights.Rd | 7 +++--- man/CST_Analogs.Rd | 20 +++++++++++------ man/CST_Anomaly.Rd | 10 ++++----- man/CST_BEI_Weighting.Rd | 16 +++++++++----- man/CST_BiasCorrection.Rd | 7 +++--- man/CST_Calibration.Rd | 19 ++++++++++------ man/CST_CategoricalEnsCombination.Rd | 17 +++++++++----- man/CST_EnsClustering.Rd | 17 +++++++++----- man/CST_Load.Rd | 1 - man/CST_MergeDims.Rd | 9 +++++--- man/CST_MultiEOF.Rd | 11 +++++++--- man/CST_MultiMetric.Rd | 9 ++++---- man/CST_MultivarRMSE.Rd | 7 +++--- man/CST_QuantileMapping.Rd | 20 +++++++++++------ man/CST_RFSlope.Rd | 1 - man/CST_RFWeights.Rd | 7 +++--- man/CST_RainFARM.Rd | 24 ++++++++++++++------ man/CST_SaveExp.Rd | 7 +++--- man/CST_SplitDim.Rd | 1 - man/Calibration.Rd | 20 +++++++++++------ man/EnsClustering.Rd | 19 +++++++++++----- man/MergeDims.Rd | 9 +++++--- man/MultiEOF.Rd | 17 ++++++++++---- man/PlotCombinedMap.Rd | 33 ++++++++++++++++++++-------- man/PlotForecastPDF.Rd | 17 +++++++++----- man/PlotMostLikelyQuantileMap.Rd | 18 ++++++++++----- man/RFSlope.Rd | 4 +--- man/RainFARM.Rd | 23 ++++++++++++++----- man/SplitDim.Rd | 1 - man/areave_data.Rd | 1 - man/as.s2dv_cube.Rd | 7 +++--- man/lonlat_data.Rd | 1 - man/lonlat_prec.Rd | 1 - man/s2dv_cube.Rd | 19 +++++++++++----- 37 files changed, 285 insertions(+), 162 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index cf5d323e..ccc1d5a9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -70,4 +70,4 @@ VignetteBuilder: knitr License: Apache License 2.0 Encoding: UTF-8 LazyData: true -RoxygenNote: 5.0.0 +RoxygenNote: 7.0.2 diff --git a/man/Analogs.Rd b/man/Analogs.Rd index ee8a737e..06107c07 100644 --- a/man/Analogs.Rd +++ b/man/Analogs.Rd @@ -4,9 +4,19 @@ \alias{Analogs} \title{Analogs based on large scale fields.} \usage{ -Analogs(expL, obsL, time_obsL, expVar = NULL, obsVar = NULL, - criteria = "Large_dist", lonVar = NULL, latVar = NULL, region = NULL, - nAnalogs = NULL, return_list = FALSE) +Analogs( + expL, + obsL, + time_obsL, + expVar = NULL, + obsVar = NULL, + criteria = "Large_dist", + lonVar = NULL, + latVar = NULL, + region = NULL, + nAnalogs = NULL, + return_list = FALSE +) } \arguments{ \item{expL}{an array of N named dimensions containing the experimental field @@ -377,11 +387,6 @@ Local_scalecor <- Analogs(expL=expSLP, str(Local_scalecor) Local_scalecor$AnalogsInfo -} -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} - -Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -389,4 +394,8 @@ and M. Vrac, 2013 : Ensemble reconstruction of the atmospheric column from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. \email{pascal.yiou@lsce.ipsl.fr} } +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} +Nuria Perez-Zanon \email{nuria.perez@bsc.es} +} diff --git a/man/BEI_PDFBest.Rd b/man/BEI_PDFBest.Rd index f836ab72..0ba24a84 100644 --- a/man/BEI_PDFBest.Rd +++ b/man/BEI_PDFBest.Rd @@ -4,9 +4,16 @@ \alias{BEI_PDFBest} \title{Computing the Best Index PDFs combining Index PDFs from two SFSs} \usage{ -BEI_PDFBest(index_obs, index_hind1, index_hind2, index_fcst1 = NULL, - index_fcst2 = NULL, method_BC = "none", time_dim_name = "time", - na.rm = FALSE) +BEI_PDFBest( + index_obs, + index_hind1, + index_hind2, + index_fcst1 = NULL, + index_fcst2 = NULL, + method_BC = "none", + time_dim_name = "time", + na.rm = FALSE +) } \arguments{ \item{index_obs}{Index (e.g. NAO index) array from an observational database @@ -113,12 +120,11 @@ dim(res) # time statistic season # 1 2 2 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/BEI_Weights.Rd b/man/BEI_Weights.Rd index 61db33af..867a4eb0 100644 --- a/man/BEI_Weights.Rd +++ b/man/BEI_Weights.Rd @@ -43,13 +43,12 @@ dim(res) # sdate dataset member season # 10 3 5 1 -} -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} } \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/CST_Analogs.Rd b/man/CST_Analogs.Rd index 7c9a1e6f..d7dd5e14 100644 --- a/man/CST_Analogs.Rd +++ b/man/CST_Analogs.Rd @@ -4,8 +4,15 @@ \alias{CST_Analogs} \title{Downscaling using Analogs based on large scale fields.} \usage{ -CST_Analogs(expL, obsL, time_obsL, expVar = NULL, obsVar = NULL, - region = NULL, criteria = "Large_dist") +CST_Analogs( + expL, + obsL, + time_obsL, + expVar = NULL, + obsVar = NULL, + region = NULL, + criteria = "Large_dist" +) } \arguments{ \item{expL}{an 's2dv_cube' object containing the experimental field on the @@ -81,11 +88,6 @@ adapted version of the method of Yiou et al 2013. \examples{ res <- CST_Analogs(expL = lonlat_data$exp, obsL = lonlat_data$obs) -} -\author{ -M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} - -Nuria Perez-Zanon \email{nuria.perez@bsc.es} } \references{ Yiou, P., T. Salameh, P. Drobinski, L. Menut, R. Vautard, @@ -97,4 +99,8 @@ from surface pressure using analogues. Clim. Dyn., 41, 1419-1437. code{\link{CST_Load}}, \code{\link[s2dverification]{Load}} and \code{\link[s2dverification]{CDORemap}} } +\author{ +M. Carmen Alvarez-Castro, \email{carmen.alvarez-castro@cmcc.it} +Nuria Perez-Zanon \email{nuria.perez@bsc.es} +} diff --git a/man/CST_Anomaly.Rd b/man/CST_Anomaly.Rd index e1c31f0c..07691ea7 100644 --- a/man/CST_Anomaly.Rd +++ b/man/CST_Anomaly.Rd @@ -4,8 +4,7 @@ \alias{CST_Anomaly} \title{Anomalies relative to a climatology along selected dimension with or without cross-validation} \usage{ -CST_Anomaly(exp = NULL, obs = NULL, cross = FALSE, memb = TRUE, - dim_anom = 3) +CST_Anomaly(exp = NULL, obs = NULL, cross = FALSE, memb = TRUE, dim_anom = 3) } \arguments{ \item{exp}{an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the seasonal forecast experiment data in the element named \code{$data}.} @@ -53,13 +52,12 @@ str(anom3) anom4 <- CST_Anomaly(exp = exp, obs = obs, cross = FALSE, memb = FALSE) str(anom4) +} +\seealso{ +\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} } \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Pena Jesus, \email{jesus.pena@bsc.es} } -\seealso{ -\code{\link[s2dverification]{Ano_CrossValid}}, \code{\link[s2dverification]{Clim}} and \code{\link{CST_Load}} -} - diff --git a/man/CST_BEI_Weighting.Rd b/man/CST_BEI_Weighting.Rd index 0e60a356..d6f65bb5 100644 --- a/man/CST_BEI_Weighting.Rd +++ b/man/CST_BEI_Weighting.Rd @@ -4,8 +4,13 @@ \alias{CST_BEI_Weighting} \title{Weighting SFSs of a CSTools object.} \usage{ -CST_BEI_Weighting(var_exp, aweights, terciles = NULL, type = "ensembleMean", - time_dim_name = "time") +CST_BEI_Weighting( + var_exp, + aweights, + terciles = NULL, + type = "ensembleMean", + time_dim_name = "time" +) } \arguments{ \item{var_exp}{An object of the class 's2dv_cube' containing the variable @@ -68,12 +73,11 @@ dim(res_CST$data) # time lat lon dataset # 2 3 2 2 } -\author{ -Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} -} \references{ Regionally improved seasonal forecast of precipitation through Best estimation of winter NAO, Sanchez-Garcia, E. et al., Adv. Sci. Res., 16, 165174, 2019, https://doi.org/10.5194/asr-16-165-2019 } - +\author{ +Eroteida Sanchez-Garcia - AEMET, \email{esanchezg@aemet.es} +} diff --git a/man/CST_BiasCorrection.Rd b/man/CST_BiasCorrection.Rd index e8a82af0..a1b415fb 100644 --- a/man/CST_BiasCorrection.Rd +++ b/man/CST_BiasCorrection.Rd @@ -35,10 +35,9 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_BiasCorrection(exp = exp, obs = obs) str(a) } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} -} \references{ Torralba, V., F.J. Doblas-Reyes, D. MacLeod, I. Christel and M. Davis (2017). Seasonal climate prediction: a new source of information for the management of wind energy resources. Journal of Applied Meteorology and Climatology, 56, 1231-1247, doi:10.1175/JAMC-D-16-0204.1. (CLIM4ENERGY, EUPORIAS, NEWA, RESILIENCE, SPECS) } - +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} +} diff --git a/man/CST_Calibration.Rd b/man/CST_Calibration.Rd index ed880aab..891e2e5f 100644 --- a/man/CST_Calibration.Rd +++ b/man/CST_Calibration.Rd @@ -4,9 +4,15 @@ \alias{CST_Calibration} \title{Forecast Calibration} \usage{ -CST_Calibration(exp, obs, cal.method = "mse_min", - eval.method = "leave-one-out", multi.model = F, na.fill = T, - ncores = 1) +CST_Calibration( + exp, + obs, + cal.method = "mse_min", + eval.method = "leave-one-out", + multi.model = F, + na.fill = T, + ncores = 1 +) } \arguments{ \item{exp}{an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the seasonal forecast experiment data in the element named \code{$data}.} @@ -44,12 +50,11 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_Calibration(exp = exp, obs = obs, cal.method = "mse_min", eval.method = "in-sample") str(a) } +\seealso{ +\code{\link{CST_Load}} +} \author{ Verónica Torralba, \email{veronica.torralba@bsc.es} Bert Van Schaeybroeck, \email{bertvs@meteo.be} } -\seealso{ -\code{\link{CST_Load}} -} - diff --git a/man/CST_CategoricalEnsCombination.Rd b/man/CST_CategoricalEnsCombination.Rd index e551c3ec..c23f8341 100644 --- a/man/CST_CategoricalEnsCombination.Rd +++ b/man/CST_CategoricalEnsCombination.Rd @@ -4,8 +4,14 @@ \alias{CST_CategoricalEnsCombination} \title{Make categorical forecast based on a multi-model forecast with potential for calibrate} \usage{ -CST_CategoricalEnsCombination(exp, obs, cat.method = "pool", - eval.method = "leave-one-out", amt.cat = 3, ...) +CST_CategoricalEnsCombination( + exp, + obs, + cat.method = "pool", + eval.method = "leave-one-out", + amt.cat = 3, + ... +) } \arguments{ \item{exp}{an object of class \code{s2dv_cube} as returned by \code{CST_Load} function, containing the seasonal forecast experiment data in the element named \code{$data}. The amount of forecasting models is equal to the size of the \code{dataset} dimension of the data array. The amount of members per model may be different. The size of the \code{member} dimension of the data array is equal to the maximum of the ensemble members among the models. Models with smaller ensemble sizes have residual indices of \code{member} dimension in the data array filled with NA values.} @@ -83,9 +89,6 @@ attr(obs, 'class') <- 's2dv_cube' a <- CST_CategoricalEnsCombination(exp = exp, obs = obs, amt.cat = 3, cat.method = "mmw") } } -\author{ -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} \references{ Rajagopalan, B., Lall, U., & Zebiak, S. E. (2002). Categorical climate forecasts through regularization and optimal combination of multiple GCM ensembles. Monthly Weather Review, 130(7), 1792-1811. @@ -93,4 +96,6 @@ Robertson, A. W., Lall, U., Zebiak, S. E., & Goddard, L. (2004). Improved combin Van Schaeybroeck, B., & Vannitsem, S. (2019). Postprocessing of Long-Range Forecasts. In Statistical Postprocessing of Ensemble Forecasts (pp. 267-290). } - +\author{ +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} diff --git a/man/CST_EnsClustering.Rd b/man/CST_EnsClustering.Rd index c13bf205..154541d5 100644 --- a/man/CST_EnsClustering.Rd +++ b/man/CST_EnsClustering.Rd @@ -4,10 +4,18 @@ \alias{CST_EnsClustering} \title{Ensemble clustering} \usage{ -CST_EnsClustering(exp, time_moment = "mean", numclus = NULL, - lon_lim = NULL, lat_lim = NULL, variance_explained = 80, - numpcs = NULL, time_percentile = 90, cluster_dim = "member", - verbose = F) +CST_EnsClustering( + exp, + time_moment = "mean", + numclus = NULL, + lon_lim = NULL, + lat_lim = NULL, + variance_explained = 80, + numpcs = NULL, + time_percentile = 90, + cluster_dim = "member", + verbose = F +) } \arguments{ \item{exp}{An object of the class 's2dv_cube', containing the variables to be analysed. @@ -125,4 +133,3 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/CST_Load.Rd b/man/CST_Load.Rd index 1fee022c..bf03ba42 100644 --- a/man/CST_Load.Rd +++ b/man/CST_Load.Rd @@ -47,4 +47,3 @@ obs <- CSTools::lonlat_data$obs \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} } - diff --git a/man/CST_MergeDims.Rd b/man/CST_MergeDims.Rd index 449e011e..0762e83f 100644 --- a/man/CST_MergeDims.Rd +++ b/man/CST_MergeDims.Rd @@ -4,8 +4,12 @@ \alias{CST_MergeDims} \title{Function to Merge Dimensions} \usage{ -CST_MergeDims(data, merge_dims = c("ftime", "monthly"), rename_dim = NULL, - na.rm = FALSE) +CST_MergeDims( + data, + merge_dims = c("ftime", "monthly"), + rename_dim = NULL, + na.rm = FALSE +) } \arguments{ \item{data}{a 's2dv_cube' object} @@ -38,4 +42,3 @@ dim(new_data$data) \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/CST_MultiEOF.Rd b/man/CST_MultiEOF.Rd index fb584751..036a6470 100644 --- a/man/CST_MultiEOF.Rd +++ b/man/CST_MultiEOF.Rd @@ -4,8 +4,14 @@ \alias{CST_MultiEOF} \title{EOF analysis of multiple variables} \usage{ -CST_MultiEOF(datalist, neof_max = 40, neof_composed = 5, minvar = 0.6, - lon_lim = NULL, lat_lim = NULL) +CST_MultiEOF( + datalist, + neof_max = 40, + neof_composed = 5, + minvar = 0.6, + lon_lim = NULL, + lat_lim = NULL +) } \arguments{ \item{datalist}{A list of objects of the class 's2dv_cube', containing the variables to be analysed. @@ -69,4 +75,3 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } - diff --git a/man/CST_MultiMetric.Rd b/man/CST_MultiMetric.Rd index 079a5588..8e3ce593 100644 --- a/man/CST_MultiMetric.Rd +++ b/man/CST_MultiMetric.Rd @@ -37,15 +37,14 @@ c(ano_exp, ano_obs) \%<-\% CST_Anomaly(exp = exp, obs = obs, cross = TRUE, memb a <- CST_MultiMetric(exp = ano_exp, obs = ano_obs) str(a) } -\author{ -Mishra Niti, \email{niti.mishra@bsc.es} - -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} \references{ Mishra, N., Prodhomme, C., & Guemas, V. (n.d.). Multi-Model Skill Assessment of Seasonal Temperature and Precipitation Forecasts over Europe, 29-31.\url{http://link.springer.com/10.1007/s00382-018-4404-z} } \seealso{ \code{\link[s2dverification]{Corr}}, \code{\link[s2dverification]{RMS}}, \code{\link[s2dverification]{RMSSS}} and \code{\link{CST_Load}} } +\author{ +Mishra Niti, \email{niti.mishra@bsc.es} +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_MultivarRMSE.Rd b/man/CST_MultivarRMSE.Rd index 685eaf77..24af608c 100644 --- a/man/CST_MultivarRMSE.Rd +++ b/man/CST_MultivarRMSE.Rd @@ -56,10 +56,9 @@ weight <- c(1, 2) a <- CST_MultivarRMSE(exp = ano_exp, obs = ano_obs, weight = weight) str(a) } -\author{ -Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} -} \seealso{ \code{\link[s2dverification]{RMS}} and \code{\link{CST_Load}} } - +\author{ +Deborah Verfaillie, \email{deborah.verfaillie@bsc.es} +} diff --git a/man/CST_QuantileMapping.Rd b/man/CST_QuantileMapping.Rd index 1c93843e..ad8f4b6c 100644 --- a/man/CST_QuantileMapping.Rd +++ b/man/CST_QuantileMapping.Rd @@ -4,9 +4,16 @@ \alias{CST_QuantileMapping} \title{Quantiles Mapping for seasonal or decadal forecast data} \usage{ -CST_QuantileMapping(exp, obs, exp_cor = NULL, sample_dims = c("sdate", - "ftime", "member"), sample_length = NULL, method = "QUANT", - ncores = NULL, ...) +CST_QuantileMapping( + exp, + obs, + exp_cor = NULL, + sample_dims = c("sdate", "ftime", "member"), + sample_length = NULL, + method = "QUANT", + ncores = NULL, + ... +) } \arguments{ \item{exp}{an object of class \code{s2dv_cube}} @@ -77,10 +84,9 @@ res <- CST_QuantileMapping(exp = exp, obs = obs, sample_dims = 'time', method = 'DIST') } } -\author{ -Nuria Perez-Zanon, \email{nuria.perez@bsc.es} -} \seealso{ \code{\link[qmap]{fitQmap}} and \code{\link[qmap]{doQmap}} } - +\author{ +Nuria Perez-Zanon, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_RFSlope.Rd b/man/CST_RFSlope.Rd index d2b5aec0..0c4e1671 100644 --- a/man/CST_RFSlope.Rd +++ b/man/CST_RFSlope.Rd @@ -50,4 +50,3 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/CST_RFWeights.Rd b/man/CST_RFWeights.Rd index 08a7b850..ef5ebe4d 100644 --- a/man/CST_RFWeights.Rd +++ b/man/CST_RFWeights.Rd @@ -47,9 +47,6 @@ nf <- 8 ww <- CST_RFWeights("./worldclim.nc", nf, lon, lat, fsmooth = TRUE) } } -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} -} \references{ Terzago, S., Palazzi, E., & von Hardenberg, J. (2018). Stochastic downscaling of precipitation in complex orography: @@ -57,4 +54,6 @@ A simple method to reproduce a realistic fine-scale climatology. Natural Hazards and Earth System Sciences, 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 . } - +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} diff --git a/man/CST_RainFARM.Rd b/man/CST_RainFARM.Rd index 4a667f9a..1c609e08 100644 --- a/man/CST_RainFARM.Rd +++ b/man/CST_RainFARM.Rd @@ -4,9 +4,20 @@ \alias{CST_RainFARM} \title{RainFARM stochastic precipitation downscaling of a CSTools object} \usage{ -CST_RainFARM(data, nf, weights = 1, slope = 0, kmin = 1, nens = 1, - fglob = FALSE, fsmooth = TRUE, nprocs = 1, time_dim = NULL, - verbose = FALSE, drop_realization_dim = FALSE) +CST_RainFARM( + data, + nf, + weights = 1, + slope = 0, + kmin = 1, + nens = 1, + fglob = FALSE, + fsmooth = TRUE, + nprocs = 1, + time_dim = NULL, + verbose = FALSE, + drop_realization_dim = FALSE +) } \arguments{ \item{data}{An object of the class 's2dv_cube' as returned by `CST_Load`, @@ -95,13 +106,12 @@ dim(res$data) # dataset member realization sdate ftime lat lon # 1 2 3 3 4 64 64 -} -\author{ -Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } \references{ Terzago, S. et al. (2018). NHESS 18(11), 2825-2840. http://doi.org/10.5194/nhess-18-2825-2018 ; D'Onofrio et al. (2014), J of Hydrometeorology 15, 830-843; Rebora et. al. (2006), JHM 7, 724. } - +\author{ +Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} +} diff --git a/man/CST_SaveExp.Rd b/man/CST_SaveExp.Rd index 17537205..0e49c119 100644 --- a/man/CST_SaveExp.Rd +++ b/man/CST_SaveExp.Rd @@ -29,11 +29,10 @@ destination <- "./path/" CST_SaveExp(data = data, destination = destination) } -} -\author{ -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} } \seealso{ \code{\link{CST_Load}}, \code{\link{as.s2dv_cube}} and \code{\link{s2dv_cube}} } - +\author{ +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} diff --git a/man/CST_SplitDim.Rd b/man/CST_SplitDim.Rd index 2019ea7b..ee93aedc 100644 --- a/man/CST_SplitDim.Rd +++ b/man/CST_SplitDim.Rd @@ -43,4 +43,3 @@ dim(new_data$data) \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/Calibration.Rd b/man/Calibration.Rd index 4290abd7..9f884671 100644 --- a/man/Calibration.Rd +++ b/man/Calibration.Rd @@ -4,8 +4,15 @@ \alias{Calibration} \title{Forecast Calibration} \usage{ -Calibration(exp, obs, cal.method = "mse_min", eval.method = "leave-one-out", - multi.model = F, na.fill = T, ncores = 1) +Calibration( + exp, + obs, + cal.method = "mse_min", + eval.method = "leave-one-out", + multi.model = F, + na.fill = T, + ncores = 1 +) } \arguments{ \item{exp}{an array containing the seasonal forecast experiment data.} @@ -30,11 +37,6 @@ Four types of member-by-member bias correction can be performed. The \code{bias} Both in-sample or our out-of-sample (leave-one-out cross validation) calibration are possible. } -\author{ -Verónica Torralba, \email{veronica.torralba@bsc.es} - -Bert Van Schaeybroeck, \email{bertvs@meteo.be} -} \references{ Doblas-Reyes F.J, Hagedorn R, Palmer T.N. The rationale behind the success of multi-model ensembles in seasonal forecasting-II calibration and combination. Tellus A. 2005;57:234-252. doi:10.1111/j.1600-0870.2005.00104.x @@ -45,4 +47,8 @@ Van Schaeybroeck, B., & Vannitsem, S. (2015). Ensemble post-processing using mem \seealso{ \code{\link{CST_Load}} } +\author{ +Verónica Torralba, \email{veronica.torralba@bsc.es} +Bert Van Schaeybroeck, \email{bertvs@meteo.be} +} diff --git a/man/EnsClustering.Rd b/man/EnsClustering.Rd index 27aca453..2fd8a3f1 100644 --- a/man/EnsClustering.Rd +++ b/man/EnsClustering.Rd @@ -4,10 +4,20 @@ \alias{EnsClustering} \title{Ensemble clustering} \usage{ -EnsClustering(data, lat, lon, time_moment = "mean", numclus = NULL, - lon_lim = NULL, lat_lim = NULL, variance_explained = 80, - numpcs = NULL, time_percentile = 90, cluster_dim = "member", - verbose = T) +EnsClustering( + data, + lat, + lon, + time_moment = "mean", + numclus = NULL, + lon_lim = NULL, + lat_lim = NULL, + variance_explained = 80, + numpcs = NULL, + time_percentile = 90, + cluster_dim = "member", + verbose = T +) } \arguments{ \item{data}{A matrix of dimensions 'dataset member sdate ftime lat lon' containing the variables to be analysed.} @@ -67,4 +77,3 @@ Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/MergeDims.Rd b/man/MergeDims.Rd index 585049e8..7539ef6e 100644 --- a/man/MergeDims.Rd +++ b/man/MergeDims.Rd @@ -4,8 +4,12 @@ \alias{MergeDims} \title{Function to Split Dimension} \usage{ -MergeDims(data, merge_dims = c("time", "monthly"), rename_dim = NULL, - na.rm = FALSE) +MergeDims( + data, + merge_dims = c("time", "monthly"), + rename_dim = NULL, + na.rm = FALSE +) } \arguments{ \item{data}{an n-dimensional array with named dimensions} @@ -28,4 +32,3 @@ new_data <- MergeDims(data, merge_dims = c('time', 'lat')) \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/MultiEOF.Rd b/man/MultiEOF.Rd index 1e822fc4..dd0fc7fe 100644 --- a/man/MultiEOF.Rd +++ b/man/MultiEOF.Rd @@ -4,9 +4,19 @@ \alias{MultiEOF} \title{EOF analysis of multiple variables starting from an array (reduced version)} \usage{ -MultiEOF(data, lon, lat, time, lon_dim = "lon", lat_dim = "lat", - neof_max = 40, neof_composed = 5, minvar = 0.6, lon_lim = NULL, - lat_lim = NULL) +MultiEOF( + data, + lon, + lat, + time, + lon_dim = "lon", + lat_dim = "lat", + neof_max = 40, + neof_composed = 5, + minvar = 0.6, + lon_lim = NULL, + lat_lim = NULL +) } \arguments{ \item{data}{A multidimensional array with dimension \code{"var"}, @@ -46,4 +56,3 @@ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} Paolo Davini - ISAC-CNR, \email{p.davini@isac.cnr.it} } - diff --git a/man/PlotCombinedMap.Rd b/man/PlotCombinedMap.Rd index 6857c64d..616b84f9 100644 --- a/man/PlotCombinedMap.Rd +++ b/man/PlotCombinedMap.Rd @@ -4,11 +4,27 @@ \alias{PlotCombinedMap} \title{Plot Multiple Lon-Lat Variables In a Single Map According to a Decision Function} \usage{ -PlotCombinedMap(maps, lon, lat, map_select_fun, display_range, - map_dim = "map", brks = NULL, cols = NULL, col_unknown_map = "white", - mask = NULL, col_mask = "grey", bar_titles = NULL, legend_scale = 1, - fileout = NULL, width = 8, height = 5, size_units = "in", res = 100, - ...) +PlotCombinedMap( + maps, + lon, + lat, + map_select_fun, + display_range, + map_dim = "map", + brks = NULL, + cols = NULL, + col_unknown_map = "white", + mask = NULL, + col_mask = "grey", + bar_titles = NULL, + legend_scale = 1, + fileout = NULL, + width = 8, + height = 5, + size_units = "in", + res = 100, + ... +) } \arguments{ \item{maps}{List of matrices to plot, each with (longitude, latitude) dimensions, or 3-dimensional array with the dimensions (longitude, latitude, map). Dimension names are required.} @@ -67,12 +83,11 @@ PlotCombinedMap(list(a, b, c), lons, lats, bar_titles = paste('\% of belonging to', c('a', 'b', 'c')), brks = 20, width = 10, height = 8) } +\seealso{ +\code{PlotCombinedMap} and \code{PlotEquiMap} +} \author{ Nicolau Manubens, \email{nicolau.manubens@bsc.es} Veronica Torralba, \email{veronica.torralba@bsc.es} } -\seealso{ -\code{PlotCombinedMap} and \code{PlotEquiMap} -} - diff --git a/man/PlotForecastPDF.Rd b/man/PlotForecastPDF.Rd index d7b95b08..c04b43c1 100644 --- a/man/PlotForecastPDF.Rd +++ b/man/PlotForecastPDF.Rd @@ -4,10 +4,18 @@ \alias{PlotForecastPDF} \title{Plot one or multiple ensemble forecast pdfs for the same event} \usage{ -PlotForecastPDF(fcst, tercile.limits, extreme.limits = NULL, obs = NULL, - plotfile = NULL, title = "Set a title", var.name = "Varname (units)", - fcst.names = NULL, add.ensmemb = c("above", "below", "no"), - color.set = c("ggplot", "s2s4e", "hydro")) +PlotForecastPDF( + fcst, + tercile.limits, + extreme.limits = NULL, + obs = NULL, + plotfile = NULL, + title = "Set a title", + var.name = "Varname (units)", + fcst.names = NULL, + add.ensmemb = c("above", "below", "no"), + color.set = c("ggplot", "s2s4e", "hydro") +) } \arguments{ \item{fcst}{a dataframe or array containing all the ensember members for each forecast. If \code{'fcst'} is an array, it should have two labelled dimensions, and one of them should be \code{'members'}. If \code{'fcsts'} is a data.frame, each column shoul be a separate forecast, with the rows beeing the different ensemble members.} @@ -49,4 +57,3 @@ PlotForecastPDF(fcsts2, c(-0.66, 0.66), extreme.limits = c(-1.2, 1.2), \author{ Llorenç Lledó \email{llledo@bsc.es} } - diff --git a/man/PlotMostLikelyQuantileMap.Rd b/man/PlotMostLikelyQuantileMap.Rd index 6c92850e..4c400b18 100644 --- a/man/PlotMostLikelyQuantileMap.Rd +++ b/man/PlotMostLikelyQuantileMap.Rd @@ -4,8 +4,15 @@ \alias{PlotMostLikelyQuantileMap} \title{Plot Maps of Most Likely Quantiles} \usage{ -PlotMostLikelyQuantileMap(probs, lon, lat, cat_dim = "bin", - bar_titles = NULL, col_unknown_cat = "white", ...) +PlotMostLikelyQuantileMap( + probs, + lon, + lat, + cat_dim = "bin", + bar_titles = NULL, + col_unknown_cat = "white", + ... +) } \arguments{ \item{probs}{a list of bi-dimensional arrays with the named dimensions 'latitude' (or 'lat') and 'longitude' (or 'lon'), with equal size and in the same order, or a single tri-dimensional array with an additional dimension (e.g. 'bin') for the different categories. The arrays must contain probability values between 0 and 1, and the probabilities for all categories of a grid cell should not exceed 1 when added.} @@ -109,11 +116,10 @@ PlotMostLikelyQuantileMap(bins, lons, lats, mask = 1 - (w1 + w2 / max(c(w1, w2))), brks = 20, width = 10, height = 8) -} -\author{ -Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} } \seealso{ \code{PlotCombinedMap} and \code{PlotEquiMap} } - +\author{ +Veronica Torralba, \email{veronica.torralba@bsc.es}, Nicolau Manubens, \email{nicolau.manubens@bsc.es} +} diff --git a/man/RFSlope.Rd b/man/RFSlope.Rd index 09a24ff5..db3f0e10 100644 --- a/man/RFSlope.Rd +++ b/man/RFSlope.Rd @@ -4,8 +4,7 @@ \alias{RFSlope} \title{RainFARM spectral slopes from an array (reduced version)} \usage{ -RFSlope(data, kmin = 1, time_dim = NULL, lon_dim = "lon", - lat_dim = "lat") +RFSlope(data, kmin = 1, time_dim = NULL, lon_dim = "lon", lat_dim = "lat") } \arguments{ \item{data}{Array containing the spatial precipitation fields to downscale. @@ -60,4 +59,3 @@ slopes \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/RainFARM.Rd b/man/RainFARM.Rd index 984dcd42..0db84679 100644 --- a/man/RainFARM.Rd +++ b/man/RainFARM.Rd @@ -4,10 +4,24 @@ \alias{RainFARM} \title{RainFARM stochastic precipitation downscaling (reduced version)} \usage{ -RainFARM(data, lon, lat, nf, weights = 1, nens = 1, slope = 0, kmin = 1, - fglob = FALSE, fsmooth = TRUE, nprocs = 1, time_dim = NULL, - lon_dim = "lon", lat_dim = "lat", drop_realization_dim = FALSE, - verbose = FALSE) +RainFARM( + data, + lon, + lat, + nf, + weights = 1, + nens = 1, + slope = 0, + kmin = 1, + fglob = FALSE, + fsmooth = TRUE, + nprocs = 1, + time_dim = NULL, + lon_dim = "lon", + lat_dim = "lat", + drop_realization_dim = FALSE, + verbose = FALSE +) } \arguments{ \item{data}{Precipitation array to downscale. @@ -117,4 +131,3 @@ dim(res$data) \author{ Jost von Hardenberg - ISAC-CNR, \email{j.vonhardenberg@isac.cnr.it} } - diff --git a/man/SplitDim.Rd b/man/SplitDim.Rd index e36aa8a5..f07e4756 100644 --- a/man/SplitDim.Rd +++ b/man/SplitDim.Rd @@ -35,4 +35,3 @@ new_data <- SplitDim(data, indices = time, freq = 'year') \author{ Nuria Perez-Zanon, \email{nuria.perez@bsc.es} } - diff --git a/man/areave_data.Rd b/man/areave_data.Rd index cc79c85c..a772220a 100644 --- a/man/areave_data.Rd +++ b/man/areave_data.Rd @@ -41,4 +41,3 @@ areave_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} - diff --git a/man/as.s2dv_cube.Rd b/man/as.s2dv_cube.Rd index 13a2a296..c2b8f3a8 100644 --- a/man/as.s2dv_cube.Rd +++ b/man/as.s2dv_cube.Rd @@ -40,12 +40,11 @@ data <- as.s2dv_cube(data) class(data) } } +\seealso{ +\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} +} \author{ Perez-Zanon Nuria, \email{nuria.perez@bsc.es} Nicolau Manubens, \email{nicolau.manubens@bsc.es} } -\seealso{ -\code{\link{s2dv_cube}}, \code{\link[s2dverification]{Load}}, \code{\link[startR]{Start}} and \code{\link{CST_Load}} -} - diff --git a/man/lonlat_data.Rd b/man/lonlat_data.Rd index eca7abac..0c6ee30f 100644 --- a/man/lonlat_data.Rd +++ b/man/lonlat_data.Rd @@ -41,4 +41,3 @@ lonlat_data <- Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{data} - diff --git a/man/lonlat_prec.Rd b/man/lonlat_prec.Rd index 69cb94e8..345e3cab 100644 --- a/man/lonlat_prec.Rd +++ b/man/lonlat_prec.Rd @@ -29,4 +29,3 @@ lonlat_prec <- CST_Load('prlr', exp = list(infile), obs = NULL, Jost von Hardenberg \email{j.vonhardenberg@isac.cnr.it} } \keyword{data} - diff --git a/man/s2dv_cube.Rd b/man/s2dv_cube.Rd index 48af7bbb..b0ce8966 100644 --- a/man/s2dv_cube.Rd +++ b/man/s2dv_cube.Rd @@ -4,8 +4,16 @@ \alias{s2dv_cube} \title{Creation of a 's2dv_cube' object} \usage{ -s2dv_cube(data, lon = NULL, lat = NULL, Variable = NULL, - Datasets = NULL, Dates = NULL, when = NULL, source_files = NULL) +s2dv_cube( + data, + lon = NULL, + lat = NULL, + Variable = NULL, + Datasets = NULL, + Dates = NULL, + when = NULL, + source_files = NULL +) } \arguments{ \item{data}{an array with any number of named dimensions, typically an object output from CST_Load, with the following dimensions: dataset, member, sdate, ftime, lat and lon.} @@ -75,10 +83,9 @@ exp8 <- s2dv_cube(data = exp_original, lon = seq(-10, 10, 5), lat = c(45, 50), end = paste0(rep("31", 10), rep("01", 10), 1990:1999))) class(exp8) } -\author{ -Perez-Zanon Nuria, \email{nuria.perez@bsc.es} -} \seealso{ \code{\link[s2dverification]{Load}} and \code{\link{CST_Load}} } - +\author{ +Perez-Zanon Nuria, \email{nuria.perez@bsc.es} +} -- GitLab From 7780de933eb0b6825a20731534bcf317342cd727 Mon Sep 17 00:00:00 2001 From: nperez Date: Fri, 7 Feb 2020 19:21:04 +0100 Subject: [PATCH 34/34] bumped version number --- DESCRIPTION | 2 +- NEWS.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index ccc1d5a9..2c87e147 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: CSTools Title: Assessing Skill of Climate Forecasts on Seasonal-to-Decadal Timescales -Version: 2.0.0 +Version: 3.0.0 Authors@R: c( person("Nuria", "Perez-Zanon", , "nuria.perez@bsc.es", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-8568-3071")), person("Louis-Philippe", "Caron", , "louis-philippe.caron@bsc.es", role = "aut", comment = c(ORCID = "0000-0001-5221-0147")), diff --git a/NEWS.md b/NEWS.md index 7d1ea1e5..3e625ed0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,14 @@ +### CSTools 3.0.0 +**Submission date to CRAN: 10-02-2020** + +- New features: + + CST_MergeDims and MergeDims + + Version working with R 3.4.2 + + PlotForecastPDF handles independent terciles, extremes and observations for each panel +- Fixes + + CST_Calibration handles missing values + + BEI functions handle missing values + ### CSTools 2.0.0 **Submission date to CRAN: 25-11-2019** -- GitLab