RInside Version 0.2.12
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
wtdensityPlain.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8; -*-
2 //
3 // Wt usage example for RInside, inspired by the standard 'density sliders' example
4 //
5 // Copyright (C) 2011 Dirk Eddelbuettel and Romain Francois
6 //
7 // This file is licensed under GPL 2 or later, as are the rest of RInside and Rcpp
8 //
9 // Derived from hello.C in the Wt sources
10 // Copyright (C) 2008 Emweb bvba, Heverlee, Belgium.
11 
12 #include <cstdio>
13 
14 #include <Wt/WApplication>
15 #include <Wt/WBreak>
16 #include <Wt/WContainerWidget>
17 #include <Wt/WLineEdit>
18 #include <Wt/WPushButton>
19 #include <Wt/WText>
20 #include <Wt/WImage>
21 #include <Wt/WSpinBox>
22 #include <Wt/WGroupBox>
23 #include <Wt/WButtonGroup>
24 #include <Wt/WRadioButton>
25 #include <Wt/WHBoxLayout>
26 #include <Wt/WEnvironment>
27 #include <Wt/WFileResource>
28 
29 #include <RInside.h>
30 
31 using namespace Wt;
32 
33 class DensityApp : public WApplication {
34 public:
35  DensityApp(const WEnvironment& env, RInside & R);
36 
37 private:
38  WLineEdit *codeEdit_; // to edit the RNG draw expression
39  WButtonGroup *group_; // holds the radiobuttons
40  WSpinBox *spin_; // selects the density bandwidth
41  WImage *img_; // displays the image
42  WFileResource *imgfile_; // controls the file resources
43  WText *greeting_; // text label for status message
44 
45  void reportButton(); // called when new button selected
46  void reportEdit(); // called when RNG expression edited
47  void reportSpinner(); // called when bandwidth changed
48  void plot(); // to call R for new plot
49 
50  enum Kernel { Gaussian = 0, Epanechnikov = 1, Rectangular = 2,
51  Triangular = 3, Cosine = 4 };
52 
53  RInside & R_; // reference to embedded R instance
54  std::string tempfile_; // name of file used by R for plots
55  int bw_, kernel_; // parameters used to estimate the density
56  std::string cmd_; // random draw command string
57  Rcpp::NumericVector Yvec_; // the random draw
58 };
59 
60 // The env argument contains information about the new session, and the initial request.
61 // It must be passed to the WApplication // constructor so it is typically also an argument
62 // for your custom application constructor.
63 DensityApp::DensityApp(const WEnvironment& env, RInside & R) : WApplication(env), R_(R) {
64 
65  setTitle("Witty WebApp With RInside"); // application title
66 
67  std::string tfcmd = "tfile <- tempfile(pattern=\"img\", tmpdir=\"/tmp\", fileext=\".png\")";
68  tempfile_ = Rcpp::as<std::string>(R_.parseEval(tfcmd)); // assign to 'tfile' in R, and report back
69  bw_ = 100;
70  kernel_ = 0; // parameters used to estimate the density
71  cmd_ = "c(rnorm(100,0,1), rnorm(50,5,1))"; // random draw command string
72 
73  Wt::WGroupBox *wc = new Wt::WGroupBox("Density Estimation", root());
74 
75  Wt::WHBoxLayout *layout = new Wt::WHBoxLayout();
76  Wt::WContainerWidget *midbox = new Wt::WContainerWidget(root());
77  layout->addWidget(midbox);
78  Wt::WContainerWidget *container = new Wt::WContainerWidget(root());
79  layout->addWidget(container);
80 
81  wc->setLayout(layout, AlignTop | AlignJustify);
82 
83  midbox->addWidget(new WText("Density estimation scale factor (div. by 100)"));
84  midbox->addWidget(new WBreak()); // insert a line break
85  spin_ = new WSpinBox(midbox);
86  spin_->setRange(5, 200);
87  spin_->setValue(bw_);
88  spin_->valueChanged().connect(this, &DensityApp::reportSpinner);
89 
90  midbox->addWidget(new WBreak()); // insert a line break
91  midbox->addWidget(new WText("R Command for data generation")); // show some text
92  midbox->addWidget(new WBreak()); // insert a line break
93  codeEdit_ = new WLineEdit(midbox); // allow text input
94  codeEdit_->setTextSize(30);
95  codeEdit_->setText(cmd_);
96  codeEdit_->setFocus(); // give focus
97  codeEdit_->enterPressed().connect(this, &DensityApp::reportEdit);
98 
99  group_ = new Wt::WButtonGroup(container); // use button group to arrange radio buttons
100 
101  Wt::WRadioButton *button;
102  button = new Wt::WRadioButton("Gaussian", container);
103  new Wt::WBreak(container);
104  group_->addButton(button, Gaussian);
105 
106  button = new Wt::WRadioButton("Epanechnikov", container);
107  new Wt::WBreak(container);
108  group_->addButton(button, Epanechnikov);
109 
110  button = new Wt::WRadioButton("Rectangular", container);
111  new Wt::WBreak(container);
112  group_->addButton(button, Rectangular);
113 
114  button = new Wt::WRadioButton("Triangular", container);
115  new Wt::WBreak(container);
116  group_->addButton(button, Triangular);
117 
118  button = new Wt::WRadioButton("Cosine", container);
119  new Wt::WBreak(container);
120  group_->addButton(button, Cosine);
121 
122  group_->setCheckedButton(group_->button(kernel_));
123  group_->checkedChanged().connect(this, &DensityApp::reportButton);
124 
125  Wt::WGroupBox *botbox = new Wt::WGroupBox("Resulting chart", root());
126  imgfile_ = new Wt::WFileResource("image/png", tempfile_);
127  imgfile_->suggestFileName("density.png"); // name the clients sees of datafile
128  img_ = new Wt::WImage(imgfile_, "PNG version", botbox);
129 
130  Wt::WGroupBox *stbox = new Wt::WGroupBox("Status", root());
131  greeting_ = new WText(stbox); // empty text
132  greeting_->setText("Setting up...");
133 
134  reportEdit(); // create a new RNG draw in Yvec_
135  plot(); // and draw a new density plot
136 }
137 
139  kernel_ = group_->checkedId(); // get id of selected kernel
140  plot();
141 }
142 
143 void DensityApp::reportEdit() {
144  cmd_ = codeEdit_->text().toUTF8(); // get text written in box, as UTF-8, assigned to string
145  std::string rng = "y <- " + cmd_ + ";";
146  R_.parseEvalQ(rng); // evaluates expression, assigns to 'y'
147  Yvec_ = R_["y"]; // cache the y vector
148  plot();
149 }
150 
152  bw_ = spin_->value(); // get the value of the spin selector
153  plot();
154 }
155 
156 void DensityApp::plot() {
157  const char *kernelstr[] = { "gaussian", "epanechnikov", "rectangular", "triangular", "cosine" };
158  greeting_->setText("Starting R call");
159  R_["tfile"] = tempfile_;
160  R_["bw"] = bw_;
161  R_["kernel"] = kernelstr[kernel_]; // passes the string to R
162  R_["y"] = Yvec_;
163  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: ";
164  std::string cmd1 = "\"); points(y, rep(0, length(y)), pch=16, col=rgb(0,0,0,1/4)); dev.off()";
165  std::string cmd = cmd0 + kernelstr[kernel_] + cmd1; // stick the selected kernel in the middle
166  R_.parseEvalQ(cmd); // evaluate command -- generates new density plot
167  imgfile_->setChanged(); // important: tells consumer that image has changed, forces refresh
168  greeting_->setText("Finished request from " + this->environment().clientAddress() + " using " + this->environment().userAgent()) ;
169 }
170 
171 WApplication *createApplication(const WEnvironment& env) {
172  // You could read information from the environment to decide whether
173  // the user has permission to start a new application
174  //
175  // We grab an instance of the embedded R. Note we can start only one,
176  // so resource conflicts have to be managed (eg add mutexes etc)
177  //
178  return new DensityApp(env, RInside::instance());
179 }
180 
181 int main(int argc, char **argv) {
182 
183  RInside R(argc, argv); // create the one embedded R instance
184 
185  // Your main method may set up some shared resources, but should then
186  // start the server application (FastCGI or httpd) that starts listening
187  // for requests, and handles all of the application life cycles.
188  //
189  // The last argument to WRun specifies the function that will instantiate
190  // new application objects. That function is executed when a new user surfs
191  // to the Wt application, and after the library has negotiated browser
192  // support. The function should return a newly instantiated application
193  // object.
194  return WRun(argc, argv, createApplication);
195 }
DensityApp(const WEnvironment &env, RInside &R)
Definition: wtdensity.cpp:63
WImage * img_
Definition: wtdensity.cpp:41
void reportEdit()
Definition: wtdensity.cpp:156
WText * greeting_
Definition: wtdensity.cpp:43
Rcpp::NumericVector Yvec_
Definition: wtdensity.cpp:57
WApplication * createApplication(const WEnvironment &env)
RInside & R_
Definition: wtdensity.cpp:53
void parseEvalQ(const std::string &line)
Definition: RInside.cpp:366
void reportSpinner()
Definition: wtdensity.cpp:164
std::string tempfile_
Definition: wtdensity.cpp:54
int parseEval(const std::string &line, SEXP &ans)
Definition: RInside.cpp:308
WSpinBox * spin_
Definition: wtdensity.cpp:40
std::string cmd_
Definition: wtdensity.cpp:56
static RInside & instance()
Definition: RInside.cpp:398
WFileResource * imgfile_
Definition: wtdensity.cpp:42
WButtonGroup * group_
Definition: wtdensity.cpp:39
void reportButton()
Definition: wtdensity.cpp:151
void plot()
Definition: wtdensity.cpp:169
int main(int argc, char **argv)
WLineEdit * codeEdit_
Definition: wtdensity.cpp:38