Nothing
#' Function to detect year transitions and calculate cumulative age
#' of model results
#'
#' Takes the result of iterative growth modeling and
#' transforms data from Julian Day (0 - 365) to cumulative
#' day of the shell age by detecting where transitions
#' from one year to the next occur and adding full years
#' (365 days) to simulations in later years.
#' @param resultarray Array containing the full results of
#' the optimized growth model
#' @param threshold Artificial threshold value used to recognize
#' peaks in occurrences of year transitions (default = 5)
#' @param plotyearmarkers Should the location of identified year
#' transitions be plotted? \code{TRUE/FALSE}
#' @return A new version of the resultarray with Julian Day model
#' estimates replaced by estimates of cumulative age of the record
#' in days.
#' @references package dependencies: zoo 1.8.7
#' @importFrom graphics plot
#' @examples
#' testarray <- array(NA, dim = c(20, 16, 9)) # Create empty array
#' # with correct third dimension
#' windowfill <- seq(50, 500, 50) # Create dummy simulation data
#' # (ages) to copy through the array
#' for(i in 6:length(testarray[1, , 1])){
#' testarray[, i, 3] <- c(windowfill, rep(NA, length(testarray[, 1, 3]) -
#' length(windowfill)))
#' windowfill <- c(NA, (windowfill + 51) %% 365)
#' }
#' testarray[, 1, 3] <- seq(1, length(testarray[, 1, 3]), 1) # Add
#' # dummy /code{D} column.
#' testarray2 <- cumdy(testarray, 3, FALSE) # Apply function on array
#' @export
cumdy <- function(resultarray, # Align Day of year results from modeling in different windows to a common time axis
threshold = 5, # Threshold for separating peaks in year changes for marking the transitions between years
plotyearmarkers = TRUE
){
dat <- resultarray[, 1:5, 3]
Yearends <- rbind(rep(NA, length(resultarray[1, -(1:length(dat[1, ])), 3])), diff(resultarray[, -(1:length(dat[1, ])), 3]) < 0) # Matrix of positions in individual windows where end of year (day 365) is recorded
Tyearmarkers <- cbind(c(0, dat[-nrow(dat), 1]) + c(0, diff(dat[, 1])), rowSums(Yearends, na.rm = TRUE)) # Aggregate of end of year (Day = 365) positions across windows against depth of record
Tyearmarkers <- cbind(Tyearmarkers, c(rep(0, floor(threshold / 2)), zoo::rollmean(Tyearmarkers[, 2], threshold, align = "center"), rep(0, threshold - floor(threshold / 2) - 1))) # Add moving average of threshold value, pad with zeroes to match column length
if(!all(Tyearmarkers[, 3] < (3 / threshold))){Tyearmarkers[which(Tyearmarkers[, 3] < (3 / threshold)), 3] <- 0} # Remove small numbers consisting of averages of 1 or 2 yearends in windows except in cases with very low resolution
pks <- which(diff(sign(diff(Tyearmarkers[, 3], na.pad = FALSE)), na.pad = FALSE) < 0) + 2 # Find peaks in the number of yearmarkers by taking the second derivative
Tyearmarkers <- cbind(Tyearmarkers, rep(0, length(Tyearmarkers[, 3]))) # Add column to store yearmarkers based on age modeling
for(i in 1:(length(which(diff(pks) > threshold)) + 1)){ # Loop through the instances where peaks are far enough apart to be taken as separate (as judged through the threshold)
Tyearmarkers[mean(pks[(c(0, which(diff(pks) > threshold), length(pks))[i] + 1) : c(0, which(diff(pks) > threshold), length(pks))[i + 1]]), 4] <- 1 # Combine peaks that cluster together and add markers to the mean positions where windows record the end of the year
}
Tyearends <- cbind(seq(1, sum(Tyearmarkers[, 4]), 1), Tyearmarkers[which(Tyearmarkers[, 4] == 1), 1]) # Find numbers and positions of mean yearmarkers in record based on age modeling
if(plotyearmarkers == TRUE){
dev.new()
plot(Tyearmarkers[, c(1, 3)], type = "l") # Plot aggregate of yearmarkers
points(Tyearmarkers[which(Tyearmarkers[, 4] == 1), c(1, 3)], col = "red") # Plot location of yearmarkers
}
Yearends[which(Yearends == TRUE)] <- apply(abs(outer(Tyearends[, 2], Tyearmarkers[which(Yearends == TRUE) %% nrow(Yearends), 1], "-")), 2, which.min) # Find distance values for year ends in all windows and replace the positions of the year ends with the number of years along the records based on the nearest peak in yearends found earlier
for(col in 1:ncol(Yearends)){ # Loop through columns and create matrix of the cumulative year in which the datapoints of all models are set.
Yearends[min(which(!is.na(Yearends[, col]))) - 1, col] <- 0 # Replace the last NA before the modeled values start with a zero to compensate for the missing first value due to diff() function above (first line of function)
if(length(Yearends[which(Yearends[, col] > 0), col]) > 0){ # Check if there are year ends in the column
X <- Yearends[which(Yearends[, col] > 0), col] # Find values associated with the year ends
row <- which(Yearends[, col] %in% X) # Find rows in which these year end values are contained
row0 <- which(Yearends[, col] == 0) # Find rownumbers of zeroes in column
if(length(row) > 1){ # Check if multiple year ends are present on the column
rowcomp <- outer(row0, row, "-") # Match rownumbers of all zeroes in the column with the rownumbers of all year end values
rowcomp[rowcomp < 0] <- NA # Remove all instances where zeroes precede year ends
Yearends[row0, col] <- as.numeric(apply(rowcomp, 1, which.min)) # Replace zeroes with closest year end directly above
Yearends[row0[which(is.na(Yearends[row0, col]))], col] <- X[1] - 1 # Replace all zeroes above the year end with the number of the previous year (year end - 1)
}else{ # Alternatively, if there is only one year end:
Yearends[row0[which(row0 > row)], col] <- Yearends[row, col] # Replace all zeroes below the year end with the number belonging to the year end
Yearends[row0[which(row0 < row)], col] <- Yearends[row, col] - 1 # Replace all zeroes above the year end with the number of the previous year (year end - 1)
}
}else if(col > 1){
Yearends[which(!is.na(Yearends[, col])), col] <- rep(as.numeric(names(sort(table(Yearends[, (col - 1)]), decreasing = TRUE)[1])), length(which(!is.na(Yearends[, col])))) # If no yearends are present, replace all zeroes with the most common year in the previous column
}
}
result <- resultarray[, , 3] + cbind(matrix(0, ncol = length(dat[1, ]), nrow = length(Yearends[,1])), Yearends) * 365 # Create matrix of cumulative days in model centered on position of highest summer value (default t_maxtemp = day 182.5) and based on length of day (default T_per = G_per = 365)
return(result)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.