## Regression Demo with Data Sheet, check boxes, and slider. local({ require(RGtk) || stop("RGtk library not available") require(gtkDevice) || stop("gtkDevice library not available") require(MASS) ## Set up main window wRegDemo <- gtkWindow(show=FALSE) wRegDemo$AddCallback( "destroy-event", function(x,ev)cat("Closing\n")) wRegDemo$SetTitle("Regression Demo Version 3") ## Create box1 to go into the main window box1 <- gtkVBox( show =FALSE, spac=10) box1$SetBorderWidth(10) wRegDemo$Add( box1) box1$Show() ## Initial Label: label1 <- gtkLabel( "Change numerical values to move points.", show=FALSE) label1$SetJustify("left") label1$Show() box1$PackStart(label1) ##within box 1 put several items side-by-side, so create an Hbox to hold them box2 <- gtkHBox(show=FALSE,spac=10) box2$SetBorderWidth(10) ## Create initial Data Table x <- sort(rnorm(10, 100,10)) reg.frame <- data.frame(x=round(x), y = round(x + rnorm(10,0,4))) xlimits <- range(reg.frame$x) ylimits <- range(reg.frame$y) checklm <- gtkCheckButtonNewWithLabel("Show Least Squares Fit (Black)",FALSE) checklm$SetUsize(20,20) checkrlm <- gtkCheckButtonNewWithLabel("Show Resistant Fit (Red)", FALSE) checkrlm$SetUsize(20,20) checkrlm$SetActive(FALSE) checklm$SetActive(TRUE) textrlm <- gtkText(); textrlm$SetUsize(20,20) textlm <- gtkText(); textlm$SetUsize(20,20) ## Setup Plotting Area drawArea <- gtkDrawingArea() drawArea$SetUsize(300,300) asGtkDevice(drawArea) par(mar=c(4,4,2,2)+.01) loess.span <- .5 lmcoef <- lm(y~x, data = reg.frame)$coef rlmcoef <- rlm(y~x, data = reg.frame)$coef redraw <- function(...){ ## function to plot points and draw regression line plot(y ~ x, data = reg.frame, xlim=xlimits, ylim=ylimits, xlab = "x",ylab="y", pch = 16, col=4) if( checklm$GetActive() ) { lmcoef <<- lm(y~x, data = reg.frame)$coef abline(lmcoef, col=1)} if( checkrlm$GetActive() ) { rlmcoef <<- rlm(y~x, data = reg.frame)$coef abline(rlmcoef, col=2)} lines(lowess(reg.frame$x, reg.frame$y, loess.span), col=4) if( textrlm$GetLength() >0) textrlm$BackwardDelete(nchars= textrlm$GetLength() ) textrlm$Insert(char= (t1 =paste("Robust Fit: y =", round(rlmcoef[1],2), "+", round(rlmcoef[2],2),"x")), length = nchar(t1) ) if( textlm$GetLength() >0) textlm$BackwardDelete(nchars= textlm$GetLength() ) textlm$Insert(char= (t2 =paste("Least Squares: y =", round(lmcoef[1],2), "+", round(lmcoef[2],2),"x")), length = nchar(t2) ) } if(require(RGtkExtra)){ ## Use dataViewer code. O/wise create editable text windows instead sheet <- gtkSheetNew(nrow(reg.frame), 2, title = "Regression Data", show = FALSE) sheet$ColumnButtonAddLabel(0, "x") sheet$ColumnButtonAddLabel(1, "y") sheet$ShowColumnTitles() for (j in 1:2) { for (i in 1:nrow(reg.frame)) { sheet$SetCellText(i - 1, j - 1, as.character(reg.frame[i,j])) } } floor.ceiling <- function(x,floor,ceiling=NULL){ if(length(floor)==2 & is.null(ceiling)){ ceiling <- max(floor) floor <- min(floor) } if (x > ceiling) return(ceiling) return(max(c(floor,x))) } sheet$AddCallback("set-cell", function(sheet, i, j) { ## Function to replot points and redraw the regression line ## If input is off the "page", it moves points ## to the edge of the plotting region. newVal <- as.numeric(sheet$CellGetText(i, j)) if (reg.frame[i + 1, j + 1] != newVal){ if(j == 0) ## x column sheet$SetCellText(i, j, as.character(newVal <- floor.ceiling(newVal,xlimits))) else if(j == 1){ sheet$SetCellText(i, j, as.character(newVal <- floor.ceiling(newVal,ylimits))) } reg.frame[i+1,j+1] <<- newVal redraw() } }) box2$PackStart(sheet) sheet$Show() }else{ ## RGtkExtra not available. ## Does not attempt to handle off-the-page points, ## Changes the plotted region with each change in the data. ## Setup printable version of x in it's own text widget xtxt <- paste(c("x", as.character(reg.frame$x)), collapse="\n") textx <- gtkText() textx$SetEditable(TRUE) textx$SetUsize(70,50) xNchar <- nchar(xtxt) textx$Insert(chars=xtxt, length= xNchar ) box2$PackStart(textx) ## Add Callback when x is changed textx$AddCallback("insert-text", function(...) { ##need a timer here to slow input? tmp <- gtkEditableGetChars(textx,start=1, end=textx$GetLength()) xNchar <- nchar(xtxt) reg.frame$x <<- as.numeric(unlist(strsplit(tmp,"\n"))[-1]) redraw() }) ## Printable version of y in it's own text widget ytxt <- paste(c("y",as.character( reg.frame$y)), collapse="\n") texty <- gtkText() texty$SetEditable(TRUE) yNchar <- nchar(ytxt) texty$SetUsize(70,50) texty$Insert(chars=ytxt, length= yNchar ) box2$PackStart(texty) ## callback for when y is changed texty$AddCallback("insert-text", function(...) { ##need a timer here to slow input tmp <- gtkEditableGetChars(texty,start=1, end=texty$GetLength()) yNchar <- nchar(ytxt) reg.frame$y <<- as.numeric(unlist(strsplit(tmp,"\n"))[-1]) redraw() }) } ## Now draw the plot redraw() box2$PackStart(drawArea, expa=TRUE,fill= TRUE) drawArea$Show() box1$PackStart(box2, expa=TRUE,fill= TRUE) box2$Show() # Table to hold Check Buttons and loess-smoothness slider table1 <- gtkTable(3,2, homo=TRUE, show=FALSE) table1$Attach(checklm, left.attach=0, right.attach=1, top.attach=0, bottom.attach=1) table1$Attach(checkrlm, left.attach=0, right.attach=1, top.attach=1, bottom.attach=2) ## Add callbacks for the toggled buttons checklm$AddCallback("toggled", function(...) redraw(...)) checklm$Show() checkrlm$AddCallback("toggled",function(...) redraw(...)) checkrlm$Show() smoothness <- gtkAdjustment(loess.span, 0, 1.1, .05, .1, .1) hscale <- gtkHScale (smoothness) hscale$SetUsize ( 100, 20) # Create a callback for when the slider thumb is moved. # This allows the span to vary from 0 to 1 with increments of .1 smoothness$AddCallback("value-changed", function(adj) { ##need a timer here to slow input tmp <- adj$GetValue() if(tmp == 0) return() loess.span <<- tmp redraw() }) label2 <- gtkLabel( "Smoothness of the Lowess smoother goes from 0 to 1.\n Move the slider to set the smoothness", show=FALSE) table1$Attach(label2, left.attach=1, right.attach=2, top.attach=0, bottom.attach=1) label2$Show() table1$Attach(hscale, left.attach=1, right.attach=2, top.attach=1, bottom.attach=2) hscale$Show() ## Add in text boxes for output if( textrlm$GetLength() <1) textrlm$Insert(char= (t1 =paste("Robust Fit: y =", round(rlmcoef[1],2),"+", round(rlmcoef[2],2),"x")), length = nchar(t1) ) if( textlm$GetLength() <1) textlm$Insert(char= (t2 =paste("Least Squares: y =", round(lmcoef[1],2),"+", round(lmcoef[2],2),"x")), length = nchar(t2) ) table1$Attach(textlm, left.attach=0, right.attach=1, top.attach=2, bottom.attach=3) table1$Attach(textrlm, left.attach=1, right.attach=2, top.attach=2, bottom.attach=3) box1$PackStart(table1) table1$Show() wRegDemo$Show() # cat("******************************************************\n", # "The source for this demo can be found in the file:\n", # file.path(system.file(package = "RGtk"), "examples", "RegressionDemo.R"), # "\n******************************************************\n") })