ClassContingencyTable2 <-
function(RefPnts.mat, PredPnts.mat, Species, ModelNameOut, SubsetVariableNumber, VariableSubsets, output1,
Conditions2, OutDirectIn3, TestDataType, Run, RunType, FunctDirectIn, Blank..., VarImp, Output) {
  library(caret)
  library(e1071)
  library(data.table)
  FunctDirectIn <- FunctDirectIn
  #OutDirectIn3 <- OutDirectIn2
  #VariableSubsets <- VariableSubset
  setwd(FunctDirectIn)
  # Read in User Defined Functions
  source("Kappa.Calc_Function.R")
  #
  if(missing(VarImp)) { VarImpOut=FALSE 
    } else {
    VarImpOut=TRUE  
  }
  if(missing(Output)) { Output=FALSE }
  #
  OutDirectIn3 <- OutDirectIn3
  VariableNamesSelOut <- data.frame(c(unlist(VariableSubsets)), stringsAsFactors=FALSE)
  colnames(VariableNamesSelOut) <- "VarNames"
  ConfMat.lst <- list()
  # If a class is missing from RefPnts.mat, add it in to keep table balanced
  RefClasses <- unique(RefPnts.mat)
  PredClasses <- unique(PredPnts.mat)
  head(PredPnts.mat)
  MissingRefClasses <- setdiff(PredClasses,RefClasses)
  MissingPredClasses <- setdiff(RefClasses,PredClasses)
  MissingClasses <- unique(c(MissingRefClasses, MissingPredClasses))
  # Add missing classes
  if(length(MissingClasses)>0) {
    for(i in 1:length(MissingClasses)) {
    #i=1
    #Add row for missing class in both matrices
    MissingValues.mat <- c(MissingClasses[i])
    # Merge MissingValues.mat with both matrices
    PredPnts.mat <- as.matrix(rbind(PredPnts.mat, MissingValues.mat))
    RefPnts.mat <- as.matrix(rbind(RefPnts.mat, MissingValues.mat))
    }
  }
  #
  ContTable <- round(table(PredPnts.mat, RefPnts.mat))
  names(dimnames(ContTable)) <- c('PredPnts', 'RefPnts')
  #
  NumClasses <- nrow(ContTable)
  ## Construct confusion matrix with User's and Producer's accuracies
  OverallAccuracy <- as.matrix(sum(diag(ContTable))/sum(ContTable))
  rownames(OverallAccuracy)[1] <- "OverallAccuracy"
  # Calculate Overall TSS for special case where absence values for one class equal
  # the presence values for other classes
  OverallTSS <- (OverallAccuracy*2)-1
  rownames(OverallTSS)[1] <- "OverallTSS"
  sumf <- function(x) c(sum=sum(x))
  ColSums <- round(t(as.matrix(apply(ContTable,2,sumf))),2)
  rownames(ColSums)[1] <- "Total     "
  RowSums <- as.matrix(apply(ContTable,1,sumf))
  colnames(RowSums)[1] <- "Total"
  DiagonalSum <- as.matrix(sum(diag(ContTable)))
  RowSums <- rbind(RowSums, DiagonalSum)
  GrandTotal <- as.matrix(sum(ColSums))
  UsersAccuracy <- round(as.matrix(diag(ContTable)/rowSums(ContTable)),2)
  colnames(UsersAccuracy)[1] <- "User's Accuracy"
  UsersAccuracy <- rbind(UsersAccuracy, 0)
  ProducersAccuracy <- round(t(as.matrix(diag(ContTable)/colSums(ContTable))),2)
  ProducersAccuracy <- cbind(ProducersAccuracy, 0, "      ", GrandTotal)
  rownames(ProducersAccuracy)[1] <- "Producer's  "
  ConfMatTable <- rbind(ContTable, ColSums)
  ConfMatTable <- cbind(ConfMatTable, RowSums, UsersAccuracy)
  # Convert matrices to factors for caret package
  PredPnts.fac <- as.factor(PredPnts.mat)
  RefPnts.fac <- as.factor(RefPnts.mat)
  #
  ConfMat <- confusionMatrix(PredPnts.fac, RefPnts.fac)  # from caret package
  ConfMat.lst[[1]] <- ConfMat
  Kappa <- ConfMat$overall[2]
  # Collect Producer's Accuracy values (same as Sensitivity) from confusionMatrix output by class
  ProducersAccuracyVal <- ConfMat$byClass[1:NumClasses, 1]
  names(ProducersAccuracyVal) <- gsub("Class: ", "ProdAcc:", names(ProducersAccuracyVal))
  ProducersAccuracyVal.df <- data.frame(t(as.matrix(ProducersAccuracyVal)), stringsAsFactors=FALSE)
  colnames(ProducersAccuracyVal.df) <- paste0(colnames(ProducersAccuracyVal.df), ".", TestDataType)
  # Collect User's Accuracy values (same as Positive Predictive Value) from confusionMatrix output by class
  UsersAccuracyVal <- ConfMat$byClass[1:NumClasses, 3]
  names(UsersAccuracyVal) <- gsub("Class: ", "UserAcc:", names(UsersAccuracyVal))
  UsersAccuracyVal.df <- data.frame(t(as.matrix(UsersAccuracyVal)), stringsAsFactors=FALSE)
  colnames(UsersAccuracyVal.df) <- paste0(colnames(UsersAccuracyVal.df), ".", TestDataType)
  ###
  ## Calculate Conditional User's and Producer's Kappa with variance
  ## Kappa.Calc function from Rossiter (2014): http://www.css.cornell.edu/faculty/dgr2/teach/R/R_ac.pdf
  KappaCalc.Res <- Kappa.Calc(ContTable)
  #sum(KappaCalc.Res$user.naive)/nrow(ContTable); sum(KappaCalc.Res$prod.naive)/ncol(ContTable)
  # Collect Producer's per class kappa from ContTable
  ProducersKappaVal <- KappaCalc.Res$prod.kappa  
  names(ProducersKappaVal) <- paste("ProdKap", names(ProducersKappaVal))
  ProducersKappaVal.df <- data.frame(t(as.matrix(ProducersKappaVal)), stringsAsFactors=FALSE)
  names(ProducersKappaVal.df) <- paste0(names(ProducersKappaVal.df), ".", TestDataType)
  # Collect User's per class kappa from ContTable
  UsersKappaVal <- KappaCalc.Res$user.kappa  
  names(UsersKappaVal) <- paste("UserKap", names(UsersKappaVal))
  UsersKappaVal.df <- data.frame(t(as.matrix(UsersKappaVal)), stringsAsFactors=FALSE)
  names(UsersKappaVal.df) <- paste0(names(UsersKappaVal.df), ".", TestDataType)
  # Substitute "Prod" for "User" in names of UsersKappaVal.df before combining below
  names(UsersKappaVal.df) <- gsub("User", "Prod", names(UsersKappaVal.df))
  # Calculate mean User's and Producer's kappa per class from above values
  MeanKappaVal.df <- rbindlist(list(ProducersKappaVal.df,UsersKappaVal.df), fill=TRUE)[,lapply(.SD,mean), list()]  #from data.table package
  names(MeanKappaVal.df) <- gsub("Prod", "MeanCond", names(MeanKappaVal.df))
  # Assemble main evaluation statistics together for later csv output
  ConfMatStats.df1 <- data.frame(t(as.matrix(c(ConfMat$overall[1], ConfMat$overall[2], OverallTSS))))
  colnames(ConfMatStats.df1) <- c(paste0("OverallAccuracy.", TestDataType), paste0("Kappa.", TestDataType), paste0("OverallTSS.", TestDataType))
  ConfMatStats.df <- cbind(VariableNamesSelOut, ConfMatStats.df1, ProducersAccuracyVal.df, UsersAccuracyVal.df, ProducersKappaVal.df, UsersKappaVal.df, MeanKappaVal.df)
  ConfMat.lst[[2]] <- ConfMatStats.df
  ####
  if(Output==TRUE) {
    header <- "               Reference Data"
    Model <- paste0("Classification for ", SubsetVariableNumber, " Feature Subset: ", TestDataType, " Data for Model Testing ")
    ## Save confusion matrix statistics
    setwd(OutDirectIn3)
    # Output codes of variables used
    outCM <- paste0("ContTable_Run", Run, "_", RunType, "_", TestDataType, ".txt")
    outA <- paste0(Model, output1, "\n", Conditions2)
    cat(outA, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n")
    outB <- paste0("Variables: ", VariableNamesSelOut, "\n")
    cat(outB, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    outC <- paste("\n                             Reference Data")
    cat(outC, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    ConfMatTableO <- capture.output(print(ConfMatTable))
    outD <- paste(ConfMatTableO)
    cat(outD, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    printf <- function(m){write.table(format(m), col.names=F, quote=F)}
    ProducersAccuracyO <- capture.output(printf(ProducersAccuracy))
    outE <- paste(ProducersAccuracyO)
    cat(outE, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    outF <- paste("Accuracy")
    cat(outF, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    outG <- paste("\nOverall Accuracy:", round(OverallAccuracy,2))
    cat(outG, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    outH <- paste("\nKappa:", round(Kappa,2))
    cat(outH, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    outI <- paste("\nOverall TSS:", round(OverallTSS,2))
    cat(outI, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    outJ <- paste("\nconfusionMatrix Output\n")
    cat(outJ, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    outK <- capture.output(print(ConfMat))
    cat(outK, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    # 
    if(VarImpOut==TRUE) {
      outL <- paste("\nRandom Forest Model Variable Importance from Caret Package\n")
      cat(outL, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
      outM <- capture.output(print(VarImp))
      cat(outM, file=paste0(Species, "_", ModelNameOut, "_", output1, "_", outCM), sep="\n", append=TRUE)
    }
  }
  return(ConfMat.lst)
}
