|
RInside Version 0.2.10
|
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 setCssTheme("polished"); 00068 messageResourceBundle().use(appRoot() + "wtdensity"); 00069 00070 new WText(WString::tr("overview"), root()); 00071 00072 std::string tfcmd = "tfile <- tempfile(pattern=\"img\", tmpdir=\"/tmp\", fileext=\".png\")"; 00073 tempfile_ = Rcpp::as<std::string>(R_.parseEval(tfcmd)); // assign to 'tfile' in R, and report back 00074 bw_ = 100; 00075 kernel_ = 0; // parameters used to estimate the density 00076 cmd_ = "c(rnorm(100,0,1), rnorm(50,5,1))"; // random draw command string 00077 00078 new WText(WString::tr("user input"), root()); 00079 Wt::WContainerWidget *wc = new Wt::WContainerWidget(root()); 00080 wc->setStyleClass("box"); 00081 00082 Wt::WHBoxLayout *layout = new Wt::WHBoxLayout(); 00083 Wt::WContainerWidget *midbox = new Wt::WContainerWidget(root()); 00084 layout->addWidget(midbox); 00085 Wt::WContainerWidget *container = new Wt::WContainerWidget(root()); 00086 layout->addWidget(container); 00087 00088 wc->setLayout(layout, AlignTop | AlignJustify); 00089 00090 midbox->addWidget(new WText("Density estimation scale factor (div. by 100)")); 00091 midbox->addWidget(new WBreak()); // insert a line break 00092 spin_ = new WSpinBox(midbox); 00093 spin_->setRange(5, 200); 00094 spin_->setValue(bw_); 00095 spin_->valueChanged().connect(this, &DensityApp::reportSpinner); 00096 00097 midbox->addWidget(new WBreak()); // insert a line break 00098 midbox->addWidget(new WText("R Command for data generation")); // show some text 00099 midbox->addWidget(new WBreak()); // insert a line break 00100 codeEdit_ = new WLineEdit(midbox); // allow text input 00101 codeEdit_->setTextSize(30); 00102 codeEdit_->setText(cmd_); 00103 codeEdit_->setFocus(); // give focus 00104 codeEdit_->enterPressed().connect(this, &DensityApp::reportEdit); 00105 00106 group_ = new Wt::WButtonGroup(container); // use button group to arrange radio buttons 00107 00108 Wt::WRadioButton *button; 00109 button = new Wt::WRadioButton("Gaussian", container); 00110 new Wt::WBreak(container); 00111 group_->addButton(button, Gaussian); 00112 00113 button = new Wt::WRadioButton("Epanechnikov", container); 00114 new Wt::WBreak(container); 00115 group_->addButton(button, Epanechnikov); 00116 00117 button = new Wt::WRadioButton("Rectangular", container); 00118 new Wt::WBreak(container); 00119 group_->addButton(button, Rectangular); 00120 00121 button = new Wt::WRadioButton("Triangular", container); 00122 new Wt::WBreak(container); 00123 group_->addButton(button, Triangular); 00124 00125 button = new Wt::WRadioButton("Cosine", container); 00126 new Wt::WBreak(container); 00127 group_->addButton(button, Cosine); 00128 00129 group_->setCheckedButton(group_->button(kernel_)); 00130 group_->checkedChanged().connect(this, &DensityApp::reportButton); 00131 00132 new WText(WString::tr("r result"), root()); 00133 Wt::WContainerWidget *botbox = new Wt::WContainerWidget(root()); 00134 botbox->setStyleClass("box"); 00135 imgfile_ = new Wt::WFileResource("image/png", tempfile_); 00136 imgfile_->suggestFileName("density.png"); // name the clients sees of datafile 00137 img_ = new Wt::WImage(imgfile_, "PNG version", botbox); 00138 00139 new WText(WString::tr("browser info"), root()); 00140 Wt::WContainerWidget *stbox = new Wt::WContainerWidget(root()); 00141 stbox->setStyleClass("box"); 00142 greeting_ = new WText(stbox); // empty text 00143 greeting_->setText("Setting up..."); 00144 00145 useStyleSheet("wtdensity.css"); // set our style sheet last 00146 00147 reportEdit(); // create a new RNG draw in Yvec_ 00148 plot(); // and draw a new density plot 00149 } 00150 00151 void DensityApp::reportButton() { 00152 kernel_ = group_->checkedId(); // get id of selected kernel 00153 plot(); 00154 } 00155 00156 void DensityApp::reportEdit() { 00157 cmd_ = codeEdit_->text().toUTF8(); // get text written in box, as UTF-8, assigned to string 00158 std::string rng = "y2 <- " + cmd_ + "; y <- y2"; 00159 R_.parseEvalQNT(rng); // evaluates expression, assigns to 'y' 00160 Yvec_ = R_["y"]; // cache the y vector 00161 plot(); 00162 } 00163 00164 void DensityApp::reportSpinner() { 00165 bw_ = spin_->value(); // get the value of the spin selector 00166 plot(); 00167 } 00168 00169 void DensityApp::plot() { 00170 const char *kernelstr[] = { "gaussian", "epanechnikov", "rectangular", "triangular", "cosine" }; 00171 greeting_->setText("Starting R call"); 00172 R_["tfile"] = tempfile_; 00173 R_["bw"] = bw_; 00174 R_["kernel"] = kernelstr[kernel_]; // passes the string to R 00175 R_["y"] = Yvec_; 00176 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: "; 00177 std::string cmd1 = "\"); points(y, rep(0, length(y)), pch=16, col=rgb(0,0,0,1/4)); dev.off()"; 00178 std::string cmd = cmd0 + kernelstr[kernel_] + cmd1; // stick the selected kernel in the middle 00179 R_.parseEvalQ(cmd); // evaluate command -- generates new density plot 00180 imgfile_->setChanged(); // important: tells consumer that image has changed, forces refresh 00181 greeting_->setText("Finished request from " + this->environment().clientAddress() + " using " + this->environment().userAgent()) ; 00182 } 00183 00184 WApplication *createApplication(const WEnvironment& env) { 00185 // You could read information from the environment to decide whether 00186 // the user has permission to start a new application 00187 // 00188 // We grab an instance of the embedded R. Note we can start only one, 00189 // so resource conflicts have to be managed (eg add mutexes etc) 00190 // 00191 return new DensityApp(env, RInside::instance()); 00192 } 00193 00194 int main(int argc, char **argv) { 00195 00196 RInside R(argc, argv); // create the one embedded R instance 00197 00198 // Your main method may set up some shared resources, but should then 00199 // start the server application (FastCGI or httpd) that starts listening 00200 // for requests, and handles all of the application life cycles. 00201 // 00202 // The last argument to WRun specifies the function that will instantiate 00203 // new application objects. That function is executed when a new user surfs 00204 // to the Wt application, and after the library has negotiated browser 00205 // support. The function should return a newly instantiated application 00206 // object. 00207 return WRun(argc, argv, createApplication); 00208 }