proc-real_sensor_values.r 5.33 KB
Newer Older
1 2 3 4 5 6 7 8 9
#' Add 'real'-scale sensor values to glatos detetections
#' 
#' Get transmitter sensor (e.g., depth, temperature) conversion parameters
#' (e.g., intercept, slope) from a Vemco transmitter specification object (e.g.,
#' from \link{read_vemco_tag_specs}, calculate 'real'-scale values 
#' (e.g., depth in meters), and add real values to detection data in a new 
#' column.
#'
#' @param det A \code{glatos_detections} object (e.g., produced by
10 11 12
#'   \link{read_glatos_detections}). 
#'   
#'   \emph{OR} A data frame containing detection
Chris Holbrook's avatar
Chris Holbrook committed
13 14 15 16 17 18 19 20 21 22 23
#'   data with the following columns: 
#'   \describe{ 
#'   \item{transmitter_codespace}{A character string with transmitter code space
#'   (e.g., "A69-1061" for Vemco PPM coding").}
#'   \item{transmitter_id}{A character string with transmitter ID code (e.g.,
#'   "1363" for Vemco PPM coding").}
#'   \item{sensor_value}{A numeric sensor measurement (e.g., an integer for
#'   'raw' Vemco sensor tags).}
#'   \item{sensor_unit}{A character string with \code{sensor_value} units
#'   (e.g., "ADC" for 'raw' Vemco sensor tag detections). }
#'   }
24
#'
25 26 27 28
#' @param tag_specs An object produced by \link{read_vemco_tag_specs}.
#'  
#'   \emph{OR} A data frame containing transmitter specification data with the
#'   following columns:
Chris Holbrook's avatar
Chris Holbrook committed
29 30 31 32 33 34 35 36 37 38 39 40
#'   \describe{ 
#'   \item{code_space}{A character string with transmitter code space (e.g.,
#'   "A69-1061" for Vemco PPM coding").}
#'   \item{id_code}{A character string with transmitter ID code (e.g., "1363"
#'   for Vemco PPM coding").}
#'   \item{sensor_type}{A numeric sensor measurement (e.g., an integer for 'raw'
#'   Vemco sensor tags).}
#'   \item{sensor_range}{A numeric with max. range of the sensor in 'real' units
#'   (e.g., "Meters" for Vemco depth tags). }
#'   \item{sensor_units}{A character string with 'real'-scale units (e.g.,
#'   "Meters" for 'raw' Vemco pressure tags). }
#'   }
41 42
#'   
#'   The following columns are also required for \strong{depth} and
Chris Holbrook's avatar
Chris Holbrook committed
43 44 45 46
#'   \strong{temperature} sensors: 
#'   \describe{ 
#'   \item{sensor_slope}{Slope parameter, for converting 'raw' (ADC) to 'real'
#'   measurements. }
47
#'   \item{sensor_intercept}{Intercept parameter, for converting 'raw' (ADC) to
Chris Holbrook's avatar
Chris Holbrook committed
48 49
#'   'real' measurements. }
#'   }
50 51 52 53 54
#'   
#'   The following columns are also required for \strong{acceleration} sensors:
#'   \describe{
#'   \item{accel_algorithm}{The algorithm used, accelerometers only. }   
#'   \item{accel_sample_rate}{Sample rate used, accelerometers only. }  
55 56
#'   \item{sensor_transmit_ratio}{Sensor transmit rate used, accelerometers
#'   only. }
57 58 59 60 61 62 63 64 65 66 67 68 69
#'   }  
#' 
#' @details Tag spec data are joined to detection data and then raw-scale sensor
#'   measurements are converted to real-scale using \eqn{sensor_value_real =
#'   sensor_intercept + (sensor_value * sensor_slope)}, where \eqn{sensor_value}
#'   is in raw scale.
#'   
#' @details It is possible that \code{transmitter_codespace} and
#'   \code{transmitter_id} are not unique among transmitters, so users must
#'   ensure that the each combination of those columns occurs only once in
#'   \code{tag_specs} and is the correct record for the corresponding tags in
#'   \code{det}.
#'   
70 71
#' @return The input data frame, data.table, or tibble with the following
#'   columns added (see column descriptions above):
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
#'   
#'   \itemize{
#'     \item sensor_range
#'     \item sensor_units
#'     \item sensor_slope
#'     \item sensor_intercept
#'     \item accel_algorithm
#'     \item accel_sample_rate
#'     \item sensor_transmit_ratio
#'     \item sensor_value_real
#'  }
#' 
#' @author Chris Holbrook, \email{cholbrook@usgs.gov}
#' 
#' @examples
#'
#' #get path to example detection file
#' det_file <- system.file("extdata", 
#'   "lamprey_detections.csv", package="glatos")
#'   
#' lamprey_detections <- read_glatos_detections(det_file)
#' 
#' #get path to example Vemco tag spec file
#' spec_file <- system.file("extdata", 
#'   "lamprey_tag_specs.xls", package="glatos")
#'   
#' lamprey_tags <- read_vemco_tag_specs(spec_file, file_format = "vemco_xls")
#' 
#' #note use of '$specs' in tag_specs argument
#' dtc <- real_sensor_values(lamprey_detections, lamprey_tags$specs)
#' 
#' #now view records with sensor measurements
#' dtc[!is.na(dtc$sensor_value_real),]
#'
#' @export

real_sensor_values <- function(det, tag_specs){
  
  #coerce to data.table
  dtc <- data.table::as.data.table(det)
  
  dtc[ , ord := 1:.N] #original order
  
  data.table::setkey(dtc, transmitter_codespace, transmitter_id)

  #coerce to data.table  
  tags <- data.table::as.data.table(tag_specs)

  data.table::setkey(tags, code_space, id_code) 
  
  tags <- tags[ , c("code_space", "id_code", "sensor_range", "sensor_units", 
                    "sensor_slope", "sensor_intercept", "accel_algorithm", 
                    "accel_sample_rate", "sensor_transmit_ratio") 
                , with = FALSE]
  
  #merge
  dtc <- merge(dtc, tags, by.x = data.table::key(dtc), 
                          by.y = data.table::key(tags))
      
  
  data.table::setkey(dtc, ord) #reorder to original
  
  #drop unwanted column
  drop_col <- "ord"
  dtc[ , !drop_col, with = FALSE]
  
  #calculate real values
  dtc[ , sensor_value_real := sensor_intercept + (sensor_value * sensor_slope)]
  
141 142 143 144 145 146 147
  
  #return data.table if input class data.table
  if(inherits(det, "data.table")) return(dtc)
  
  #return tibble if input class tibble
  if(inherits(det, "tbl")) return(tibble::as_tibble(dtc))
  
148 149
  return(as.data.frame(dtc))
}