R/AlradSpectra.R

Defines functions AlradSpectra

Documented in AlradSpectra

#' AlradSpectra: a Quantification Tool for Soil Properties Using Spectroscopic Data in R
#'
#' AlradSpectra was developed to accomplish tasks such as perform a large range of spectral preprocessing techniques, implement several multivariate calibration methods, which can provide well-fitted and accurate models, statistics assessment, graphical output, validate the models using independent data sets, and predict unknown samples.
#' @author Andre C. Dotto, \email{andrecdot@gmail.com}
#' @author Diego J. Gris, \email{diegojgris@gmail.com}
#' @import gWidgets2
#' @export

AlradSpectra <- function() {
  
  # Create environment for AlradSpectra
  AE <- new.env()
  
  ###################################################
  ### Structural functions
  ###################################################
  
  # Display alert function
  falert       <- function(t,w,h,l)    {AE$alert <- gbasicdialog(title = t, parent = window, do.buttons = F)
  size(AE$alert) <- c(w, h)
  g <- ggroup(cont = AE$alert, horizontal = F)
  glabel(l, cont = g)
  }
  # Warning handler
  fwarning     <- function(w)         {dispose(AE$alert)
    gmessage(msg = w$message, title = "Warning", icon="warning", parent = window)
    stop()
  }
  # Error handler
  ferror       <- function(e)         {dispose(AE$alert)
    gmessage(msg = e$message, title = "Error", icon="error", parent = window)
    stop()
  }
  # Makes sure the user really wants to quit Alrad when closing the window
  fconfirmquit <- function(h, ...)    {sure <- gconfirm("Clear AlradSpectra and quit?", parent=h$obj)
  if(as.logical(sure)) {
    rm(list = ls(AE),
       envir = AE) #Remove everything in Alrad Environment
    return(FALSE) #Close
  } else{
    return(TRUE) #Don't close
  }
  }
  # Clears all data, empties forms and resets Alrad to initial status
  fnew         <- function(...)       {sure <- gconfirm("Clear AlradSpectra and \nstart a new project?",
                                                        title="New", icon="warning", parent=window)
  if(as.logical(sure)) {
    svalue(file.browse)      <- ""
    svalue(file.sep)         <- ","
    svalue(file.dec)         <- "."
    svalue(spc.start.col)    <- ""
    svalue(spc.end.col)      <- ""
    svalue(soil.var.col)     <- ""
    svalue(soil.var.nm)      <- ""
    select.dataset[]         <- ""
    svalue(pred.file.browse) <- ""
    svalue(pred.file.sep)    <- ","
    svalue(pred.file.dec)    <- "."
    select.model[]           <- ""
    svalue(notebook)         <- 1 #Focus on import tab
    enabled(viewdt.button) = FALSE
    enabled(plotdt.button) = FALSE
    enabled(viewst.button) = FALSE
    enabled(viewhs.button) = FALSE
    enabled(pp) = FALSE
    enabled(models) = FALSE
    enabled(mdl) = FALSE
    enabled(pred) = FALSE
    rm(list = ls(AE), envir = AE) #Remove everything in Alrad Environment
  }
  }
  fopen        <- function(...)        {proj.browse <- gfile("Open File", type="open",
                                                             filter=c("Workspace image (.RData)"="RData"),
                                                             cont = window)
  if(!(is.na(proj.browse))) {
    rm(list = ls(AE), envir = AE) #Remove everything in Alrad Environment
    alertop <- falert("Loading Project", 150, 20, "Wait...")
    Sys.sleep(1) #Wait for alert to be shown
    load(proj.browse, envir=AE)
    svalue(file.browse)    <- AE$file.location
    svalue(file.sep)       <- AE$file.separator
    svalue(file.dec)       <- AE$file.decimal
    svalue(spc.start.col)  <- AE$spectra.start.column
    svalue(spc.end.col)    <- AE$spectra.end.column
    svalue(soil.var.col)   <- AE$soil.var.column
    svalue(soil.var.nm)    <- AE$soil.var.name
    svalue(notebook)       <- 1 #Focus on import tab
    enabled(viewdt.button) = TRUE
    enabled(plotdt.button) = TRUE
    enabled(viewst.button) = TRUE
    enabled(viewhs.button) = TRUE
    enabled(pp) = TRUE #Enable preprocessing module
    enabled(models) = TRUE #Enable modeling module
    select.dataset[]       <- AE$dataset
    svalue(select.dataset) <- AE$sel.data
    svalue(split.val)      <- AE$sel.splt
    if(exists("Train", envir=AE)) {#If there is a training dataset (data has been split)
      enabled(mdl) = TRUE # Enable models group
      if(AE$sel.splt!=0) { #If validation set size is not equal to zero
        enabled(homo.button) = TRUE #Enable homogeneity test button
        enabled(desc.button) = TRUE #Enable descriptive stats button
      }
      enabled(boxplot.button) = TRUE #Enable boxplot button
    }
    if(length(AE$pred.models)!=0) {#If there are models in the loaded data
      select.model[]       <- AE$pred.models
      svalue(select.model) <- AE$pred.models[1]
      enabled(pred) = TRUE #Enable prediction module
    }
    if(exists("spc.pred", envir=AE)) {#If there is a dataset for prediction
      svalue(pred.file.browse) <- AE$pred.file.location
      svalue(pred.file.sep)    <- AE$pred.file.separator
      svalue(pred.file.dec)    <- AE$pred.file.decimal
      enabled(pred.predict) = TRUE #Enable predict group
    }
    dispose(alertop)
    gmessage(msg = "Project loaded!", title = "Open Project", parent = window)
  }
  }
  # Saves current project with all R workspace
  fsave        <- function(...)        {fdialog <- gfile("Save Project", type="save", initial.filename="Project", container=window,
                                                         filter=c("Workspace image (.RData)"="RData"),
                                                         cont = window)
  #If fdialog is not equal to NA, keep running
  if(!(is.na(fdialog))) {
    falert("Saving Project", 150, 20, "Wait...")
    Sys.sleep(1) #Wait for alert to be shown
    fname <- paste0(fdialog,".RData")
    save(list = ls(AE, all.names = TRUE), file = fname, envir = AE)
    dispose(AE$alert)
    gmessage(msg = "Project saved!", title = "Save Project", parent = window)
  }
  }
  # Handler for quit action. Makes sure the user really wants to quit Alrad.
  fquit        <- function(...)        {sure <- gconfirm("Clear AlradSpectra and quit?", icon="warning", parent=window)
  if(as.logical(sure)) {
    rm(list = ls(AE), envir = AE) #Remove everything in Alrad Environment
    dispose(window)
  }
  }
  # Creates and shows the window with information about AlradSpectra
  fabout       <- function(...)       {aboutwin <- gwindow("About AlradSpectra", width=450, height=430, parent = window)
  wingroup <- ggroup(horizontal = FALSE, container = aboutwin)
  gimage(system.file("images","AlradLogo.png", package="AlradSpectra"), container = wingroup)
  glabel(paste0("AlradSpectra: a Quantification Tool for Soil Properties\n",
                "Using Spectroscopic Data in R\n\n",
                "Developed by researchers at\n",
                "Universidade Federal de Santa Maria and\n",
                "Universidade Federal de Santa Catarina, Brazil.\n\n",
                "Authors and contributors:\n",
                "<b>A</b>","ndre Dotto\n",
                "<b>L</b>","uis Ruiz\n",
                "<b>R</b>","icardo Dalmolin\n",
                "<b>A</b>","lexandre ten Caten\n",
                "<b>D</b>","iego Gris\n",
                "\n",
                "How to cite AlradSpectra:\n",
                "Dotto, Andre Carnieletto; Dalmolin, Ricardo Simão Diniz;\n",
                "Caten, Alexandre ten; Gris, Diego José; Ruiz, Luis Fernando Chimelo,\n",
                "AlradSpectra: a Quantification Tool for Soil Properties Using\n",
                "Spectroscopic Data in R. Rev Bras Cienc Solo. 2019, 43, e0180263.\n",
                "Doi: https://dx.doi.org/10.1590/18069657rbcs20180263\n",
                "\n",
                "AlradSpectra source code is available at:\n",
                "<i>github.com/AlradSpectra/AlradSpectra</i>",
                sep="", collapse=""
  ),
  markup = TRUE, container = wingroup
  )
  gbutton("View AlradSpectra article on the Internet", cont = wingroup, handler = function(...) 
    browseURL("https://www.rbcsjournal.org/article/alradspectra-a-quantification-tool-for-soil-properties-using-spectroscopic-data-in-r/"))
  
  }
  # Opens up a dialog to search for file to be imported
  fbrowse      <- function(h, ...)    {svalue(h) <- gfile("Open File", type="open",
                                                          filter= list("Delimited Files (*.txt, *.csv)" = list(patterns = c("*.txt", "*.csv")),
                                                                       "All files" = list(patterns = c("*"))), cont = window)
  }
  # Imports csv file to Alrad environment and sets variables used afterwards
  fimport      <- function(...)       {falert("Importing File", 150, 20, "Wait...")
    tryCatch({AE$file.location        <- svalue(file.browse)
    AE$file.separator       <- svalue(file.sep)
    AE$file.decimal         <- svalue(file.dec)
    if(AE$file.separator=="") {
      AE$alldata <- read.delim(file = AE$file.location,
                               header = as.logical(svalue(file.header)),
                               dec = AE$file.decimal)
    } else {
      AE$alldata <- read.table(file = AE$file.location,
                               header = as.logical(svalue(file.header)),
                               sep = AE$file.separator,
                               dec = AE$file.decimal, 
                               quote = "" )
    }
    AE$spectra.start.column <- as.numeric(svalue(spc.start.col))
    AE$spectra.end.column   <- as.numeric(svalue(spc.end.col))
    AE$spectra.start.number <- as.numeric(substring(colnames(AE$alldata)[AE$spectra.start.column], 2))
    AE$spectra.end.number   <- as.numeric(substring(colnames(AE$alldata)[AE$spectra.end.column], 2))
    AE$soil.var.column      <- as.numeric(svalue(soil.var.col))
    AE$soil.var.name        <- svalue(soil.var.nm)
    fonlyspectra() #Create dataframe with spectra only
    AE$dataset              <- c("Original")
    select.dataset[]              <-  AE$dataset
    svalue(select.dataset)        <- "Original"
    AE$pred.models          <- c()
    },
    warning = function(w) fwarning(w),
    error =  function(e) ferror(e)
    )
    enabled(viewdt.button) = TRUE
    enabled(plotdt.button) = TRUE
    enabled(viewst.button) = TRUE
    enabled(viewhs.button) = TRUE
    enabled(pp) = TRUE
    enabled(models) = TRUE
    dispose(AE$alert)
    gmessage(msg = "Import successful!", title = "File import", parent = window)
  }
  # Create dataframe that contains only the spectral data to be used for preprocessing
  fonlyspectra <- function(...)       {spc <- AE$alldata[,AE$spectra.start.column:AE$spectra.end.column]
  colnames(spc) <- as.numeric(substring(colnames(AE$alldata)[AE$spectra.start.column:AE$spectra.end.column], 2))
  AE$Original <- spc
  }
  # Opens up a window to display imported data in tabular form
  fview        <- function(h, w, ...) {gtable(h, cont = gwindow("View data", width = w, height = 300, parent = window))}
  # Plots spectral data
  fplot        <- function(h, s, e,
                           ylab="Reflectance", ...) {plotwin <- gwindow("Plot", width = 800, height = 600, parent = window)
                           wingroup <- ggroup(horizontal=FALSE, cont=plotwin)
                           ggraphics(width = 800, height = 600, dpi = 300, cont = wingroup)
                           Sys.sleep(1) #Wait for window creation before trying to plot to avoid errors
                           gbutton("Save plot", cont=wingroup, handler = function(...) fsaveplot(2400, 1800))
                           graphics::matplot(colnames(h), t(h), xlim = c(s, e),
                                             type = "l",
                                             xlab = "Wavelength (nm)",
                                             ylab = ylab)
  }
  # Export plot as png graphics file
  fsaveplot    <- function(w, h,...)  {fdialog <- gfile("Save File", type="save", initial.filename="Plot", container=window,
                                                        filter=c("Portable Network Graphics (.png)"="png"))
  #If fdialog is not equal to NA, keep running
  if(!(is.na(fdialog))) {fname <- paste0(fdialog,".png")
  dev.copy(png, fname, width=w, height=h, res=300, antialias = "cleartype")
  dev.off() #Close graphics device
  }
  }
  # View Y variable descriptive statistics
  fdescy       <- function(...)       {falert("Descriptive Statistics", 150, 20, "Wait...")
    descstats  <- fitdistrplus::descdist(AE$alldata[,AE$soil.var.column], graph=F)
    descnames  <- rbind("Obs","Min","Max","Mean","Median","Std Dev","Skewness","Kurtosis")
    descvalues <- rbind(nrow(AE$alldata),
                        round(descstats$min,2),
                        round(descstats$max,2),
                        round(descstats$mean,2),
                        round(descstats$median,2),
                        round(descstats$sd,2),
                        round(descstats$skewness,2),
                        round(descstats$kurtosis,2))
    desctable  <- data.frame("Parameter"=descnames,"Value"=descvalues)
    dispose(AE$alert)
    descwin    <- gwindow("Descriptive statistics", width=150, height=270, parent=window)
    desc.lyt   <- glayout(horizontal=FALSE, container=descwin)
    desc.lyt[1,1,expand=TRUE, fill='y']  <- gtable(as.data.frame(desctable), cont = desc.lyt)
    desc.lyt[2,1,expand=TRUE] <- gbutton("Save results", cont=desc.lyt,
                                         anchor=c(0,-1),
                                         handler=function(...) fsaveresults(desctable))
  }
  # Plots y histogram
  fhist        <- function(...)       {plotwin  <- gwindow("Histogram", width = 600, height = 500, parent = window)
  wingroup <- ggroup(horizontal=FALSE, cont=plotwin)
  ggraphics(width = 600, height = 500, dpi = 300, cont = wingroup)
  Sys.sleep(1) #Wait for window creation before trying to plot to avoid errors
  gbutton("Save plot", cont=wingroup, handler = function(...) fsaveplot(1500, 1350))
  histo    <- ggplot2::ggplot(AE$alldata,
                              ggplot2::aes(x=AE$alldata[,AE$soil.var.column])) + 
    ggplot2::geom_histogram(ggplot2::aes(fill = ..count..), binwidth = 0.5) +
    ggplot2::scale_fill_gradient("Frequency", low = "darkolivegreen2",
                                 high = "dodgerblue3") +
    ggplot2::labs(x = AE$soil.var.name, y = "Frequency") +
    ggplot2::guides(fill=FALSE)
  print(histo)
  }
  # Export preprocessed spectra as csv file
  fsavespectra <- function(h, ...)    {fdialog <- gfile("Save File", type="save", initial.filename="Output", container=window,
                                                        filter=c("Comma Separated Values (.csv)"="csv"))
  #If fdialog is not equal to NA, keep running        
  if(!(is.na(fdialog))) {fname      <- paste0(fdialog,".csv")
  spectrum   <- seq(AE$spectra.start.column,
                    AE$spectra.end.column)
  exportdata <- cbind(AE$alldata[,-spectrum], h)
  write.csv(exportdata, row.names = FALSE, file = fname)
  }
  }
  # Adds preprocessing to combobox in Model tab only if it is not already there
  faddtodtset  <- function(h, ...) {present <- is.element(h, AE$dataset)
  if(present==FALSE)
    AE$dataset <- c(AE$dataset, h)
  select.dataset[] <- AE$dataset
  svalue(select.dataset) <- ifelse(exists("Train", envir=AE), AE$sel.data, "Original")
  }
  # Splits dataset in training and validaton sets
  fsplit       <- function(...)       {#set.seed(1)
    AE$sel.data <- svalue(select.dataset)
    AE$sel.splt <- svalue(split.val)
    x           <- eval(parse(text = paste0("AE$", AE$sel.data))) #Get selected dataset
    x           <- cbind(x, AE$alldata[AE$soil.var.column]) #Join spectral data and soil property
    indices     <- sample(1:nrow(x), size = (AE$sel.splt/100)*nrow(x)) #Random sampling
    if(AE$sel.splt==0) #If validation set size is equal to zero
      t         <- x #Training set corresponds to all data
    else
      t         <- x[-indices,] #Training set
    v           <- x[ indices,] #Validation set
    colnames(t) <- paste("X", colnames(t), sep = "") #Add X before wavelength
    colnames(v) <- paste("X", colnames(v), sep = "") #Add X before wavelength
    AE$Train    <- t
    AE$Val      <- v
    AE$last.col <- ncol(AE$Train) #Get position of last column (soil variable)
    #Create formula for models
    AE$form.mdl <- as.formula(paste(colnames(AE$Train[AE$last.col]),"~",
                                    paste(names(AE$Train)[c(1:AE$last.col-1)],
                                          collapse="+"), collapse=""))
    enabled(mdl) = TRUE #Enable models module
    if(AE$sel.splt!=0) { #If validation set size is not equal to zero
      enabled(homo.button) = TRUE #Enable homogeneity test button
      enabled(desc.button) = TRUE #Enable descriptive stats button
    }
    enabled(boxplot.button) = TRUE #Enable boxplot button
    gmessage(paste("Number of training samples:", nrow(AE$Train),
                   "\n\nNumber of validation samples:", nrow(AE$Val)),
             title = "Split", parent = window)
  }
  # Homogeneity of variance test
  fhomo        <- function(...)       {falert("Levene's test", 150, 20, "Wait...")
    categories <- as.factor(c(rep(1,length(AE$Train[,AE$last.col])),
                              rep(2,length(AE$Val[,AE$last.col]))))
    homog.test <- car::leveneTest(AE$alldata[,AE$soil.var.column]~categories)
    if(homog.test$`Pr(>F)`[1]>0.05) {
      lev.res <- c("is", 'are')
    } else {
      lev.res <- c("is not", 'are not')
    }
    dispose(AE$alert)
    gmessage(paste("Levene's Test for Homogeneity of Variance",
                   "\n\nIf the P-value is greater than 0.05 (significance level), \nthe null hypothesis",
                   "is not rejected and it is concluded \nthat there is no significant difference",
                   "between \nthe variances of the two groups.",
                   "\n\nSignificance level = 0.05",
                   "\nDegrees of freedom =",homog.test$Df[2],
                   "\nF-value =", round(homog.test$`F value`[1], 3),
                   "\nP-value =", round(homog.test$`Pr(>F)`[1], 3),
                   "\n\nTest interpretation:",
                   "\nThe P-value",lev.res[1],"greater than 0.05.",
                   "\nTraining and Validation groups",lev.res[2],"homogeneous."),
             title = "Homogeneity of variance test", parent = window)
  }
  # View train and validation descriptive statistics
  fdesc        <- function(...)       {falert("Descriptive statistics", 150, 20, "Wait...")
    trainds    <- fitdistrplus::descdist(AE$Train[,AE$last.col], graph=F)
    valds      <- fitdistrplus::descdist(AE$Val[,AE$last.col], graph=F)
    descnames  <- rbind("Obs","Min","Max","Mean","Median","Std Dev","Skewness","Kurtosis")
    descvalues <- rbind(c(nrow(AE$Train), nrow(AE$Val)),
                        c(round(trainds$min,2), round(valds$min,2)),
                        c(round(trainds$max,2), round(valds$max,2)),
                        c(round(trainds$mean,2), round(valds$mean,2)),
                        c(round(trainds$median,2), round(valds$median,2)),
                        c(round(trainds$sd,2), round(valds$sd,2)),
                        c(round(trainds$skewness,2), round(valds$skewness,2)),
                        c(round(trainds$kurtosis,2), round(valds$kurtosis,2)))
    desctable  <- data.frame("Parameter"=descnames,"Training"=descvalues[,1],
                             "Validation"=descvalues[,2])
    dispose(AE$alert)
    descwin    <- gwindow("Descriptive statistics", width=300, height=300, parent=window)
    desc.lyt   <- glayout(horizontal=FALSE, container=descwin)
    desc.lyt[1,1,expand=TRUE, fill='y'] <- gtable(as.data.frame(desctable), cont = desc.lyt)
    desc.lyt[2,1,expand=TRUE] <- gbutton("Save results", cont=desc.lyt,
                                         anchor=c(0,-1),
                                         handler=function(...) fsaveresults(desctable))
  }
  # Boxplot of Y variable
  fboxplot     <- function(...)       {plotwin    <- gwindow("Plot", width = 400, height = 500, parent = window)
  wingroup   <- ggroup(horizontal=FALSE, cont=plotwin)
  ggraphics(width = 400, height = 500, dpi = 300, cont = wingroup)
  Sys.sleep(1) #Wait for window creation before trying to plot to avoid errors
  gbutton("Save plot", cont=wingroup, handler = function(...) fsaveplot(1200, 1350))
  categories <- as.factor(c(rep("Training", length(AE$Train[,AE$last.col])),
                            rep("Validation", length(AE$Val[,AE$last.col]))))
  boxpl      <- ggplot2::ggplot(AE$alldata, ggplot2::aes(x=categories,
                                                         y=AE$alldata[,AE$soil.var.column],
                                                         fill=categories)) + 
    ggplot2::geom_boxplot(notch = TRUE) +
    ggplot2::guides(fill=FALSE) +
    ggplot2::labs(x = "", y = AE$soil.var.name) +
    ggplot2::theme(axis.text = ggplot2::element_text(size=12),
                   axis.title = ggplot2::element_text(size=13))
  print(boxpl)
  }
  # Disables models module and homo, desc stats and boxplot buttons when dataset or validation size is changed
  fchangesplit <- function(h, ...)    {enabled(mdl) = FALSE
  enabled(homo.button) = FALSE
  enabled(desc.button) = FALSE
  enabled(boxplot.button) = FALSE
  }
  # Export model or prediction results
  fsaveresults <- function(h, ...)    {fdialog <- gfile("Save File", type="save", initial.filename="Output", container=window,
                                                        filter=c("Comma Separated Values (.csv)"="csv"))
  #If fdialog is not equal to NA, keep running        
  if(!(is.na(fdialog))) {fname <- paste0(fdialog,".csv")
  write.csv(h, row.names = FALSE, file = fname)
  }
  }
  # Compute model prediction errors
  fstats       <- function(y, yhat)   {n              <- length(y)
  r              <- cor(y, yhat)
  lmy            <- lm(y~yhat)
  a              <- coefficients(lmy)[1]
  b              <- coefficients(lmy)[2]
  r2             <- summary(lmy)$r.squared[1]
  bias           <- mean(yhat)-mean(y)
  msd            <- sum((yhat-y)^2)/n
  rmse           <- sqrt(msd)
  msd.c          <- sum((yhat-bias-y)^2)/n
  rmse.c         <- sqrt(msd.c)
  sb             <- (mean(yhat)-mean(y))^2
  nu             <- ((1-b)^2)*(var(yhat)*((n-1)/n))
  lc             <- (1-r^2)*(var(y)*((n-1)/n))
  rpd            <- sd(y)/rmse
  q1             <- quantile(y)[2]
  q3             <- quantile(y)[4]
  rpiq           <- (q3-q1)/rmse
  error.s        <- round(c(r2, rmse, rpiq ),2)
  names(error.s) <- c("R2", "RMSE", "RPIQ")
  return(error.s)
  }
  # Get model accuracy and display in tabular form
  fmdl.stats    <- function(t, v, ...) {t.stats.name <- paste0(deparse(substitute(t)), ".stats") #Create training stats table name
  assign(t.stats.name, fstats(t[,1], t[,2]), envir = AE) #Compute training stats
  if(nrow(v)!=0) {#If validation set size is not equal to zero
    v.stats.name <- paste0(deparse(substitute(v)), ".stats") #Create validation stats table name
    assign(v.stats.name, fstats(v[,1], v[,2]), envir = AE) #Compute validation stats
    results      <- rbind(get(t.stats.name, envir = AE),
                          get(v.stats.name, envir = AE)) #Merge training and validation stats
    Set          <- c("Training", "Validation") #Titles for prediction statistics table
    res.table    <- cbind(Set, results) #Create prediction statistics table
  } else {
    res.table    <- rbind(get(t.stats.name, envir = AE)) #Only Training results
  }
  statswin     <- gwindow("Prediction statistics", width=250, height=100, parent=window)
  stats.lyt    <- glayout(horizontal=FALSE, container=statswin)
  stats.lyt[1,1,expand=TRUE,fill='y'] <- gtable(res.table, cont = stats.lyt)
  stats.lyt[2,1,expand=TRUE] <- gbutton("Save results", cont=stats.lyt,
                                        anchor=c(0,-1),
                                        handler=function(...) fsaveresults(res.table))
  }
  # Plot measured vs. predicted
  fmdl.plot.res <- function(t, v, ...) {plotwin      <- gwindow("Plot", width = ifelse(nrow(v)!=0, 1000, 500), height = 500, parent = window)
  wingroup     <- ggroup(horizontal=FALSE, cont=plotwin)
  ggraphics(width = ifelse(nrow(v)!=0, 1000, 500), height = 500, dpi = 300, cont = wingroup)
  t.stats.name <- paste0(deparse(substitute(t)), ".stats") #Create training stats table name
  assign(t.stats.name, fstats(t[,1], t[,2]), envir = AE) #Compute training stats
  train.plot   <- ggplot2::ggplot(t, ggplot2::aes(x=t[,1], y=t[,2])) +
    ggplot2::geom_point(shape=19) +
    ggplot2::ggtitle("Training") +
    ggplot2::labs(x=NULL, y=paste(AE$soil.var.name, "Predicted")) + 
    ggplot2::theme(plot.title = ggplot2::element_text(size=12, hjust=0.5)) +
    ggplot2::theme(axis.title = ggplot2::element_text(size=12, hjust=0.5)) + 
    ggplot2::xlim(0, max(t)) +
    ggplot2::ylim(0, max(t)) +
    ggplot2::geom_abline(intercept = 0, slope = 1) +
    ggplot2::annotate("text", x=max(t)*0.05, y=seq(max(t)*0.95, max(t)*0.83,-max(t)*0.06), hjust = 0,
                      label = paste(c("R^2", "RMSE", "RPIQ"), "==",
                                    get(t.stats.name, envir = AE)), parse = TRUE)
  if(nrow(v)!=0) {#If validation set size is not equal to zero
    v.stats.name <- paste0(deparse(substitute(v)), ".stats") #Create validation stats table name
    assign(v.stats.name, fstats(v[,1], v[,2]), envir = AE) #Compute validation stats
    val.plot     <- ggplot2::ggplot(v, ggplot2::aes(x=v[,1], y=v[,2])) +
      ggplot2::geom_point(shape=19) +
      ggplot2::ggtitle("Validation") +
      ggplot2::labs(x=NULL, y=NULL) + 
      ggplot2::theme(plot.title = ggplot2::element_text(size=12, hjust=0.5)) +
      ggplot2::theme(axis.title = ggplot2::element_text(size=12, hjust=0.5)) + 
      ggplot2::xlim(0, max(v)) +
      ggplot2::ylim(0, max(v)) +
      ggplot2::geom_abline(intercept = 0, slope = 1) +
      ggplot2::annotate("text", x=max(v)*0.05, y=seq(max(v)*0.95,max(v)*0.83,-max(v)*0.06), hjust = 0,
                        label = paste(c("R^2", "RMSE", "RPIQ"), "==",
                                      get(v.stats.name, envir = AE)), parse = TRUE)
    Sys.sleep(1)
    gbutton("Save plot", cont = wingroup, handler = function(...) fsaveplot(2400, 1200))
    gridExtra::grid.arrange(train.plot, val.plot, ncol=2, bottom=paste(AE$soil.var.name, "Measured"))
  } else {
    Sys.sleep(1)
    gbutton("Save plot", cont = wingroup, handler = function(...) fsaveplot(1200, 1200))
    gridExtra::grid.arrange(train.plot, bottom=paste(AE$soil.var.name, "Measured"))
  }
  }
  # Plot RMSE of PLSR components
  fpls.plot.imp <- function(h, ...)    {plotwin   <- gwindow("Plot", width = 600, height = 400, parent=window)
  wingroup  <- ggroup(horizontal=FALSE, cont=plotwin)
  ggraphics(width = 600, height = 400, dpi = 300, cont = wingroup)
  Sys.sleep(1)
  gbutton("Save plot", cont = wingroup, handler = function(...) fsaveplot(1200, 1500))
  comp.plot <- ggplot2::ggplot(h) +
    ggplot2::labs(x="PLS Components", y="RMSE")
  print(comp.plot)
  }
  
  # Plot variables importance for MLR
  fmlr.plot.imp <- function(h, ...)    {plotwin   <- gwindow("Plot", width = 900, height = 300, parent=window)
  wingroup  <- ggroup(horizontal=FALSE, cont=plotwin)
  ggraphics(width = 900, height = 300, dpi = 300, cont = wingroup)
  Sys.sleep(1)
  gbutton("Save plot", cont = wingroup, handler = function(...) fsaveplot(2700, 900))
  var.imp   <- caret::varImp(h)$importance
  spc.st    <- as.numeric(substring(row.names(var.imp)[1], 2))
  spc.lt    <- as.numeric(substring(row.names(var.imp)[length(row.names(var.imp))], 2))
  spc.all   <- as.numeric(substring(row.names(var.imp), 2))
  row.names(var.imp) <- spc.all
  comp.plot <- ggplot2::ggplot(var.imp, ggplot2::aes(x=spc.all, y=var.imp[,1])) +
    ggplot2::scale_x_continuous(breaks = floor(seq(spc.st,spc.lt,(spc.lt-spc.st)/20))) +
    ggplot2::geom_point(pch=20) +
    ggplot2::labs(x="Variables", y="Importance")
  print(comp.plot)
  }  
  # Plot variables importance 
  fmdl.plot.imp <- function(h, ...)    {plotwin   <- gwindow("Plot", width = 900, height = 300, parent=window)
  wingroup  <- ggroup(horizontal=FALSE, cont=plotwin)
  ggraphics(width = 900, height = 300, dpi = 300, cont = wingroup)
  Sys.sleep(1)
  gbutton("Save plot", cont = wingroup, handler = function(...) fsaveplot(2700, 900))
  var.imp   <- caret::varImp(h)$importance
  spc.st    <- as.numeric(substring(row.names(var.imp)[1], 2))
  spc.lt    <- as.numeric(substring(row.names(var.imp)[length(row.names(var.imp))], 2))
  spc.all   <- as.numeric(substring(row.names(var.imp), 2))
  row.names(var.imp) <- spc.all
  comp.plot <- ggplot2::ggplot(var.imp, ggplot2::aes(x=spc.all, y=var.imp[,1])) +
    ggplot2::scale_x_continuous(breaks = floor(seq(spc.st, spc.lt, (spc.lt-spc.st)/20))) +
    ggplot2::geom_point(pch=20) +
    ggplot2::labs(x="Variables", y="Importance")
  print(comp.plot)
  }
  # Adds preprocessing to combobox in Model tab only if it is not already there
  faddtomodels  <- function(h, ...) {present <- is.element(h, AE$pred.models)
  if(present==FALSE) {
    if(length(AE$pred.models)==0) { #Special case when the list is empty (first model is being added)
      AE$pred.models <- c(h)
      select.model[]       <- AE$pred.models
      svalue(select.model) <-  h
    } else {
      AE$pred.models <- c(AE$pred.models, h)
      select.model[]       <- AE$pred.models
    }
  }
  }
  # Imports csv file to Alrad environment for prediction
  fimport.pred  <- function(...)       {falert("Importing File", 150, 20, "Wait...")
    tryCatch({AE$pred.file.location  <- svalue(pred.file.browse)
    AE$pred.file.separator <- svalue(pred.file.sep)
    AE$pred.file.decimal   <- svalue(pred.file.dec)
    if(AE$pred.file.separator=="") {
      spc <- read.delim(file = AE$pred.file.location,
                        header = as.logical(svalue(pred.file.header)),
                        dec = AE$pred.file.decimal)
    } else {
      spc <- read.table(file = AE$pred.file.location,
                        header = as.logical(svalue(pred.file.header)),
                        sep = AE$pred.file.separator,
                        dec = AE$pred.file.decimal)
    }
    AE$pred.spectra.start.number <- as.numeric(substring(colnames(spc)[1], 2))
    AE$pred.spectra.end.number   <- as.numeric(substring(colnames(spc)[ncol(spc)], 2))
    colnames(spc)     <- as.numeric(substring(colnames(spc), 2))
    AE$spc.pred <- spc
    },
    warning = function(w) fwarning(w),
    error =  function(e) ferror(e)
    )
    enabled(pred.predict) = TRUE #Enable predict group
    dispose(AE$alert)
    gmessage(msg = "Import successful!", title = "File import", parent = window)
  }
  # Predict soil property based on a new spectra
  fpredict      <- function(...)       {falert("Importing File", 150, 20, "Wait...")
    tryCatch({spc.X <- AE$spc.pred
    colnames(spc.X) <- paste("X", colnames(spc.X), sep = "") #Add X before wavelength
    mdl <- eval(parse(text = paste0("AE$", svalue(select.model)))) #Get selected model
    if(svalue(select.model)=="PLSR") {#PLSR special case
      pls.pred <-  data.frame(predict(AE$PLSR, newdata=spc.X))
      AE$prediction <- data.frame(ID=row.names(spc.X),
                                  Predicted=pls.pred[,ncol(pls.pred)])
    } else {
      AE$prediction <- data.frame(ID=row.names(spc.X),
                                  Predicted=predict(mdl, newdata=spc.X))
    }
    },
    warning = function(w) fwarning(w),
    error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "Prediction", parent = window)
  }
  
  ###################################################
  ### Preprocessing functions
  ###################################################
  
  # Smoothing
  fnrm         <- function(...) {falert("Smoothing", 150, 20, "Wait...")
    tryCatch(
      {AE$Smoothing  <- prospectr::movav(AE$Original, w = as.numeric(svalue(number.smooth)))
      faddtodtset("Smoothing")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "Smoothing", icon = "info", parent = window)
  }
  # Binning
  fbin         <- function(...) {falert("Binning", 150, 20, "Wait...")
    tryCatch(
      {AE$Binning <- prospectr::binning(AE$Original, bin.size = as.numeric(svalue(bin.number)))
      faddtodtset("Binning")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "Binning", icon = "info", parent = window)
  }
  # Absorbance
  fabs         <- function(...) {falert("Absorbance", 150, 20, "Wait...")
    tryCatch(
      {AE$Absorbance <- log10(1/AE$Original)
      faddtodtset("Absorbance")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "Absorbance", icon = "info", parent = window)
  }
  # Detrend
  fdet         <- function(...) {falert("Detrend", 150, 20, "Wait...")
    tryCatch(
      {AE$Detrend <- prospectr::detrend(X = AE$Original,
                                        wav = as.numeric(colnames(AE$Original)))
      faddtodtset("Detrend")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "Detrend", icon = "info", parent = window)
  }
  # Continuum Removal
  fcrm         <- function(...) {falert("Continuum Removal", 150, 20, "Wait...")
    tryCatch(
      {ContRem <- prospectr::continuumRemoval(X=AE$Original,
                                              wav = as.numeric(colnames(AE$Original)),
                                              type = "R", interpol="linear", method="division")
      AE$ContinuumRemoval <- ContRem[,c(-1,-ncol(ContRem))]
      faddtodtset("ContinuumRemoval")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "Continuum Removal", icon = "info", parent = window)
  }
  # Savitzky-Golay Derivative
  fsgd         <- function(...) {falert("Savitzky-Golay Derivative", 150, 20, "Wait...")
    tryCatch(
      {AE$SavitzkyGolayDerivative <- prospectr::savitzkyGolay(AE$Original,
                                                              p = as.numeric(svalue(sgd.poly)),
                                                              w = as.numeric(svalue(sgd.smooth)),
                                                              m = as.numeric(svalue(sgd.deriv)))
      faddtodtset("SavitzkyGolayDerivative")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "Savitzky-Golay Derivative", icon = "info", parent = window)
  }
  # Standard Normal Variate
  fsnv         <- function(...) {falert("SNV", 150, 20, "Wait...")
    tryCatch(
      {AE$SNV <- prospectr::standardNormalVariate(X = AE$Original)
      faddtodtset("SNV")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "SNV", icon = "info", parent = window)
  }
  # Multiplicative Scatter Correction
  fmsc         <- function(...) {falert("MSC", 150, 20, "Wait...")
    tryCatch(
      {AE$MSC <- pls::msc(as.matrix(AE$Original))
      faddtodtset("MSC")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage(msg = "Done!", title = "MSC", icon = "info", parent = window)
  }
  # Normalization
  fnor         <- function(...) {falert("Normalization", 150, 20, "Wait...")
    tryCatch(
      {AE$Normalization <- clusterSim::data.Normalization(AE$Original,
                                                          type = sub(":.*$","", svalue(nor.type)),
                                                          normalization = "row")
      faddtodtset("Normalization")
      },
      warning = function(w) fwarning(w),
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage("Done!", title = "Normalization", icon = "info",  parent = window)
  }
  
  ###################################################
  ### Modeling functions
  ###################################################
  
  # MLR
  fmlr        <- function(...)  {falert("MLR model", 180, 35, "Wait... \nThis may take a few minutes!")
    Sys.sleep(1) #Wait for AE$alert to be shown
    tryCatch(
      {form.mlr  <- as.formula(paste(colnames(AE$Train[AE$last.col]),"~",
                                     paste(names(AE$Train)[c(seq(1,AE$last.col-1,
                                                                 by=svalue(mlr.band.interval)))],
                                           collapse="+"),collapse=""))
      bootctrl.mlr <- caret::trainControl(method = svalue(mlr.resampling),
                                          number = svalue(mlr.kfold),
                                          repeats = svalue(mlr.reps)
      )
      AE$MLR  <- caret::train(form.mlr, data = AE$Train, method = "glmStepAIC", 
                              direction = "backward", trace = 0,
                              trControl = bootctrl.mlr)
      AE$mlr.train <- data.frame(AE$Train[AE$last.col],
                                 Predicted=predict(AE$MLR))
      AE$mlr.val   <- data.frame(AE$Val[AE$last.col],
                                 Predicted=predict(AE$MLR, newdata=AE$Val))
      faddtomodels("MLR")
      enabled(pred) = TRUE #Enable prediction module
      },
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage("MLR model done", title = "MLR model", parent = window)
  }
  # PLSR
  fpls        <- function(...) {falert("PLSR model", 180, 35, "Wait... \nThis may take a few minutes!")
    Sys.sleep(1)
    tryCatch(
      {bootctrl.pls <- caret::trainControl(method = svalue(pls.resampling),
                                           number = svalue(pls.kfold),
                                           repeats = svalue(pls.reps)
      )
      if(svalue(pls.resampling)=="none") {
        Grid <- expand.grid(.ncomp = svalue(pls.comp))
      } else {
        Grid <- expand.grid(.ncomp = seq(1,svalue(pls.comp), 1))
      }
      AE$pls.test  <- caret::train(AE$form.mdl, data = AE$Train, method = 'pls',
                                   trControl = bootctrl.pls, tuneGrid = Grid)
      AE$PLSR      <- pls::plsr(AE$form.mdl, data = AE$Train,
                                ncomp = AE$pls.test$bestTune$ncomp)
      t.pred             <-  data.frame(AE$PLSR$fitted.values)
      v.pred             <-  data.frame(predict(AE$PLSR, newdata=AE$Val))
      AE$pls.train <- data.frame(AE$Train[AE$last.col], Predicted=t.pred[,ncol(t.pred)])
      AE$pls.val   <- data.frame(AE$Val[AE$last.col], Predicted=v.pred[,ncol(v.pred)])
      faddtomodels("PLSR")
      enabled(pred) = TRUE #Enable prediction module
      },
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage("PLSR model done", title = "PLSR model", parent = window)
  }
  # SVM
  fsvm        <- function(...) {falert("SVM model", 180, 35, "Wait... \nThis may take a few minutes!")
    Sys.sleep(1)
    tryCatch(
      {AE$bootctrl.svm <- caret::trainControl(method = svalue(svm.resampling),
                                              number = svalue(svm.kfold),
                                              repeats = svalue(svm.reps)
      )
      if (svalue(svm.kernel, index=TRUE)==1) fsvmlinear()
      if (svalue(svm.kernel, index=TRUE)==2) fsvmradial()
      AE$svm.train    <- data.frame(AE$Train[AE$last.col], Predicted=AE$SVM$fitted)
      AE$svm.val      <- data.frame(AE$Val[AE$last.col],
                                    Predicted=predict(AE$SVM, newdata=AE$Val))
      faddtomodels("SVM")
      enabled(pred) = TRUE #Enable prediction module
      },
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage("SVM model done", title = "SVM model", parent = window)
  }
  fsvmlinear  <- function(...) {if(svalue(svm.resampling)=="none") {
    Grid <- expand.grid(.C = 1)
  } else {
    Grid <- expand.grid(.C = seq(1,16,5))
  }
    AE$svm.test <- caret::train(AE$form.mdl, data = AE$Train, method = "svmLinear",
                                trControl = AE$bootctrl.svm, tuneGrid = Grid)
    AE$SVM      <- e1071::svm(AE$form.mdl, data=AE$Train, kernel="linear", type ="eps",
                              cost=AE$svm.test$bestTune$C)
  }
  fsvmradial  <- function(...) {if(svalue(svm.resampling)=="none") {
    Grid <- expand.grid(.sigma = 0.001, .C = 1)
  } else {
    Grid <- expand.grid(.sigma = seq(0.000001,0.1,0.01), .C = seq(1,16,5))
  }
    AE$svm.test <- caret::train(AE$form.mdl, data = AE$Train, method = "svmRadial",
                                trControl = AE$bootctrl.svm, tuneGrid = Grid
    )
    AE$SVM      <- e1071::svm(AE$form.mdl, data=AE$Train, kernel="radial", type ="eps",
                              gamma=AE$svm.test$bestTune$sigma, cost=AE$svm.test$bestTune$C)
  }
  # RF
  frf         <- function(...) {falert("RF model", 180, 35, "Wait... \nThis may take a few minutes!")
    Sys.sleep(1)
    tryCatch(
      {bootControl <- caret::trainControl(method = svalue(rf.resampling),
                                          number = svalue(rf.kfold),
                                          repeats = svalue(rf.reps)
      )
      if(svalue(rf.resampling)=="none") {
        Grid <- expand.grid(.mtry = svalue(rf.mtry))
      } else {
        Grid <- expand.grid(.mtry = seq(svalue(rf.mtry)/5,svalue(rf.mtry),svalue(rf.mtry)/5))
      }
      AE$rf.test     <- caret::train(AE$form.mdl, data = AE$Train, 
                                     method = 'rf', trControl = bootControl,
                                     tuneGrid = Grid, importance = TRUE)
      AE$RF          <- randomForest::randomForest(AE$form.mdl, 
                                                   data=AE$Train, mtry=AE$rf.test$bestTune$mtry,
                                                   ntree = as.numeric(svalue(rf.ntree)))
      AE$rf.train    <- data.frame(AE$Train[AE$last.col], 
                                   Predicted=AE$RF$predicted)
      AE$rf.val      <- data.frame(AE$Val[AE$last.col], 
                                   Predicted=predict(AE$RF, newdata=AE$Val))
      faddtomodels("RF")
      enabled(pred) = TRUE #Enable prediction module
      },
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage("RF model done", title = "RF model", parent = window)
  }
  # ANN
  #fann         <- function(...) {falert("ANN model", 180, 35, "Wait... \nThis may take a few minutes!")
  #                               Sys.sleep(1)
  #                               tryCatch(
  #                                       {bootControl  <- caret::trainControl(method = svalue(ann.resampling),
  #                                                                            number = svalue(ann.kfold),
  #                                                                             repeats = svalue(ann.reps),
  #                                                                             preProcOptions = list(thresh = 0.95, cutoff = 0.95)
  #                                                                             )
  #                                         if(svalue(ann.resampling)=="none") {
  #                                           Grid <- expand.grid(.nhid= svalue(ann.hid),
  #                                                              .actfun= svalue(ann.act))
  #                                         } else {
  #                                          Grid <- expand.grid(.nhid= seq(1,svalue(ann.hid),ceiling(svalue(ann.hid)/10)),
  #                                                              .actfun= svalue(ann.act))
  #                                         }
  #                                        AE$ann.test     <- caret::train(AE$form.mdl, data = AE$Train, method = 'elm', 
  #                                                                              trControl = bootControl, tuneGrid = Grid , na.action = na.fail, 
  #                                                                               preProcess = c("nzv","center"))
  #                                        AE$ANN          <- elmNNRcpp::elm_train(AE$form.mdl, data=AE$Train, 
  #                                                                                  nhid=AE$ann.test$bestTune$nhid,
  #                                                                                 actfun= AE$ann.test$bestTune$actfun)
  #                                         AE$ann.train    <- data.frame(AE$Train[AE$last.col], 
  #                                                                             Predicted=AE$ANN$fitted.values)
  #                                         AE$ann.val      <- data.frame(AE$Val[AE$last.col], 
  #                                                                             Predicted=predict(AE$ANN, newdata=AE$Val))
  #                                        faddtomodels("ANN")
  #                                         enabled(pred) = TRUE #Enable prediction module
  #                                        },
  #                                       error =  function(e) ferror(e)
  #                                       )
  #                              dispose(AE$alert)
  #                              gmessage("ANN model done", title = "ANN model", parent = window)
  #                              }
  # GPR
  fgpr        <- function(...) {falert("GPR model", 180, 35, "Wait... \nThis may take a few minutes!")
    Sys.sleep(1)
    tryCatch(
      {AE$bootctrl.gpr <- caret::trainControl(method = svalue(gpr.resampling),
                                              number = svalue(gpr.kfold),
                                              repeats = svalue(gpr.reps)
      )
      if (svalue(gpr.kernel, index=TRUE)==1) fgprlinear()
      if (svalue(gpr.kernel, index=TRUE)==2) fgprradial()
      AE$gpr.train    <- data.frame(AE$Train[AE$last.col], 
                                    Predicted=predict(AE$GPR, newdata=AE$Train))
      AE$gpr.val      <- data.frame(AE$Val[AE$last.col], 
                                    Predicted=predict(AE$GPR, newdata=AE$Val))
      faddtomodels("GPR")
      enabled(pred) = TRUE #Enable prediction module
      },
      error =  function(e) ferror(e)
    )
    dispose(AE$alert)
    gmessage("GPR model done", title = "GPR model", parent = window)
  }
  fgprlinear  <- function(...) {AE$GPR <- caret::train(AE$form.mdl, data = AE$Train, method = 'gaussprLinear',
                                                       trControl = AE$bootctrl.gpr)
  }
  fgprradial  <- function(...) {if(svalue(gpr.resampling)=="none") {
    Grid <- expand.grid(.sigma = 0.001)
  } else {
    Grid <- expand.grid(.sigma = seq(.00001,.1,.005))
  }
    AE$GPR  <- caret::train(AE$form.mdl, data = AE$Train, method = 'gaussprRadial', 
                            trControl = AE$bootctrl.gpr, tuneGrid = Grid
    )
  }
  
  ###################################################
  ### Vectors
  ###################################################
  
  sgpolynomial         <- c(1:12)
  sgderivarive         <- c(1:4)
  splitnumbers         <- seq(from = 0, to = 50, by = 5)
  normalization.types  <- c("n1: standardization ((x-mean)/sd)",
                            "n5: normalization in range <-1,1> ((x-mean)/max(abs(x-mean)))",
                            "n6: quotient transformation (x/mean)",
                            "n12: normalization ((x-mean)/sqrt(sum((x-mean)^2)))",
                            "n13: normalization with zero being the central point ((x-midrange)/(range/2))")
  train.ctrl.method    <- c("cv", "repeatedcv", "LOOCV", "LGOCV", "boot", "boot632", "none")
  train.ctrl.method.rf <- c("oob", "cv", "repeatedcv", "LOOCV", "LGOCV", "boot", "boot632", "none")
  kernel.param.svm     <- c("Linear Kernel", "Radial Kernel")
  actf.ann             <- c("purelin","radbas","sin","tansig")
  kernel.param.gpr     <- c("Linear Kernel", "Radial Kernel")
  gpr.param.var        <- c(.0001,.001,.01,.1,1,10,100)
  
  ###################################################
  ### Main window
  ###################################################
  
  ### Create main window
  window        <- gwindow("AlradSpectra", visible=F, width = 600,height = 600)
  ### Confirm window closing
  addHandlerUnrealize(window, handler = fconfirmquit)
  ### Clear, Quit and About buttons
  action.list   <- list(new =  gaction(label = "New",  icon = "new",  handler = fnew),
                        open =  gaction(label = "Open",  icon = "open",  handler = fopen),
                        save =  gaction(label = "Save",  icon = "save",  handler = fsave),
                        quit = gaction(label = "Quit", icon = "quit",  handler = fquit),
                        about = gaction(label = "About", icon = "about",  handler = fabout))
  toolbar.list  <- c(action.list[c("new", "open", "save")], sep = gseparator(), action.list["quit"],
                     sep = gseparator(), action.list["about"] )
  toolbar       <- gtoolbar(toolbar.list, cont = window)
  
  ###################################################
  ### Import Data module
  ###################################################
  
  ### Create notebook for modules
  notebook       <- gnotebook(cont = window)
  ### Add Import module to main notebook
  import         <- ggroup(cont = notebook, horizontal = F, label = gettext("      Import Data      "))
  ### Browse file
  frame.imp      <- gframe("File path:", cont = import, horizontal=T)
  file.browse    <- gedit(text = "", cont = frame.imp, width = 100)
  browse.button  <- gbutton("  Browse  ", cont = frame.imp, handler = function(...) fbrowse(file.browse))
  ### Parameters
  frame.file.arg <- gframe("Parameters:", cont = import, horizontal=TRUE)
  lyt.file.arg   <- glayout(cont = frame.file.arg, expand = F)
  lyt.file.arg[1,1,anchor=c(-1,0)]    <- "Separator (leave blank for tab):"
  file.sep       <- lyt.file.arg[1,2,anchor=c(0,0)]    <- gedit(text = ",", cont = lyt.file.arg, width = 6)
  lyt.file.arg[1,3,anchor=c(-1,0)]    <- "Decimal separator:"
  file.dec       <- lyt.file.arg[1,4,anchor=c(0,0)]    <- gedit(text = ".", cont = lyt.file.arg, width = 6)
  lyt.file.arg[1,9,anchor=c(-1,0)]    <- "Header:"
  file.header    <- lyt.file.arg[1,10,anchor=c(0,0)]   <- gcombobox(c("TRUE", "FALSE"), cont = lyt.file.arg)
  size(file.header)                  <- c(60,1) # Increase width of Header combobox
  lyt.file.arg[2,1,anchor=c(-1,0)]    <- "Spectral data starts at column:"
  spc.start.col  <- lyt.file.arg[2,2,anchor=c(0,0)]    <- gedit(text = "", cont = lyt.file.arg, width = 6)
  lyt.file.arg[2,3,anchor=c(-1,0)]    <- "Spectral data ends at column:"
  spc.end.col    <- lyt.file.arg[2,4,anchor=c(0,0)]    <- gedit(text = "", cont = lyt.file.arg, width = 6)
  lyt.file.arg[3,1,anchor=c(-1,0)]    <- "Y variable is at column:"
  soil.var.col   <- lyt.file.arg[3,2,anchor=c(0,0)]    <- gedit(text = "", cont = lyt.file.arg, width = 6)
  lyt.file.arg[3,3,anchor=c(-1,0)]    <- "Y variable name:"
  soil.var.nm    <- lyt.file.arg[3,4:10,anchor=c(0,0)] <- gedit(text = "", cont = lyt.file.arg, width = 6)
  ### Import button
  gbutton("Import data", cont = import, handler = fimport)
  ### View data button
  viewdt.button  <- gbutton("View first 10 rows and columns", cont = import,
                            handler = function(...) fview(AE$alldata[1:min(10,nrow(AE$alldata)),1:min(10,ncol(AE$alldata))], 600))
  ### Plot imported data button
  plotdt.button  <- gbutton("View imported spectra", cont = import, handler = function(...) fplot(AE$Original, AE$spectra.start.number, 
                                                                                                  AE$spectra.end.number))
  ### View descriptive statistics button
  viewst.button  <- gbutton("View Y descriptive statistics", cont = import, handler = fdescy)
  ### View histogram button
  viewhs.button  <- gbutton("View Y histogram", cont = import, handler = fhist)
  ### Disable buttons
  enabled(viewdt.button) = FALSE
  enabled(plotdt.button) = FALSE
  enabled(viewst.button) = FALSE
  enabled(viewhs.button) = FALSE
  ###################################################
  ### Preprocessing module
  ###################################################
  
  ### Add Preprocessing module to main notebook
  pp  <- gnotebook(cont = notebook, label = gettext(" Spectral Preprocessing"),horizontal = F, width = 30)
  enabled(pp) = FALSE #Disable preprocessing module
  nrm <- ggroup(cont = pp, horizontal = F,label = gettext(" Smoothing "))
  bin <- ggroup(cont = pp, horizontal = F,label = gettext(" Binning "))
  abs <- ggroup(cont = pp, horizontal = F,label = gettext(" Absorbance "))
  det <- ggroup(cont = pp, horizontal = F,label = gettext("  Detrend  "))
  crm <- ggroup(cont = pp, horizontal = F,label = gettext("Continuum Removal"))
  sgd <- ggroup(cont = pp, horizontal = F,label = gettext("   SGD   "))
  snv <- ggroup(cont = pp, horizontal = F,label = gettext("   SNV   "))
  msc <- ggroup(cont = pp, horizontal = F,label = gettext("   MSC   "))
  nor <- ggroup(cont = pp, horizontal = F,label = gettext("Normalization"))
  ### Smoothing
  frame.desc.nrm     <- gframe("Description:", cont = nrm, horizontal = T)
  lyt.desc.nrm       <- glayout(cont = frame.desc.nrm , expand = TRUE)
  lyt.desc.nrm[1,1]  <- "A simple moving average of spectral data using a convolution function. Package: prospectr"
  frame.param.nrm    <- gframe("Parameters:", cont = nrm, horizontal=T)
  lyt.param.nrm      <- glayout(cont = frame.param.nrm, expand = TRUE)
  lyt.param.nrm[1,1] <- "Number of smoothing points"
  number.smooth      <- lyt.param.nrm[2,1] <- gspinbutton(from = 5, to = 101, by = 2, cont = lyt.param.nrm)
  gbutton("Run", cont = nrm, handler = fnrm)
  gbutton("View spectra", cont = nrm, handler = function(...) fplot(AE$Smoothing, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = nrm, handler = function(...) fsavespectra(AE$Smoothing))
  ### Binning
  frame.desc.bin     <- gframe("Description:", cont = bin, horizontal = T)
  lyt.desc.bin       <- glayout(cont = frame.desc.bin , expand = TRUE)
  lyt.desc.bin[1,1]  <- "Compute average values of a signal in pre-determined bins. Package: prospectr"
  frame.param.bin    <- gframe("Parameters:", cont = bin, horizontal=T)
  lyt.param.bin      <- glayout(cont = frame.param.bin, expand = TRUE)
  lyt.param.bin[1,1] <- "Bin size"
  bin.number         <- lyt.param.bin[2,1:4] <- gspinbutton(from = 2, to = 100, by = 1, cont = lyt.param.bin)
  gbutton("Run", cont = bin, handler = fbin)
  gbutton("View spectra", cont = bin, handler = function(...) fplot(AE$Binning, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = bin, handler = function(...) fsavespectra(AE$Binning))
  ### Absorbance
  frame.desc.abs     <- gframe("Description:", cont = abs, horizontal=T)
  lyt.desc.abs       <- glayout(cont = frame.desc.abs, expand = TRUE)
  lyt.desc.abs[1,1]  <- "Transforms reflectance to absorbance values (log10(1/R))."
  gbutton("Run", cont = abs, handler = fabs)
  gbutton("View spectra", cont = abs, handler = function(...) fplot(AE$Absorbance, AE$spectra.start.number, 
                                                                    AE$spectra.end.number, ylab="Absorbance"))
  gbutton("Save preprocessed spectra", cont = abs, handler = function(...) fsavespectra(AE$Absorbance))
  ### Detrend
  frame.desc.det     <- gframe("Description:", cont = det, horizontal=T)
  lyt.desc.det       <- glayout(cont = frame.desc.det, expand = TRUE)
  lyt.desc.det[1,1]  <- "Normalizes each row by applying a Standard Normal Variate transformation followed by fitting a second order \nlinear model and returning the fitted residuals. Package: prospectr"
  gbutton("Run", cont = det, handler = fdet)
  gbutton("View spectra", cont = det, handler = function(...) fplot(AE$Detrend, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = det, handler = function(...) fsavespectra(AE$Detrend))
  ### Continuum Removal
  frame.desc.crm     <- gframe("Description:", cont = crm, horizontal=T)
  lyt.desc.crm       <- glayout(cont = frame.desc.crm, expand = TRUE)
  lyt.desc.crm[1,1]  <- "The continuum removal technique was introduced by Clark and Roush (1984). The algorithm find points lying on the \n
  convex hull of a spectrum, connects the points by linear interpolation and normalizes the spectrum by \n
  dividing the input data by the interpolated line. Package: prospectr\nData type: Reflectance\nInterpolation method: Linear\nNormalization method: Division"
  gbutton("Run", cont = crm, handler = fcrm)
  gbutton("View spectra", cont = crm, handler = function(...) fplot(AE$ContinuumRemoval, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = crm, handler = function(...) fsavespectra(AE$ContinuumRemoval))
  ### SG Derivative
  frame.desc.sgd     <- gframe("Description:",cont = sgd, horizontal = T)
  lyt.desc.sgd       <- glayout(cont = frame.desc.sgd , expand = TRUE)
  lyt.desc.sgd[1,1]  <- "Savitzky-Golay Derivative. The Savitzky-Golay algorithm fits a local polynomial regression on the signal. It requires evenly \nspaced data points. Package: prospectr"
  frame.param.sgd    <- gframe("Parameters:", cont = sgd, horizontal=T)
  lyt.param.sgd      <- glayout(cont = frame.param.sgd, expand = TRUE)
  lyt.param.sgd[1,1] <- "Number of smoothing points"
  sgd.smooth         <- lyt.param.sgd[2,1] <- gspinbutton(from = 5, to = 101, by = 2, cont = lyt.param.sgd)
  lyt.param.sgd[1,2] <- "Polynomial order"
  sgd.poly           <- lyt.param.sgd[2,2] <- gcombobox(sgpolynomial, cont = lyt.param.sgd)
  lyt.param.sgd[1,3] <- "Derivative order"
  sgd.deriv          <- lyt.param.sgd[2,3] <- gcombobox(sgderivarive, cont = lyt.param.sgd)
  gbutton("Run", cont = sgd, handler = fsgd)
  gbutton("View spectra", cont = sgd, handler = function(...) fplot(AE$SavitzkyGolayDerivative, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = sgd, handler = function(...) fsavespectra(AE$SavitzkyGolayDerivative))
  ### SNV
  frame.desc.snv     <- gframe("Description:", cont = snv, horizontal=T)
  lyt.desc.snv       <- glayout(cont = frame.desc.snv, expand = TRUE)
  lyt.desc.snv[1,1]  <- "Standard Normal Variate normalizes each row by substracting each row by its mean and dividing by \nits standard deviation. Package: prospectr"
  gbutton("Run", cont = snv, handler = fsnv)
  gbutton("View spectra", cont = snv, handler = function(...) fplot(AE$SNV, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = snv, handler = function(...) fsavespectra(AE$SNV))
  ### MSC
  frame.desc.msc     <- gframe("Description:", cont = msc, horizontal=T)
  lyt.desc.msc       <- glayout(cont = frame.desc.msc, expand = TRUE)
  lyt.desc.msc[1,1]  <- "Performs multiplicative scatter/signal correction on spectral data. Package: pls"
  gbutton("Run", cont = msc, handler = fmsc)
  gbutton("View spectra", cont = msc, handler = function(...) fplot(AE$MSC, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = msc, handler = function(...) fsavespectra(AE$MSC))
  ### Normalization
  frame.desc.nor     <- gframe("Description:",cont = nor, horizontal = T)
  lyt.desc.nor       <- glayout(cont = frame.desc.nor , expand = TRUE)
  lyt.desc.nor[1,1]  <- "Different types of data normalization. Package: clusterSim"
  frame.param.nor    <- gframe("Parameters:", cont = nor, horizontal=T)
  lyt.param.nor      <- glayout(cont = frame.param.nor, expand = TRUE)
  lyt.param.nor[1,1, anchor=(c(-1,0))] <- "Type of Normalization."
  nor.type           <- lyt.param.nor[2,1] <- gradio(normalization.types, checked = T, cont = lyt.param.nor)
  gbutton("Run", cont = nor, handler = fnor)
  gbutton("View spectra", cont = nor, handler = function(...) fplot(AE$Normalization, AE$spectra.start.number, 
                                                                    AE$spectra.end.number))
  gbutton("Save preprocessed spectra", cont = nor, handler = function(...) fsavespectra(AE$Normalization))
  
  ###################################################
  ### Modeling module
  ###################################################
  
  ### Add Modeling module to main notebook
  models             <- ggroup(cont = notebook, label = gettext("           Modeling           "), horizontal = F)
  glabel("Select input data for modeling:", cont = models, anchor = c(-1,0))
  select.dataset     <- gcombobox("", cont = models, handler = fchangesplit)
  glabel("Size of validation set (%):", cont = models, anchor = c(-1,0))
  split.val          <- gcombobox(splitnumbers, cont = models, selected = 7, handler = fchangesplit)
  gbutton("Split data", cont = models, handler = fsplit)
  homo.button        <- gbutton("Homogeneity of variance test", cont = models, handler = fhomo)
  desc.button        <- gbutton("View descriptive statistics of groups", cont = models, handler = fdesc)
  boxplot.button     <- gbutton("View box plots", cont = models, handler = fboxplot)
  mdl                <- gnotebook(cont = models)
  enabled(homo.button) = FALSE #Disable homogeneity test button
  enabled(desc.button) = FALSE #Disable descriptive stats button
  enabled(boxplot.button) = FALSE #Disable box plots button
  enabled(models) = FALSE #Disable modeling module
  enabled(mdl)    = FALSE #Disable models notebook
  ### MLR
  mdl.mlr            <- ggroup(cont = mdl, horizontal = F,label = gettext("   MLR   "))
  frame.desc.mlr     <- gframe("Description:",cont = mdl.mlr, horizontal = T)
  lyt.desc.mlr       <- glayout(cont = frame.desc.mlr, expand = TRUE)
  lyt.desc.mlr[1,1]  <- "Multiple Linear Regression. MLR is a statistical method that uses several explanatory variables to predict the outcome of a \nresponse variable in a simple linear model. Package: caret"
  frame.param.mlr    <- gframe("Tuning parameters:", cont = mdl.mlr, horizontal=T)
  lyt.param.mlr      <- glayout(cont = frame.param.mlr , expand = TRUE)
  lyt.param.mlr[1,1] <- "Resampling method"
  mlr.resampling     <- lyt.param.mlr[2,1] <- gcombobox(train.ctrl.method, cont = lyt.param.mlr)
  lyt.param.mlr[1,2] <- "Number of folds or \nresampling iterations"
  mlr.kfold          <- lyt.param.mlr[2,2] <- gspinbutton(from = 1, to = 50, by = 1, value = 10, cont = lyt.param.mlr)
  lyt.param.mlr[1,3] <- "For repeatedcv only: \nnumber of repetitions"
  mlr.reps           <- lyt.param.mlr[2,3] <- gspinbutton(from = 1, to = 20, by = 1, value = 3, cont = lyt.param.mlr)
  lyt.param.mlr[1,4] <- "Band interval"
  mlr.band.interval  <- lyt.param.mlr[2,4] <- gspinbutton(from = 1, to = 30, by = 1, value = 25, cont = lyt.param.mlr)
  gbutton("Run MLR model", cont = mdl.mlr, handler = fmlr)
  gbutton("View variables importance", cont = mdl.mlr, handler = function(...) fmlr.plot.imp(AE$MLR))
  gbutton("MLR prediction statistics", cont = mdl.mlr, handler = function(...) fmdl.stats(AE$mlr.train, AE$mlr.val))
  gbutton("View measured vs. predicted",cont = mdl.mlr, handler = function(...) fmdl.plot.res(AE$mlr.train, AE$mlr.val))
  ### PLS
  mdl.pls            <- ggroup(cont = mdl, horizontal = F,label = gettext("   PLSR   "))
  frame.desc.pls     <- gframe("Description:",cont = mdl.pls, horizontal = T)
  lyt.desc.pls       <- glayout(cont = frame.desc.pls, expand = TRUE)
  lyt.desc.pls[1,1]  <- "Partial Least Squares Regression. PLSR is considered the most common regression method applied in chemometrics and \ncan deal with complex modeling problems. Packages: pls / caret"
  frame.param.pls    <- gframe("Tuning parameters:", cont = mdl.pls, horizontal=T)
  lyt.param.pls      <- glayout(cont = frame.param.pls , expand = TRUE)
  lyt.param.pls[1,1] <- "Resampling method"
  pls.resampling     <- lyt.param.pls[2,1] <- gcombobox(train.ctrl.method, cont = lyt.param.pls)
  lyt.param.pls[1,2] <- "Number of folds or \nresampling iterations"
  pls.kfold          <- lyt.param.pls[2,2] <- gspinbutton(from = 1, to = 50, by = 1, value = 10, cont = lyt.param.pls)
  lyt.param.pls[1,3] <- "For repeatedcv only: \nnumber of repetitions"
  pls.reps           <- lyt.param.pls[2,3] <- gspinbutton(from = 1, to = 20, by = 1,value = 3, cont = lyt.param.pls)
  lyt.param.pls[1,4] <- "Number of components to \ninclude in the model"
  pls.comp           <- lyt.param.pls[2,4] <- gspinbutton(from = 1, to = 500, by = 1, value = 30, cont = lyt.param.pls)
  gbutton("Run PLSR model", cont = mdl.pls , handler = fpls)
  gbutton("View variables importance", cont = mdl.pls, handler = function(...) fmdl.plot.imp(AE$pls.test))
  gbutton("View PLS components vs. RMSE", cont = mdl.pls, handler = function(...) fpls.plot.imp(AE$pls.test))
  gbutton("PLSR prediction statistics", cont = mdl.pls, handler = function(...) fmdl.stats(AE$pls.train, AE$pls.val))
  gbutton("View measured vs. predicted",cont = mdl.pls, handler = function(...) fmdl.plot.res(AE$pls.train, AE$pls.val))
  ### SVM
  mdl.svm            <- ggroup(cont = mdl, horizontal = F,label = gettext("    SVM    "))
  frame.desc.svm     <- gframe("Description:",cont = mdl.svm, horizontal = T)
  lyt.desc.svm       <- glayout(cont = frame.desc.svm, expand = TRUE)
  lyt.desc.svm[1,1]  <- "Support Vector Machine. SVM models are efficient in modeling linear or nonlinear relationships and handling large databases. \nPackages: e1071 / caret"
  frame.param.svm    <- gframe("Tuning parameters:", cont = mdl.svm, horizontal=T)
  lyt.param.svm      <- glayout(cont = frame.param.svm , expand = TRUE)
  lyt.param.svm[1,1] <- "Resampling method"
  svm.resampling     <- lyt.param.svm[2,1] <- gcombobox(train.ctrl.method, cont = lyt.param.svm)
  lyt.param.svm[1,2] <- "Number of folds or \nresampling iterations"
  svm.kfold          <- lyt.param.svm[2,2] <- gspinbutton(from = 1, to = 50, by = 1, value = 10, cont = lyt.param.svm)
  lyt.param.svm[1,3] <- "For repeatedcv only: \nnumber of repetitions"
  svm.reps           <- lyt.param.svm[2,3] <- gspinbutton(from = 1, to = 20, by = 1,value =  3, cont = lyt.param.svm)
  lyt.param.svm[1,4] <- "Kernel parameters"
  svm.kernel         <- lyt.param.svm[2,4:6] <- gcombobox(kernel.param.svm, cont = lyt.param.svm)
  gbutton("Run SVM model", cont = mdl.svm, handler = fsvm)
  gbutton("View variables importance", cont = mdl.svm, handler = function(...) fmdl.plot.imp(AE$svm.test))
  gbutton("SVM prediction statistics", cont = mdl.svm, handler = function(...) fmdl.stats(AE$svm.train, AE$svm.val))
  gbutton("View measured vs. predicted",cont = mdl.svm, handler = function(...) fmdl.plot.res(AE$svm.train, AE$svm.val))
  ### RF
  mdl.rf             <- ggroup(cont = mdl, horizontal = F,label = gettext("    RF    "))
  frame.desc.rf      <- gframe("Description:",cont = mdl.rf, horizontal = T)
  lyt.desc.rf        <- glayout(cont = frame.desc.rf, expand = TRUE)
  lyt.desc.rf[1,1]   <- "Random Forest. RF models are black boxes approach that are very hard to interpret. Packages: randomForest / caret"
  frame.param.rf     <- gframe("Tuning parameters:", cont = mdl.rf, horizontal=T)
  lyt.param.rf       <- glayout(cont = frame.param.rf , expand = TRUE)
  lyt.param.rf[1,1]  <- "Resampling method"
  rf.resampling      <- lyt.param.rf[2,1]  <- gcombobox(train.ctrl.method.rf, cont = lyt.param.rf)
  lyt.param.rf[1,2]  <- "Number of folds or \nresampling iterations"
  rf.kfold           <- lyt.param.rf[2,2] <- gspinbutton(from = 1, to = 50, by = 1, value = 10, cont = lyt.param.rf)
  lyt.param.rf[1,3]  <- "For repeatedcv only: \nnumber of repetitions"
  rf.reps            <- lyt.param.rf[2,3] <- gspinbutton(from = 1, to = 20, by = 1,value =  3, cont = lyt.param.rf)
  lyt.param.rf[1,4]  <- "Randomly selected \npredictors (mtry)"
  rf.mtry            <- lyt.param.rf[2,4]  <- gspinbutton(from = 5, to = 500, by = 5, value = 5, cont = lyt.param.rf)
  lyt.param.rf[1,5]  <- "Number of trees \n(ntree)"
  rf.ntree           <- lyt.param.rf[2,5]  <- gedit(text = "500", cont = lyt.param.rf, width = 4)
  gbutton("Run RF model", cont = mdl.rf, handler = frf)
  gbutton("View variables importance", cont = mdl.rf, handler = function(...) fmdl.plot.imp(AE$rf.test))
  gbutton("RF prediction statistics", cont = mdl.rf, handler = function(...) fmdl.stats(AE$rf.train, AE$rf.val))
  gbutton("View measured vs. predicted",cont = mdl.rf, handler = function(...) fmdl.plot.res(AE$rf.train, AE$rf.val))
  ### ANN
  #mdl.ann            <- ggroup(cont = mdl, horizontal = F,label = gettext("    ANN    "))
  #frame.desc.ann     <- gframe("Description:",cont = mdl.ann, horizontal = T)
  #lyt.desc.ann       <- glayout(cont = frame.desc.ann, expand = TRUE)
  #lyt.desc.ann[1,1]  <- "Artificial Neural Network. Training functions for Single Hidden-layer Feedforward Neural Networks (SLFN) \nusing the Extreme Learning Machine (ELM) algorithm. Packages: elmNNRcpp / caret"
  #frame.param.ann    <- gframe("Tuning parameters:", cont = mdl.ann, horizontal=T)
  #lyt.param.ann      <- glayout(cont = frame.param.ann , expand = TRUE)
  #lyt.param.ann[1,1] <- "Resampling method"
  #ann.resampling     <- lyt.param.ann[2,1] <- gcombobox(train.ctrl.method, cont = lyt.param.ann)
  #lyt.param.ann[1,2] <- "Number of folds or \nresampling iterations"
  #nn.kfold          <- lyt.param.ann[2,2] <- gspinbutton(from = 1, to = 50, by = 1, value = 10, cont = lyt.param.ann)
  #lyt.param.ann[1,3] <- "For repeatedcv only: \nnumber of repetitions"
  #ann.reps           <- lyt.param.ann[2,3] <- gspinbutton(from = 1, to = 20, by = 1,value =  3, cont = lyt.param.ann)
  #lyt.param.ann[1,4] <- "Activation function"
  #nn.act            <- lyt.param.ann[2,4] <- gcombobox(actf.ann, cont = lyt.param.ann)
  #yt.param.ann[1,5] <- "Hidden units"
  #ann.hid            <- lyt.param.ann[2,5] <- gspinbutton(from = 1, to = 50, by = 1, value = 10, cont = lyt.param.ann)
  #gbutton("Run ANN model", cont = mdl.ann, handler = fann)
  #gbutton("View variables importance", cont = mdl.ann, handler = function(...) fmdl.plot.imp(AE$ann.test))
  #gbutton("ANN prediction statistics", cont = mdl.ann, handler = function(...) fmdl.stats(AE$ann.train, AE$ann.val))
  #button("View measured vs. predicted", cont = mdl.ann, handler = function(...) fmdl.plot.res(AE$ann.train, AE$ann.val))
  ## GPR
  mdl.gpr            <- ggroup(cont = mdl, horizontal = F,label = gettext("    GPR    "))
  frame.desc.gpr     <- gframe("Description:",cont = mdl.gpr, horizontal = T)
  lyt.desc.gpr       <- glayout(cont = frame.desc.gpr, expand = TRUE)
  lyt.desc.gpr[1,1]  <- "Gaussian Process Regression. Gaussian process applies a kernel function for training and predicting. \nPackages: kernlab / caret"
  frame.param.gpr    <- gframe("Tuning parameters:", cont = mdl.gpr, horizontal=T)
  lyt.param.gpr      <- glayout(cont = frame.param.gpr , expand = TRUE)
  lyt.param.gpr[1,1] <- "Resampling method"
  gpr.resampling     <- lyt.param.gpr[2,1] <- gcombobox(train.ctrl.method, cont = lyt.param.gpr)
  lyt.param.gpr[1,2] <- "Number of folds or \nresampling iterations"
  gpr.kfold          <- lyt.param.gpr[2,2] <- gspinbutton(from = 1, to = 50, by = 1, value = 10, cont = lyt.param.gpr)
  lyt.param.gpr[1,3] <- "For repeatedcv only: \nnumber of repetitions"
  gpr.reps           <- lyt.param.gpr[2,3] <- gspinbutton(from = 1, to = 20, by = 1,value =  3, cont = lyt.param.gpr)
  lyt.param.gpr[1,4] <- "Kernel function used \nin training and predicting"
  gpr.kernel         <- lyt.param.gpr[2,4] <- gcombobox(kernel.param.gpr, cont = lyt.param.gpr)
  gbutton("Run GPR model", cont = mdl.gpr, handler = fgpr)
  gbutton("View variables importance", cont = mdl.gpr, handler = function(...) fmdl.plot.imp(AE$GPR))
  gbutton("GPR prediction statistics", cont = mdl.gpr, handler = function(...) fmdl.stats(AE$gpr.train, AE$gpr.val))
  gbutton("View measured vs. predicted", cont = mdl.gpr, handler = function(...) fmdl.plot.res(AE$gpr.train, AE$gpr.val))
  
  ###################################################
  ### Prediction module
  ###################################################
  
  ### Add Prediction module to main notebook
  pred                <- ggroup(cont = notebook, label = gettext("          Prediction          "), horizontal = F)
  ### Create import group
  pred.imp            <- ggroup(cont = pred, horizontal = F)
  ### Browse file
  glabel("Import spectral data for Prediction\n  Conditions:\n-File must contain only spectral data.\n-Spectral data for Prediction and Modeling must be the same length.\n-Spectral data used here must have the same preprocessing used to build the model.",
         cont = pred.imp, anchor = c(-1,0))
  pred.frame.imp      <- gframe("File path:", cont = pred.imp, horizontal=T)
  pred.file.browse    <- gedit(text = "", cont = pred.frame.imp, width = 100)
  pred.browse.button  <- gbutton("  Browse  ", cont = pred.frame.imp, handler = function(...) fbrowse(pred.file.browse))
  ### Parameters
  pred.frame.file.arg <- gframe("Parameters:", cont = pred.imp, horizontal=TRUE)
  pred.lyt.file.arg   <- glayout(cont = pred.frame.file.arg, expand = F)
  pred.lyt.file.arg[1,1,anchor=c(1,0)] <- "Separator (leave blank for tab):"
  pred.file.sep       <- pred.lyt.file.arg[1,2,anchor=c(0,0)] <- gedit(text = ",", cont = pred.lyt.file.arg, width = 8)
  pred.lyt.file.arg[1,3,anchor=c(1,0)] <- "Decimal separator:"
  pred.file.dec       <- pred.lyt.file.arg[1,4,anchor=c(0,0)] <- gedit(text = ".", cont = pred.lyt.file.arg, width = 8)
  pred.lyt.file.arg[1,8,anchor=c(1,0)] <- "Header:"
  pred.file.header    <- pred.lyt.file.arg[1,9,anchor=c(0,0)] <- gcombobox(c("TRUE", "FALSE"), cont = pred.lyt.file.arg)
  size(pred.file.header)               <- c(60,1) # Increase width of Header combobox
  ### Import button
  gbutton("Import data", cont = pred.imp, handler = fimport.pred)
  ### View data button
  gbutton("View first 10 rows and columns", cont = pred.imp,
          handler = function(...) fview(AE$spc.pred[1:min(10,nrow(AE$spc.pred)),1:min(10,ncol(AE$spc.pred))], 600))
  ### Plot imported data button
  gbutton("View imported spectra", cont = pred.imp, handler = function(...) fplot(AE$spc.pred, 
                                                                                  AE$pred.spectra.start.number, 
                                                                                  AE$pred.spectra.end.number))
  ### Draw a separator line
  gseparator(cont = pred)
  ### Create predict group
  pred.predict        <- ggroup(cont = pred, horizontal = F)
  ### Select model for prediction
  glabel("Select model for prediction:", cont = pred.predict, anchor = c(-1,0))
  select.model        <- gcombobox("", cont = pred.predict)
  gbutton("Predict", cont = pred.predict, handler = fpredict)
  gbutton("View predictions", cont = pred.predict, handler = function(...) fview(AE$prediction, 300))
  gbutton("Save predictions", cont = pred.predict, handler = function(...) fsaveresults(AE$prediction))
  enabled(pred.predict) = FALSE #Disable predict group
  enabled(pred) = FALSE #Disable prediction module
  
  ### Focus on first tabs
  svalue(notebook) <- 1
  svalue(pp)       <- 1
  svalue(mdl)      <- 1
  ### Window visibility
  visible(window)  <- TRUE
  
} #Closes AlradSpectra() function
AlradSpectra/AlradSpectra documentation built on March 17, 2022, 10:57 p.m.