Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gsDesign interface attempt #1 #15

Closed
keaven opened this issue Aug 19, 2012 · 4 comments
Closed

gsDesign interface attempt #1 #15

keaven opened this issue Aug 19, 2012 · 4 comments

Comments

@keaven
Copy link

keaven commented Aug 19, 2012

Following is a simple, limited interface to the gsDesign R package (ui and server code below).
This requires the gsDesign package available at CRAN.
This project has been open source since its inception in 2006 and is NOT for profit.
I am trying to replace an interface developed in Qt so that it can be maintained and extended by an R programmer.
See http://biopharmnet.com/wiki/GsDesign_Package if you want to see the Qt interface.
Any comments on this are welcome!

Comments:

  1. shiny is VERY accessible for an R programmer who is a statistician (read: NOT a professional programmer!).
    ~8 hours to learn shiny and do the interface so far is not bad!
    This could make somewhat complex packages such as gsDesign easily accessible!
  2. I am running this using Chrome 21.0.1180.79 m, R 2.15.0 and a version of shiny downloaded on August 18, 2012.

Initial issues with the current interface:

  1. I don't understand why the plot subtab under the "Group Sequential Design" tab is not functioning.
    Also, if I want to use ggplot2, how do I get a plot to output (I pretty recent release of ggplot2)?
  2. Look at the sample size tab in the UI. It would be ideal if I could use radio buttons or tabs
    (instead of both) to get the functionality implemented here (I would prefer just tabs, but on the server side,
    I don't have access to which tab is selected, so I had to use a radio buttons; radio buttons, on the other hand,
    do not allow the dynamic ui side that tabs do).
  3. Supporting variable length vector input (issue Input variable length vector #14) is needed for this application. In the timing tab,
    I need to have a vector of the length specified there...and will want increasing numbers in
    that vector between 0 and 1.
    This functionality will be used in two other instances in a more complete interface.
  4. One of the nice things about the current Qt interface is that I can compare multiple designs.
    This would require storing all of the parameters for each design, as well as some way to
    navigate between them.
  5. See the "Timing" input on the spending function tab. It would be nice to have control over
    input increments in numericInput.

ui.r

library(shiny)
library(gsDesign)
shinyUI(pageWithSidebar(

  # Application title
  headerPanel("gsDesign Explorer"),

  # Sidebar with a slider input for spending fn parameter and
  # time to evaluate spending function
  sidebarPanel(
    tabsetPanel(
      tabPanel("Sample Size",
               numericInput("alpha",label="alpha (1-sided):",value=.025,min=.00001,max=.39999),
               numericInput("Power",label="Power:",value=.9,min=.4,max=.999),
               radioButtons("dist",  "Endpoint type", list("User defined" = "User", "Binomial" = "Binomial")),
               tabsetPanel(
                 tabPanel("User input", 
                          numericInput(inputId="nfix",label="N for Fixed Design", value=1, min=1)),
                 tabPanel("Binomial", 
                          numericInput(inputId="p1",label="Control event rate", value=.15, min=.005,max=.995),
                          numericInput(inputId="p2",label="Experimental event rate", value=.1, min=.005,max=.995),
                          numericInput(inputId="delta0",label="H0 difference",value=0)))),                  
      tabPanel("Timing",
        numericInput(inputId="km1", label="Number of interim analyses", value=2, min=1)),
      tabPanel("Spending Functions",
        tabsetPanel(
          tabPanel("Upper spending",
            sliderInput(inputId="rho", label="Rho:", min = 0.1, max = 15.0, value = 4.0, step=.05),
            numericInput(inputId="t", label="Timing:", value=.5, min=0, max=1)),
          tabPanel("Lower spending",
            sliderInput(inputId="lrho", label="Rho:", min = 0.1, max = 15.0, value = 2.0, step=.05),
            numericInput(inputId="lt", label="Timing:", value=.5, min=0, max=1)))))
  ),
  # Show a plot of the generated distribution
  mainPanel(
    tabsetPanel(
      tabPanel("Upper spending",plotOutput("sfPlot")),
      tabPanel("Fixed design sample size",verbatimTextOutput("dist")),
      tabPanel("Group sequential design",
        tabsetPanel(
          tabPanel("Text",verbatimTextOutput("design")),
          tabPanel("Plot",plotOutput("plot"))
))))))

server.r

library(shiny)
library(ggplot2)
shinyServer(function(input, output){

  # Function that generates a plot of a spending function. The function
  # is wrapped in a call to reactivePlot to indicate that:
  #
  #  1) It is "reactive" and therefore should be automatically 
  #     re-executed when inputs change
  #  2) Its output type is a plot 
  #
  output$sfPlot <- reactivePlot(function(){
    # generate a power spending function
    tt <- (0:100)/100
    alpha <- input$alpha
    spend <- sfPower(alpha,input$t,input$rho)$spend
    plot(tt, sfPower(alpha,tt,input$rho)$spend,
         xlab="Timing", ylab="Spend", main="Power Spending Function", type="l")
    points(input$t,spend,cex=2)
    if (spend > alpha/2) delt <- -alpha/20
    else delt <- alpha/20
    text(input$t,spend+delt,as.character(round(spend,4)))
  })
  N <- reactive(function(){
                   switch(input$dist, 
                      "User" = input$nfix,
                      "Binomial" = nBinomial(p1=input$p1,p2=input$p2,delta0=input$delta0,alpha=input$alpha,beta=1-input$Power)
                   )})
  output$dist <- reactivePrint(function(){N()})
  output$design <- reactivePrint(function(){
    gsDesign(k=input$km1+1,n.fix=N(),sfu=sfPower,sfl=sfPower,sfupar=input$rho,sflpar=input$lrho,alpha=input$alpha,
             beta=1-input$Power)})
  output$plot <- reactivePlot(function(){
    plot(gsDesign(k=input$km1+1,n.fix=N(),sfu=sfPower,sfl=sfPower,sfupar=input$rho,sflpar=input$lrho,alpha=input$alpha,
                  beta=1-input$Power),base=TRUE)
  })
})
@jcheng5
Copy link
Member

jcheng5 commented Aug 20, 2012

Thanks for all of this amazing feedback!

1) I don't understand why the plot subtab under the "Group Sequential Design" tab is not functioning.
Also, if I want to use ggplot2, how do I get a plot to output (I pretty recent release of ggplot2)?

This is a bug, fixed in Shiny 0.1.3 which will be released imminently.

2) Look at the sample size tab in the UI. It would be ideal if I could use radio buttons or tabs
(instead of both) to get the functionality implemented here (I would prefer just tabs, but on the server side,
I don't have access to which tab is selected, so I had to use a radio buttons; radio buttons, on the other hand,
do not allow the dynamic ui side that tabs do).

This is coming soon, hopefully this week or next. This has probably been our most common feature request.

3) Supporting variable length vector input (issue #14) is needed for this application. In the timing tab,
I need to have a vector of the length specified there...and will want increasing numbers in
that vector between 0 and 1. This functionality will be used in two other instances in a more complete interface.

This might be implementable as a custom control (i.e. will need JavaScript). It isn't quite possible to do this nicely right now but support is coming soon.

4) One of the nice things about the current Qt interface is that I can compare multiple designs.
This would require storing all of the parameters for each design, as well as some way to
navigate between them.

Interesting, we don't have anything for this at the moment. I'll think about it.

5) See the "Timing" input on the spending function tab. It would be nice to have control over
input increments in numericInput.

I've added a "step" attribute to numericInput, but it just missed the boat for Shiny 0.1.3--it will be in 0.1.4.

@jcheng5
Copy link
Member

jcheng5 commented Aug 20, 2012

Just deployed Shiny 0.1.3, and the change to numericInput made it after all. You can re-run these commands to update Shiny:

options(repos=c(RStudio="http://rstudio.org/_packages", getOption("repos")))
install.packages("shiny")

@jcheng5 jcheng5 closed this as completed Aug 20, 2012
@jcheng5
Copy link
Member

jcheng5 commented Aug 21, 2012

For #2 (the server side knowing what tab is selected), I've just committed a change that will allow you to add an id param to any call to tabsetPanel, which will cause the tabset to send its selected tab as input$id. If you don't do anything else, the value of that input will be the title of the active tab; you can add a value parameter to a tabPanel to override this with your own value.

@keaven
Copy link
Author

keaven commented Aug 21, 2012

Thanks for your response. I will probably continue to play with this over weekends and will keep you posted on my progress or post issues as they arise. The upated tab feature will take me a long ways...but eventually having the variable length vector (or matrix!) input would be essential to replace the current interface...
I will try to think of other ways to save multiple designs and possibly rotate between them...
Honestly, to get so much done with so little code and time and to have a pretty respectable looking application was amazing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants