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