x <- gconfirm("Run Program?",title="gConfirm")
if (x){
w <- gwindow(title="List of Programs",visible=TRUE)
g = ggroup(horizontal = FALSE, cont=w)
glabel("Please select the Program", cont=g)
ptype <- c("A","B")
temp <- gcombobox(ptype , cont=g)
addHandlerChanged(temp , handler=function(...){})
gbutton("Run", cont=g,handler = function(...){
print(svalue(temp)
dispose(g)
runagain <- gconfirm("Run again?",title="gConfirm")
if(runagain){
## If user clicks okay, I want to start running again from the third line of the code, w <- gwindow......)**
}
}
Can anyone hint a work around that? Also how do I display the svalue(temp) in to similar UI box instead of printing it on the console. Any help is much appreciated.
SOmething like this might get you what you want:
library(gWidgets2)
programs = list("Program A"="a.R",
"Program B" = "b.R")
w <- gwindow("run programs")
g <- ggroup(cont=w, horizontal=FALSE)
fl <- gformlayout(cont=g)
cb <- gcombobox(names(programs), cont=fl, label="Select a program to run")
b <- gbutton("Run selected program", cont=fl, label="", handler=function(h,...) {
prog <- svalue(cb)
val <- gconfirm(sprintf("Run program %s?", prog), parent=w)
if (val) {
source(programs[[val]])
gmessage("All done", parent=w)
}
})
Related
I am developing a topological data analysis app on R thanks to shiny and I have some trouble with one of my functions.
I would like to put those lines into the server as reactive elements:
l = length(V(aspargus.graph))
cc.maj.vertex <- c()
filter.vertex <- c()
for (i in 1:l){
points.in.vertex <- aspargus.mapper$points_in_vertex[[i]]
Mode.in.vertex <- Mode(normaspargus$`DataAspargus$Treatment`[points.in.vertex])
cc.maj.vertex <- c(cc.maj.vertex,as.character(Mode.in.vertex))
filter.vertex <- c(filter.vertex,mean(filter_list[points.in.vertex]))
}
vertex.size <- rep(0,l)
for (i in 1:l){
points.in.vertex <- aspargus.mapper$points_in_vertex[[i]]
vertex.size[i] <- length((aspargus.mapper$points_in_vertex[[i]]))
}
MapperNodes <- mapperVertices(aspargus.mapper, labels_pts )
MapperNodes$cc.maj.vertex <- as.factor(cc.maj.vertex)
MapperNodes$filter_list <- filter.vertex
MapperNodes$Nodesize <- vertex.size
MapperLinks <- mapperEdges(aspargus.mapper)
My main problems are for the for loop (lines 5 and 14), and the column change as:
MapperNodes$filter_list <- filter.vertex
At the moment my code looks like that:
server <- function (input, output){
l = reactive({length(V(data.mapper.graph()))})
reactive({for (i in 1:l()){
points.in.vertex <- reactive({data.mapper()$points_in_vertex[[i]]})
Mode.in.vertex <- reactive({Mode(X1()$`DataAspargus$Treatment`[points.in.vertex()])})
cc.maj.vertex <- reactive({c(cc.maj.vertex(),as.character(Mode.in.vertex()))})
filter.vertex <- reactive({c(filter.vertex(),mean(f()[points.in.vertex()]))})
}
})
vertex.size <- reactive({rep(0,l)})
reactive({for (i in 1:l){
points.in.vertex <- reactive({data.mapper()$points_in_vertex[[i]]})
vertex.size()[i] <- reactive({length((data.mapper()$points_in_vertex[[i]]))})
}
})
MapperNodes <- reactive({mapperVertices(data.mapper(), labels_pts )})
MapperNodes$cc.maj.vertex <- reactive({as.factor(cc.maj.vertex())})
MapperNodes$f <- reactive({filter.vertex()})
MapperNodes$Nodesize <- reactive({vertex.size()})
MapperLinks <- reactive({mapperEdges(data.mapper())})
As you can imagine, it is not working:
Error in MapperNodes$cc.maj.vertex <- reactive({ :
object of type 'closure' is not subsettable
I have tried to put bracket before MapperNodes, after etc...and I don't find any solution...
I hope someone will get an idea!
If you need any more details, feel free to ask :D
The way to resolve this problem is to put all the code inside the output function.
I am trying to build a GUI using gWidgets R library to download satellite imagery. The intention is to read the urls from a comma separated values file. The GUI looks ok but it does not do what I expect it to do. I am doing something wrong, any help is greatly appreciated.
Here is the sample data:
Online.Access.URLs <- c("http://e4ftl01.cr.usgs.gov//MODIS_Composites/MOLT/MOD09A1.005/2000.02.18/MOD09A1.A2000049.h09v06.005.2006268183648.hdf",
"http://e4ftl01.cr.usgs.gov//MODIS_Composites/MOLT/MOD09A1.005/2000.02.26/MOD09A1.A2000057.h09v06.005.2006270065224.hdf",
"http://e4ftl01.cr.usgs.gov//MODIS_Composites/MOLT/MOD09A1.005/2000.03.05/MOD09A1.A2000065.h09v06.005.2006269234536.hdf")
Producer.Granule.ID <- c("MOD09A1.A2000049.h09v06.005.2006268183648.hdf",
"MOD09A1.A2000057.h09v06.005.2006270065224.hdf",
"MOD09A1.A2000065.h09v06.005.2006269234536.hdf")
df <- data.frame(Producer.Granule.ID,Online.Access.URLs)
write.csv(df,"C:\\GUI_test\\h09v06v3.csv",row.names=FALSE)
And this is my try:
my.DownloadHDF <- function(){
library(gWidgets)
library(gWidgetstcltk)
library(RCurl)
options(guiToolkit = "tcltk")
win <- gwindow("Download HDF with R!", visible = FALSE)
csv.frame <- gframe("csv file ", container = win)
csv.label <- glabel("csv with HDF's names ", container = csv.frame)
csv.file.name <- gfilebrowse("Select csv file", type="open",cont=csv.frame,action="read.csv")
dir.frame <- gframe("Output Directory ", container = win)
dir.label <- glabel("Where to save HDF's? ", container = dir.frame)
dir.out <- gfilebrowse("Select folder ",type = "selectdir", cont=dir.frame)
dlw.frame <- gframe("Download ", container = win)
dlw.label <- glabel(" ", container = dlw.frame)
btnDwn <- gbutton("Start Download", container = dlw.frame,
handler = function(csv.file.name,dir.out){
df <- read.csv(csv.file.name, header=TRUE,sep=",")
hdf.urls <- df$Online.Access.URLs
hdf.urls <- as.character(hdf.urls)
hdf.names <- df$Producer.Granule.ID
hdf.names <- as.character(hdf.names)
for (i in 1:length(hdf.names)){
URL <- hdf.urls [i]
file <- hdf.names[i]
download.file(URL,paste(dir.out,file,sep=""),mode="wb")
cat(paste("Composite number ",i,"successfully downloaded!"),sep="\n")
cat("\n\n\n\n\n\n\n\n")
}})
visible(win) <- TRUE
}
my.DownloadHDF()
I am using R-3.2.2 with RStudio 0.98.1103.
Here is the script after the improvements. Now it does exactly what I expect it to do. I hope someone finds it useful:
# load functions ####
# download function
f.d <- function(hdf.urls,hdf.names,out.dir){
for(i in 1:length(hdf.urls)){
URL <- hdf.urls [i]
file <- hdf.names [i]
download.file(URL,paste(out.dir,"/",file,sep=""),mode="wb")
}}
# read csv function
f.csv <- function(x){
df1 <<- read.csv(x,header=TRUE,sep=",")
hdf.urls <<- df1$Online.Access.URLs
hdf.urls <<- as.character(hdf.urls)
hdf.names <<- df1$Producer.Granule.ID
hdf.names <<- as.character(hdf.names)
}
# load functions ####
# my.DownloadHDFv2 this one works fine ####
my.DownloadHDF <- function(){
options(guiToolkit = "tcltk")
win <- gwindow("Download HDF with R!", visible = FALSE)
csv.frame <- gframe("csv with HDFs names ", container = win)
a <- gfilebrowse("Upload csv file",cont=csv.frame,
handler=function(h,...){
f.csv(svalue(a))
})
path.frame <- gframe("Output Directory ", container = win)
brow <- gfilebrowse(text = "Select folder...", type = "selectdir",container=path.frame,
handler=function(h,...){
out.dir <<- svalue(brow)
})
b <- gbutton(text="Start Download",container = win,
handler = function(h,...){
f.d(hdf.urls,hdf.names,out.dir=out.dir)
})
visible(win)<-TRUE
}
my.DownloadHDF()
# my.DownloadHDFv2 this one works fine ####
Consider:
fix_df <- function(DF, ...) {
dfname <- deparse(substitute(DF))
w <- gbasicdialog(..., handler=function(h,...) {
assign(dfname, df[,], .GlobalEnv)
})
g <- ggroup(cont=w, horizontal=FALSE)
glabel("Edit a data frame", cont=g)
df <- gdf(DF, cont=g, expand=TRUE)
size(w) <- c(400, 400)
out <- visible(w)
}
m <- mtcars[1:3, 1:4]
fix_df(m)
How can I programmatically disable the OK button in w?
There is a do.buttons argument to not show the buttons. To access the button requires digging into the internals. You can see how that is hacked in where do.buttons is implemented in gWidgets2RGtk2.
This is probably so simple I will cringe when the answer comes back but I am totally stumped. I have tried the manuals, tried searching the web, assorted examples and anything else I can think of. I am still stuck.
I am trying to create a simple input for the user to add two values I can then use in the rest of the R script. I need the script to pause and wait for the input from the user and then continue along once it gets the input (like how the choose file function works). AFter reading a bunch of stuff I decided to use library(tcltk). I have a nice little box within a function.
inputs <- function(){
xvar <- tclVar("")
yvar <- tclVar("")
tt <- tktoplevel()
tkwm.title(tt,"Input Numbers")
x.entry <- tkentry(tt, textvariable=xvar)
y.entry <- tkentry(tt, textvariable=yvar)
reset <- function()
{
tclvalue(xvar)<-""
tclvalue(yvar)<-""
}
reset.but <- tkbutton(tt, text="Reset", command=reset)
submit <- function() {
x <- as.numeric(tclvalue(xvar))
y <- as.numeric(tclvalue(yvar))
print(x)
print(y)
tkdestroy(tt)
}
submit.but <- tkbutton(tt, text="submit", command=submit)
tkgrid(tklabel(tt,text="Enter Two Inputs"),columnspan=2)
tkgrid(tklabel(tt,text="Input1"), x.entry, pady = 10, padx =10)
tkgrid(tklabel(tt,text="Input2"), y.entry, pady = 10, padx =10)
tkgrid(submit.but, reset.but)
}
When I type in:
inputs()
The nice little box pops up and I can input my values, say 3 and 4 for this example.
I get back
<Tcl>
[1] 3
[1] 4
I want to use those number in a subsequent part of the R code. How do I get them so I can get the equivalent of this?
input1 <- 3
input2 <- 4
Thanks in advance for helping.
Here is a modification of your function:
inputs <- function(){
xvar <- tclVar("")
yvar <- tclVar("")
tt <- tktoplevel()
tkwm.title(tt,"Input Numbers")
x.entry <- tkentry(tt, textvariable=xvar)
y.entry <- tkentry(tt, textvariable=yvar)
reset <- function()
{
tclvalue(xvar)<-""
tclvalue(yvar)<-""
}
reset.but <- tkbutton(tt, text="Reset", command=reset)
submit <- function() {
x <- as.numeric(tclvalue(xvar))
y <- as.numeric(tclvalue(yvar))
e <- parent.env(environment())
e$x <- x
e$y <- y
tkdestroy(tt)
}
submit.but <- tkbutton(tt, text="submit", command=submit)
tkgrid(tklabel(tt,text="Enter Two Inputs"),columnspan=2)
tkgrid(tklabel(tt,text="Input1"), x.entry, pady = 10, padx =10)
tkgrid(tklabel(tt,text="Input2"), y.entry, pady = 10, padx =10)
tkgrid(submit.but, reset.but)
tkwait.window(tt)
return(c(x,y))
}
Now run the function like:
myvals <- inputs()
Now enter your 2 values and click "Submit", then look at the myvals variable, it contains your 2 values.
You have them in the submit callback -- you just need to put them somewhere. Sometimes global variables are best for this. Just use <<- to assign to them so the bindings happen outside of the scope of the submit callback. You can also use an environment for this purpose or even a reference class.
I have been trying to define multiple combo boxes in R using the tcltk package but to no avail. I am using the below code. My inspiration was here, however I can't seem to just label them comboBox1, comboBox2, etc... so I decided to try and set their output values into a vector... but their output values don't make any sense to me... any ideas out there?
many thanks
require(tcltk)
tclRequire("BWidget")
tt <- tktoplevel()
tkgrid(tklabel(tt,text="What's your favorite fruits?"))
fruit <- c("Apple","Orange","Banana","Pear")
num <- c(0:3)
num.fruit <- cbind(num, fruit)
#####1st box
comboBox <- tkwidget(tt,"ComboBox",editable=FALSE,values=num.fruit[,2])
tkgrid(comboBox)
Cbox1<- comboBox
tkfocus(tt)
######2nd box
comboBox <- tkwidget(tt,"ComboBox",editable=FALSE,values=num.fruit[,2])
tkgrid(comboBox)
Cbox2 <- comboBox
###
##preliminary wrap-ip to pass to OnOK function
pref1 <- tcl(Cbox1,"getvalue")
pref2 <- tcl(Cbox2,"getvalue")
Prefs <- c(pref1,pref2)
######action on OK button
OnOK <- function()
{
fruitChoice <- fruits[as.numeric(tclvalue(tcl(Prefs,"getvalue")))+1]
tkdestroy(tt)
msg <- paste("Good choice! ",fruitChoice,"s are delicious!",sep="")
tkmessageBox(title="Fruit Choice",message=msg)
}
OK.but <-tkbutton(tt,text=" OK ",command=OnOK)
tkgrid(OK.but)
tkfocus(tt)
Why don't you just use ttkcombobox?
require(tcltk)
tt <- tktoplevel()
tkwm.title(tt, "Fruits!")
tkwm.geometry(tt, "200x150+300+300")
onOK <- function()
{
fav <- tclvalue(favFruit)
worst <- tclvalue(worstFruit)
if (fav != "Choose one")
tkmessageBox(title="Favorite fruit", message = paste("Your favorite fruit is", fav))
if (worst != "Choose one")
tkmessageBox(title="Worst fruit", message = paste("The fruit you like the least is", worst))
if (fav == "Choose one" & worst == "Choose one")
tkmessageBox(title="Well...", message = "Select a fruit!")
}
label1 <- tklabel(tt, text="What's your favorite fruit?")
label2 <- tklabel(tt, text="What fruit you like the least?")
fruits <- c("Choose one", "Apple", "Orange", "Banana", "Pear")
# Default selections for the two combo boxes
favFruit <- tclVar("Choose one")
worstFruit <- tclVar("Choose one")
# 1st box
combo.1 <- ttkcombobox(tt, values=fruits, textvariable=favFruit, state="readonly")
# 2nd box
combo.2 <- ttkcombobox(tt, values=fruits, textvariable=worstFruit, state="readonly")
# If you need to do something when the user changes selection just use
# tkbind(combo.1, "<<ComboboxSelected>>", functionname)
OK.but <- tkbutton(tt,text=" OK ", command = onOK)
tkpack(label1, combo.1)
tkpack(label2, combo.2)
tkpack(OK.but)
tkfocus(tt)
PS: personally, I abandoned tcltk in favour of RGtk2, much more flexible in my opinion and you can design interfaces visually using Glade Interface Designer
If you don't want to get too involved with tcltk, you might find gWidgets easier to work with.
library(gWidgets)
options(guiToolkit="tcltk") ## or RGtk2 or Qt
w <- gwindow("Multiple comboboxes")
tbl <- glayout(cont=w, horizontal=FALSE)
fruit <- c("Apple","Orange","Banana","Pear")
tbl[1,1] <- "Favorite fuits"
tbl[1,2] <- (cb1 <- gcombobox(fruit, cont=tbl))
tbl[2,1] <- "Other fruit?"
tbl[2,2] <- (cb2 <- gcombobox(fruit, cont=tbl))
tbl[3,2] <- (b <- gbutton("Ok", cont=tbl))
addHandlerClicked(b, handler=function(h,...) {
cat(sprintf("You picked %s and %s\n", svalue(cb1), svalue(cb2)))
})