From d580ce080dad20332fc7ca1250887703a6e132f4 Mon Sep 17 00:00:00 2001 From: Cecilia Nilsson Date: Thu, 16 Apr 2020 17:30:25 +0200 Subject: [PATCH 01/35] change from stopifnot to assert_that --- R/get_param.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/get_param.R b/R/get_param.R index 00d83319c..9405bb444 100644 --- a/R/get_param.R +++ b/R/get_param.R @@ -14,7 +14,7 @@ #' my_param <- get_param(example_scan, "VRADH") #' my_param get_param <- function(x, param) { - stopifnot(inherits(x, "scan")) - if (!(param %in% names(x$params))) stop(paste("scan parameter", param, "not found")) + assert_that(class(x) == "scan", msg = "`x` must be a scan object.") + if (!(param %in% names(x$params))) stop(paste("Scan parameter", param, "not found in `x`.")) x$params[[param]] } From af5c919129360965d9e38bd52d5dfd3066cd0039 Mon Sep 17 00:00:00 2001 From: Cecilia Nilsson Date: Thu, 16 Apr 2020 17:30:44 +0200 Subject: [PATCH 02/35] documentation updates --- R/get_param.R | 8 ++++---- man/get_param.Rd | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/get_param.R b/R/get_param.R index 9405bb444..5b494ab05 100644 --- a/R/get_param.R +++ b/R/get_param.R @@ -1,9 +1,9 @@ -#' Get a scan parameter (\code{param}) from a scan (\code{scan}) +#' Get a scan parameter `param` from a scan `scan` #' -#' @param x An object of class \code{scan}. -#' @param param a scan parameter +#' @param x An object of class `scan`. +#' @param param A scan parameter. #' -#' @return An object of class '\link[=summary.param]{param}'. +#' @return An object of class [param][summary.param]. #' #' @export #' @examples diff --git a/man/get_param.Rd b/man/get_param.Rd index 1e37f2fc2..4c5b10813 100644 --- a/man/get_param.Rd +++ b/man/get_param.Rd @@ -2,20 +2,20 @@ % Please edit documentation in R/get_param.R \name{get_param} \alias{get_param} -\title{Get a scan parameter (\code{param}) from a scan (\code{scan})} +\title{Get a scan parameter \code{param} from a scan \code{scan}} \usage{ get_param(x, param) } \arguments{ \item{x}{An object of class \code{scan}.} -\item{param}{a scan parameter} +\item{param}{A scan parameter.} } \value{ -An object of class '\link[=summary.param]{param}'. +An object of class \link[=summary.param]{param}. } \description{ -Get a scan parameter (\code{param}) from a scan (\code{scan}) +Get a scan parameter \code{param} from a scan \code{scan} } \examples{ # we will extract a scan parameter from the example scan object: From cc4ad27b3e9f1ef4394090cd690f280f7d783b83 Mon Sep 17 00:00:00 2001 From: Cecilia Nilsson Date: Thu, 16 Apr 2020 17:31:06 +0200 Subject: [PATCH 03/35] Unit tests for get_parm --- tests/testthat/test-get_param.R | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/testthat/test-get_param.R b/tests/testthat/test-get_param.R index 1d86f1072..feb6358cc 100644 --- a/tests/testthat/test-get_param.R +++ b/tests/testthat/test-get_param.R @@ -1,3 +1,17 @@ +pvolfile <- system.file("extdata", "volume.h5", package = "bioRad") +pvol <- read_pvolfile(pvolfile) +scan <- pvol$scans[[1]] + test_that("returns error on incorrect parameters", { + expect_error(get_param("not_a_scan"), "`x` must be a scan object.") + expect_error(get_param(vp),"`x` must be a scan object.") + expect_error(get_param(pvol),"`x` must be a scan object.") + expect_error(get_param(scan)) + expect_error(get_param(scan, "not_a_param"), "Scan parameter not_a_param not found in `x`.") +}) +test_that("get_param returns correct parameters", { + expect_equal(get_param(scan, names(scan$params[1])), scan$params[[1]]) + expect_equal(get_param(scan, names(scan$params[2])), scan$params[[2]]) }) + From fe7c7d6c700ed793a7e2fe8e5357475c60c2dbf4 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Fri, 24 Apr 2020 13:29:11 +0200 Subject: [PATCH 04/35] Move code for as.data.frame to own file Move test as well --- R/as.data.frame.R | 240 ++++++++++++++++++++++++++++ R/vp.R | 117 -------------- R/vpts.R | 124 -------------- man/as.data.frame.vp.Rd | 2 +- man/as.data.frame.vpts.Rd | 2 +- tests/testthat/test-as.data.frame.R | 129 +++++++++++++++ tests/testthat/test-vp.R | 128 +-------------- 7 files changed, 372 insertions(+), 370 deletions(-) create mode 100644 R/as.data.frame.R create mode 100644 tests/testthat/test-as.data.frame.R diff --git a/R/as.data.frame.R b/R/as.data.frame.R new file mode 100644 index 000000000..2e70851d3 --- /dev/null +++ b/R/as.data.frame.R @@ -0,0 +1,240 @@ +#' Convert a vertical profile (\code{vp}) to a Data Frame +#' +#' Converts a vertical profile to a Data Frame, and optionally adds information +#' on sunrise/sunset, day/night and derived quantities like migration +#' traffic rates. +#' +#' @param x An object of class \code{vp}. +#' @param row.names \code{NULL} or a character vector giving the row names for +#' the data frame. Missing values are not allowed. See [base::as.data.frame()]. +#' @param optional If \code{FALSE} then the names of the variables in the data +#' frame are checked to ensure that they are syntactically valid variable names +#' and are not duplicated. +#' @param quantities An optional character vector with the names of the +#' quantities to include as columns in the data frame. +#' @param elev Sun elevation in degrees, see \link{sunrise}/\link{sunset}. +#' @param lat Radar latitude in decimal degrees. When set, overrides the +#' latitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations +#' @param lon Radar longitude in decimal degrees. When set, overrides the +#' longitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations. +#' @param suntime Logical, when \code{TRUE}, adds sunrise/sunset and day/night +#' information to each row. +#' @param geo Logical, when \code{TRUE}, adds latitude, longitude and antenna +#' height of the radar to each row. +#' @param ... Additional arguments to be passed to or from methods. +#' +#' @return An object of class \code{data.frame}. +#' +#' @export +#' +#' @details +#' Note that only the "dens" quantity is thresholded for radial velocity +#' standard deviation by \link{sd_vvp_threshold}. Note that this is different from the +#' default \link{plot.vp}, \link{plot.vpts} and \link{get_quantity.vp} +#' functions, where quantities "eta", "dbz", "ff", "u", "v", "w", "dd" are +#' all thresholded by \link{sd_vvp_threshold} +#' +#' @examples +#' # Load the example vertical profile +#' vp <- example_vp +#' +#' # Convert to a data.frame +#' vp_df <- as.data.frame(vp) +#' +#' # Print data.frame +#' vp_df +#' +#' # Do not compute sunrise/sunset information +#' vp_df <- as.data.frame(vp, suntime = FALSE) +#' +#' # Override the latitude/longitude information stored in the object when +#' # calculating sunrise/sunset information +#' vp_df <- as.data.frame(vp, suntime = TRUE, lat = 50, lon = 4) +as.data.frame.vp <- function(x, row.names = NULL, optional = FALSE, + quantities = names(x$data), suntime = TRUE, + geo = TRUE, elev = -0.268, lat = NULL, + lon = NULL, ...) { + stopifnot(inherits(x, "vp")) + if (!is.null(row.names)) { + if (is.character(row.names) & length(row.names) == + length(x$datetime) * length(x$height)) { + rownames(output) <- row.names + } else { + stop(paste( + "`row.names` is not a character vector of length", + length(x$datetime) * length(x$height) + )) + } + } + if (is.null(lat)) { + lat <- x$attributes$where$lat + } + if (is.null(lon)) { + lon <- x$attributes$where$lon + } + missing <- which(!(quantities %in% names(x$data))) + if (length(missing) > 0) { + stop(paste( + paste(quantities[missing], collapse = " "), + "not an available quantity, select one or more of", + paste(names(x$data), collapse = ",") + )) + } + # coerce data to a data frame + output <- as.data.frame(x$data, optional = optional, ...) + # add height and datetime as a column + output <- cbind(datetime = x$datetime, height = output$height, output) + output$height <- NULL + # add radar name + output <- cbind(radar = x$radar, output, stringsAsFactors = FALSE) + # add location information + if (geo) { + output$lat <- lat + output$lon <- lon + output$height_antenna <- x$attributes$where$height + } + # override the lat,lon attributes in case of user-provided values + x$attributes$where$lat <- lat + x$attributes$where$lon <- lon + # add day + if (suntime) { + dayQ <- !check_night(x, elev = elev) + dayQ <- c(t(replicate(nrow(x), dayQ))) + output <- cbind(output, day = dayQ) + sunrise <- sunrise(x$datetime, lat = lat, lon = lon) + sunset <- sunset(x$datetime, lat = lat, lon = lon) + output$sunrise <- as.POSIXct( + c(t(replicate(nrow(x), sunrise))), + origin = "1970-1-1", tz = "UTC" + ) + output$sunset <- as.POSIXct( + c(t(replicate(nrow(x), sunset))), + origin = "1970-1-1", tz = "UTC" + ) + } + output +} + +#' Convert a time series of vertical profiles (\code{vpts}) to a data frame +#' +#' Converts vertical profile time series (objects of class \code{vpts}) to a +#' data Frame, and optionally adds information on sunrise/sunset, day/night +#' and derived quantities like migration traffic rates. +#' +#' @param x An object of class \code{vpts}. +#' @param row.names \code{NULL} or a character vector giving the row names for +#' the data frame. Missing values are not allowed. +#' @param optional If \code{FALSE} then the names of the variables in the data +#' frame are checked to ensure that they are syntactically valid variable names +#' and are not duplicated. +#' @param quantities An optional character vector with the names of the +#' quantities to include as columns in the data frame. +#' @param elev Sun elevation in degrees, see \link{sunrise}/\link{sunset}. +#' @param lat Radar latitude in decimal degrees. When set, overrides the +#' latitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations. +#' @param lon Radar longitude in decimal degrees. When set, overrides the +#' longitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations. +#' @param suntime Logical, when TRUE, adds sunrise/sunset and day/night +#' information to each row. +#' @param geo Logical, when TRUE, adds latitude, longitude and antenna height +#' of the radar to each row. +#' @param ... Additional arguments to be passed to or from methods. +#' +#' @return An object of class data.frame. +#' +#' @export +#' +#' @details +#' Note that only the 'dens' quantity is thresholded for radial velocity +#' standard deviation by \link{sd_vvp_threshold}. Note that this is different from the +#' default \link{plot.vp}, \link{plot.vpts} and \link{get_quantity.vp} +#' functions, where quantities "eta", "dbz", "ff", "u", "v", "w", "dd" are all +#' thresholded by \link{sd_vvp_threshold}. +#' +#' @examples +#' # Load the example time series of vertical profiles +#' vpts <- example_vpts +#' +#' # Convert to a data.frame +#' vpts_df <- as.data.frame(vpts) +#' +#' # Print the first 10 rows of the data.frame +#' vpts_df[1:10, ] +#' +#' # Do not compute sunrise/sunset information +#' vpts_df <- as.data.frame(vpts, suntime = FALSE) +#' +#' # Override the latitude/longitude information stored in the object when +#' # calculating sunrise/sunset information +#' vpts_df <- as.data.frame(vpts, suntime = TRUE, lat = 50, lon = 4) +as.data.frame.vpts <- function(x, row.names = NULL, optional = FALSE, + quantities = names(x$data), suntime = TRUE, + geo = TRUE, elev = -0.268, lat = NULL, + lon = NULL, ...) { + stopifnot(inherits(x, "vpts")) + if (!is.null(row.names)) { + if (is.character(row.names) & length(row.names) == + length(x$datetime) * length(x$height)) { + rownames(output) <- row.names + } else { + stop(paste( + "'row.names' is not a character vector of length", + length(x$datetime) * length(x$height) + )) + } + } + if (is.null(lat)) { + lat <- x$attributes$where$lat + } + if (is.null(lon)) { + lon <- x$attributes$where$lon + } + missing <- which(!(quantities %in% names(x$data))) + if (length(missing) > 0) { + stop(paste( + paste(quantities[missing], collapse = " "), + "not an available quantity, select one or more of", + paste(names(x$data), collapse = ",") + )) + } + # coerce data to a data frame + output <- as.data.frame(lapply(x$data[quantities], c), + optional = optional, ... + ) + # add height and datetime as a column + output <- cbind( + datetime = as.POSIXct( + c(t(replicate(length(x$height), x$datetime))), + origin = "1970-1-1", tz = "UTC" + ), + height = rep(x$height, length(x$datetime)), output + ) + # add radar name + output <- cbind(radar = x$radar, output, stringsAsFactors = FALSE) + # add location information + if (geo) { + output$lat <- lat + output$lon <- lon + output$height_antenna <- x$attributes$where$height + } + # override the lat,lon attributes in case of user-provided values + x$attributes$where$lat <- lat + x$attributes$where$lon <- lon + # add day + if (suntime) { + dayQ <- !check_night(x, elev = elev) + dayQ <- c(t(replicate(length(x$height), dayQ))) + output <- cbind(output, day = dayQ) + sunrise <- sunrise(x$datetime, lat = lat, lon = lon) + sunset <- sunset(x$datetime, lat = lat, lon = lon) + output$sunrise <- as.POSIXct( + c(t(replicate(length(x$height), sunrise))), + origin = "1970-1-1", tz = "UTC" + ) + output$sunset <- as.POSIXct( + c(t(replicate(length(x$height), sunset))), + origin = "1970-1-1", tz = "UTC" + ) + } + output +} diff --git a/R/vp.R b/R/vp.R index 1bf9f2ba2..029437774 100644 --- a/R/vp.R +++ b/R/vp.R @@ -136,123 +136,6 @@ dim.vp <- function(x) { dim(x$data) } -#' Convert a vertical profile (\code{vp}) to a Data Frame -#' -#' Converts a vertical profile to a Data Frame, and optionally adds information -#' on sunrise/sunset, day/night and derived quantities like migration -#' traffic rates. -#' -#' @param x An object of class \code{vp}. -#' @param row.names \code{NULL} or a character vector giving the row names for -#' the data frame. Missing values are not allowed. See [base::as.data.frame()]. -#' @param optional If \code{FALSE} then the names of the variables in the data -#' frame are checked to ensure that they are syntactically valid variable names -#' and are not duplicated. -#' @param quantities An optional character vector with the names of the -#' quantities to include as columns in the data frame. -#' @param elev Sun elevation in degrees, see \link{sunrise}/\link{sunset}. -#' @param lat Radar latitude in decimal degrees. When set, overrides the -#' latitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations -#' @param lon Radar longitude in decimal degrees. When set, overrides the -#' longitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations. -#' @param suntime Logical, when \code{TRUE}, adds sunrise/sunset and day/night -#' information to each row. -#' @param geo Logical, when \code{TRUE}, adds latitude, longitude and antenna -#' height of the radar to each row. -#' @param ... Additional arguments to be passed to or from methods. -#' -#' @return An object of class \code{data.frame}. -#' -#' @export -#' -#' @details -#' Note that only the "dens" quantity is thresholded for radial velocity -#' standard deviation by \link{sd_vvp_threshold}. Note that this is different from the -#' default \link{plot.vp}, \link{plot.vpts} and \link{get_quantity.vp} -#' functions, where quantities "eta", "dbz", "ff", "u", "v", "w", "dd" are -#' all thresholded by \link{sd_vvp_threshold} -#' -#' @examples -#' # Load the example vertical profile -#' vp <- example_vp -#' -#' # Convert to a data.frame -#' vp_df <- as.data.frame(vp) -#' -#' # Print data.frame -#' vp_df -#' -#' # Do not compute sunrise/sunset information -#' vp_df <- as.data.frame(vp, suntime = FALSE) -#' -#' # Override the latitude/longitude information stored in the object when -#' # calculating sunrise/sunset information -#' vp_df <- as.data.frame(vp, suntime = TRUE, lat = 50, lon = 4) -as.data.frame.vp <- function(x, row.names = NULL, optional = FALSE, - quantities = names(x$data), suntime = TRUE, - geo = TRUE, elev = -0.268, lat = NULL, - lon = NULL, ...) { - stopifnot(inherits(x, "vp")) - if (!is.null(row.names)) { - if (is.character(row.names) & length(row.names) == - length(x$datetime) * length(x$height)) { - rownames(output) <- row.names - } else { - stop(paste( - "`row.names` is not a character vector of length", - length(x$datetime) * length(x$height) - )) - } - } - if (is.null(lat)) { - lat <- x$attributes$where$lat - } - if (is.null(lon)) { - lon <- x$attributes$where$lon - } - missing <- which(!(quantities %in% names(x$data))) - if (length(missing) > 0) { - stop(paste( - paste(quantities[missing], collapse = " "), - "not an available quantity, select one or more of", - paste(names(x$data), collapse = ",") - )) - } - # coerce data to a data frame - output <- as.data.frame(x$data, optional = optional, ...) - # add height and datetime as a column - output <- cbind(datetime = x$datetime, height = output$height, output) - output$height <- NULL - # add radar name - output <- cbind(radar = x$radar, output, stringsAsFactors = FALSE) - # add location information - if (geo) { - output$lat <- lat - output$lon <- lon - output$height_antenna <- x$attributes$where$height - } - # override the lat,lon attributes in case of user-provided values - x$attributes$where$lat <- lat - x$attributes$where$lon <- lon - # add day - if (suntime) { - dayQ <- !check_night(x, elev = elev) - dayQ <- c(t(replicate(nrow(x), dayQ))) - output <- cbind(output, day = dayQ) - sunrise <- sunrise(x$datetime, lat = lat, lon = lon) - sunset <- sunset(x$datetime, lat = lat, lon = lon) - output$sunrise <- as.POSIXct( - c(t(replicate(nrow(x), sunrise))), - origin = "1970-1-1", tz = "UTC" - ) - output$sunset <- as.POSIXct( - c(t(replicate(nrow(x), sunset))), - origin = "1970-1-1", tz = "UTC" - ) - } - output -} - #' Concatenate vertical profiles (`vp`) into a list of vertical profiles #' #' Concatenates vertical profiles (`vp`) into a list of vertical profiles diff --git a/R/vpts.R b/R/vpts.R index 3553c0fc6..39221ca55 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -202,130 +202,6 @@ dim.vpts <- function(x) { return(x) } -#' Convert a time series of vertical profiles (\code{vpts}) to a data frame -#' -#' Converts vertical profile time series (objects of class \code{vpts}) to a -#' data Frame, and optionally adds information on sunrise/sunset, day/night -#' and derived quantities like migration traffic rates. -#' -#' @param x An object of class \code{vpts}. -#' @param row.names \code{NULL} or a character vector giving the row names for -#' the data frame. Missing values are not allowed. -#' @param optional If \code{FALSE} then the names of the variables in the data -#' frame are checked to ensure that they are syntactically valid variable names -#' and are not duplicated. -#' @param quantities An optional character vector with the names of the -#' quantities to include as columns in the data frame. -#' @param elev Sun elevation in degrees, see \link{sunrise}/\link{sunset}. -#' @param lat Radar latitude in decimal degrees. When set, overrides the -#' latitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations. -#' @param lon Radar longitude in decimal degrees. When set, overrides the -#' longitude stored in \code{x} in \link{sunrise}/\link{sunset} calculations. -#' @param suntime Logical, when TRUE, adds sunrise/sunset and day/night -#' information to each row. -#' @param geo Logical, when TRUE, adds latitude, longitude and antenna height -#' of the radar to each row. -#' @param ... Additional arguments to be passed to or from methods. -#' -#' @return An object of class data.frame. -#' -#' @export -#' -#' @details -#' Note that only the 'dens' quantity is thresholded for radial velocity -#' standard deviation by \link{sd_vvp_threshold}. Note that this is different from the -#' default \link{plot.vp}, \link{plot.vpts} and \link{get_quantity.vp} -#' functions, where quantities "eta", "dbz", "ff", "u", "v", "w", "dd" are all -#' thresholded by \link{sd_vvp_threshold}. -#' -#' @examples -#' # Load the example time series of vertical profiles -#' vpts <- example_vpts -#' -#' # Convert to a data.frame -#' vpts_df <- as.data.frame(vpts) -#' -#' # Print the first 10 rows of the data.frame -#' vpts_df[1:10, ] -#' -#' # Do not compute sunrise/sunset information -#' vpts_df <- as.data.frame(vpts, suntime = FALSE) -#' -#' # Override the latitude/longitude information stored in the object when -#' # calculating sunrise/sunset information -#' vpts_df <- as.data.frame(vpts, suntime = TRUE, lat = 50, lon = 4) -as.data.frame.vpts <- function(x, row.names = NULL, optional = FALSE, - quantities = names(x$data), suntime = TRUE, - geo = TRUE, elev = -0.268, lat = NULL, - lon = NULL, ...) { - stopifnot(inherits(x, "vpts")) - if (!is.null(row.names)) { - if (is.character(row.names) & length(row.names) == - length(x$datetime) * length(x$height)) { - rownames(output) <- row.names - } else { - stop(paste( - "'row.names' is not a character vector of length", - length(x$datetime) * length(x$height) - )) - } - } - if (is.null(lat)) { - lat <- x$attributes$where$lat - } - if (is.null(lon)) { - lon <- x$attributes$where$lon - } - missing <- which(!(quantities %in% names(x$data))) - if (length(missing) > 0) { - stop(paste( - paste(quantities[missing], collapse = " "), - "not an available quantity, select one or more of", - paste(names(x$data), collapse = ",") - )) - } - # coerce data to a data frame - output <- as.data.frame(lapply(x$data[quantities], c), - optional = optional, ... - ) - # add height and datetime as a column - output <- cbind( - datetime = as.POSIXct( - c(t(replicate(length(x$height), x$datetime))), - origin = "1970-1-1", tz = "UTC" - ), - height = rep(x$height, length(x$datetime)), output - ) - # add radar name - output <- cbind(radar = x$radar, output, stringsAsFactors = FALSE) - # add location information - if (geo) { - output$lat <- lat - output$lon <- lon - output$height_antenna <- x$attributes$where$height - } - # override the lat,lon attributes in case of user-provided values - x$attributes$where$lat <- lat - x$attributes$where$lon <- lon - # add day - if (suntime) { - dayQ <- !check_night(x, elev = elev) - dayQ <- c(t(replicate(length(x$height), dayQ))) - output <- cbind(output, day = dayQ) - sunrise <- sunrise(x$datetime, lat = lat, lon = lon) - sunset <- sunset(x$datetime, lat = lat, lon = lon) - output$sunrise <- as.POSIXct( - c(t(replicate(length(x$height), sunrise))), - origin = "1970-1-1", tz = "UTC" - ) - output$sunset <- as.POSIXct( - c(t(replicate(length(x$height), sunset))), - origin = "1970-1-1", tz = "UTC" - ) - } - output -} - vpts_to_vp <- function(x, i) { stopifnot(inherits(x, "vpts")) nvp <- dim(x)[2] diff --git a/man/as.data.frame.vp.Rd b/man/as.data.frame.vp.Rd index fbff1fba7..396dd8cfd 100644 --- a/man/as.data.frame.vp.Rd +++ b/man/as.data.frame.vp.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vp.R +% Please edit documentation in R/as.data.frame.R \name{as.data.frame.vp} \alias{as.data.frame.vp} \title{Convert a vertical profile (\code{vp}) to a Data Frame} diff --git a/man/as.data.frame.vpts.Rd b/man/as.data.frame.vpts.Rd index 87dad7fa2..6f607d0ef 100644 --- a/man/as.data.frame.vpts.Rd +++ b/man/as.data.frame.vpts.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vpts.R +% Please edit documentation in R/as.data.frame.R \name{as.data.frame.vpts} \alias{as.data.frame.vpts} \title{Convert a time series of vertical profiles (\code{vpts}) to a data frame} diff --git a/tests/testthat/test-as.data.frame.R b/tests/testthat/test-as.data.frame.R new file mode 100644 index 000000000..527305d0a --- /dev/null +++ b/tests/testthat/test-as.data.frame.R @@ -0,0 +1,129 @@ +vp <- example_vp + +test_that("as.data.frame() returns error on incorrect parameters", { + expect_error(as.data.frame(vp, row.names = "not_a_vector")) + expect_error( + as.data.frame(vp, quantities = c("not_a_quantity")), + "select one or more of ff,dbz" # Full message is a list of all quantities + ) + expect_error(as.data.frame(vp, suntime = "not_a_logical")) + expect_error(as.data.frame(vp, geo = "not_a_logical")) + expect_error(as.data.frame(vp, elev = "not_a_double")) + expect_error(as.data.frame(vp, lat = "not_a_double")) + expect_error(as.data.frame(vp, lon = "not_a_double")) +}) + +test_that("as.data.frame() returns a data frame", { + expect_is(as.data.frame(vp), "data.frame") +}) + +test_that("as.data.frame() returns correct number of rows/cols", { + df <- as.data.frame(vp) + expect_equal(nrow(df), 25) # 25 rows in nrow(vp$data) + expect_gte(ncol(df), 16) # 16 cols in ncol(vp$data), but extra added by bioRad +}) + +test_that("as.data.frame() returns the expected column names", { + expected_col_names <- c( + "radar", "datetime", "ff", "dbz", "dens", "u", "v", "gap", "w", "n_dbz", + "dd", "n", "DBZH", "height", "n_dbz_all", "eta", "sd_vvp", "n_all", "lat", + "lon", "height_antenna", "day", "sunrise", "sunset" + ) + expect_equal(names(as.data.frame(vp)), expected_col_names) +}) + +test_that("as.data.frame() returns the correct data", { + df <- as.data.frame(example_vp) + + expect_equal(unique(df[["radar"]]), "seang") # One unique radar + expect_equal(as.character(unique(df[["datetime"]])), "2015-10-18 18:00:00") # One unique timestamp + + # Check a few randomly selected values (coming directly from the source data): + expect_equal(df$height[1], 0) + expect_equal(df$height[8], 1400) + expect_equal(df$ff[4], 13.77482, tolerance = 0.001) + expect_equal(df$dens[10], 17.3985100, tolerance = 0.001) + expect_equal(is.na(df$sd_vvp[1]), TRUE) + expect_equal(df$sd_vvp[13], 2.994742, tolerance = 0.001) +}) + +test_that("as.data.frame() includes lat/lon/height_antenna and can be assigned, unless geo = FALSE", { + # lat/lon/height_antenna columns are added by default and taken from metadata + df <- as.data.frame(example_vp) + expect_equal(unique(df[["lat"]]), example_vp$attributes$where$lat) + expect_equal(unique(df[["lon"]]), example_vp$attributes$where$lon) + expect_equal(unique(df[["height_antenna"]]), example_vp$attributes$where$height) + + # lat/lon/height_antenna columns are missing if geo = FALSE + df_geo_false <- as.data.frame(example_vp, geo = FALSE) + expect_null(df_geo_false$lat) + expect_null(df_geo_false$lon) + expect_null(df_geo_false$height_antenna) + + # lat/lon can be set explicitly + df_latlong <- as.data.frame(example_vp, lat = 50.6472, lon = 4.3603) + expect_equal(unique(df_latlong[["lat"]]), 50.6472) + expect_equal(unique(df_latlong[["lon"]]), 4.3603) +}) + + +test_that("as.data.frame() includes sunset/sunrise/day cols, unless suntime = FALSE", { + # sunset/sunrise/day columns are added by default + df <- as.data.frame(example_vp) + expect_is(df$sunset, "POSIXct") + expect_is(df$sunrise, "POSIXct") + expect_is(df$day, "logical") + + # sunset/sunrise/day columns are missing if suntime = FALSE + df_suntime_false <- as.data.frame(example_vp, suntime = FALSE) + expect_null(df_suntime_false$sunset) + expect_null(df_suntime_false$sunrise) + expect_null(df_suntime_false$day) + } +) + +test_that("as.data.frame() values in suntime/sunset/day cols are correct and updated with lat/lon", { + # Note: timestamp for example_vp is 2015-10-18 18:00:00 UTC + + # 1. Check for lat/long contained in example_vp: 56.3675, 12.8517 + df <- as.data.frame(example_vp) + + # Manual data check on: https://www.suncalc.org/#/56.3675,12.8517,12/2015.10.18/09:00/1/3 + expected_sunrise <- as.POSIXlt("2015-10-18 05:45:26", tz = "UTC") # 07:45:26 UTC+2 + expected_sunset <- as.POSIXlt("2015-10-18 16:01:13", tz = "UTC") # 18:01:13 UTC+2 + + expect_equal(as.POSIXlt(df$sunrise[1]), expected_sunrise, tolerance = 5) # Tolerance: minutes + expect_equal(as.POSIXlt(df$sunset[1]), expected_sunset, tolerance = 5) + expect_false(df$day[1]) # At the 18:00:00 UTC timestamp, it is night + + # 2. Set lat/lon to other values and check if it's still correct + df <- as.data.frame(example_vp, lat = 50.6472, lon = 4.3603) + + # Manual data check on: https://www.suncalc.org/#/50.6472,4.3603,12/2015.10.18/09:00/1/3 + expected_sunrise <- as.POSIXlt("2015-10-18 06:09:09", tz = "UTC") # 08:09:09 UTC+2 + expected_sunset <- as.POSIXlt("2015-10-18 16:45:35", tz = "UTC") # 18:45:35 UTC+2 + + expect_equal(as.POSIXlt(df$sunrise[1]), expected_sunrise, tolerance = 5) + expect_equal(as.POSIXlt(df$sunset[1]), expected_sunset, tolerance = 5) + expect_false(df$day[1]) # At the 18:00:00 UTC timestamp, it is night + + # 3. Let's go to Antartica, it should be day there + df <- as.data.frame(example_vp, lat = -74.2486, lon = -1.2497) + expect_true(df$day[1]) +}) + +test_that("as.data.frame() allows to select quantities", { + df <- as.data.frame(example_vp, quantities = c("dens", "ff")) + expect_is(df$dens, "numeric") + expect_is(df$ff, "numeric") + + # FIXME: If we only request "dens", shouldn't "dd" be missing? + # expect_null(df$dd) + + # We get a proper error message if requesting a nonexistent quantity + +}) + +# TODO: test "row.names" parameter +# TODO: test "optional" parameter +# TODO: test "elev" parameter diff --git a/tests/testthat/test-vp.R b/tests/testthat/test-vp.R index 527305d0a..9a07aa619 100644 --- a/tests/testthat/test-vp.R +++ b/tests/testthat/test-vp.R @@ -1,129 +1,3 @@ -vp <- example_vp +test_that("... returns error on incorrect parameters", { -test_that("as.data.frame() returns error on incorrect parameters", { - expect_error(as.data.frame(vp, row.names = "not_a_vector")) - expect_error( - as.data.frame(vp, quantities = c("not_a_quantity")), - "select one or more of ff,dbz" # Full message is a list of all quantities - ) - expect_error(as.data.frame(vp, suntime = "not_a_logical")) - expect_error(as.data.frame(vp, geo = "not_a_logical")) - expect_error(as.data.frame(vp, elev = "not_a_double")) - expect_error(as.data.frame(vp, lat = "not_a_double")) - expect_error(as.data.frame(vp, lon = "not_a_double")) }) - -test_that("as.data.frame() returns a data frame", { - expect_is(as.data.frame(vp), "data.frame") -}) - -test_that("as.data.frame() returns correct number of rows/cols", { - df <- as.data.frame(vp) - expect_equal(nrow(df), 25) # 25 rows in nrow(vp$data) - expect_gte(ncol(df), 16) # 16 cols in ncol(vp$data), but extra added by bioRad -}) - -test_that("as.data.frame() returns the expected column names", { - expected_col_names <- c( - "radar", "datetime", "ff", "dbz", "dens", "u", "v", "gap", "w", "n_dbz", - "dd", "n", "DBZH", "height", "n_dbz_all", "eta", "sd_vvp", "n_all", "lat", - "lon", "height_antenna", "day", "sunrise", "sunset" - ) - expect_equal(names(as.data.frame(vp)), expected_col_names) -}) - -test_that("as.data.frame() returns the correct data", { - df <- as.data.frame(example_vp) - - expect_equal(unique(df[["radar"]]), "seang") # One unique radar - expect_equal(as.character(unique(df[["datetime"]])), "2015-10-18 18:00:00") # One unique timestamp - - # Check a few randomly selected values (coming directly from the source data): - expect_equal(df$height[1], 0) - expect_equal(df$height[8], 1400) - expect_equal(df$ff[4], 13.77482, tolerance = 0.001) - expect_equal(df$dens[10], 17.3985100, tolerance = 0.001) - expect_equal(is.na(df$sd_vvp[1]), TRUE) - expect_equal(df$sd_vvp[13], 2.994742, tolerance = 0.001) -}) - -test_that("as.data.frame() includes lat/lon/height_antenna and can be assigned, unless geo = FALSE", { - # lat/lon/height_antenna columns are added by default and taken from metadata - df <- as.data.frame(example_vp) - expect_equal(unique(df[["lat"]]), example_vp$attributes$where$lat) - expect_equal(unique(df[["lon"]]), example_vp$attributes$where$lon) - expect_equal(unique(df[["height_antenna"]]), example_vp$attributes$where$height) - - # lat/lon/height_antenna columns are missing if geo = FALSE - df_geo_false <- as.data.frame(example_vp, geo = FALSE) - expect_null(df_geo_false$lat) - expect_null(df_geo_false$lon) - expect_null(df_geo_false$height_antenna) - - # lat/lon can be set explicitly - df_latlong <- as.data.frame(example_vp, lat = 50.6472, lon = 4.3603) - expect_equal(unique(df_latlong[["lat"]]), 50.6472) - expect_equal(unique(df_latlong[["lon"]]), 4.3603) -}) - - -test_that("as.data.frame() includes sunset/sunrise/day cols, unless suntime = FALSE", { - # sunset/sunrise/day columns are added by default - df <- as.data.frame(example_vp) - expect_is(df$sunset, "POSIXct") - expect_is(df$sunrise, "POSIXct") - expect_is(df$day, "logical") - - # sunset/sunrise/day columns are missing if suntime = FALSE - df_suntime_false <- as.data.frame(example_vp, suntime = FALSE) - expect_null(df_suntime_false$sunset) - expect_null(df_suntime_false$sunrise) - expect_null(df_suntime_false$day) - } -) - -test_that("as.data.frame() values in suntime/sunset/day cols are correct and updated with lat/lon", { - # Note: timestamp for example_vp is 2015-10-18 18:00:00 UTC - - # 1. Check for lat/long contained in example_vp: 56.3675, 12.8517 - df <- as.data.frame(example_vp) - - # Manual data check on: https://www.suncalc.org/#/56.3675,12.8517,12/2015.10.18/09:00/1/3 - expected_sunrise <- as.POSIXlt("2015-10-18 05:45:26", tz = "UTC") # 07:45:26 UTC+2 - expected_sunset <- as.POSIXlt("2015-10-18 16:01:13", tz = "UTC") # 18:01:13 UTC+2 - - expect_equal(as.POSIXlt(df$sunrise[1]), expected_sunrise, tolerance = 5) # Tolerance: minutes - expect_equal(as.POSIXlt(df$sunset[1]), expected_sunset, tolerance = 5) - expect_false(df$day[1]) # At the 18:00:00 UTC timestamp, it is night - - # 2. Set lat/lon to other values and check if it's still correct - df <- as.data.frame(example_vp, lat = 50.6472, lon = 4.3603) - - # Manual data check on: https://www.suncalc.org/#/50.6472,4.3603,12/2015.10.18/09:00/1/3 - expected_sunrise <- as.POSIXlt("2015-10-18 06:09:09", tz = "UTC") # 08:09:09 UTC+2 - expected_sunset <- as.POSIXlt("2015-10-18 16:45:35", tz = "UTC") # 18:45:35 UTC+2 - - expect_equal(as.POSIXlt(df$sunrise[1]), expected_sunrise, tolerance = 5) - expect_equal(as.POSIXlt(df$sunset[1]), expected_sunset, tolerance = 5) - expect_false(df$day[1]) # At the 18:00:00 UTC timestamp, it is night - - # 3. Let's go to Antartica, it should be day there - df <- as.data.frame(example_vp, lat = -74.2486, lon = -1.2497) - expect_true(df$day[1]) -}) - -test_that("as.data.frame() allows to select quantities", { - df <- as.data.frame(example_vp, quantities = c("dens", "ff")) - expect_is(df$dens, "numeric") - expect_is(df$ff, "numeric") - - # FIXME: If we only request "dens", shouldn't "dd" be missing? - # expect_null(df$dd) - - # We get a proper error message if requesting a nonexistent quantity - -}) - -# TODO: test "row.names" parameter -# TODO: test "optional" parameter -# TODO: test "elev" parameter From 186b73d76c71a143e50086d01754e32251d82a4a Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 11:38:56 +0200 Subject: [PATCH 05/35] Write summary.pvol, print.pvol, is.pvol tests --- tests/testthat/test-pvol.R | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-pvol.R b/tests/testthat/test-pvol.R index 9a07aa619..aae7b1d93 100644 --- a/tests/testthat/test-pvol.R +++ b/tests/testthat/test-pvol.R @@ -1,3 +1,24 @@ -test_that("... returns error on incorrect parameters", { +pvolfile <- system.file("extdata", "volume.h5", package = "bioRad") +pvol <- read_pvolfile(pvolfile) +vp <- example_vp +# No tests for error on incorrect parameters: +# summary(), print() are generic and work for every input +# is.pvol() returns TRUE/FALSE and works for every input + +# print.pvol() is not tested as it is the same as and called from summary.pvol() + +test_that("summary.pvol() prints metadata to the console", { + expect_output(summary(pvol), "Polar volume (class pvol)", fixed = TRUE) + expect_output(summary(pvol), "# scans:", fixed = TRUE) + expect_output(summary(pvol), "radar:", fixed = TRUE) + expect_output(summary(pvol), "source:", fixed = TRUE) + expect_output(summary(pvol), "nominal time:", fixed = TRUE) + +}) + +test_that("is.pvol() returns TRUE/FALSE correctly", { + expect_true(is.pvol(pvol)) + expect_false(is.pvol("not_a_pvol")) + expect_false(is.pvol(vp)) }) From 9638e1f5c33c15d164543c537db2d3c208a20fdd Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 12:22:35 +0200 Subject: [PATCH 06/35] Write tests for summary.scan, print.scan, is.scan, dim.scan --- tests/testthat/test-pvol.R | 3 +-- tests/testthat/test-scan.R | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-pvol.R b/tests/testthat/test-pvol.R index aae7b1d93..0a6a9e59a 100644 --- a/tests/testthat/test-pvol.R +++ b/tests/testthat/test-pvol.R @@ -6,9 +6,8 @@ vp <- example_vp # summary(), print() are generic and work for every input # is.pvol() returns TRUE/FALSE and works for every input -# print.pvol() is not tested as it is the same as and called from summary.pvol() - test_that("summary.pvol() prints metadata to the console", { + # print.pvol() is not tested as it is the same as and called from summary.pvol() expect_output(summary(pvol), "Polar volume (class pvol)", fixed = TRUE) expect_output(summary(pvol), "# scans:", fixed = TRUE) expect_output(summary(pvol), "radar:", fixed = TRUE) diff --git a/tests/testthat/test-scan.R b/tests/testthat/test-scan.R index 9a07aa619..955eb90e0 100644 --- a/tests/testthat/test-scan.R +++ b/tests/testthat/test-scan.R @@ -1,3 +1,26 @@ -test_that("... returns error on incorrect parameters", { +scan <- example_scan +vp <- example_vp +# No tests for error on incorrect parameters: +# summary(), print(), dim() are generic and work for every input +# is.scan() returns TRUE/FALSE and works for every input + +test_that("summary.scan() prints metadata to the console", { + # print.scan() is not tested as it is the same as and called from summary.scan() + expect_output(summary(scan), "Polar scan (class scan)", fixed = TRUE) + expect_output(summary(scan), "parameters:", fixed = TRUE) + expect_output(summary(scan), "elevation angle:", fixed = TRUE) + expect_output(summary(scan), "dims:", fixed = TRUE) + +}) + +test_that("is.scan() returns TRUE/FALSE correctly", { + expect_true(is.scan(scan)) + expect_false(is.scan("not_a_scan")) + expect_false(is.scan(vp)) +}) + +test_that("dim.scan() returns dimensions", { + expect_vector(dim(scan)) + expect_equal(dim(scan), c(5, 480, 360)) # 5 param, 480 bins, 360 rays in example_scan }) From 822f68e15eaedb885fece049d7ceb2579196fc97 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 12:23:10 +0200 Subject: [PATCH 07/35] Write tests for summary.param, print.param, is.param --- tests/testthat/test-param.R | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-param.R b/tests/testthat/test-param.R index 9a07aa619..b60e05d01 100644 --- a/tests/testthat/test-param.R +++ b/tests/testthat/test-param.R @@ -1,3 +1,19 @@ -test_that("... returns error on incorrect parameters", { +param <- get_param(example_scan, "DBZH") +vp <- example_vp +# No tests for error on incorrect parameters: +# summary(), print() are generic and work for every input +# is.param() returns TRUE/FALSE and works for every input + +test_that("summary.param() prints metadata to the console", { + # print.param() is not tested as it is the same as and called from summary.param() + expect_output(summary(param), "Polar scan parameter (class param)", fixed = TRUE) + expect_output(summary(param), "quantity:", fixed = TRUE) + expect_output(summary(param), "dims:", fixed = TRUE) +}) + +test_that("is.param() returns TRUE/FALSE correctly", { + expect_true(is.param(param)) + expect_false(is.param("not_a_param")) + expect_false(is.param(vp)) }) From ff2576b294bfcec58bd0113873e30c85fdc6e56b Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 12:23:42 +0200 Subject: [PATCH 08/35] Write tests for summary.ppi, print.ppi, is.ppi, dim.ppi, subset.ppi --- tests/testthat/test-ppi.R | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-ppi.R b/tests/testthat/test-ppi.R index 9a07aa619..5c75db6d0 100644 --- a/tests/testthat/test-ppi.R +++ b/tests/testthat/test-ppi.R @@ -1,3 +1,30 @@ -test_that("... returns error on incorrect parameters", { +ppi <- project_as_ppi(example_scan) +vp <- example_vp +# No tests for error on incorrect parameters: +# summary(), print(), dim() are generic and work for every input +# is.ppi() returns TRUE/FALSE and works for every input + +test_that("summary.ppi() prints metadata to the console", { + # print.ppi() is not tested as it is the same as and called from summary.ppi() + expect_output(summary(ppi), "Plan position indicator (class ppi)", fixed = TRUE) + expect_output(summary(ppi), "parameters:", fixed = TRUE) + expect_output(summary(ppi), "dims:", fixed = TRUE) +}) + +test_that("is.ppi() returns TRUE/FALSE correctly", { + expect_true(is.ppi(ppi)) + expect_false(is.ppi("not_a_ppi")) + expect_false(is.ppi(vp)) +}) + +test_that("dim.ppi() returns dimensions", { + expect_vector(dim(ppi)) + expect_equal(dim(ppi), c(5, 200, 200)) # 5 param, 200 x pixels, 200 y pixels for default range_max +}) + +test_that("[.ppi subsets by param", { + # parameters: VRADH DBZH ZDR RHOHV PHIDP + expect_equal(names(ppi[1]$data), c("VRADH")) + expect_equal(names(ppi[2:4]$data), c("DBZH", "ZDR", "RHOHV")) }) From 218fdae0f296b95de27b0344e6bde7dbb6393d28 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 15:11:25 +0200 Subject: [PATCH 09/35] Fix #370 Ping @adokter @cecilianilsson709 - Shorten warning message and reference convert_legacy() - Rather than testing for legacy column (HGHT, dates), it checks if the expected column (height, datetime) is there - It uses convert_legacy() to be able to print, but doesn't change the object --- R/vp.R | 8 +++----- R/vpts.R | 14 ++++++-------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/R/vp.R b/R/vp.R index 57c8a8617..fe4461d79 100644 --- a/R/vp.R +++ b/R/vp.R @@ -88,11 +88,9 @@ summary.vp <- function(object, ...) { #' @export print.vp <- function(x, digits = max(3L, getOption("digits") - 3L), ...) { stopifnot(inherits(x, "vp")) - if (!is.null(x$data$HGHT)) { - warning("vp object is an obsolete one generated with bioRad version < 0.5.0. - vp objects should contain a column `height` (rather than `HGHT`) in the - `data` element." - ) + if (is.null(x$data$height)) { + warning("`x` is a legacy vp object without a column `height`. Use convert_legacy() to avoid errors.") + x <- convert_legacy(x) } cat(" Vertical profile (class vp)\n\n") cat(" radar: ", x$radar, "\n") diff --git a/R/vpts.R b/R/vpts.R index 8cf4e69d3..116f42d87 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -65,15 +65,13 @@ summary.vpts <- function(object, ...) { #' @export print.vpts <- function(x, digits = max(3L, getOption("digits") - 3L), ...) { stopifnot(inherits(x, "vpts")) - # check if we are dealing with a deprecated vpts class structure - if (!is.null(x$heights)) { - warning("obsolete vtps object generated with bioRad version < 0.5.0. - vpts objects should contain a list element 'height' (instead of obsolete 'heights')") + if (is.null(x$height)) { + warning("`x` is a legacy vpts object without a column `height`. Use convert_legacy() to avoid errors.") + x <- convert_legacy(x) } - if (!is.null(x$dates)) { - warning("obsolete vtps object generated with bioRad version < 0.4.0. - vpts objects should contain a list element 'datetime' (instead of obsolete 'dates')") - x$datetime <- x$dates + if (is.null(x$datetime)) { + warning("`x` is a legacy vpts object without a column `datetime`. Use convert_legacy() to avoid errors.") + x <- convert_legacy(x) } cat( " ", From 4eac9cedeee915b9577bfb183ff63bf02d733414 Mon Sep 17 00:00:00 2001 From: Cecilia Nilsson Date: Mon, 27 Apr 2020 15:11:58 +0200 Subject: [PATCH 10/35] Update regularize_vpts() to remove duplicate timestamps regularize_vpts() also fails on profiles with duplicate timestamps, see #235 . As a suggestion I just copied the code from plot.vpts() to drop duplicate timestamps. --- R/regularize_vpts.R | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/R/regularize_vpts.R b/R/regularize_vpts.R index f46bf0bad..51564e701 100644 --- a/R/regularize_vpts.R +++ b/R/regularize_vpts.R @@ -60,6 +60,13 @@ regularize_vpts <- function(ts, interval = "auto", date_min, date_max, stop("Fill argument should be a logical value.") } + # remove profiles with duplicate timestamps: + index_duplicates <- which(ts$timesteps == 0) + 1 + if (length(index_duplicates) > 0) { + warning(paste("Dropped", length(index_duplicates), "profiles with duplicate datetime values")) + ts <- ts[-index_duplicates] + } + if (interval == "auto") { dt <- as.difftime(median(ts$timesteps), units = "secs") if (verbose) { From f062ddffb1d8576120bd0467ebb158665621fd9d Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 16:20:17 +0200 Subject: [PATCH 11/35] Test for incorrect parameters for subset ppi --- tests/testthat/test-ppi.R | 4 ++++ tests/testthat/test-pvol.R | 1 - tests/testthat/test-scan.R | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-ppi.R b/tests/testthat/test-ppi.R index 5c75db6d0..6d76751e7 100644 --- a/tests/testthat/test-ppi.R +++ b/tests/testthat/test-ppi.R @@ -5,6 +5,10 @@ vp <- example_vp # summary(), print(), dim() are generic and work for every input # is.ppi() returns TRUE/FALSE and works for every input +test_that("[.ppi returns error on incorrect parameters", { + expect_error(ppi["not_numeric"]) +}) + test_that("summary.ppi() prints metadata to the console", { # print.ppi() is not tested as it is the same as and called from summary.ppi() expect_output(summary(ppi), "Plan position indicator (class ppi)", fixed = TRUE) diff --git a/tests/testthat/test-pvol.R b/tests/testthat/test-pvol.R index 0a6a9e59a..0a9dd55c5 100644 --- a/tests/testthat/test-pvol.R +++ b/tests/testthat/test-pvol.R @@ -13,7 +13,6 @@ test_that("summary.pvol() prints metadata to the console", { expect_output(summary(pvol), "radar:", fixed = TRUE) expect_output(summary(pvol), "source:", fixed = TRUE) expect_output(summary(pvol), "nominal time:", fixed = TRUE) - }) test_that("is.pvol() returns TRUE/FALSE correctly", { diff --git a/tests/testthat/test-scan.R b/tests/testthat/test-scan.R index 955eb90e0..c975ecb72 100644 --- a/tests/testthat/test-scan.R +++ b/tests/testthat/test-scan.R @@ -11,7 +11,6 @@ test_that("summary.scan() prints metadata to the console", { expect_output(summary(scan), "parameters:", fixed = TRUE) expect_output(summary(scan), "elevation angle:", fixed = TRUE) expect_output(summary(scan), "dims:", fixed = TRUE) - }) test_that("is.scan() returns TRUE/FALSE correctly", { From 81b9f3d4237a36e4cce2f4f6166ab06477ef3771 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 16:43:59 +0200 Subject: [PATCH 12/35] Use x[["height"]] since data$height tries to match magically --- R/vp.R | 2 +- R/vpts.R | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/vp.R b/R/vp.R index fe4461d79..6c029bf7a 100644 --- a/R/vp.R +++ b/R/vp.R @@ -88,7 +88,7 @@ summary.vp <- function(object, ...) { #' @export print.vp <- function(x, digits = max(3L, getOption("digits") - 3L), ...) { stopifnot(inherits(x, "vp")) - if (is.null(x$data$height)) { + if (is.null(x$data[["height"]])) { warning("`x` is a legacy vp object without a column `height`. Use convert_legacy() to avoid errors.") x <- convert_legacy(x) } diff --git a/R/vpts.R b/R/vpts.R index 116f42d87..4414d43d7 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -65,11 +65,11 @@ summary.vpts <- function(object, ...) { #' @export print.vpts <- function(x, digits = max(3L, getOption("digits") - 3L), ...) { stopifnot(inherits(x, "vpts")) - if (is.null(x$height)) { + if (is.null(x[["height"]])) { warning("`x` is a legacy vpts object without a column `height`. Use convert_legacy() to avoid errors.") x <- convert_legacy(x) } - if (is.null(x$datetime)) { + if (is.null(x[["datetime"]])) { warning("`x` is a legacy vpts object without a column `datetime`. Use convert_legacy() to avoid errors.") x <- convert_legacy(x) } From 47a698b6ce303643da80b450d2615816bb27de9e Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 16:48:18 +0200 Subject: [PATCH 13/35] Add minimal doc to helper function vpts_to_vp --- R/vpts.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/vpts.R b/R/vpts.R index 4414d43d7..52954a02d 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -195,6 +195,9 @@ dim.vpts <- function(x) { return(x) } +#' Helper function to convert a vpts[i] to a vp object +#' +#' @noRd vpts_to_vp <- function(x, i) { stopifnot(inherits(x, "vpts")) nvp <- dim(x)[2] From 7f13f866906380ca7d2676c6b0a1a74f8c0de4d3 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 16:59:55 +0200 Subject: [PATCH 14/35] Write tests for summary.vp, print.vp, is.vp, dim.vp, c.vp --- tests/testthat/test-vp.R | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-vp.R b/tests/testthat/test-vp.R index 9a07aa619..1dd05a792 100644 --- a/tests/testthat/test-vp.R +++ b/tests/testthat/test-vp.R @@ -1,3 +1,41 @@ -test_that("... returns error on incorrect parameters", { +vp <- example_vp +scan <- example_scan +# No tests for error on incorrect parameters: +# summary(), print(), dim() are generic and work for every input +# is.vp() returns TRUE/FALSE and works for every input + +test_that("c.vp() returns error on incorrect parameters", { + expect_error(c(vp, "not_a_vp"), "Each element must be a vp object.") +}) + +test_that("summary.vp() prints metadata to the console", { + # print.vp() is not tested as it is the same as and called from summary.vp() + expect_output(summary(vp), "Vertical profile (class vp)", fixed = TRUE) + expect_output(summary(vp), "radar:", fixed = TRUE) + expect_output(summary(vp), "source:", fixed = TRUE) + expect_output(summary(vp), "nominal time:", fixed = TRUE) + expect_output(summary(vp), "generated by:", fixed = TRUE) +}) + +test_that("summary.vp() warns for legacy objects", { + names(vp$data) <- sub("height", "HGHT", names(vp$data)) # Rename to legacy "HGHT" + expect_warning(summary(vp), "`x` is a legacy vp object without a column `height`.", fixed = TRUE) +}) + +test_that("is.vp() returns TRUE/FALSE correctly", { + expect_true(is.vp(vp)) + expect_false(is.vp("not_a_vp")) + expect_false(is.vp(scan)) +}) + +test_that("dim.vp() returns dimensions", { + expect_vector(dim(vp)) + expect_equal(dim(vp), c(25, 16)) # 25 heights, 17 quantities in example_vp +}) + +test_that("c.vp() warns if vp are not of same radar", { + vp_other_radar <- vp + vp_other_radar$radar <- "test" + expect_warning(c(vp, vp_other_radar), "Vertical profiles are not from a single radar.") }) From 2d06e24decb46a9f2716f96b047a8c1021976952 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 17:00:45 +0200 Subject: [PATCH 15/35] Write tests for summary.vpts, print.vpts, is.vpts, dim.vpts, subset.vpts --- tests/testthat/test-vpts.R | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-vpts.R b/tests/testthat/test-vpts.R index 9a07aa619..37f3d5ea6 100644 --- a/tests/testthat/test-vpts.R +++ b/tests/testthat/test-vpts.R @@ -1,3 +1,41 @@ -test_that("... returns error on incorrect parameters", { +vpts <- example_vpts +vp <- example_vp +# No tests for error on incorrect parameters: +# summary(), print(), dim() are generic and work for every input +# is.vpts() returns TRUE/FALSE and works for every input +# vpts["not_numeric] will return NA + +test_that("summary.vpts() prints metadata to the console", { + # print.vpts() is not tested as it is the same as and called from summary.vpts() + expect_output(summary(vpts), "Irregular time series of vertical profiles (class vpts)", fixed = TRUE) + expect_output(summary(vpts), "radar:", fixed = TRUE) + expect_output(summary(vpts), "# profiles:", fixed = TRUE) + expect_output(summary(vpts), "time range (UTC):", fixed = TRUE) + expect_output(summary(vpts), "time step (s):", fixed = TRUE) +}) + +test_that("summary.vpts() warns for legacy objects", { + names(vpts) <- sub("height", "heights", names(vpts)) # Rename to legacy "heights" + expect_warning(summary(vpts), "`x` is a legacy vpts object without a column `height`.", fixed = TRUE) + vpts <- convert_legacy(vpts) # Reset + names(vpts) <- sub("datetime", "dates", names(vpts)) # Rename to legacy "dates" + expect_warning(summary(vpts), "`x` is a legacy vpts object without a column `datetime`.", fixed = TRUE) +}) + +test_that("is.vpts() returns TRUE/FALSE correctly", { + expect_true(is.vpts(vpts)) + expect_false(is.vpts("not_a_vpts")) + expect_false(is.vpts(vp)) +}) + +test_that("dim.vpts() returns dimensions", { + expect_vector(dim(vpts)) + expect_equal(dim(vpts), c(25, 1934, 15)) # 25 heights, 1934 datetimes, 15 quantities +}) + +test_that("[.vpts subsets by profiles and returns a vp object for single selection", { + expect_s3_class(vpts[10], "vp") # Done with internal function vpts_to_vp() + expect_s3_class(vpts[10:20], "vpts") + expect_equal(dim(vpts[10:20]), c(25, 11, 15)) # 11 datetimes selected }) From 143c3f32fb3f4d3ee3962d2cf3dbba914665eb7f Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 17:02:28 +0200 Subject: [PATCH 16/35] Remove error message for subsetting @adokter dropped this error, because it seems pretty edge case to generate it. Would almost have to do vpts[c()], but maybe I am missing something? This error catch is also not there for ppi[] --- R/vpts.R | 3 --- 1 file changed, 3 deletions(-) diff --git a/R/vpts.R b/R/vpts.R index 52954a02d..afb73a6ac 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -157,9 +157,6 @@ dim.vpts <- function(x) { #' vpts[20:100] `[.vpts` <- function(x, i) { stopifnot(inherits(x, "vpts")) - if (length(i) < 1) { - stop("Time series should contain more than one profile.") - } if (length(i) == 1) { if (i > 0) { return(vpts_to_vp(x, i)) From f33e45b94fbe0138c370b11e65e356f98a556132 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 17:30:36 +0200 Subject: [PATCH 17/35] Correct test + add test for regular_vpts --- tests/testthat/test-vpts.R | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-vpts.R b/tests/testthat/test-vpts.R index 37f3d5ea6..6e315a580 100644 --- a/tests/testthat/test-vpts.R +++ b/tests/testthat/test-vpts.R @@ -13,6 +13,9 @@ test_that("summary.vpts() prints metadata to the console", { expect_output(summary(vpts), "# profiles:", fixed = TRUE) expect_output(summary(vpts), "time range (UTC):", fixed = TRUE) expect_output(summary(vpts), "time step (s):", fixed = TRUE) + + regular_vpts <- regularize_vpts(vpts) + expect_output(summary(regular_vpts), "Regular time series of vertical profiles (class vpts)", fixed = TRUE) }) test_that("summary.vpts() warns for legacy objects", { @@ -37,5 +40,5 @@ test_that("dim.vpts() returns dimensions", { test_that("[.vpts subsets by profiles and returns a vp object for single selection", { expect_s3_class(vpts[10], "vp") # Done with internal function vpts_to_vp() expect_s3_class(vpts[10:20], "vpts") - expect_equal(dim(vpts[10:20]), c(25, 11, 15)) # 11 datetimes selected + expect_equal(length(vpts[10:20]$datetime), 11) # 11 selected }) From 7a6c0354d0b0ce335c770ffa0529ff63fc03e8c5 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 17:55:02 +0200 Subject: [PATCH 18/35] Add dim.pvol(), see #355 --- NAMESPACE | 1 + R/pvol.R | 16 ++++++++++++++++ man/summary.pvol.Rd | 9 +++++++++ tests/testthat/test-pvol.R | 7 ++++++- 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index b0b45a1d7..8112fed4a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -26,6 +26,7 @@ S3method(check_night,vpts) S3method(convert_legacy,vp) S3method(convert_legacy,vpts) S3method(dim,ppi) +S3method(dim,pvol) S3method(dim,scan) S3method(dim,vp) S3method(dim,vpts) diff --git a/R/pvol.R b/R/pvol.R index f6400fe51..f1785dbed 100644 --- a/R/pvol.R +++ b/R/pvol.R @@ -39,6 +39,9 @@ #' # Get summary info #' pvol # Same as summary(pvol) or print(pvol) #' +#' # Get dimensions +#' dim(pvol) +#' #' # Get summary info for the scans in the polar volume #' pvol$scans summary.pvol <- function(object, ...) { @@ -72,3 +75,16 @@ print.pvol <- function(x, digits = max(3L, getOption("digits") - 3L), ...) { is.pvol <- function(x) { inherits(x, "pvol") } + +#' Get dimensions for an object of class `pvol` +#' +#' @return For [dim.pvol()]: number of scans (`scan`) in a polar volume +#' (`pvol`). +#' +#' @rdname summary.pvol +#' +#' @export +dim.pvol <- function(x) { + stopifnot(inherits(x, "pvol")) + c(length(x$scans)) +} diff --git a/man/summary.pvol.Rd b/man/summary.pvol.Rd index e6d105163..642388f05 100644 --- a/man/summary.pvol.Rd +++ b/man/summary.pvol.Rd @@ -3,11 +3,14 @@ \name{summary.pvol} \alias{summary.pvol} \alias{is.pvol} +\alias{dim.pvol} \title{Inspect a polar volume (\code{pvol})} \usage{ \method{summary}{pvol}(object, ...) is.pvol(x) + +\method{dim}{pvol}(x) } \arguments{ \item{object}{A \code{pvol} object.} @@ -19,6 +22,9 @@ is.pvol(x) \value{ For \code{\link[=is.pvol]{is.pvol()}}: \code{TRUE} for an object of class \code{pvol}, otherwise \code{FALSE}. + +For \code{\link[=dim.pvol]{dim.pvol()}}: number of scans (\code{scan}) in a polar volume +(\code{pvol}). } \description{ R base functions for inspecting a polar volume (\code{pvol}) object. @@ -52,6 +58,9 @@ is.pvol(pvol) # Get summary info pvol # Same as summary(pvol) or print(pvol) +# Get dimensions +dim(pvol) + # Get summary info for the scans in the polar volume pvol$scans } diff --git a/tests/testthat/test-pvol.R b/tests/testthat/test-pvol.R index 0a9dd55c5..e8b8eb393 100644 --- a/tests/testthat/test-pvol.R +++ b/tests/testthat/test-pvol.R @@ -3,7 +3,7 @@ pvol <- read_pvolfile(pvolfile) vp <- example_vp # No tests for error on incorrect parameters: -# summary(), print() are generic and work for every input +# summary(), print(), dim() are generic and work for every input # is.pvol() returns TRUE/FALSE and works for every input test_that("summary.pvol() prints metadata to the console", { @@ -20,3 +20,8 @@ test_that("is.pvol() returns TRUE/FALSE correctly", { expect_false(is.pvol("not_a_pvol")) expect_false(is.pvol(vp)) }) + +test_that("dim.pvol() returns number of scans", { + expect_vector(dim(pvol)) + expect_equal(dim(pvol), c(3)) # 3 scans in example_pvol +}) From 76d562f533dbba43c25a010e83cf493ff22e3ad6 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 17:55:17 +0200 Subject: [PATCH 19/35] Be explicit about what dim should return in tests --- tests/testthat/test-ppi.R | 4 ++-- tests/testthat/test-scan.R | 2 +- tests/testthat/test-vp.R | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/testthat/test-ppi.R b/tests/testthat/test-ppi.R index 6d76751e7..772eb3c51 100644 --- a/tests/testthat/test-ppi.R +++ b/tests/testthat/test-ppi.R @@ -22,9 +22,9 @@ test_that("is.ppi() returns TRUE/FALSE correctly", { expect_false(is.ppi(vp)) }) -test_that("dim.ppi() returns dimensions", { +test_that("dim.ppi() returns number of params, x, y", { expect_vector(dim(ppi)) - expect_equal(dim(ppi), c(5, 200, 200)) # 5 param, 200 x pixels, 200 y pixels for default range_max + expect_equal(dim(ppi), c(5, 200, 200)) # 5 param, 200 x, 200 y }) test_that("[.ppi subsets by param", { diff --git a/tests/testthat/test-scan.R b/tests/testthat/test-scan.R index c975ecb72..77ed2a15c 100644 --- a/tests/testthat/test-scan.R +++ b/tests/testthat/test-scan.R @@ -19,7 +19,7 @@ test_that("is.scan() returns TRUE/FALSE correctly", { expect_false(is.scan(vp)) }) -test_that("dim.scan() returns dimensions", { +test_that("dim.scan() returns number of params, bins, rays", { expect_vector(dim(scan)) expect_equal(dim(scan), c(5, 480, 360)) # 5 param, 480 bins, 360 rays in example_scan }) diff --git a/tests/testthat/test-vp.R b/tests/testthat/test-vp.R index 1dd05a792..282f3dc48 100644 --- a/tests/testthat/test-vp.R +++ b/tests/testthat/test-vp.R @@ -29,7 +29,7 @@ test_that("is.vp() returns TRUE/FALSE correctly", { expect_false(is.vp(scan)) }) -test_that("dim.vp() returns dimensions", { +test_that("dim.vp() returns number of heights, quantities", { expect_vector(dim(vp)) expect_equal(dim(vp), c(25, 16)) # 25 heights, 17 quantities in example_vp }) From 07a239129dd0ee5ff88f8f4b5170dbd9aeb2a1b1 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 17:56:22 +0200 Subject: [PATCH 20/35] Update dim.vpts() to datetimes, heights, quantities Fix #355 --- R/vpts.R | 7 ++++--- tests/testthat/test-vpts.R | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/R/vpts.R b/R/vpts.R index afb73a6ac..6ab651a3c 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -117,7 +117,7 @@ is.vpts <- function(x) { #' Get dimensions for an object of class `vpts` #' -#' @return For [dim.vpts()]: number of heights, datetimes and quantities in a +#' @return For [dim.vpts()]: number of datetimes, heights and quantities in a #' time series of vertical profiles (`vpts`). #' #' @rdname summary.vpts @@ -125,8 +125,9 @@ is.vpts <- function(x) { #' @export dim.vpts <- function(x) { stopifnot(inherits(x, "vpts")) - data.dim <- dim(x$data[[1]]) - c(data.dim, length(x$data)) + heights <- nrow(x$data[[1]]) + datetimes <- ncol(x$data[[1]]) + c(datetimes, heights, length(x$data)) } #' Subset a time series of vertical profiles (`vpts`) diff --git a/tests/testthat/test-vpts.R b/tests/testthat/test-vpts.R index 6e315a580..808d53ec2 100644 --- a/tests/testthat/test-vpts.R +++ b/tests/testthat/test-vpts.R @@ -32,9 +32,9 @@ test_that("is.vpts() returns TRUE/FALSE correctly", { expect_false(is.vpts(vp)) }) -test_that("dim.vpts() returns dimensions", { +test_that("dim.vpts() returns number of datetimes, heights, quantities", { expect_vector(dim(vpts)) - expect_equal(dim(vpts), c(25, 1934, 15)) # 25 heights, 1934 datetimes, 15 quantities + expect_equal(dim(vpts), c(1934, 25, 15)) # 1934 datetimes, 25 heights, 15 quantities }) test_that("[.vpts subsets by profiles and returns a vp object for single selection", { From 8534b0add6d8f4c25c18a38bfa0b4ba50e0839a1 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Mon, 27 Apr 2020 18:09:02 +0200 Subject: [PATCH 21/35] Update style and documentation for convert_legacy() --- R/convert_legacy.R | 16 ++++++++-------- man/convert_legacy.Rd | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/R/convert_legacy.R b/R/convert_legacy.R index 258ac677b..a829a3ca1 100644 --- a/R/convert_legacy.R +++ b/R/convert_legacy.R @@ -1,19 +1,19 @@ #' Convert legacy bioRad objects to current version #' -#' Convert legacy bioRad objects (vp, vpts) that have become -#' obsolete and make them compatible with the current bioRad version. +#' Convert legacy bioRad objects (`vp`, `vpts`) that have become obsolete +#' compatible with the current bioRad version. #' -#' @param x A `vp`, or `vpts` object. +#' @param x A `vp` or `vpts` object. #' #' @return An updated object of the same class as the input. #' #' @export #' #' @examples -#' # convert a vp object: +#' # Convert a vp object #' convert_legacy(example_vp) #' -#' # convert a vpts object: +#' # Convert a vpts object #' convert_legacy(example_vpts) convert_legacy <- function(x) { UseMethod("convert_legacy", x) @@ -24,7 +24,7 @@ convert_legacy <- function(x) { #' @export convert_legacy.vp <- function(x) { assert_that(inherits(x, "vp")) - names(x$data)=sub("HGHT","height",names(x$data)) + names(x$data) <- sub("HGHT", "height", names(x$data)) x } @@ -33,7 +33,7 @@ convert_legacy.vp <- function(x) { #' @export convert_legacy.vpts <- function(x) { assert_that(inherits(x, "vpts")) - names(x)=sub("heights","height",names(x)) - names(x)=sub("dates","datetime",names(x)) + names(x) <- sub("heights", "height", names(x)) + names(x) <- sub("dates", "datetime", names(x)) x } diff --git a/man/convert_legacy.Rd b/man/convert_legacy.Rd index 83e01f457..795577d58 100644 --- a/man/convert_legacy.Rd +++ b/man/convert_legacy.Rd @@ -13,19 +13,19 @@ convert_legacy(x) \method{convert_legacy}{vpts}(x) } \arguments{ -\item{x}{A \code{vp}, or \code{vpts} object.} +\item{x}{A \code{vp} or \code{vpts} object.} } \value{ An updated object of the same class as the input. } \description{ -Convert legacy bioRad objects (vp, vpts) that have become -obsolete and make them compatible with the current bioRad version. +Convert legacy bioRad objects (\code{vp}, \code{vpts}) that have become obsolete +compatible with the current bioRad version. } \examples{ -# convert a vp object: +# Convert a vp object convert_legacy(example_vp) -# convert a vpts object: +# Convert a vpts object convert_legacy(example_vpts) } From 3967dae50299c1b962f1569886cc1af86416c71e Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 15:41:38 +0200 Subject: [PATCH 22/35] Add negative subsetting examples + tests --- R/ppi.R | 3 +++ R/vpts.R | 11 +++++++---- man/example_vpts.Rd | 2 +- man/sub-.ppi.Rd | 3 +++ man/sub-.vpts.Rd | 11 +++++++---- man/summary.vpts.Rd | 2 +- tests/testthat/test-ppi.R | 1 + tests/testthat/test-vpts.R | 15 ++++++++++++--- 8 files changed, 35 insertions(+), 13 deletions(-) diff --git a/R/ppi.R b/R/ppi.R index b6b6907d5..4a566eaa9 100644 --- a/R/ppi.R +++ b/R/ppi.R @@ -117,6 +117,9 @@ dim.ppi <- function(x) { #' #' # Subset ppi to one containing the first three parameters (VRADH, DBZH, ZDR) #' ppi[1:3] +#' +#' # Subset ppi to one without the first 2 parameters (ZDR RHOHV PHIDP) +#' ppi[-1:-2] `[.ppi` <- function(x, i) { stopifnot(inherits(x, "ppi")) my_ppi <- list( diff --git a/R/vpts.R b/R/vpts.R index 6ab651a3c..02085fc7c 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -151,11 +151,14 @@ dim.vpts <- function(x) { #' # This vpts contains 1934 profiles (i.e. datetimes) #' dim(vpts) #' -#' # Subset vpts to extract 10th profile (returns a vp object) -#' vpts[10] +#' # Subset vpts to extract 10th profile +#' vpts[10] # A vp object #' -#' # Subset vpts to extract the 20th to 100th profile (returns a vpts object) -#' vpts[20:100] +#' # Subset vpts to extract the 20th to 100th profile +#' vpts[20:100] # A vpts object with 81 profiles +#' +#' # Subset vpts to remove the first 10 profiles +#' vpts[-1:-10] # A vpts object with 10 less profiles `[.vpts` <- function(x, i) { stopifnot(inherits(x, "vpts")) if (length(i) == 1) { diff --git a/man/example_vpts.Rd b/man/example_vpts.Rd index 4b7ddb3fe..373a54a1d 100644 --- a/man/example_vpts.Rd +++ b/man/example_vpts.Rd @@ -5,7 +5,7 @@ \alias{example_vpts} \title{Example object of class \code{vpts}} \format{ -An object of class \code{vpts} of dimension 25 x 1934 x 15. +An object of class \code{vpts} of dimension 1934 x 25 x 15. } \usage{ example_vpts diff --git a/man/sub-.ppi.Rd b/man/sub-.ppi.Rd index 0edce4d97..a625931db 100644 --- a/man/sub-.ppi.Rd +++ b/man/sub-.ppi.Rd @@ -31,4 +31,7 @@ ppi[1] # Subset ppi to one containing the first three parameters (VRADH, DBZH, ZDR) ppi[1:3] + +# Subset ppi to one without the first 2 parameters (ZDR RHOHV PHIDP) +ppi[-1:-2] } diff --git a/man/sub-.vpts.Rd b/man/sub-.vpts.Rd index 14461cc2f..ec1ee11bb 100644 --- a/man/sub-.vpts.Rd +++ b/man/sub-.vpts.Rd @@ -27,9 +27,12 @@ vpts <- example_vpts # This vpts contains 1934 profiles (i.e. datetimes) dim(vpts) -# Subset vpts to extract 10th profile (returns a vp object) -vpts[10] +# Subset vpts to extract 10th profile +vpts[10] # A vp object -# Subset vpts to extract the 20th to 100th profile (returns a vpts object) -vpts[20:100] +# Subset vpts to extract the 20th to 100th profile +vpts[20:100] # A vpts object with 81 profiles + +# Subset vpts to remove the first 10 profiles +vpts[-1:-10] # A vpts object with 10 less profiles } diff --git a/man/summary.vpts.Rd b/man/summary.vpts.Rd index ac79cf19f..2ce5c6029 100644 --- a/man/summary.vpts.Rd +++ b/man/summary.vpts.Rd @@ -23,7 +23,7 @@ is.vpts(x) For \code{\link[=is.vpts]{is.vpts()}}: \code{TRUE} for an object of class \code{vpts}, otherwise \code{FALSE}. -For \code{\link[=dim.vpts]{dim.vpts()}}: number of heights, datetimes and quantities in a +For \code{\link[=dim.vpts]{dim.vpts()}}: number of datetimes, heights and quantities in a time series of vertical profiles (\code{vpts}). } \description{ diff --git a/tests/testthat/test-ppi.R b/tests/testthat/test-ppi.R index 772eb3c51..ec7fe59ab 100644 --- a/tests/testthat/test-ppi.R +++ b/tests/testthat/test-ppi.R @@ -31,4 +31,5 @@ test_that("[.ppi subsets by param", { # parameters: VRADH DBZH ZDR RHOHV PHIDP expect_equal(names(ppi[1]$data), c("VRADH")) expect_equal(names(ppi[2:4]$data), c("DBZH", "ZDR", "RHOHV")) + expect_equal(names(ppi[-2:-4]$data), c("VRADH", "PHIDP")) # All except 2 to 4 }) diff --git a/tests/testthat/test-vpts.R b/tests/testthat/test-vpts.R index 808d53ec2..f156836c4 100644 --- a/tests/testthat/test-vpts.R +++ b/tests/testthat/test-vpts.R @@ -37,8 +37,17 @@ test_that("dim.vpts() returns number of datetimes, heights, quantities", { expect_equal(dim(vpts), c(1934, 25, 15)) # 1934 datetimes, 25 heights, 15 quantities }) -test_that("[.vpts subsets by profiles and returns a vp object for single selection", { - expect_s3_class(vpts[10], "vp") # Done with internal function vpts_to_vp() +test_that("[.vpts subsets by profiles", { + # 1934 profiles in total + expect_equal(length(vpts[10]$datetime), 1) # Select 10th => 1 profile + expect_equal(length(vpts[10:20]$datetime), 11) # Select 10:20 => 11 profiles + expect_equal(length(vpts[-1:-1900]$datetime), 34) # Remove 1:1900 => 34 profiles left +}) + +test_that("[.vpts returns a vp object for single selection", { expect_s3_class(vpts[10:20], "vpts") - expect_equal(length(vpts[10:20]$datetime), 11) # 11 selected + expect_s3_class(vpts[10], "vp") # Select 10th => 1 profile + vpts_of_2 <- vpts[1:2] + expect_s3_class(vpts_of_2[-1], "vp") # Remove 1st => 1 profile left + expect_s3_class(vpts_of_2[-2], "vp") # Remove 2nd => 1 profile left }) From aac4639f58f521ad41ab3c23e8cebcecf2765464 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 15:42:55 +0200 Subject: [PATCH 23/35] Simplify vpts_to_vp: only if vpts has single profile Include test that otherwise fails --- R/vpts.R | 35 +++++++++++++---------------------- tests/testthat/test-vpts.R | 1 + 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/R/vpts.R b/R/vpts.R index 02085fc7c..1a33d3a7f 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -161,20 +161,7 @@ dim.vpts <- function(x) { #' vpts[-1:-10] # A vpts object with 10 less profiles `[.vpts` <- function(x, i) { stopifnot(inherits(x, "vpts")) - if (length(i) == 1) { - if (i > 0) { - return(vpts_to_vp(x, i)) - } else { - if (dim(x)[2] == 2) { - if (i == -1) { - return(vpts_to_vp(x, 2)) - } - if (i == -2) { - return(vpts_to_vp(x, 1)) - } - } - } - } + x$datetime <- x$datetime[i] x$daterange <- .POSIXct(c(min(x$datetime), max(x$datetime)), tz = "UTC") x$timesteps <- difftime(x$datetime[-1], x$datetime[-length(x$datetime)], @@ -193,25 +180,29 @@ dim.vpts <- function(x) { } ) names(x$data) <- quantity.names + + # Convert to vp if only 1 profile + if(length(x$datetime) == 1) { + x <- vpts_to_vp(x) + } + return(x) } -#' Helper function to convert a vpts[i] to a vp object +#' Helper function to convert a vpts[1] to a vp object #' #' @noRd -vpts_to_vp <- function(x, i) { +vpts_to_vp <- function(x) { stopifnot(inherits(x, "vpts")) - nvp <- dim(x)[2] - if (i < 1 || i > nvp) { - return(NA) - } + stopifnot(length(x$datetime) == 1) + vpout <- list() vpout$radar <- x$radar - vpout$datetime <- x$datetime[i] + vpout$datetime <- x$datetime[1] vpout$data <- as.data.frame(lapply( names(x$data), function(y) { - x$data[y][[1]][, i] + x$data[y][[1]] } )) names(vpout$data) <- names(x$data) diff --git a/tests/testthat/test-vpts.R b/tests/testthat/test-vpts.R index f156836c4..6b4a12545 100644 --- a/tests/testthat/test-vpts.R +++ b/tests/testthat/test-vpts.R @@ -47,6 +47,7 @@ test_that("[.vpts subsets by profiles", { test_that("[.vpts returns a vp object for single selection", { expect_s3_class(vpts[10:20], "vpts") expect_s3_class(vpts[10], "vp") # Select 10th => 1 profile + expect_s3_class(vpts[-1:-1933], "vp") # Remove 1933 => 1 profile left vpts_of_2 <- vpts[1:2] expect_s3_class(vpts_of_2[-1], "vp") # Remove 1st => 1 profile left expect_s3_class(vpts_of_2[-2], "vp") # Remove 2nd => 1 profile left From f485dd15532cc203441f28fa1e612fe55b5d0f3d Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 15:44:57 +0200 Subject: [PATCH 24/35] Fix updated dim --- R/vpts.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/vpts.R b/R/vpts.R index 02085fc7c..477dd069f 100644 --- a/R/vpts.R +++ b/R/vpts.R @@ -165,7 +165,7 @@ dim.vpts <- function(x) { if (i > 0) { return(vpts_to_vp(x, i)) } else { - if (dim(x)[2] == 2) { + if (dim(x)[1] == 2) { if (i == -1) { return(vpts_to_vp(x, 2)) } @@ -201,7 +201,7 @@ dim.vpts <- function(x) { #' @noRd vpts_to_vp <- function(x, i) { stopifnot(inherits(x, "vpts")) - nvp <- dim(x)[2] + nvp <- dim(x)[1] if (i < 1 || i > nvp) { return(NA) } From 5973634dd140811a233d7d4c6a40b4c30bc49be2 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 16:52:06 +0200 Subject: [PATCH 25/35] Mention pvol in get_scan --- R/get_scan.R | 3 ++- man/get_scan.Rd | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/R/get_scan.R b/R/get_scan.R index e5e32cb57..9ffeb5f98 100644 --- a/R/get_scan.R +++ b/R/get_scan.R @@ -1,6 +1,7 @@ #' Get a scan (`scan`) from a polar volume (`pvol`) #' -#' Returns the scan with elevation angle closest to `elev`. +#' Returns the scan (`scan`) from a polar volume (`pvol`) with elevation angle +#' closest to `elev`. #' #' @param x A `pvol` object. #' @param elev Numeric. Elevation angle. diff --git a/man/get_scan.Rd b/man/get_scan.Rd index 3eaad13b3..2c26d9831 100644 --- a/man/get_scan.Rd +++ b/man/get_scan.Rd @@ -15,7 +15,8 @@ get_scan(x, elev) A \code{scan} object. } \description{ -Returns the scan with elevation angle closest to \code{elev}. +Returns the scan (\code{scan}) from a polar volume (\code{pvol}) with elevation angle +closest to \code{elev}. } \examples{ # Locate and read the polar volume example file From dd33ffa0c22d0ecf13324da34718d707760ee5ec Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 16:58:48 +0200 Subject: [PATCH 26/35] Use fixed = TRUE for error message testing --- tests/testthat/test-get_scan.R | 4 ++-- tests/testthat/test-rcs.R | 4 ++-- tests/testthat/test-sd_vvp_threshold.R | 4 ++-- tests/testthat/test-vp.R | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/testthat/test-get_scan.R b/tests/testthat/test-get_scan.R index d2c9d79cd..f94901da7 100644 --- a/tests/testthat/test-get_scan.R +++ b/tests/testthat/test-get_scan.R @@ -2,8 +2,8 @@ pvolfile <- system.file("extdata", "volume.h5", package = "bioRad") pvol <- read_pvolfile(pvolfile) test_that("get_scan() returns error on incorrect parameters", { - expect_error(get_scan("not_a_pvol", 5), "`x` must be a pvol object.") - expect_error(get_scan(pvol, "not_numeric"), "`elev` must be numeric.") + expect_error(get_scan("not_a_pvol", 5), "`x` must be a pvol object.", fixed = TRUE) + expect_error(get_scan(pvol, "not_numeric"), "`elev` must be numeric.", fixed = TRUE) }) test_that("get_scan() returns a object of class scan", { diff --git a/tests/testthat/test-rcs.R b/tests/testthat/test-rcs.R index b3e1814c6..651f54960 100644 --- a/tests/testthat/test-rcs.R +++ b/tests/testthat/test-rcs.R @@ -6,7 +6,7 @@ vpi <- integrate_profile(example_vpts) test_that("rcs() returns error on incorrect parameters", { expect_error(rcs("not_a_vp")) - expect_error(rcs(vp_list_mixed), "`x` must be list of vp objects.") + expect_error(rcs(vp_list_mixed), "`x` must be list of vp objects.", fixed = TRUE) }) test_that("rcs()<- returns error on incorrect parameters", { @@ -14,7 +14,7 @@ test_that("rcs()<- returns error on incorrect parameters", { expect_error(rcs(vp) <- NULL) expect_error(rcs(vp) <- c(2, 2)) expect_error(rcs("not_a_vp") <- 5) - expect_error(rcs(vp_list_mixed) <- 5, "`x` must be list of vp objects.") + expect_error(rcs(vp_list_mixed) <- 5, "`x` must be list of vp objects.", fixed = TRUE) expect_error(rcs(vp) <- -11) }) diff --git a/tests/testthat/test-sd_vvp_threshold.R b/tests/testthat/test-sd_vvp_threshold.R index f6db8f27f..f393017da 100644 --- a/tests/testthat/test-sd_vvp_threshold.R +++ b/tests/testthat/test-sd_vvp_threshold.R @@ -5,7 +5,7 @@ vpts <- example_vpts test_that("sd_vvp_threshold() returns error on incorrect parameters", { expect_error(sd_vvp_threshold("not_a_vp")) - expect_error(sd_vvp_threshold(vp_list_mixed), "`x` must be list of vp objects.") + expect_error(sd_vvp_threshold(vp_list_mixed), "`x` must be list of vp objects.", fixed = TRUE) }) test_that("sd_vvp_threshold()<- returns error on incorrect parameters", { @@ -13,7 +13,7 @@ test_that("sd_vvp_threshold()<- returns error on incorrect parameters", { expect_error(sd_vvp_threshold(vp) <- NULL) expect_error(sd_vvp_threshold(vp) <- c(2, 2)) expect_error(sd_vvp_threshold("not_a_vp") <- 2) - expect_error(sd_vvp_threshold(vp_list_mixed) <- 2, "`x` must be list of vp objects.") + expect_error(sd_vvp_threshold(vp_list_mixed) <- 2, "`x` must be list of vp objects.", fixed = TRUE) }) test_that("sd_vvp_threshold() returns the correct sd_vvp_thresh", { diff --git a/tests/testthat/test-vp.R b/tests/testthat/test-vp.R index 282f3dc48..fb60fe2f7 100644 --- a/tests/testthat/test-vp.R +++ b/tests/testthat/test-vp.R @@ -6,7 +6,7 @@ scan <- example_scan # is.vp() returns TRUE/FALSE and works for every input test_that("c.vp() returns error on incorrect parameters", { - expect_error(c(vp, "not_a_vp"), "Each element must be a vp object.") + expect_error(c(vp, "not_a_vp"), "Each element must be a vp object.", fixed = TRUE) }) test_that("summary.vp() prints metadata to the console", { From ef16be11bb629542d6e7659281797371bd8683f5 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 16:59:06 +0200 Subject: [PATCH 27/35] Use get_ in get_elevation_angle tests --- tests/testthat/test-get_elevation_angles.R | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/testthat/test-get_elevation_angles.R b/tests/testthat/test-get_elevation_angles.R index 125e0e8fb..842dc9cd9 100644 --- a/tests/testthat/test-get_elevation_angles.R +++ b/tests/testthat/test-get_elevation_angles.R @@ -1,12 +1,10 @@ pvolfile <- system.file("extdata", "volume.h5", package = "bioRad") pvol <- read_pvolfile(pvolfile) -scan <- pvol$scans[[1]] -param <- scan$params$DBZH +scan <- get_scan(pvol, 0.5) +param <- get_param(scan, "DBZH") test_that("get_elevation_angles() returns error on incorrect parameters", { expect_error(get_elevation_angles("not_a_vp")) - expect_error(get_elevation_angles(1)) - expect_error(get_elevation_angles(NULL)) }) test_that("get_elevation_angles() returns the correct elangle", { From d13ffd9dddd2c8f7bf596c7d15dcf4aefea37b4f Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 16:59:48 +0200 Subject: [PATCH 28/35] Update doc and reference summary.param() --- R/get_param.R | 29 ++++++++++++++++++++--------- man/get_param.Rd | 29 +++++++++++++++++++---------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/R/get_param.R b/R/get_param.R index 5b494ab05..e3a79f6e8 100644 --- a/R/get_param.R +++ b/R/get_param.R @@ -1,18 +1,29 @@ -#' Get a scan parameter `param` from a scan `scan` +#' Get a parameter `param` from a scan (`scan`) #' -#' @param x An object of class `scan`. -#' @param param A scan parameter. +#' Returns the selected parameter (`param`) from a scan (`scan`). #' -#' @return An object of class [param][summary.param]. +#' @param x A `scan` object. +#' @param param Character. A scan parameter, such as `DBZH` or `VRADH`. See +#' [summary.param()] for commonly available parameters. +#' +#' @return A `param` object. #' #' @export +#' +#' @seealso [summary.param()] +#' #' @examples -#' # we will extract a scan parameter from the example scan object: -#' example_scan +#' # Load the example scan +#' scan <- example_scan +#' +#' # Get summary info (including parameters) +#' scan +#' +#' # Extact the VRADH scan parameter +#' param <- get_param(scan, "VRADH") #' -#' # extract the VRADH scan parameter -#' my_param <- get_param(example_scan, "VRADH") -#' my_param +#' # Get summary info for this parameter +#' param get_param <- function(x, param) { assert_that(class(x) == "scan", msg = "`x` must be a scan object.") if (!(param %in% names(x$params))) stop(paste("Scan parameter", param, "not found in `x`.")) diff --git a/man/get_param.Rd b/man/get_param.Rd index 4c5b10813..745048100 100644 --- a/man/get_param.Rd +++ b/man/get_param.Rd @@ -2,26 +2,35 @@ % Please edit documentation in R/get_param.R \name{get_param} \alias{get_param} -\title{Get a scan parameter \code{param} from a scan \code{scan}} +\title{Get a parameter \code{param} from a scan (\code{scan})} \usage{ get_param(x, param) } \arguments{ -\item{x}{An object of class \code{scan}.} +\item{x}{A \code{scan} object.} -\item{param}{A scan parameter.} +\item{param}{Character. A scan parameter, such as \code{DBZH} or \code{VRADH}. See +\code{\link[=summary.param]{summary.param()}} for commonly available parameters.} } \value{ -An object of class \link[=summary.param]{param}. +A \code{param} object. } \description{ -Get a scan parameter \code{param} from a scan \code{scan} +Returns the selected parameter (\code{param}) from a scan (\code{scan}). } \examples{ -# we will extract a scan parameter from the example scan object: -example_scan +# Load the example scan +scan <- example_scan -# extract the VRADH scan parameter -my_param <- get_param(example_scan, "VRADH") -my_param +# Get summary info (including parameters) +scan + +# Extact the VRADH scan parameter +param <- get_param(scan, "VRADH") + +# Get summary info for this parameter +param +} +\seealso{ +\code{\link[=summary.param]{summary.param()}} } From 68e9d47a6dc9f7a0602d2eac7d6d0c4e6abb379a Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 17:00:13 +0200 Subject: [PATCH 29/35] Update error message --- R/get_param.R | 2 +- tests/testthat/test-get_param.R | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/R/get_param.R b/R/get_param.R index e3a79f6e8..8e7cee984 100644 --- a/R/get_param.R +++ b/R/get_param.R @@ -26,6 +26,6 @@ #' param get_param <- function(x, param) { assert_that(class(x) == "scan", msg = "`x` must be a scan object.") - if (!(param %in% names(x$params))) stop(paste("Scan parameter", param, "not found in `x`.")) + if (!(param %in% names(x$params))) stop(paste0("Can't find parameter `", param, "` in `x`.")) x$params[[param]] } diff --git a/tests/testthat/test-get_param.R b/tests/testthat/test-get_param.R index 0384827ec..28bb33f27 100644 --- a/tests/testthat/test-get_param.R +++ b/tests/testthat/test-get_param.R @@ -3,15 +3,13 @@ pvol <- read_pvolfile(pvolfile) scan <- pvol$scans[[1]] test_that("get_param() returns error on incorrect parameters", { - expect_error(get_param("not_a_scan"), "`x` must be a scan object.") - expect_error(get_param(vp),"`x` must be a scan object.") - expect_error(get_param(pvol),"`x` must be a scan object.") - expect_error(get_param(scan)) - expect_error(get_param(scan, "not_a_param"), "Scan parameter not_a_param not found in `x`.") + expect_error(get_param("not_a_scan", "DBZH"), "`x` must be a scan object.", fixed = TRUE) + expect_error(get_param(pvol, "DBZH"),"`x` must be a scan object.", fixed = TRUE) + expect_error(get_param(scan)) # Parameter "param" missing + expect_error(get_param(scan, "not_a_param"), "Can't find parameter `not_a_param` in `x`", fixed = TRUE) }) test_that("get_param() returns correct parameters", { expect_equal(get_param(scan, names(scan$params[1])), scan$params[[1]]) expect_equal(get_param(scan, names(scan$params[2])), scan$params[[2]]) }) - From 6b1e179df852868006006fd2ad47076c8766f3f4 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 17:03:27 +0200 Subject: [PATCH 30/35] Use parenthesis --- R/get_param.R | 2 +- man/get_param.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/get_param.R b/R/get_param.R index 8e7cee984..267ed0e2a 100644 --- a/R/get_param.R +++ b/R/get_param.R @@ -1,4 +1,4 @@ -#' Get a parameter `param` from a scan (`scan`) +#' Get a parameter (`param`) from a scan (`scan`) #' #' Returns the selected parameter (`param`) from a scan (`scan`). #' diff --git a/man/get_param.Rd b/man/get_param.Rd index 745048100..22fc17527 100644 --- a/man/get_param.Rd +++ b/man/get_param.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/get_param.R \name{get_param} \alias{get_param} -\title{Get a parameter \code{param} from a scan (\code{scan})} +\title{Get a parameter (\code{param}) from a scan (\code{scan})} \usage{ get_param(x, param) } From 807fa8546743ae7abcf76d15bacc05983378baf3 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 17:03:34 +0200 Subject: [PATCH 31/35] Test for literal parameters + test class --- tests/testthat/test-get_param.R | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/testthat/test-get_param.R b/tests/testthat/test-get_param.R index 28bb33f27..8d145a6d5 100644 --- a/tests/testthat/test-get_param.R +++ b/tests/testthat/test-get_param.R @@ -1,6 +1,6 @@ pvolfile <- system.file("extdata", "volume.h5", package = "bioRad") pvol <- read_pvolfile(pvolfile) -scan <- pvol$scans[[1]] +scan <- example_scan test_that("get_param() returns error on incorrect parameters", { expect_error(get_param("not_a_scan", "DBZH"), "`x` must be a scan object.", fixed = TRUE) @@ -9,7 +9,9 @@ test_that("get_param() returns error on incorrect parameters", { expect_error(get_param(scan, "not_a_param"), "Can't find parameter `not_a_param` in `x`", fixed = TRUE) }) -test_that("get_param() returns correct parameters", { - expect_equal(get_param(scan, names(scan$params[1])), scan$params[[1]]) - expect_equal(get_param(scan, names(scan$params[2])), scan$params[[2]]) +test_that("get_param() returns correct parameter", { + # Parameters: VRADH DBZH ZDR RHOHV PHIDP + expect_equal(get_param(scan, "DBZH"), scan$params[["DBZH"]]) + expect_equal(get_param(scan, "PHIDP"), scan$params[["PHIDP"]]) + expect_s3_class(get_param(scan, "RHOHV"), "param") }) From 9118ae5dce0fd58e94877d67891d9a42d388ba61 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 17:39:02 +0200 Subject: [PATCH 32/35] Use markdown + extend examples --- R/data.R | 61 ++++++++++++++++++++++++++------------------- man/example_scan.Rd | 21 ++++++++++------ man/example_vp.Rd | 22 +++++++++------- man/example_vpts.Rd | 21 ++++++++++------ 4 files changed, 75 insertions(+), 50 deletions(-) diff --git a/R/data.R b/R/data.R index 271e68b7e..bfb78f3c2 100644 --- a/R/data.R +++ b/R/data.R @@ -1,64 +1,75 @@ -#' Example object of class \code{vp} +#' Vertical profile (`vp`) example #' -#' Example of a \code{\link[=summary.vp]{vp}} object with name -#' \code{example_vp}. Can be created with \code{\link{calculate_vp}} or read -#' from file with \code{\link{read_vpfiles}}. +#' Example object of class [`vp`][summary.vp()] with name `example_vp`. #' #' @rdname example_vp #' +#' @seealso [summary.vp] +#' #' @examples -#' # get summary of example vp: -#' summary(example_vp) +#' # Reload example_vp from package (e.g. in case it was altered) +#' data(example_vp) +#' +#' # Get summary info +#' example_vp #' -#' # example_vp was created with: +#' # example_vp was created with +#' \dontrun{ #' vpfile <- system.file("extdata", "profile.h5", package = "bioRad") #' example_vp <- read_vpfiles(vpfile) -#' \dontrun{ -#' # save(example_vp, file = "data/example_vp.rda") +#' save(example_vp, file = "data/example_vp.rda") #' } "example_vp" -#' Example object of class \code{scan} +#' Scan (`scan`) example #' -#' Example of a \code{\link[=summary.scan]{scan}} object with name -#' \code{example_scan}. +#' Example object of class [`scan`][summary.scan()] with name `example_scan`. #' #' @rdname example_scan #' +#' @seealso [summary.scan] +#' #' @examples -#' # get summary of example scan: -#' summary(example_scan) +#' # Reload example_scan from package (e.g. in case it was altered) +#' data(example_scan) #' -#' # example_scan was created with: +#' # Get summary info +#' example_scan +#' +#' # example_scan was created with +#' \dontrun{ #' pvolfile <- system.file("extdata", "volume.h5", package = "bioRad") #' pvol <- read_pvolfile(pvolfile) #' example_scan <- pvol$scans[[1]] -#' \dontrun{ -#' # save(example_scan, file = "data/example_scan.rda") +#' save(example_scan, file = "data/example_scan.rda") #' } "example_scan" -#' Example object of class \code{vpts} +#' Time series of vertical profiles (`vpts`) example #' -#' Example of a \code{\link[=summary.vpts]{vpts}} object (a time series of -#' vertical profiles) with name \code{example_vpts}. +#' Example object of class [`vpts`](summary.vpts()] with name `example_vpts`. #' #' @rdname example_vpts #' +#' @seealso [summary.vpts] +#' #' @examples -#' # get summary of example vpts: -#' summary(example_vpts) +#' # Reload example_vpts from package (e.g. in case it was altered) +#' data(example_vpts) +#' +#' # Get summary info +#' example_vpts #' -#' # example_vpts was created with: +#' # example_vpts was created with #' \dontrun{ #' vptsfile <- system.file("extdata", "vpts.txt.zip", package = "bioRad") -#' unzip(vptsfile, exdir = (dirname(vptsfile)), junkpaths = T) +#' unzip(vptsfile, exdir = (dirname(vptsfile)), junkpaths = TRUE) #' vptsfile <- substr(vptsfile, 1, nchar(vptsfile) - 4) #' example_vpts <- read_vpts(vptsfile, radar = "KBGM", wavelength = "S") #' rcs(example_vpts) <- 11 #' sd_vvp_threshold(example_vpts) <- 2 #' example_vpts$attributes$where$lat <- 42.2 #' example_vpts$attributes$where$lon <- -75.98 -#' # save(example_vpts, file = "data/example_vpts.rda", compress = "xz") +#' save(example_vpts, file = "data/example_vpts.rda", compress = "xz") #' } "example_vpts" diff --git a/man/example_scan.Rd b/man/example_scan.Rd index 9d9e9caf5..ba18c7506 100644 --- a/man/example_scan.Rd +++ b/man/example_scan.Rd @@ -3,7 +3,7 @@ \docType{data} \name{example_scan} \alias{example_scan} -\title{Example object of class \code{scan}} +\title{Scan (\code{scan}) example} \format{ An object of class \code{scan} of dimension 5 x 480 x 360. } @@ -11,19 +11,24 @@ An object of class \code{scan} of dimension 5 x 480 x 360. example_scan } \description{ -Example of a \code{\link[=summary.scan]{scan}} object with name -\code{example_scan}. +Example object of class \code{\link[=summary.scan]{scan}} with name \code{example_scan}. } \examples{ -# get summary of example scan: -summary(example_scan) +# Reload example_scan from package (e.g. in case it was altered) +data(example_scan) -# example_scan was created with: +# Get summary info +example_scan + +# example_scan was created with +\dontrun{ pvolfile <- system.file("extdata", "volume.h5", package = "bioRad") pvol <- read_pvolfile(pvolfile) example_scan <- pvol$scans[[1]] -\dontrun{ -# save(example_scan, file = "data/example_scan.rda") +save(example_scan, file = "data/example_scan.rda") +} } +\seealso{ +\link{summary.scan} } \keyword{datasets} diff --git a/man/example_vp.Rd b/man/example_vp.Rd index 5f42e0274..9de20461b 100644 --- a/man/example_vp.Rd +++ b/man/example_vp.Rd @@ -3,7 +3,7 @@ \docType{data} \name{example_vp} \alias{example_vp} -\title{Example object of class \code{vp}} +\title{Vertical profile (\code{vp}) example} \format{ An object of class \code{vp} with 25 rows and 16 columns. } @@ -11,19 +11,23 @@ An object of class \code{vp} with 25 rows and 16 columns. example_vp } \description{ -Example of a \code{\link[=summary.vp]{vp}} object with name -\code{example_vp}. Can be created with \code{\link{calculate_vp}} or read -from file with \code{\link{read_vpfiles}}. +Example object of class \code{\link[=summary.vp]{vp}} with name \code{example_vp}. } \examples{ -# get summary of example vp: -summary(example_vp) +# Reload example_vp from package (e.g. in case it was altered) +data(example_vp) -# example_vp was created with: +# Get summary info +example_vp + +# example_vp was created with +\dontrun{ vpfile <- system.file("extdata", "profile.h5", package = "bioRad") example_vp <- read_vpfiles(vpfile) -\dontrun{ -# save(example_vp, file = "data/example_vp.rda") +save(example_vp, file = "data/example_vp.rda") +} } +\seealso{ +\link{summary.vp} } \keyword{datasets} diff --git a/man/example_vpts.Rd b/man/example_vpts.Rd index 373a54a1d..1478b2607 100644 --- a/man/example_vpts.Rd +++ b/man/example_vpts.Rd @@ -3,7 +3,7 @@ \docType{data} \name{example_vpts} \alias{example_vpts} -\title{Example object of class \code{vpts}} +\title{Time series of vertical profiles (\code{vpts}) example} \format{ An object of class \code{vpts} of dimension 1934 x 25 x 15. } @@ -11,24 +11,29 @@ An object of class \code{vpts} of dimension 1934 x 25 x 15. example_vpts } \description{ -Example of a \code{\link[=summary.vpts]{vpts}} object (a time series of -vertical profiles) with name \code{example_vpts}. +Example object of class \code{\link{vpts}}(summary.vpts()] with name \code{example_vpts}. } \examples{ -# get summary of example vpts: -summary(example_vpts) +# Reload example_vpts from package (e.g. in case it was altered) +data(example_vpts) -# example_vpts was created with: +# Get summary info +example_vpts + +# example_vpts was created with \dontrun{ vptsfile <- system.file("extdata", "vpts.txt.zip", package = "bioRad") -unzip(vptsfile, exdir = (dirname(vptsfile)), junkpaths = T) +unzip(vptsfile, exdir = (dirname(vptsfile)), junkpaths = TRUE) vptsfile <- substr(vptsfile, 1, nchar(vptsfile) - 4) example_vpts <- read_vpts(vptsfile, radar = "KBGM", wavelength = "S") rcs(example_vpts) <- 11 sd_vvp_threshold(example_vpts) <- 2 example_vpts$attributes$where$lat <- 42.2 example_vpts$attributes$where$lon <- -75.98 -# save(example_vpts, file = "data/example_vpts.rda", compress = "xz") +save(example_vpts, file = "data/example_vpts.rda", compress = "xz") +} } +\seealso{ +\link{summary.vpts} } \keyword{datasets} From 10e6ee2fd6243874076de70328f4bc98ea0255f0 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 17:45:10 +0200 Subject: [PATCH 33/35] Change order to scan, vp, vpts --- R/data.R | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/R/data.R b/R/data.R index bfb78f3c2..6e96da95f 100644 --- a/R/data.R +++ b/R/data.R @@ -1,26 +1,3 @@ -#' Vertical profile (`vp`) example -#' -#' Example object of class [`vp`][summary.vp()] with name `example_vp`. -#' -#' @rdname example_vp -#' -#' @seealso [summary.vp] -#' -#' @examples -#' # Reload example_vp from package (e.g. in case it was altered) -#' data(example_vp) -#' -#' # Get summary info -#' example_vp -#' -#' # example_vp was created with -#' \dontrun{ -#' vpfile <- system.file("extdata", "profile.h5", package = "bioRad") -#' example_vp <- read_vpfiles(vpfile) -#' save(example_vp, file = "data/example_vp.rda") -#' } -"example_vp" - #' Scan (`scan`) example #' #' Example object of class [`scan`][summary.scan()] with name `example_scan`. @@ -45,6 +22,27 @@ #' } "example_scan" +#' Vertical profile (`vp`) example +#' +#' Example object of class [`vp`][summary.vp()] with name `example_vp`. +#' +#' @rdname example_vp +#' +#' @examples +#' # Reload example_vp from package (e.g. in case it was altered) +#' data(example_vp) +#' +#' # Get summary info +#' example_vp +#' +#' # example_vp was created with +#' \dontrun{ +#' vpfile <- system.file("extdata", "profile.h5", package = "bioRad") +#' example_vp <- read_vpfiles(vpfile) +#' save(example_vp, file = "data/example_vp.rda") +#' } +"example_vp" + #' Time series of vertical profiles (`vpts`) example #' #' Example object of class [`vpts`](summary.vpts()] with name `example_vpts`. From c858b5ecc59dbcbc984816f15a589b52286a85e9 Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 17:45:26 +0200 Subject: [PATCH 34/35] Correct typo and remove see also --- R/data.R | 6 +----- man/example_scan.Rd | 3 --- man/example_vp.Rd | 3 --- man/example_vpts.Rd | 5 +---- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/R/data.R b/R/data.R index 6e96da95f..356c72b8f 100644 --- a/R/data.R +++ b/R/data.R @@ -4,8 +4,6 @@ #' #' @rdname example_scan #' -#' @seealso [summary.scan] -#' #' @examples #' # Reload example_scan from package (e.g. in case it was altered) #' data(example_scan) @@ -45,12 +43,10 @@ #' Time series of vertical profiles (`vpts`) example #' -#' Example object of class [`vpts`](summary.vpts()] with name `example_vpts`. +#' Example object of class [`vpts`][summary.vpts()] with name `example_vpts`. #' #' @rdname example_vpts #' -#' @seealso [summary.vpts] -#' #' @examples #' # Reload example_vpts from package (e.g. in case it was altered) #' data(example_vpts) diff --git a/man/example_scan.Rd b/man/example_scan.Rd index ba18c7506..494f646df 100644 --- a/man/example_scan.Rd +++ b/man/example_scan.Rd @@ -28,7 +28,4 @@ example_scan <- pvol$scans[[1]] save(example_scan, file = "data/example_scan.rda") } } -\seealso{ -\link{summary.scan} -} \keyword{datasets} diff --git a/man/example_vp.Rd b/man/example_vp.Rd index 9de20461b..bfb877ab7 100644 --- a/man/example_vp.Rd +++ b/man/example_vp.Rd @@ -27,7 +27,4 @@ example_vp <- read_vpfiles(vpfile) save(example_vp, file = "data/example_vp.rda") } } -\seealso{ -\link{summary.vp} -} \keyword{datasets} diff --git a/man/example_vpts.Rd b/man/example_vpts.Rd index 1478b2607..826860429 100644 --- a/man/example_vpts.Rd +++ b/man/example_vpts.Rd @@ -11,7 +11,7 @@ An object of class \code{vpts} of dimension 1934 x 25 x 15. example_vpts } \description{ -Example object of class \code{\link{vpts}}(summary.vpts()] with name \code{example_vpts}. +Example object of class \code{\link[=summary.vpts]{vpts}} with name \code{example_vpts}. } \examples{ # Reload example_vpts from package (e.g. in case it was altered) @@ -33,7 +33,4 @@ example_vpts$attributes$where$lon <- -75.98 save(example_vpts, file = "data/example_vpts.rda", compress = "xz") } } -\seealso{ -\link{summary.vpts} -} \keyword{datasets} From fee92a71cf763520b9e558f94b2ced7466d1a75e Mon Sep 17 00:00:00 2001 From: peterdesmet Date: Tue, 28 Apr 2020 17:47:47 +0200 Subject: [PATCH 35/35] Add simple test for example objects Could be extended with more tests if need be, but is not part of coverage --- tests/testthat/test-data.R | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-data.R b/tests/testthat/test-data.R index 9a07aa619..10e61f403 100644 --- a/tests/testthat/test-data.R +++ b/tests/testthat/test-data.R @@ -1,3 +1,5 @@ -test_that("... returns error on incorrect parameters", { - +test_that("Example objects are of the correct class", { + expect_s3_class(example_scan, "scan") + expect_s3_class(example_vp, "vp") + expect_s3_class(example_vpts, "vpts") })