R/ConvertFrameDepth.R

#' @title MMR frame/depth conversion helper function
#' @author Brandon McNellis
#'
#' @description
#'
#' @return
#'
#' Returns the original dataframe with new 'real.depth' and 'tube.depth' columns, the former
#' being the actual soil depth of the measurement oint and 'tube'depth' being the relative
#' depth along the length of the tube, both in meters.
#'
#' Units of 'depth' are in centimeters.
#'
#' @param data          Input dataframe. See 'details'.
#' @param tube.length   Length of the MMR tube, in meters. Defauls to 1.
#' @param tube.angle    Angle of tube install, relative to vertical. See 'details'.
#' @param max.frames    Maximum number of frames in a full tube depth.
#' @param frame.length  Length of a frame, in centimeters.
#'
#' @details
#'
#' The default frame length here is from a particular MMR manufacturer's
#' technical specifications.
#'
#' \code{'tube.angle'} is given as degrees relative to the vertical - must be the same
#' length as unique tube identifiers in the dataset, and each identifier is matched
#' according to \code{sort}. Units are in degrees and converted to radians for passing
#' to R internal trig functions.
#'
#' @export
#' @examples
#' data <- read.table("SDEF_2016_RootLengths.txt", sep='\t', header=TRUE)
#' test.data <- data
#' test.data$date <- as.character(test.data$date)
#' test.data$date <- as.Date(test.data$date, format="%m/%d/%Y")
#' test.data <- ConvertFrameDepth(test.data)
#' plot(data$frame, test.data$depth)
#' # Should be 1:1 correspondence between frame # and depth in the new dataframe
ConvertFrameDepth <- function(data, tube.length = 1, tube.angle = NULL,
                              frame_length = 0.675,
                              max.frames = 100) {
  # Data input validity check section ####
  stopifnot(
    is.data.frame(data),
    "frame" %in% colnames(data),
    "tube" %in% colnames(data),
    length(tube.length) == 1,
    class(tube.length) == "numeric",
    class(data$frame) == "numeric" | class(data$frame) == "integer"
  )
  if (length(tube.angle) < 1) {
    tube.angle <- rep(x = 45, times = length(unique(data$tube)))
  } else {
    stopifnot(
      length(tube.angle) == unique(data$tube),
      class(tube.angle) == "numeric",
      all(tube.angle < 90),
      all(tube.angle > 0)
    )
    if (any(tube.angle) < 2) {
      stop("Tube angles must be >2.0 degrees - are they radians?")
    }
  }

  # Calculation section ####
  frame_depth <- data[["frame"]] * frame_length
  names(tube.angle) <- sort(unique(data[["tube"]]))
  real_depth <- frame_depth * cos(tube.angle[data[["tube"]]] * ((pi / 180)))
  real_depth <- round(real_depth, digits = 2)

  # Wrap-up & return
  data <- data.frame(data, real_depth)
  return(data)
}
bmcnellis/SDEF.analysis documentation built on June 4, 2019, 10 a.m.