1#' Interactive GUI for Amelia 2#' 3#' @name ameliagui 4#' 5#' @description 6#' Brings up the AmeliaView graphical interface, which allows users 7#' to load datasets, manage options and run Amelia from a traditional 8#' windowed environment. 9#' 10#' @usage AmeliaView() 11#' @keywords utilities 12 13main.close<-function() { 14 qvalue<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="Are you sure you want to exit Amelia?", 15 icon="question", 16 type="okcancel", 17 default="cancel") 18 if (tcltk::tclvalue(qvalue)=="ok") { 19 tcltk::tkdestroy(getAmelia("gui")) 20 } 21} 22 23 24 25setWorkingDir <- function() { 26 newwd <- tcltk::tkchooseDirectory(parent = getAmelia("gui"), 27 initialdir = getwd(), 28 title = "Set output directory...", 29 mustexist = TRUE) 30 if (tcltk::tclvalue(newwd) != "") 31 setwd(tcltk::tclvalue(newwd)) 32 33 return(NULL) 34} 35 36loadStata <- function() { 37 38 filetype <- c("{{Stata files} {.dta}} {{All files} *}") 39 40 putAmelia("am.filename", tcltk::tclvalue(tcltk::tkgetOpenFile(parent=getAmelia("gui"), filetypes=filetype))) 41 if (getAmelia("am.filename") == "") 42 return(NULL) 43 if (!is.null(getAmelia("amelia.data"))) { 44 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you load another dataset, your current settings will be erased. Are you sure you want to load the new data?",icon="question",type="yesno") 45 if (tcltk::tclvalue(sure) == "no") 46 return(NULL) 47 } 48 putAmelia("amelia.data",try(read.dta(getAmelia("am.filename"),convert.factors=FALSE))) 49 putAmelia("am.filetype", "Stata") 50 if (inherits(getAmelia("amelia.data"), "try-error")) { 51 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Failure in loading the data. Try again.",icon="error",type="ok") 52 putAmelia("amelia.data",NULL) 53 return(NULL) 54 } 55 activateGUI() 56} 57 58loadSPSS <- function() { 59 60 filetype <- c("{{SPSS} {.sav}} {{All files} *}") 61 putAmelia("am.filename", tcltk::tclvalue(tcltk::tkgetOpenFile(parent=getAmelia("gui"), filetypes=filetype))) 62 63 if (getAmelia("am.filename") == "") 64 return(NULL) 65 if (!is.null(getAmelia("amelia.data"))) { 66 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you load another dataset, your current settings will be erased. Are you sure you want to load the new data?",icon="question",type="yesno") 67 if (tcltk::tclvalue(sure) == "no") 68 return(NULL) 69 } 70 putAmelia("amelia.data",try(read.spss(getAmelia("am.filename"),use.value.labels=FALSE,to.data.frame=TRUE))) 71 putAmelia("am.filetype", "SPSS") 72 if (inherits(getAmelia("amelia.data"), "try-error")) { 73 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Failure in loading the data. Try again.",icon="error",type="ok") 74 putAmelia("amelia.data",NULL) 75 return(NULL) 76 } 77 activateGUI() 78} 79 80loadSAS <- function() { 81 82 filetype <- c("{{SAS Transport} {.xpt}} {{All files} *}") 83 putAmelia("am.filename", tcltk::tclvalue(tcltk::tkgetOpenFile(parent=getAmelia("gui"), filetypes=filetype))) 84 85 if (getAmelia("am.filename") == "") 86 return(NULL) 87 if (!is.null(getAmelia("amelia.data"))) { 88 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you load another dataset, your current settings will be erased. Are you sure you want to load the new data?",icon="question",type="yesno") 89 if (tcltk::tclvalue(sure) == "no") 90 return(NULL) 91 } 92 putAmelia("amelia.data",try(read.xport(getAmelia("am.filename")))) 93 putAmelia("am.filetype", "SAS") 94 if (inherits(getAmelia("amelia.data"), "try-error")) { 95 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Failure in loading the data. Try again.",icon="error",type="ok") 96 putAmelia("amelia.data",NULL) 97 return(NULL) 98 } 99 activateGUI() 100} 101 102loadTAB <- function() { 103 104 filetype <- c("{{Tab-delimited files} {.txt .tab .dat}} {{All files} *}") 105 putAmelia("am.filename", tcltk::tclvalue(tcltk::tkgetOpenFile(parent=getAmelia("gui"), filetypes=filetype))) 106 if (getAmelia("am.filename") == "") 107 return(NULL) 108 if (!is.null(getAmelia("amelia.data"))) { 109 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you load another dataset, your current settings will be erased. Are you sure you want to load the new data?",icon="question",type="yesno") 110 if (tcltk::tclvalue(sure) == "no") 111 return(NULL) 112 } 113 putAmelia("amelia.data",try(read.table(getAmelia("am.filename"),header=TRUE))) 114 putAmelia("am.filetype", "TAB") 115 if (inherits(getAmelia("amelia.data"), "try-error")) { 116 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Failure in loading the data. Try again.",icon="error",type="ok") 117 putAmelia("amelia.data",NULL) 118 return(NULL) 119 } 120 activateGUI() 121} 122 123loadCSV <- function() { 124 125 filetype <- c("{{Comma-delimited files} {.csv}} {{All files} *} ") 126 putAmelia("am.filename", tcltk::tclvalue(tcltk::tkgetOpenFile(parent=getAmelia("gui"), filetypes=filetype))) 127 if (getAmelia("am.filename") == "") 128 return(NULL) 129 if (!is.null(getAmelia("amelia.data"))) { 130 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you load another dataset, your current settings will be erased. Are you sure you want to load the new data?",icon="question",type="yesno") 131 if (tcltk::tclvalue(sure) == "no") 132 return(NULL) 133 } 134 putAmelia("amelia.data",try(read.csv(getAmelia("am.filename"),header=TRUE))) 135 putAmelia("am.filetype", "CSV") 136 if (inherits(getAmelia("amelia.data"), "try-error")) { 137 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Failure in loading the data. Try again.",icon="error",type="ok") 138 putAmelia("amelia.data",NULL) 139 return(NULL) 140 } 141 activateGUI() 142} 143 144 145loadRData <- function() { 146 onOK <- function() { 147 putAmelia("amelia.data", eval(as.name(tcltk::tclvalue(tcltk::tkget(objectChooser))))) 148 tcltk::tkdestroy(chooseObjectWindow) 149 tcltk::tkfocus(getAmelia("gui")) 150 tcltk::tkgrab.release(chooseObjectWindow) 151 activateGUI() 152 return() 153 } 154 onCancel <- function() { 155 rm(list=getAmelia("amelia.data")) 156 tcltk::tkdestroy(chooseObjectWindow) 157 tcltk::tkfocus(getAmelia("gui")) 158 tcltk::tkgrab.release(chooseObjectWindow) 159 return() 160 } 161 162 filetype <- c("{{R Data files} {.RData .Rdata .Rda .rda}} {{All files} *} ") 163 putAmelia("am.filename", tcltk::tclvalue(tcltk::tkgetOpenFile(parent=getAmelia("gui"), filetypes=filetype))) 164 if (getAmelia("am.filename") == "") 165 return(NULL) 166 if (!is.null(getAmelia("amelia.data"))) { 167 sure <- tcltk::tkmessageBox(parent = getAmelia("gui"), 168 message = "If you load another dataset, your current settings will be erased. Are you sure you want to load the new data?", 169 icon = "question", type = "yesno") 170 if (tcltk::tclvalue(sure) == "no") 171 return(NULL) 172 } 173 putAmelia("amelia.data",try(load(getAmelia("am.filename")))) 174 putAmelia("am.filetype", "RData") 175 if (inherits(getAmelia("amelia.data"), "try-error")) { 176 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Failure in loading the data. Try again.",icon="error",type="ok") 177 putAmelia("amelia.data",NULL) 178 return(NULL) 179 } 180 if (length(getAmelia("amelia.data")) == 1) { 181 putAmelia("amelia.data", eval(as.name(getAmelia("amelia.data")))) 182 } else { 183 datasets <- sapply(getAmelia("amelia.data"), function(x) is.data.frame(eval(as.name(x)))) 184 datasets <- getAmelia("amelia.data")[datasets] 185 chooseObjectWindow <- tcltk::tktoplevel(parent=getAmelia("gui")) 186 tcltk::tkwm.title(chooseObjectWindow, "Find Data Set") 187 chooseFrame <- tcltk::ttkframe(chooseObjectWindow) 188 objectChooser <- tcltk::ttkcombobox(chooseFrame, width = 20) 189 tcltk::tkconfigure(objectChooser, values = datasets) 190 tcltk::tkset(objectChooser, datasets[1]) 191 objectOK <- tcltk::ttkbutton(chooseFrame, text = "OK", width = 10, command = onOK) 192 objectCancel <- tcltk::ttkbutton(chooseFrame, text = "Cancel", width = 10, command = onCancel) 193 194 tcltk::tkgrid(tcltk::ttklabel(chooseFrame, text = "Please select your dataset from the following objects:"), 195 row = 0, column = 0, columnspan = 2, padx = 10, pady = 10) 196 tcltk::tkgrid(objectChooser, row = 1, column = 0, columnspan = 2, padx = 10, pady = 10) 197 tcltk::tkgrid(objectOK, row = 2, column = 0, padx = 10, pady = 10) 198 tcltk::tkgrid(objectCancel, row = 2, column = 1, padx = 10, pady = 10) 199 tcltk::tkgrid(chooseFrame, padx = 10, pady = 10) 200 tcltk::tkgrab(chooseObjectWindow) 201 tcltk::tkfocus(chooseObjectWindow) 202 tcltk::tkwm.protocol(chooseObjectWindow, "WM_DELETE_WINDOW", onCancel) 203 centerModalDialog(chooseObjectWindow, resize=FALSE) 204 } 205 return() 206} 207 208loadDemo <- function(name) { 209 if (!is.null(getAmelia("amelia.data"))) { 210 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you load another dataset, your current settings will be erased. Are you sure you want to load the new data?",icon="question",type="yesno") 211 if (tcltk::tclvalue(sure) == "no") 212 return(NULL) 213 } 214 data(list=name, package="Amelia", envir = ameliaEnv) 215 putAmelia("amelia.data", eval(as.name(name))) 216 putAmelia("am.filetype", "demo") 217 putAmelia("am.filename", name) 218 activateGUI() 219} 220 221drawMissMap <- function() { 222 dev.new() 223 missmap(getAmelia("amelia.data"), csvar = getAmelia("csvar"), tsvar = getAmelia("tsvar")) 224} 225 226activateGUI <- function(session = FALSE) { 227 temp.list <- strsplit(getAmelia("am.filename"),"/")[[1]] 228 if (getAmelia("am.filetype") != "demo") { 229 temp.list <- strsplit(getAmelia("am.filename"),"/")[[1]] 230 putAmelia("am.directory", 231 paste(temp.list[-length(temp.list)],"",sep="/",collapse="")) 232 setwd(getAmelia("am.directory")) 233 } else { 234 putAmelia("am.directory", getwd()) 235 } 236 filename <- temp.list[length(temp.list)] 237 dotList <- strsplit(filename, "\\.")[[1]] 238 if (length(dotList) > 1) 239 dotList <- dotList[-length(dotList)] 240 filestub <- paste(paste(dotList, collapse = "."), "-imp", sep="") 241 putAmelia("varnames" , names(getAmelia("amelia.data"))) 242 243 244 tcltk::tkgrid.remove(getAmelia("error.label")) 245 tcltk::tkgrid.remove(getAmelia("allgood.label")) 246 tcltk::tkgrid(getAmelia("noimps.label"), row = 2, column = 7, 247 sticky ="e", padx = 10) 248 ## Get rid of welcome frame 249 if (as.logical(tcltk::tkwinfo("ismapped", getAmelia("gui.welcome")))) { 250 tcltk::tkgrid.remove(getAmelia("gui.welcome")) 251 tcltk::tkgrid(getAmelia("gui.skel"), row = 0, column = 0, sticky ="news") 252 tcltk::tkgrid(getAmelia("statusbar"), sticky = "sew") 253 } 254 ## initialize values 255 256 257 258 ## turn on various forms and buttons 259 tcltk::tkconfigure(getAmelia("output.run"), state = "normal") 260 #tcltk::tkconfigure(getAmelia("output.entry"), textvariable=getAmelia("outname")) 261 #tcltk::tkconfigure(getAmelia("output.num"), textvariable=getAmelia("outnum")) 262 tcltk::tkentryconfigure(getAmelia("main.menu.file"),"Edit Data...", state="normal") 263 tcltk::tkentryconfigure(getAmelia("main.menu.options"),"Draw Missingness Map", state="normal") 264 tcltk::tkentryconfigure(getAmelia("main.menu.file"),"Save Session...", 265 state = "normal") 266 tcltk::tkentryconfigure(getAmelia("main.menu.options"),"Output File Type...", 267 state = "normal") 268 tcltk::tkentryconfigure(getAmelia("main.menu.options"),"Output File Options...", 269 state = "normal") 270 tcltk::tkconfigure(getAmelia("missmapButton"), state = "normal") 271 tcltk::tkconfigure(getAmelia("editDataButton"), state = "normal") 272 tcltk::tkconfigure(getAmelia("plotHistButton"), state = "normal") 273 tcltk::tkconfigure(getAmelia("showLogButton"), state = "disabled") 274 fillMainTree() 275 276 277 ## Mark factors as ID by default. 278 279 classes <- sapply(getAmelia("amelia.data"), class) 280 factorVars <- which(classes == "factor" | 281 classes == "character") 282 283 if (!session) { 284 opt.holder <- vector("numeric",ncol(getAmelia("amelia.data"))) 285 names(opt.holder) <- getAmelia("varnames") 286 putAmelia("noms", opt.holder) 287 putAmelia("ords", opt.holder) 288 putAmelia("logs", opt.holder) 289 putAmelia("sqrt", opt.holder) 290 putAmelia("lgstc", opt.holder) 291 putAmelia("idvar", opt.holder) 292 putAmelia("lags", opt.holder) 293 putAmelia("leads", opt.holder) 294 295 boundsholder <- matrix(NA, nrow = ncol(getAmelia("amelia.data")), 296 ncol = 3) 297 boundsholder[,1] <- 1:ncol(getAmelia("amelia.data")) 298 rownames(boundsholder) <- getAmelia("varnames") 299 300 putAmelia("num.poly",tcltk::tclVar("0")) 301 putAmelia("intercs",tcltk::tclVar("0")) 302 putAmelia("priorsmat", NULL) 303 putAmelia("boundsmat", boundsholder) 304 putAmelia("max.resample", tcltk::tclVar("1000")) 305 306 putAmelia("outname", tcltk::tclVar(filestub)) 307 putAmelia("outnum", tcltk::tclVar("5")) 308 putAmelia("empri", tcltk::tclVar("0")) 309 putAmelia("tsvar", NULL) 310 putAmelia("csvar", NULL) 311 id.holder <- opt.holder 312 id.holder[factorVars] <- 1 313 putAmelia("idvar", id.holder) 314 for (i in factorVars) { 315 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], 316 "transform", "ID") 317 } 318 } else { 319 for (i in factorVars) { 320 if (all(getAmelia("idvar")[i]==0, 321 getAmelia("csvar")!=getAmelia("varnames")[i],getAmelia("noms")[i]==0)) { 322 tcltk::tcl(getAmelia("main.tree"), "item", getAmelia("varnames")[i], image = getAmelia("redFlagIcon")) 323 } 324 } 325 } 326 tcltk::tkentryconfigure(getAmelia("main.menu.options"), "Add Observations Priors...", state="normal") 327 328 tcltk::tkentryconfigure(getAmelia("main.menu.options"), "Numerical Options", state="normal") 329 ## add the filename and rows/cols to statusbar 330 tcltk::tkconfigure(getAmelia("statusbar.lab1b"), text = getAmelia("am.filename"), foreground = "blue") 331 tcltk::tkconfigure(getAmelia("statusbar.n"), text = paste(nrow(getAmelia("amelia.data"))), foreground = "blue") 332 tcltk::tkconfigure(getAmelia("statusbar.k"), text = paste(ncol(getAmelia("amelia.data"))), foreground = "blue") 333 334} 335 336save.session <- function() { 337 if (is.null(getAmelia("amelia.data"))) { 338 tcltk::tkmessageBox(parent=getAmelia("gui"), message="You must load a dataset before you can save a session.", icon="error", type="ok") 339 return(NULL) 340 } 341 file.select <- tcltk::tclvalue(tcltk::tkgetSaveFile(parent=getAmelia("gui"), 342 filetypes="{{RData files} {.RData}} {{All files} *}")) 343 putAmelia("session.flag", TRUE) 344 sessionList <- c("am.directory","amelia.data", "am.filename", 345 "am.filetype", "boundsmat", "csvar", "idvar", "lags", 346 "leads", "lgstc", "logs", "noms", "num.poly", 347 "ords", "outname.value", "outnum.value", "output.log", "outtype.value", "priorsmat", 348 "runState", "seed.value", "session.flag", "splinestime.value", "sqrt", "tol.value", 349 "tsvar", "empri.value", "intercs.value", 350 "max.resample.value", "ameliaObject") 351 putAmelia("empri.value", tcltk::tclvalue(getAmelia("empri"))) 352 putAmelia("intercs.value", tcltk::tclvalue(getAmelia("intercs"))) 353 putAmelia("max.resample.value", tcltk::tclvalue(getAmelia("max.resample"))) 354 putAmelia("outname.value", tcltk::tclvalue(getAmelia("outname"))) 355 putAmelia("outnum.value", tcltk::tclvalue(getAmelia("outnum"))) 356 putAmelia("outtype.value", tcltk::tclvalue(getAmelia("outtype"))) 357 putAmelia("seed.value", tcltk::tclvalue(getAmelia("seed"))) 358 putAmelia("tol.value", tcltk::tclvalue(getAmelia("tol"))) 359 putAmelia("splinestime.value", tcltk::tclvalue(getAmelia("splinestime"))) 360 361 save(list = sessionList, envir=ameliaEnv, file = file.select) 362 return(NULL) 363} 364 365load.session <- function() { 366 367 ## diaglog to get RData file 368 file.select <- tcltk::tclvalue(tcltk::tkgetOpenFile(parent=getAmelia("gui"), filetypes= 369 "{{RData files} {.RData}} {{All files} *}")) 370 if (nchar(file.select) <= 0) 371 return(NULL) 372 373 ## try loading the RData file and stop if it doesn't work 374 tryloadsess <- try(load(file=file.select, envir=ameliaEnv), silent=TRUE) 375 376 if (inherits(tryloadsess,"try-error")) { 377 tcltk::tkmessageBox(parent=getAmelia("gui"),message="Error loading session. This is not a valid session file.",icon="error",type="ok") 378 return(NULL) 379 } 380 381 ## make sure that the RData file loaded the right list 382 if (!("session.flag" %in% ls(ameliaEnv)) | !getAmelia("session.flag")) { 383 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Not an Amelia session file. Try again.",icon="error",type="ok") 384 return(NULL) 385 } 386 activateGUI(session = TRUE) 387 388 nn <- ncol(getAmelia("amelia.data")) 389 if (!is.null(getAmelia("tsvar"))) { 390 tcltk::tcl(getAmelia("main.tree"), "item", getAmelia("tsvar"), image = getAmelia("clockIcon")) 391 tcltk::tkentryconfigure(getAmelia("main.menu.options"),0, state="normal") 392 for (i in 1:nn) { 393 if (getAmelia("lags")[i] == 1) 394 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "lag", "X") 395 if (getAmelia("leads")[i] == 1) 396 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "lead", "X") 397 } 398 } 399 if (!is.null(getAmelia("csvar"))) { 400 tcltk::tcl(getAmelia("main.tree"), "item", getAmelia("csvar"), image = getAmelia("userIcon")) 401 tcltk::tkentryconfigure(getAmelia("main.menu.options"), 1, state="normal") 402 tcltk::tkentryconfigure(getAmelia("main.menu.options"), 1, variable = getAmelia("intercs")) 403 } 404 405 for (i in 1:nn) { 406 if (getAmelia("idvar")[i] == 1) 407 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "transform", "ID") 408 if (getAmelia("ords")[i] == 1) 409 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "transform", "Ordinal") 410 if (getAmelia("noms")[i] == 1) 411 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "transform", "Nominal") 412 if (getAmelia("logs")[i] == 1) 413 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "transform", "Log") 414 if (getAmelia("sqrt")[i] == 1) 415 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "transform", "Square Root") 416 if (getAmelia("lgstc")[i] == 1) 417 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "transform", "Logistic") 418 } 419 for (i in 1:nn) { 420 bdMin <- getAmelia("boundsmat")[i,2] 421 bdMax <- getAmelia("boundsmat")[i,3] 422 if (!is.na(bdMin)) { 423 treeBounds <- paste("[",bdMin,", ", bdMax,"]", sep = "") 424 } else { 425 treeBounds <- "" 426 } 427 tcltk::tkset(getAmelia("main.tree"), getAmelia("varnames")[i], "bounds", treeBounds) 428 } 429 430 tcltk::tcl("set", getAmelia("seed"), getAmelia("seed.value")) 431 tcltk::tcl("set", getAmelia("tol"), getAmelia("tol.value")) 432 tcltk::tcl("set", getAmelia("empri"), getAmelia("empri.value")) 433 tcltk::tcl("set", getAmelia("outname"), getAmelia("outname.value")) 434 tcltk::tcl("set", getAmelia("outnum"), getAmelia("outnum.value")) 435 tcltk::tcl("set", getAmelia("outtype"), getAmelia("outtype.value")) 436 tcltk::tcl("set", getAmelia("intercs"), getAmelia("intercs.value")) 437 tcltk::tcl("set", getAmelia("splinestime"), getAmelia("splinestime.value")) 438 tcltk::tcl("set", getAmelia("max.resample"), 439 getAmelia("max.resample.value")) 440 441 tcltk::tkgrid.remove(getAmelia("noimps.label")) 442 tcltk::tkgrid.remove(getAmelia("error.label")) 443 tcltk::tkgrid.remove(getAmelia("allgood.label")) 444 tcltk::tkgrid(getAmelia(paste(getAmelia("runState"),"label", sep = ".")), 445 row = 2, column = 7, sticky ="e", padx = 10) 446 if (getAmelia("runState") != "noimps") { 447 tcltk::tkentryconfigure(getAmelia("main.menu.output"), "Output Log", 448 state="normal") 449 tcltk::tkconfigure(getAmelia("showLogButton"), state = "normal") 450 } 451 if (getAmelia("runState") == "allgood") { 452 tcltk::tkentryconfigure(getAmelia("main.menu.output"), 0, 453 state = "normal") 454 tcltk::tkentryconfigure(getAmelia("main.menu.output"), 2, 455 state = "normal") 456 resave <- tcltk::tkmessageBox(parent = getAmelia("gui"), message = 457 "Re-save imputed data sets to the working directory?", icon = 458 "question", default = "yes", type = "yesno") 459 if (tcltk::tclvalue(resave) == "yes") { 460 amelia.save(getAmelia("ameliaObject"), 461 tcltk::tclvalue(getAmelia("outname")), as.numeric(tcltk::tclvalue(getAmelia("outnum")))) 462 } 463 464 } 465 return(NULL) 466} 467 468 469run.amelia <- function() { 470 save.type <- as.numeric(tcltk::tclvalue(getAmelia("outtype"))) 471 if (file.access(getwd(), mode = 2) == -1 & !(save.type %in% c(0,6))) 472 { 473 tcltk::tkmessageBox(parent = getAmelia("gui"), message = 474 "The current working directory is not writable. Please select a different working directory or chose to not save the imputed data sets.", 475 type ="ok") 476 return(NULL) 477 478 } 479 480 ## Let's not allow people to overwrite their data. 481 temp.list <- strsplit(getAmelia("am.filename"),"/")[[1]] 482 filename <- temp.list[length(temp.list)] 483 outfiles <- paste(tcltk::tclvalue(getAmelia("outname")), 484 1:as.numeric(tcltk::tclvalue(getAmelia("outnum"))), sep 485 ="") 486 save.type <- as.numeric(tcltk::tclvalue(getAmelia("outtype"))) 487 exten <- switch(save.type, "csv","txt","dta","dta","RData") 488 outfiles <- paste(outfiles, exten, sep = ".") 489 outfiles <- paste(paste(temp.list[-length(temp.list)], collapse = 490 "/"), outfiles, sep = "/") 491 if (getAmelia("am.filename") %in% outfiles) { 492 tcltk::tkmessageBox(parent = getAmelia("gui"), message = 493 "Current settings would overwrite the original data. Please change the output file name.", 494 icon = "error", type ="ok") 495 return(NULL) 496 } 497 498 499 ts <- getAmelia("tsvar") 500 cs <- getAmelia("csvar") 501 nn <- ncol(getAmelia("amelia.data")) 502 503 am.intercs <- as.logical(as.numeric(tcltk::tclvalue(getAmelia("intercs")))) 504 sptime <- as.numeric(tcltk::tclvalue(getAmelia("splinestime"))) 505 506 if (sptime == 0) 507 if (am.intercs == FALSE) 508 sptime <- NULL 509 if (is.null(ts)) 510 sptime <- NULL 511 if (is.null(cs)) 512 am.intercs <- FALSE 513 514 id <- getAmelia("varnames")[getAmelia("idvar")==1] 515 ord <- getAmelia("varnames")[getAmelia("ords")==1] 516 nom <- getAmelia("varnames")[getAmelia("noms")==1] 517 logs <- getAmelia("varnames")[getAmelia("logs")==1] 518 sqrts <- getAmelia("varnames")[getAmelia("sqrt")==1] 519 lgstc <- getAmelia("varnames")[getAmelia("lgstc")==1] 520 amlags<- getAmelia("varnames")[getAmelia("lags")==1] 521 amfut <- getAmelia("varnames")[getAmelia("leads")==1] 522 523 if (length(id) == 0) id <- NULL 524 if (length(ord) == 0) ord <- NULL 525 if (length(nom) == 0) nom <- NULL 526 if (length(logs) == 0) logs <- NULL 527 if (length(sqrts)== 0) sqrts<- NULL 528 if (length(lgstc)== 0) lgstc<- NULL 529 if (length(amlags)==0) amlags <- NULL 530 if (length(amfut)== 0) amfut<- NULL 531 532 pmat <- getAmelia("priorsmat") 533 colnames(pmat) <- NULL 534 rownames(pmat) <- NULL 535 536 bdmat <- getAmelia("boundsmat") 537 colnames(bdmat) <- NULL 538 rownames(bdmat) <- NULL 539 bdmat <- bdmat[!is.na(bdmat[,2]) & !is.na(bdmat[,3]),,drop=FALSE] 540 if (nrow(bdmat) == 0) 541 bdmat <- NULL 542 543 tol <- as.numeric(tcltk::tclvalue(getAmelia("tol"))) 544 max.re <- as.numeric(tcltk::tclvalue(getAmelia("max.resample"))) 545 num.imp <- as.numeric(tcltk::tclvalue(getAmelia("outnum"))) 546 emp <- as.numeric(tcltk::tclvalue(getAmelia("empri"))) 547 if (!is.na(as.numeric(tcltk::tclvalue(getAmelia("seed"))))) 548 set.seed(as.numeric(tcltk::tclvalue(getAmelia("seed")))) 549 tcltk::tkgrid.remove(getAmelia("noimps.label")) 550 tcltk::tkgrid.remove(getAmelia("error.label")) 551 tcltk::tkgrid.remove(getAmelia("allgood.label")) 552 tcltk::tkgrid(getAmelia("runAmeliaProgress"), row = 2, column = 7, 553 sticky ="e", padx = 10) 554 amcall <- substitute(amelia(x = getAmelia("amelia.data"), m = num.imp, 555 idvars = id, ts = ts, cs= cs, 556 priors = pmat, lags = amlags, empri = emp, 557 intercs = am.intercs, leads = amfut, 558 splinetime = sptime, 559 logs = logs, sqrts = sqrts, lgstc = lgstc, 560 ords = ord, noms = nom, bounds = bdmat, 561 max.resample = max.re, tolerance= tol)) 562 563 putAmelia("output.log", c(getAmelia("output.log"), 564 sub(" ","\n ",deparse(amcall, control=NULL, width.cutoff=60)),"\n\n")) 565 putAmelia("wdForLastImputation", getwd()) 566 ## run amelia! or at least try, and put the output in a list 567 ## the name of the list will be the output name set by user 568 output.connection <- textConnection(".Output", open="w", local = TRUE) 569 sink(output.connection, type="output") 570 putAmelia("ameliaObject", 571 try(amelia.default(x = getAmelia("amelia.data"), 572 m = as.numeric(tcltk::tclvalue(getAmelia("outnum"))), 573 p2s = 1, 574 idvars = id, 575 ts = ts, 576 cs = cs, 577 priors = pmat, 578 lags = amlags, 579 empri = as.numeric(tcltk::tclvalue(getAmelia("empri"))), 580 intercs = am.intercs, 581 leads = amfut, 582 splinetime = sptime, 583 frontend = TRUE, 584 logs = logs, 585 sqrts = sqrts, 586 lgstc = lgstc, 587 ords = ord, 588 noms = nom, 589 bounds = bdmat, 590 max.resample = as.numeric(tcltk::tclvalue(getAmelia("max.resample"))), 591 tolerance= as.numeric(tcltk::tclvalue(getAmelia("tol")))), 592 silent=TRUE)) 593 sink(type = "output") 594 putAmelia("output.log", c(getAmelia("output.log"), paste(textConnectionValue(output.connection), "\n"))) 595 596 tcltk::tkgrid.remove(getAmelia("runAmeliaProgress")) 597 tcltk::tkconfigure(getAmelia("runAmeliaProgress"), value = 0) 598 ## check for errors in the process. 599 if (inherits(getAmelia("ameliaObject"),"try-error")) { 600 putAmelia("output.log", c(getAmelia("output.log"),"\nThere was an unexpected error in the execution of Amelia. \nDouble check all inputs for errors and take note of the error message:\n\n")) 601 putAmelia("output.log", c(getAmelia("output.log"),paste(getAmelia("ameliaObject")))) 602 #tcltk::tkconfigure(getAmelia("pass.fail.label"), foreground = "red") 603 #tmp <- getAmelia("pass.fail") 604 #tcltk::tclvalue(tmp) <- "Error! See log." 605 show.output.log() 606 tcltk::tkentryconfigure(getAmelia("main.menu.output"), 1, state = 607 "normal") 608 tcltk::tkconfigure(getAmelia("showLogButton"), state = "normal") 609 tcltk::tkgrid(getAmelia("error.label"), row = 2, column = 7, 610 sticky ="e", padx = 10) 611 putAmelia("runState", "error") 612 return(NULL) 613 } 614 if (all(getAmelia("ameliaObject")$code!=c(1,2))) { 615 putAmelia("output.log", c(getAmelia("output.log"),"\n")) 616 putAmelia("output.log", c(getAmelia("output.log"),paste("Amelia Error Code:", 617 getAmelia("ameliaObject")[[1]],"\n", 618 getAmelia("ameliaObject")[[2]]))) 619 #tcltk::tkconfigure(getAmelia("pass.fail.label"), foreground = "red") 620 #tmp <- getAmelia("pass.fail") 621 #tcltk::tclvalue(tmp) <- "Error! See log." 622 show.output.log() 623 tcltk::tkentryconfigure(getAmelia("main.menu.output"), 1, state = 624 "normal") 625 tcltk::tkconfigure(getAmelia("showLogButton"), state = "normal") 626 tcltk::tkgrid(getAmelia("error.label"), row = 2, column = 7, 627 sticky ="e", padx = 10) 628 putAmelia("runState", "error") 629 } else { 630 putAmelia("output.log", c(getAmelia("output.log"),"Amelia has run successfully.\n")) 631 tcltk::tkentryconfigure(getAmelia("main.menu.output"), 0, state = "normal") 632 tcltk::tkentryconfigure(getAmelia("main.menu.output"), 1, state = 633 "normal") 634 tcltk::tkentryconfigure(getAmelia("main.menu.output"), 2, state = "normal") 635 tcltk::tkconfigure(getAmelia("showLogButton"), state = "normal") 636 amelia.save(getAmelia("ameliaObject"), 637 tcltk::tclvalue(getAmelia("outname")), as.numeric(tcltk::tclvalue(getAmelia("outnum")))) 638 tcltk::tkgrid(getAmelia("allgood.label"), row = 2, column = 7, 639 sticky ="e", padx = 10) 640 putAmelia("runState", "allgood") 641 } 642 643} 644 645amelia.save <- function(out,outname,m) { 646 save.type <- as.numeric(tcltk::tclvalue(getAmelia("outtype"))) 647 if (save.type == 1) { 648 write.amelia(out, file.stem = outname, format = "csv", 649 row.names = FALSE) 650 } 651 652 if (save.type == 2) { 653 write.amelia(out, file.stem = outname, extension = "txt", 654 format = "table", row.names = FALSE) 655 } 656 if (save.type == 3) { 657 write.amelia(out, file.stem = outname, format = "dta", 658 version = 6) 659 } 660 if (save.type == 4) { 661 write.amelia(out, file.stem = outname, format = "dta", 662 version = 7) 663 } 664 if (save.type == 5) { 665 write.amelia(out, file.stem = outname, format = "dta", 666 version = 8) 667 } 668 if (save.type == 6) { 669 write.amelia(out, file.stem = outname, format = "dta", 670 version = 10) 671 } 672 if (save.type == 7) { 673 write.amelia(out, file.stem = outname, format = "dta", 674 separate = FALSE, version = 10) 675 } 676 if (save.type == 8) { 677 save(list = "ameliaObject", envir = ameliaEnv, 678 file = paste(outname, ".RData", sep = "")) 679 } 680} 681 682set.out<-function(...) { 683 putAmelia("output.select",as.numeric(tcltk::tkget(getAmelia("output.drop.box")))) 684} 685 686setTS <- function() { 687 tsvartemp <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"selection")), " ")[[1]] 688 if (length(tsvartemp) > 1) { 689 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Only one variable can be set as the times-series variable.",icon="error",type="ok") 690 return(NULL) 691 } 692 if (!is.null(getAmelia("csvar"))) { 693 if (getAmelia("csvar") == tsvartemp) { 694 tcltk::tkmessageBox(parent=getAmelia("gui"), message="A variable cannot be both the time-series and cross-section index.",icon="error",type="ok") 695 return(NULL) 696 } 697 } 698 if (!(sapply(getAmelia("amelia.data"), class)[tsvartemp] %in% c("numeric","integer"))) { 699 tcltk::tkmessageBox(parent=getAmelia("gui"), 700 message="The time-series index must be numeric.",icon="error",type="ok") 701 return(NULL) 702 } 703 children <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"children","")), " ")[[1]] 704 for(i in setdiff(children, getAmelia("csvar"))) 705 tcltk::tcl(getAmelia("main.tree"), "item", i , image="") 706 707 tcltk::tcl(getAmelia("main.tree"), "item", tsvartemp, image = getAmelia("clockIcon")) 708 putAmelia("tsvar", tsvartemp) 709 tcltk::tkentryconfigure(getAmelia("main.menu.options"),0, state="normal") 710 dropTrans() 711} 712 713unsetTS <- function() { 714 tsvartemp <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"selection")), " ")[[1]] 715 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you unset the time-series variable, you will lose any time-series settings such as lags, leads, or polynomials of time. Unset the time-series variable?",icon="question",type="yesno") 716 if (tcltk::tclvalue(sure) == "no") 717 return(NULL) 718 719 tcltk::tcl(getAmelia("main.tree"), "item", tsvartemp, image = "") 720 putAmelia("tsvar", NULL) 721 tcltk::tkentryconfigure(getAmelia("main.menu.options"),0, state="disabled") 722 putAmelia("lags",vector("numeric",ncol(getAmelia("amelia.data")))) 723 putAmelia("leads",vector("numeric",ncol(getAmelia("amelia.data")))) 724 children <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"children","")), " ")[[1]] 725 for(i in children) { 726 tcltk::tkset(getAmelia("main.tree"), i, "lag", "") 727 tcltk::tkset(getAmelia("main.tree"), i, "lead", "") 728 } 729} 730 731unsetCS <- function() { 732 csvartemp <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"selection")), " ")[[1]] 733 sure<-tcltk::tkmessageBox(parent=getAmelia("gui"), message="If you unset the cross-section variable, you will lose any cross-section settings. Unset the cross-section variable?",icon="question",type="yesno") 734 if (tcltk::tclvalue(sure) == "no") 735 return(NULL) 736 737 tcltk::tcl(getAmelia("main.tree"), "item", csvartemp, image = "") 738 putAmelia("csvar", NULL) 739 tcltk::tkentryconfigure(getAmelia("main.menu.options"),0, state="normal") 740 if (is.factor(getAmelia("amelia.data")[,csvartemp]) | 741 is.character(getAmelia("amelia.data")[,csvartemp])) { 742 tcltk::tcl(getAmelia("main.tree"), "item", csvartemp, image = getAmelia("redFlagIcon")) 743 } 744} 745 746setCS <- function() { 747 csvartemp <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"selection")), " ")[[1]] 748 if (length(csvartemp) > 1) { 749 tcltk::tkmessageBox(parent=getAmelia("gui"), message="Only one variable can be set as the cross-section variable.",icon="error",type="ok") 750 return(NULL) 751 } 752 if (!is.null(getAmelia("tsvar"))) { 753 if (getAmelia("tsvar") == csvartemp) { 754 tcltk::tkmessageBox(parent=getAmelia("gui"), message="A variable cannot be both the time-series and cross-section index.",icon="error",type="ok") 755 return(NULL) 756 } 757 } 758 759 if (!is.null(getAmelia("csvar"))) { 760 if (is.factor(getAmelia("amelia.data")[,getAmelia("csvar")]) | 761 is.character(getAmelia("amelia.data")[,getAmelia("csvar")])) { 762 tcltk::tcl(getAmelia("main.tree"), "item", getAmelia("csvar"), image = getAmelia("redFlagIcon")) 763 } else { 764 tcltk::tcl(getAmelia("main.tree"), "item", getAmelia("csvar"), image = "") 765 } 766 } 767 768 dropTrans() 769 tcltk::tcl(getAmelia("main.tree"), "item", csvartemp, image = getAmelia("userIcon")) 770 putAmelia("csvar", csvartemp) 771 tcltk::tkentryconfigure(getAmelia("main.menu.options"),1,state="normal") 772 tcltk::tkentryconfigure(getAmelia("main.menu.options"), 1, variable = getAmelia("intercs")) 773 774} 775 776 777fillMainTree <- function() { 778 children <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"children","")), " ")[[1]] 779 tcltk::tkdelete(getAmelia("main.tree"), children) 780 for (i in names(getAmelia("amelia.data"))) { 781 782 if (is.factor(getAmelia("amelia.data")[,i]) | 783 is.character(getAmelia("amelia.data")[,i])) { 784 vals <- c("","","","","(factor)","...","...","...") 785 vals <- c(vals,paste(sum(is.na(getAmelia("amelia.data")[,i])), 786 nrow(getAmelia("amelia.data")), sep="/")) 787 } else { 788 vals <- c(min(getAmelia("amelia.data")[,i],na.rm=T), max(getAmelia("amelia.data")[,i],na.rm=T), 789 mean(getAmelia("amelia.data")[,i],na.rm=T), sd(getAmelia("amelia.data")[,i],na.rm=T)) 790 vals <- signif(vals, digits = 4) 791 vals <- c("","","","", vals, paste(sum(is.na(getAmelia("amelia.data")[,i])), 792 nrow(getAmelia("amelia.data")), sep="/")) 793 } 794 tcltk::tkinsert(getAmelia("main.tree"),"","end", id = i,tag="normal",text 795 = i, values = vals) 796 } 797 bandTree() 798 return() 799} 800 801 802#' Interactive GUI for Amelia 803#' 804#' Brings up the AmeliaView graphical interface, which allows users to load datasets, 805#' manage options and run Amelia from a traditional windowed environment. 806#' 807#' @details 808#' Requires the tcltk package. 809#' 810AmeliaView<-function() { 811 812 ##Preamble 813 requireNamespace("tcltk") || stop("The package 'tcltk' is required") 814 815 if (.Platform$OS.type != "windows") { 816 tcltk::tcl("ttk::style", "theme", "use", "clam") 817 tcltk::tkfont.configure("TkHeadingFont", weight="normal") 818 tcltk::tkfont.configure("TkCaptionFont", weight="normal") 819 } 820 821 ## If the current working directory is not writable, move to a 822 ## sensible default locations: the HOME dir 823 if (file.access(getwd(), mode = 2) == -1) { 824 if (file.access(Sys.getenv("HOME"), mode = 0) == 0 & 825 file.access(Sys.getenv("HOME"), mode = 2) == 0) { 826 setwd(Sys.getenv("HOME")) 827 } 828 829 } 830 tcltk::tclServiceMode(on=FALSE) 831 putAmelia("outname", tcltk::tclVar("outdata")) 832 putAmelia("outnum", tcltk::tclVar("5")) 833 putAmelia("empri", tcltk::tclVar("0")) 834 putAmelia("tol", tcltk::tclVar("0.0001")) 835 putAmelia("amelia.data",NULL) 836 putAmelia("am.filename",NULL) 837 putAmelia("varnames", NULL) 838 putAmelia("tsvar", NULL) 839 putAmelia("csvar", NULL) 840 putAmelia("varmin", NULL) 841 putAmelia("varmax", NULL) 842 putAmelia("runState", "noimps") 843 putAmelia("session.flag", FALSE) 844 putAmelia("intercs",tcltk::tclVar("0")) 845 putAmelia("splinestime",tcltk::tclVar("0")) 846 putAmelia("outtype", tcltk::tclVar("1")) 847 putAmelia("max.resample", tcltk::tclVar("1000")) 848 putAmelia("inname", tcltk::tclVar("")) 849 putAmelia("seed", tcltk::tclVar("")) 850 putAmelia("output.log", NULL) 851 putAmelia("boundMin", tcltk::tclVar("")) 852 putAmelia("boundMax", tcltk::tclVar("")) 853 putAmelia("wdForLastImputation", getwd()) 854 855 output.types <- c("(no save)", 856 "CSV", 857 "Tab Delimited", 858 "Stata 6", 859 "Stata 7", 860 "Stata 8/9", 861 "Stata 10+", 862 "Stata 10+ (stacked)", 863 "RData") 864 ampath <- find.package(package = "Amelia")[1] 865 ameliaFile <- file.path(ampath, "gui/gallery19.gif") 866 goFile <- file.path(ampath, "gui/action_go.gif") 867 tableFile <- file.path(ampath, "gui/table.gif") 868 rFile <- file.path(ampath, "gui/page-R.gif") 869 dtaFile <- file.path(ampath, "gui/page_dta.gif") 870 spssFile <- file.path(ampath, "gui/page_spss.gif") 871 clockFile <- file.path(ampath, "gui/icon_clock.gif") 872 userFile <- file.path(ampath, "gui/icon_user.gif") 873 upFile <- file.path(ampath, "gui/arrow_up.gif") 874 downFile <- file.path(ampath, "gui/arrow_down.gif") 875 worldFile <- file.path(ampath, "gui/icon_world.gif") 876 pageTextFile <- file.path(ampath, "gui/page_text.gif") 877 pageEditFile <- file.path(ampath, "gui/page_edit.gif") 878 histFile <- file.path(ampath, "gui/histogram.gif") 879 saveFile <- file.path(ampath, "gui/action_save.gif") 880 pageUpFile <- file.path(ampath, "gui/page_up.gif") 881 redStopFile <- file.path(ampath, "gui/action_stop.gif") 882 redFlagFile <- file.path(ampath, "gui/flag_red.gif") 883 greenCheckFile <- file.path(ampath, "gui/icon_accept.gif") 884 885 putAmelia("ameliaPic", tcltk::tkimage.create("photo", file=ameliaFile)) 886 putAmelia("action.go.icon", tcltk::tkimage.create("photo", file = goFile)) 887 putAmelia("tablePic", tcltk::tkimage.create("photo", file = tableFile)) 888 putAmelia("rPic", tcltk::tkimage.create("photo", file = rFile)) 889 putAmelia("dtaPic", tcltk::tkimage.create("photo", file = dtaFile)) 890 putAmelia("spssPic", tcltk::tkimage.create("photo", file = spssFile)) 891 putAmelia("clockIcon", tcltk::tkimage.create("photo", file = clockFile)) 892 putAmelia("userIcon", tcltk::tkimage.create("photo", file = userFile)) 893 putAmelia("worldIcon", tcltk::tkimage.create("photo", file = worldFile)) 894 putAmelia("upArrowIcon", tcltk::tkimage.create("photo", file = upFile)) 895 putAmelia("downArrowIcon", tcltk::tkimage.create("photo", file = downFile)) 896 putAmelia("histIcon", tcltk::tkimage.create("photo", file = histFile)) 897 putAmelia("saveIcon", tcltk::tkimage.create("photo", file = saveFile)) 898 putAmelia("pageUpIcon", tcltk::tkimage.create("photo", file = pageUpFile)) 899 putAmelia("redFlagIcon", tcltk::tkimage.create("photo", file = 900 redFlagFile)) 901 putAmelia("redStopIcon", tcltk::tkimage.create("photo", file = redStopFile)) 902 putAmelia("greenCheckIcon", tcltk::tkimage.create("photo", file = greenCheckFile)) 903 putAmelia("pageTextIcon", tcltk::tkimage.create("photo", file = 904 pageTextFile)) 905 putAmelia("pageEditIcon", tcltk::tkimage.create("photo", file = pageEditFile)) 906 putAmelia("gui", tcltk::tktoplevel()) 907 tcltk::tkwm.title(getAmelia("gui"), "AmeliaView") 908 tcltk::tkwm.protocol(getAmelia("gui"),"WM_DELETE_WINDOW", function() main.close()) 909 tcltk::tkwm.geometry(getAmelia("gui"), "800x500") 910 ##Menu 911 putAmelia("main.menu", tcltk::tkmenu(getAmelia("gui"))) 912 putAmelia("main.menu.file", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 913 putAmelia("main.menu.demo", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 914 putAmelia("main.menu.import", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 915 putAmelia("main.menu.options", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 916 putAmelia("main.menu.splines", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 917 putAmelia("main.menu.output", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 918 putAmelia("main.menu.help", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 919 putAmelia("main.menu.variables", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0, 920 postcommand = variableOptionsPost)) 921 putAmelia("main.menu.trans", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 922 putAmelia("main.menu.outfile", tcltk::tkmenu(getAmelia("main.menu"), tearoff=0)) 923 tcltk::tkadd(getAmelia("main.menu.file"),"command",label="Load R Data File...",command=function()loadRData(), 924 underline = 5) 925 tcltk::tkadd(getAmelia("main.menu.import"),"command",label="Import comma-separated value data...", 926 command=loadCSV, underline = 7) 927 tcltk::tkadd(getAmelia("main.menu.import"),"command",label="Import tab-delimited data...", 928 command=loadTAB, underline = 7) 929 tcltk::tkadd(getAmelia("main.menu.import"),"command",label="Import Stata dta file...", 930 command=loadStata, underline = 13) 931 tcltk::tkadd(getAmelia("main.menu.import"),"command",label="Import SPSS data...", 932 command=loadSPSS, underline = 7) 933 tcltk::tkadd(getAmelia("main.menu.import"),"command",label="Import SAS Transport data...", 934 command=loadSAS, underline = 8) 935 tcltk::tkadd(getAmelia("main.menu.file"),"cascade",menu=getAmelia("main.menu.import"),label="Import Data", 936 underline = 0) 937 tcltk::tkadd(getAmelia("main.menu.demo"),"command",label="africa", command=function() 938 loadDemo(name="africa"), underline = 0) 939 tcltk::tkadd(getAmelia("main.menu.demo"),"command",label="freetrade", command=function() 940 loadDemo(name="freetrade"), underline = 0) 941 tcltk::tkadd(getAmelia("main.menu.file"),"cascade",menu=getAmelia("main.menu.demo"),label="Load Package Data", 942 underline = 5) 943 tcltk::tkadd(getAmelia("main.menu.file"),"command",command = 944 setWorkingDir,label="Set Working Directory...", underline = 4) 945 tcltk::tkadd(getAmelia("main.menu.file"),"command",label="Edit Data...", 946 command=function(){putAmelia("amelia.data", 947 edit(getAmelia("amelia.data")));updateTreeStats()},state="disabled", 948 underline = 0) 949 tcltk::tkadd(getAmelia("main.menu.file"),"separator") 950 tcltk::tkadd(getAmelia("main.menu.file"),"command",label="Load Session...",command=function()load.session(), 951 underline = 0) 952 tcltk::tkadd(getAmelia("main.menu.file"),"command",label="Save Session...",command=function()save.session(), 953 state="disabled", underline = 0) 954 tcltk::tkadd(getAmelia("main.menu.file"),"separator") 955 tcltk::tkadd(getAmelia("main.menu.file"),"command",label="Quit Amelia",command=function()main.close(), 956 underline = 0) 957 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = 958 "Set as Time-Series Variable", command = setTS, state = "disabled", 959 underline = 0) 960 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = 961 "Set as Cross-Section Variable", command = setCS, state = 962 "disabled", underline = 7) 963 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = 964 "Unset as Time-Series Variable", command = unsetTS, state = 965 "disabled", underline = 0) 966 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = 967 "Unset as Cross-Section Variable", command = unsetCS, state = 968 "disabled", underline = 23) 969 tcltk::tkadd(getAmelia("main.menu.variables"),"separator") 970 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = "Add Lag", command = 971 function() addLag(), state = "disabled", underline = 0) 972 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = "Add Lead", command = 973 function() addLead(), state = "disabled", underline = 4) 974 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = "Remove Lag", command 975 = function() dropLag(), state = "disabled", underline = 0) 976 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = "Remove Lead", command 977 = function() dropLead(), state = "disabled", underline = 1) 978 tcltk::tkadd(getAmelia("main.menu.variables"),"separator") 979 980 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = 981 "Plot Histogram(s) of Selected", command = plotHist, state = 982 "disabled", underline = 0) 983 tcltk::tkadd(getAmelia("main.menu.trans"), "command", label = "Log", command = 984 function(x) setTrans("logs"), underline = 0) 985 tcltk::tkadd(getAmelia("main.menu.trans"), "command", label = "Square Root", command = 986 function(x) setTrans("sqrt"), underline = 0) 987 tcltk::tkadd(getAmelia("main.menu.trans"), "command", label = "Logistic", command = 988 function(x) setTrans("lgstc"), underline = 1) 989 tcltk::tkadd(getAmelia("main.menu.trans"), "command", label = "Nominal", command = 990 function(x) setTrans("noms"), underline = 0) 991 tcltk::tkadd(getAmelia("main.menu.trans"), "command", label = "Ordinal", command = 992 function(x) setTrans("ords"), underline = 0) 993 tcltk::tkadd(getAmelia("main.menu.trans"), "command", label = "ID Variable", command = 994 function(x) setTrans("idvar"), underline = 0) 995 tcltk::tkadd(getAmelia("main.menu.variables"), "cascade", label = 996 "Add Transformation...", menu = getAmelia("main.menu.trans"), state = "disabled", 997 underline = 4) 998 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = 999 "Remove Transformations", command = dropTrans, state = 1000 "disabled", underline = 2) 1001 tcltk::tkadd(getAmelia("main.menu.variables"),"separator") 1002 tcltk::tkadd(getAmelia("main.menu.variables"), "command", label = 1003 "Add or Edit Bounds", command = addBounds, state = "disabled", 1004 underline = 12) 1005 for (i in 0:10) 1006 tcltk::tkadd(getAmelia("main.menu.splines"), "radiobutton", variable = 1007 getAmelia("splinestime"), label = paste(i,"knots"), value = i, 1008 underline = 0) 1009 tcltk::tkadd(getAmelia("main.menu.options"), "cascade", label = 1010 "Splines of Time with...", menu = getAmelia("main.menu.splines"), 1011 state="disabled", underline = 0) 1012 tcltk::tkadd(getAmelia("main.menu.options"), "checkbutton", label = 1013 "Interact Spline With Cross-Section?", variable = 1014 getAmelia("intercs"), onvalue=1,offvalue=0, state="disabled", 1015 underline = 0) 1016 1017 tcltk::tkadd(getAmelia("main.menu.options"),"separator") 1018 tcltk::tkadd(getAmelia("main.menu.options"),"command", label = 1019 "Add Observations Priors...", command = gui.pri.setup, 1020 state="disabled", underline = 17) 1021 tcltk::tkadd(getAmelia("main.menu.options"), "separator") 1022 tcltk::tkadd(getAmelia("main.menu.options"), "command", label = "Numerical Options", 1023 command = buildNumericalOptions, state = "disabled", underline 1024 = 0) 1025 tcltk::tkadd(getAmelia("main.menu.options"), "command", label = "Draw Missingness Map", 1026 command = drawMissMap, state="disabled", underline = 5) 1027 tcltk::tkadd(getAmelia("main.menu.options"), "command", label = "Output File Options...", 1028 command = buildOutputOptions, state = "disabled", underline = 0) 1029 for (i in 1:length(output.types)) { 1030 tcltk::tkadd(getAmelia("main.menu.outfile"), "radiobutton", variable = 1031 getAmelia("outtype"), label = output.types[i], value = i-1) 1032 } 1033 tcltk::tkadd(getAmelia("main.menu.options"), "cascade", label = "Output File Type...", 1034 menu = getAmelia("main.menu.outfile"), state = "disabled", underline = 7) 1035 tcltk::tkadd(getAmelia("main.menu.output"),"command", label = 1036 "Imputation Diagnostics...", command = gui.diag.setup, 1037 state="disabled", underline = 11) 1038 tcltk::tkadd(getAmelia("main.menu.output"),"command", label = "Output Log", command = 1039 show.output.log, state="disabled", underline = 0) 1040 tcltk::tkadd(getAmelia("main.menu.output"),"command", label = 1041 "Open Folder Containing Imputated Data", command = 1042 showImputedFiles, state="disabled", underline = 12) 1043 tcltk::tkadd(getAmelia("main.menu.help"),"command",label="Amelia Website",command= 1044 function()browseURL("http://gking.harvard.edu/amelia/"), 1045 underline = 7) 1046 tcltk::tkadd(getAmelia("main.menu.help"),"command",label="Documentation",command= 1047 function() browseURL("http://gking.harvard.edu/amelia/docs/"), 1048 underline = 0) 1049 1050 tcltk::tkadd(getAmelia("main.menu.help"),"command",label="About...",command= 1051 function()buildAboutDialog(), underline = 0) 1052 1053 tcltk::tkadd(getAmelia("main.menu"),"cascade",label="File", 1054 menu = getAmelia("main.menu.file"), underline = 0) 1055 tcltk::tkadd(getAmelia("main.menu"),"cascade",label="Variables", 1056 menu = getAmelia("main.menu.variables"), underline = 0) 1057 tcltk::tkadd(getAmelia("main.menu"),"cascade",label="Options", 1058 menu = getAmelia("main.menu.options"), underline = 0) 1059 tcltk::tkadd(getAmelia("main.menu"),"cascade",label="Output", 1060 menu = getAmelia("main.menu.output"), underline = 1) 1061 tcltk::tkadd(getAmelia("main.menu"),"cascade",label="Help", 1062 menu = getAmelia("main.menu.help"), underline = 0) 1063 tcltk::tkconfigure(getAmelia("gui"), menu = getAmelia("main.menu")) 1064 1065 1066 ## Welcome Screen 1067 putAmelia("gui.welcome", tcltk::ttkframe(getAmelia("gui"))) 1068 ameliaPicLabel <- tcltk::ttklabel(getAmelia("gui.welcome"), relief = "groove", image = getAmelia("ameliaPic")) 1069 loadRButton <- tcltk::ttkbutton(getAmelia("gui.welcome"), text = "Load R Data", 1070 image = getAmelia("rPic"), compound = "top", 1071 command = loadRData) 1072 loadCSVButton <- tcltk::ttkbutton(getAmelia("gui.welcome"), text = "Import CSV", 1073 image = getAmelia("tablePic"), compound = "top", 1074 command = loadCSV) 1075 loadStataButton <- tcltk::ttkbutton(getAmelia("gui.welcome"), text = "Import STATA", 1076 image = getAmelia("dtaPic"), compound = "top", 1077 command = loadStata) 1078 loadSPSSButton <- tcltk::ttkbutton(getAmelia("gui.welcome"), text = "Import SPSS", 1079 image = getAmelia("spssPic"), compound = "top", 1080 command = loadSPSS) 1081 loadDemoButton <- tcltk::ttkbutton(getAmelia("gui.welcome"), text = "Load Demo", 1082 image = getAmelia("tablePic"), compound = "top", 1083 command = function () loadDemo(name = "africa")) 1084 1085 tcltk::tkgrid(ameliaPicLabel, row = 0, column = 0, columnspan = 6, padx = 1086 10, pady = 10) 1087 tcltk::tkgrid(tcltk::ttklabel(getAmelia("gui.welcome"), 1088 text=paste("Welcome to AmeliaView ",packageDescription("Amelia", 1089 fields="Version"), "!", sep="")), 1090 row = 1, column = 0, columnspan = 6, padx = 10, pady = 10) 1091 tcltk::tkgrid(tcltk::ttklabel(getAmelia("gui.welcome"), text="Please load a dataset:"), 1092 row = 2, column = 0, columnspan = 6, padx = 10, pady = 10) 1093 tcltk::tkgrid(loadRButton, row = 3, column = 0, padx = 10, pady = 10) 1094 tcltk::tkgrid(loadCSVButton, row = 3, column = 1, padx = 10, pady = 10) 1095 tcltk::tkgrid(loadStataButton, row = 3, column = 2, padx = 10, pady = 10) 1096 tcltk::tkgrid(loadSPSSButton, row = 3, column = 3, padx = 10, pady = 10) 1097 tcltk::tkgrid(loadDemoButton, row = 3, column = 4, padx = 10, pady = 10) 1098 tcltk::tkgrid(getAmelia("gui.welcome"), row = 0, column = 0) 1099 ##Frame 1100 putAmelia("gui.skel", tcltk::ttkpanedwindow(getAmelia("gui"), orient = "vertical")) 1101 1102############### 1103### Toolbar ### 1104############### 1105 1106 toolbar <- tcltk::ttkframe(getAmelia("gui.skel")) 1107 putAmelia("loadSessionButton", 1108 tcltk::ttkbutton(toolbar, text = "Load Session", 1109 command = load.session, image = getAmelia("pageUpIcon"), compound = "top", 1110 style="Toolbutton")) 1111 putAmelia("saveSessionButton", 1112 tcltk::ttkbutton(toolbar, text = "Save Session", 1113 command = save.session, image = getAmelia("saveIcon"), compound = "top", 1114 style="Toolbutton")) 1115 putAmelia("plotHistButton", 1116 tcltk::ttkbutton(toolbar, text = "Plot Histogram", state = 1117 "disabled", command = plotHist, image = getAmelia("histIcon"), compound = "top", 1118 style="Toolbutton")) 1119 putAmelia("editDataButton", 1120 tcltk::ttkbutton(toolbar, text = "Edit Data", state = "disabled", 1121 command = function(){putAmelia("amelia.data", edit(getAmelia("amelia.data")));updateTreeStats()}, image = 1122 getAmelia("pageEditIcon"), compound = "top", 1123 style="Toolbutton")) 1124 putAmelia("missmapButton", 1125 tcltk::ttkbutton(toolbar, text = "Missingness Map", state = "disabled", 1126 command = drawMissMap, image = 1127 getAmelia("worldIcon"), compound = "top", 1128 style="Toolbutton")) 1129 putAmelia("output.run", 1130 tcltk::ttkbutton(toolbar,text="Impute!", state = "disabled", 1131 command = run.amelia, image = 1132 getAmelia("action.go.icon"), compound = "top", 1133 style="Toolbutton")) 1134 1135 putAmelia("showLogButton", 1136 tcltk::ttkbutton(toolbar, text = "Output Log", state = "disabled", 1137 command = show.output.log, image = 1138 getAmelia("pageTextIcon"), compound = "top", 1139 style="Toolbutton")) 1140 tcltk::tkgrid(getAmelia("loadSessionButton"), row =0, column = 0, sticky = "ew") 1141 tcltk::tkgrid(getAmelia("saveSessionButton"), row =0, column = 1, sticky = "ew") 1142 tcltk::tkgrid(tcltk::ttkseparator(toolbar, orient = "vertical"), row = 0, column = 1143 2, padx=5, pady=5, sticky="ns") 1144 tcltk::tkgrid(getAmelia("plotHistButton"), row = 0, column = 3, sticky = "ew") 1145 tcltk::tkgrid(getAmelia("editDataButton"), row = 0, column = 4, sticky = "ew") 1146 tcltk::tkgrid(getAmelia("missmapButton"), row = 0, column = 5, sticky="ew") 1147 tcltk::tkgrid(tcltk::ttkseparator(toolbar, orient = "vertical"), row = 0, column = 1148 6, padx=5, pady=5, sticky="ns") 1149 tcltk::tkgrid(getAmelia("output.run"), row = 0 , column = 7, sticky = "ew") 1150 tcltk::tkgrid(getAmelia("showLogButton"), row = 0, column = 8, sticky = "ew") 1151 1152########################## 1153### Variable Dashboard ### 1154########################## 1155 1156 dashboard <- tcltk::ttkframe(getAmelia("gui.skel")) 1157 1158 yscr <- tcltk::ttkscrollbar(dashboard, orient = "vertical", 1159 command=function(...)tcltk::tkyview(getAmelia("main.tree"),...)) 1160 xscr <- tcltk::ttkscrollbar(dashboard, orient = "horizontal", 1161 command=function(...)tcltk::tkxview(getAmelia("main.tree"),...)) 1162 1163 sorts <- rep(FALSE, times = 10) 1164 names(sorts) <- c("#0","transform","lag", "lead","bounds", "min", "max", 1165 "mean", "sd", "miss") 1166 putAmelia("sortDirs", sorts) 1167 putAmelia("main.tree", tcltk::ttktreeview(dashboard, columns = 1168 "transform lag lead bounds min max mean sd miss", 1169 yscrollcommand=function(...)tcltk::tkset(yscr,...), xscrollcommand=function(...)tcltk::tkset(xscr,...), 1170 selectmode = "extended")) 1171 1172 #putAmelia("sum.right.click",tcltk::tkmenu(getAmelia("main.tree"), tearoff = FALSE) ) 1173 #tcltk::tkadd(getAmelia("sum.right.click"), "command", label = "Plot Histogram of Selected", command = function() sum.plot()) 1174 #tcltk::tkbind(getAmelia("main.tree"), "<Button-3>", RightClick) 1175 #putAmelia("sum.right.dis",tcltk::tkmenu(getAmelia("main.tree"), tearoff = FALSE) ) 1176 #tcltk::tkadd(getAmelia("sum.right.dis"), "command", label = "Plot Histogram of Selected", state = "disabled") 1177 1178 tcltk::tcl(getAmelia("main.tree"), "column", "#0", width = 70, minwidth = 80) 1179 tcltk::tcl(getAmelia("main.tree"), "column", 0, width = 78, minwidth = 78, anchor = "center") 1180 tcltk::tcl(getAmelia("main.tree"), "column", 1, width = 20, minwidth = 20, anchor = "center") 1181 tcltk::tcl(getAmelia("main.tree"), "column", 2, width = 20, minwidth = 20, 1182 anchor = "center") 1183 tcltk::tcl(getAmelia("main.tree"), "column", 3, width = 50, minwidth = 50, anchor = "e") 1184 tcltk::tcl(getAmelia("main.tree"), "column", 4, width = 50, minwidth = 50, anchor = "e") 1185 tcltk::tcl(getAmelia("main.tree"), "column", 5, width = 50, minwidth = 50, anchor = "e") 1186 tcltk::tcl(getAmelia("main.tree"), "column", 6, width = 50, minwidth = 50, anchor = "e") 1187 tcltk::tcl(getAmelia("main.tree"), "column", 7, width = 50, minwidth = 50, anchor = "e") 1188 tcltk::tcl(getAmelia("main.tree"), "column", 8, width = 50, minwidth = 50, anchor = "e") 1189 1190 tcltk::tcl(getAmelia("main.tree"), "heading", "#0", text = "Variable", 1191 command = function() sortTreeBy("#0")) 1192 tcltk::tcl(getAmelia("main.tree"), "heading", 0, text = "Transformation", 1193 command = function() sortTreeBy("transform")) 1194 tcltk::tcl(getAmelia("main.tree"), "heading", 1, text = "Lag", 1195 command = function() sortTreeBy("lag")) 1196 tcltk::tcl(getAmelia("main.tree"), "heading", 2, text = "Lead", 1197 command = function() sortTreeBy("lead")) 1198 tcltk::tcl(getAmelia("main.tree"), "heading", 3, text = "Bounds", 1199 command = function() sortTreeBy("lower")) 1200 tcltk::tcl(getAmelia("main.tree"), "heading", 4, text = "Min", 1201 command = function() sortTreeBy("min")) 1202 tcltk::tcl(getAmelia("main.tree"), "heading", 5, text = "Max", 1203 command = function() sortTreeBy("max")) 1204 tcltk::tcl(getAmelia("main.tree"), "heading", 6, text = "Mean", 1205 command = function() sortTreeBy("mean")) 1206 tcltk::tcl(getAmelia("main.tree"), "heading", 7, text = "SD", 1207 command = function() sortTreeBy("sd")) 1208 tcltk::tcl(getAmelia("main.tree"), "heading", 8, text = "Missing", 1209 command = function() sortTreeBy("miss")) 1210 tcltk::tkbind(getAmelia("main.tree"), "<Button-3>", mainTreeRightClick) 1211 1212 ## Windows 7 doesn't handle treeview selection correctly 1213 selectbg <- tcltk::tcl("ttk::style","configure",".","-selectbackground") 1214 selectfg <- tcltk::tcl("ttk::style","configure",".","-selectforeground") 1215 tcltk::tktag.configure(getAmelia("main.tree"),"normal", background="white") 1216 tcltk::tktag.configure(getAmelia("main.tree"),"selected", 1217 background=selectbg, foreground=selectfg) 1218 tcltk::tkbind(getAmelia("main.tree"),"<<TreeviewSelect>>",function() 1219 refreshSelection(getAmelia("main.tree"))) 1220 putAmelia("legendFrame", tcltk::ttkframe(dashboard)) 1221 tcltk::tkgrid(tcltk::ttklabel(getAmelia("legendFrame"), text="= Time-Series Variable", image = 1222 getAmelia("clockIcon"), compound = "left"), row = 0, column = 0, sticky="w", 1223 padx = 5) 1224 tcltk::tkgrid(tcltk::ttklabel(getAmelia("legendFrame"), text="= Cross-Section Variable", image = 1225 getAmelia("userIcon"), compound = "left"), row = 0, column = 1, 1226 sticky="w", padx = 5) 1227 tcltk::tkgrid(tcltk::ttklabel(getAmelia("legendFrame"), text="= Unhandled Factor Variable", image = 1228 getAmelia("redFlagIcon"), compound = "left"), row = 0, column = 1229 2, sticky="w", padx = 5) 1230 1231 tcltk::tkgrid(getAmelia("main.tree"), row=0,column=0, sticky="news") 1232 tcltk::tkgrid(yscr, row = 0, column = 1, sticky = "ns") 1233 tcltk::tkgrid(xscr, row = 1, column = 0, sticky = "ew") 1234 tcltk::tkgrid(getAmelia("legendFrame"), row = 2, column = 0, sticky = "ew") 1235 tcltk::tkgrid.rowconfigure(dashboard, 0, weight = 1) 1236 tcltk::tkgrid.columnconfigure(dashboard, 0, weight = 1) 1237 ##Output Frame 1238 ##output options, run button, diag 1239 1240 ##output options 1241 1242 1243 ##grid the whole thing 1244 tcltk::tkadd(getAmelia("gui.skel"), toolbar) 1245 tcltk::tkadd(getAmelia("gui.skel"), dashboard) 1246 1247 tcltk::tkgrid(toolbar, row = 0, column = 1, padx = 2, pady=2, sticky = "ew") 1248 tcltk::tkgrid(dashboard,row = 1, column = 1, sticky = "news", padx = 10, 1249 pady = 5) 1250 1251 tcltk::tkgrid.rowconfigure(getAmelia("gui.skel"), 1, weight = 1) 1252 tcltk::tkgrid.columnconfigure(getAmelia("gui.skel"), 1, weight = 1) 1253 #tcltk::tkgrid(gui.skel,sticky="news") 1254 tcltk::tkgrid.rowconfigure(getAmelia("gui"), 0, weight = 1) 1255 tcltk::tkgrid.columnconfigure(getAmelia("gui"), 0, weight = 1) 1256 1257 ##statusbar at the bottom. 1258 putAmelia("statusbar", tcltk::ttkframe(getAmelia("gui"), relief = "groove", borderwidth = 3)) 1259 statusbar.lab1a <- tcltk::ttklabel(getAmelia("statusbar"), text = "Data Loaded:", anchor = "w", 1260 padding = c(2,0)) 1261 putAmelia("statusbar.lab1b", 1262 tcltk::ttklabel(getAmelia("statusbar"), text = "Unspecified", relief = "sunken", 1263 anchor = "w", foreground = "red",padding = c(2,0), 1264 width = 35)) 1265 statusbar.nlab <- tcltk::ttklabel(getAmelia("statusbar"), text = "Obs:", anchor="e", padding = c(2,0)) 1266 putAmelia("statusbar.n", 1267 tcltk::ttklabel(getAmelia("statusbar"), text = "----", relief = "sunken", 1268 anchor = "w", foreground = "red",padding = c(2,0,0,0), 1269 width = 6)) 1270 1271 statusbar.klab <- tcltk::ttklabel(getAmelia("statusbar"), text = "Vars:", anchor="e", 1272 padding = c(2,0)) 1273 1274 putAmelia("statusbar.k", 1275 tcltk::ttklabel(getAmelia("statusbar"), text = "----", relief = "sunken", anchor = "w", 1276 foreground = "red", padding = c(2,0,0,0), width = 6)) 1277 1278 putAmelia("runAmeliaProgress", 1279 tcltk::ttkprogressbar(getAmelia("statusbar"), value = 0, length = 200, 1280 mode = "determinate")) 1281 putAmelia("error.label", tcltk::ttkbutton(getAmelia("statusbar"), text = 1282 "Error! See Output Log.", image = 1283 getAmelia("redStopIcon"), compound = "left", style = 1284 "Toolbutton", command = show.output.log)) 1285 putAmelia("allgood.label", tcltk::ttkbutton(getAmelia("statusbar"), text = "Successful Imputation.", image = 1286 getAmelia("greenCheckIcon"), compound = "left", 1287 style = "Toolbutton", command = showImputedFiles)) 1288 putAmelia("noimps.label", tcltk::ttklabel(getAmelia("statusbar"), text = 1289 "No imputations run.", justify = "right")) 1290 1291 tcltk::tkgrid(statusbar.lab1a,row = 2, column = 1, sticky="w") 1292 tcltk::tkgrid(getAmelia("statusbar.lab1b"),row = 2, column = 2, sticky="w") 1293 tcltk::tkgrid(statusbar.nlab,row = 2, column = 3, sticky="w") 1294 tcltk::tkgrid(getAmelia("statusbar.n"),row = 2, column = 4, sticky="w") 1295 tcltk::tkgrid(statusbar.klab,row = 2, column = 5, sticky="w") 1296 tcltk::tkgrid(getAmelia("statusbar.k"), row = 2, column = 6, sticky = "w") 1297 tcltk::tkgrid(getAmelia("noimps.label"), row = 2, column = 7, 1298 sticky ="e", padx = 10) 1299 tcltk::tkgrid.rowconfigure(getAmelia("statusbar"), 2, weight = 1) 1300 #tcltk::tkgrid(statusbar, sticky = "sew") 1301 1302 1303 bindTooltip(widget = "output.run", tip = "Run Amelia on your input dataset with the current settings.") 1304 # bindTooltip(widget = "output.diag", tip = "Post-imputation checks for problems in the imputation.") 1305 bindTooltip(widget = "runAmeliaProgress", tip = 1306 "Amelia is currently running and this shows its progress. On large datasets, Amelia may take quite some time.") 1307 # bindTooltip(widget = "output.drop.label", tip = "Set the file format for saving the imputed datasets, if you want to save them.") 1308 # bindTooltip(widget = "output.drop.box", tip = "Set the file format for saving the imputed datasets, if you want to save them.") 1309 bindTooltip(widget = "showLogButton", tip = "Show the output log for the Amelia run. From here, you can save the output. Look here if something went wrong.") 1310 bindTooltip(widget = "missmapButton", tip = "Show a map of the missingnes in the data.") 1311 bindTooltip(widget = "editDataButton", tip = 1312 "Edit individual cells of the data set.") 1313 1314 bindTooltip(widget = "plotHistButton", tip = 1315 "Plot histogram(s) of the selected variable(s).") 1316 1317 bindTooltip(widget = "loadSessionButton", tip = 1318 "Load a previously saved Amelia session. This will remove any current settings.") 1319 1320 bindTooltip(widget = "saveSessionButton", tip = 1321 "Save the current Amelia session. This will save the data, settings, and any imputed data in the Amelia session.") 1322 bindTooltip(widget = "legendFrame", tip = 1323 "A legend for the icons used in the variable dashboard.") 1324 bindTooltip(widget = "noimps.label", tip = 1325 "No imputations have been run yet. To run Amelia, hit the 'Impute!' button in the toolbar.") 1326 bindTooltip(widget = "allgood.label", tip = 1327 "Amelia has run successfully! You can now run imputation diagnostics from the 'Output' menu above. If you chose to save the imputations to file, they should be saved in the working directory. Click here to open the containing folder..") 1328 bindTooltip(widget = "error.label", tip = 1329 "There was an error the last time you ran Amelia. Click here to open the output log to identify the problem and to see how to fix it.") 1330 ## these commands force R to wait for tcltk 1331 if (.Platform$OS.type == "windows") 1332 tcltk::tkwm.iconbitmap(getAmelia("gui"),file.path(find.package(package = "Amelia")[1], "gui/amelia.ico")) 1333 tcltk::tkraise(getAmelia("gui")) 1334 tcltk::tkwm.deiconify(getAmelia("gui")) 1335 tcltk::tkfocus(getAmelia("gui")) 1336 tcltk::tclServiceMode(on = TRUE) 1337 tcltk::tkwait.window(getAmelia("gui")) 1338 1339 1340} 1341 1342buildNumericalOptions <- function() { 1343 onCancel <- function(){ 1344 tcltk::tcl("set", getAmelia("seed"), getAmelia("temp.seed")) 1345 tcltk::tcl("set", getAmelia("tol"), getAmelia("temp.tol")) 1346 tcltk::tkwm.withdraw(getAmelia("numericalWindow")) 1347 tcltk::tkgrab.release(getAmelia("numericalWindow")) 1348 tcltk::tkfocus(getAmelia("gui")) 1349 } 1350 1351 putAmelia("temp.seed", tcltk::tclvalue(getAmelia("seed"))) 1352 putAmelia("temp.tol", tcltk::tclvalue(getAmelia("tol"))) 1353 1354 if (exists("numericalWindow", envir = ameliaEnv)) { 1355 tcltk::tkwm.deiconify(getAmelia("numericalWindow")) 1356 tcltk::tkraise(getAmelia("numericalWindow")) 1357 return() 1358 } 1359 1360 putAmelia("numericalWindow", tcltk::tktoplevel()) 1361 tcltk::tkwm.title(getAmelia("numericalWindow"), "Numerical Options") 1362 numericalBox <- tcltk::ttkframe(getAmelia("numericalWindow")) 1363 putAmelia("output.seedlab", tcltk::ttklabel(numericalBox, text="Seed:")) 1364 putAmelia("output.seed", 1365 tcltk::ttkentry(numericalBox, width="7", textvariable=getAmelia("seed"))) 1366 putAmelia("output.tollab", tcltk::ttklabel(numericalBox, text="Tolerance:")) 1367 putAmelia("output.tol", 1368 tcltk::ttkentry(numericalBox, width="7", 1369 textvariable=getAmelia("tol"))) 1370 putAmelia("empri.ent", tcltk::ttkentry(numericalBox, width=7,textvariable = getAmelia("empri"))) 1371 putAmelia("empri.label", tcltk::ttklabel(numericalBox,text="Ridge prior:")) 1372 putAmelia("maxre.ent", tcltk::ttkentry(numericalBox, width=7,textvariable = getAmelia("max.resample"))) 1373 putAmelia("maxre.label", 1374 tcltk::ttklabel(numericalBox,text="Maximum Resample for Bounds:")) 1375 1376 buttonBox <- tcltk::ttkframe(numericalBox) 1377 okButton <- tcltk::ttkbutton(buttonBox, text = "OK", width = 10, command = function() {tcltk::tkwm.withdraw(getAmelia("numericalWindow"));tcltk::tkgrab.release(getAmelia("numericalWindow"));tcltk::tkfocus(getAmelia("gui"))}) 1378 cancelButton <- tcltk::ttkbutton(buttonBox, width = 10, text = "Cancel", command = onCancel) 1379 1380 1381 tcltk::tkgrid(getAmelia("output.seedlab"), row = 1, column = 1, sticky = "w", padx = 10, pady = 10) 1382 tcltk::tkgrid(getAmelia("output.seed"), row = 1, column = 2, sticky = "w", padx = 10, pady = 10) 1383 tcltk::tkgrid(getAmelia("output.tollab"), row = 2, column = 1, sticky = 1384 "w", padx = 10, pady = 10) 1385 tcltk::tkgrid(getAmelia("output.tol"), row = 2, column = 2, sticky = "w", 1386 padx = 10, pady = 10) 1387 tcltk::tkgrid(getAmelia("empri.label"), row = 3, column = 1, sticky = "w", padx = 10, pady = 10) 1388 tcltk::tkgrid(getAmelia("empri.ent"), row = 3, column = 2, sticky = "w", 1389 padx = 10, pady = 10) 1390 1391 tcltk::tkgrid(getAmelia("maxre.label"), row = 4, column = 1, sticky = "w", padx = 10, pady = 10) 1392 tcltk::tkgrid(getAmelia("maxre.ent"), row = 4, column = 2, sticky = "w", 1393 padx = 10, pady = 10) 1394 tcltk::tkgrid(okButton, row = 0, column = 0, padx = 10, pady = 10) 1395 tcltk::tkgrid(cancelButton, row = 0, column = 1, padx = 10, pady = 10) 1396 tcltk::tkgrid(buttonBox, row = 5, column = 1, sticky = "e", columnspan = 2) 1397 tcltk::tkgrid(numericalBox, sticky = "news") 1398 1399 tcltk::tkwm.protocol(getAmelia("numericalWindow"), "WM_DELETE_WINDOW", onCancel) 1400 1401 centerModalDialog(getAmelia("numericalWindow"), resize=FALSE) 1402 1403 bindTooltip(widget = "empri.ent", "Ridge prior that shrinks the covariances, which stabilizes estimation. Five percent of the number of observations is a useful default.") 1404 bindTooltip(widget = "empri.label", "Ridge prior that shrinks the covariances, which stabilizes estimation. Five percent of the number of observations is a useful default.") 1405 bindTooltip(widget = "output.seed", tip = "Set seed for random number generator. Useful if you need to replicate the exact same imputations.") 1406 bindTooltip(widget = "output.seedlab", tip = 1407 "Set seed for random number generator. Useful if you need to replicate the exact same imputations.") 1408 bindTooltip(widget = "output.tol", tip = 1409 "Set the tolerance for the Amelia run. This is the value used to determine when Amelia has converged. Higher values mean Amelia will coverge more quickly, but this may lead to a poor approximation of the parameters.") 1410 bindTooltip(widget = "output.tollab", tip = 1411 "Set the tolerance for the Amelia run. This is the value used to determine when Amelia has converged. Higher values mean Amelia will coverge more quickly, but this may lead to a poor approximation of the parameters.") 1412 bindTooltip(widget = "maxre.ent", tip = "Amelia fits bounds by rejecting any draws that do not fall within the bounds. This value sets the number of times Amelia should attempt to resample to fit the bounds before setting the imputation to the bound.") 1413 bindTooltip(widget = "maxre.label", tip = "Amelia fits bounds by rejecting any draws that do not fall within the bounds. This value sets the number of times Amelia should attempt to resample to fit the bounds before setting the imputation to the bound.") 1414 1415} 1416 1417 1418buildOutputOptions <- function() { 1419 onCancel <- function(){ 1420 tcltk::tcl("set", getAmelia("outname"), getAmelia("temp.name")) 1421 tcltk::tcl("set", getAmelia("outnum"), getAmelia("temp.num")) 1422 tcltk::tkwm.withdraw(getAmelia("outputWindow")) 1423 tcltk::tkgrab.release(getAmelia("outputWindow")) 1424 tcltk::tkfocus(getAmelia("gui")) 1425 } 1426 1427 putAmelia("temp.name", tcltk::tclvalue(getAmelia("outname"))) 1428 putAmelia("temp.num", tcltk::tclvalue(getAmelia("outnum"))) 1429 1430 if (exists("outputWindow", envir = ameliaEnv)) { 1431 tcltk::tkwm.deiconify(getAmelia("outputWindow")) 1432 tcltk::tkraise(getAmelia("outputWindow")) 1433 return() 1434 } 1435 1436 putAmelia("outputWindow", tcltk::tktoplevel()) 1437 tcltk::tkwm.title(getAmelia("outputWindow"), "Output Options") 1438 outputBox <- tcltk::ttkframe(getAmelia("outputWindow")) 1439 1440 putAmelia("output.label", tcltk::ttklabel(outputBox, text="Name the Imputed Dataset:")) 1441 putAmelia("output.entry", 1442 tcltk::ttkentry(outputBox, width="15", 1443 textvariable = getAmelia("outname"))) 1444 1445 putAmelia("output.numlab", tcltk::ttklabel(outputBox, text = "Number of Imputed Datasets:")) 1446 putAmelia("output.num", 1447 tcltk::ttkentry(outputBox, width = "7", 1448 textvariable = getAmelia("outnum"))) 1449 1450 buttonBox <- tcltk::ttkframe(outputBox) 1451 okButton <- tcltk::ttkbutton(buttonBox, text = "OK", width = 10, command = function() {tcltk::tkwm.withdraw(getAmelia("outputWindow"));tcltk::tkgrab.release(getAmelia("outputWindow"));tcltk::tkfocus(getAmelia("gui"))}) 1452 cancelButton <- tcltk::ttkbutton(buttonBox, width = 10, text = "Cancel", command = onCancel) 1453 1454 1455 tcltk::tkgrid(getAmelia("output.label"), row = 1, column = 1, sticky = "w", padx = 10, pady = 10) 1456 tcltk::tkgrid(getAmelia("output.entry"), row = 1, column = 2, sticky = "w", padx = 10, pady = 10) 1457 tcltk::tkgrid(getAmelia("output.numlab"), row = 2, column = 1, sticky = "w", padx = 10, pady = 10) 1458 tcltk::tkgrid(getAmelia("output.num"), row = 2, column = 2, sticky = "w", 1459 padx = 10, pady = 10) 1460 tcltk::tkgrid(okButton, row = 0, column = 0, padx = 10, pady = 10) 1461 tcltk::tkgrid(cancelButton, row = 0, column = 1, padx = 10, pady = 10) 1462 tcltk::tkgrid(buttonBox, row = 3, column = 1, sticky = "e", columnspan = 2) 1463 tcltk::tkgrid(outputBox, sticky = "news") 1464 1465 tcltk::tkwm.protocol(getAmelia("outputWindow"), "WM_DELETE_WINDOW", onCancel) 1466 1467 centerModalDialog(getAmelia("outputWindow"), resize=FALSE) 1468 1469 bindTooltip(widget = "output.entry", tip = "The prefix for the saved imputed datasets. For most saving options they will be in the following format: \n\nmyprefix1.out\nmyprefix2.out\n...\n\nAnd so on, where \"out\" is the file extension.") 1470 bindTooltip(widget = "output.label", tip = "The prefix for the saved imputed datasets. For most saving options they will be in the following format: \n\nmyprefix1.out\nmyprefix2.out\n...\n\nAnd so on, where \"out\" is the file extension.") 1471 bindTooltip(widget = "output.num", tip = "Set the number of imputed datasets.\n\nIn many cases, around 5 is sufficient, but if the fraction of missingness is high, you may need more. Use the Summarize Data and Missingness Map above to get a sense for the amount of missingness in your data.") 1472 bindTooltip(widget = "output.numlab", tip = "Set the number of imputed datasets.\n\nIn many cases, around 5 is sufficient, but if the fraction of missingness is high, you may need more. Use the Summarize Data and Missingness Map above to get a sense for the amount of missingness in your data.") 1473 1474} 1475 1476 1477 1478buildAboutDialog <- function() { 1479 if (exists("aboutWindow", envir = ameliaEnv)) { 1480 tcltk::tkwm.deiconify(getAmelia("aboutWindow")) 1481 tcltk::tkraise(getAmelia("aboutWindow")) 1482 return() 1483 } 1484 putAmelia("aboutWindow", tcltk::tktoplevel(parent=getAmelia("gui"))) 1485 tcltk::tkwm.title(getAmelia("aboutWindow"), "About AmeliaView") 1486 aboutBox <- tcltk::ttkframe(getAmelia("aboutWindow"), height = 150, width = 200) 1487 #ameliaPic <- tcltk::tkimage.create("photo",file=ameliaFile) 1488 picLabel <- tcltk::ttklabel(aboutBox, image=getAmelia("ameliaPic"), relief="groove", borderwidth=2) 1489 tcltk::tkgrid(tcltk::ttkframe(aboutBox,width=100), row=0,column=1) 1490 tcltk::tkgrid(tcltk::ttkframe(aboutBox,height=150,width=0), row=0,column=0,rowspan=3) 1491 tcltk::tkgrid(picLabel, row = 1, column=1, pady = 20, padx = 20) 1492 tcltk::tkgrid(tcltk::ttklabel(aboutBox, text=paste("AmeliaView",packageDescription("Amelia", fields="Version")), justify="center"), row = 2, column = 1) 1493 tcltk::tkgrid(tcltk::ttklabel(aboutBox, text="James Honaker, Gary King, Matthew Blackwell", justify="center"), row = 3, column = 1, padx=20) 1494 tcltk::tkgrid(tcltk::ttklabel(aboutBox, text="\uA9 2006-2010", justify="center"), row = 4, column = 1, padx=20) 1495 buttonBox <- tcltk::ttkframe(aboutBox) 1496 closeButton <- tcltk::ttkbutton(buttonBox, text = "Close", command = function() {tcltk::tkwm.withdraw(getAmelia("aboutWindow"));tcltk::tkgrab.release(getAmelia("aboutWindow"));tcltk::tkfocus(getAmelia("gui"))}, width = 10) 1497 websiteButton <- tcltk::ttkbutton(buttonBox, text = "Website", 1498 command = function() browseURL("http://gking.harvard.edu/amelia/")) 1499 tcltk::tkgrid(websiteButton, row=0, column = 0, sticky="w", padx=10, pady=10) 1500 tcltk::tkgrid(closeButton, row=0, column = 0, sticky="e", padx=10, pady=10) 1501 tcltk::tkgrid.columnconfigure(buttonBox, 0, weight=1) 1502 tcltk::tkgrid(buttonBox, row=5, column = 1, sticky="ew") 1503 tcltk::tkgrid(aboutBox, sticky = "nsew") 1504 tcltk::tkwm.protocol(getAmelia("aboutWindow"), "WM_DELETE_WINDOW", function() {tcltk::tkwm.withdraw(getAmelia("aboutWindow"));tcltk::tkgrab.release(getAmelia("aboutWindow"));tcltk::tkfocus(getAmelia("gui"))}) 1505 1506 centerModalDialog(getAmelia("aboutWindow"), resize=FALSE) 1507} 1508 1509 1510 1511 1512 1513gui.pri.setup <- function() { 1514 cancelPriors <- function() { 1515 putAmelia("priorsmat", getAmelia("temp.priorsmat")) 1516 } 1517 onOK <- function() { 1518 1519 nm <- c("dist","range")[getAmeliaInd("addpri.note")+1] 1520 varBox <- paste("add",nm,"var",sep=".") 1521 caseBox <- paste("add",nm,"case",sep=".") 1522 caseSelection <- as.numeric(tcltk::tcl(getAmelia(caseBox),"current")) 1523 varSelection <- as.numeric(tcltk::tcl(getAmelia(varBox),"current")) + 1 1524 1525 thiscase <- tcltk::tclvalue(tcltk::tkget(getAmelia(caseBox))) 1526 thisvar <- tcltk::tclvalue(tcltk::tkget(getAmelia(varBox))) 1527 1528 1529 if (caseSelection==0) { 1530 rowSelection <- 0 1531 colSelection <- which(anyMissing)[varSelection] 1532 } else { 1533 rowSelection <- missingCases[caseSelection] 1534 colSelection <- which(is.na(getAmelia("amelia.data")[rowSelection,]))[varSelection] 1535 } 1536 1537 # fork for range vs. dist 1538 if (nm == "range") { 1539 if (tcltk::tclvalue(getAmelia("priorMin"))=="") { 1540 tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Error", 1541 message="Please enter a minimum value.", 1542 type="ok",icon="error") 1543 return() 1544 } 1545 if (tcltk::tclvalue(getAmelia("priorMax"))=="") { 1546 tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Error", 1547 message="Please enter a maximum value.", 1548 type="ok",icon="error") 1549 return() 1550 } 1551 1552 if (tcltk::tclvalue(getAmelia("priorConf"))=="") { 1553 tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Error", 1554 message="Please enter a confidence value.", 1555 type="ok",icon="error") 1556 return() 1557 } 1558 if (isTRUE(as.numeric(tcltk::tclvalue(getAmelia("priorConf"))) <= 0 1559 | as.numeric(tcltk::tclvalue(getAmelia("priorConf"))) >= 1)) { 1560 tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Error", 1561 message="Confidence levels must be between 0 and 1.", 1562 type="ok",icon="error") 1563 return() 1564 } 1565 1566 prMax <- as.numeric(tcltk::tclvalue(getAmelia("priorMax"))) 1567 prMin <- as.numeric(tcltk::tclvalue(getAmelia("priorMin"))) 1568 prCon <- as.numeric(tcltk::tclvalue(getAmelia("priorConf"))) 1569 if (prMax <= prMin) { 1570 tcltk::tkmessageBox(title="Error", 1571 message="The max is less than the min.", 1572 type="ok",icon="error") 1573 return() 1574 } 1575 prMean<- prMin + ((prMax-prMin)/2) 1576 prSD <-(prMax-prMin)/(2*qnorm(1-(1-prCon)/2)) 1577 1578 1579 #if dist prior 1580 } else { 1581 if (tcltk::tclvalue(getAmelia("priorMean"))=="") { 1582 tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Error", 1583 message="Please enter a mean value.", 1584 type="ok",icon="error") 1585 return() 1586 } 1587 if (tcltk::tclvalue(getAmelia("priorSD"))=="") { 1588 tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Error", 1589 message="Please enter a standard deviation.", 1590 type="ok",icon="error") 1591 return() 1592 } 1593 if (isTRUE(as.numeric(tcltk::tclvalue(getAmelia("priorSD"))) == 0)) { 1594 tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Error", 1595 message="Standard deviations must be greater than 0.", 1596 type="ok",icon="error") 1597 return() 1598 } 1599 prMean <- as.numeric(tcltk::tclvalue(getAmelia("priorMean"))) 1600 prSD <- as.numeric(tcltk::tclvalue(getAmelia("priorSD"))) 1601 1602 1603 } 1604 newPrior <- c(rowSelection, colSelection,prMean,prSD) 1605 if (!is.null(getAmelia("priorsmat"))) { 1606 matchPrior <- apply(getAmelia("priorsmat"), 1, 1607 function(x) all(x[1]==rowSelection, 1608 x[2]==colSelection)) 1609 } else { 1610 matchPrior <- FALSE 1611 } 1612 1613 if (any(matchPrior)) { 1614 mess <- "There is a prior associate with this case. Overwrite?" 1615 over <- tcltk::tkmessageBox(parent=getAmelia("priorsWindow"), title="Overwrite Prior",message=mess, 1616 icon="question",type="yesno",default="no") 1617 if (tcltk::tclvalue(over)=="no") { 1618 return() 1619 } else { 1620 putAmelia("priorsmat",getAmelia("priorsmat")[-which(matchPrior),]) 1621 tcltk::tkdelete(getAmelia("priors.tree"), paste(rowSelection,colSelection,sep="-")) 1622 } 1623 } 1624 1625 putAmelia("priorsmat",rbind(getAmelia("priorsmat"),newPrior)) 1626 1627 ## need to change the treeview 1628 #updateTree() 1629 tcltk::tkinsert(getAmelia("priors.tree"),"","end", id = paste(rowSelection,colSelection,sep="-"), values = c(thisvar,prMean,prSD), 1630 text = thiscase,tag="normal") 1631 resetEntries() 1632 return() 1633 } 1634 validateNumeric <- function(x) { 1635 if (isTRUE(grep("(^-?[0-9]*\\.?[0-9]*$)",x)==1)) 1636 return(tcltk::tclVar("TRUE")) 1637 else 1638 return(tcltk::tclVar("FALSE")) 1639 } 1640 validateSD <- function(x) { 1641 if (isTRUE(grep("^[0-9]*\\.?[0-9]*$",x)==1)) 1642 return(tcltk::tclVar("TRUE")) 1643 else 1644 return(tcltk::tclVar("FALSE")) 1645 } 1646 validateConf <- function(x) { 1647 if (isTRUE(grep("^0*\\.[0-9]*$",x)==1)) 1648 return(tcltk::tclVar("TRUE")) 1649 else 1650 return(tcltk::tclVar("FALSE")) 1651 } 1652 setMissingVars <- function() { 1653 currentSelection <- as.numeric(tcltk::tcl(getAmelia("add.dist.case"), "current")) 1654 currentCase <- missingCases[currentSelection] 1655 if (currentSelection==0) 1656 missVars <- anyMissing 1657 else 1658 missVars <- is.na(getAmelia("amelia.data")[currentCase,]) 1659 missVarNames <- colnames(getAmelia("amelia.data"))[missVars] 1660 tcltk::tkconfigure(getAmelia("add.dist.var"),values = missVarNames) 1661 tcltk::tcl(getAmelia("add.dist.var"), "current", 0) 1662 } 1663 setMissingRangeVars <- function() { 1664 currentSelection <- as.numeric(tcltk::tcl(getAmelia("add.range.case"), "current")) 1665 currentCase <- missingCases[currentSelection] 1666 if (currentSelection==0) 1667 missVars <- anyMissing 1668 else 1669 missVars <- is.na(getAmelia("amelia.data")[currentCase,]) 1670 missVarNames <- colnames(getAmelia("amelia.data"))[missVars] 1671 tcltk::tkconfigure(getAmelia("add.range.var"),values = missVarNames) 1672 tcltk::tcl(getAmelia("add.range.var"), "current", 0) 1673 } 1674 resetEntries <- function() { 1675 tcltk::tcl("set", getAmelia("priorMin"),"") 1676 tcltk::tcl("set", getAmelia("priorMax"),"") 1677 tcltk::tcl("set", getAmelia("priorMean"),"") 1678 tcltk::tcl("set", getAmelia("priorSD"),"") 1679 tcltk::tcl("set", getAmelia("priorConf"),"") 1680 return() 1681 } 1682 updateTree <- function() { 1683 allrows <- paste(tcltk::tcl(getAmelia("priors.tree"),"children","")) 1684 tcltk::tkdelete(getAmelia("priors.tree"), allrows) 1685 1686 if (is.null(getAmelia("priorsmat"))) { 1687 return() 1688 } 1689 1690 varnames <- names(getAmelia("amelia.data")) 1691 cases <- paste(rownames(getAmelia("amelia.data")), ") ", 1692 getAmelia("amelia.data")[,getAmelia("csvar")]," ", 1693 getAmelia("amelia.data")[,getAmelia("tsvar")], sep="") 1694 cases <- c("(whole variable)", cases) 1695 for (i in 1:nrow(getAmelia("priorsmat"))) { 1696 thiscase <- cases[getAmelia("priorsmat")[i,1]+1] 1697 thisvar <- varnames[getAmelia("priorsmat")[i,2]] 1698 tcltk::tkinsert(getAmelia("priors.tree"),"","end", id = paste(getAmelia("priorsmat")[i,1],getAmelia("priorsmat")[i,2],sep="-"), values = c(thisvar,getAmelia("priorsmat")[i,c(3,4)]), 1699 text = thiscase,tag="normal") 1700 } 1701 return() 1702 1703 } 1704 dropPriors <- function() { 1705 sel.pri <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("priors.tree"), "selection")), " ")[[1]] 1706 pri.mat.rows <- c() 1707 for (i in 1:length(sel.pri)) { 1708 pri.mat.rows <- c(pri.mat.rows, tcltk::tclvalue(tcltk::tkindex(getAmelia("priors.tree"),sel.pri[i]))) 1709 } 1710 pri.mat.rows <- as.numeric(pri.mat.rows) + 1 1711 putAmelia("priorsmat", getAmelia("priorsmat")[-pri.mat.rows,, drop = FALSE]) 1712 tcltk::tkdelete(getAmelia("priors.tree"),paste(tcltk::tcl(getAmelia("priors.tree"), "selection"))) 1713 if (nrow(getAmelia("priorsmat")) == 0) putAmelia("priorsmat", NULL) 1714 return(NULL) 1715 } 1716 RightClick <- function(x, y) { # x and y are the mouse coordinates 1717 rootx <- as.integer(tcltk::tkwinfo("rootx", getAmelia("priors.tree"))) # tcltk::tkwinfo() return several infos 1718 rooty <- as.integer(tcltk::tkwinfo("rooty", getAmelia("priors.tree"))) 1719 xTxt <- as.integer(x) + rootx 1720 yTxt <- as.integer(y) + rooty 1721 # Create a Tcl command in a character string and run it 1722 tcltk::.Tcl(paste("tk_popup", tcltk::.Tcl.args(getAmelia("pri.right.click"), xTxt, yTxt))) 1723 } 1724 1725 1726 putAmelia("temp.priorsmat", getAmelia("priorsmat")) 1727 1728 if (exists("priorsWindow", envir=ameliaEnv)) { 1729 updateTree() 1730 resetEntries() 1731 tcltk::tkwm.deiconify(getAmelia("priorsWindow")) 1732 tcltk::tkraise(getAmelia("priorsWindow")) 1733 tcltk::tkgrab(getAmelia("priorsWindow")) 1734 return() 1735 } 1736 putAmelia("priorsWindow", tcltk::tktoplevel()) 1737 tcltk::tkwm.title(getAmelia("priorsWindow"),"Observational Priors") 1738 1739 priorsBox <- tcltk::ttkframe(getAmelia("priorsWindow")) 1740 1741 prior.frame <- tcltk::ttkpanedwindow(priorsBox, orient = "horizontal") 1742 prior.disp <- tcltk::ttklabelframe(prior.frame, text = "Observational priors ", height = 200, width = 200) 1743 prior.add <- tcltk::ttklabelframe(prior.frame, text = "Add priors", height = 200, width = 200) 1744 putAmelia("prior.add.but", tcltk::ttkbutton(prior.add, text = "Add", command = function() onOK())) 1745 1746 yscr <- tcltk::ttkscrollbar(prior.disp, orient = "vertical", 1747 command=function(...)tcltk::tkyview(getAmelia("priors.tree"),...)) 1748 xscr <- tcltk::ttkscrollbar(prior.disp, orient = "horizontal", 1749 command=function(...)tcltk::tkxview(getAmelia("priors.tree"),...)) 1750 putAmelia("priors.tree", tcltk::ttktreeview(prior.disp, columns = "Variable Mean SD", 1751 yscrollcommand=function(...)tcltk::tkset(yscr,...), xscrollcommand=function(...)tcltk::tkset(xscr,...))) 1752 1753 putAmelia("pri.right.click",tcltk::tkmenu(getAmelia("priors.tree"), tearoff = FALSE) ) 1754 tcltk::tkadd(getAmelia("pri.right.click"), "command", label = "Remove selected priors", command = function() dropPriors()) 1755 tcltk::tkbind(getAmelia("priors.tree"), "<Button-3>", RightClick) 1756 1757 tcltk::tcl(getAmelia("priors.tree"), "column", "#0", width = 120) 1758 tcltk::tcl(getAmelia("priors.tree"), "column", 0, width = 80, anchor = "center") 1759 tcltk::tcl(getAmelia("priors.tree"), "column", 1, width = 40, anchor = "center") 1760 tcltk::tcl(getAmelia("priors.tree"), "column", 2, width = 40, anchor = "center") 1761 tcltk::tcl(getAmelia("priors.tree"), "heading", "#0", text = "Case") 1762 tcltk::tcl(getAmelia("priors.tree"), "heading", 0, text = "Variable") 1763 tcltk::tcl(getAmelia("priors.tree"), "heading", 1, text = "Mean") 1764 tcltk::tcl(getAmelia("priors.tree"), "heading", 2, text = "SD") 1765 ## Windows 7 doesn't handle treeview selection correctly 1766 if (.Platform$OS.type == "windows") { 1767 tcltk::tktag.configure(getAmelia("priors.tree"),"normal", background="white") 1768 tcltk::tktag.configure(getAmelia("priors.tree"),"selected", background="SystemHighlight") 1769 tcltk::tkbind(getAmelia("priors.tree"),"<<TreeviewSelect>>",function() refreshSelection(getAmelia("priors.tree"))) 1770 } 1771 putAmelia("addpri.note", tcltk::ttknotebook(prior.add)) 1772 add.dist.frame <- tcltk::ttkframe(getAmelia("addpri.note")) 1773 add.range.frame <- tcltk::ttkframe(getAmelia("addpri.note")) 1774 1775 1776 1777 missingCases <- which(!complete.cases(getAmelia("amelia.data"))) 1778 anyMissing <- apply(getAmelia("amelia.data"), 2, function(x) any(is.na(x))) 1779 1780 cases1 <- paste(rownames(getAmelia("amelia.data"))[missingCases], ") ", 1781 getAmelia("amelia.data")[missingCases, getAmelia("csvar")]," ", 1782 getAmelia("amelia.data")[missingCases, getAmelia("tsvar")], sep="") 1783 1784 1785 cases <- c("(whole variable)",cases1) 1786 1787 if (!is.null(getAmelia("priorsmat"))) updateTree() 1788 vars <- getAmelia("varnames")[anyMissing] 1789 1790 1791 ## Distribution prior note 1792 1793 putAmelia("add.dist.case",tcltk::ttkcombobox(add.dist.frame, values=cases, 1794 state="readonly", width=15)) 1795 putAmelia("add.dist.var",tcltk::ttkcombobox(add.dist.frame, values=vars, 1796 state="readonly", width=15)) 1797 tcltk::tkbind(getAmelia("add.dist.case"), "<<ComboboxSelected>>", function(...) setMissingVars()) 1798 tcltk::tkgrid(tcltk::ttklabel(add.dist.frame, text="Case:"), column=1, row=1, sticky = "e") 1799 tcltk::tkgrid(tcltk::ttklabel(add.dist.frame, text="Variable:"), column=1, row=2, sticky = "e") 1800 tcltk::tcl(getAmelia("add.dist.case"), "current", 0) 1801 tcltk::tcl(getAmelia("add.dist.var"), "current", 0) 1802 tcltk::tkconfigure(getAmelia("add.dist.var"), postcommand=function(...) setMissingVars()) 1803 tcltk::tkgrid(getAmelia("add.dist.case"), column=2, row=1, pady=3) 1804 tcltk::tkgrid(getAmelia("add.dist.var"), column=2, row=2, pady=3) 1805 1806 1807 1808 putAmelia("priorMean", tcltk::tclVar()) 1809 putAmelia("priorSD", tcltk::tclVar()) 1810 1811 1812 tcltk::tkgrid(tcltk::ttkframe(add.dist.frame, width = 150, height = 0), column = 1, row = 0) 1813 putAmelia("meanBox", tcltk::ttkentry(add.dist.frame, textvar=getAmelia("priorMean"), validate="key", 1814 validatecommand = function(P) validateNumeric(P))) 1815 1816 putAmelia("sdBox", tcltk::ttkentry(add.dist.frame, textvar=getAmelia("priorSD"), validate="key", 1817 validatecommand = function(P) validateSD(P))) 1818 1819 tcltk::tkgrid(tcltk::ttklabel(add.dist.frame, text="Mean:"), column=1, row=3, sticky = "e") 1820 tcltk::tkgrid(tcltk::ttklabel(add.dist.frame, text="Standard Deviation:"), column=1, 1821 row=4, sticky = "e") 1822 1823 tcltk::tkgrid(getAmelia("meanBox"), column=2, row=3, pady=5, padx=5) 1824 tcltk::tkgrid(getAmelia("sdBox"), column=2, row=4, pady=5, padx=5) 1825 1826 ## Range prior note 1827 1828 putAmelia("add.range.case",tcltk::ttkcombobox(add.range.frame, values=cases, 1829 state="readonly", width=15)) 1830 putAmelia("add.range.var",tcltk::ttkcombobox(add.range.frame, values=vars, 1831 state="readonly", width=15)) 1832 tcltk::tkbind(getAmelia("add.range.case"), "<<ComboboxSelected>>", function(...) setMissingRangeVars()) 1833 tcltk::tkgrid(tcltk::ttklabel(add.range.frame, text="Case:"), column=1, row=1, sticky = "e") 1834 tcltk::tkgrid(tcltk::ttklabel(add.range.frame, text="Variable:"), column=1, row=2, sticky = "e") 1835 tcltk::tcl(getAmelia("add.range.case"), "current", 0) 1836 tcltk::tcl(getAmelia("add.range.var"), "current", 0) 1837 tcltk::tkconfigure(getAmelia("add.range.var"), postcommand=function(...) setMissingRangeVars()) 1838 tcltk::tkgrid(getAmelia("add.range.case"), column=2, row=1, pady=3) 1839 tcltk::tkgrid(getAmelia("add.range.var"), column=2, row=2, pady=3) 1840 1841 tcltk::tkgrid(tcltk::ttkframe(add.range.frame, width = 150, height = 0), column = 1, row = 0) 1842 putAmelia("priorMax", tcltk::tclVar()) 1843 putAmelia("priorMin", tcltk::tclVar()) 1844 putAmelia("priorConf", tcltk::tclVar()) 1845 1846 1847 putAmelia("minBox", tcltk::ttkentry(add.range.frame, textvar=getAmelia("priorMin"), validate="key", 1848 validatecommand = function(P) validateNumeric(P))) 1849 1850 putAmelia("maxBox", tcltk::ttkentry(add.range.frame, textvar=getAmelia("priorMax"), validate="key", 1851 validatecommand = function(P) validateNumeric(P))) 1852 1853 1854 putAmelia("confBox", tcltk::ttkentry(add.range.frame, textvar=getAmelia("priorConf"), validate="key", 1855 validatecommand = function(P) validateNumeric(P))) 1856 1857 tcltk::tkgrid(tcltk::ttklabel(add.range.frame, text="Minimum:"), column=1, row=3, sticky = "e") 1858 tcltk::tkgrid(tcltk::ttklabel(add.range.frame, text="Maximum:"), column=1, row=4, sticky = "e") 1859 tcltk::tkgrid(tcltk::ttklabel(add.range.frame, text="Confidence:"), column=1, row=5, sticky = "e") 1860 #tcltk::tkgrid(tkframe(add.range.frame, width = 20, height = 0), column = 1, row = 6) 1861 1862 tcltk::tkgrid(getAmelia("minBox"), column=2, row=3, pady=5, padx=5) 1863 tcltk::tkgrid(getAmelia("maxBox"), column=2, row=4, pady=5, padx=5) 1864 tcltk::tkgrid(getAmelia("confBox"), column=2, row=5, pady=5, padx=5) 1865 1866 tcltk::tkadd(getAmelia("addpri.note"), add.dist.frame, text = "Add Distribution Prior") 1867 tcltk::tkadd(getAmelia("addpri.note"), add.range.frame, text = "Add Range Prior") 1868 1869 1870 tcltk::tkgrid(getAmelia("addpri.note"), row = 1, sticky = "nsew") 1871 1872 tcltk::tkgrid(getAmelia("prior.add.but"), sticky = "se", padx = 10, pady = 10) 1873 but.frame <- tcltk::ttkframe(priorsBox) 1874 putAmelia("pri.ok", tcltk::ttkbutton(but.frame, text = "OK", command = function(){tcltk::tkwm.withdraw(getAmelia("priorsWindow"));tcltk::tkgrab.release(getAmelia("priorsWindow"));tcltk::tkfocus(getAmelia("gui"))}, width = 10)) 1875 putAmelia("pri.can", tcltk::ttkbutton(but.frame, text = "Cancel", width = 10, command = function() {cancelPriors();tcltk::tkwm.withdraw(getAmelia("priorsWindow"));tcltk::tkgrab.release(getAmelia("priorsWindow"));tcltk::tkfocus(getAmelia("gui"))})) 1876 1877 1878 tcltk::tkgrid(getAmelia("priors.tree"), row = 1, column = 1, sticky = "nsew") 1879 tcltk::tkgrid(yscr, row = 1, column = 2, sticky = "nsew") 1880 tcltk::tkgrid(xscr, row = 2, column = 1, sticky = "nsew") 1881 tcltk::tkgrid.rowconfigure(prior.disp, 1, weight = 1) 1882 tcltk::tkgrid.columnconfigure(prior.disp, 1, weight = 1) 1883 tcltk::tkadd(prior.frame, prior.add) 1884 tcltk::tkadd(prior.frame, prior.disp) 1885 1886 tcltk::tkgrid(prior.frame, row = 1, column = 0, columnspan = 2, padx = 10, pady = 10, sticky = "news") 1887 tcltk::tkgrid(getAmelia("pri.ok"), row = 0, column = 1, sticky = "ne", padx = 10, pady = 10) 1888 tcltk::tkgrid(getAmelia("pri.can"), row = 0, column = 2, sticky = "ne", padx = 10, pady = 10) 1889 tcltk::tkgrid(but.frame, row = 2, column = 1, sticky = "ne") 1890 tcltk::tkgrid.rowconfigure(priorsBox, 1, weight = 1) 1891 tcltk::tkgrid.columnconfigure(priorsBox, 0, weight = 1) 1892 tcltk::tkgrid.columnconfigure(priorsBox, 1, weight = 1) 1893 tcltk::tkgrid(priorsBox, row = 0, column = 0, sticky = "news") 1894 tcltk::tkgrid.rowconfigure(getAmelia("priorsWindow"), 0, weight = 1) 1895 tcltk::tkgrid.columnconfigure(getAmelia("priorsWindow"), 0, weight = 1) 1896 1897 tcltk::tkwm.protocol(getAmelia("priorsWindow"), "WM_DELETE_WINDOW", function() {tcltk::tkwm.withdraw(getAmelia("priorsWindow"));tcltk::tkgrab.release(getAmelia("priorsWindow"));tcltk::tkfocus(getAmelia("gui"))}) 1898 1899 centerModalDialog(getAmelia("priorsWindow"), resize = TRUE) 1900 1901 bindTooltip(widget = "priors.tree", "Currently set observation-level priors for the data. You can remove these using the right-click menu.") 1902 bindTooltip(widget = "pri.ok", tip = "Save changes and close window.") 1903 bindTooltip(widget = "pri.can", tip = "Cancel any changes and close window.") 1904 bindTooltip(widget = "prior.add.but", tip = "Add the above prior for the selected observation and variable to the list of priors for this data set.") 1905 bindTooltip(widget = "meanBox", tip = "The mean of a normal prior distribution on the value of the selected missing cell.") 1906 bindTooltip(widget = "sdBox", tip = "The standard deviation of a normal prior distribution on the value of the selected missing cell.") 1907 bindTooltip(widget = "add.dist.case", tip = "Select the case name or row number of the case for the cell-level prior.") 1908 bindTooltip(widget = "add.dist.var", tip = "Select the variable name for the cell-level prior.") 1909 bindTooltip(widget = "confBox", tip = "A confidence level between 0 and 1 for the confidence bound on the distribution of the selected missing cell. These confidence bounds are converted into a normal distribution prior on the value.") 1910 bindTooltip(widget = "minBox", tip = "A lower confidence bound on the distribution of the selected missing cell. These confidence bounds are converted into a normal distribution prior on the value.") 1911 bindTooltip(widget = "maxBox", tip = "An upper confidence bound on the distribution of the selected missing cell. These confidence bounds are converted into a normal distribution prior on the value.") 1912 bindTooltip(widget = "add.range.case", tip = "Select the case name or row number of the case for the cell-level prior.") 1913 bindTooltip(widget = "add.range.var", tip = "Select the variable name for the cell-level prior.") 1914} 1915 1916 1917 1918gui.diag.setup <- function() { 1919 1920 if (exists("diagWindow", envir = ameliaEnv)) { 1921 tcltk::tkwm.deiconify(getAmelia("diagWindow")) 1922 tcltk::tkraise(getAmelia("diagWindow")) 1923 tcltk::tkfocus(getAmelia("diagWindow")) 1924 return() 1925 } 1926 putAmelia("diagWindow", tcltk::tktoplevel()) 1927 tcltk::tkwm.title(getAmelia("diagWindow"), "Diagnostics") 1928 1929 diagBox <- tcltk::ttkframe(getAmelia("diagWindow")) 1930 gui.top<-tcltk::ttkpanedwindow(diagBox, orient = "vertical") 1931 var.diags <- tcltk::ttklabelframe(gui.top, text = "Individual Variable Plots", width = 100, height = 100) 1932 tscs.diags <- tcltk::ttklabelframe(gui.top, text = "Time-Series Cross-Sectional Plots", width = 100, height = 100) 1933 disp.diags <- tcltk::ttklabelframe(gui.top, text = "Overdispersion Plots", width = 100, height = 100) 1934 1935 tcltk::tcl("set","indvar","") 1936 1937 ## get variable names that are actually numeric 1938 variables <- getAmelia("varnames") 1939 variables <- variables[sapply(getAmelia("amelia.data"), is.numeric)] 1940 1941 putAmelia("var.diags.combo", tcltk::ttkcombobox(var.diags,textvariable="indvar", 1942 values = variables, state = "readonly")) 1943 indvar.lab <- tcltk::ttklabel(var.diags, text = "Variable:") 1944 var.button.frame <- tcltk::ttkframe(var.diags) 1945 putAmelia("diag.but.compare",tcltk::ttkbutton(var.button.frame, text="Compare", 1946 command = function() compare.density(getAmelia("ameliaObject"), 1947 var=tcltk::tclvalue("indvar"),frontend=TRUE))) 1948 1949 putAmelia("diag.overimp",tcltk::ttkbutton(var.button.frame,text="Overimpute",state="normal", 1950 command = function() overimpute(getAmelia("ameliaObject"), 1951 var=tcltk::tclvalue("indvar"),frontend=TRUE))) 1952 tcltk::tcl(getAmelia("var.diags.combo"), "current", 0) 1953 tcltk::tkgrid(indvar.lab, row = 0, column = 0, padx = 5) 1954 tcltk::tkgrid(getAmelia("var.diags.combo"), row = 0, column = 1, padx = 10, pady = 10) 1955 tcltk::tkgrid(getAmelia("diag.but.compare"), row = 0, column = 0, padx = 10, pady = 10) 1956 tcltk::tkgrid(getAmelia("diag.overimp"), row = 0, column = 1, padx = 10, pady = 10) 1957 tcltk::tkgrid(var.button.frame, row =0, column = 2) 1958 tcltk::tkgrid(tcltk::ttkframe(var.diags, width = 50, height = 0), row = 1) 1959 1960 1961 ## tscs plots 1962 csvar <- getAmelia("ameliaObject")$arguments$cs 1963 tsvar <- getAmelia("ameliaObject")$arguments$ts 1964 1965 ## can't do tscsplots for the ts or cs variable 1966 tscsvariables <- variables[variables != getAmelia("varnames")[csvar] & 1967 variables != getAmelia("varnames")[tsvar]] 1968 1969 if (is.null(tsvar) | is.null(csvar)) { 1970 st <- "disabled" 1971 but.st <- st 1972 } else { 1973 st <- "readonly" 1974 but.st <- "normal" 1975 } 1976 if (!is.null(csvar)) { 1977 cases <- unique(getAmelia("amelia.data")[,csvar]) 1978 if (is.factor(getAmelia("amelia.data")[,csvar])) { 1979 cases <- levels(getAmelia("amelia.data")[,csvar])[cases] 1980 } 1981 1982 } else { 1983 cases <- 1:nrow(getAmelia("amelia.data")) 1984 } 1985 tcltk::tcl("set", "casename","") 1986 tcltk::tcl("set", "tscsvarname", "") 1987 putAmelia("tscs.case.combo", 1988 tcltk::ttkcombobox(tscs.diags,textvariable="casename", values = cases, 1989 state = st)) 1990 putAmelia("tscs.var.combo", 1991 tcltk::ttkcombobox(tscs.diags,textvariable="tscsvarname", 1992 values = tscsvariables, state = st)) 1993 putAmelia("tscs.plot.but", 1994 tcltk::ttkbutton(tscs.diags, text = "TSCS Plot", state = but.st, 1995 command = function() tscsPlot(getAmelia("ameliaObject"), 1996 cs = tcltk::tclvalue("casename"), 1997 var = tcltk::tclvalue("tscsvarname"), 1998 frontend = TRUE))) 1999 if (st == "readonly") { 2000 tcltk::tcl(getAmelia("tscs.case.combo"), "current", 0) 2001 tcltk::tcl(getAmelia("tscs.var.combo"), "current", 0) 2002 } 2003 tcltk::tkgrid(tcltk::ttklabel(tscs.diags, text = "Case:"), row = 0, column = 0, sticky = "e", padx = 5) 2004 tcltk::tkgrid(getAmelia("tscs.case.combo"), row = 0, column = 1, padx = 10, pady = 10) 2005 tcltk::tkgrid(tcltk::ttklabel(tscs.diags, text = "Variable:"), row = 1, column = 0, sticky = "e", padx = 5) 2006 tcltk::tkgrid(getAmelia("tscs.var.combo"), row = 1, column = 1, padx = 10, pady = 10) 2007 tcltk::tkgrid(getAmelia("tscs.plot.but"), row = 1, column = 2, padx = 10, pady = 10, sticky = "se") 2008 tcltk::tkgrid(tcltk::ttkframe(tscs.diags, width = 50, height = 0), row = 2) 2009 2010 dimvalue<-tcltk::tclVar("1") 2011 putAmelia("onedim", tcltk::ttkradiobutton(disp.diags, variable=dimvalue, value="1")) 2012 putAmelia("twodims", tcltk::ttkradiobutton(disp.diags, variable=dimvalue, value="2")) 2013 disp.imps.tcl<-tcltk::tclVar("5") 2014 putAmelia("disp.imps", tcltk::ttkentry(disp.diags,width="5",textvariable=disp.imps.tcl)) 2015 putAmelia("disp.but", tcltk::ttkbutton(disp.diags,text="Overdisperse",state="normal", 2016 command = function() disperse(m=as.numeric(tcltk::tclvalue(disp.imps.tcl)), 2017 dims=as.numeric(tcltk::tclvalue(dimvalue)),frontend=TRUE,output=getAmelia("ameliaObject")))) 2018 tcltk::tkgrid(tcltk::ttklabel(disp.diags,text="Number of dispersions:"),row=2,column=1, 2019 sticky="e") 2020 tcltk::tkgrid(tcltk::ttkframe(disp.diags, width = 50, height = 0), row = 5) 2021 tcltk::tkgrid(getAmelia("disp.imps"),column=2,row=2,sticky="nw", padx = 10, pady = 10) 2022 tcltk::tkgrid(tcltk::ttklabel(disp.diags,text="One Dimension:"),row=3,column=1, sticky = "e") 2023 tcltk::tkgrid(tcltk::ttklabel(disp.diags,text="Two Dimensions:"),row=4,column=1, sticky = "e") 2024 tcltk::tkgrid(getAmelia("onedim"),row=3,column=2,padx=10,pady=5) 2025 tcltk::tkgrid(getAmelia("twodims"),row=4,column=2,padx=10) 2026 tcltk::tkgrid(getAmelia("disp.but"),row=4,column=3,padx=15, pady=10,sticky="news") 2027 2028 tcltk::tkadd(gui.top, var.diags) 2029 tcltk::tkadd(gui.top, tscs.diags) 2030 tcltk::tkadd(gui.top, disp.diags) 2031 tcltk::tkgrid(gui.top, row = 0, padx = 20, pady = 20) 2032 tcltk::tkgrid(diagBox, sticky = "news", row = 0, column = 0) 2033 tcltk::tkgrid.rowconfigure(getAmelia("diagWindow"), 0, weight = 1) 2034 tcltk::tkgrid.columnconfigure(getAmelia("diagWindow"), 0, weight = 1) 2035 2036 tcltk::tkwm.protocol(getAmelia("diagWindow"), "WM_DELETE_WINDOW", function() {tcltk::tkwm.withdraw(getAmelia("diagWindow"));tcltk::tkgrab.release(getAmelia("diagWindow"));tcltk::tkfocus(getAmelia("gui"))}) 2037 centerModalDialog(getAmelia("diagWindow"), resize = FALSE) 2038 2039 bindTooltip(widget = "var.diags.combo", tip = "Variable for either the density comparison plot or the overimputation plot.") 2040 bindTooltip(widget = "tscs.var.combo", tip = "Variable to use for the time-series cross-sectional plot.") 2041 bindTooltip(widget = "tscs.case.combo", tip = "Case to use for the time-series cross-sectional plot.") 2042 bindTooltip(widget = "diag.but.compare", tip = "Compare densities of the imputed values vs. observed values.") 2043 bindTooltip(widget = "diag.overimp", tip = "Overimpute and graph confidence intervals. ") 2044 2045 bindTooltip(widget = "disp.but", tip = "Plot the convergence of the EM algorithm from overdispersed starting values.") 2046 2047 bindTooltip(widget = "tscs.plot.but", tip = "Plot a time-series within one cross-section with imputation distributions in red.") 2048 2049 bindTooltip(widget = "disp.imps", tip = "Number of different overdispersed starting values to use.") 2050 2051 bindTooltip(widget = "onedim", tip = "Number of dimensions to visualize convergence.") 2052 2053 bindTooltip(widget = "twodims", tip = "Number of dimensions to visualize convergence.") 2054 2055} 2056 2057 2058## the following functions have been imported from Rcmdr 2059 2060putAmelia <- function(x, value) { 2061 assign(x, value, envir = ameliaEnv) 2062} 2063 2064getAmelia <- function(x, mode="any") 2065 get(x, envir = ameliaEnv, mode = mode, inherits = FALSE) 2066 2067 2068getAmeliaInd <- function(x) { 2069 as.numeric(tcltk::tkindex(getAmelia(x), "current")) 2070} 2071ameliaTclSet <- function(name, value){ 2072 name <- ls(unclass(getAmelia(name))$env) 2073 tcltk::tcl("set", name, value) 2074} 2075 2076save.log <- function() { 2077 file.select <- tcltk::tclvalue(tcltk::tkgetSaveFile(parent=getAmelia("gui"), filetypes="{{Text files} {*.txt}} {{All files} *}")) 2078 cat(getAmelia("output.log"), file = file.select) 2079} 2080 2081show.output.log <- function() { 2082 2083 RightClick <- function(x, y) { # x and y are the mouse coordinates 2084 rootx <- as.integer(tcltk::tkwinfo("rootx", getAmelia("log.viewer"))) # tcltk::tkwinfo() return several infos 2085 rooty <- as.integer(tcltk::tkwinfo("rooty", getAmelia("log.viewer"))) 2086 xTxt <- as.integer(x) + rootx 2087 yTxt <- as.integer(y) + rooty 2088 # Create a Tcl command in a character string and run it 2089 tcltk::.Tcl(paste("tk_popup", tcltk::.Tcl.args(getAmelia("log.right.click"), xTxt, yTxt))) 2090 } 2091 2092 2093 if (exists("log.top", envir = ameliaEnv)) { 2094 tcltk::tkconfigure(getAmelia("log.viewer"), state = "normal") 2095 tcltk::tkdelete(getAmelia("log.viewer"), "0.0", "end") 2096 tcltk::tkinsert(getAmelia("log.viewer"), "end", 2097 paste(getAmelia("output.log"), collapse = "")) 2098 tcltk::tkconfigure(getAmelia("log.viewer"), state = "disabled") 2099 tcltk::tkwm.deiconify(getAmelia("log.top")) 2100 tcltk::tkraise(getAmelia("log.top")) 2101 tcltk::tkfocus(getAmelia("log.top")) 2102 return() 2103 } 2104 putAmelia("log.top", tcltk::tktoplevel()) 2105 tcltk::tkwm.title(getAmelia("log.top"), "Output Log") 2106 scr <- tcltk::ttkscrollbar(getAmelia("log.top"), 2107 command=function(...)tcltk::tkyview(getAmelia("log.viewer"),...)) 2108 2109 putAmelia("log.viewer", tcltk::tktext(getAmelia("log.top"), width = 80, height = 25, 2110 yscrollcommand=function(...)tcltk::tkset(scr,...))) 2111 tcltk::tkinsert(getAmelia("log.viewer"), "end", paste(getAmelia("output.log"), collapse = "")) 2112 tcltk::tkconfigure(getAmelia("log.viewer"), state = "disabled") 2113 main.menu <- tcltk::tkmenu(getAmelia("log.top")) 2114 main.menu.file <- tcltk::tkmenu(main.menu, tearoff=0) 2115 tcltk::tkadd(main.menu.file,"command",label="Save log file",command=function() save.log()) 2116 tcltk::tkadd(main.menu.file,"command",label="Close",command=function(){tcltk::tkwm.withdraw(getAmelia("log.top"));tcltk::tkgrab.release(getAmelia("log.top"));tcltk::tkfocus(getAmelia("gui"))}) 2117 2118 tcltk::tkadd(main.menu,"cascade",label="File",menu=main.menu.file) 2119 tcltk::tkconfigure(getAmelia("log.top"),menu=main.menu) 2120 2121 2122 putAmelia("log.right.click",tcltk::tkmenu(getAmelia("log.viewer"), tearoff = FALSE) ) 2123 tcltk::tkadd(getAmelia("log.right.click"), "command", label = "Copy <Ctrl-V>", 2124 command = function() tcltk::tkevent.generate(getAmelia("log.viewer"),"<<Copy>>")) 2125 tcltk::tkbind(getAmelia("log.viewer"), "<Button-3>", RightClick) 2126 2127 #tcltk::tkgrid(main.menu, row = 0, sticky = "ew") 2128 tcltk::tkgrid(getAmelia("log.viewer"), row = 0, column = 0, sticky = "news") 2129 tcltk::tkgrid(scr, row =0, column = 1, sticky = "ns") 2130 #tcltk::tkgrid.columnconfigure(log.top, 1, weight = 1) 2131 tcltk::tkgrid.columnconfigure(getAmelia("log.top"), 0, weight = 1) 2132 tcltk::tkgrid.rowconfigure(getAmelia("log.top"), 0, weight = 1) 2133 tcltk::tkwm.protocol(getAmelia("log.top"), "WM_DELETE_WINDOW", function() {tcltk::tkwm.withdraw(getAmelia("log.top"));tcltk::tkgrab.release(getAmelia("log.top"));tcltk::tkfocus(getAmelia("gui"))}) 2134 centerModalDialog(getAmelia("log.top"), resize=TRUE) 2135 2136 2137} 2138 2139after <- function(ms, func) { 2140 tcltk::.Tcl(paste("after", ms, tcltk::.Tcl.callback(func))) 2141} 2142 2143cancel.after <- function(id) { 2144 invisible(tcltk::.Tcl(paste("after","cancel", id))) 2145} 2146 2147bindTooltip <- function(widget, tip) { 2148 after.name <- paste(widget, "after", sep = ".") 2149 tip.name <- paste(widget, "tip", sep = ".") 2150 # tcltk::tkbind(getAmelia(widget), "<Any-Enter>", showTooltip(widget, tip)) 2151 tcltk::tkbind(getAmelia(widget), "<Any-Enter>", function() putAmelia(after.name, after(400, showTooltip(widget, tip)))) 2152 tcltk::tkbind(getAmelia(widget), "<Any-Leave>", function() {killTooltip(widget) 2153 cancel.after(getAmelia(after.name))}) 2154 tcltk::tkbind(getAmelia(widget), "<Any-Button>", function() cancel.after(getAmelia(after.name))) 2155 tcltk::tkbind(getAmelia(widget), "<Any-KeyPress>", function() cancel.after(getAmelia(after.name))) 2156 2157} 2158 2159 2160 2161showTooltip <- function(widget, text) { 2162 2163 function() { 2164 if (getAmelia(widget)$ID != tcltk::tclvalue(tcltk::tkwinfo("containing", tcltk::tkwinfo("pointerx","."), 2165 tcltk::tkwinfo("pointery",".")))) { 2166 return() 2167 } 2168 tip.name <- paste(widget, "tip", sep = ".") 2169 tiplabel.name <- paste(widget, "tiplabel",sep=".") 2170 2171 2172 if (exists(tip.name, envir = ameliaEnv)) { 2173 if (as.logical(tcltk::tkwinfo("exists",getAmelia(tip.name)))) { 2174 if (as.logical(tcltk::tkwinfo("ismapped",getAmelia(tip.name)))) { 2175 return() 2176 } 2177 } 2178 } 2179 2180 2181 scrh <- tcltk::tclvalue(tcltk::tkwinfo("screenheight", getAmelia(widget))) 2182 scrw <- tcltk::tclvalue(tcltk::tkwinfo("screenwidth", getAmelia(widget))) 2183 2184 2185 tcltk::tclServiceMode(on=FALSE) 2186 if (!exists(tip.name, envir = ameliaEnv)) { 2187 if (.Platform$OS.type == "windows") { 2188 borderColor <- "SystemWindowFrame" 2189 bgColor <- "SystemWindow" 2190 fgColor <- "SystemWindowText" 2191 } else { 2192 borderColor <- "black" 2193 bgColor <- "lightyellow" 2194 fgColor <- "black" 2195 } 2196 putAmelia(tip.name, tcltk::tktoplevel(getAmelia(widget), bd = 1, bg = borderColor, relief = "raised")) 2197 tcltk::tkwm.geometry(getAmelia(tip.name), paste("+",scrh,"+",scrw,sep="")) 2198 tcltk::tcl("wm","overrideredirect", getAmelia(tip.name), 1) 2199 2200 putAmelia(tiplabel.name, tcltk::ttklabel(getAmelia(tip.name), background = bgColor, 2201 foreground = fgColor, text = text, justify = "left", 2202 wraplength=300)) 2203 tcltk::tkpack(getAmelia(tiplabel.name)) 2204 2205 tcltk::tkbind(getAmelia(tip.name), "<Any-Enter>", 2206 function() tcltk::tkwm.withdraw(getAmelia(tip.name))) 2207 tcltk::tkbind(getAmelia(tip.name), "<Any-Leave>", 2208 function() tcltk::tkwm.withdraw(getAmelia(tip.name))) 2209 tcltk::tkbind(getAmelia(tip.name), "<Any-Button>", 2210 function() tcltk::tkwm.withdraw(getAmelia(tip.name))) 2211 } 2212 2213 width <- as.numeric(tcltk::tclvalue(tcltk::tkwinfo("reqwidth", getAmelia(tiplabel.name)))) 2214 height <- as.numeric(tcltk::tclvalue(tcltk::tkwinfo("reqheight",getAmelia(tiplabel.name)))) 2215 2216 posX <- as.numeric(tcltk::tclvalue(tcltk::tkwinfo("pointerx","."))) 2217 posY <- as.numeric(tcltk::tclvalue(tcltk::tkwinfo("pointery","."))) + 25 2218 screen <- as.numeric(tcltk::tclvalue(tcltk::tkwinfo("screenwidth","."))) 2219 2220 # a.) Ad-hockery: Set positionX so the entire tooltip widget will be displayed. 2221 if ((posX + width) > screen) { 2222 posX <- posX - ((posX + width) - screen) - 3 2223 } 2224 tcltk::tclServiceMode(on = TRUE) 2225 tcltk::tkwm.geometry(getAmelia(tip.name), 2226 paste("+",posX,"+",posY,sep = "")) 2227 2228 tcltk::tkwm.deiconify(getAmelia(tip.name)) 2229 tcltk::tkraise(getAmelia(tip.name)) 2230 2231 2232 2233 } 2234} 2235 2236killTooltip <- function(widget) { 2237 tip.name <- paste(widget,"tip", sep = ".") 2238 if (exists(tip.name, envir = ameliaEnv)) { 2239 tcltk::tkwm.withdraw(getAmelia(tip.name)) 2240 } 2241} 2242 2243 2244refreshSelection <- function(tree) { 2245 all <- strsplit(tcltk::tclvalue(tcltk::tcl(tree,"children","")), " ")[[1]] 2246 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(tree, "selection")), " ")[[1]] 2247 bandTree() 2248 for (i in sel) { 2249 tcltk::tcl(tree, "item", i, tags = "selected") 2250 } 2251 return(NULL) 2252} 2253 2254variableOptionStatus <- function(sel) { 2255 states <- rep("normal", 15) 2256 classes <- sapply(getAmelia("amelia.data"), class)[sel] 2257 if (length(sel) ==0) { 2258 states <- rep("disabled", 15) 2259 return(states) 2260 } 2261 if (length(sel) > 1) 2262 states[c(1:4,15)] <- "disabled" 2263 if (!is.null(getAmelia("tsvar"))) 2264 if (getAmelia("tsvar") %in% sel) 2265 states[c(1:2,5:9,12:13,15)] <- "disabled" 2266 else 2267 states[3] <- "disabled" 2268 if (!is.null(getAmelia("csvar"))) 2269 if (getAmelia("csvar") %in% sel) 2270 states[c(1:2,5:9,12:13,15)] <- "disabled" 2271 else 2272 states[4] <- "disabled" 2273 if (is.null(getAmelia("tsvar"))) 2274 states[c(3,6:9)] <- "disabled" 2275 if (is.null(getAmelia("csvar"))) 2276 states[4] <- "disabled" 2277 if ("factor" %in% classes | "character" %in% classes) 2278 states[c(11,15)] <- "disabled" 2279 if (is.null(getAmelia("amelia.data"))) 2280 states <- rep("disabled", 15) 2281 return(states) 2282} 2283 2284variableOptionsPost <- function() { 2285 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2286 states <- variableOptionStatus(sel) 2287 for (i in 0:14) { 2288 if (tcltk::tclvalue(tcltk::tktype(getAmelia("main.menu.variables"), i)) != "separator") 2289 tcltk::tkentryconfigure(getAmelia("main.menu.variables"),i, state = states[i+1]) 2290 } 2291 return(NULL) 2292} 2293 2294mainTreeRightClick <- function(x, y) { # x and y are the mouse coordinates 2295 rootx <- as.integer(tcltk::tkwinfo("rootx", getAmelia("main.tree"))) # tcltk::tkwinfo() return several infos 2296 rooty <- as.integer(tcltk::tkwinfo("rooty", getAmelia("main.tree"))) 2297 xTxt <- as.integer(x) + rootx 2298 yTxt <- as.integer(y) + rooty 2299 # Create a Tcl command in a character string and run it 2300 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2301 states <- variableOptionStatus(sel) 2302 main.tree.right.click <- tcltk::tkmenu(getAmelia("main.tree"), tearoff = FALSE) 2303 main.tree.trans <- tcltk::tkmenu(getAmelia("main.tree"), tearoff = FALSE) 2304 tcltk::tkadd(main.tree.right.click, "command", label = "Set as Time-Series Variable", command = setTS, state = states[1]) 2305 tcltk::tkadd(main.tree.right.click, "command", label = "Set as Cross-Section Variable", command = setCS, state = states[2]) 2306 tcltk::tkadd(main.tree.right.click, "command", label = "Unset as Time-Series Variable", command = unsetTS, state = states[3]) 2307 tcltk::tkadd(main.tree.right.click, "command", label = "Unset as Cross-Section Variable", command = unsetCS, state = states[4]) 2308 tcltk::tkadd(main.tree.right.click,"separator") 2309 tcltk::tkadd(main.tree.right.click, "command", label = "Add Lag", command = function() addLag(), state = states[6]) 2310 tcltk::tkadd(main.tree.right.click, "command", label = "Add Lead", command = function() addLead(), state = states[7]) 2311 tcltk::tkadd(main.tree.right.click, "command", label = "Remove Lag", command = function() dropLag(), state = states[8]) 2312 tcltk::tkadd(main.tree.right.click, "command", label = "Remove Lead", command = function() dropLead(), state = states[9]) 2313 tcltk::tkadd(main.tree.right.click,"separator") 2314 2315 tcltk::tkadd(main.tree.right.click, "command", label = 2316 "Plot Histogram(s) of Selected", command = plotHist, state = states[10]) 2317 if (.Platform$OS.type == "windows") { 2318 tcltk::tkadd(main.tree.trans, "command", label = "Log", command = function(x) setTrans("logs")) 2319 tcltk::tkadd(main.tree.trans, "command", label = "Square Root", command = function(x) setTrans("sqrt")) 2320 tcltk::tkadd(main.tree.trans, "command", label = "Logistic", command = function(x) setTrans("lgstc")) 2321 tcltk::tkadd(main.tree.trans, "command", label = "Nominal", command = function(x) setTrans("noms")) 2322 tcltk::tkadd(main.tree.trans, "command", label = "Ordinal", command = function(x) setTrans("ords")) 2323 tcltk::tkadd(main.tree.trans, "command", label = "ID Variable", command = function(x) setTrans("idvar")) 2324 tcltk::tkadd(main.tree.right.click, "cascade", label = "Add Transformation...", menu = main.tree.trans, state = states[12]) 2325 } else { 2326 tcltk::tkadd(main.tree.right.click, "command", label = "Mark as Log", command = function(x) setTrans("logs"), state = states[12]) 2327 tcltk::tkadd(main.tree.right.click, "command", label = "Mark as Square Root", command = function(x) setTrans("sqrt"), state = states[12]) 2328 tcltk::tkadd(main.tree.right.click, "command", label = "Mark as Logistic", command = function(x) setTrans("lgstc"), state = states[12]) 2329 tcltk::tkadd(main.tree.right.click, "command", label = "Mark as Nominal", command = function(x) setTrans("noms"), state = states[12]) 2330 tcltk::tkadd(main.tree.right.click, "command", label = "Mark as Ordinal", command = function(x) setTrans("ords"), state = states[12]) 2331 tcltk::tkadd(main.tree.right.click, "command", label = "Mark as ID Variable", command = function(x) setTrans("idvar"), state = states[12]) 2332 } 2333 tcltk::tkadd(main.tree.right.click, "command", label = 2334 "Remove Transformations", command = dropTrans, state = states[13]) 2335 tcltk::tkadd(main.tree.right.click,"separator") 2336 tcltk::tkadd(main.tree.right.click, "command", label = 2337 "Add or Edit Bounds", command = addBounds, state = states[15]) 2338 tcltk::tkpopup(main.tree.right.click, xTxt, yTxt) 2339} 2340 2341addLag <- function() { 2342 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2343 tmp <- getAmelia("lags") 2344 tmp[sel] <- 1 2345 putAmelia("lags", tmp) 2346 for (i in sel) 2347 tcltk::tkset(getAmelia("main.tree"), i, "lag", "X") 2348 return() 2349} 2350addLead <- function() { 2351 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2352 tmp <- getAmelia("leads") 2353 tmp[sel] <- 1 2354 putAmelia("leads", tmp) 2355 for (i in sel) 2356 tcltk::tkset(getAmelia("main.tree"), i, "lead", "X") 2357 return() 2358} 2359dropLag <- function() { 2360 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2361 tmp <- getAmelia("lags") 2362 tmp[sel] <- 0 2363 putAmelia("lags", tmp) 2364 for (i in sel) 2365 tcltk::tkset(getAmelia("main.tree"), i, "lag", "") 2366 return() 2367} 2368dropLead <- function() { 2369 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2370 tmp <- getAmelia("leads") 2371 tmp[sel] <- 0 2372 putAmelia("leads", tmp) 2373 for (i in sel) 2374 tcltk::tkset(getAmelia("main.tree"), i, "lead", "") 2375 return() 2376} 2377 2378setTrans <- function(trans) { 2379 all.trans <- c(logs = "Log",sqrt = "Square Root", 2380 lgstc = "Logistic", noms = "Nominal", ords = "Ordinal", idvar = "ID") 2381 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2382 tmp <- getAmelia(trans) 2383 tmp[sel] <- 1 2384 putAmelia(trans, tmp) 2385 for (j in sel) { 2386 tcltk::tkset(getAmelia("main.tree"), j,"transform", all.trans[trans]) 2387 tcltk::tcl(getAmelia("main.tree"), "item", j, image = "") 2388 } 2389 return() 2390} 2391 2392dropTrans <- function() { 2393 all.trans <- c("logs","sqrt","lgstc","noms","ords","idvar") 2394 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), " ")[[1]] 2395 for (j in sel) 2396 tcltk::tkset(getAmelia("main.tree"), j,"transform", "") 2397 if (is.factor(getAmelia("amelia.data")[,j]) | 2398 is.character(getAmelia("amelia.data")[,j])) { 2399 tcltk::tcl(getAmelia("main.tree"), "item", j, image = getAmelia("redFlagIcon")) 2400 } 2401 2402 for (i in all.trans) { 2403 tmp <- getAmelia(i) 2404 tmp[sel] <- 0 2405 putAmelia(i, tmp) 2406 } 2407} 2408 2409addBounds <- function() { 2410 onOK <- function(sel) { 2411 2412 bdMax <- as.numeric(tcltk::tclvalue(getAmelia("boundMax"))) 2413 bdMin <- as.numeric(tcltk::tclvalue(getAmelia("boundMin"))) 2414 2415 if (is.na(bdMax) & !is.na(bdMin)) { 2416 tcltk::tkmessageBox(parent=getAmelia("addBoundsWindow"), title="Error", 2417 message="Please enter a minimum and a maximum value or neither to clear the bounds.", 2418 type="ok",icon="error") 2419 return() 2420 } 2421 if (!is.na(bdMax) & is.na(bdMin)) { 2422 tcltk::tkmessageBox(parent=getAmelia("addBoundsWindow"), title="Error", 2423 message="Please enter a minimum and a maximum value or neither to clear the bounds.", 2424 type="ok",icon="error") 2425 return() 2426 } 2427 2428 if (!is.na(bdMax) & !is.na(bdMin)) { 2429 if (bdMax <= bdMin) { 2430 tcltk::tkmessageBox(parent=getAmelia("addBoundsWindow"), title="Error", 2431 message="The maximum is less than the minimum.", 2432 type="ok",icon="error") 2433 return() 2434 } 2435 } 2436 tmpbmat <- getAmelia("boundsmat") 2437 tmpbmat[sel,2:3] <- c(bdMin, bdMax) 2438 putAmelia("boundsmat", tmpbmat) 2439 if (!is.na(bdMin)) { 2440 treeBounds <- paste("[",bdMin,", ", bdMax,"]", sep = "") 2441 } else { 2442 treeBounds <- "" 2443 } 2444 tcltk::tkset(getAmelia("main.tree"), sel, "bounds", treeBounds) 2445 tcltk::tkwm.withdraw(getAmelia("addBoundsWindow")) 2446 tcltk::tkgrab.release(getAmelia("addBoundsWindow")) 2447 tcltk::tkfocus(getAmelia("gui")) 2448 return() 2449 } 2450 validateNumeric <- function(x) { 2451 if (isTRUE(grep("(^-?[0-9]*\\.?[0-9]*$)",x)==1)) 2452 return(tcltk::tclVar("TRUE")) 2453 else 2454 return(tcltk::tclVar("FALSE")) 2455 } 2456 2457 2458 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), 2459 " ")[[1]] 2460 if (sum(is.na(getAmelia("amelia.data")[,sel])) == 0) { 2461 tcltk::tkmessageBox(parent = getAmelia("gui"), message = 2462 "No missing data on the selected variable.", type = "ok") 2463 return() 2464 2465 } 2466 currMin <- getAmelia("boundsmat")[sel,2] 2467 currMax <- getAmelia("boundsmat")[sel,3] 2468 2469 putAmelia("boundMin", tcltk::tclVar(ifelse(is.na(currMin), "", 2470 currMin))) 2471 putAmelia("boundMax", tcltk::tclVar(ifelse(is.na(currMax), "", 2472 currMax))) 2473 2474 if (exists("addBoundsWindow", envir = ameliaEnv)) { 2475 tcltk::tkconfigure(getAmelia("maxBox"), textvar = getAmelia("boundMax")) 2476 tcltk::tkconfigure(getAmelia("minBox"), textvar = getAmelia("boundMin")) 2477 tcltk::tkconfigure(getAmelia("bd.ok"), command = function() onOK(sel)) 2478 tcltk::tkwm.deiconify(getAmelia("addBoundsWindow")) 2479 tcltk::tkraise(getAmelia("addBoundsWindow")) 2480 return() 2481 } 2482 putAmelia("addBoundsWindow", tcltk::tktoplevel()) 2483 tcltk::tkwm.title(getAmelia("addBoundsWindow"), "Add or Edit Bounds") 2484 bounds.add <- tcltk::ttkframe(getAmelia("addBoundsWindow")) 2485 2486 2487 putAmelia("minBox", tcltk::ttkentry(bounds.add, textvar=getAmelia("boundMin"), validate="key", 2488 validatecommand = function(P) validateNumeric(P))) 2489 2490 putAmelia("maxBox", tcltk::ttkentry(bounds.add, textvar=getAmelia("boundMax"), validate="key", 2491 validatecommand = function(P) validateNumeric(P))) 2492 2493 tcltk::tkgrid(tcltk::ttklabel(bounds.add, text="Minimum:"), column=1, row=2, 2494 sticky = "e", padx = 10, pady = 10) 2495 tcltk::tkgrid(tcltk::ttklabel(bounds.add, text="Maximum:"), column=1, row=3, 2496 sticky = "e", padx = 10, pady = 10) 2497 2498 tcltk::tkgrid(getAmelia("minBox"), column=2, row=2, pady=5, padx=5) 2499 tcltk::tkgrid(getAmelia("maxBox"), column=2, row=3, pady=5, padx=5) 2500 but.frame <- tcltk::ttkframe(bounds.add) 2501 putAmelia("bd.ok", tcltk::ttkbutton(but.frame, text = "OK", command = function() onOK(sel))) 2502 putAmelia("bd.can", tcltk::ttkbutton(but.frame, text = "Cancel", width = 2503 10, command = function() {tcltk::tkwm.withdraw(getAmelia("addBoundsWindow"));tcltk::tkgrab.release(getAmelia("addBoundsWindow"));tcltk::tkfocus(getAmelia("gui"))})) 2504 tcltk::tkgrid(getAmelia("bd.ok"), row = 0, column = 1, sticky = "ne", padx = 10, pady = 10) 2505 tcltk::tkgrid(getAmelia("bd.can"), row = 0, column = 2, sticky = "ne", padx = 10, pady = 10) 2506 tcltk::tkgrid(but.frame, row = 4, column = 1, columnspan = 2, sticky = 2507 "ne") 2508 tcltk::tkgrid(bounds.add, sticky = "news") 2509 2510 tcltk::tkwm.protocol(getAmelia("addBoundsWindow"), "WM_DELETE_WINDOW", function() {tcltk::tkwm.withdraw(getAmelia("addBoundsWindow"));tcltk::tkgrab.release(getAmelia("addBoundsWindow"));tcltk::tkfocus(getAmelia("gui"))}) 2511 2512 centerModalDialog(getAmelia("addBoundsWindow"), resize=FALSE) 2513} 2514 2515 2516plotHist <- function() { 2517 sel <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), "selection")), 2518 " ")[[1]] 2519 if (length(sel)==0) { 2520 tcltk::tkmessageBox(parent = getAmelia("gui"), type = "ok", message = 2521 "No variable selected.") 2522 return(NULL) 2523 } 2524 sel <- sel[which(sapply(getAmelia("amelia.data")[sel], is.numeric))] 2525 if (length(sel)==0) { 2526 tcltk::tkmessageBox(parent = getAmelia("gui"), type = "ok", message = 2527 "Cannot plot non-numeric variables.") 2528 return(NULL) 2529 } 2530 dev.new() 2531 mfrow <- set.mfrow(nvars = length(sel)) 2532 on.exit(par(NULL)) 2533 layout <- par(mfrow = mfrow) 2534 j <- 0 2535 for (i in sel) { 2536 j <- j + 1 2537 if (j > 9) { 2538 j <- 1 2539 dev.new() 2540 layout <- par(mfrow = mfrow) 2541 } 2542 2543 hist(getAmelia("amelia.data")[,i], 2544 main = paste("Histogram of",i), ylab = "Frequnecy", 2545 xlab ="", col="grey", border = "white") 2546 2547 } 2548 invisible() 2549 2550} 2551 2552 2553sortTreeBy <- function(col) { 2554 coldata <- c() 2555 children <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), 2556 "children","")), " ")[[1]] 2557 2558 if (col == "#0") { 2559 coldata <- children 2560 } else { 2561 for (i in children) { 2562 coldata <- c(coldata, tcltk::tclvalue(tcltk::tkset(getAmelia("main.tree"), i, col))) 2563 } 2564 } 2565 dirs <- getAmelia("sortDirs") 2566 sortDir <- dirs[col] 2567 if (col %in% c("mean", "sd", "min", "max")) { 2568 coldata[coldata == "..."] <- "-Inf" 2569 coldata[coldata == "(factor)"] <- "-Inf" 2570 sortOrder <- order(as.numeric(coldata), decreasing = sortDir) 2571 } else if (col == "miss") { 2572 coldata <- matrix(unlist(strsplit(coldata,"/")), nrow=2)[1,] 2573 sortOrder <- order(as.numeric(coldata), decreasing = sortDir) 2574 } else { 2575 sortOrder <- order(coldata, decreasing = sortDir) 2576 } 2577 2578 2579 sorted <- children[sortOrder] 2580 for (i in 1:length(children)) { 2581 tcltk::tkmove(getAmelia("main.tree"), sorted[i],"", i-1) 2582 } 2583 drawArrow(col, sortDir) 2584 refreshSelection(getAmelia("main.tree")) 2585 dirs[col] <- !sortDir 2586 putAmelia("sortDirs", dirs) 2587} 2588 2589drawArrow <- function(col, down) { 2590 treecols <- names(getAmelia("sortDirs")) 2591 for (i in treecols) { 2592 tcltk::tcl(getAmelia("main.tree"), "heading", i, image = "") 2593 } 2594 if (down) { 2595 tcltk::tcl(getAmelia("main.tree"), "heading", col, 2596 image = getAmelia("upArrowIcon")) 2597 } else { 2598 tcltk::tcl(getAmelia("main.tree"), "heading", col, 2599 image = getAmelia("downArrowIcon")) 2600 } 2601 return(NULL) 2602} 2603 2604bandTree <- function() { 2605 children <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"), 2606 "children","")), " ")[[1]] 2607 j <- 0 2608 tcltk::tktag.configure(getAmelia("main.tree"),"white", background="white") 2609 tcltk::tktag.configure(getAmelia("main.tree"),"gray", background="gray92") 2610 for (i in children) { 2611 j <- j+1 2612 if ((j %% 2) == 0) { 2613 tcltk::tcl(getAmelia("main.tree"), "item", i, tag = "white") 2614 } else { 2615 tcltk::tcl(getAmelia("main.tree"), "item", i, tag = "gray") 2616 } 2617 } 2618} 2619 2620updateTreeStats <- function(){ 2621 children <- strsplit(tcltk::tclvalue(tcltk::tcl(getAmelia("main.tree"),"children","")), " ")[[1]] 2622 for (i in names(getAmelia("amelia.data"))) { 2623 2624 if (is.factor(getAmelia("amelia.data")[,i]) | 2625 is.character(getAmelia("amelia.data")[,i])) { 2626 vals <- c("(factor)","...","...","...") 2627 vals <- c(vals,paste(sum(is.na(getAmelia("amelia.data")[,i])), 2628 nrow(getAmelia("amelia.data")), sep="/")) 2629 } else { 2630 vals <- c(min(getAmelia("amelia.data")[,i],na.rm=T), max(getAmelia("amelia.data")[,i],na.rm=T), 2631 mean(getAmelia("amelia.data")[,i],na.rm=T), sd(getAmelia("amelia.data")[,i],na.rm=T)) 2632 vals <- signif(vals, digits = 4) 2633 vals <- c(vals, paste(sum(is.na(getAmelia("amelia.data")[,i])), 2634 nrow(getAmelia("amelia.data")), sep="/")) 2635 } 2636 tcltk::tkset(getAmelia("main.tree"), i, "min", vals[1]) 2637 tcltk::tkset(getAmelia("main.tree"), i, "max", vals[2]) 2638 tcltk::tkset(getAmelia("main.tree"), i, "mean", vals[3]) 2639 tcltk::tkset(getAmelia("main.tree"), i, "sd", vals[4]) 2640 tcltk::tkset(getAmelia("main.tree"), i, "miss", vals[5]) 2641 } 2642 2643 2644} 2645 2646centerModalDialog <- function(window, resize=TRUE) { 2647 xpos <- as.numeric(tcltk::tkwinfo("rootx",getAmelia("gui"))) 2648 ypos <- as.numeric(tcltk::tkwinfo("rootx",getAmelia("gui"))) 2649 rwidth <- as.numeric(tcltk::tkwinfo("width",getAmelia("gui"))) 2650 rheight <- as.numeric(tcltk::tkwinfo("height", getAmelia("gui"))) 2651 width <- as.numeric(tcltk::tkwinfo("reqwidth",window)) 2652 height <- as.numeric(tcltk::tkwinfo("reqheight",window)) 2653 newxpos <- xpos + .5*rwidth - .5*width 2654 newypos <- ypos + .5*rheight - .5*height 2655 if (.Platform$OS.type == "windows") 2656 tcltk::tkwm.geometry(window, paste("+",round(newxpos),"+",round(newypos),sep="")) 2657 tcltk::tkfocus(window) 2658 tcltk::tkgrab.set(window) 2659 if (!resize) { 2660 tcltk::tkwm.resizable(window, 0,0) 2661 } 2662 tcltk::tkwm.transient(window, getAmelia("gui")) 2663 tcltk::tcl("update","idletasks") 2664} 2665 2666 2667showImputedFiles <- function() { 2668 if (Sys.info()['sysname'] %in% c("Windows", "Darwin")) 2669 system(paste("open", shQuote(getAmelia("wdForLastImputation")))) 2670 else 2671 system(paste("xdg-open", shQuote(getAmelia("wdForLastImputation")))) 2672 return(NULL) 2673} 2674 2675 2676## Here is (finally) a decent solution to the tcl/tk issues with 2677## global variables. Here we create new environment, whose parent is 2678## the Amelia namespace. We then make sure that all of the GUI 2679## functions use that as their enclosure. This means that any of these 2680## functions can use values in the ameliaEnv. This eliminates the need 2681## for any "getAmelia" calls, but we still have to be careful since 2682## assigning values in these functions is local and doesn't 2683## automatically add the value to ameliaEnv. So, for assigning, 2684## 'putAmelia' probably still makes sense. We could use 2685## assign("foo", "bar", envir = parent.frame()) 2686## but putAmelia is probably more clear. getAmelia() is probably still 2687## a little more safe to use because it will throw an error if 2688## something is missing, whereas relying on lexical scoping will try 2689## to use something with the same name in the search path. 2690ameliaEnv <- new.env() 2691environment(main.close) <- ameliaEnv 2692environment(setWorkingDir) <- ameliaEnv 2693environment(loadStata) <- ameliaEnv 2694environment(loadSPSS) <- ameliaEnv 2695environment(loadSAS) <- ameliaEnv 2696environment(loadTAB) <- ameliaEnv 2697environment(loadCSV) <- ameliaEnv 2698environment(loadRData) <- ameliaEnv 2699environment(loadDemo) <- ameliaEnv 2700environment(drawMissMap) <- ameliaEnv 2701environment(activateGUI) <- ameliaEnv 2702environment(save.session) <- ameliaEnv 2703environment(load.session) <- ameliaEnv 2704environment(run.amelia) <- ameliaEnv 2705environment(amelia.save) <- ameliaEnv 2706environment(set.out) <- ameliaEnv 2707environment(setTS) <- ameliaEnv 2708environment(unsetTS) <- ameliaEnv 2709environment(setCS) <- ameliaEnv 2710environment(unsetCS) <- ameliaEnv 2711environment(fillMainTree) <- ameliaEnv 2712environment(AmeliaView) <- ameliaEnv 2713environment(buildNumericalOptions) <- ameliaEnv 2714environment(buildOutputOptions) <- ameliaEnv 2715environment(buildAboutDialog) <- ameliaEnv 2716environment(gui.pri.setup) <- ameliaEnv 2717environment(gui.diag.setup) <- ameliaEnv 2718environment(save.log) <- ameliaEnv 2719environment(show.output.log) <- ameliaEnv 2720environment(bindTooltip) <- ameliaEnv 2721environment(showTooltip) <- ameliaEnv 2722environment(killTooltip) <- ameliaEnv 2723environment(refreshSelection) <- ameliaEnv 2724environment(variableOptionStatus) <- ameliaEnv 2725environment(variableOptionsPost) <- ameliaEnv 2726environment(mainTreeRightClick) <- ameliaEnv 2727environment(addLag) <- ameliaEnv 2728environment(addLead) <- ameliaEnv 2729environment(dropLag) <- ameliaEnv 2730environment(dropLead) <- ameliaEnv 2731environment(setTrans) <- ameliaEnv 2732environment(dropTrans) <- ameliaEnv 2733environment(addBounds) <- ameliaEnv 2734environment(plotHist) <- ameliaEnv 2735environment(sortTreeBy) <- ameliaEnv 2736environment(drawArrow) <- ameliaEnv 2737environment(bandTree) <- ameliaEnv 2738environment(updateTreeStats) <- ameliaEnv 2739environment(centerModalDialog) <- ameliaEnv 2740environment(showImputedFiles) <- ameliaEnv 2741