#' @export Warping
Warping <- function(Spectrum_data, normalization.type = c("median", "mean",
"firstquartile", "peak", "none"), fromto.normW = c(3.05, 4.05),
reference.choice = c("fixed", "before", "after", "manual"), reference = 1,
optim.crit = c("RMS", "WCC"), ptw.wp = FALSE, K = 3, L = 40, lambda.smooth = 0,
deg = 3, lambda.bspline = 0.01, kappa = 1e-04, max_it_Bspline = 10,
returnReference = FALSE, returnWarpFunc = FALSE, verbose = FALSE) {
# Mean square difference function definition --------------------------------------
meanSqrDiff <- function(m, row){
# for the row ref, x - m[ref,] is 0 to get, the mean, we divide by
# nrow(data)-1 because the row ref is ignored we could actually just do
# the sum and not the mean, both choices are good
return(sum(apply(m, 1, function(x) sum((x - m[row, ])^2, na.rm = TRUE)))/(nrow(m) -
1))
}
# Data initialisation and checks ----------------------------------------------
checkArg(verbose, c("bool"))
begin_info <- beginTreatment("Warping", Spectrum_data, force.real = TRUE,verbose = verbose)
Spectrum_data <- begin_info[["Signal_data"]]
normalization.type <- match.arg(normalization.type)
reference.choice <- match.arg(reference.choice)
optim.crit <- match.arg(optim.crit)
checkArg(K, c("int", "pos"))
checkArg(L, c("int", "pos0"))
checkArg(lambda.smooth, c("num", "pos0"))
checkArg(deg, c("int", "pos"))
checkArg(lambda.bspline, c("num", "pos0"))
checkArg(kappa, c("num", "pos0"))
checkArg(max_it_Bspline, c("int", "pos"))
if (reference.choice == "fixed" & !(reference[1] %in% row.names(Spectrum_data))) {
checkArg(reference, c("int", "pos"))
reference <- row.names(Spectrum_data)[reference]
}
if (reference.choice == "manual" & (length(reference) != dim(Spectrum_data)[2] | !is.numeric(reference))) {
stop("reference is misspecified with reference.choice == manual")
}
if (L > 0 && L <= deg) {
stop("L should be greater than deg because with 1 interval, there is already deg+1 Bsplines.")
}
# adding the manual reference to the spectral matrix
if (reference.choice == "manual") {
colnam <- colnames(Spectrum_data)
rownam <- rownames(Spectrum_data)
Spectrum_data <- rbind(reference, Spectrum_data)
Spectrum_data <- as.matrix(Spectrum_data)
colnames(Spectrum_data) <- colnam
rownames(Spectrum_data) <- c("manual_ref", rownam)
}
n <- nrow(Spectrum_data)
m <- ncol(Spectrum_data)
# Data pre-normalization ----------------------------------------------
if (normalization.type != "none") {
norm.res <- Normalization(Spectrum_data, type.norm = normalization.type,
fromto.norm = fromto.normW, returnFactor = TRUE)
Spectrum_data <- norm.res[["Spectrum_data"]]
normFactor <- norm.res[["factor"]]
}
# Warping -----------------------------------------------------
rnames <- rownames(Spectrum_data)
if (n > 1) {
# (pool of potential) candidate(s) as reference spectrum
if (reference.choice == "fixed") {
pool <- reference
} else if (reference.choice == "before") {
argmin <- which.min(sapply(rnames, function(i) meanSqrDiff(Spectrum_data,
i)))
pool <- names(argmin)
} else if (reference.choice == "after") {
pool <- rnames
} else {pool = "manual_ref"} # dummy value that works
best.meanSqrDiff <- NULL
best.Warped_data <- NULL
decreasing <- FALSE
# Warping for each potential reference specturm
for (reference in pool) {
ref <- Spectrum_data[reference, ] # reference spectrum
samp_rnames <- rnames[rnames != reference]
sample <- Spectrum_data[samp_rnames, , drop = FALSE] # spectra to be warped
beta <- rep(0, K + 1) # starting coefficients
cur.Warped_data <- Spectrum_data # initialize the matrix of warped spectra
warp.func <- Spectrum_data # initialize the matrix of estimated warping functions
# if (reference.choice %in% c("fixed", "before", "after")) {
warp.func[reference, ] <- 0
# }
if (K >= 1) {
# This is beta_1 which should be approximately 1 because if they are
# perfectly aligned w(v) = v = 0*1 + 1*v + 0*v^2 + 0*v^3
beta[2] <- 1
}
if (ptw.wp) {
# A. Parametric time warping with polynomials
ptw.output <- ptw::ptw(ref, sample, optim.crit = optim.crit,
init.coef = beta, smooth.param = lambda.smooth)
cur.Warped_data[samp_rnames, ] <- ptw.output$warped.sample
# We transpose because 'diff' is along the columns
w <- t(ptw.output$warp.fun)
warp.func[samp_rnames, ] <- w
} else {
# or B. Semi-parametric time warping with polynomials AND B splines
if (optim.crit == "WCC") {
stop("WCC is only implemented in ptw, set ptw.wp = TRUE to use WCC.")
}
for (samp_rname in samp_rnames) {
sw.output <- SingleWarp(ref = ref, sample = sample[samp_rname,
], beta = beta, L = L, lambda.smooth = lambda.smooth,
deg = deg, lambda.bspline = lambda.bspline, kappa = kappa,
max_it_Bspline = max_it_Bspline)
warped <- sw.output$warped
w <- sw.output$w
cur.Warped_data[samp_rname, ] <- warped
warp.func[samp_rname, ] <- w
}
}
cur.meanSqrDiff <- meanSqrDiff(cur.Warped_data, reference)
# Update the results if current is best
if (is.null(best.meanSqrDiff) || cur.meanSqrDiff < best.meanSqrDiff) {
best.meanSqrDiff <- cur.meanSqrDiff
best.Warped_data <- cur.Warped_data
decreasing <- (FALSE %in% (diff(w) > 0))
}
}
# check if warping function is decreasing
if (decreasing) {
warning("The warping function is not increasing for the sample",
samp_rname, ".")
}
} else {
best.Warped_data <- Spectrum_data
}
# Data finalisation ----------------------------------------------
best.Warped_data <- best.Warped_data*normFactor # denormalize the spectra
if (reference.choice=="manual") {
best.Warped_data <- best.Warped_data[-1,] # remove the manual reference spectrum
}
Spectrum_data <- endTreatment("Warping", begin_info, best.Warped_data,verbose = verbose)
if (returnReference) {
if (returnWarpFunc) {
return(list(Spectrum_data = Spectrum_data, Reference = reference,
Warp.func = warp.func))
} else {
return(list(Spectrum_data = Spectrum_data, Reference = reference))
}
} else {
if (returnWarpFunc) {
return(list(Spectrum_data = Spectrum_data, Warp.func = warp.func))
} else {
return(Spectrum_data)
}
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.