RInside Version 0.2.6
inst/examples/wt/wtdensity.cpp
Go to the documentation of this file.
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4;  tab-width: 8; -*-
00002 //
00003 // Wt usage example for RInside, inspired by the standard 'density sliders' example
00004 //
00005 // Copyright (C) 2011  Dirk Eddelbuettel and Romain Francois
00006 //
00007 // This file is licensed under GPL 2 or later, as are the rest of RInside and Rcpp
00008 //
00009 // Derived from hello.C in the Wt sources
00010 // Copyright (C) 2008 Emweb bvba, Heverlee, Belgium.
00011 
00012 #include <cstdio>
00013 
00014 #include <Wt/WApplication>
00015 #include <Wt/WBreak>
00016 #include <Wt/WContainerWidget>
00017 #include <Wt/WLineEdit>
00018 #include <Wt/WPushButton>
00019 #include <Wt/WText>
00020 #include <Wt/WImage>
00021 #include <Wt/WSpinBox>
00022 #include <Wt/WGroupBox>
00023 #include <Wt/WButtonGroup>
00024 #include <Wt/WRadioButton>
00025 #include <Wt/WHBoxLayout>
00026 #include <Wt/WEnvironment>
00027 #include <Wt/WFileResource>
00028 
00029 #include <RInside.h>
00030 
00031 using namespace Wt;
00032 
00033 class DensityApp : public WApplication {
00034 public:
00035     DensityApp(const WEnvironment& env, RInside & R);
00036 
00037 private:
00038     WLineEdit *codeEdit_;       // to edit the RNG draw expression
00039     WButtonGroup *group_;       // holds the radiobuttons
00040     WSpinBox *spin_;            // selects the density bandwidth
00041     WImage *img_;               // displays the image
00042     WFileResource *imgfile_;    // controls the file resources
00043     WText *greeting_;           // text label for status message
00044 
00045     void reportButton();        // called when new button selected
00046     void reportEdit();          // called when RNG expression edited
00047     void reportSpinner();       // called when bandwidth changed
00048     void plot();                // to call R for new plot
00049     
00050     enum Kernel { Gaussian     = 0, Epanechnikov = 1, Rectangular  = 2,
00051                   Triangular   = 3, Cosine       = 4 };
00052   
00053     RInside & R_;               // reference to embedded R instance
00054     std::string tempfile_;      // name of file used by R for plots
00055     int bw_, kernel_;           // parameters used to estimate the density
00056     std::string cmd_;           // random draw command string
00057     Rcpp::NumericVector Yvec_;  // the random draw
00058 };
00059 
00060 // The env argument contains information about the new session, and the initial request. 
00061 // It must be passed to the WApplication // constructor so it is typically also an argument
00062 // for your custom application constructor.
00063 DensityApp::DensityApp(const WEnvironment& env, RInside & R) : WApplication(env), R_(R) {
00064 
00065     setTitle("Witty WebApp With RInside");                      // application title
00066 
00067     std::string tfcmd = "tfile <- tempfile(pattern=\"img\", tmpdir=\"/tmp\", fileext=\".png\")";        
00068     tempfile_ = Rcpp::as<std::string>(R_.parseEval(tfcmd));     // assign to 'tfile' in R, and report back
00069     bw_ = 100; 
00070     kernel_ = 0;                                                // parameters used to estimate the density
00071     cmd_ = "c(rnorm(100,0,1), rnorm(50,5,1))";                  // random draw command string
00072    
00073     Wt::WGroupBox *wc = new Wt::WGroupBox("Density Estimation", root());
00074 
00075     Wt::WHBoxLayout *layout = new Wt::WHBoxLayout();
00076     Wt::WContainerWidget *midbox = new Wt::WContainerWidget(root());
00077     layout->addWidget(midbox);
00078     Wt::WContainerWidget *container = new Wt::WContainerWidget(root());
00079     layout->addWidget(container);
00080 
00081     wc->setLayout(layout, AlignTop | AlignJustify);
00082 
00083     midbox->addWidget(new WText("Density estimation scale factor (div. by 100)"));
00084     midbox->addWidget(new WBreak());                            // insert a line break
00085     spin_ = new WSpinBox(midbox);
00086     spin_->setRange(5, 200);
00087     spin_->setValue(bw_);
00088     spin_->valueChanged().connect(this, &DensityApp::reportSpinner);
00089 
00090     midbox->addWidget(new WBreak());                            // insert a line break
00091     midbox->addWidget(new WText("R Command for data generation"));  // show some text
00092     midbox->addWidget(new WBreak());                            // insert a line break
00093     codeEdit_ = new WLineEdit(midbox);                          // allow text input
00094     codeEdit_->setTextSize(30);
00095     codeEdit_->setText(cmd_); 
00096     codeEdit_->setFocus();                                      // give focus
00097     codeEdit_->enterPressed().connect(this, &DensityApp::reportEdit);
00098 
00099     group_ = new Wt::WButtonGroup(container);                   // use button group to arrange radio buttons
00100 
00101     Wt::WRadioButton *button;
00102     button = new Wt::WRadioButton("Gaussian", container);
00103     new Wt::WBreak(container);
00104     group_->addButton(button, Gaussian);
00105 
00106     button = new Wt::WRadioButton("Epanechnikov", container);
00107     new Wt::WBreak(container);
00108     group_->addButton(button, Epanechnikov);
00109 
00110     button = new Wt::WRadioButton("Rectangular", container);
00111     new Wt::WBreak(container);
00112     group_->addButton(button, Rectangular);
00113 
00114     button = new Wt::WRadioButton("Triangular", container);
00115     new Wt::WBreak(container);
00116     group_->addButton(button, Triangular);
00117 
00118     button = new Wt::WRadioButton("Cosine", container);
00119     new Wt::WBreak(container);
00120     group_->addButton(button, Cosine);
00121 
00122     group_->setCheckedButton(group_->button(kernel_));
00123     group_->checkedChanged().connect(this, &DensityApp::reportButton);
00124 
00125     Wt::WGroupBox *botbox = new Wt::WGroupBox("Resulting chart", root());
00126     imgfile_ = new Wt::WFileResource("image/png", tempfile_);
00127     imgfile_->suggestFileName("density.png");  // name the clients sees of datafile
00128     img_ = new Wt::WImage(imgfile_, "PNG version", botbox);
00129 
00130     Wt::WGroupBox *stbox = new Wt::WGroupBox("Status", root());
00131     greeting_ = new WText(stbox);                               // empty text
00132     greeting_->setText("Setting up...");
00133   
00134     reportEdit();                                               // create a new RNG draw in Yvec_
00135     plot();                                                     // and draw a new density plot
00136 }
00137 
00138 void DensityApp::reportButton() {
00139     kernel_ = group_->checkedId();                              // get id of selected kernel 
00140     plot();
00141 }
00142 
00143 void DensityApp::reportEdit() {
00144     cmd_ = codeEdit_->text().toUTF8();  // get text written in box, as UTF-8, assigned to string
00145     std::string rng = "y <- " + cmd_ + ";";
00146     R_.parseEvalQ(rng);                 // evaluates expression, assigns to 'y'
00147     Yvec_ = R_["y"];                    // cache the y vector
00148     plot();
00149 }
00150 
00151 void DensityApp::reportSpinner() {
00152     bw_ = spin_->value();               // get the value of the spin selector
00153     plot();
00154 }
00155 
00156 void DensityApp::plot() {
00157     const char *kernelstr[] = { "gaussian", "epanechnikov", "rectangular", "triangular", "cosine" };
00158     greeting_->setText("Starting R call");
00159     R_["tfile"]  = tempfile_;
00160     R_["bw"]     = bw_;
00161     R_["kernel"] = kernelstr[kernel_];                  // passes the string to R
00162     R_["y"]      = Yvec_;
00163     std::string cmd0 = "png(filename=tfile,width=600,height=400); plot(density(y, bw=bw/100, kernel=kernel), xlim=range(y)+c(-2,2), main=\"Kernel: ";
00164     std::string cmd1 = "\"); points(y, rep(0, length(y)), pch=16, col=rgb(0,0,0,1/4));  dev.off()";
00165     std::string cmd = cmd0 + kernelstr[kernel_] + cmd1; // stick the selected kernel in the middle
00166     R_.parseEvalQ(cmd);                                 // evaluate command -- generates new density plot
00167     imgfile_->setChanged();                             // important: tells consumer that image has changed, forces refresh
00168     greeting_->setText("Finished request from " + this->environment().clientAddress() + " using " + this->environment().userAgent()) ;
00169 }
00170 
00171 WApplication *createApplication(const WEnvironment& env) {
00172     // You could read information from the environment to decide whether
00173     // the user has permission to start a new application
00174     //
00175     // We grab an instance of the embedded R. Note we can start only one,
00176     // so resource conflicts have to be managed (eg add mutexes etc)
00177     //
00178     return new DensityApp(env, RInside::instance());
00179 }
00180 
00181 int main(int argc, char **argv) {
00182 
00183     RInside R(argc, argv);              // create the one embedded R instance 
00184 
00185     // Your main method may set up some shared resources, but should then
00186     // start the server application (FastCGI or httpd) that starts listening
00187     // for requests, and handles all of the application life cycles.
00188     //
00189     // The last argument to WRun specifies the function that will instantiate
00190     // new application objects. That function is executed when a new user surfs
00191     // to the Wt application, and after the library has negotiated browser
00192     // support. The function should return a newly instantiated application
00193     // object.
00194     return WRun(argc, argv, createApplication);
00195 }
 All Classes Files Functions Variables Enumerations Enumerator Defines