R/gui.R

Defines functions gui

Documented in gui

#' @title gui
#' @description gui (GUI) is a GUI wrapper for CaseSolver
#' @details The function starts the CaseSolver software.
#' @param envirfile A file to a saved environment of a project (must contain nnTK)
#' @param envir A saved environment (nnTK)
#' @export

#library(casesolver);gui()
#library(casesolver);envirfile=NULL; envir=NULL
#load("C:/Users/oyvbl/Documents/CSproj_20woe.Rdata")

gui = function(envirfile=NULL, envir=NULL) {
  LUSsymbol = "_"
  MPSsymbol = ":" #Added in version 1.5.0
  colonsymbol = ":" #use variable for colon
  #noKit = "NONE" #name of empty kit
  defaultEncoding =  options()$encoding #Set default to local encoder: Makes it possible to use Language-text files in own language
  defaultLanguage = "English"
  
  #size of main window
  mwH <- 500
  mwW <- 1000
  w0 <- 20 #default textwidth (for gWidgets2::gedit)
  nLarge = 10000 #this is large threshold of number of references (dont change table alignment if more than this number)
  
  #type of gwidgets-kit
  options(guiToolkit="tcltk")
  
  #models:
  version =  packageVersion("casesolver") #obtain version
  spc <- 10  #Spacing between widgets
  
  #REPORT ITEMS (may change over versions)
  
  nReportItems = 26 #number of report items (will be inserted when opening program)
  reportitems <- rep("",nReportItems)  #assign emtpy  report items (must correspond to size of reportitems)
  
  #########################################################
  ################Environment variables####################
  #########################################################
  
  #NB: pgkPath and .sep must be changed before compiling R-package!
  pgkPath <- path.package("casesolver", quiet = FALSE) # Get package path.
  #pgkPath <- "config"# Get package path (possible to synchronize)
  .sep <- .Platform$file.sep # Platform dependent path separator. 
  
  setupRead = function(file) scan(file,what=character(),quiet=TRUE,sep="\n") #skip line is new element
  setupWrite = function(vals,file) write(vals,file=file,sep="\n")   #save to file in installation folder
  setupFileThresh <- paste(pgkPath,"configThresh",sep=.sep)   #file for threshold selection
  setupFileModel <- paste(pgkPath,"configModel",sep=.sep)   #file for model selection
  setupFileMarkers <- paste(pgkPath,"configMarkers",sep=.sep)   #file for model selection per markers
  setupFileKit <- paste(pgkPath,"configKit",sep=.sep)  #file for kit selection
  setupFilePop <- paste(pgkPath,"configPop",sep=.sep)  #file for population selection
  setupFileRare <- paste(pgkPath,"configRare",sep=.sep)  #file for options of rare alleles 
  setupFileCase <- paste(pgkPath,"configCase",sep=.sep)   #file for case selection
  setupFileImport <- paste(pgkPath,"configImport",sep=.sep)  #file for import selection
  setupFileReportLay <- paste(pgkPath,"configReportLay",sep=.sep) #used to set report layout
  setupFileReportOpt <- paste(pgkPath,"configReportOpt",sep=.sep) #used to set report options
  setupFileReportExpTyp <- paste(pgkPath,"configReportExpType",sep=.sep) #used to set report export type
  setupFileReportExpOpt <- paste(pgkPath,"configReportExpOpt",sep=.sep) #used to set report export option
  setupFileReportLocNames <- paste(pgkPath,"configReportLocNames",sep=.sep) #used to set marker names in report
  
  setupFileMCMC <- paste(pgkPath,"configMCMC",sep=.sep) #used to set advanced settings
  setupFileSorting <- paste(pgkPath,"configSorting",sep=.sep) #used to set sorting of tables settings
  setupFileAdvanced <- paste(pgkPath,"configAdvanced",sep=.sep) #used to set advanced settings
  setupFileView <- paste(pgkPath,"configView",sep=.sep) #used to set GUI layout
  setupFileLanguage <- paste(pgkPath,"configLanguage",sep=.sep)  #file for Language selection
  setupFileExport <- paste(pgkPath,"mmTK.Rdata",sep=.sep)  #used to run euroformix
  setupFileExport2 <- paste(pgkPath,"mmTK2.Rdata",sep=.sep)  #used to run euroformix
  
  #The files are stored in system settings and loaded when opening the tool:
  
  #Thresholds:
  optF = c(0.8,10,1000,7,14,15,0.99)
  if(file.exists(setupFileThresh)) optF <- setupRead(file=setupFileThresh)
  setupThresh = list(MACthresh=as.numeric(optF[1]),LRthresh1=as.numeric(optF[2]),LRthresh2=as.numeric(optF[3]),minLociSS=as.integer(optF[4]),minIBS=as.integer(optF[5]),ratio=as.numeric(optF[6]),probA=as.numeric(optF[7]))
  
  #Model options (global):
  optF =  c(50,0.05,0.01,0.01,1,2,2,1) #threshT: default value of detection threshold value,dropinC: Dropin probability parameter in model,dropinL: Dropin peak height distribution parameter Lambda. Modeltype={1,2,3}={qual,quan,both}
  if(file.exists(setupFileModel)) optF <- setupRead(file=setupFileModel)
  setupModel= list(threshT=as.numeric(optF[1]),dropinC=as.numeric(optF[2]),dropinL=as.numeric(optF[3]),fst=as.numeric(optF[4]),degrad=as.integer(optF[5]),stuttBW=as.integer(optF[6]),stuttFW=as.integer(optF[7]),modeltype=as.integer(optF[8]))
  
  #Model options per marker (need to traverse a flexible number of items):
  setupMarkers <- NULL #default is no specification (using global)
  nItemsMarkers = 5 #marker names, AT values, Dropin probs, Dropin lambdas, Fsts
  if(file.exists(setupFileMarkers)) {
    optF <- setupRead(file=setupFileMarkers)
    if(length(optF)>0) { #if registered
      nLocs = round(length(optF)/nItemsMarkers) #number of loci in file
      setupMarkers = list()#obtain vector with names and values 
      for(itemInd in 1:nItemsMarkers) { #traverse through each elemen type
        readRange = nLocs*(itemInd-1) + 1:nLocs
        insVal = optF[readRange] #extend existing vector with value
        if(itemInd>1) insVal = as.numeric(insVal)
        setupMarkers[[itemInd]] = insVal
      }
    }
  }
  
  #costumized locus/marker names in report
  setupReportLocNames = NULL
  if(file.exists(setupFileReportLocNames)) {
    optF <- setupRead(file=setupFileReportLocNames)
    if(length(optF)>0) nLocs = round(length(optF)/2) #use number of loci in file
    setupReportLocNames = optF[1:nLocs + nLocs] #obtain edited marker names
    names(setupReportLocNames) = optF[1:nLocs] #obtain Conventional names
  }
  
  #Kit selection
  optF = "" #no kit selected by default
  if(file.exists(setupFileKit)) optF <- setupRead(file=setupFileKit)
  setupKit = list(kitname=optF[1])   
   
  #Population freq (file selection):
  optF = rep("",2) #filename, amelChoice
  if(file.exists(setupFilePop)) optF <- setupRead(file=setupFilePop)
  setupPop = list(popfile=optF[1],amel=optF[2])
   
  #Population freq (rare alleles):
  optF = c("TRUE","") #whether to normalize, min. frequencies
  if(file.exists(setupFileRare)) optF <- setupRead(file=setupFileRare)
  setupRare = list(normalize=optF[1],minFreq=optF[2])
  
  #Path to Case folder (selection)
  optF = "" #empty casepath by default. Points to a folder with CASEID given as folder names. 
  if(file.exists(setupFileCase)) optF <- setupRead(file=setupFileCase)
  setupCase = list(casepath=optF[1]) 
  
  #Path to importData R-file (must contain the R-function importData. Points to a text-file.)
  optF = "" #empty importfile by default (must contain the R-function importData. Points to a text-file.
  if(file.exists(setupFileImport)) optF <- setupRead(file=setupFileImport)
  setupImport = list(importfile=optF[1])
  
  #Advanced options
  optF = c(4,4,3,"TRUE","FALSE","FALSE","FALSE","FALSE","FALSE") #this is default
  if(file.exists(setupFileAdvanced)) optF <- setupRead(file=setupFileAdvanced)
  if(length(optF)<8) optF = c(optF,rep("FALSE",2)) #include default value (COMPATIBLE FROM VERSION v2.0.2)
  setupAdvanced = list(maxC1=as.integer(optF[1]),maxC2=as.integer(optF[2]),nDone=as.integer(optF[3]),useMinK1=optF[4],compSS=optF[5],isSNP=optF[6],selProfiles=optF[7],useEFMex=optF[8],useMAC=optF[9])
  
  #Data view (vertical or horizontal)
  optF = c("FALSE")
  if(file.exists(setupFileView)) optF <- setupRead(file=setupFileView)
  setupView = list(importHorizontal=optF[1])
  
  #selected language
  optF = defaultLanguage #,encoding=defaultEncoding) #English langugage used by default.  
  if(file.exists(setupFileLanguage)) optF <- setupRead(file=setupFileLanguage)
  setupLanguage = list(language=optF[1])#,encoding=optF[2]) 
  
  #Option for sorting of tables:
  #Tables in import: 1) Evid (SingleSources and Mixtures) [EPGs will follow same order] and  2) Refs (known and extended)
  #Tables from comparison: 3) MatchList(Qual), 4) MatchList(Quan), 5) Matches
  optF = rep(1, 5) #defualt sorting
  if(file.exists(setupFileSorting)) optF <- setupRead(file=setupFileSorting)
  setupSorting = as.integer(optF)
  
  #Options for MCMC
  optF = c(2000,2,0.05,1)
  if(file.exists(setupFileMCMC)) optF <- setupRead(file=setupFileMCMC)
  setupMCMC = list(niter=as.integer(optF[1]),delta=as.numeric(optF[2]),quantile=as.numeric(optF[3]),seed=as.integer(optF[4]))   
  
  #Report:
  #Layout option
  optF = 1:nReportItems #order considered (0 means not used)
  if(file.exists(setupFileReportLay)) optF <- setupRead(file=setupFileReportLay)
  setupReportLay = list(priority=as.integer(optF)) #Gives priority of how layout should be given
  
  #Other options (whether to include in report or not)
  optNames = c("MatchStatus","MCMCsettings","mleLR","bayesLR","consLR","Mx","validFailed","verbalLR","headerTime")
  setupReportOpt <- optF <- setNames( rep(TRUE,length(optNames)),optNames) #WHether to show different options
  if(file.exists(setupFileReportOpt)) {
    optF2 <- setupRead(file=setupFileReportOpt)
    setupReportOpt[seq_along(optF2)] <- as.logical(optF2) #handling special case
  }
    
  #Export options: Export/Preview
  optF = c(TRUE,TRUE,FALSE,FALSE,FALSE,FALSE) #default values to insert
  if(file.exists(setupFileReportExpTyp)) optF <- as.logical( setupRead(file=setupFileReportExpTyp) )
  setupReportExpTyp = list(HTML=optF[1:2],DOCX=optF[3:4],DOC=optF[5:6]) 
  
  #Other export options (Table, sizes), DOC
  optF = c(1920,1080,120, 11,8.5,0.1,6,9,  6,11)
  if(file.exists(setupFileReportExpOpt)) optF <- setupRead(file=setupFileReportExpOpt)
  names(optF) = c("Width (px)","Height (px)","Resolution (ppi)",   #image options
                 "Width (inch)","Height (inch)","Margin (inch)","Table size","Text font size", #DOC options
                 "Table size","Text font size") #DOCX options
  setupReportExpOpt = list(PNG=optF[1:3], DOC=optF[4:8],DOCX=optF[9:10]) 
  
  if(is.null(envir)) { #Need to create invironment
    #Always done: create new envornment object. Parent must be empty
    nnTK = new.env( parent = emptyenv() ) 
    
    #Toolbar options: can be changed any time by using toolbar
    assign("setupThresh",setupThresh,envir=nnTK) 
    assign("setupModel",setupModel,envir=nnTK) 
    assign("setupMarkers",setupMarkers,envir=nnTK)  
    assign("setupKit",setupKit,envir=nnTK) 
    assign("setupPop",setupPop,envir=nnTK)
    assign("setupRare",setupRare,envir=nnTK)
    assign("setupCase",setupCase,envir=nnTK) 
    assign("setupImport",setupImport,envir=nnTK) 
    assign("setupAdvanced",setupAdvanced,envir=nnTK) 
    assign("setupView",setupView,envir=nnTK) 
    assign("setupLanguage",setupLanguage,envir=nnTK) 
    assign("setupMCMC",setupMCMC,envir=nnTK) 
    assign("setupSorting",setupSorting,envir=nnTK) 
    
    #Report settings
    assign("setupReportLay",setupReportLay,envir=nnTK)  #layout options
    assign("setupReportExpTyp",setupReportExpTyp,envir=nnTK)  #Export types
    assign("setupReportExpOpt",setupReportExpOpt,envir=nnTK)  #export format
    assign("setupReportOpt",setupReportOpt,envir=nnTK)  #other options (also whether to rotate tables)
    assign("setupReportLocNames",setupReportLocNames,envir=nnTK)  #User may modify marker names
    
    #initializing environment variables
    assign("workdir",NULL,envir=nnTK) #assign working directory to nnTK-environment
    
    #Considered CaseID:
    assign("caseID",NULL,envir=nnTK) #Used for report
    assign("version",version,envir=nnTK) #Include version which is used (useful for later)
    
    #imported data:
    assign("popFreq",NULL,envir=nnTK) #assign to nnTK-environment
    assign("mixDataTABLE",NULL,envir=nnTK) #Table of evidence profiles (only alleles)
    assign("refDataTABLE",NULL,envir=nnTK) #Table of ref profiles (only alleles)
    assign("mixDataMATCHSTATUS",NULL,envir=nnTK) #vector with match status for evidence profiles
    assign("mixDataLIST",NULL,envir=nnTK)  #list of evidence profiles (alleles and heights)
    assign("metaDataLIST",NULL,envir=nnTK) #list of imported metadata
    assign("consDataTABLE",NULL,envir=nnTK) #list of imported consensus data
    
    #table click: Program remembers last settings
    assign("clicktableLast",NULL,envir=nnTK) #used for table click when visualizing epgs
    
    #results: stored results after calculations
    assign("resCompMAC",NULL,envir=nnTK)  #store MAC results from comparison
    assign("resCompLR1",NULL,envir=nnTK)  #store LR results from qual based comparison (sorted)
    assign("resCompLR2",NULL,envir=nnTK)  #store LR results from quan comparison (sorted)
    assign("resCompLR",NULL,envir=nnTK)  #store LR results from qual/quan comparison (unsorted) 
    assign("resMatches",NULL,envir=nnTK)  #store match-results from comparison (those with LR>threshold)
    assign("allMixList",NULL,envir=nnTK)  #store match-results from comparison (those with LR>threshold) together with all mixtures
    assign("DClist",NULL,envir=nnTK)  #store list with deconvoluted reference candidates
    assign("DClistReport",NULL,envir=nnTK)  #store list with confirmed deconvoluted reference candidates (includes probs)
    assign("resRMP",NULL,envir=nnTK)  #store random match prob results 
    assign("resIBS",NULL,envir=nnTK)  #store IBS compare results (used in report)
    assign("storedFitHp",NULL,envir=nnTK) #store mle-fitted objects under Hp (for quantitative LR matchlist)
    assign("resEvidConc",NULL,envir=nnTK)  #store concordance results
    
    #Object for WoE calculations
    assign("modelSettings",NULL,envir=nnTK)  #currently not in use: would include following objects: popFreq,kit,fst,lambda,threshT,xiBW,xiFW,pC (updated when saved)
    assign("resWOEeval",NULL,envir=nnTK)  #store match-results from weight of evidence evaluations (LR-per marker, PH-validation)
    
    nnTK0 = nnTK #store environment to make older projects backward compatible
  } else if(is.null(envirfile)) {
    nnTK = envir #copy environment
  }
    
  #} else { #IF FILE IS GIVEN
  if(!is.null(envirfile)) {
    load(envirfile) #loading environment
    
    #Inform the user that the old project file is not supported by current version of casesolver
    outdated=FALSE
    projVersion = nnTK$version #obtain project version get("version",envir=nnTK)
    if(is.null(projVersion)) {
      outdated = TRUE
    }  else {
      projVersion2 = unlist(projVersion)[1:2] #strsplit(projVersion,"\\."))[1:2]
      version2 = unlist(version)[1:2]
      if( is.null(projVersion) || version2[1]!=projVersion2[1] || version2[2]!=projVersion2[2]) outdated = TRUE
    }
    if(outdated) { #notify if stored project version is outdated
      versionTxt = "The loaded project file was outdated:\n"
      versionTxt = paste0(versionTxt,"Project version: ",projVersion,"\n")
      versionTxt = paste0(versionTxt,"Note: The program may not work properly with an outdated project file.\n")
      #gWidgets2::gmessage(versionTxt,"Outdated project file", icon="info")
      cat(versionTxt)
      
      #Try make loaded project as backward compatible as possible: Use 'default settings' if non-compatible objects
      reqObjs = names(nnTK0) #obtain (all) required objects
      oldObjs = names(nnTK)  #objects from old version
      for(obj in reqObjs) {  #traverse all objects
        if(!obj%in%oldObjs) {
          assign(obj , nnTK0[[obj]] ,envir=nnTK)  #store default object if not found
        } else {
          reqItems = names(nnTK0[[obj]]) #obtain required items
          if(is.null(reqItems)) next #jump to next object
          
          oldItems = names(nnTK[[obj]]) #obtain required items
          if(length(reqItems)!= length(oldItems) || !all(reqItems==oldItems)) {
            assign(obj , nnTK0[[obj]] ,envir=nnTK)  #store default object if missmatch found
          }
        }
      }
    } #end if outdated
    #assign("setupRare",setupRare,envir=nnTK)
  } #end if project file was restored
  
  #################################################################################
  ###########################GUI HELPFUNCTIONS#####################################
  #################################################################################
  
  #This function is written since the encoding in  gWidgets2::gfile is fixed to UTF-8 which doesn't handle special letters
  mygfile <- function(text,type,filter=list(),initf=NULL) { #Possible bug: text ignored when type="selectdir"
   file <- gWidgets2::gfile(text=text,type=type,filter=filter,initial.filename=initf)
   Encoding(file ) <- defaultEncoding #Set to local encoder L$encoding #set special encoding (latin1 is default)
   return(file)
  }
  
  #Helpfunction to check if file is OK
  fileNotOK = function(x) { return( is.na(x) || length(x)==0)  }
   
  #Helpfunction to save a table to text file
  saveTable = function(tab,sep="txt") {
    tabfile  <- mygfile(text= paste( L$save , L$table) ,type="save") #csv is correct format!
    if(fileNotOK(tabfile)) return()
    
    if(length(unlist(strsplit(basename(tabfile),"\\.")))==1) tabfile = paste0(tabfile,".",sep)
    if(sep=="txt" | sep=="tab") write.table(tab,file=tabfile,quote=FALSE,sep="\t",row.names=FALSE) 
    if(sep=="csv") write.table(tab,file=tabfile,quote=FALSE,sep=";",row.names=FALSE) 
    print(paste("Table saved in ",tabfile,sep=""))
  } #end file
  
  #Helpfunction to set pop freq to environment 
  setPopFreq = function(change=FALSE,giveMessage=TRUE) { #helpfunction to read popFreq from file and set to environment
    if(!change && !is.null( get("popFreq",envir=nnTK))) return(TRUE) #return if already set
    
    opt <- get("setupPop",envir=nnTK) 
    tryCatch( {
      popFreq <- getFreqs(opt$popfile)
      AMEL <- c(0.75,0.25) #Assuming 50-50 Male/Femal population, abuse on Y/Y possibility
      names(AMEL) <- c("X","Y")
      if( opt$amel=="TRUE" && !any(grepl("AM",names(popFreq))) ) popFreq$AMEL =AMEL
      assign("popFreq",popFreq,envir=nnTK) #assign popFreq to nnTK-environment
      #if(verbose) print(popFreq) #print first time
    }, error = function(e) return(FALSE) )
    if(is.null(get("popFreq",envir=nnTK))) { #if popFreq is missing
      if(giveMessage) gWidgets2::gmessage( paste( L$msg.setPopFreq, L$setup,">",L$popfreq  ) ) 
      return(FALSE) 
    }
    return(TRUE)
  } 
  
  #Helpfunction to show table in GDF (editable cells)
  showGDFtable = function(title,table) {
    setwin2 <- gWidgets2::gwindow( title ,visible=FALSE) 
    guitab <- gWidgets2::gdf(items=table,container = setwin2) 
    gWidgets2::visible(setwin2) <- TRUE
    gWidgets2::focus(setwin2) <- TRUE
  }
  
  #Helpfunction to ensure focus of main window
  setFocus = function() { gWidgets2::focus(mainwin) <- TRUE }

  ###########################FILE#####################################
  f_setwd = function(h,...) {
    dirfile = mygfile(text= paste( L$select , L$folder) ,type="selectdir")
    if(fileNotOK(dirfile)) return()
    setwd(dirfile)
    assign("workdir",dirfile,envir=nnTK) #assign working directory
  }
  
  f_openproj = function(h,...) {
    filterList = list()
    filterList[[ L$proj  ]] = list(patterns=list("*.Rdata")) #set file extension pattern 
    filterList[[ L$all  ]] = list(patterns=list("*")) #set file extension pattern 
    projfile = mygfile(text= paste( L$open , L$proj) ,type="open", filter=filterList)
    if(fileNotOK(projfile)) return()
    gWidgets2::dispose(mainwin)
    casesolver::gui(projfile) #open environment file in program
  }
  
  f_saveproj = function(h,...) {
    projfile = mygfile(text= paste( L$save , L$proj) ,type="save")
    if(fileNotOK(projfile)) return()
    if(length(unlist(strsplit(basename(projfile),"\\.")))==1) projfile = paste0(projfile,".Rdata")
    print("Size of stored objects (in MB):") #prints size of each stored object
    print(sapply(nnTK,object.size)/1e6) #prints size of each stored object
    save(nnTK,file=projfile,compress="xz",eval.promises=FALSE,precheck=FALSE,compression_level=2)
    print(paste("Project saved in ",projfile,sep=""))
  }
  
  f_quitproj = function(h,...) {
    ubool <- gWidgets2::gconfirm( L$msg.saveproj ,title= L$quitprog ,icon="info")
    if(ubool) {
      f_saveproj(h)
    } else { 
      print("Program terminated without saving")
    }
    gWidgets2::dispose(mainwin) #remove window!
  }
  
  ###########################REPORT SETTINGS#####################################
  #Selection of report layout
  f_reportlay = function(h,...) { #GUI function to set report layout
    opt <- get("setupReportLay",envir=nnTK) #get layout settings
    setwin <- gWidgets2::gwindow( L$reportlayout ,visible=FALSE)
    group = gWidgets2::ggroup(spacing=5,container= setwin,horizontal=FALSE) 
    checkbox = gWidgets2::glayout(spacing=0,container=(group),horizontal=FALSE) 
    reportitems2 = paste( L$show , reportitems) #put "show" in front of each reportitems
    nItems = length(reportitems) #number of items
    itemRange = 0:nItems
    checkbox[1,2] = gWidgets2::glabel("Report object",container=checkbox)
    checkbox[1,3] = gWidgets2::glabel("Priority",container=checkbox)
    for(i in 1:nItems) {
      val = opt$priority[i] #obtain value
      checkbox[i+1,1] <- gWidgets2::glabel(paste0(i),container=checkbox) #add item number
      checkbox[i+1,2] <- gWidgets2::gcheckbox( reportitems2[i] ,checked=val>0,container=checkbox)
      checkbox[i+1,3] <- gWidgets2::gcombobox(items=itemRange,selected=which(val==itemRange),editable=TRUE,container=checkbox)
      gWidgets2::size(checkbox[i+1,3]) = 4
    } 
    #gWidgets2::add(tabval,checkbox)#,expand=TRUE,fill=TRUE)
    savebut <- gWidgets2::gbutton( L$save ,use.table=FALSE,container=group,handler = function(h, ...) { 
      for(i in 1:nItems) {
       val = 0 #default is not checked
       checked = gWidgets2::svalue(checkbox[i+1,2]) #indicate if checked
       if(checked) val= as.integer(gWidgets2::svalue(checkbox[i+1,3])) #obtain value
       opt$priority[i] = val #update priority variable
      } 
      assign("setupReportLay",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt$priority),file=setupFileReportLay)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    })
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #Selection of report options
  f_reportopt = function(h,...) { #GUI function to set report option
    opt <- get("setupReportOpt",envir=nnTK) #get layout settings
    #obtain names of options (INSERT HERE ONLY, NOT USED IN REPORT)
    items = paste(L$show,names(opt)) #c(L$matchstatus) #"MatchStatus"  
    setwin <- gWidgets2::gwindow( paste(L$report, L$options)  ,visible=FALSE)
    tabtmp <- gWidgets2::ggroup(horizontal = FALSE,container=setwin)
    
    #Option layout
    checkBox = gWidgets2::glayout(spacing=0,container= tabtmp)  
    for(j in 1:length(items)) {
      checkBox[j,1] = gWidgets2::glabel(names(items)[j],container=checkBox)
      checkBox[j,2] = gWidgets2::gcheckbox(items[j],checked = as.logical(opt[j]),container=checkBox)
    }
    
    #Save-button:
    savebut = gWidgets2::gbutton(L$save,container=tabtmp, handler = function(h) {
      for(j in 1:length(items)) {
         val = as.logical( gWidgets2::svalue(checkBox[j,2]) )
         if(!is.na(val)) opt[j]= val #insert value if not NA
      }
      assign("setupReportOpt",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileReportOpt)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    })
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #Selection of (exported) report types 
  f_reportexptyp = function(h,...) { #GUI function to set report export options
    opt <- get("setupReportExpTyp",envir=nnTK) #get layout setting
    setwin <- gWidgets2::gwindow( paste(L$report, L$export)  ,visible=FALSE, width=300,height=200)
    checkbox = gWidgets2::glayout(spacing=5,container=(setwin),horizontal=FALSE) 
    
    #Showing selection tables:
    types = names(opt) #c("HTML","DOCX","DOC") #report types
    items = c(L$report, L$preview) 
    for(i in 1:length(types)) checkbox[i+1,1] = gWidgets2::glabel(types[i],container=checkbox)
    for(j in 1:length(items)) checkbox[1,j+1] = gWidgets2::glabel(items[j],container=checkbox)
    for(i in 1:length(types)) {
      type = types[i]
      for(j in 1:length(items)) {
       val=opt[[type]][j] #obtain value
       checkbox[i+1,j+1] <- gWidgets2::gcheckbox("",checked=val,container=checkbox)
      }
    }
    #Save-button:
    checkbox[1,1] = gWidgets2::gbutton(L$save,container=checkbox, handler = function(h) {
      for(i in 1:length(types)) {
       type = types[i]
       for(j in 1:length(items)) {
         opt[[type]][j]=  gWidgets2::svalue(checkbox[i+1,j+1]) #obtain value
       }
      }
      assign("setupReportExpTyp",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileReportExpTyp)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    })
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #export options
  f_reportexpopt = function(h,...) { #GUI function to set report option
    opt <- get("setupReportExpOpt",envir=nnTK) #get layout settings
    types = names(opt)
    setwin <- gWidgets2::gwindow( paste(L$report,  L$export, L$options)  ,visible=FALSE)
    tabtmp <- gWidgets2::ggroup(horizontal = FALSE,container=setwin)
    
    #Option layout
    checkList = list() #layout list
    for(i in 1:length(types)) {
      type = types[i]
      items = opt[[type]]
      checkList[[i]] = gWidgets2::glayout(spacing=0,container= gWidgets2::gframe(type, container=tabtmp))  
      
      for(j in 1:length(items)) {
        checkList[[i]][j,1] = gWidgets2::glabel(names(items)[j],container=checkList[[i]])
        checkList[[i]][j,2] = gWidgets2::gedit(items[j],container=checkList[[i]])
      }
    }
    #Save-button:
    savebut = gWidgets2::gbutton(L$save,container=tabtmp, handler = function(h) {
      for(i in 1:length(types)) {
        type = types[i]
        items = opt[[type]]
        for(j in 1:length(items)) {
          val = as.numeric( gWidgets2::svalue(checkList[[i]][j,2]) )
          if(!is.na(val)) opt[[type]][j]= val #insert value if not NA
        }
      }
      assign("setupReportExpOpt",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileReportExpOpt)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    } )
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #helpfunction to modify marker names for report tables
  f_reportlocnames = function(h,...) {
    locNameVec <- get("setupReportLocNames",envir=nnTK) #obtain stored object (vector of marker names)
  
    #Obtain marker names from current imported case
    evidTable = get("mixDataTABLE",envir=nnTK) #Table of evidence profiles (only alleles)
    refTable = get("refDataTABLE",envir=nnTK) #Table of ref profiles (only alleles)
    
    caseLocNames <- NULL #toupper( names(locNameVec)) #default is markers stored in setupFile
    if(!is.null(evidTable)) { #if evid table found
      caseLocNames = toupper(colnames(evidTable))
    } else if(!is.null(refTable)) { #if else ref table found
      caseLocNames = toupper(colnames(refTable))
    }
    if(is.null(caseLocNames) && is.null(locNameVec)) return() #if no marker info found
    
    #POSSIBLY MODIFY THE locNAme vector    
    if(is.null(locNameVec)) {
      locNameVec = setNames(caseLocNames,caseLocNames) #use markers from imported case
    } else if(!is.null(caseLocNames)) { #If something was previously stored and case info is found
      locNameVec2 = setNames(caseLocNames,caseLocNames) #use markers from imported case
      commonLocs = intersect(caseLocNames,names(locNameVec)) #find common
      locNameVec2[commonLocs] = locNameVec[commonLocs] #update marker names from settings (not from case)
      locNameVec = locNameVec2 #update
    }
    locNames = names(locNameVec) #obtain names
    
    #Create window for selection
    setwin <- gWidgets2::gwindow( paste(L$Markernames)  ,visible=FALSE, width=100, height=500)
    grouplay <- gWidgets2::ggroup(spacing=2,container=(setwin),horizontal = FALSE, use.scrollwindow = TRUE)  #set group layout
    tabsel = gWidgets2::glayout(spacing=10,container=(grouplay),horizontal = TRUE)  #set grid  (will contain buttons)
    tabsel[1,1] = gWidgets2::gbutton(text=L$restore,container=tabsel, handler = function(h,...) {
      for(rowind in 1:length(locNameVec))  gWidgets2::svalue(tabval[rowind,2]) <- locNameVec[rowind] #recover name in edit box
    }) 
    tabsel[1,2] = gWidgets2::gbutton(text=L$save,container=tabsel, handler = function(h,...) {
      for(rowind in 1:length(locNameVec))  locNameVec[rowind] <- gWidgets2::svalue(tabval[rowind,2]) #obtain names from edit box
      assign("setupReportLocNames",locNameVec,envir=nnTK)  #assign user-values
      setupWrite(c(names(locNameVec),locNameVec),file=setupFileReportLocNames)    #save to file in installation folder
      gWidgets2::dispose(setwin) #remove window
    }) 
    
    #Box with names
    tabval = gWidgets2::glayout(spacing=0,container=(grouplay))  #create grid layout
    w0 <- 15 #width of textbox
    for(rowind in 1:length(locNameVec)) {
      tabval[rowind,1] <- gWidgets2::glabel(text=locNames[rowind],container=tabval)  #insert conventional marker name
      tabval[rowind,2] <- gWidgets2::gedit(text=locNameVec[rowind],width=w0,container=tabval)  #insert conventional marker name
    }
    gWidgets2::focus(setwin) = TRUE #set top
    gWidgets2::visible(setwin) = TRUE #show window
  }
  
  
  ###########################SETTINGS#####################################
  
  #GUI function to selecting threshold values
  f_threshsel=  function(h,...) { 
    opt <- get("setupThresh",envir=nnTK) 
    setwin <- gWidgets2::gwindow(paste0(  L$threshsettings ),visible=FALSE)
    tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
    tabval[1,1] <- gWidgets2::glabel(text= paste0( L$macthreshold ),container=tabval) #MATCH THRESHOLD
    tabval[1,2] <- gWidgets2::gedit(text=opt$MACthresh,width=w0,container=tabval)
    tabval[2,1] <- gWidgets2::glabel(text= paste0( L$qualLRthreshold ),container=tabval) #QUAL LR THRESHOLD
    tabval[2,2] <- gWidgets2::gedit(text=opt$LRthresh1,width=w0,container=tabval)
    tabval[3,1] <- gWidgets2::glabel(text= paste0( L$quanLRthreshold ) ,container=tabval) #QUAN LR THRESHOLD
    tabval[3,2] <- gWidgets2::gedit(text=opt$LRthresh2,width=w0,container=tabval)
    tabval[4,1] <- gWidgets2::glabel(text= paste0( L$minLocSSmatch ) ,container=tabval) #MINIMUM NUMBER OF LOCI TO MATCH WITH SINGLE SOURCE
    tabval[4,2] <- gWidgets2::gedit(text=opt$minLociSS ,width=w0,container=tabval)
    tabval[5,1] <- gWidgets2::glabel(text= paste0( L$minIBSrelative ) ,container=tabval) #REQUIRED MATCHING ALLELES BETWEEN REFS
    tabval[5,2] <- gWidgets2::gedit(text=opt$minIBS ,width=w0,container=tabval)
    tabval[6,1] <- gWidgets2::glabel(text= paste0( L$probRatioToNext ) ,container=tabval) #RATIO TO NEXT GENO-PROBABILITY THRESHOLD
    tabval[6,2] <- gWidgets2::gedit(text=opt$ratio ,width=w0,container=tabval)
    tabval[7,1] <- gWidgets2::glabel(text= paste0( L$probSingleAllele ) ,container=tabval) #ALLELE-PROBABILITY THRESHOLD
    tabval[7,2] <- gWidgets2::gedit(text=opt$probA ,width=w0,container=tabval)
    tabval[8,1] <- gWidgets2::gbutton( L$save, container=tabval,handler = function(h, ...) { 
      opt$MACthresh <- as.numeric(gWidgets2::svalue(tabval[1,2])) 
      opt$LRthresh1 <- as.numeric(gWidgets2::svalue(tabval[2,2])) 
      opt$LRthresh2 <- as.numeric(gWidgets2::svalue(tabval[3,2])) 
      opt$minLociSS <- as.numeric(gWidgets2::svalue(tabval[4,2])) #number of loci for being a match
      opt$minIBS <- as.numeric(gWidgets2::svalue(tabval[5,2])) #number of common alleles for being a relative
      opt$ratio <- as.numeric(gWidgets2::svalue(tabval[6,2])) #ratio of probability (deconvolution candidates)
      opt$probA <- as.numeric(gWidgets2::svalue(tabval[7,2])) #ratio of probability (deconvolution candidates)
      
      if(any(is.na(unlist(opt)))) stop("Invalid input given!") #throw error if any input is wrong
      assign("setupThresh",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileThresh)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    })
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #GUI for for selecting model settings
  f_modelsel=  function(h,...) {
    modtypetxt <- c( L$qualmodel , L$quanmodel , L$both )
    opt <- get("setupModel",envir=nnTK) 
    setwin <- gWidgets2::gwindow(paste0(  L$modelsettings ),visible=FALSE)
    tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
    
    tabval[1,1] <- gWidgets2::glabel(text= paste0(L$modeltypes," (",L$compare,")") ,container=tabval) #Model type(s)
    tabval[1,2] <- gWidgets2::gcombobox(items=modtypetxt,selected=opt$modeltype,horizontal=TRUE,container=tabval)
    tabval[2,1] <- gWidgets2::glabel(text= L$analyticalthreshold ,container=tabval) #Detection threshold
    tabval[2,2] <- gWidgets2::gedit(text=opt$threshT,width=w0,container=tabval)
    tabval[3,1] <- gWidgets2::glabel(text= L$dropinprob ,container=tabval) #Dropin probability
    tabval[3,2] <- gWidgets2::gedit(text=opt$dropinC,width=w0,container=tabval)
    tabval[4,1] <- gWidgets2::glabel(text= L$dropinpeakheightlambda ,container=tabval) #Dropin peak height Lambda (EFM)
    tabval[4,2] <- gWidgets2::gedit(text=opt$dropinL,width=w0,container=tabval)
    tabval[5,1] <- gWidgets2::glabel(text= L$fstsetting,container=tabval) #Dropin peak height Lambda (EFM)
    tabval[5,2] <- gWidgets2::gedit(text=opt$fst,width=w0,container=tabval)
    tabval[6,1] <- gWidgets2::glabel(text= L$degradationmodel ,container=tabval) #Degradation model (EFM)
    tabval[6,2] <- gWidgets2::gradio(items=radiotxt,selected=opt$degrad,horizontal=TRUE,container=tabval)
    tabval[7,1] <- gWidgets2::glabel(text= L$BWstuttermodel,container=tabval) #Stutter model (EFM)
    tabval[7,2] <- gWidgets2::gradio(items=radiotxt,selected=opt$stuttBW,horizontal=TRUE,container=tabval)
    tabval[8,1] <- gWidgets2::glabel(text= L$FWstuttermodel,container=tabval) #Stutter model (EFM)
    tabval[8,2] <- gWidgets2::gradio(items=radiotxt,selected=opt$stuttFW,horizontal=TRUE,container=tabval)
    
    #helpfunction to set marker specific settings
    f_setpermarker = function(h) {
      isok = setPopFreq(giveMessage=FALSE) #set  population frequency from last selected file
      if(!isok) {
        print("Specify a frequency file to continue.")
        return()
      }
      gWidgets2::dispose(setwin) #close setup window
      print("Please be patient (this could take a while)...")
      casesolver::setMarkerSettings(nnTK) # Obtain updated object
      
      #Store object to project and to file:     
      write(unlist(get("setupMarkers",envir=nnTK)),file=setupFileMarkers)    #save to file in installation folder
      gWidgets2::gmessage("Marker settings was successfully stored.")
    }
    
    tabval[2,3] <- gWidgets2::gbutton(text= L$setpermarker ,container=tabval, handler=f_setpermarker) #Detection threshold
    tabval[3,3] <- gWidgets2::gbutton(text= L$setpermarker ,container=tabval, handler=f_setpermarker) #Drop-in
    tabval[4,3] <- gWidgets2::gbutton(text= L$setpermarker ,container=tabval, handler=f_setpermarker) #dropin lambda
    tabval[5,3] <- gWidgets2::gbutton(text= L$setpermarker ,container=tabval, handler=f_setpermarker) #fst
    
    tabval[9,1] <- gWidgets2::gbutton( L$save , container=tabval,handler = function(h, ...) { 
      opt$modeltype <- which(gWidgets2::svalue(tabval[1,2])==modtypetxt) #set index 1,2,3
      opt$threshT <- as.numeric(gWidgets2::svalue(tabval[2,2]))
      opt$dropinC <- as.numeric(gWidgets2::svalue(tabval[3,2])) 
      opt$dropinL <- as.numeric(gWidgets2::svalue(tabval[4,2]))
      opt$fst <- as.numeric(gWidgets2::svalue(tabval[5,2]))
      opt$degrad <- which(gWidgets2::svalue(tabval[6,2])==radiotxt)  #set index 1,2
      opt$stuttBW <-  which(gWidgets2::svalue(tabval[7,2])==radiotxt)  #set index 1,2 
      opt$stuttFW <-  which(gWidgets2::svalue(tabval[8,2])==radiotxt)  #set index 1,2 
      
      if(any(is.na(unlist(opt)))) stop("Invalid input given!") #throw error if any input is wrong
      assign("setupModel",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileModel)    #save to file in installation folder
      
      #STORE setting INFO IN separate modelSettings Object (not used)
      assign("modelSettings",NULL,envir=nnTK)  #includes following objects: popFreq,kit,fst,lambda,threshT,xiBW,xiFW,pC (updated when saved)
      
      gWidgets2::dispose(setwin)
    } )
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #Function for selecting kit
  f_kitsel=  function(h,...) { #GUI function to select kit
    items0 = c(L$none,euroformix::getKit()) #no kits also possible
    opt <- get("setupKit",envir=nnTK) 
    setwin <- gWidgets2::gwindow( paste( L$select ,L$kit) ,visible=FALSE)
    tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
    tabval[1,1] <- gWidgets2::glabel(text= paste0( L$selected ," ", L$kit,colonsymbol) ,container=tabval)
    tabval[1,2] <- gWidgets2::glabel(text=opt$kitname,container=tabval)
    tabval[2,1] <- gWidgets2::glabel(text= paste( L$select , L$kit),container=tabval)
    tabval[2,2] <- gWidgets2::gcombobox(items=items0, width=100, selected=0, editable = FALSE, container = tabval)
    tabval[3,1] <- gWidgets2::gbutton( L$save , container=tabval,handler = function(h, ...) { 
      opt$kitname <-gWidgets2::svalue(tabval[2,2]) #get selected
      assign("setupKit",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileKit)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    } )
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #GUI for importing and modifying population frequency settings
  f_popsel=  function(h,...) {
   opt <- get("setupPop",envir=nnTK) 
   popfn <-  opt$popfile #population file name
   rareOpt = get("setupRare",envir=nnTK) 
   
   #Helpfunction for storing rare allele settings from GUI
   storeRareSettings = function(dispose=TRUE) {
     rareOpt$normalize = gWidgets2::svalue(grid2[1,1])
     rareOpt$minFreq = gWidgets2::svalue(grid2[3,1])
     assign("setupRare",rareOpt,envir=nnTK)   #store to environment
     setupWrite(unlist(rareOpt),file=setupFileRare)    #save to file in installation folder if successful
     if(dispose) gWidgets2::dispose(setwin) #remove subwindow
   }
   
   setwin <- gWidgets2::gwindow( paste( L$select ,L$popfreq) ,visible=FALSE)
   grp = gWidgets2::ggroup(spacing=4,container=(setwin),horizontal = FALSE)
   grid1 = gWidgets2::glayout(spacing=0,container=grp) 
   grid1[1,1] <- gWidgets2::glabel(text= paste0( L$selected ," ", L$popfreq,colonsymbol),container=grid1)
   grid1[1,2] <- gWidgets2::glabel(text= basename( popfn ) ,container=grid1)
   gWidgets2::tooltip(grid1[1,2]) <- popfn #highligh full file name when hovered
   grid1[2,1] <- gWidgets2::gcheckbox(text=paste( L$include , L$AMEL ),checked = ifelse(opt$amel=="TRUE",TRUE,FALSE),container=grid1)
   gWidgets2::tooltip(grid1[2,1]) <- "Including AMEL into the probabilistic model (ad-hoc approach). Needs to be ticked before selecting file." 
   grid1[3,1] <- gWidgets2::gbutton( paste( L$select , L$popfreq) , container = grid1,handler = function(h, ...) { 
    ff <- mygfile(paste( L$select , L$file ),type="open")
    if(length(ff)==0) return()
    opt$popfile <- ff
    opt$amel <-gWidgets2::svalue(grid1[2,1])
    assign("setupPop",opt,envir=nnTK)  #assign user-value to opt-list
    ok <- setPopFreq(change=TRUE)	#Assume that another freq file has been selected
    if(ok) {
      setupWrite(unlist(opt),file=setupFilePop)    #save to file in installation folder if successful
      storeRareSettings(TRUE) #store rare settings first
      #gWidgets2::dispose(setwin) #remove subwindow
      #f_popsel(); #update gui window again after selecting new folder
    }
   })
   
    #BUTTON TO SHOW FREQUENCIES (OWN WINDOW)
    grid1[4,1] <- gWidgets2::gbutton( paste( L$show , L$popfreq ), container = grid1,handler = function(h, ...) { #SHOW FREQS
      ok = setPopFreq() #import population frequency from last selected file
      if(!ok) return()
      popL = get("popFreq",envir=nnTK)
      maxA <- max(sapply(popL,length)) #maximum observed
      locs <- names(popL)
      nL <- length(locs)
      nB <- 4 #block size
      tab <- matrix("",nrow=nL*nB,ncol=maxA)
      for(ll in 1:nL) { #for each loci 
        loc <- locs[ll]
        inds <- 1:length(popL[[loc]])
        tab[(ll-1)*nB + 1,1] <- loc 
        tab[(ll-1)*nB + 2,inds] <- names(popL[[loc]])
        tab[(ll-1)*nB + 3,inds] <- popL[[loc]] #frequencies
      }
      colnames(tab) <- paste0(1:ncol(tab)) #set index (column numbers)
      showGDFtable( L$popfreq, tab)
    })
    
    grid1[5,1] <- gWidgets2::gbutton( L$removeselected, container = grid1,handler = function(h, ...) { 
      opt = list(popfile="",amel="")
      assign("setupPop",opt,envir=nnTK)  
      setupWrite(unlist(opt),file=setupFilePop) #make empty
      assign("popFreq",NULL,envir=nnTK) #assign popFreq to nnTK-environment
      gWidgets2::dispose(setwin) #remove subwindow
      f_popsel() #open again
    })
    
    #Other options (about freq for rare alles)
    grid2 = gWidgets2::glayout(spacing=0,container=gWidgets2::gframe( L$rarealleles ,container=grp)) 
    grid2[1,1] <- gWidgets2::gcheckbox( L$normalizeimpute ,checked = as.logical(rareOpt$normalize),container=grid2)
    gWidgets2::tooltip(grid2[1,1]) <- "Normalize allele frequencies after inserting rare alleles (not in allele freq population file)"
    grid2[2,1] <- gWidgets2::glabel(text= paste0( L$minFreq ,colonsymbol) ,container=grid2)
    gWidgets2::tooltip(grid2[2,1]) <- "Select minimum allele frequency value to be used for rare alleles (leaving it empty will make it use minimium observed)"
    minFreq = rareOpt$minFreq
    if(is.na(minFreq)) minFreq = ""
    grid2[3,1] <- gWidgets2::gedit( minFreq,container=grid2)
    grid2[4,1] <- gWidgets2::gbutton(L$save,container=grid2, handler=function(h) storeRareSettings())
    gWidgets2::tooltip(grid2[4,1]) <- "Selecting allele frequency file will also save the settings"
    
    gWidgets2::visible(setwin) <- TRUE
    gWidgets2::focus(setwin) <- TRUE
  }#end popfreq function
  
  #Function for selecting importData function file (R-script)
  f_importsel=  function(h,...) {
   opt <- get("setupImport",envir=nnTK) 
   setwin <- gWidgets2::gwindow( paste( L$select , L$importfun) ,visible=FALSE)
   tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
   tabval[1,1] <- gWidgets2::glabel(text= paste0( L$selected ," ", L$importfun,colonsymbol) ,container=tabval)
   tabval[1,2] <- gWidgets2::glabel(text=opt$importfile,container=tabval)
   tabval[2,1] <- gWidgets2::glabel(text= paste( L$select , L$importfun),container=tabval)
   tabval[2,2] <- gWidgets2::gbutton(  L$select , container = tabval,handler = function(h, ...) { 
     ff <- mygfile(paste( L$select , L$file ),type="open")
     if(length(ff)==0) return()
     opt$importfile <- ff
     assign("setupImport",opt,envir=nnTK)  #assign user-value to opt-list
     setupWrite(unlist(opt),file=setupFileImport)    #save to file in installation folder
     gWidgets2::dispose(setwin) #remove subwindow
     #f_importsel(); #update gui window again after selecting new folder
   })
   gWidgets2::visible(setwin) <- TRUE
  }
  
  #Function for selecting case directory
  f_casedirsel =  function(h,...) {
    opt <- get("setupCase",envir=nnTK) 
    setwin <- gWidgets2::gwindow( paste( L$select , L$pathcasefolders ) ,visible=FALSE)
    tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
    tabval[1,1] <- gWidgets2::glabel(text= paste0( L$selected ," ", L$pathcasefolders,colonsymbol),container=tabval)
    tabval[1,2] <- gWidgets2::glabel(text=opt$casepath,container=tabval)
    tabval[2,1] <- gWidgets2::glabel(text= paste( L$select , L$pathcasefolders) ,container=tabval)
    tabval[2,2] <- gWidgets2::gbutton( L$select , container = tabval,handler = function(h, ...) { 
      opt$casepath <- mygfile( paste( L$select , L$folder ),type="selectdir")
      
      assign("setupCase",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileCase)    #save to file in installation folder
      gWidgets2::dispose(setwin) #remove subwindow
      gWidgets2::dispose(mainwin) #remove main window
      gui(); #update restarted gui window again after selecting new folder 
    })
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #The user can change advanced model settings (nDone,maxContributors)
  f_advancedoptions = function(h,...) { 
    opt <- get("setupAdvanced",envir=nnTK) 
    setwin <- gWidgets2::gwindow( paste( L$advanced , L$options ) ,visible=FALSE)
    tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
    tabval[1,1] <- gWidgets2::glabel(text= L$maxcontrqual ,container=tabval) #"Maximum contributors in QualLR (LRmix)"
    tabval[1,2] <- gWidgets2::gedit(text=opt$maxC1,width=w0,container=tabval) 
    tabval[2,1] <- gWidgets2::glabel(text= L$maxcontrquan ,container=tabval) #Maximum contributors in QuanLR (EFM)
    tabval[2,2] <- gWidgets2::gedit(text=opt$maxC2,width=w0,container=tabval)
    tabval[3,1] <- gWidgets2::glabel(text= L$numoptim ,container=tabval) #"Number of required optimizes (EFM)"
    tabval[3,2] <- gWidgets2::gedit(text=opt$nDone,width=w0,container=tabval)
    tabval[4,1] <- gWidgets2::glabel(text= L$useoneaslowestnoc ,container=tabval) #Start with one contributor when estimating contrs
    tabval[4,2] <- gWidgets2::gcheckbox(text="",checked=opt$useMinK1=="TRUE",container=tabval)
    tabval[5,1] <- gWidgets2::glabel(text= L$showssinmatchlist ,container=tabval) #"Compare single sources"
    tabval[5,2] <- gWidgets2::gcheckbox(text="",checked=opt$compSS=="TRUE",container=tabval)
    tabval[6,1] <- gWidgets2::glabel(text= L$useSNPmodule ,container=tabval) #Use SNP module
    tabval[6,2] <- gWidgets2::gcheckbox(text="",checked=opt$isSNP=="TRUE",container=tabval)
    tabval[7,1] <- gWidgets2::glabel(text= L$profileselector ,container=tabval) #User can select profile when import/report
    tabval[7,2] <- gWidgets2::gcheckbox(text="",checked=opt$selProfiles=="TRUE",container=tabval)
    tabval[8,1] <- gWidgets2::glabel(text= L$useEFMex,container=tabval) #User can select if EFMex to be used
    tabval[8,2] <- gWidgets2::gcheckbox(text="",checked=opt$useEFMex=="TRUE",container=tabval)
    tabval[9,1] <- gWidgets2::glabel(text= L$useMAC,container=tabval) #User can select NOC estimate to be based on MAC (maximum allele counts)
    tabval[9,2] <- gWidgets2::gcheckbox(text="",checked=opt$useMAC=="TRUE",container=tabval)
    
    tabval[10,1] <- gWidgets2::gbutton( L$save , container=tabval,handler = function(h, ...) { 
      opt2 = list() #avoid wrong order 
      opt2$maxC1 <- as.numeric(gWidgets2::svalue(tabval[1,2]))  #max number of contributors in LRmix model
      opt2$maxC2 <- as.numeric(gWidgets2::svalue(tabval[2,2]))  #max number of contributors in EFM model
      opt2$nDone <- as.numeric(gWidgets2::svalue(tabval[3,2]))  #iterations in optimizer
      opt2$useMinK1 <- as.character(gWidgets2::svalue(tabval[4,2])==TRUE)  #should K=1 be used as start contr?
      opt2$compSS <- as.character(gWidgets2::svalue(tabval[5,2])==TRUE)  #Should single source profiles be compared?
      opt2$isSNP <- as.character(gWidgets2::svalue(tabval[6,2])==TRUE)  #Should SNP module be used (all evid samples are mixtures)
      opt2$selProfiles  <- as.character(gWidgets2::svalue(tabval[7,2])==TRUE)   #User can select profile when import/report
      opt2$useEFMex  <- as.character(gWidgets2::svalue(tabval[8,2])==TRUE)   #User can select profile if EFMex should be used
      opt2$useMAC  <- as.character(gWidgets2::svalue(tabval[9,2])==TRUE)   #User can select profile if EFMex should be used
      
      if(any(is.na(unlist(opt2)))) stop("Invalid input given!") #throw error if any input is wrong
      assign("setupAdvanced",opt2,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt2),file=setupFileAdvanced)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    } )
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #The user can change MCMC settings (niter,delta,seed)
  f_mcmcoptions = function(h,...) { 
    opt <- get("setupMCMC",envir=nnTK) 
    setwin <- gWidgets2::gwindow( paste( L$mcmc , L$options ) ,visible=FALSE)
    tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
    
    #Traversing each option:
    for(elem in names(opt)) {
      rowind = which(names(opt)==elem) #get rowindex
      tabval[rowind,1] <- gWidgets2::glabel(text= L[[elem]] ,container=tabval) #"Maximum contributors in QualLR (LRmix)"
      tabval[rowind,2] <- gWidgets2::gedit(text=opt[[elem]],width=w0,container=tabval) 
    }
  
    #Last button is save (storing and writing settings)
    tabval[length(opt)+1,1] <- gWidgets2::gbutton( L$save , container=tabval,handler = function(h, ...) { 
      opt2 = list() #avoid wrong order 
      for(elem in names(opt)) {
        rowind = which(names(opt)==elem) #get rowindex
        opt2[[elem]] <- as.numeric(gWidgets2::svalue(tabval[rowind,2]))  #max number of contributors in LRmix model
      }
      assign("setupMCMC",opt2,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt2),file=setupFileMCMC)    #save to file in installation folder
      gWidgets2::dispose(setwin)
    } )
    gWidgets2::visible(setwin) <- TRUE
  }
  
  #The user can select language:
  f_selLanguage =  function(h,...) { #GUI function to select language
    items0 = casesolver::getLanguage() #get list of available languages
    opt <- get("setupLanguage",envir=nnTK) 
    #if(is.null(opt)) opt = list(language=defaultLanguage,encoding=defaultEncoding) #set default if not found
    setwin <- gWidgets2::gwindow( paste( L$select , L$language ),visible=FALSE)
    tabval = gWidgets2::glayout(spacing=0,container=(setwin)) 
    tabval[1,1] <- gWidgets2::glabel(text= paste0( L$selected ," ", L$language,colonsymbol) ,container=tabval)
    tabval[1,2] <- gWidgets2::glabel(text=opt$language,container=tabval)
    tabval[2,1] <- gWidgets2::glabel(text= paste0( L$select ," ", L$language,colonsymbol) ,container=tabval)
    tabval[2,2] <- gWidgets2::gcombobox(items=items0, width=100, selected=0, editable = FALSE, container = tabval)
    tabval[3,1] <- gWidgets2::gbutton( L$save , container=tabval,handler = function(h, ...) { 
      opt$language <- gWidgets2::svalue(tabval[2,2]) #get selected
      #opt$encoding <- defaultEncoding #set default encoding (could extract encoding for current language)
      assign("setupLanguage",opt,envir=nnTK)  #assign user-value to opt-list
      setupWrite(unlist(opt),file=setupFileLanguage)    #save to file in installation folder
      gWidgets2::dispose(setwin) #close windown
      
      #RESTARTING PROGRAM
      gWidgets2::dispose(mainwin) #shut down main window
      gui(envir=nnTK); #start an with same session (recognized)
    } )
    gWidgets2::visible(setwin) <- TRUE
  }
  
  
  ################################################# 
  ##########FUNCTIONALITIES HELPFUNCTIONS########## 
  #################################################
  
  #Helpfunction for resaving to setupSorting object
  resave_Sorting = function(index,value) {
    sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types
    sortTypes[index] = value
    assign("setupSorting",sortTypes,envir=nnTK)
  }
  
  #MAIN FUNCTION TO IMPORT DATA
  f_importData = function(h,...) { #wrapper function which calls other functions: importData and getStructuredData
    #REMOVE PREV. RESULTS WHEN NEW IMPORT:
    if(!is.null(get("DClist",envir=nnTK)) || !is.null(get("resCompMAC",envir=nnTK))) {
      gWidgets2::gmessage( L$msg.restartfirst ) #message that user should restart before proceed with new case
    }
    caseID = gWidgets2::svalue( tabimportA[1,2] ) #get ID from table
    assign("caseID",caseID,envir=nnTK) #store ID in environment
    fn <- list.files(path=paste0(casedir,.sep,caseID), pattern="",full.names=TRUE) #get full names 
    
    print("-----------------------------")
    print("-------IMPORTING DATA--------")
    #NB: "importData" is a tailored function which must be created such that it provides a list with Evidence and Reference table:
    #Evidences: colnames(data$mix)=("SampleName","Marker","Alleles","Heights"). Separated with "/" in text format.
    #References: colnames(data$ref)=("SampleName","Marker","Alleles"). Separated with "/" in text format.
    
    #obtain importData from R-script and use to load data
    Rfile = get("setupImport",envir=nnTK)$importfile
    if(is.na(Rfile) ||  Rfile=="") {
      print("Couldn't find importData file. Returning..")
      return()
    }
    #This approach enables the R-function to have other name than importData
    importData <- source(Rfile, new.env(parent = globalenv() ),echo=FALSE)$value #obtain function with source 
    if(is.null(importData)) {
      gWidgets2::gmessage( paste( L$msg.importfunerror, L$settings,">",L$set,L$importfun ) )
      return()
    }
    data <- list(mix= matrix(nrow=0,ncol=4),ref= matrix(nrow=0,ncol=3))  #Formar: SampleName,Marker,Allele,(Height)
    markers <- numeric()
    metalist <- list() #contains list of table-elements
    consdata <- NULL #default value
  
   for(ff in fn) { #for each files: 
  #ff=fn[2]
     #if( file.info(ff)$isdir ) next #skip if it was a folder
     
     #IMPORTING DATA FROM USER-SPECIFIED FUNCTION (MUST BE NAMED "importData")
    tryCatch({ 
     data2 <- importData(ff) #import data for selected case. Structure of markers must be given inside this function and returned by "markers".
     data$mix <-  rbind(data$mix,data2$mix) #add data to table
     data$ref <-  rbind(data$ref,data2$ref) #add data to table
     if(length(markers)==0 && length(data2$markers)>0) markers <- data2$markers #get marker order from costumized importData file
     consdata <- rbind(consdata,data2$cons) #add data to table (consensus data)
  
     #Add metadata (assumed to be matrix/dataframes:
     tmplist <- data2$meta
     if(length(tmplist)==0) next #skip if no elements
     if(length(metalist)==0) { #if no list elements
       metalist <- tmplist 
     } else { #list elements found
       if(all(names(metalist)==names(tmplist))) { #check if containing same elements
         for(elem in names(metalist)) {
          if(length(tmplist[[elem]])>0)  { #check if not empty
            if( is.matrix(tmplist[[elem]]) ) { #BLOCK MODIFIED (v1.8.1)
              metalist[[elem]] <- rbind(metalist[[elem]],tmplist[[elem]]) #add to matrix
            } else {
              metalist[[elem]] <- c(metalist[[elem]],tmplist[[elem]]) #append to vector
            }
          }
         }
       } else {
        print("Metadata did not contain same list elements")        
       }
     }
    }, error = function(e) e) 
   }
   data$ref <- unique(data$ref) #consider only uniques
   data$mix <- unique(data$mix) #consider only uniques
   print("------------------------------")
   
   #Store non-profile data (CAN BE SHOWN IN REPORT)
   assign("metaDataLIST",metalist,envir=nnTK) #assign to nnTK-environment
   assign("consDataTABLE",consdata,envir=nnTK) #list of imported consensus data
   
   if( get("setupAdvanced",envir=nnTK)$selProfiles=="TRUE" ) {
     print("-------USER SELECTION-------") #the user may select a subset of samples to import
     guienv = new.env( parent = emptyenv() ) #create new envornment object. Parent must be empty
     assign("selected",list(evids=unique(data$mix[,1]),refs=unique(data$ref[,1])),envir=guienv)
     profileSelectorGUI(env=guienv) #calling function to select data
     selList =  get("selected",envir=guienv) #get list of 
     data = list( mix=data$mix[data$mix[,1]%in%selList$evids,,drop=FALSE] , ref=data$ref[data$ref[,1]%in%selList$refs,,drop=FALSE] ) #update data object
   }
   
   #In case of no data (RETURN WITH MESSAGE):
   if(length(markers)==0 || (nrow(data$mix)==0 && nrow(data$ref)==0) ) {
     gWidgets2::gmessage( L$msg.nodata ) #user need to select at least one profile to proceed
     return()
   }
     
   print("-------STRUCTURING DATA-------")
   datalist <- casesolver::getStructuredData(data,ln=toupper(markers),minLoc=get("setupThresh",envir=nnTK)$minLociSS) #get Data in both List-format and Table-format (mixDataTABLE,refDataTABLE,mixDataLIST)
   datalist$mixDataMATCHSTATUS = changeUnknownName(datalist$mixDataMATCHSTATUS) #update unknown names
   rownames(datalist$refDataTABLE) = changeUnknownName(rownames(datalist$refDataTABLE)) #update unknown names
   
   if(!is.null(datalist$mixDataMATCHSTATUS) && length(datalist$mixDataMATCHSTATUS)>0 && !is.null(get("setupAdvanced",envir=nnTK)$isSNP) && get("setupAdvanced",envir=nnTK)$isSNP=="TRUE") {
     datalist$mixDataMATCHSTATUS[1:length(datalist$mixDataMATCHSTATUS)] = L$mixture #assign as mixture
   } 
  
   ##Notice: The alleles in a loci should be ordered: Hence samples with same alleles can be detected   
   #STORE DATA (BOTH TYPES) -> EASY AVAILABLE THROUGH ENVIRONMENT
   assign("mixDataTABLE",datalist$mixDataTABLE,envir=nnTK) #assign to nnTK-environment
   assign("refDataTABLE",datalist$refDataTABLE,envir=nnTK) #assign to nnTK-environment
   assign("mixDataMATCHSTATUS",datalist$mixDataMATCHSTATUS,envir=nnTK) #assign to nnTK-environment
   assign("mixDataLIST",datalist$mixDataLIST,envir=nnTK) #assign to nnTK-environment
  # assign("refDataLIST",datalist$refDataLIST,envir=nnTK) #NOT USED ANYMORE!
  
   updateTables() #update datables (default sorting first time)
   refreshTabLIST() #update mixture-list (default sorting first time)
   setFocus() #set focus
  } #end import function
  
  
  #A do-all function for selected profiles(substitutes Export and Deconvolute):
  f_markprofs = function(h,...) { #helpfunction to operate on selected profiles (View/Export/Deconvolve/Delete)
    mixSelID <- refSelID <- NULL
    tryCatch( { mixSelID =  as.integer(gsub("#","",gWidgets2::svalue(mixTabGUI))) }, error=function(e) print("No EVIDS in table"))
    tryCatch( { refSelID =  as.integer(gsub("#","",gWidgets2::svalue(refTabGUI))) }, error=function(e) print("No REFS in table"))
    if(length(mixSelID)==0 && length(refSelID)==0) {
  	  gWidgets2::gmessage( L$msg.selectprofile ) #user need to select at least one profile to proceed
  	 	return()
    }
    mixL <- get("mixDataLIST",envir=nnTK)[mixSelID] #get selected mixtures
    refTab <- get("refDataTABLE",envir=nnTK)[refSelID,,drop=FALSE] #get reference table
    refL <- casesolver::tabToListRef(tab=refTab,setEmpty=FALSE) #FORCING 1-alleles to be homozygous (necessary for EFM)	
    rm(refTab);gc()
    evids <- names(mixL)
    refs <- names(refL)
    
    #Begin GUI
    selwin <- gWidgets2::gwindow( L$functionalities ,width=100,height=100,visible=FALSE)
    tabtmp <- gWidgets2::glayout(container=selwin)
    
    #Data selection:
    tabSel = gWidgets2::glayout(spacing=0,container=(tabtmp[1,1] <- gWidgets2::gframe( L$data.select ,container=tabtmp)))  
    tabSel[1,1] = gWidgets2::glabel(text= L$evidences ,container=tabSel)
    tabSel[1,2] = gWidgets2::glabel(text= L$references ,container=tabSel)
    tabSel[2,1] <- gWidgets2::gcheckboxgroup(items=evids,container=tabSel,checked=TRUE)
    tabSel[2,2] <- gWidgets2::gcheckboxgroup(items=refs,container=tabSel,checked=TRUE)
    
    tabFun = gWidgets2::glayout(spacing=spc/2,container=(tabtmp[1,2] <- gWidgets2::gframe( L$functionalities ,container=tabtmp)))  
    
    getSelected = function() { #helpfunction to get selected
     selEvid <- selRef <-  NULL
     if(!is.null(evids) && length(evids)>0 ) selEvid <- gWidgets2::svalue(tabSel[2,1]) #get selected evids
     if(!is.null(refs) && length(refs)>0) selRef <- gWidgets2::svalue(tabSel[2,2]) #get selected refs
     return( list(Evid=selEvid,Ref=selRef) )
    }
    
    #FUNCTION 1: View data
    tabFun[1,1] = gWidgets2::gbutton(text= paste( L$show,L$data ),container=tabFun, handler=function(h,...) { 
     selL <- getSelected()
     if( all(sapply(selL,length)==0) ) return() #return if no selected profiles
     viewdata(mixL[selL[[1]]],refL[selL[[2]]]) 
    }) 
    
    #FUNCTION 2: Deconvolute
    tabFun[2,1] = gWidgets2::gbutton(text= L$deconvolve ,container=tabFun, handler=function(h,...) { 
     selL <- getSelected() #get selected evid/refs
     if(length(selL[[1]])==0) return()  #return if no selected evid profile
     createHypDCWindow(selL[[1]],selL[[2]],nC=length(selL[[2]])+1) #create window for specify model for DC  
    }) 
    
    #FUNCTION 3: Open data in EFM:
    tabFun[3,1] = gWidgets2::gbutton(text=paste( L$openin ,"EuroForMix"),container=tabFun, handler=function(h,...) { 
      load(setupFileExport) #load emtpy object with ESX17 kit popfreq in euroformix 
      selL <- getSelected() #get selected evid/refs
      if(length(selL[[1]])>0) mmTK$mixData <- mixL[selL[[1]]]
      if(length(selL[[2]])>0) mmTK$refData <- refL[selL[[2]]]
      
      #Obtain popfreq and selected kit: 
      mmTK$popFreq = nnTK$popFreq #obtain frequencies if any
      mmTK$selPopKitName = rep(NA,2)
      if(!is.null(nnTK$setupKit$kitname)) mmTK$selPopKitName[1] = nnTK$setupKit$kitname #insert selected kit
      if(!is.null(nnTK$setupPop$popfile)) mmTK$selPopKitName[2] = basename(nnTK$setupPop$popfile) #insert selected kit
      
      #Obtain settings from GUI:
      #Obtain global settings:
      mmTK$optSetup$thresh0 <- nnTK$setupModel$threshT
      mmTK$optSetup$pC0 <- nnTK$setupModel$dropinC
      mmTK$optSetup$lam0 <- nnTK$setupModel$dropinL
      mmTK$optSetup$fst0 <-  nnTK$setupModel$fst
      
      #Specify marker-based settings if given (load it into EFM object)
      if(!is.null(nnTK$setupMarkers)) {
        locNames = nnTK$setupMarkers[[1]] #obtain loci names
        mmTK$optMarkerSetup = list( 
          threshv = setNames(nnTK$setupMarkers[[2]],locNames),
          pCv = setNames(nnTK$setupMarkers[[3]],locNames),
          lamv = setNames(nnTK$setupMarkers[[4]],locNames),
          fstv = setNames(nnTK$setupMarkers[[5]],locNames))
      }
      save(mmTK,file=setupFileExport2,compress="xz") #save envir object to file (Rdata)
      euroformix::efm(envirfile=setupFileExport2) #run efm with saved file
    }) #end export to EFM
    
    
    #FUNCTION 4: Delete selected profiles from GUI
    tabFun[4,1] = gWidgets2::gbutton(text= paste(L$deletefrom, L$gui) ,container=tabFun, handler=function(h,...) { 
     	selL <- getSelected()
     	if( length(selL[[1]])==0 && length(selL[[2]])==0) return() #return if none selected
    	txt = L$msg.deleteprofiles #delete following profiles?
    	sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types (all tables except of matchMatrix)
    	
    	#Obtain match lists (matchmatrix,qualLR,quanLR,matchlist)
    	resCompMAC = get("resCompMAC",envir=nnTK)
    	resCompLR1 = get("resCompLR1",envir=nnTK)
    	resCompLR2 = get("resCompLR2",envir=nnTK)
    	resCompLR  = get("resCompLR",envir=nnTK) #overview of combined results
    	resMatches = get("resMatches",envir=nnTK) #this is final match results
    	allMixList = get("allMixList",envir=nnTK) #list of all evidence profiles
    	#storedFitHp = get("storedFitHp",envir=nnTK)

    	#if removing any evid profiles: 
    	anyIsDeleted = FALSE
    	if( length(selL[[1]])>0 ) {  
        bool <- gWidgets2::gconfirm(paste0(txt,"\n",paste0(selL[[1]],collapse="\n")))
        if(bool) {
          if( !is.null(get("resCompMAC",envir=nnTK)) || !is.null(get("DClist",envir=nnTK)) ) {
            gWidgets2::gmessage("You can't delete evidence profiles after comparison or deconvolution!")
          } else { #If deletion was possible
            anyIsDeleted = TRUE
            mixTab = get("mixDataTABLE",envir=nnTK) #get evid table
            mixStatus = get("mixDataMATCHSTATUS",envir=nnTK) #get status
            mixList = get("mixDataLIST",envir=nnTK) #get evid list table
            allevids = names(mixList) #rownames(tabT) #get name of all evidence
            keepevids = setdiff(allevids,selL[[1]])
            keepevidsInd = which(allevids%in%keepevids) #obtain index for keeping
            mixStatus = mixStatus[keepevidsInd]
            mixTab = mixTab[keepevidsInd,,drop=FALSE] #update table
            
            #Remove evid from comparisons
            if(FALSE) {
              if(!is.null(resCompLR1)) resCompLR1 = resCompLR1[resCompLR1[,1]%in%keepevids,,drop=FALSE]
              if(!is.null(resCompLR2)) resCompLR2 = resCompLR2[resCompLR2[,1]%in%keepevids,,drop=FALSE]
              if(!is.null(resCompLR)) resCompLR  = resCompLR[resCompLR[,1]%in%keepevids,,drop=FALSE]
              if(!is.null(resMatches)) resMatches  = resMatches[resMatches[,1]%in%keepevids,,drop=FALSE]
              if(!is.null(allMixList)) allMixList = allMixList[allMixList[,1]%in%keepevids,,drop=FALSE]
              if(!is.null(resCompMAC)) {
                resCompMAC$MatchList = resCompMAC$MatchList[resCompMAC$MatchList[,1]%in%keepevids,,drop=FALSE]
                if(any( colnames(resCompMAC$MatchMatrix)%in%selL[[1]]) ) { #if columns was evids
                  resCompMAC$MatchMatrix= resCompMAC$MatchMatrix[,colnames(resCompMAC$MatchMatrix)%in%keepevids,drop=FALSE]
                } else {  #if rows was evids
                  resCompMAC$MatchMatrix= resCompMAC$MatchMatrix[rownames(resCompMAC$MatchMatrix)%in%keepevids,,drop=FALSE]
                }
              }
              #storedFitHp #REFRESH DECONVOLUTION TAB?
            } #end
            
            #REASSIGNING VALUES
            assign("mixDataTABLE",mixTab,envir=nnTK) #store evid table 
            assign("mixDataMATCHSTATUS",mixStatus,envir=nnTK) #store match status again 
            assign("mixDataLIST", get("mixDataLIST",envir=nnTK)[rownames(mixTab)],envir=nnTK) #store evid list
            updateTables(type="mix",sort=sortTypes[1]) #updates evid tables again 
          }
        } 
    	} #end if remove evid profiles
    	
    	#if removing any ref profiles
    	if(length(selL[[2]])>0) {  
        bool <- gWidgets2::gconfirm(paste0(txt,"\n",paste0(selL[[2]],collapse="\n")))
        if(bool) {
          anyIsDeleted = TRUE
          refTab = get("refDataTABLE",envir=nnTK) #get table with reference data
          allrefs = rownames(refTab)
          keeprefs = setdiff(allrefs,selL[[2]])
          mixStatus = get("mixDataMATCHSTATUS",envir=nnTK) #get status
          refTab = refTab[allrefs%in%keeprefs,,drop=FALSE] #update reference table
          mixStatusIndremove = mixStatus%in%selL[[2]] #get bool of those to remove
          mixStatus[mixStatusIndremove] = "" #NA #set NA as empty if removed
          assign("mixDataMATCHSTATUS",mixStatus,envir=nnTK) #store match status again 
          assign("refDataTABLE",refTab,envir=nnTK) #store ref table 
          
          #Helpfunction to remove references in table
          removeRef = function(tab,refsrm) {
            rmIdx = NULL #obtain indices where reference is removed
            for(ref in refsrm) rmIdx = c(rmIdx,grep(ref, tab[,2]))
            for(i in unique(rmIdx)) {
              refs = strsplit(tab[i,2],"/")[[1]]  #obtain refs
              refs = refs[!refs%in%refsrm]
              tab[i,2] = paste0(refs,collapse="/")
            }
            return(tab)
          }
          #Update comparison tables:
          if(!is.null(resCompLR1)) resCompLR1 = resCompLR1[resCompLR1[,2]%in%keeprefs,,drop=FALSE]
          if(!is.null(resCompLR2)) resCompLR2 = resCompLR2[resCompLR2[,2]%in%keeprefs,,drop=FALSE]
          if(!is.null(resCompLR)) resCompLR  = resCompLR[resCompLR[,2]%in%keeprefs,,drop=FALSE]
          if(!is.null(allMixList)) allMixList = removeRef(allMixList,selL[[2]])
          if(!is.null(resMatches)) resMatches = removeRef(resMatches,selL[[2]])
          if(!is.null(resCompMAC)) {
            resCompMAC$MatchList = resCompMAC$MatchList[resCompMAC$MatchList[,2]%in%keeprefs,,drop=FALSE]
            if(any( rownames(resCompMAC$MatchMatrix)%in%selL[[2]])) { #if columns was evids
              resCompMAC$MatchMatrix = resCompMAC$MatchMatrix[rownames(resCompMAC$MatchMatrix)%in%keeprefs,,drop=FALSE]
            } else {  #if rows was evids
              resCompMAC$MatchMatrix= resCompMAC$MatchMatrix[,colnames(resCompMAC$MatchMatrix)%in%keeprefs,drop=FALSE]
            }
          }
       	  #Update tables     	  
       	  updateTables(type="ref",sort=sortTypes[2]) #updates tables again 
       	  if(any(mixStatusIndremove)) updateTables(type="mix",sort=sortTypes[1]) #updates mix tables again 
      	} #end bool
    	}
    	
    	if(anyIsDeleted) { #restore tables if any deleted
      	#Save match lists (matchmatrix,qualLR,quanLR,matchlist) and update
      	assign("resCompMAC",resCompMAC,envir=nnTK)
      	assign("resCompLR1",resCompLR1,envir=nnTK)
      	assign("resCompLR2",resCompLR2,envir=nnTK)
      	assign("resCompLR",resCompLR,envir=nnTK) #overview of combined results
      	assign("resMatches",resMatches,envir=nnTK) #this is final match results
      	assign("allMixList",allMixList,envir=nnTK) #list of all evidence profiles
      	#assign("storedFitHp",storedFitHp,envir=nnTK)
      	refreshTabMATRIX(1)
      	refreshTabLIST1(sort=sortTypes[3]) #update match list (quanLR)
      	refreshTabLIST2(sort=sortTypes[4]) #update match list (quanLR)
      	refreshTabLIST(sort=sortTypes[5]) #update match list (final)
    	}
    }) #end delete funciton
    
    #FUNCTION 5: Modify match s selected profiles from GUI
    tabFun[5,1] = gWidgets2::gbutton(text= paste(L$select,L$matchstatus) ,container=tabFun, handler=function(h,...) { 
      selL <- getSelected()
      sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types
      #if removing any evid profiles: 
      evidSel = selL[[1]] #obtain selected evidence
      if( length(evidSel)==0 ) return()
      #if( !is.null(get("resCompMAC",envir=nnTK)) || !is.null(get("DClist",envir=nnTK)) ) {
      #gWidgets2::gmessage("You can't delete evidence profiles after comparison or deconvolution!")
      refTab = get("refDataTABLE",envir=nnTK) #get table with reference data
      refNames = rownames(refTab) #obtain reference names
      mixStatus = get("mixDataMATCHSTATUS",envir=nnTK) #get status for evids
      #Note: samples with "mixture" are separated from the others in report

      #Create dropdown meny with choices:
      items = c(L$none, L$mixture, refNames)
      itemselwin <- gWidgets2::gwindow( paste(L$select,L$matchstatus),visible=FALSE)
      itemselgrid =  gWidgets2::glayout(container=itemselwin)
      itemselgrid[1,1] = gWidgets2::glabel("Evidence(s):",container=itemselgrid) #export peak heights?
      itemselgrid[1,2] = gWidgets2::glabel( paste0(evidSel,collapse="/") ,container=itemselgrid) #export peak heights?
      itemselgrid[2,1] = gWidgets2::gcombobox(items,container=itemselgrid) #export peak heights?
      itemselgrid[2,2] = gWidgets2::gbutton(text=L$save,container=itemselgrid, handler=function(h,...){
        matchStatusSel = gWidgets2::svalue(itemselgrid[2,1]) #Obtain value from dropdown list
        if(matchStatusSel==items[1]) matchStatusSel = "" #make empty
        if(matchStatusSel==items[2]) matchStatusSel = "mixture" #insert as mixture (translated after)
        mixStatus[names(mixStatus)%in%evidSel] = matchStatusSel #modify matchstatus
        assign("mixDataMATCHSTATUS",mixStatus,envir=nnTK) #store match status again 
        updateTables(type="mix",sort=sortTypes[1]) #updates evid tables again 
        gWidgets2::dispose(itemselwin) #close selection window
      }) #Modify matchstatus?
      gWidgets2::visible(itemselwin)=TRUE
      gWidgets2::size(itemselwin) = c(300,30)
    }) 
    
    #Export reference file panels
    tabExp = gWidgets2::glayout(spacing=spc/2,container=(tabtmp[1,3] <- gWidgets2::gframe( L$fileexport ,container=tabtmp)))  
    	tabExp[2,1] = gWidgets2::gcheckbox(text=paste0( L$export ,"\n", L$withPH ),container=tabExp,checked=TRUE) #export peak heights?
    	tabExp[1,1] = gWidgets2::gbutton(text= paste0( L$export ,"\n", L$evidences ) ,container=tabExp,handler=function(h,...) {  #"Store\nevidence(s)
      selEvid <- gWidgets2::svalue(tabSel[2,1]) #get selected evids
      mixL2 = mixL[selEvid]
     	 if(length(mixL2)>0)  saveTable( sampleListToTable(mixL2,PH=gWidgets2::svalue(tabExp[2,1])) )
    })
    tabExp[1,2] = gWidgets2::gbutton(text= paste0( L$export ,"\n", L$references ) ,container=tabExp,handler=function(h,...) {  #"Store\nreference(s)"
     selRef <- gWidgets2::svalue(tabSel[2,2]) #get selected refs
     refL2 = refL[selRef]
     	 if(length(refL2)>0) saveTable(sampleListToTable(refL2))
    })
    gWidgets2::visible(selwin)=TRUE
  } #end function
  
  
  f_calcRMP = function(h,...) {  #Function to calculate RMP for each references and RMNE for all evidence
    isok = setPopFreq(giveMessage=TRUE) #import population frequency from last selected file (not required)
    if(!isok) return()
    resRMP = casesolver::calcRMP(nnTK)
    colnames(resRMP$evid) <- c(".", L$samplename , L$RMNE )
    colnames(resRMP$ref) <- c(".", L$samplename , L$RMP ) #insert column names
    assign("resRMP",resRMP,envir=nnTK)  #store random match prob results (to be shown in report)
  
    setwin <- gWidgets2::gwindow(paste0( L$randommatchprob ),visible=FALSE) 
    tabval <- gWidgets2::ggroup(container=gWidgets2::gframe( paste0( L$evidences,paste0(rep("\t",4),collapse=""), L$references ),container=setwin,expand=TRUE,fill=TRUE),expand=TRUE,fill=TRUE) #evidence,ref dataframe
    guitab1 <- gWidgets2::gtable(items=resRMP$evid,container = tabval) 
    guitab2 <- gWidgets2::gtable(items=resRMP$ref,container = tabval) 
    gWidgets2::add(tabval,guitab1,expand=TRUE,fill=TRUE) 
    gWidgets2::add(tabval,guitab2,expand=TRUE,fill=TRUE) 
    gWidgets2::visible(setwin) <- TRUE 
  } #end function
  
  #Function to calculate concordance between evidences: Much of the code is similar as IBS
  f_calcEvidConc = function(h,...) {  
    setPopFreq(giveMessage=FALSE) #import population frequency from last selected file (not required)
     
    out = NULL
    tryCatch({
      out = casesolver::calcEvidConc(nnTK)
    },error = function(e)  
       gWidgets2::gmessage( L$msg.largesampleerror ) #throw large sample eror  
    )
    if(!is.null(out)) {
     colnames(out) <- c( L$concordance , L$comparison, "." )# "Concordance","Comparison")
     assign("resEvidConc",out,envir=nnTK)  #store random match prob results (to be shown in report)
    
     #show candidates in GUI:
     out = cbind(1:nrow(out),out) #include rank
     colnames(out)[1] = L$rank 
     setwin <- gWidgets2::gwindow(paste0( L$concordantevidences ) ,visible=FALSE) 
     tabval <- gWidgets2::ggroup(container=gWidgets2::gframe( L$comparisons ,container=setwin,expand=TRUE,fill=TRUE),expand=TRUE,fill=TRUE,horizontal = FALSE) #evidence,ref dataframe
     guitab1 <- gWidgets2::gtable(items=out,container = tabval) 
     gWidgets2::add(tabval,guitab1,expand=TRUE,fill=TRUE) 
     gWidgets2::visible(setwin) <- TRUE 
    } else {
     gWidgets2::gmessage( L$msg.nocandidates )
     assign("resEvidConc",matrix(nrow=0,ncol=3),envir=nnTK)  #store empty table 
    }
  }
  
  
  f_calcIBS = function(h,...) {  #Function to calculate IBS between references
    setPopFreq(giveMessage=FALSE) #import population frequency from last selected file (not required)
    tabIBS = casesolver::calcIBS(nnTK,nLarge,L$mixture) #calculate IBS
    
    if(!is.null(tabIBS)) {
     colnames(tabIBS) <- c( L$nummismatch, L$comparison, ".", L$IBS, L$nummarkers  ) #note the added column names
     assign("resIBS",tabIBS,envir=nnTK)  #store random match prob results (to be shown in report)
    
     #show candidates in GUI:
     tabIBS = cbind(1:nrow(tabIBS),tabIBS) #include rank
     colnames(tabIBS)[1] = L$rank 
     setwin <- gWidgets2::gwindow( L$concordantreferences ,visible=FALSE)  #"Similarity of references"
     tabval <- gWidgets2::ggroup(container=gWidgets2::gframe( L$comparisons ,container=setwin,expand=TRUE,fill=TRUE),expand=TRUE,fill=TRUE,horizontal = FALSE) #evidence,ref dataframe
     guitab1 <- gWidgets2::gtable(items=tabIBS,container = tabval) 
     gWidgets2::add(tabval,guitab1,expand=TRUE,fill=TRUE) 
     gWidgets2::visible(setwin) <- TRUE 
    } else {
     gWidgets2::gmessage( L$msg.nocandidates )
     assign("resIBS",matrix(nrow=0,ncol=3),envir=nnTK)  #store empty IBS 
    }
  }
  
  f_calcIBSdist = function(h,...) {  #Function to calculate IBD between references
    ok = setPopFreq() #import population frequency from last selected file
    if(!ok) return() 
    
    #Ask for user permission to run (because of extensive calculation)
    userin = gWidgets2::gconfirm(  L$msg.calculationconfirmwarning ,icon="warning")
    if(userin) {
     dist <- casesolver::getIBSdistr(get("popFreq",envir=nnTK)) #simulate random match probas
     tab <- 1-cumsum(dist[,2]) #consider cumulative probs
     names(tab) <- dist[,1]
     barplot(tab,main="Random allele sharing under unrelatedness",xlab="x=number of shared alleles",ylab="Prob. sharing>=x") 
     #abline(h=0.05,lty=2)
     print(tab)
    }
  }
  
  #Helpfunction to create TopPlots (after model fit)
  makePlotTop = function(type,contFit,dc,kitname=NULL) {
   if(require(plotly)) {
     switch(type,
      "EPG" = euroformix::plotTopEPG2(contFit,dc,kit=kitname), #,AT=threshT)
      "LUS" = euroformix::plotTopMPS2(contFit,dc,grpsymbol=LUSsymbol),
      "MPS" = plotTopMPS2(contFit,dc, grpsymbol=MPSsymbol) )
     
   } else {
     switch(type,
      "EPG" = euroformix::plotTopEPG(contFit,dc,kitname=kitname),#threshT=threshT) 
      "LUS" = euroformix::plotTopLUS(contFit,dc,LUSsymbol=LUSsymbol),
      "MPS" = gWidgets2::gmessage("Please install plotly to show plot!") )
   }
  } #end function
  
  
  viewdata = function(mixL,refL=NULL,printout=TRUE) { #helpfunction to visualize data
    kitname = casesolver::getEnvirKit(nnTK)
    threshT=get("setupModel",envir=nnTK)$threshT
    type = casesolver::getSampleType2(mixL, kitname) #get sample types (EPG/MPS/LUS)
    
    #print out to console:
    if(printout) {
     for(mixid in names(mixL)) { #print out evidence profiles 
         print("--------------------------------") 
         print(mixid) 
         out = rbind(sapply(mixL[[mixid]],function(x) paste0(x$adata,collapse="/")),sapply(mixL[[mixid]],function(x) paste0(x$hdata,collapse="/")))
         rownames(out) = c("Alleles","Heights")
         print(out) 
     }  
     out = numeric()
     for(refid in names(refL)) { #print out evidence profiles 
         out = rbind( out, sapply(refL[[refid ]],function(x) paste0(x$adata,collapse="/")) )
     }      
     if(length(out)>0) {
       rownames(out) = names(refL)
       print("--------------------------------") 
       print(out) 
     }
    } #end if printout
    if( length(mixL)==0) return() #return if no evidence profiles given
    
    #Show plots in browser if plotly is installed (PRETTY)
    if( require(plotly) ) { 
      switch(type,
             "EPG" =  euroformix::plotEPG2(mixData=mixL,refData=refL,kit=kitname,AT=threshT),
             "LUS" =  euroformix::plotMPS2(mixData=mixL,refData=refL,AT=threshT,grpsymbol=LUSsymbol),
             "MPS" =  euroformix::plotMPS2(mixData=mixL,refData=refL,AT=threshT,grpsymbol=MPSsymbol))
      
    } else { #Otherwise we show in Rgui
      if(type=="MPS") {
        gWidgets2::gmessage("Please install plotly to show plot!")
      } else {
        dev.new(width=25, height=10)
        if(type=="LUS") {
          for(mixid in names(mixL)) { 	 
            euroformix::plotLUS(mixData=mixL[[mixid]],sn=mixid,refData=refL,LUSsymbol=LUSsymbol,threshT=threshT) 
            if(length(mixL)>1) dev.new() #plot in new window
          }
        } else {
          euroformix::plotEPG(mixL,refcond=refL,kitname=kitname,threshT=threshT)
        }
        dev.new()
        op <- par(no.readonly = TRUE)
        dev.off()
        par(op)
        setFocus()
      } #end if not MPS
    }
  } #end viewdata function
  
  
  #Function executed when double clicked one of the data tables
  clicktable = function(h,...) { #UPDATED V1.5 to HANDLE MPS FORMAT
  last <- get("clicktableLast",envir=nnTK) #assign to nnTK-environment
  mixL <- get("mixDataLIST",envir=nnTK)
  
  if(h$action=="mix") { #IF evid profile selected
   id <- as.integer(gsub("#","",gWidgets2::svalue(h$obj)))
   last <- list(mix=id) #store id, refs deleted
   assign("clicktableLast",last,envir=nnTK) #
   viewdata(mixL[id])
  }
  if(h$action=="ref" && !is.null(last$mix)) { #IF ref profile selected
   id <- as.integer(gsub("#","",gWidgets2::svalue(h$obj)))
   allid <- c(last$ref,id) #remember the other refs also
   last <- list(mix=last$mix,ref=allid) #store ids
   assign("clicktableLast",last,envir=nnTK) #
   refL <- casesolver::tabToListRef(tab=get("refDataTABLE",envir=nnTK)[allid,,drop=FALSE],setEmpty=FALSE) #FORCING DUP alleles
   viewdata(mixL[last$mix],refL)
  } 
  } #end function
  
  f_calcQuanLRall = function(h,...) { #function to run LR for all comparisons having LR>LRthresh(Qual)
   sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types
   
   getMatchesLR(type="quan") #run EFM 
   refreshTabLIST2(sort=sortTypes[4]) #update QUAN LR table with results
  
   #Create matchlist (Final step)
   createMatchlist(modtype=2) #update matchlist with results from QUAN LR
   refreshTabLIST(sort=sortTypes[5]) #update tables  
   gWidgets2::svalue(nb) <- 5 #go to overview when done
  }
  
  #Function executed when double clicked on the matchlist (LRmix): Specify #contr and calc LR.
  clickmatchlistQUAL = function(h,...) {
    LRtab <- get("resCompLR1",envir=nnTK) #get match list (sorted)
    if(is.null(LRtab)) return()
    matchlist <- get("resMatches",envir=nnTK) #get match list in mix-table
    id <- as.integer(gsub("#","",gWidgets2::svalue(h$obj)))
    evid = LRtab[id,1]
    ref = LRtab[id,2]
    lrval <- format(as.numeric(LRtab[id,4]),digits=4) #get LR for ref
    matchind = which(matchlist[,1]==evid) #get index of matchlist
    condRefs = NULL
    if(length(matchind)>0) {
     condRefs= unlist(strsplit(matchlist[matchind,2],"/"))
     condRefs = setdiff(condRefs,ref)
     if(length(condRefs)==0) {
       condRefs = NULL
       lrval2 = NULL
     } else {
       LRtab0 <- get("resCompLR",envir=nnTK) #get default match list
       subtab = LRtab0[ LRtab0[,1]==evid ,,drop=FALSE] #get relevant evidence 
       lrval2 <- format( as.numeric(na.omit(subtab[match(condRefs,subtab[,2]),4])) ,digits=4) #Order fixed in v2.1.0
     }
    } else {
      lrval2 = NULL #NONE is also possible
    }
    #User may specify number of contributors and conditionals
    #OPEN WINDOW TO SPECIFY HYP:
    suppressWarnings({
    #evids=evid;nC=as.integer(LRtab[id,5]);lrvals=lrval;condRefs=condRefs
     createHypLRWindow(evids=evid,ref=ref,condRefs=condRefs,nC=as.integer(LRtab[id,5]),lrvals=lrval,lrvals2=lrval2)  #creates a window to specify hypotheses
    })
  }
  
  #Function executed when double clicked on the matchlist (EFM): Show expected peak heights
  clickmatchlistQUAN = function(h,...) {
    id <- as.integer(gsub("#","",gWidgets2::svalue(h$obj)))
    tab <- get("resCompLR",envir=nnTK) #get match list (unsorted but truncated)
    tab2 <- get("resCompLR2",envir=nnTK) #get match list (sorted)
    ind <- which(tab2[id,1]==tab[,1] & tab2[id,2]==tab[,2]) #get correct index of unsorted list
    if(length(ind)==0) {
      tab1 <- get("resCompLR1",envir=nnTK) #get match list (sorted and not truncated)
      ind <- which(tab2[id,1]==tab1[,1] & tab2[id,2]==tab1[,2]) #get correct index of unsorted list
    }
    contFit <- get("storedFitHp",envir=nnTK)[[ind]]  #get stored model fit under Hp
    kitname = getEnvirKit(nnTK) #get selected kit
    
    suppressWarnings({
     dc <- euroformix::deconvolve(contFit,maxlist=1) #get top candidate profiles
    })
    
    #Again: determine whether it is EPG/MPS(LUS)/(strings): Check if "_" is used. Otherwise check with all alleles are strings
    type = casesolver::getSampleType2(contFit$model$samples,kitname) #get sample type
    makePlotTop(type,contFit,dc,kitname) #create plot
  } #end if clickmatchlistQUAN 
  
  #Helpfunction to get refList for specific given refs (single alleles are always filled twice, assumed homozygouz)
  getRefL = function(refs) { #return list with same order as for refs
    reftab=get("refDataTABLE",envir=nnTK)
    refL <- casesolver::tabToListRef(tab=reftab[match(refs,rownames(reftab)),,drop=FALSE],setEmpty=TRUE) #Genotypes with 1-alleles are ignored
    rm(reftab);gc()
    return(refL)
  }
  
  #FUNCTION WHICH PERFORMS DC (uses settings in GUI)
  doDC = function(nC,evids=NULL,refs=NULL,showPlot=TRUE,useplotly=TRUE,addedProfiles=NULL) {
   useplotly <- useplotly && require(plotly) #must be installed
   
   refData <- condOrder <- NULL
   if(!is.null(refs) && length(refs)>0) {
     refData = getRefL(refs) # get list of reference data
     condOrder = 1:length(refs) #hypothesis is to condition on all references
   }
   evidData <- get("mixDataLIST",envir=nnTK)[evids] #evidence to consider
   evids = paste0(evids,collapse="/") #collapse multiple evidence names
   condrefs = paste0(refs,collapse="/")
   
   suppressWarnings({ 
     contFit <- casesolver::calcQuanMLE(evidData,refData,condOrder,nC,nnTK,verbose=TRUE) #get fitted object
     dc <- euroformix::deconvolve(contFit,maxlist=1) #get top candidate profiles
   })
   if(showPlot) {
     kitname = casesolver::getEnvirKit(nnTK) #get kitname
     type = casesolver::getSampleType2(evidData,kitname) #get sample type
  
     #INSERTING ADDED PROFILE BY MANIPULATE FITTED MLE-model
     if(!is.null(addedProfiles)) {
       locs = names(dc$toprankGi) #obtain locus names
       for(loc in locs) {
         if(is.null( contFit$model$refData)) contFit$model$refData = list() #must create list if not exist
         for(comp in names(addedProfiles)) {
           if(is.null( contFit$model$refData[[loc]])) contFit$model$refData[[loc]] = list() #must create list if not exist
           alleles = addedProfiles[[comp]][[loc]]$adata
           contFit$model$refData[[loc]][[comp]] = alleles #insert aleles
         }
       }
       #conditional index to insert
       if(!is.null(contFit$model$condOrder)) {
         contFit$model$condOrder = c(contFit$model$condOrder, max(contFit$model$condOrder)+1)
       } else {
         contFit$model$condOrder = 1
       }
     }
     
     tryCatch({
       makePlotTop(type,contFit,dc,kitname)
      }, error = function(e) print(e))
   } #end if showPlot
   if(!is.null(addedProfiles)) return() #stopfunction if there was added profiles to show in plot (special case)
   
   #INSERTING CANDIDATE DECONVOLED PROFILES:
   ratio <- get("setupThresh",envir=nnTK)$ratio #get ratio-threshold
   probA <- get("setupThresh",envir=nnTK)$probA #get probability of allele - threshold
   
   locs0 <- names(dc$toprankGi) #get loci (from DC)
   contrs = colnames(dc$toprankGi[[1]]) #get contributors
   candtab <- matrix(nrow=0,ncol=2*length(locs0)+4) #list of candidates with genotypes (and probabilities)
   colnames(candtab) <- c(L$Component, L$Conditionals,L$NOC,L$MixProp,locs0,locs0)
   nR = length(refData) #number of conditional refs
   for(cind in 1:length(contrs)) { #for each contributors
     compn <-  contrs[cind] #paste0(evid,"_C",uind) #component name
     addRef = FALSE #Should the profile be added? (Must have at least 1 deduced allele for an unknown component)
     mxhat <- contFit$fit$thetahat2[cind] #get mixture proportion
     newrow <- rep(NA,2*length(locs0))
     for(loc in locs0) { #for each locus 
       insind <- which(locs0==loc) #insert index for genotypes
       insind2 <- length(locs0) + insind #insert index for probabilities (added last)
       if(is.null(dc$toprankGi[[loc]])) next #skip if marker not found
       cand <- dc$toprankGi[[loc]][,cind] #get candidate  
       candRatio = as.numeric(cand[3]) #obtain 'ratio to next' for candidate
       if(!is.na(cand[3]) &&  candRatio<ratio) { #if not a likely genotype
         ind <- which(dc$table4[,1]==compn & dc$table4[,2]==loc)[1] #find top ranked single allele
         candProbA = as.numeric(dc$table4[ind,4]) #get allele prob for candidate
         if( candProbA >= probA ) {
           newrow[insind] <- dc$table4[ind,3] #insert allele if prob>probA
           #newrow[insind2] <- candProbA #insert allele prob
         } 
       } else { #else insert genotype candidate
         newrow[insind] <- cand[1] #insert genotype
       }
       newrow[insind2] <- signif(candRatio,2) #insert ratio, rounded, to marker (always)
       if( cind <= nR && length(refData[[cind]][[loc]]$adata)==0 && !is.na(newrow[insind]) ) addRef  = TRUE #indicate that ref prof. should be added
     } #end for each loci
     if(all(is.na(newrow[1:length(locs0)]))) next #skip if not deduced genotypes (Notice change from v1.8 when adding probabilities)
     if( cind <= nR && !addRef) next #skip if ref should not be added
     if(cind <= nR ) compn = names(refData)[cind] #use ref name instead if conditioned on
     newrow <- c(paste0(evids,"-",compn),condrefs,nC,signif(mxhat,2),newrow)
     candtab <- rbind(candtab, newrow)
   } 
   return(candtab)
  } #end doDC
  
  #helpfunction to change "Unknown" to language specific name
  changeUnknownName = function(x) {
   unknowntxt = "Unknown" #this is default name
   isUnknown=substr(x,1,nchar(unknowntxt))==unknowntxt #recognize positions
   x = gsub(unknowntxt,L$unknown,x) #update vector
   return(x)
  }
  
  #Helpfunction to calc LR (fit quan model for both hyps)
  #REPLICATES NOT SUPPORTED!
  fitEFMHYPs = function(nC,evids,ref,condref=NULL) {
    #Prepare data:
    #popFreq=get("popFreq",envir=nnTK);
    samples <- get("mixDataLIST",envir=nnTK)[evids] #consider lists
    #uselocs <-  names(popFreq)[toupper(names(popFreq))%in%toupper(names(samples[[1]]))] #loci to consider
    #if(is.null(xi)) uselocs <- setdiff(uselocs,"AMEL") #EXCLUDE AMEL IF STUTTER CONSIDERD (QUICK SOLUTION) 
    #samples = lapply(samples,function(x) x[uselocs])
    allrefs = c(ref,condref) #get all refs. POI is first ref
    refData = getRefL(allrefs) # get list of reference data (1-alleles are put as empty)
  
    condhp <- 1:length(allrefs) #conditional order must be increasing order
    condhd <- condhp - 1 #don't condition on POI under Hd
  
    #RUN CALCULATIONS:
    fitMLE = function(condOrder) {
      mlefit <- casesolver::calcQuanMLE(samples,refData,condOrder,nC,nnTK,verbose=TRUE)
      return(mlefit)
    }
    #Calculate under Hp:
    fithp = fitMLE(condhp)
    print("Estimate under Hp:")
    print(prettyNum(fithp$fit$thetahat2))
  
    #Calculate under Hd:
    fithd = fitMLE(condhd)
    print("Estimate under Hd:")
    print(prettyNum(fithd$fit$thetahat2))
    mleLR = (fithp$fit$loglik - fithd$fit$loglik)/log(10) #get estimated log10LR (Quan based)
  
    return(list(fithp=fithp,fithd=fithd,mleLR=mleLR))
  } #end function
  
  #FUNCTION TO SPECIFY HYPOTHESIS AND CALCUALTE SINGLE LR
  createHypLRWindow = function(evids,ref,nC,condRefs=NULL,lrvals=NULL,lrvals2=NULL) {
    Krange = 1:4 #range of number of contributors
    selind = which(nC==Krange)
    if(length(selind)==0) selind = max(Krange)
    selwin <- gWidgets2::gwindow(paste0( L$quanmodel ), visible=TRUE)
    tabSel <- gWidgets2::glayout(container=selwin)
    tabSel[1,1] = gWidgets2::glabel(text= paste0( L$evidence ,colonsymbol) ,container=tabSel)
    tabSel[1,2] = gWidgets2::gcheckboxgroup(items=evids,container=tabSel,checked=TRUE)
    tabSel[2,1] = gWidgets2::glabel(text= paste0( L$POI ,colonsymbol),container=tabSel)
    tabSel[2,2] = gWidgets2::glabel(text=ref,container=tabSel)
    tabSel[3,1] = gWidgets2::glabel(text= paste0( L$numcontr , colonsymbol) ,container=tabSel) 
    tabSel[3,2] = gWidgets2::gcombobox(items=Krange,selected=selind,editable=TRUE,container=tabSel) 
    # gWidgets2::gedit(text=nC,container=tabSel)
    tabSel[4,1] = gWidgets2::glabel(text= paste0( L$condtionON, colonsymbol) ,container=tabSel)
    tabSel[4,2] = gWidgets2::gcheckboxgroup(items=condRefs,container=tabSel,checked=FALSE) #don't select by default
    if(!is.null(lrvals)) { #if lr values given
     tabSel[1,3] = gWidgets2::glabel(text= L$logLR ,container=tabSel)
     tabSel[2,3] = gWidgets2::glabel(lrvals,container=tabSel)
    }
    if(!is.null(lrvals2)) { #if lr values given
     tabSel[4,3] = gWidgets2::glabel(lrvals2,container=tabSel)
    }
    tabSel[5,1] = gWidgets2::gbutton(text= L$calculate ,container=tabSel,handler=function(h,...) {
      nC2 <- as.integer(gWidgets2::svalue(tabSel[3,2])) #get selected number of contributors
      if(nC2>get("setupAdvanced",envir=nnTK)$maxC2) gWidgets2::gmessage( paste( L$msg.morecontrwarning, L$advanced , L$options  ) ,title= L$warning )
    
      condsel <- NULL #conditional references
      if(!is.null(condRefs) && length(condRefs)>0) {
       condsel <- gWidgets2::svalue(tabSel[4,2]) #get selected ref to condition on
      }
      mixsel <-  gWidgets2::svalue(tabSel[1,2]) #get selected samples
      if(length(mixsel)==0) {
        gWidgets2::gmessage( L$msg.selectprofile )
        return()
      }
      gWidgets2::dispose(selwin) #remove window 
      ret = fitEFMHYPs(nC=nC2,evids=mixsel,ref=ref,condref=condsel) 
    
      #user can choose whether to replace results
      txt = paste0( L$msg.calculatedLR ,"\n", L$logLR ,"=",signif(ret$mleLR,digits=4),"\n\n", L$msg.useresult )
      ubool <- gWidgets2::gconfirm(txt,title= L$msg.useresult ,icon="info")
      if(!ubool) return() #return from function 
    
      #STORE MATCH HERE (not in function directly)  
      matchlist0 = get("resCompLR",envir=nnTK)  #get stored results from Qual/Quan comparison (unsorted, but truncated)
      matchlist1 = get("resCompLR1",envir=nnTK)  #get stored qual based results from comparison (sorted wrt QualLR)
      matchlist2 = get("resCompLR2",envir=nnTK)  #get stored quan based results from comparison (sorted wrt QuanLR)
      hpfitlist = get("storedFitHp",envir=nnTK)  #get stored model results under Hp
    
      condREF = FALSE #bool if cond. ref is included
      hasCondREF = FALSE #whether condtional ref columns is in table
      if(!is.null(condsel) && length(condsel)>0) condREF = TRUE #add cond.refs to table?
      if(!is.null(matchlist2) && L$condref%in%colnames(matchlist2)) hasCondREF = TRUE 
      if(!is.null(matchlist2) && condREF && !hasCondREF) { #need to extend the table
        matchlist2 = cbind(matchlist2,"") #add an extra column
        colnames(matchlist2)[ncol(matchlist2)] = L$condref #"condRef" #add name
      } 
       
      #NEED TO REMOVE ALREADY EXISTING COMPARISON AND EXCHANGE WITH NEW RESULTS:
      ind = which(matchlist0[,1]==mixsel & matchlist0[,2]==ref)  #get index in matchlist0 (hp stored in this index)
      if(length(ind)==0) { #NB: this variant was not computet before
        ind = which(matchlist1[,1]==mixsel & matchlist1[,2]==ref)  #get index in matchlist0 (hp NOT stored in this index)
        newrow = matchlist1[ind,]
      } else { #Found
        newrow = matchlist0[ind,-6] #don't include model type
      }
      if(condREF || hasCondREF) newrow = c(newrow,"") #add column if condRef considered OR before
      newrow[4] = signif(ret$mleLR,digits=4) #round
      newrow[5] = nC2 #insert number of contributors
      if(condREF) newrow[6] = paste0(condsel,collapse="/") #show conditionalRefs in table
      if(is.null(matchlist2) && condREF) names(newrow)[6] = L$condref #"condRef" #need to add name
      add = FALSE #should be added to list
      insInd= 1 #give index of inserted row in matchlist2  (also used to fast recognize inserted)
      if(!is.null(matchlist2)) {
        ind2 = which(matchlist2[,1]==mixsel & matchlist2[,2]==ref) #find index in matchlist2 (LR placed in this index)
        if(length(ind2)>0) {
         matchlist2[ind2,] = newrow #insert row
         insInd = ind2 #index of inserted row 
        } else {
         add = TRUE
         insInd = nrow(matchlist2)+1 #added as last row
        }
      } else {
         add = TRUE      
      }
      if(add)   matchlist2 = rbind(matchlist2,newrow) #add to table if not already there
      ord = order(as.numeric(matchlist2[,4]),decreasing=TRUE) #get order of table wrt LR vals
      matchlist2 = matchlist2[ord,,drop=FALSE] #sort table wrt LR values
      assign("resCompLR2",matchlist2,envir=nnTK)  #store sorted matchlist2 
    
      #New in v1.2.1: Update resCompLR object 
      matchlist0[ind,4] <- ret$mleLR
      matchlist0[ind,5] <- nC2 
      matchlist0[ind,6] <- "quan" #update model type
      assign("resCompLR",matchlist0,envir=nnTK)  
    
      #STORE HPFIT RESULTS
      hpfitlist = get("storedFitHp",envir=nnTK)  #get already stored objects
      if(is.null(hpfitlist)) hpfitlist = replicate(nrow(matchlist1),list()) #init. list if first time
      hpfitlist[[ind]] <- ret$fithp  #insert on right index
      assign("storedFitHp",hpfitlist,envir=nnTK)  #store object
    
      #UPDATE TABLES:
      sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types
      refreshTabLIST2(which(ord==insInd),sort=sortTypes[4]) #update tables with results, with marked on selected one
      createMatchlist(modtype=3) #final step is to update MIXTURES table
      refreshTabLIST(evidsel=mixsel,sort=sortTypes[5]) #update match-tables: mark on considered evidence  
    
      gWidgets2::svalue(nb) <- 4 #go to quan LR result tab when done
    }) #end button
  }
  
  #FUNCTION TO SPECIFY HYPOTHESIS AND PERFORMS A SINGLE DC
  createHypDCWindow = function(evids,refs,nC,lrvals=NULL) { 
    Krange = 1:4 #range of number of contributors
    selind = which(nC==Krange)
    if(length(selind)==0) selind = max(Krange)
    selwin <- gWidgets2::gwindow(paste0( L$deconvolution,"/", L$expPHplot ), visible=TRUE)
    tabSel <- gWidgets2::glayout(container=selwin)
    tabSel[1,1] = gWidgets2::glabel(text=paste0( L$evidences ,colonsymbol),container=tabSel)
    tabSel[1,2] = gWidgets2::gcheckboxgroup(items=evids,container=tabSel,checked=TRUE)
    tabSel[2,1] = gWidgets2::glabel(text=paste0( L$numcontr ,colonsymbol),container=tabSel)
    tabSel[2,2] = gWidgets2::gcombobox(items=Krange,selected=selind,editable=TRUE,container=tabSel) 
    # gWidgets2::gedit(text=nC,container=tabSel)
    tabSel[3,1] = gWidgets2::glabel(text=paste0( L$condtionON,colonsymbol),container=tabSel)
    tabSel[3,2] = gWidgets2::gcheckboxgroup(items=refs,container=tabSel,checked=TRUE)
    if(!is.null(lrvals)) { #if lr values given
     tabSel[2,3] = gWidgets2::glabel(text= L$logLR ,container=tabSel) #log10 LR
     tabSel[3,3] = gWidgets2::glabel(lrvals,container=tabSel)
    }
    tabSel[4,1] = gWidgets2::gbutton(text= L$calculate ,container=tabSel,handler=function(h,...) {
      nC2 <- as.integer(gWidgets2::svalue(tabSel[2,2])) #get selected references
      refsel <- NULL #conditional references
      if(length(refs)>0) {
       refsel <- gWidgets2::svalue(tabSel[3,2]) #get selected refs
      }
      mixsel <- gWidgets2::svalue(tabSel[1,2]) #get selected samples
      if(length(mixsel)==0) {
        gWidgets2::gmessage( L$msg.selectprofile )
        return()
      }
      ok = setPopFreq()
      if(!ok) return()
      gWidgets2::dispose(selwin) #remove window
      candtab <- doDC(nC=nC2,evids=mixsel,refs=refsel) #perform DC   
      if(nrow(candtab)>0) { #if more than one new 
       dclist <- get("DClist",envir=nnTK) #get stored DC-list
       dclist <- rbind(dclist,candtab) #add candidates
       assign("DClist",dclist,envir=nnTK) #get stored DC-list  
       refreshDCLIST() #refresh DC-list
       gWidgets2::svalue(nb) <- 5 #go to DC-tab
      }
    }) #end button
  } #end function createHypDCWindow
  
  #Functions executed when double clicked on the Mixture list: 
  #1) Show expected peak heights (given as a plot)
  #2) Show Deconvoluted candidates (added to deconvoluted reference list)
  clickmixlist = function(h,...) {
    id <- as.integer(gsub("#","",gWidgets2::svalue(h$obj)))
    tab <- get("allMixList",envir=nnTK)  #load from envir
    if(is.null(tab)) return() #return if no elements
    evid <- tab[id,1] #get evidence
    refs <- unlist(strsplit(tab[id,2],"/"))  #get refs
    #Get corresponding LR values
    LRtab <- get("resCompLR",envir=nnTK)  #load from envir
    LRtab <- LRtab[LRtab[,1]==evid,,drop=FALSE]
    lrvals <- format(as.numeric(LRtab[match(refs,LRtab[,2]),4]),digits=4)
    nC <- tab[id,3] #get number of contributors (should be editable)
    createHypDCWindow(evid,refs,nC,lrvals) #create window for specify model for DC
  }
  
  #Functions executed when double clicked on the DC list: 
  #2) Show Deconvoluted candidates (added to deconvoluted reference list)
  addDCprofile = function(h,...) {
   DClist <- get("DClist",envir=nnTK)
   if(is.null(DClist)) return() #return if no list found
   suppressWarnings({
     id <- as.integer(gsub("#","",gWidgets2::svalue(h$obj)))
   })
   if(is.na(id)) id <- as.integer(gsub("#","",gWidgets2::svalue(DClistGUI)))
   
   if(length(id)>1) {
   	gWidgets2::gmessage( L$msg.selectoneprofile )
     return()
   }
   answ <- gWidgets2::gconfirm(paste0( L$msg.addDCprofile ,"\n",DClist[id,1]))
   if(answ) { #if extracting DCed candidate
     DCrow = DClist[id,] #obtain DC row to extract
     f_addref(h=list(action=DCrow)) #open edit window of references
  
     #Store extracted DC-result to report object:
     refTab = get("refDataTABLE",envir=nnTK)
     DCtab = rbind(get("DClistReport",envir=nnTK),DCrow) #create DC-tab
     rownames(DCtab)[nrow(DCtab)] = rownames(refTab)[nrow(refTab)] #obtain last extracted ref-name and insert to row
     
     #UPDATING DClistReport object (used for reporting):
     assign("DClistReport",DCtab,envir=nnTK)
     #gWidgets2::svalue(nb) <- 1 #go to data-tab     
   }
  }
  
  #Helpfunction to show LRper marker when clicked
  showLRperMarker = function(h,...) {
    resWOEeval = get("resWOEeval",envir=nnTK) #obtain object
    if(is.null(resWOEeval)) return()
    suppressWarnings({
      ids <- as.integer(gsub("#","",gWidgets2::svalue(h$obj))) #svalue gives name of button if pressed, otherwise its the row in table
    })
    if(is.na(ids)) ids <- as.integer(gsub("#","",gWidgets2::svalue(WOElistGUI)))
    
    s0 = 2 #signif level
    for(id in ids) {
      hypsettxt = paste0(L$lrpermarker,": Hyp. set #",id)
      tab <- cbind(round(resWOEeval[[id]]$mleLRi,s0))  #obtain LR per marker
      colnames(tab) = L$LR
      showGDFtable(hypsettxt, casesolver::addRownameTable(tab,samplename = L$Marker))
    }
  }
  
  #function which takes all matches (with LR>threshold) and create a list to double click on (showing confirming under all conded)
  createMatchlist = function(modtype) { #directly after calculations are done
    #modtype: 0=MAConly(noLR), 1=All Qual LR, 2=All Quan LR, 3=Original Qual LR, but some updated with Quan LR
    threshLR <- get("setupThresh",envir=nnTK)$LRthresh1 #QualLR used by default
    tab <- get("resCompLR1",envir=nnTK) #QualLR used by default
    if(modtype==2)  { 
      threshLR <- get("setupThresh",envir=nnTK)$LRthresh2 #QuanLR used if type 2
      tab <- get("resCompLR2",envir=nnTK)
    }
    if(modtype==0)  { #if only MAC were used
      threshMAC <- get("setupThresh",envir=nnTK)$MACthresh #MAC used if type 0
      tab <- get("resCompMAC",envir=nnTK)$MatchList
      tab <- tab[as.numeric(tab[,3])>=threshMAC,,drop=FALSE] #combinations to consider (all above MAC treshold AND above threshold used in Compare)
    } else { #IF LR was calculated (MAC also stored here)
      score <- as.numeric(tab[,4])
      tab <- tab[score>=log10(threshLR),,drop=FALSE] #combinations to consider (all above LR treshold)
    }
    if(nrow(tab)==0) return()
    if(modtype==3) {
      threshLR2 <- get("setupThresh",envir=nnTK)$LRthresh2 #QualLR used if type 1
      tab2 <- get("resCompLR2",envir=nnTK) #must create a concensus table of Qual/Quan based (using both thresholds)
      if(nrow(tab2)>0) {
       for(rr in 1:nrow(tab2)) { #for each row
         checkind = which( tab[,1]==tab2[rr,1] & tab[,2]==tab2[rr,2]) #find corresponding comparison
         if(length(checkind)==0) {
            if(as.numeric(tab2[rr,4])>=log10(threshLR2)) tab = rbind(tab,tab2[rr,])  #if not found AND it is above threshold, we add it to the list      
         } else {
          	if( as.numeric(tab2[rr,4])<log10(threshLR2)) {
           	 tab = tab[-checkind,,drop=FALSE] #remove from list
         	} else {
             tab[checkind,4:5] = tab2[rr,4:5] #update tab if still keeped
          	}
         }
       } #end for each rr
      } #if any QUAN based LRs
    } #end model type =3
    unEvid <- unique(tab[,1]) #get unique evidence
    unRef <- unique(tab[,2]) #get unique references
    if(length(unEvid)>0) { #if any matches
     resMatches <- numeric() #create match table
     for(evid in unEvid) { #for each evidence we condition on all evidence 
      evidind <- tab[,1]==evid
      refs <- tab[evidind,2] #get references
      if(modtype==0) {
       nC <- sapply(get("mixDataLIST",envir=nnTK)[evid],function(elem) { ceiling(max(sapply(elem,function(x) length(x$adata)))/2) })
      } else {
       nC <- as.numeric(tab[evidind,5][1]) #get number of contributors (equal for all)
      }  
      resMatches <- rbind(resMatches, c(evid,paste0(refs,collapse="/"),nC) )
     }
    } else {
     resMatches =  matrix(nrow=0,ncol=3)
    }
    colnames(resMatches) <- c( L$evidence , L$references , L$numcontr )
    assign("resMatches",resMatches,envir=nnTK) 
  }
  
  #Show matches in a graph:
  #UPDATED IN v1.5.0: Uses plotly to get interactive plot
  f_showMatchNetwork = function(h,...) {
   require(igraph)
  
   createInteractive = FALSE
   if(!is.null(h)) createInteractive = TRUE
   action = "all" #indicate action of plot ("all, onlymix, onlyss)
   if(!is.null(h)) { #IF BUTTON CLICKED: 
     if(h$action=="onlymix") action = "onlymix" #tab = tab[tab[,5]!="1",,drop=FALSE]  # Check if comparing only against Mixture
     if(h$action=="onlyss") action = "onlyss" #tab = tab[tab[,5]=="1",,drop=FALSE]  # Check if comparing only against Mixture
   }
   casesolver::showMatchNetwork(nnTK,action,createInteractive)
   return(TRUE)
  }
  
  ############
  #COMPARISON#
  ####################################
  #STEP 1) CALCULATE MATCHING ALLELES#
  #Function executed when clicking "Comparison"
  getMatchesMAC = function(locs=NULL) { #Compare only alleles (given selection of loci
    DBmix <- get("mixDataTABLE",envir=nnTK) #consider lists
    DBref <- get("refDataTABLE",envir=nnTK) #consider lists
    DBmixmatch <- get("mixDataMATCHSTATUS",envir=nnTK) #consider lists

    #Add evidence profiles as "mixture" OR considered as unknown 
    #ONLY EVALUATE PROFILES WHICH HAS NOT MATCHED A REFERENCE (Mixtures and EMpty)
    indUse = DBmixmatch=="mixture" | DBmixmatch==""  #not L$mixture ?
    #if(get("setupAdvanced",envir=nnTK)$compSS=="TRUE")  indUse = indUse | TRUE # grepl("Unknown ",DBmixmatch) #search only those with matchstatus "Unknown"
    DBmix <- DBmix[indUse,,drop=FALSE] #All evidences must be mixtures OR assigned to unknown
    
    if(!is.null(locs)) {
     keep = toupper(colnames(DBmix))%in%toupper(locs)
     DBmix <- DBmix[,keep,drop=FALSE] #use relevant loci
     DBref <- DBref[,keep,drop=FALSE] #use relevant loci
    }
    
    #Perform the Matching allele counting algorithm-> Output is score for all comparisons
    matchMAC <- calcMACcomparison(DBmix=DBmix,DBref=DBref,threshMAC=get("setupThresh",envir=nnTK)$MACthresh) #calculating the score=normalized number of allele match counting for all combinations
    #  colnames(samplename
    
    #Post-process: Remove candidates that are same profile (early stage): BASEDO ON MATCH STATUS???
    if(!is.null(matchMAC) && nrow(matchMAC$MatchList)>0) { #if any comparison results
     DBmixmatchConsider = DBmixmatch[grepl( L$unknown ,DBmixmatch)] #profiles to consider
     DBmixmatchConsiderEvid = names( DBmixmatchConsider)
     rmind = rep(FALSE,nrow(matchMAC$MatchList)) #indices to remove
     for(i in 1:length(DBmixmatchConsider) ) {
      ind = DBmixmatchConsiderEvid[i] == matchMAC$MatchList[,1] &  DBmixmatchConsider[i] == matchMAC$MatchList[,2] 
      rmind[ind] = TRUE #index to remove 
     }
     matchMAC$MatchList = matchMAC$MatchList[!rmind,,drop=FALSE] #remove matches
    } #end If comparison results
    assign("resCompMAC",matchMAC,envir=nnTK)  #store match-matrix in environment 
  } #end MAC comparison
  
  ############################################
  #STEP 2) CALCULATE LR FOR REMAINING MATCHES#
  getMatchesLR = function(type="quan") { #Calculate LR for individuals in MatchList 
    #type={"qual","quan"} 
    Clist <- get("resCompMAC",envir=nnTK)$MatchList  #list to consider for calculating LR
    
    if(type=="quan" && !is.null(get("resCompLR1",envir=nnTK)) ) {
     Clist <- get("resCompLR1",envir=nnTK)  #list to consider for calculating LR (based on qualLR)
     Clist <- Clist[as.numeric(Clist[,4])>=log10(get("setupThresh",envir=nnTK)$LRthresh1),,drop=FALSE] #keep only variants above thrshold AND COLUMNS in MAC
    }
    DBmix <- get("mixDataLIST",envir=nnTK)[unique(Clist[,1])] #get relevant evidence
    DBref <- get("refDataTABLE",envir=nnTK)
    DBref = DBref[rownames(DBref)%in%unique(Clist[,2]),,drop=FALSE] #get only relevant references
    
    mod <- casesolver::getModelSettings(nnTK)  #object for model settings
    
    #matchlist=Clist;popFreq=mod$popFreq;pC=mod$pC; maxC=get("setupAdvanced",envir=nnTK)$maxC1;useMinK1=as.logical(get("setupAdvanced",envir=nnTK)$useMinK1);normalize=mod$normalize;minFreq=mod$minFreq
    suppressWarnings({
     if(type=="qual")  matchLRres <- casesolver::calcQualLRcomparison(DBmix,DBref,matchlist=Clist,popFreq=mod$popFreq,pC=mod$pC, maxC=get("setupAdvanced",envir=nnTK)$maxC1,useMinK1=as.logical(get("setupAdvanced",envir=nnTK)$useMinK1),normalize=mod$normalize,minFreq=mod$minFreq, useMAC=as.logical(get("setupAdvanced",envir=nnTK)$useMAC))
     if(type=="quan") {
        nContr = NULL #Number of contributors to use (default is the max(nA)/2 rule)
        if(ncol(Clist)==5) nContr = Clist[,5] #number of contributors given in last column if qualLR calculated
    
        #use "Rule of three" for EFM model when applied to SNPs
        if(!is.null(get("setupAdvanced",envir=nnTK)$isSNP) && get("setupAdvanced",envir=nnTK)$isSNP=="TRUE")  nContr = rep("3",nrow(Clist))
        useEFMex = get("setupAdvanced",envir=nnTK)$useEFMex=="TRUE"
    #matchlist=Clist[,1:3,drop=FALSE];popFreq=mod$popFreq;kit=mod$kit;xiBW=mod$xiBW;xiFW=mod$xiFW;pC=mod$pC;lambda=mod$lambda;threshT=mod$threshT;nDone=mod$nDone;maxC=get("setupAdvanced",envir=nnTK)$maxC2;normalize=mod$normalize;minFreq=mod$minFreq
        matchLRres <- calcQuanLRcomparison(DBmix,DBref,matchlist=Clist[,1:3,drop=FALSE],popFreq=mod$popFreq,kit=mod$kit,xiBW=mod$xiBW,xiFW=mod$xiFW,pC=mod$pC,lambda=mod$lambda,threshT=mod$threshT,nDone=mod$nDone,maxC=get("setupAdvanced",envir=nnTK)$maxC2,nContr=nContr, normalize=mod$normalize,minFreq=mod$minFreq,useEFMex=useEFMex) 
     }
    })
    matchlist <- matchLRres$MatchList
    matchlist2 = cbind(matchlist,type) #Added in v1.2.1
    assign("resCompLR",matchlist2,envir=nnTK)  #store results from comparison
    
    if(type=="qual") {
      #sort the matchlist with respect to the LRs:  
      LRcol <- which(colnames(matchlist)=="log10LR") #get column where LR is
      LRval <- as.numeric(matchlist[,LRcol])
      ord <- order( LRval,decreasing=TRUE)
      matchlist[,LRcol] <- round(LRval,2) #round to 2 dec
      #matchlist[ord,] #sort list by LR
      assign("resCompLR1", matchlist[ord,,drop=FALSE],envir=nnTK)  #store sorted matchlist 
    }
    if(type=="quan") {
      assign("storedFitHp",matchLRres$storedFitHp,envir=nnTK)  #store model results under Hp
      
      #sort the matchlist with respect to the LRs:  
      LRcol <- which(colnames(matchlist)=="log10LR") #get column where LR is
      LRval <- as.numeric(matchlist[,LRcol])
      ord <- order( LRval,decreasing=TRUE)
      matchlist[,LRcol] <- round(LRval,2) #round to 2 dec
      #matchlist[ord,] #sort list by LR
      assign("resCompLR2", matchlist[ord,,drop=FALSE],envir=nnTK)  #store sorted matchlist 
    }
  } #end LR comparison
  
  
  #Function giving window for editing alleles for new references (returns ref-name)
  f_addref = function(h,...) { 
    refT <- get("refDataTABLE",envir=nnTK)
    refTNames = rownames(refT)
    if(nrow(refT)>0) {
     locs <- colnames(refT) #get loci names from ref-table
    } else {
     locs <- colnames(get("mixDataTABLE",envir=nnTK)) #get loci names from mix-table (in case of no refs)
    }
    refind = 1:nrow(refT) #index of refs to consider (may be empty also)
    if( length(refTNames)>=nLarge) { #the user must give a segment of refs
      ret = gWidgets2::ginput( L$msg.indexinput , text = "1-10", title = "User input", icon = "info")
      ret = unlist(strsplit(ret,","))
      refind = numeric()
      for(rng in ret) {
       tmp = as.integer(unlist(strsplit(rng,"-")))
       if(length(tmp)==1) refind = c(refind , tmp)
       if(length(tmp)==2) refind = c(refind , tmp[1]:tmp[2])
      }
      refind = refind[refind>=1 & refind<=nrow(refT) ]  #require valid range
      refT <- refT[refind,,drop=FALSE]
    }
    def <- "A/B" #default genotype
    defN <- L$name #default name
    refN <- rownames(refT) #refnames
    newTab <- cbind(refN,refT)
    colnames(newTab)[1] <- L$samplename
    
    newline <- c(defN,rep(def,length(locs)))
    if(!is.null(h$action)) { #opened with deconvolution
      tmp <- h$action #get sample name
      newline[1] <- tmp[1] #get sample name (component)
      dat <- tmp[5:length(tmp)] #get suggested deconvolved elem
      newline[-1] <- dat[match(locs,names(dat))] #obtain correct order (notice that only 1st match element is used)
      newline[is.na(newline)] <- ""
    }
    newTab <- rbind(newTab,newline) #add empty/new row
    
    #CREATE GUI WINDOW (OTHER PROCESS WILL STOP)
    flag <- tcltk::tclVar("") #init flag to avoid quitting GUI
    setwin <- gWidgets2::gwindow(paste0( L$data.editrefs ),visible=FALSE) 
    gWidgets2::addHandlerUnrealize( setwin, handler = function(h,...) { #
      tcltk::tclvalue(flag) <- "destroy" #Destroy wait flag
      return(NULL) #return selected profiles when window is exit 
    }  ) #call quit function
    
    tabval = gWidgets2::ggroup(spacing=0,container=(setwin),horizontal=FALSE)  
    guitab <- gWidgets2::gdf(items=newTab,container = tabval) 
    gWidgets2::add(tabval,guitab,expand=TRUE,fill=TRUE) 
    
    gWidgets2::gbutton(text= L$save ,spacing=0,container=tabval,handler = function(h, ...) { 
      if(nrow(refT)==0) {
        newref <- t(as.character(unlist(guitab[])))
      } else {
        newref <- as.matrix(guitab[])
      }
      nL <- nrow(newref) #rowindex of new ref
      addRef <- newref[nL,] #reference to add
      newref = newref[-nL,,drop=FALSE] #keep only tab without added ref
      delindsOld <- newref[,1]=="" #index of all refs to delete (When names are set to "")
    
      if(any(delindsOld)) { #if deleting previous stored refs
       answ <- gWidgets2::gconfirm(paste0( L$msg.suredelete ,":\n",paste0(refN[delindsOld],collapse="/"),"?"))
       if(answ) { #if agree then refs are deleted
        refT <- refT[!delindsOld,,drop=FALSE] #update ref-table
        newref = newref[!delindsOld,,drop=FALSE] #BUG fixed in v1.4.0
        refN = refN[!delindsOld]
       }
      } 
    
      #CHECK FOR CHANGES (not added ref)
      if(nrow(refT)>0) { #must have at least one ref
       isChanged = which(refT != newref[,-1],arr.ind=TRUE)
       if(length(isChanged)>0) {
        text = paste0(refN[isChanged[,1]]," (",colnames(refT)[isChanged[,2]],")")
        answ <- gWidgets2::gconfirm(paste0( L$msg.sureapplychanges ,":\n",paste0(text,collapse="/"),"?"))
        if(answ) { #apply changes:
         refT <- newref[,-1,drop=FALSE]  #update ref-table
         rownames(refT) = refN  #add rownames
        } else {
         newref[,-1] = refT #replace with prev
        }
       }
      }
      sn = addRef[1]
      Anew2 = NULL
      if(!sn%in%c("",defN)) { #only include ref if a new sample name were given
       Anew <- addRef[-1] #new alleles
       Anew[Anew==def] <- "" #Defaults are set as empty
       if(sn%in%refTNames) {
        gWidgets2::gmessage( L$msg.refnametaken )
       } else {
         if( any(Anew!="")) Anew2 = Anew
       }
      } #end if insert ref
    
      #In case the user gave a segment of refs
      if( length(refTNames)>=nLarge) {
         refT2 = get("refDataTABLE",envir=nnTK) #get full table 
         if(length(isChanged)>0) { #if anything was changed
          refT2[refind[!delindsOld],] = refT
         }
         if(any(delindsOld)) { #if any deleted
           refT2 = refT2[-refind[delindsOld],,drop=FALSE] #indices to be removed
         } 
         refT = refT2 #update
         rm(refT2);gc()
      } #end selected segment
    
      #Add to table if something to add:
      if(!is.null(Anew2)) {
       refT <- rbind(refT,Anew2) #add to existing table
       rownames(refT)[nrow(refT)] <- sn
       
       
      }    
      assign("refDataTABLE",refT,envir=nnTK) #store table 
      gWidgets2::dispose(setwin) #close window
      tcltk::tclvalue(flag) <- "destroy" #Destroy wait flag
      
      sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types
      updateTables(type="ref",sort=sortTypes[2]) #updates tables again (with same sorting)
    }) #end button
    gWidgets2::visible(setwin) <- TRUE
    tcltk::tkwait.variable(flag) #important to not quit window before broken
  }  #end add ref
  
  #FUNCTION TO STORE TABLE:
  f_exporttable = function(h,...) { 
    tab <- NULL
    if(h$action=="mac")    tab <- casesolver::addRownameTable(get("resCompMAC",envir=nnTK)$MatchMatrix,type=1,L$samplename)
    if(h$action=="qual")   tab <- get("resCompLR1",envir=nnTK)
    if(h$action=="quan")   tab <- get("resCompLR2",envir=nnTK)
    if(h$action=="final")  tab <- get("allMixList",envir=nnTK)
    if(h$action=="dc")     tab <- get("DClist",envir=nnTK)
    if(h$action=="woe")    tab <-  get("resWOEeval",envir=nnTK)$resTable
    saveTable(tab,"csv")
  }
  
  #Function to deconvolve for all mixtures (conditions on matching references)
  f_doDCall = function(h,...) {
    mixList <- get("allMixList",envir=nnTK) #get match list (from function)
    if(is.null(mixList)) return() #return if no list found
    nS = nrow(mixList) #get number of mixtures 
    if(nS==0) return()
    candtabs = numeric() 
    for(ss in 1:nS) {
      evid = mixList[ss,1]
      refs = unlist(strsplit(mixList[ss,2],"/"))
      if(length(refs)==0) refs = NULL 
      nC = as.integer(mixList[ss,3])
    
      #UPDATED v1.4.1 to fix possible crash.
      if(nC<=length(refs)) {
       print(paste0("No unknowns to deconvolve for sample ",evid)) 
      } else {
       print(paste0("Deconvolving sample #",ss,": ",evid)) 
       candtab <- doDC(nC,evid,refs,showPlot=FALSE,useplotly=FALSE)
       candtabs = rbind(candtabs,candtab) #add candidate table
       print("")
       print(paste0(round(ss/nS* 100), "% DC calculation complete...")) 
      } 
    }
    if(length(candtabs)>0) { #if more than one new 
     dclist <- get("DClist",envir=nnTK) #get stored DC-list
     dclist <- rbind(dclist,candtabs) #add candidates
     assign("DClist",dclist,envir=nnTK) #get stored DC-list  
     refreshDCLIST() #refresh DC-list
     gWidgets2::svalue(nb) <- 6 #go to DC-tab after calculation
    }
  } #end f_doDCall
  
  #Function to do WOE as a final step from matchlist
  f_doWOEcall = function(h,...) {
   
   #CHECK AND SET FREQUENCY FILE BEFORE
   ok = setPopFreq(giveMessage=TRUE) #import population frequency from last selected file
   if(!ok) return() #retun from function if not frequencies are set.
  
   #perform WOE calculation (returns from function when closed/finished)
   calcWOEhyps(nnTK) 
   #Update with WoE table when done evaluated
   #length( get("resWOEeval",envir=nnTK) )
   resList = get("resWOEeval",envir=nnTK) #obtain results
   #object.size(resWOEeval)/1e6 #size of object
   if(length(resList)==0 || !is.null(resList$resTable)) return(NULL) #return if no elements
   extractrow = function(x) {
     s0 = 2
     evidtxt = paste0(x$evid,collapse="/")
     condtxt = paste0(x$cond ,collapse="/")
     validtxt = paste0(x$nFailedHp,"/",x$nFailedHd)
     c(evidtxt,x$poi,condtxt,x$NOC,round(x$mleLR,s0),round(x$bayesLR,s0),round(x$consLR,s0),round(x$MxPOI,s0),validtxt)
   }
   resTable = t(sapply(resList,  extractrow))
   colnames(resTable) = c(L$evidences, L$POI, L$Conditionals, L$NOC, L$LRmle, L$LRbayes, L$LRcons, L$MxPOI, L$nFailed)
   resList$resTable =resTable #insert table
   
   print("Done with Weight-of-evidence calculations!")
   assign("resWOEeval",resList,envir=nnTK) #obtain results
   refreshWOELIST()
   gWidgets2::svalue(nb) <- 7  #change panel
   setFocus() #refocus
  }
  
  
  ##################################################################################################
  ########### Program starts #######################################################################
  ##################################################################################################
  
  
  #SELECT LANGUAGE (before anything else sat)
  L = casesolver::getLanguage( get("setupLanguage",envir=nnTK)$language ) #, get("setupLanguage",envir=nnTK)$encoding ) #get list of words from selected language
  
  #software name:
  softname <- paste("CaseSolver",L$version,version)
  
  #DEFINE REPORT ITEMS BASED ON LANGUAGE:
  reportitems = rep(NA,nReportItems)
  reportitems[1] = L$header #"Header"
  reportitems[2] = L$references  #"References"
  reportitems[3] = L$extractedprofiles #Extracted profiles"
  reportitems[4] = paste0( L$singlesources ," (", L$alleles,")")  #"Single sources (alleles)"
  reportitems[5] = paste0( L$mixtures ," (", L$alleles,")") #"Mixtures (alleles)"
  reportitems[6] = paste0( L$consensusprofiles ," (", L$alleles,")") #"Consensus (alleles)"
  reportitems[7] = paste( L$singlesources , L$withPH ) #"Single sources w/PH"
  reportitems[8] = paste( L$mixtures , L$withPH ) #"Mixtures w/PH"
  reportitems[9] = L$metadata  # "Metadata"
  
  #Comparisons:
  reportitems[10] = L$matchmatrix #"Match matrix"
  reportitems[11] = paste0( L$matchlist ," (", L$qualLR,")")  #"MatchList (Qual)"
  reportitems[12] = paste0( L$matchlist ," (", L$quanLR,")")  #"MatchList (Quan)"
  reportitems[13] = paste( L$finalmatchlist )  #"FinalMatchList"
  reportitems[14] = paste( L$matchnetwork )  #""MatchNetwork"
  reportitems[15] = paste0( L$RMNE ," (", L$evidence,")" ) #"RMNE for evidence" 
  reportitems[16] = paste0( L$RMP ," (", L$reference,")" ) #"RMP for references"
  reportitems[17] = paste( L$concordantevidences ) #"Concordant Evidences"
  reportitems[18] = paste0( L$IBS ," (", L$reference,")" ) #"IBS for references"
  
  #Quantifications:
  reportitems[19] = L$deconvoluted #Deconvoluted
  reportitems[20] = L$woeResult #WoE table
  reportitems[21] = L$woeStatements #Statements
  reportitems[22] = L$woeParams #Estimated model parameters (listed per hypothesis)
  reportitems[23] = L$lrpermarker #LR per marker (woe)
  
  #attachments:
  reportitems[24] = L$settings #"Settings"
  reportitems[25] = paste0(  L$EPG, " (", L$singlesources ,")") #"EPG figures for single sources"
  reportitems[26] = paste0(  L$EPG, " (", L$mixtures ,")") # "EPG figures for mixtures"
  #reportitems[25] = L$expPHplot #"Expected PH plots"
  if(length(reportitems)!=nReportItems) stop("Number of report items were wrong.")
  
  #storing report item names to be used in report:
  optReport <- get("setupReportLay",envir=nnTK)  #get report options
  optReport$reportitems = reportitems #store name of reportnames
  assign("setupReportLay",optReport,envir=nnTK) #store back to environment
  
  #Get ON-OFF choices (used in f_createreport and f_modelsel)
  radiotxt = c( L$on , L$off )
  
  ###############
  #start layout:#
  ###############
  mblst = list() 
  mblst[[ L$file ]] = list(  
   gWidgets2::gaction( paste( L$set , L$workdir ) ,handler=f_setwd),
   gWidgets2::gaction( paste( L$open , L$proj ) ,handler=f_openproj),
   gWidgets2::gaction( paste( L$save , L$proj ) ,handler=f_saveproj),
   gWidgets2::gaction( L$quit ,handler=f_quitproj,icon="close")
  )
  mblst[[ L$setup ]] =list( 
   gWidgets2::gaction( paste( L$set , L$threshsettings ) ,handler=f_threshsel),
   gWidgets2::gaction( paste( L$set , L$modelsettings )  ,handler=f_modelsel),
   gWidgets2::gaction( paste( L$select ,L$kit) ,handler=f_kitsel),
   gWidgets2::gaction( paste( L$select ,L$popfreq) ,handler=f_popsel),
   gWidgets2::gaction( paste( L$select , L$importfun) ,handler=f_importsel),
   gWidgets2::gaction( paste( L$select , L$pathcasefolders ) ,handler=f_casedirsel)
  )
   mblst[[ L$report ]] =list( 
   gWidgets2::gaction( paste( L$set , L$reportlayout ) ,handler=f_reportlay),
   gWidgets2::gaction( paste( L$set , L$report, L$options) ,handler=f_reportopt),
   gWidgets2::gaction( paste( L$set , L$report, L$export, "Types" ) ,handler=f_reportexptyp),
   gWidgets2::gaction( paste( L$set , L$report, L$export, L$options) ,handler=f_reportexpopt),
   gWidgets2::gaction( paste( L$set , L$Markernames) ,handler=f_reportlocnames)
  )
  mblst[[ L$advanced ]] = list( 
   gWidgets2::gaction( paste( L$advanced , L$options ) ,handler= f_advancedoptions),
   gWidgets2::gaction( paste( L$mcmc , L$options ) ,handler= f_mcmcoptions),
   gWidgets2::gaction( L$randomibs ,handler=f_calcIBSdist), #calculates random IBS
   gWidgets2::gaction( paste( L$select , L$language ) ,handler=f_selLanguage) #select language
  )
  
  
  #change working directory to the one stored in nnTK-environment
  wd=get("workdir",envir=nnTK) #assign working directory to nnTK-environment
  if(!is.null(wd)) {
  tryCatch( { setwd(wd) }, error = function(e) print("Warning: Workdirectory could not be changed!") )
  }
  
  #############
  #Main window#
  #############
  mainwin <- gWidgets2::gwindow(softname, visible=FALSE)#, width=mwW,height=mwH)
  gWidgets2::addHandlerUnrealize( mainwin, handler = function(h,...) { return( !gWidgets2::gconfirm( L$msg.quit ) )}  ) #call quit function
  
  gWidgets2::gmenu(mblst,container=mainwin)
  nb = gWidgets2::gnotebook(container=mainwin)
  tabimport = gWidgets2::ggroup(horizontal=FALSE,spacing=spc/2,container=nb,label= L$data ) #tab2: (imports all files)
  tabmatchmatrix = gWidgets2::ggroup(horizontal=FALSE,spacing=spc/2,container=nb,label= paste( L$matchmatrix ) ) #comparison results
  tabmatchlist1 = gWidgets2::ggroup(horizontal=FALSE,spacing=spc/2,container=nb,label= paste0( L$matchlist," (", L$qualLR,")" )) #results from Qualitative model (LRmix)
  tabmatchlist2 = gWidgets2::ggroup(horizontal=FALSE,spacing=spc/2,container=nb,label= paste0( L$matchlist," (", L$quanLR,")" )) #results from Quantitative model (EFM)
  tabmixtures = gWidgets2::ggroup(horizontal=FALSE,spacing=spc/2,container=nb,label= L$matches ) #comparison results (collapsed)
  tabdeconv = gWidgets2::ggroup(horizontal=FALSE,spacing=spc/2,container=nb,label= L$deconvoluted ) #Deconvolution results
  tabWOE = gWidgets2::ggroup(horizontal=FALSE,spacing=spc/2,container=nb,label= L$woe ) #WoE results\
  
  ####################################################
  ###############Tab 1: Import Data:##################
  ####################################################
  
  #TAB layout
  layhor0 = as.logical(get("setupView",envir=nnTK)$importHorizontal) #get configured layout of tables
  tabimportA = gWidgets2::glayout(spacing=5,container=gWidgets2::gframe( paste( L$select , L$caseid ) ,container=tabimport)) #kit and population selecter
  tabimportC = gWidgets2::glayout(spacing=5,container=gWidgets2::gframe( L$functionalities ,container=tabimport)) #Tasks button
  tabimportB = gWidgets2::gpanedgroup(horizontal=layhor0,container=gWidgets2::gframe( paste0( L$data.evidref ),container=tabimport,expand=TRUE,fill=TRUE),expand=TRUE,fill=TRUE) #evidence,ref dataframe
  
  txtEmptycasedir = paste( L$msg.emptycasedir, L$setup, ">", L$set , L$pathcasefolders ) #create a error message for not finding case folders
  #Choose box and import button
  casedir <-  get("setupCase",envir=nnTK)$casepath
  if(is.na(casedir) || casedir=="") gWidgets2::gmessage( txtEmptycasedir )
  casefolds <- list.dirs(casedir,recursive=FALSE, full.names = TRUE)  #keep full path
  casefolds2 <- list.dirs(casedir,recursive=FALSE, full.names = FALSE)  #extract only folder CHanged in v1.7
  
  caseid <- get("caseID",envir=nnTK) 
  if(is.null(caseid)) {
    caseid <- 0 #set a default index
  } else {
    caseid <- which(casefolds2==caseid) #must be index
  }
  tabimportA[1,1] = gWidgets2::gbutton(text= L$changeview ,container=tabimportA,handler=function(h,...) { #CHANGE VIEW
    opt = get("setupView",envir=nnTK) #get options
    if(layhor0) {
      opt$importHorizontal = "FALSE"
    } else {
      opt$importHorizontal = "TRUE"
    }
    assign("setupView",opt,envir=nnTK)  #store to environment
    setupWrite(unlist(opt),file=setupFileView)    #save to file in installation folder
    gWidgets2::dispose(mainwin) #shut down window
    #gc() #empty garbage memory
    gui(envir=nnTK) #restart GUI session with project environment
  })
  
  #BUTTON FOR IMPORTING DATA (calls f_importData)
  if( length(casefolds2)>0 && length(caseid)>0  ) {#v1.4.1: ADDED if to make possible to exchange proj files
    tabimportA[1,2] <- gWidgets2::gcombobox(items=casefolds2, selected = caseid  , editable = TRUE, container = tabimportA) 
    tabimportA[1,3] <- gWidgets2::gbutton(text= L$import ,container=tabimportA,handler=f_importData) #IMPORT FUNCTION!!!
    gWidgets2::tooltip(tabimportA[1,3]) <- L$tip.data.import #add tooltip only if button is visible
  }
  
  mixTabGUI <- gWidgets2::gtable(items="",multiple = TRUE,container = tabimportB, handler=clicktable,action="mix")
  refTabGUI <- gWidgets2::gtable(items="",multiple = TRUE,container = tabimportB, handler=clicktable,action="ref")
  #gWidgets2::add(tabimportB,mixTabGUI,expand=TRUE,fill=TRUE)
  #gWidgets2::add(tabimportB,refTabGUI,expand=TRUE,fill=TRUE)
  gWidgets2::svalue(tabimportB) = 0.5 #set as 50-50 by default
  
  #TABLE SORTING
  sortstring1 <- paste( L$data.sortevid, c("#", L$name , L$matchstatus )) #EVID
  tabimportA[1,4] = gWidgets2::gcombobox(items=sortstring1,selected=1,container=tabimportA,horizontal = TRUE, handler=
  function(h,...) { 
   sortval = which(sortstring1== gWidgets2::svalue(tabimportA[1,4])) #sort value
   resave_Sorting(1,sortval) #resaving to setupSorting object
   updateTables(sort=sortval,type=h$action) 
  },action="mix")
  sortstring2 <-  paste( L$data.sortref, c("#", L$name )) #REFERENCE
  tabimportA[1,5] = gWidgets2::gcombobox(items=sortstring2,selected=1,container=tabimportA,horizontal = TRUE, handler=
  function(h,...) { 
   sortval = which(sortstring2== gWidgets2::svalue(tabimportA[1,5]))
   resave_Sorting(2,sortval) #resaving to setupSorting object
   updateTables(sort=sortval,type=h$action) 
  },action="ref")
  
  #UPDATE IN v1.5: Possible to add references afterwards
  tabimportA[1,6] <- gWidgets2::gbutton(text= L$importref ,container=tabimportA,handler = function(h, ...) { #IMPORT REFS
    ff <- mygfile( paste( L$select , L$file) ,type="open")
    if(length(ff)==0) return()
    tab = euroformix::tableReader(ff) #read table and insert to GUI format
    
    #Borrowing code from euroformix::efm L977 (import reference-databases)
    cn = colnames(tab) #colnames 
    lind = grep("marker",tolower(cn),fixed=TRUE) #locus col-ind
    if(length(lind)==0) lind = grep("locus",tolower(cn),fixed=TRUE) #locus col-ind
    sind = grep("sample",tolower(cn),fixed=TRUE)[1] #sample col-ind
    aind = grep("allele",tolower(cn),fixed=TRUE)[1:2] #allele col-ind
    
    sn = unique(tab[,sind]) 
    locs = toupper(unique(tab[,lind]))
    if(length(sn)==0) return()
  
    refT <- get("refDataTABLE",envir=nnTK) #store table 
    cn = toupper(colnames(refT))
    if(length(cn)==0) return()
    newsn = c(rownames(refT),sn)
    for(ss in sn) { #for each sample
      newT = rep("",length(cn)) 
      for(loc in locs) { #for each loci
        indins = which( cn==loc )
        av = unlist(tab[tab[,sind]==ss & toupper(tab[,lind])==loc, aind])
        av = av[av!=""] #ignore empty
        if(length(av)==0) next #skip if not found
      	#if(length(av)==1) av = rep(av,2)
      	if(length(av)==2) av = paste0(av,collapse="/")
        newT[indins] <- av  #factor(sn, levels= c(sn,levels(guitab[nR,1]) ))#insert name
      }
      refT = rbind(refT,newT) #add profiles  
    }
    rownames(refT) = newsn 
    assign("refDataTABLE",refT,envir=nnTK) #store table 
    
    sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types
    updateTables(type="ref",sort=sortTypes[2]) #updates ref-table again 
  })
  
  tabimportC[1,1] = gWidgets2::gbutton(text= L$compare ,container=tabimportC,handler= #COMPARE FUNCTION
  function(h,...) {
  
  refDataTABLE =  get("refDataTABLE",envir=nnTK)
  if(is.null(refDataTABLE) || nrow(refDataTABLE)==0) return() #return if no refs
  
  #Reset all earlier comparison-results (since method may have changed):
  print("Resetting all previous comparison-results...")
  assign("resCompMAC",NULL,envir=nnTK);assign("resCompLR1",NULL,envir=nnTK);assign("resCompLR2",NULL,envir=nnTK)  
  assign("resCompLR",NULL,envir=nnTK);assign("resMatches",NULL,envir=nnTK);assign("allMixList",NULL,envir=nnTK) 
  suppressWarnings({
   matchL1GUI[] = NULL #Set to zero if anything
   matchL2GUI[] = NULL #Set to zero if anything
  })
  
  #CHECK AND SET FREQUENCY FILE
  ok = setPopFreq(giveMessage=TRUE) #import population frequency from last selected file
  if(ok) {
   locsUse = names(get("popFreq",envir=nnTK)) #use markers in freq table if found
  } else {
   locsUse = colnames(get("mixDataTABLE",envir=nnTK)) #otherwise use loci from evid data
  }
  print(paste0(length(locsUse)," loci used in COMPARISON:"))
  print(paste0(locsUse,collapse="/")) #Print to console which loci are used
  
  #Step 1: Calculate MAC
  res <- getMatchesMAC(locs=locsUse)  #get name of loci to consider
  if(is.null(res)) return(); #return if nothing to compare.
  refreshTabMATRIX() #update tables
  gWidgets2::svalue(nb) <- 2 #go to comparison tab
  
  #CALCULATING LR BASED SCORES:
  if(nrow(res$MatchList)==0) return() #Return if no candidates to calculate
  modtype <- get("setupModel",envir=nnTK)$modeltype #model type selected {1="qual",2="quan",3="both"} #Otherwise only MAC based
  if(!ok) modtype = 0 # return() #show MAC results if LR can't be calculated
  
  sortTypes = get("setupSorting",envir=nnTK) #Obtain sort types
  #Step 2 (optional): Calculate qual based LR
  if( modtype%in%c(1,3) ) {
   getMatchesLR(type="qual") #LRmix
   refreshTabLIST1(sort=sortTypes[3]) #update table with results
   gWidgets2::svalue(nb) <- 3 #go to qual LR result tab when done
  }
  
  #Step 3 (optional): Calculate quan based LR
  if( modtype%in%c(2,3) ) {
   if( get("setupModel",envir=nnTK)$degrad==1 && !casesolver::canPrintEPG(nnTK) ) { #If degradation model chosen but kit not selected
    gWidgets2::gmessage( paste( L$msg.kitspecify, L$settings ,">", L$select ,L$kit) )
    return()
   } 
   getMatchesLR(type="quan") #EFM based
   refreshTabLIST2(sort=sortTypes[4]) #update tables with results
   gWidgets2::svalue(nb) <- 4 #go to quan LR result tab when done
  }
  
  #Step 3: Create matchlist (Final)
  createMatchlist(modtype=modtype) 
  refreshTabLIST(sort=sortTypes[5]) #update tables  
  gWidgets2::svalue(nb) <- 5 #go to overview when done
  
  })
  tabimportC[1,2] = gWidgets2::gbutton(text= paste( L$create , L$report) ,container=tabimportC,handler=function(h,...) {
   casesolver::createReport(nnTK) #creating report (separate R-script)
  })
  
  tabimportC[1,3] = gWidgets2::gbutton(text= L$data.select ,container=tabimportC,handler=f_markprofs)
  tabimportC[1,4] = gWidgets2::gbutton(text= paste( L$calculate , L$IBS ) ,container=tabimportC,handler=f_calcIBS)
  tabimportC[1,5] = gWidgets2::gbutton(text= paste( L$calculate , L$RMP ),container=tabimportC,handler=f_calcRMP)
  tabimportC[1,6] = gWidgets2::gbutton(text= L$data.concordance ,container=tabimportC,handler=f_calcEvidConc)
  tabimportC[1,7] = gWidgets2::gbutton(text= L$data.editrefs ,container=tabimportC,handler=f_addref)
  tabimportC[1,8] = gWidgets2::gbutton(text= L$restart ,container=tabimportC,handler=
  function(h,...) {
   gWidgets2::dispose(mainwin) #shut down window
   gui() #start an empty session (recognized)
  })
  
  
  #INSERT DATA (TABLE-FORMAT) TO GUI: NOTICE the clicktable handler 
  updateTables <- function(sort=1,type="both") { #function to call to update tables (possibly changed order)
   gWidgets2::visible(mainwin) = FALSE
   
   mixTab <- refTab <- "" #empty tables by default
   if(type%in%c("both","mix")) {    #Add mix-table
    mixDataTABLE <- get("mixDataTABLE",envir=nnTK) #assigned in nnTK-environment
    if( !is.null(mixDataTABLE) && nrow(mixDataTABLE)>0 ) { #make sure that there are data in table
     mixDataMATCHSTATUS <- get("mixDataMATCHSTATUS",envir=nnTK) #assign to nnTK-environment 
  
     #SORT TABLE:     
     ord = casesolver::orderTableSort(rownames(mixDataTABLE),mixDataMATCHSTATUS,sort)
     
     newtab <- cbind(mixDataMATCHSTATUS,mixDataTABLE)
     mixTab <- casesolver::addRownameTable(newtab,type=2,L$samplename)
     colnames(mixTab)[1:3] <- c(" ", L$samplename,L$matchstatus) #insert column name for table
     mixTab[mixTab[,3]=="mixture",3] = L$mixture #insert name: BEWARE THAT SAMPLENAMES SHOULD NOT CONTAIN "mixture"
  
     mixTabGUI[] <- mixTab[ord,,drop=FALSE] #update order in GUI table
     if(!layhor0 && !is.null(ncol(mixTab)) && nrow(mixTab)<nLarge ) { #if vertical layout and less than nlarge rows
      colw1 = c(30,150,150)
      colL = 100 #column width for each locus
      gWidgets2::size(mixTabGUI) <- list(column.widths=c(colw1,rep(colL,ncol(mixTab)-length(colw1))))
     }
    }
   } 
   if(type%in%c("both","ref")) {    #Add ref-table
    refDataTABLE <- get("refDataTABLE",envir=nnTK) #assign to nnTK-environment
    if(!is.null(refDataTABLE) && nrow(refDataTABLE)>0 ) { #make sure that there are data in table
      
     #SORT TABLE:     
     ord = casesolver::orderTableSort(rownames(refDataTABLE),sort=sort)
      
     refTab <- casesolver::addRownameTable(refDataTABLE,type=2,L$samplename)
     refTabGUI[] <- refTab[ord,,drop=FALSE]
  
     if(!layhor0 && !is.null(ncol(refTab)) && nrow(refTab)<nLarge ) { #if vertical layout and less than nlarge rows
      colw1 = c(30,150,150)
      colw2 = c(colw1[1],sum(colw1[-1]))
      colL = 100 #column widt for each locus
      gWidgets2::size(refTabGUI) <- list(column.widths=c(colw2,rep(colL,ncol(refTab)-length(colw2))))
     }
    } 
   }
   gWidgets2::visible(mainwin) = TRUE
   setFocus()
  } #end update Table
  updateTables() #update when program starts (use default sorting)
  
  #Add tooltips:
  gWidgets2::tooltip(tabimportA[1,1]) <- L$tip.data.changeview
  gWidgets2::tooltip(tabimportA[1,6]) <- L$tip.data.importref
  gWidgets2::tooltip(tabimportC[1,1]) <- L$tip.data.compare
  gWidgets2::tooltip(tabimportC[1,2]) <- L$tip.data.createreport
  gWidgets2::tooltip(tabimportC[1,3]) <- L$tip.data.selectprofiles
  gWidgets2::tooltip(tabimportC[1,4]) <- L$tip.data.ibs
  gWidgets2::tooltip(tabimportC[1,5]) <- L$tip.data.rmp
  gWidgets2::tooltip(tabimportC[1,6]) <- L$tip.data.conc
  gWidgets2::tooltip(tabimportC[1,7]) <- L$tip.data.editref
  gWidgets2::tooltip(tabimportC[1,8]) <- L$tip.data.restart
  
  ####################################################################################################################
  #######################################Tab 2: Match matrix: #############################################################
  #####################################################################################################################
  
  f_rotateMatchMatrix = function(h,...) {
    refreshTabMATRIX(rotate=TRUE) #update with rotated table  
  }
  
  f_truncatevals = function(h,...) { #removes values below threshold table
    val = get("setupThresh",envir=nnTK)$MACthresh #get options
    matchmat <- get("resCompMAC",envir=nnTK)$MatchMatrix
    if(is.null(matchmat)) return()
    if(gWidgets2::svalue(gridTab2[1,6])== L$truncate )  {
     matchmat[matchmat<val] = ""   #remove values below threshold
    }
    
    gWidgets2::visible(mainwin) = FALSE
    matchMATGUI[] <-  casesolver::addRownameTable(matchmat,type=2,L$samplename)
    if(!is.null(ncol(matchMATGUI[])) && all(dim(matchmat)<nLarge) ) gWidgets2::size(matchMATGUI) <- list(column.widths=c(30,rep(100,ncol(matchMATGUI[])-1)))
    gWidgets2::visible(mainwin) = TRUE
    setFocus()
  }
  
  gridTab2 = gWidgets2::glayout(horizontal = FALSE,spacing=5,container=gWidgets2::gframe( L$further ,container=tabmatchmatrix)) #kit and population selecter
  gridTab2[1,1] <- gWidgets2::gbutton(text= L$export, container=gridTab2,handler=f_exporttable,action="mac")  #Button to create matchcloud
  gWidgets2::tooltip(gridTab2[1,1]) <- L$tip.export 
  
  gridTab2[1,2] <- gWidgets2::gbutton(text= L$rotatematrix, container=gridTab2,handler=f_rotateMatchMatrix)  #Button to rotate table
  gridTab2[1,3] <- gWidgets2::gbutton(text=paste( L$sort.by , L$sort.column),container=gridTab2,handler= function(h,...) { refreshTabMATRIX(sort = 2)}) #Sort by colnames   
  gridTab2[1,4] <- gWidgets2::gbutton(text=paste( L$sort.by , L$sort.row),container=gridTab2,handler= function(h,...) { refreshTabMATRIX(sort = 3)}) #Sort by rownames   
  gridTab2[1,5] <- gWidgets2::gbutton(text=paste( L$sort.by , L$sort.matchval),container=gridTab2,handler= function(h,...) { refreshTabMATRIX(sort = 4)}) #Sort by rownames   
  gridTab2[1,6] <- gWidgets2::gradio(items= c( L$donttruncate , L$truncate ) ,selected=1,container=gridTab2,handler=f_truncatevals)  #Button to create matchcloud
  gWidgets2::tooltip(gridTab2[1,6]) <- L$tip.matchmatrix.truncate
  tabCompMatrix <- gWidgets2::ggroup(container=tabmatchmatrix,expand=TRUE,fill=TRUE)
  matchMATGUI <- gWidgets2::gtable(items="",container=tabCompMatrix) #add to frame
  gWidgets2::add(tabCompMatrix,matchMATGUI,expand=TRUE,fill=TRUE)
  
  #POSSIBLE TO CHANGE ROTATE-LAYOUT (ORDERING OF EVID/REFS) TO SHOW IN REPORT
  refreshTabMATRIX = function(rotate=FALSE,sort=1) { 
    resobj = get("resCompMAC",envir=nnTK)
    if(is.null(resobj$MatchMatrix)) return() #return if no match matrix found
    
    if(sort==2) { #sort by column names
      resobj$MatchMatrix = resobj$MatchMatrix[,order( colnames(resobj$MatchMatrix) ,decreasing=FALSE),drop=FALSE]
    } else if(sort==3) { #sort by row names
      resobj$MatchMatrix = resobj$MatchMatrix[ order( rownames(resobj$MatchMatrix) ,decreasing=FALSE),,drop=FALSE]
    }else if(sort==4) { #sort by match degree (both rows/columns)
      colOrder = order( colSums(resobj$MatchMatrix) ,decreasing=TRUE ) #order based on total MAC sum
      rowOrder = order( rowSums(resobj$MatchMatrix) ,decreasing=TRUE ) #order based on total MAC sum
      resobj$MatchMatrix = resobj$MatchMatrix[ rowOrder,colOrder, drop=FALSE]
    }
    if(rotate) resobj$MatchMatrix = t(resobj$MatchMatrix) #ROTATE MATRIX
    assign("resCompMAC",resobj,envir=nnTK) #store manipulated object (keep same form of table in report)
    
    gWidgets2::visible(mainwin) = FALSE
    matchMATGUI[] <-  casesolver::addRownameTable(resobj$MatchMatrix,type=2,L$samplename) #rotate view
    if(!is.null(ncol(matchMATGUI[])) && all(dim(resobj$MatchMatrix)<nLarge)) gWidgets2::size(matchMATGUI) <- list(column.widths=c(30,rep(100,ncol(matchMATGUI[])-1)))
    gWidgets2::visible(mainwin) = TRUE
    
    #truncate if option is selected
    if(gWidgets2::svalue(gridTab2[1,6])==L$truncate) f_truncatevals(NULL) 
    
    setFocus()
  }
  refreshTabMATRIX() #use default sort
  
  ####################################################################################################################
  #######################################Tab 3: Match List (Qual): ##################################################
  ####################################################################################################################
  sortMathListTablesTxt = paste( L$sort.by , c( L$sort.lr , L$sort.evid , L$sort.ref ))
  
  gridTab3 = gWidgets2::glayout(horizontal = FALSE,spacing=5,container=gWidgets2::gframe( L$further ,container=tabmatchlist1)) #kit and population selecter
  gridTab3[1,1] <- gWidgets2::gbutton(text= L$export ,container=gridTab3,handler=f_exporttable,action="qual")  
  gWidgets2::tooltip(gridTab3[1,1]) <- L$tip.export 
  
  gridTab3[1,2] <- gWidgets2::gbutton(text= paste( L$calculate , L$all, L$quanLR) ,container=gridTab3,handler=f_calcQuanLRall)
  gWidgets2::tooltip(gridTab3[1,2]) <- L$tip.matchlistQual.calc
  
  #gridTab3[1,3] <- gWidgets2::gbutton(text= paste("Calc with EFMex") ,container=gridTab3,handler=f_calcQuanLRall,action="EFMex")
  #gWidgets2::tooltip(gridTab3[1,3]) <- L$tip.matchlistQual.calc
  
  
  gridTab3[1,4] <- gWidgets2::gcombobox(items=sortMathListTablesTxt,selected=1,container=gridTab3,handler=
   function(h,...) {
     sortval = which(gWidgets2::svalue(gridTab3[1,4])==sortMathListTablesTxt)
     resave_Sorting(3,sortval) #resaving to setupSorting object
     refreshTabLIST1(sort=sortval) #change sorted order
   }
  )  
  tabCompLIST1 = gWidgets2::ggroup(container=tabmatchlist1,expand=TRUE,fill=TRUE)
  
  matchL1GUI <- gWidgets2::gtable(items="",container=tabCompLIST1,handler=clickmatchlistQUAL)
  gWidgets2::add(tabCompLIST1,matchL1GUI,expand=TRUE,fill=TRUE)#add to frame
  
  refreshTabLIST1 = function(sort=1) { 
    matchlist <- get("resCompLR1",envir=nnTK)
    if(is.null(matchlist)) return() #return if no list found
    if(nrow(matchlist)==0) return() #return if no candidate found
  
    resTab = casesolver::addRownameTable(matchlist,type=3,L$samplename)
    ord = casesolver::orderTableSort(resTab[,2],resTab[,3],sort) #obtain order of sorting
    
    matchL1GUI[] <-  resTab[ord,,drop=FALSE]
    if( nrow(resTab)<nLarge ) gWidgets2::size(matchL1GUI) <- list(column.widths=c(30,300,300,70,70,100))
  }
  refreshTabLIST1() #use default sort
  
  ####################################################################################################################
  #######################################Tab 4: Match List (Quan): ##################################################
  ####################################################################################################################
  
  gridTab4 = gWidgets2::glayout(horizontal = FALSE,spacing=5,container=gWidgets2::gframe( L$further ,container=tabmatchlist2)) #kit and population selecter
  gridTab4[1,1] <- gWidgets2::gbutton(text= L$export ,container=gridTab4,handler=f_exporttable,action="quan")#
  gWidgets2::tooltip(gridTab4[1,1]) <- L$tip.export 
  
  gridTab4[1,3] <- gWidgets2::gcombobox(items=sortMathListTablesTxt,selected=1,container=gridTab4,handler=
   function(h,...) {
     sortval = which(gWidgets2::svalue(gridTab4[1,3])==sortMathListTablesTxt)
     resave_Sorting(4,sortval) #resaving to setupSorting object
     refreshTabLIST2(sort=sortval) #change sorted order
   }
  )  
  
  tabCompLIST2 = gWidgets2::ggroup(container=tabmatchlist2,expand=TRUE,fill=TRUE)
  
  matchL2GUI <- gWidgets2::gtable(items="",container=tabCompLIST2,handler=clickmatchlistQUAN)
  gWidgets2::add(tabCompLIST2,matchL2GUI,expand=TRUE,fill=TRUE)#add to frame
  
  refreshTabLIST2 = function(selInd=NULL,sort=1) { 
    matchlist <- get("resCompLR2",envir=nnTK)
    if(is.null(matchlist)) return() #return if no list found
    if(nrow(matchlist)==0) return() #return if no candidate found
    resTab = casesolver::addRownameTable(matchlist,type=3,L$samplename)
    ord = casesolver::orderTableSort(resTab[,2],resTab[,3],sort) #obtain order of sorting
    
    matchL2GUI[] <- resTab[ord,,drop=FALSE]
    if(nrow(resTab)<nLarge) gWidgets2::size(matchL2GUI) <- list(column.widths=c(30,300,300,70,70,rep(100,ncol(matchlist)-4)))
    if(!is.null(selInd)) gWidgets2::svalue(matchL2GUI) <- selInd #select row
  }
  refreshTabLIST2() #use default sort
  
  ################################################################################################
  #################################Tab 5: Matches: ##############################################
  ################################################################################################
  sortMixListTablesTxt = paste( L$sort.by , c( "#" , L$sort.evid , L$sort.ref ))
  
  gridTab5 = gWidgets2::glayout(horizontal = FALSE,spacing=5,container=gWidgets2::gframe( L$further ,container=tabmixtures),expand=TRUE,fill=TRUE) #kit and population selecter
  gridTab5[1,1] <- gWidgets2::gbutton(text= paste( L$woeperform ),container=gridTab5,handler=f_doWOEcall) #Perform WOE
  gWidgets2::tooltip(gridTab5[1,1]) <- L$tip.matches.woe
  gridTab5[1,2] <- gWidgets2::gbutton(text= paste( L$deconvolvemixtures ) ,container=gridTab5,handler=f_doDCall)# perform DC for all mixtures (with default settings)
  gWidgets2::tooltip(gridTab5[1,2]) <- L$tip.matches.dcall
  
  gridTab5[1,3] <- gWidgets2::gbutton(text= paste( L$show , L$match , L$network ) ,container=gridTab5,handler=f_showMatchNetwork,action="all")  #Button to create matchcloud
  gridTab5[1,4] <- gWidgets2::gbutton(text= paste( L$showfor , L$mixtures )  ,container=gridTab5,handler=f_showMatchNetwork,action="onlymix")  #Button to create matchcloud
  gridTab5[1,5] <- gWidgets2::gbutton(text= paste( L$showfor , L$singlesources ),container=gridTab5,handler=f_showMatchNetwork,action="onlyss")  #Button to create matchcloud
  gridTab5[1,6] <- gWidgets2::gbutton(text= L$export ,container=gridTab5,handler=f_exporttable,action="final")#  
  gWidgets2::tooltip(gridTab5[1,6]) <- L$tip.export 
  
  gridTab5[1,7] <- gWidgets2::gcombobox(items=sortMixListTablesTxt,selected=1,container=gridTab5,expand=TRUE,handler=
   function(h,...) {
     sortval = which(gWidgets2::svalue(gridTab5[1,7])==sortMixListTablesTxt)
     resave_Sorting(5,sortval) #resaving to setupSorting object
     refreshTabLIST(sort=sortval) #change sorted order
   }
  )  
  
  tabmixLIST = gWidgets2::ggroup(container=tabmixtures,expand=TRUE,fill=TRUE)
  mixlistGUI <- gWidgets2::gtable(items="",container=tabmixLIST,handler=clickmixlist)
  gWidgets2::add(tabmixLIST,mixlistGUI,expand=TRUE,fill=TRUE)#add to frame
  
  refreshTabLIST = function(evidsel=NULL,sort=1) {  #get list with all mixtures with info about matched elements 
    #store match-results from comparison (those with LR>threshold) together with all mixtures
    matchstat <- get("mixDataMATCHSTATUS",envir=nnTK) #get match status mixtures
    indUse <- indMixEmpty <- matchstat == "mixture" | matchstat=="" #important for recognizing mixtures or empty
    if(get("setupAdvanced",envir=nnTK)$compSS=="TRUE")  indUse = indUse | TRUE #SHOW ALL #grepl("Unknown ",matchstat)
    mixName <- names(matchstat)[indUse]  #get sampleName of all mixtures
    if( length(mixName)==0 ) return() #return if no mixtures existing   
    nClow <- sapply(get("mixDataLIST",envir=nnTK)[mixName],function(elem) { ceiling(max(sapply(elem,function(x) length(x$adata)))/2) })
    mixlist <- cbind(mixName,"",nClow)
    colnames(mixlist) <- c( L$evidence , L$references , L$numcontr )
  
    #INSERT SINGLE SOURCE PROFILES IDENTICAL MATCHES (MATCH STATUS)    
    matchstat2 =  matchstat[!indMixEmpty] #matchstatus to use
    indInsert = mixlist[,1]%in%names(matchstat2) 
    mixlist[indInsert,2] = matchstat2[match(names(matchstat2),mixlist[indInsert,1])] #Update: insert single source match information
    
    #UPDATE CANDIDATE MATCHES BASED ON COMPARE RESULTS
    matchlist <- get("resMatches",envir=nnTK) #get match list (based on results after comparisons)
    mixlist[match(matchlist[,1],mixName),2] <- matchlist[,2] #Update contributing References
    mixlist[match(matchlist[,1],mixName),3] <- matchlist[,3] #Update number of contributors
    assign("allMixList",mixlist,envir=nnTK)  #store match-results from comparison (those with LR>threshold) together with all mixtures
  
    resTab = casesolver::addRownameTable(mixlist,type=3,L$samplename)
    ord = casesolver::orderTableSort(resTab[,2],resTab[,3],sort) #obtain order of sorting
    mixlistGUI[] <- resTab[ord,,drop=FALSE]
  
    if(nrow(resTab)<nLarge) gWidgets2::size(mixlistGUI) <- list(column.widths=c(30,300,500,100))
    if(!is.null(evidsel)) gWidgets2::svalue(mixlistGUI) = which(mixlist[,1]==evidsel)  #marking line
  }
  refreshTabLIST() #use default sort
  
  ################################################################################################
  #################################Tab 6: Deconvoluted: ##############################################
  ################################################################################################
  sortDCTableTxt <- paste( L$sort.by , c( "#" , L$sort.evid , L$similarity ))
  
  gridTab6 = gWidgets2::glayout(horizontal = FALSE,spacing=5,container=gWidgets2::gframe( L$further ,container=tabdeconv)) #kit and population selecter
  gridTab6[1,1] <- gWidgets2::gbutton(text=paste( L$export , L$table ),container=gridTab6,handler=f_exporttable,action="dc")# 
  gWidgets2::tooltip(gridTab6[1,1]) <- L$tip.export
  
  #Export selected
  gridTab6[1,2] <- gWidgets2::gbutton(text=paste( L$export , L$selected ),container=gridTab6,handler=function(h,...) {
   DClist <- get("DClist",envir=nnTK)
   if(is.null(DClist)) return() #none found
   selID =  as.integer(gsub("#","",gWidgets2::svalue(DClistGUI) ) )
   if(length(selID)==0) return() #none selected
   dupInd = which(duplicated(colnames(DClist))) #get index of duplicated
   
   refn = DClist[selID,1] #get refnames
   refTab = t(DClist[selID,-c(1:4,dupInd)])
   rownames(refTab) = refn 
   saveTable(sampleListToTable(casesolver::tabToListRef(tab=refTab,setEmpty=FALSE))) #save to file
  })# End export selected
  gWidgets2::tooltip(gridTab6[1,2]) <- L$tip.dc.exportsel
  
  #Delete selected
  gridTab6[1,3] <- gWidgets2::gbutton(text=paste( L$delete , L$selected ),container=gridTab6,handler=function(h,...) {
     DClist <- get("DClist",envir=nnTK)
     if(is.null(DClist)) return() #none found
     selID =  as.integer(gsub("#","",gWidgets2::svalue(DClistGUI) ) )
     if(length(selID)==0) return() #none selected
     DClist <- DClist[-selID,,drop=FALSE] #update
     assign("DClist",DClist,envir=nnTK)
     refreshDCLIST()
  })
  gWidgets2::tooltip(gridTab6[1,3]) <- L$tip.dc.delete
  
  #Show ratio-to-next
  gridTab6[1,4] <- gWidgets2::gbutton(text=paste( L$show , L$probRatioToNext ),container=gridTab6,handler=function(h,...) {
   DClist <- get("DClist",envir=nnTK)
   if(is.null(DClist)) return() #return if no list found
   selID =  as.integer(gsub("#","",gWidgets2::svalue(DClistGUI) ) )
   if(length(selID)==0) return() #none selected
   dupInd = which(duplicated(colnames(DClist))) #get index of duplicated
   tab = cbind(DClist[selID,-c(1:4,dupInd)], DClist[selID,dupInd])
   colnames(tab) = c(L$Genotype, L$probRatioToNext)
   
   showGDFtable(L$probRatioToNext, casesolver::addRownameTable(tab,samplename = L$Marker))
  })
  gWidgets2::tooltip(gridTab6[1,4]) <- L$tip.dc.showprobs
  
  tabDCLIST = gWidgets2::ggroup(container=tabdeconv,expand=TRUE,fill=TRUE)
  DClistGUI <- gWidgets2::gtable(items="",multiple = FALSE,container=tabDCLIST,handler=addDCprofile)
  gWidgets2::add(tabDCLIST,DClistGUI,expand=TRUE,fill=TRUE)#add to frame
  
  #Show PHexp for deconvolved profile (including other fit):
  gridTab6[1,5] <- gWidgets2::gbutton(text=paste( L$expPHplot ),container=gridTab6,handler=function(h) {
   DClist <- get("DClist",envir=nnTK)
   if(is.null(DClist)) return() #return if no list found
   selID =  as.integer(gsub("#","",gWidgets2::svalue(DClistGUI) ) )
   if(length(selID)==0) return() #none selected
   
   #Prepare profiles:
   candname = DClist[selID,1] #name of candidate
   splitPtrn = "-C" #split pattern to remove last component
   evids =  strsplit(candname,splitPtrn)[[1]] #remove last component
   candname = paste0("C",evids[length(evids)]) #obtain name of component
   evids = paste(evids[1:(length(evids)-1)],collapse=splitPtrn) #keep only evidence name but make it possible for evidence names to have pattern
   evids = strsplit(evids,"/")[[1]] #obtain evidences to consider (possibly replicates)
   conds = strsplit(DClist[selID,2],"/")[[1]] #obtain conditional refs
   NOC = as.integer(DClist[selID,3])
  
   #Prepare profile of candidate:
   dupInd = which(duplicated(colnames(DClist))) #get index of duplicated column names
   candProfile =DClist[selID,-c(1:4,dupInd),drop=FALSE] #get profile of candidate
   rownames(candProfile) = candname
   
   addedProfiles = tabToListRef(candProfile)
   doDC(nC=NOC,evids=evids,refs=conds,showPlot=TRUE,useplotly=TRUE,addedProfiles=addedProfiles)
  })
  
  #add button for adding ref
  gridTab6[1,6] <- gWidgets2::gbutton(text=paste( L$addasref ),container=gridTab6,handler=addDCprofile)
  gWidgets2::tooltip(gridTab6[1,6]) <- L$tip.dc.addasref
  
  #Possible to sort table
  gridTab6[1,7] <- gWidgets2::gcombobox(items=sortDCTableTxt,selected=1,container=gridTab6,expand=TRUE,handler=
                                         function(h,...) {
                                           sortval = which(gWidgets2::svalue(gridTab6[1,7])==sortDCTableTxt)
                                           #resave_Sorting(6,sortval) #DONT store sortvalue to setupSorting object
                                           refreshDCLIST(sort=sortval) #change sorted order
                                         })  
  
  #Function to update DC-table GUI 
  refreshDCLIST = function(sort=1) {  #get list of matched elements
   DClist <- get("DClist",envir=nnTK)
   if(is.null(DClist)) return() #return if no list found
   dupInd = which(duplicated(colnames(DClist))) #get index of duplicated column names
  #   locnames = colnames(DClist)[dupInd]  #column names
   
   #ORDER ROWS WRT criteria
   ord = 1:nrow(DClist) #default is no sorting
   if(sort==2) { #sort based on evid name
     ord = order(DClist[,1])
  #Order by clustering:
   } else if(nrow(DClist)>=3 && sort==3) { #perform sorting based on similarity (using clustering), must have at least 3 rows
     
     #Idea: Order samples based on hierachical clustering structure (based on distance outcome)
     ord = casesolver::clusterOrder( table=DClist[,-c(1:4,dupInd),drop=FALSE] )
   }# end if clustering
  
   DCtab =  casesolver::addRownameTable(DClist[,-dupInd,drop=FALSE] ,type=3,L$samplename) #add # to first column 
   
   #PREPARE OUT-PUT TABLE (SORTING + TRUNCATE COLUMNS):
   DClistGUI[] <-  DCtab[ord,,drop=FALSE] #DC table to consider 
   gWidgets2::size(DClistGUI) <- list(column.widths=c(30,100,100,30,50,rep(50,ncol(DClistGUI)-5))) 
  }
  refreshDCLIST()
  
  ################################################################################################
  #################################Tab 7: Weight of evidence: ####################################
  ################################################################################################
  gridTab7 = gWidgets2::glayout(horizontal = FALSE,spacing=5,container=gWidgets2::gframe( L$further ,container=tabWOE)) #kit and population selecter
  gridTab7[1,1] <- gWidgets2::gbutton(text=paste( L$export , L$table ),container=gridTab7,handler=f_exporttable,action="woe")#  
  gridTab7[1,2] <- gWidgets2::gbutton(text=paste( L$show , L$lrpermarker  ),container=gridTab7,handler=showLRperMarker)  #show LR-marker for selected
  
  #SHOW PARAM ESIMTATES
  gridTab7[1,3] <- gWidgets2::gbutton(text=paste( L$show , "param est."  ),container=gridTab7, handler=function(h) {
   resWOEeval <- get("resWOEeval",envir=nnTK) #obtain WOE results
   if(is.null(resWOEeval)) return()
   ids <- as.integer(gsub("#","",gWidgets2::svalue(WOElistGUI)))
   for(id in ids) {
     hypsettxt = paste0("Hyp. set #",id)
     samplename = resWOEeval$resTable[id,1]
       
     #Show mixture proportions in a separe plot:
     if(require(plotrix)) {
       MxHp = sort(resWOEeval[[id]]$MxRefs$hp,decreasing = TRUE) #sort to make same colors
       MxHd = sort(resWOEeval[[id]]$MxRefs$hd,decreasing = TRUE) #sort to make same colors
       s0 = 2
       labelHp = paste0(names(MxHp)," ",round(MxHp*100),"%") #Obtain labels
       labelHd = paste0(names(MxHd)," ",round(MxHd*100),"%") #Obtain labels
       plotfn = paste0("WOEpie",id) #file name
       graphics.off() #remove other plots first
       png(plotfn,height=400,width=1000)
       par(mfrow=c(1,2))
       marg = c(0,5,0,6)
       plotrix::pie3D(MxHp,radius=0.9,labels=labelHp,explode=0.1,main="Hp",mar=marg)
       plotrix::pie3D(MxHd,radius=0.9,labels=labelHd,explode=0.1,main="Hd",mar=marg)
       mtext(samplename,cex=1.5,outer=TRUE,line=-2)
       dev.off()
       
       TopWin <- gWidgets2::gwindow(paste0("Mixture proportions for ",hypsettxt))#,width=800,height=400)
       gWidgets2::gimage(plotfn,container=TopWin)
       gWidgets2::focus(TopWin) = TRUE
       file.remove(plotfn) #remove file after
     }
     
    #show params in table   
     tab = resWOEeval[[id]]$paramTable
     showGDFtable(hypsettxt,casesolver::addRownameTable(tab,samplename = "Param"))
   }
  })
  
  #SHOW MODEL VALIDATION
  gridTab7[1,4] <- gWidgets2::gbutton(text=paste( L$show , "model validation"  ),container=gridTab7, handler=function(h) {
    resWOEeval <- get("resWOEeval",envir=nnTK) #obtain WOE results
    if(is.null(resWOEeval)) return()
    
    ids <- as.integer(gsub("#","",gWidgets2::svalue(WOElistGUI)))
    for(id in ids) {
      hypsettxt = paste0("Hyp. set #",id)
      print(paste0("Calculating for ", hypsettxt))
      kit0 = casesolver::getEnvirKit(nnTK)
      plotfn1 =  paste0("WOEvalidHp",id) #file name
      plotfn2 =  paste0("WOEvalidHd",id) #file name
      graphics.off() #remove other plots first
      size0 = 600
      png(plotfn1,height=size0,width=size0)
      euroformix::validMLEmodel( resWOEeval[[id]]$mleHp, kit=kit0,plottitle = "Hp")
      dev.off() 
      
      png(plotfn2,height=size0,width=size0)
      euroformix::validMLEmodel( resWOEeval[[id]]$mleHd, kit=kit0,plottitle = "Hd" )
      dev.off() 
      
      TopWin <- gWidgets2::gwindow(paste0("Model validation for ",hypsettxt))#,width=800,height=400)
      ggrp <- gWidgets2::ggroup(container=TopWin)
      gWidgets2::gimage(plotfn1,container=ggrp)
      gWidgets2::gimage(plotfn2,container=ggrp)
      gWidgets2::focus(TopWin) = TRUE
      file.remove(plotfn1) #remove file after
      file.remove(plotfn2) #remove file after
    }    
  })  
  
  #SHOW MODEL FITTED PH
  gridTab7[1,5] <- gWidgets2::gbutton(text=paste( L$show , "model fitted PH"  ),container=gridTab7, handler=function(h) {
   resWOEeval <- get("resWOEeval",envir=nnTK) #obtain WOE results
   if(is.null(resWOEeval)) return()
   id <- as.integer(gsub("#","",gWidgets2::svalue(WOElistGUI)))
   if(length(id)>1) {
     gWidgets2::gmessage("Only one hypothesis must be selected for modifying a statement. Please re-select.","Wrong selection", icon="info")
     return()  
   }
   resWOEeval_id = resWOEeval[[id]]
   if(is.null(resWOEeval_id)) return() #couldnt find object
   
   hyp = gWidgets2::gconfirm("Select hypothesis (Yes=Hp, No=Hd)","Choose hypothesis",icon = "question")
   kitname = casesolver::getEnvirKit(nnTK)
   type = casesolver::getSampleType2( resWOEeval_id$mleHp$model$samples ,kitname) #get sample type
   if(hyp) {
     makePlotTop(type,resWOEeval_id$mleHp,NULL,kitname)
   } else {
     makePlotTop(type,resWOEeval_id$mleHd,NULL,kitname)
   }
  })  
  
  #SHOW STATEMENTS
  gridTab7[1,6] <- gWidgets2::gbutton(text=paste( L$show, L$statement ),container=gridTab7, handler=function(h) {
   resWOEeval <- get("resWOEeval",envir=nnTK) #obtain WOE results
   if(is.null(resWOEeval)) return()
   id <- as.integer(gsub("#","",gWidgets2::svalue(WOElistGUI)))
   if(length(id)>1) {
     gWidgets2::gmessage("Only one hypothesis must be selected for modifying a statement. Please re-select.","Wrong selection", icon="info")
     return()  
   }
   state = resWOEeval[[id]]$statement #obtain statement
   env = new.env( parent = emptyenv() ) 
   assign("text",state,envir=env)
   casesolver::textEditor(env) #use inbuilt text editor to modify statement
   resWOEeval[[id]]$statement = get("text",envir=env)#obtain possibly edited text
   assign("resWOEeval",resWOEeval,envir=nnTK) #store text to environment
  }) 
  
  #CONSERVATIVE CALCULATION:
  gridTab7[1,7] <- gWidgets2::gbutton(text=paste( L$calccons ),container=gridTab7,handler=function(h) {
   resWOEeval <- get("resWOEeval",envir=nnTK) 
   if(is.null(resWOEeval)) return()
   ids =  as.integer(gsub("#","",gWidgets2::svalue(WOElistGUI) ) )
   
   #(RE)CULCULATE CONS LR FOR SELECTED HYPS
   for(id in ids) {
     print(paste0("Performing conservative calculations for hypothesis set #",id))
     mcmcOpt = get("setupMCMC",envir=nnTK)
     
     mcmcObjList=NULL
     if(!is.null(resWOEeval[[id]]$mcmc)) mcmcObjList = resWOEeval[[id]]$mcmc$mcmcObjList #obtain previous calcs
     resWOEeval[[id]]$mcmc = euroformix::calcLRmcmc(resWOEeval[[id]]$mleHp,resWOEeval[[id]]$mleHd, mcmcOpt$niter,mcmcOpt$delta,mcmcOpt$quantile,mcmcOpt$seed, verbose=TRUE,traceplot=TRUE, mcmcObjList=mcmcObjList)
     state <- resWOEeval[[id]]$statementNoWOE #obtain statement without woe value
     consLR <- LRuse <- resWOEeval[[id]]$mcmc$log10LRcons
     bayesLR <- resWOEeval[[id]]$mcmc$log10LRbayes
     
     #insert woe strength (also possibly as text)
     LRtxt = signif(10^LRuse,2)
     useVerbalLR =  get("setupReportOpt",envir=nnTK)["verbalLR"]  #If using verbal LR
     if(useVerbalLR) {
       LRverbal = casesolver::number2word(LRuse,L) #obtain verbal LR
       LRtxt = paste0(LRverbal[1]," (",LRverbal[2],")") #add verbal in additon to down-rounded number
     }
     state = gsub("$LRtxt",LRtxt,state,fixed=TRUE)
  
     #INSERT BACK TO OBJECT:
     s0 = 2
     resWOEeval[[id]]$statement <- state
     resWOEeval[[id]]$bayesLR <- resWOEeval$resTable[id,6] <- round(bayesLR,s0) #insert updated values
     resWOEeval[[id]]$consLR  <- resWOEeval$resTable[id,7] <- round(consLR,s0) #insert updated value
   }
   
   assign("resWOEeval",resWOEeval,envir=nnTK) #store object to environment again
   refreshWOELIST() #refresh table
  })
  
  #DELETE SELECTED WOE CALCULATIONS
  gridTab7[1,8] <- gWidgets2::gbutton(text=paste( L$delete , L$selected ),container=gridTab7,handler=function(h) {
   resWOEeval <- get("resWOEeval",envir=nnTK) 
   if(is.null(resWOEeval)) return()
   nHypSets = nrow(resWOEeval$resTable) #number of hypotheses
   if(nHypSets==0) return() #return if none to select (can't happen)
   ids =  as.integer(gsub("#","",gWidgets2::svalue(WOElistGUI) ) ) #selected row
  
   existingIDs = seq_len(nHypSets)
   if(all(existingIDs%in%ids)) { #IF ALL SELECTED
     WOElistGUI[] <- resWOEeval <- NULL      #removing ALL element (set everything as zero)
   } else {
     keepIDs = setdiff(existingIDs,ids) #get which rows to keep
     tmpTable = resWOEeval$resTable[keepIDs,,drop=FALSE] #obtain subset of restable
     resWOEeval= resWOEeval[keepIDs]
     resWOEeval$resTable = tmpTable #insert updated table
   }
   assign("resWOEeval",resWOEeval,envir=nnTK) #store object to environment again
   refreshWOELIST() #refresh table
  })
  
  #INITITATE WOE TABLE
  tabWOELIST = gWidgets2::ggroup(container=tabWOE,expand=TRUE,fill=TRUE)
  WOElistGUI <- gWidgets2::gtable(items="",multiple = TRUE, container=tabWOELIST, handler=showLRperMarker)
  gWidgets2::add(tabWOELIST,WOElistGUI,expand=TRUE,fill=TRUE)#add to frame
  
  refreshWOELIST = function() {  #get list of matched elements
   resTable <- get("resWOEeval",envir=nnTK)$resTable #obtain table
   if(is.null(resTable)) return() #return if no list found
   WOElistGUI[] <- casesolver::addRownameTable( resTable ,type=3) #add DC-list
   gWidgets2::size(WOElistGUI) <- list(column.widths=c(30,150,75,150,rep(50,ncol(WOElistGUI)-4))) 
  }
  refreshWOELIST()
  
  #Add tooltips
  gWidgets2::tooltip(gridTab7[1,1]) <- L$tip.export
  gWidgets2::tooltip(gridTab7[1,2]) <- L$tip.woe.lrpermarker
  gWidgets2::tooltip(gridTab7[1,3]) <- L$tip.woe.paramest
  gWidgets2::tooltip(gridTab7[1,4]) <- L$tip.woe.modelvalid
  gWidgets2::tooltip(gridTab7[1,5]) <- L$tip.woe.fittedPH
  gWidgets2::tooltip(gridTab7[1,6]) <- L$tip.woe.statement
  gWidgets2::tooltip(gridTab7[1,7]) <- L$tip.woe.cons
  gWidgets2::tooltip(gridTab7[1,8]) <- L$tip.woe.delete
  
  ################################################################################################
  #Running through all windows to avoid "bleed through"
  sapply(7:1, function(x) {
   gWidgets2::svalue(nb) <- x
  })
  gWidgets2::visible(mainwin) <- TRUE
  gWidgets2::size(mainwin) = c(mwW,mwH) #set width and hight after window is open (must)
  setFocus()

} #end main function
oyvble/casesolver documentation built on Feb. 26, 2025, 2:05 a.m.