diff --git a/R/PlotEquiMap.R b/R/PlotEquiMap.R index 640533399ebb5ca5d485c11fa9edfb1954d245b2..c06f7bbcb0a385dda6baf02cbe861d4185cbdf09 100644 --- a/R/PlotEquiMap.R +++ b/R/PlotEquiMap.R @@ -16,7 +16,9 @@ #' descending order and latitudes in any order. It can contain NA values #' (coloured with 'colNA'). Arrays with dimensions c(longitude, latitude) #' will also be accepted but 'lon' and 'lat' will be used to disambiguate so -#' this alternative is not appropriate for square arrays. +#' this alternative is not appropriate for square arrays. It is allowed that +#' the positions of the longitudinal and latitudinal coordinate dimensions +#' are interchanged. #'@param lon Numeric vector of longitude locations of the cell centers of the #' grid of 'var', in ascending or descending order (same as 'var'). Expected #' to be regularly spaced, within either of the ranges [-180, 180] or @@ -27,9 +29,11 @@ #' grid of 'var', in any order (same as 'var'). Expected to be from a regular #' rectangular or gaussian grid, within the range [-90, 90]. #'@param varu Array of the zonal component of wind/current/other field with -#' the same dimensions as 'var'. +#' the same dimensions as 'var'. It is allowed that the positions of the +#' longitudinal and latitudinal coordinate dimensions are interchanged. #'@param varv Array of the meridional component of wind/current/other field -#' with the same dimensions as 'var'. +#' with the same dimensions as 'var'. It is allowed that the positions of the +#' longitudinal and latitudinal coordinate dimensions are interchanged. #'@param toptitle Top title of the figure, scalable with parameter #' 'title_scale'. #'@param sizetit Scale factor for the figure top title provided in parameter @@ -52,8 +56,15 @@ #' colors returned by 'color_fun'. If not available, it takes 'pink' by #' default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not #' specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. -#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control the visual -#' aspect of the drawn colour bar. See ?ColorBar for a full explanation. +#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks Set of +#' parameters to control the visual aspect of the drawn colour bar +#' (1/3). See ?ColorBar for a full explanation. +#'@param draw_separators,triangle_ends_scale,bar_label_digits Set of +#' parameters to control the visual aspect of the drawn colour bar +#' (2/3). See ?ColorBar for a full explanation. +#'@param bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin Set of +#' parameters to control the visual aspect of the drawn colour bar (3/3). +#' See ?ColorBar for a full explanation. #'@param square Logical value to choose either to draw a coloured square for #' each grid cell in 'var' (TRUE; default) or to draw contour lines and fill #' the spaces in between with colours (FALSE). In the latter case, @@ -82,6 +93,8 @@ #'@param contours Array of same dimensions as 'var' to be added to the plot #' and displayed with contours. Parameter 'brks2' is required to define the #' magnitude breaks for each contour curve. Disregarded if 'square = FALSE'. +#' It is allowed that the positions of the longitudinal and latitudinal +#' coordinate dimensions are interchanged. #'@param brks2 Vector of magnitude breaks where to draw contour curves for the #' array provided in 'contours' or if 'square = FALSE'. #'@param contour_lwd Line width of the contour curves provided via 'contours' @@ -99,7 +112,8 @@ #' plot. A value of TRUE at a grid cell will draw a dot/symbol on the #' corresponding square of the plot. By default all layers provided in 'dots' #' are plotted with dots, but a symbol can be specified for each of the -#' layers via the parameter 'dot_symbol'. +#' layers via the parameter 'dot_symbol'. It is allowed that the positions of +#' the longitudinal and latitudinal coordinate dimensions are interchanged. #'@param dot_symbol Single character/number or vector of characters/numbers #' that correspond to each of the symbol layers specified in parameter 'dots'. #' If a single value is specified, it will be applied to all the layers in @@ -134,8 +148,8 @@ #'@param lab_dist_y A numeric of the distance of the latitude labels to the #' box borders. The default value is NULL and is automatically adjusted by #' the function. -#'@param degree_sym A logical indicating whether to include degree symbol (30° N) -#' or not (30N; default). +#'@param degree_sym A logical indicating whether to include degree symbol +#' (30° N) or not (30N; default). #'@param intylat Interval between latitude ticks on y-axis, in degrees. #' Defaults to 20. #'@param intxlon Interval between latitude ticks on x-axis, in degrees. @@ -289,91 +303,214 @@ PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, fileout <- deviceInfo$files } - # Preliminar check of dots, contours, varu, varv, lon, lat - if (!is.null(dots)) { - if (!is.array(dots) || !(length(dim(dots)) %in% c(2, 3))) { - stop("Parameter 'dots' must be a logical array with two or three dimensions.") - } - if (length(dim(dots)) == 2) { - dim(dots) <- c(1, dim(dots)) - } - } - if (!is.null(contours)) { - if (!is.array(contours) || !(length(dim(contours)) == 2)) { - stop("Parameter 'contours' must be a numerical array with two dimensions.") - } - } - if (!is.null(varu) && !is.null(varv)) { - if (!is.array(varu) || !(length(dim(varu)) == 2)) { - stop("Parameter 'varu' must be a numerical array with two dimensions.") - } - if (!is.array(varv) || !(length(dim(varv)) == 2)) { - stop("Parameter 'varv' must be a numerical array with two dimensions.") - } - } else if (!is.null(varu) || !is.null(varv)) { - stop("Only one of the components 'varu' or 'varv' has been provided. Both must be provided.") - } + # Check lon, lat if (!is.numeric(lon) || !is.numeric(lat)) { stop("Parameters 'lon' and 'lat' must be numeric vectors.") } # Check var + if (is.null(var)) { + stop("Parameter 'var' cannot be NULL.") + } if (!is.array(var)) { stop("Parameter 'var' must be a numeric array.") } - if (length(dim(var)) > 2) { - var <- drop(var) - dim(var) <- head(c(dim(var), 1, 1), 2) + + transpose <- FALSE + if (!is.null(names(dim(var)))) { + if (any(names(dim(var)) %in% .KnownLonNames()) && + any(names(dim(var)) %in% .KnownLatNames())) { + lon_dim <- names(dim(var))[names(dim(var)) %in% .KnownLonNames()] + lat_dim <- names(dim(var))[names(dim(var)) %in% .KnownLatNames()] + } else { + names(dim(var)) <- NULL + lat_dim <- NULL + lon_dim <- NULL + .warning("Dimension names of 'var' doesn't correspond to any coordinates names supported by s2dv package.") + } + } else { + lon_dim <- NULL + lat_dim <- NULL + .warning("Parameter 'var' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the corresponding coordinates dimensions.") } + if (length(dim(var)) > 2) { - stop("Parameter 'var' must be a numeric array with two dimensions. See PlotMultiMap() for multi-pannel maps or AnimateMap() for animated maps.") - } else if (length(dim(var)) < 2) { + if (!is.null(lon_dim) & !is.null(lat_dim)) { + dimnames <- names(dim(var)) + dim(var) <- dim(var)[which((dimnames == lon_dim | dimnames == lat_dim | dim(var) != 1))] + } else { + if (all(dim(var) == 1)) { + dim(var) <- c(1, 1) + } else if (length(dim(var)[which(dim(var) > 1)]) == 2) { + var <- drop(var) + } else if (length(dim(var)[which(dim(var) > 1)]) == 1) { + dim(var) <- c(dim(var)[which(dim(var) > 1)], 1) + } + } + } + + if (length(dim(var)) != 2) { stop("Parameter 'var' must be a numeric array with two dimensions.") } - dims <- dim(var) - # Transpose the input matrices because the base plot functions work directly - # with dimensions c(lon, lat). - transpose <- FALSE - if (!is.null(names(dims))) { - if (any(names(dims) %in% .KnownLonNames()) && - any(names(dims) %in% .KnownLatNames())) { - if (which(names(dims) %in% .KnownLonNames()) != 1) { + + if ((dim(var)[1] == length(lon) && dim(var)[2] == length(lat)) || + (dim(var)[2] == length(lon) && dim(var)[1] == length(lat))) { + if (dim(var)[2] == length(lon) && dim(var)[1] == length(lat)) { + if (length(lon) == length(lat)) { + if (is.null(names(dim(var)))) { + .warning("Parameter 'var' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the first and second dimensions.") + } else { + if (names(dim(var)[1]) == lat_dim) { + transpose <- TRUE + } + } + } else { transpose <- TRUE - } + } } + } else { + stop("Parameters 'lon' and 'lat' must have as many elements as the number of cells along longitudes and latitudes in the input array 'var'.") } - if (dims[1] != length(lon) || dims[2] != length(lat)) { - if (dims[1] == length(lat) && dims[2] == length(lon)) { - transpose <- TRUE + + if (!is.null(names(dim(var)))) { + if (names(dim(var)[1]) == lon_dim) { + if (transpose) { + stop("Coordinates dimensions of 'var' doesn't correspond to lat or lon.") + } + } else if (names(dim(var)[2]) == lon_dim) { + if (!transpose) { + stop("Coordinates dimensions of 'var' doesn't correspond to lat or lon.") + } } } + + # Transpose the input matrices because the base plot functions work directly + # with dimensions c(lon, lat). + if (transpose) { var <- t(var) - if (!is.null(varu)) varu <- t(varu) - if (!is.null(varv)) varv <- t(varv) - if (!is.null(contours)) contours <- t(contours) - if (!is.null(dots)) dots <- aperm(dots, c(1, 3, 2)) - dims <- dim(var) } - # Check lon - if (length(lon) != dims[1]) { - stop("Parameter 'lon' must have as many elements as the number of cells along longitudes in the input array 'var'.") - } + transpose <- FALSE - # Check lat - if (length(lat) != dims[2]) { - stop("Parameter 'lat' must have as many elements as the number of cells along longitudes in the input array 'var'.") - } + names(dim(var)) <- c(lon_dim, lat_dim) + dims <- dim(var) # Check varu and varv if (!is.null(varu) && !is.null(varv)) { - if (dim(varu)[1] != dims[1] || dim(varu)[2] != dims[2]) { - stop("Parameter 'varu' must have same number of longitudes and latitudes as 'var'.") + if (!is.array(varu) || !(length(dim(varu)) == 2)) { + stop("Parameter 'varu' must be a numerical array with two dimensions.") } - if (dim(varv)[1] != dims[1] || dim(varv)[2] != dims[2]) { - stop("Parameter 'varv' must have same number of longitudes and latitudes as 'var'.") + if (!is.array(varv) || !(length(dim(varv)) == 2)) { + stop("Parameter 'varv' must be a numerical array with two dimensions.") } + } else if (!is.null(varu) || !is.null(varv)) { + stop("Only one of the components 'varu' or 'varv' has been provided. Both must be provided.") + } + + if (!is.null(varu) && !is.null(varv)) { + if (!all(dim(varu) %in% dim(varv)) || !all(names(dim(varv)) %in% names(dim(varu)))) { + stop("Parameter 'varu' and 'varv' must have equal dimensions and dimension names.") + } else if (any(dim(varu) != dim(varv)) || any(names(dim(varv)) != names(dim(varu)))) { + varv <- t(varv) + names(dim(varv)) <- names(dim(varu)) + } + + if (is.null(lon_dim)) { + names(dim(varu)) <- NULL + names(dim(varv)) <- NULL + } else { + if (!is.null(names(dim(varu)))) { + if (!(lon_dim %in% names(dim(varu)) && lat_dim %in% names(dim(varu)))) { + stop("Parameters 'varu' and 'varv' must have same dimension names as 'var'.") + } else if (dim(varu)[lon_dim] != dim(var)[lon_dim] || dim(varu)[lat_dim] != dim(var)[lat_dim]) { + stop("Parameters 'varu' and 'varv' must have same dimensions as 'var'.") + } + } else { + .warning("Parameters 'varu' and 'varv' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the corresponding coordinates dimensions.") + } + } + + + if ((dim(varu)[1] == dims[1] && dim(varu)[2] == dims[2]) || + (dim(varu)[2] == dims[1] && dim(varu)[1] == dims[2])) { + if (dim(varu)[2] == dims[1] && dim(varu)[1] == dims[2]) { + if (length(lon) == length(lat)) { + if (is.null(names(dim(varu)))) { + .warning("Parameters 'varu' and 'varv' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the first and second dimensions.") + } else { + if (names(dim(varu)[1]) == lat_dim) { + transpose <- TRUE + } + } + } else { + transpose <- TRUE + } + } + } else { + stop("Parameters 'lon' and 'lat' must have as many elements as the number of cells along longitudes and latitudes in the input array 'varu' and 'varv'.") + } + + if (transpose) { + varu <- t(varu) + varv <- t(varv) + } + + transpose <- FALSE + + } + + # Check contours + if (!is.null(contours)) { + if (!is.array(contours) || !(length(dim(contours)) == 2)) { + stop("Parameter 'contours' must be a numerical array with two dimensions.") + } + } + + + if (!is.null(contours)) { + + if (is.null(lon_dim)) { + names(dim(contours)) <- NULL + } else { + if (!is.null(names(dim(contours)))) { + if (!(lon_dim %in% names(dim(contours)) && lat_dim %in% names(dim(contours)))) { + stop("Parameters 'contours' must have same dimension names as 'var'.") + } else if (dim(contours)[lon_dim] != dim(var)[lon_dim] || dim(contours)[lat_dim] != dim(var)[lat_dim]) { + stop("Parameters 'contours' must have same dimensions as 'var'.") + } + } else { + .warning("Parameters 'contours' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the corresponding coordinates dimensions.") + } + } + + + transpose <- FALSE + if ((dim(contours)[1] == dims[1] && dim(contours)[2] == dims[2]) || + (dim(contours)[2] == dims[1] && dim(contours)[1] == dims[2])) { + if (dim(contours)[2] == dims[1] && dim(contours)[1] == dims[2]) { + if (length(lon) == length(lat)) { + if (is.null(names(dim(contours)))) { + .warning("Parameter 'contours' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the first and second dimensions.") + } else { + if (names(dim(contours)[1]) == lat_dim) { + transpose <- TRUE + } + } + } else { + transpose <- TRUE + } + } + } else { + stop("Parameters 'lon' and 'lat' must have as many elements as the number of cells along longitudes and latitudes in the input array 'contours'.") + } + + if (transpose) { + contours <- t(contours) + } + + transpose <- FALSE + } # Check toptitle @@ -533,13 +670,6 @@ PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, stop("Parameter 'shapefile_color' must be a valid colour identifier.") } - # Check contours - if (!is.null(contours)) { - if (dim(contours)[1] != dims[1] || dim(contours)[2] != dims[2]) { - stop("Parameter 'contours' must have the same number of longitudes and latitudes as 'var'.") - } - } - # Check brks2 if (is.null(brks2)) { if (is.null(contours)) { @@ -579,11 +709,59 @@ PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, stop("Parameter 'contour_label_scale' must be numeric.") } - # Check dots, dot_symbol and dot_size + # Check dots if (!is.null(dots)) { - if (dim(dots)[2] != dims[1] || dim(dots)[3] != dims[2]) { - stop("Parameter 'dots' must have the same number of longitudes and latitudes as 'var'.") + if (!is.array(dots) || !(length(dim(dots)) %in% c(2, 3))) { + stop("Parameter 'dots' must be a logical array with two or three dimensions.") + } + if (length(dim(dots)) == 2) { + dim(dots) <- c(1, dim(dots)) + } + + if (is.null(lon_dim)) { + names(dim(dots)) <- NULL + } else { + if (!is.null(names(dim(dots)))) { + if (!(lon_dim %in% names(dim(dots)) && lat_dim %in% names(dim(dots)))) { + stop("Parameters 'dots' must have same dimension names as 'var'.") + } else if (dim(dots)[lon_dim] != dim(var)[lon_dim] || dim(dots)[lat_dim] != dim(var)[lat_dim]) { + stop("Parameters 'dots' must have same dimensions as 'var'.") + } + } else { + .warning("Parameters 'dots' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the corresponding coordinates dimensions.") + } } + + transpose <- FALSE + if ((dim(dots)[2] == dims[1] && dim(dots)[3] == dims[2]) || + (dim(dots)[3] == dims[1] && dim(dots)[2] == dims[2])) { + if (dim(dots)[3] == dims[1] && dim(dots)[2] == dims[2]) { + if (length(lon) == length(lat)) { + if (is.null(names(dim(dots)))) { + .warning("Parameter 'dots' should have dimension names. Coordinates 'lon' and 'lat' have been assigned into the first and second dimensions.") + } else { + if (names(dim(dots)[2]) == lat_dim) { + transpose <- TRUE + } + } + } else { + transpose <- TRUE + } + } + } else { + stop("Parameter 'dots' must have same number of longitudes and latitudes as 'var'.") + } + + if (transpose) { + dots <- aperm(dots, c(1, 3, 2)) + } + + transpose <- FALSE + + } + + # Check dot_symbol and dot_size + if (!is.null(dots)) { if (!is.numeric(dot_symbol) && !is.character(dot_symbol)) { stop("Parameter 'dot_symbol' must be a numeric or character string vector.") } @@ -791,7 +969,7 @@ PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, ypos <- seq(latmin, latmax, intylat) + ylatshft if (length(ypos) != length(ylabels)) { stop(paste0("Parameter 'ylabels' must have the same length as the latitude ", - "vector spaced by 'intylat' (length = ", length(ypos), ").")) + "vector spaced by 'intylat' (length = ", length(ypos), ").")) } ylabs <- ylabels } else { @@ -812,7 +990,7 @@ PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, xpos <- seq(lonmin, lonmax, intxlon) + xlonshft if (length(xpos) != length(xlabels)) { stop(paste0("Parameter 'xlabels' must have the same length as the longitude ", - "vector spaced by 'intxlon' (length = ", length(xpos), ").")) + "vector spaced by 'intxlon' (length = ", length(xpos), ").")) } xlabs <- xlabels } else { diff --git a/man/PlotEquiMap.Rd b/man/PlotEquiMap.Rd index 47a0d981a3ae6d5dd022b2b59585dcd834271fd5..19ff838922f4926f1fc093ed9c5a40b2185d2c26 100644 --- a/man/PlotEquiMap.Rd +++ b/man/PlotEquiMap.Rd @@ -92,7 +92,9 @@ dimensions: c(latitude, longitude). Longitudes can be in ascending or descending order and latitudes in any order. It can contain NA values (coloured with 'colNA'). Arrays with dimensions c(longitude, latitude) will also be accepted but 'lon' and 'lat' will be used to disambiguate so -this alternative is not appropriate for square arrays.} +this alternative is not appropriate for square arrays. It is allowed that +the positions of the longitudinal and latitudinal coordinate dimensions +are interchanged.} \item{lon}{Numeric vector of longitude locations of the cell centers of the grid of 'var', in ascending or descending order (same as 'var'). Expected @@ -106,10 +108,12 @@ grid of 'var', in any order (same as 'var'). Expected to be from a regular rectangular or gaussian grid, within the range [-90, 90].} \item{varu}{Array of the zonal component of wind/current/other field with -the same dimensions as 'var'.} +the same dimensions as 'var'. It is allowed that the positions of the +longitudinal and latitudinal coordinate dimensions are interchanged.} \item{varv}{Array of the meridional component of wind/current/other field -with the same dimensions as 'var'.} +with the same dimensions as 'var'. It is allowed that the positions of the +longitudinal and latitudinal coordinate dimensions are interchanged.} \item{toptitle}{Top title of the figure, scalable with parameter 'title_scale'.} @@ -138,8 +142,9 @@ colors returned by 'color_fun'. If not available, it takes 'pink' by default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'.} -\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, triangle_ends_scale, bar_label_digits, bar_label_scale, units_scale, bar_tick_scale, bar_extra_margin}{Set of parameters to control the visual -aspect of the drawn colour bar. See ?ColorBar for a full explanation.} +\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks}{Set of +parameters to control the visual aspect of the drawn colour bar +(1/3). See ?ColorBar for a full explanation.} \item{square}{Logical value to choose either to draw a coloured square for each grid cell in 'var' (TRUE; default) or to draw contour lines and fill @@ -178,7 +183,9 @@ location of the shape. The default value is NULL.} \item{contours}{Array of same dimensions as 'var' to be added to the plot and displayed with contours. Parameter 'brks2' is required to define the -magnitude breaks for each contour curve. Disregarded if 'square = FALSE'.} +magnitude breaks for each contour curve. Disregarded if 'square = FALSE'. +It is allowed that the positions of the longitudinal and latitudinal +coordinate dimensions are interchanged.} \item{brks2}{Vector of magnitude breaks where to draw contour curves for the array provided in 'contours' or if 'square = FALSE'.} @@ -203,7 +210,8 @@ c(n, dim(var)), where n is the number of dot/symbol layers to add to the plot. A value of TRUE at a grid cell will draw a dot/symbol on the corresponding square of the plot. By default all layers provided in 'dots' are plotted with dots, but a symbol can be specified for each of the -layers via the parameter 'dot_symbol'.} +layers via the parameter 'dot_symbol'. It is allowed that the positions of +the longitudinal and latitudinal coordinate dimensions are interchanged.} \item{dot_symbol}{Single character/number or vector of characters/numbers that correspond to each of the symbol layers specified in parameter 'dots'. @@ -251,8 +259,8 @@ the function.} box borders. The default value is NULL and is automatically adjusted by the function.} -\item{degree_sym}{A logical indicating whether to include degree symbol (30° N) -or not (30N; default).} +\item{degree_sym}{A logical indicating whether to include degree symbol +(30° N) or not (30N; default).} \item{intylat}{Interval between latitude ticks on y-axis, in degrees. Defaults to 20.} @@ -286,6 +294,14 @@ and latitude axes.} TRUE. It is not possible to plot the colour bar if 'add = TRUE'. Use ColorBar() and the return values of PlotEquiMap() instead.} +\item{draw_separators, triangle_ends_scale, bar_label_digits}{Set of +parameters to control the visual aspect of the drawn colour bar +(2/3). See ?ColorBar for a full explanation.} + +\item{bar_label_scale, units_scale, bar_tick_scale, bar_extra_margin}{Set of +parameters to control the visual aspect of the drawn colour bar (3/3). +See ?ColorBar for a full explanation.} + \item{boxlim}{Limits of a box to be added to the plot, in degrees: c(x1, y1, x2, y2). A list with multiple box specifications can also be provided.}