#' Import function for Delta-T Devices HH2 Soil moisture files
#'
#' @description Imports a file created by the DeltaT handheld soil mositure reader (HH2). Works for profile probes (\code{PR2}) or TDRs (\code{ML3}) files. Sensor type must be specified at import. Re-organises the data of the HH2 file to be compatible with a data frame.
#' @param filename The name of the file to be imported. Character string.
#' @param sensor.type Either \code{"PR2"} for soil mositure profile probe or \code{"ML3"} for TDR. Other values are not allowed.
#' @return Returns a data frame with the elements Time, Sample, Plot, Device, Depth, Percent_Vol, Vol_Error, mV, mV_Error.
#' @export
HH2Import <- function(filename, sensor.type) {
# filename: character string, path and filename of the HH2 file
# sensor.type: character string, either PR2 or ML3
allowed.sensor.types <- c("PR2", "ML3")
stopifnot(sensor.type %in% allowed.sensor.types)
# import the raw file
rawfile <- readLines(filename)
# determine the row with the start of the data
# searching for the character string "Time,Sample,Plot"
header.string <- "Time,Sample,Plot,"
header.line <- grep(header.string, rawfile)
if (sensor.type == "PR2") {
# Column names are not specific, adding sensor depth information to the name
# grab the line that holds the sensor depth information
# dynamic, just in case the depth will change in future instalments
sensor.depth.line <- grep("Sensor Depth", rawfile)
sensor.depth <- gsub(" ", "", rawfile[sensor.depth.line])
sensor.depth <- gsub(",,*", ",", sensor.depth)
sensor.depth <- strsplit(sensor.depth, ",")
sensor.depth <- sensor.depth[[1]][2:length(sensor.depth[[1]])]
}
# header is in line "header_line", have to skip all lines before "header_line"
# therefore, lines to skip are all lines up to "header.line - 1"
skip.line <- header.line - 1
# remove blanks and special characters from "header_line",
# split the raw line into a vector to match a comma separated file
my.header <- gsub(" ", "_", rawfile[header.line])
my.header <- gsub("%", "Percent", my.header)
my.header <- strsplit(my.header, ",")
if (sensor.type == "PR2") {
# add the depth information to the relevant column names
# there are four columns per depth
sensor.depth <- rep(sensor.depth, each = 4)
}
# column names to alter; "Error" refers to both, "% vol" and "mV"!
# adding the depth information at the end of the name.
if (sensor.type == "PR2") {
non.specific.names <- rep(c("Percent_Vol", "Vol_Error", "mV", "mV_Error"), 4)
specific.names <- paste(non.specific.names, sensor.depth, sep = "_")
} else {
specific.names <- rep(c("Percent_Vol", "Vol_Error", "mV", "mV_Error"), 1)
}
# import the HH2 file as csv file
imported <- utils::read.csv(filename, skip = skip.line)
# replace the header with the special characters replaced
names(imported) <- c(names(imported)[1:4], specific.names)
# format the "Time" column
# the handheld reader is not consistent: sometimes the time is provided with seconds,
# sometime there are no seconds
if (is.na(as.POSIXct(imported$Time[1], format = "%d/%m/%Y %H:%M:%S"))) {
imported$Time <- as.POSIXct(imported$Time, format = "%d/%m/%Y %H:%M")
} else {
imported$Time <- as.POSIXct(imported$Time, format = "%d/%m/%Y %H:%M:%S")
}
# split the data frame per sensor depth
# based on column names
my.descriptors <- c("Time", "Sample", "Plot", "Device")
my.descriptor.columns <- which(names(imported) %in% my.descriptors)
if (sensor.type == "PR2") {
# split the data frame per each unique depth
# returns a list of data frames, one for each depth
# each data frame has depth information
my.frames <- lapply(unique(sensor.depth), function(x) {
# creates a search pattern based on sensor depth information
# use the search pattern result to select vectors from the data frame
# add depth information to resulting data frames
# remove depth information from vector names, as it's now redundant
selector <- paste(x, "$", sep = "")
my.columns <- grep(selector, names(imported))
my.frame <- imported[, c(my.descriptor.columns, my.columns)]
my.frame$Depth <- as.numeric(as.character(x))
# now that there is depth information for each sample,
# removing the depth from the names again
# search pattern for "_" followed by repeated numbers at the end of the character string
names(my.frame) <- gsub("_[0-9]*$", "", names(my.frame))
return(my.frame)
})
# put the data frames from the list back together into one data frame
imported <- do.call(rbind, my.frames)
}
# potential to do:
# there is an empty column in the csv file on the right end
# removing this column, but only when it is empty - just in case
# leaving it alone for now, who knows if this column serves a purpose in the future
# re-order column order in data frame
if (sensor.type == "PR2") {
imported <- imported[, c("Time", "Sample", "Plot", "Device", "Depth", "Percent_Vol", "Vol_Error", "mV", "mV_Error")]
} else {
imported <- imported[, c("Time", "Sample", "Plot", "Device", "Percent_Vol", "Vol_Error", "mV", "mV_Error")]
}
# return the imported data frame
return(imported)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.