[Rinside-commits] r215 - in pkg: . inst inst/examples inst/examples/qt inst/examples/wt
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Thu Nov 24 18:18:27 CET 2011
Author: edd
Date: 2011-11-24 18:18:27 +0100 (Thu, 24 Nov 2011)
New Revision: 215
Added:
pkg/inst/examples/wt/
pkg/inst/examples/wt/Makefile
pkg/inst/examples/wt/wtdensity.cpp
Modified:
pkg/ChangeLog
pkg/inst/NEWS
pkg/inst/examples/qt/qtdensity.cpp
pkg/inst/examples/qt/qtdensity.h
Log:
adds new example based on 'Wt' (Webtoolkit, aka 'witty')
minor white-space / indentation cleanup in Qt code
Modified: pkg/ChangeLog
===================================================================
--- pkg/ChangeLog 2011-11-20 21:37:16 UTC (rev 214)
+++ pkg/ChangeLog 2011-11-24 17:18:27 UTC (rev 215)
@@ -1,3 +1,10 @@
+2011-11-24 Dirk Eddelbuettel <edd at debian.org>
+
+ * inst/examples/wt: New example directory 'wt' providing a Webtoolkit
+ (aka 'witty') based density slider application
+ * inst/examples/wt/wtdensity.cpp: Application in less than 200 lines
+ * inst/examples/wt/Makefile: Makefile to build and launch (on Ubuntu)
+
2011-11-20 Dirk Eddelbuettel <edd at debian.org>
* inst/examples/qt/qtdensity.pro: Use QMAKE_LIBS, not QMAKE_LFLAGS
Modified: pkg/inst/NEWS
===================================================================
--- pkg/inst/NEWS 2011-11-20 21:37:16 UTC (rev 214)
+++ pkg/inst/NEWS 2011-11-24 17:18:27 UTC (rev 215)
@@ -1,3 +1,10 @@
+0.2.5 20xx-yy-zz
+
+ o New example embedding R inside a Wt (aka Webtoolkit, pronounced
+ 'witty') application, mirroring the previous Qt application
+
+ o Very minor fix to qmake.pro file for Qt app correcting link order
+
0.2.4 2011-04-24
o Minor code cleanups in initialization code
Modified: pkg/inst/examples/qt/qtdensity.cpp
===================================================================
--- pkg/inst/examples/qt/qtdensity.cpp 2011-11-20 21:37:16 UTC (rev 214)
+++ pkg/inst/examples/qt/qtdensity.cpp 2011-11-24 17:18:27 UTC (rev 215)
@@ -1,4 +1,4 @@
-// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8; -*-
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
//
// Qt usage example for RInside, inspired by the standard 'density
// sliders' example for other GUI toolkits -- this time with SVG
@@ -11,15 +11,15 @@
QtDensity::QtDensity(RInside & R) : m_R(R)
{
- m_bw = 100; // initial bandwidth, will be scaled by 100 so 1.0
- m_kernel = 0; // initial kernel: gaussian
+ m_bw = 100; // initial bandwidth, will be scaled by 100 so 1.0
+ m_kernel = 0; // initial kernel: gaussian
m_cmd = "c(rnorm(100,0,1), rnorm(50,5,1))"; // simple mixture
- m_R["bw"] = m_bw; // pass bandwidth to R, and have R compute a temp.file name
+ m_R["bw"] = m_bw; // pass bandwidth to R, and have R compute a temp.file name
m_tempfile = QString::fromStdString(Rcpp::as<std::string>(m_R.parseEval("tfile <- tempfile()")));
m_svgfile = QString::fromStdString(Rcpp::as<std::string>(m_R.parseEval("sfile <- tempfile()")));
m_use_svg = m_R.parseEval("require(cairoDevice)");
if (!m_use_svg) {
- std::cerr << "Consider installing the 'cairoDevice' package from CRAN to create SVG graphics." << std::endl;
+ std::cerr << "Consider installing the 'cairoDevice' package from CRAN to create SVG graphics." << std::endl;
}
setupDisplay();
}
@@ -68,16 +68,16 @@
kernelGroup->addButton(radio5, 4);
QObject::connect(kernelGroup, SIGNAL(buttonClicked(int)), this, SLOT(getKernel(int)));
- if (m_use_svg) { // svg case
- m_svg = new QSvgWidget();
- } else { // png default
- m_imageLabel = new QLabel;
- m_imageLabel->setBackgroundRole(QPalette::Base);
- m_imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
- m_imageLabel->setScaledContents(true);
- m_image = new QImage(m_tempfile);
+ if (m_use_svg) { // svg case
+ m_svg = new QSvgWidget();
+ } else { // png default
+ m_imageLabel = new QLabel;
+ m_imageLabel->setBackgroundRole(QPalette::Base);
+ m_imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+ m_imageLabel->setScaledContents(true);
+ m_image = new QImage(m_tempfile);
}
- runRandomDataCmd(); // also calls plot()
+ runRandomDataCmd(); // also calls plot()
QGroupBox *estimationBox = new QGroupBox("Density estimation bandwidth (scaled by 100)");
QHBoxLayout *spinners = new QHBoxLayout;
@@ -97,9 +97,9 @@
QHBoxLayout *lowerlayout = new QHBoxLayout;
if (m_use_svg) {
- lowerlayout->addWidget(m_svg);
+ lowerlayout->addWidget(m_svg);
} else {
- lowerlayout->addWidget(m_imageLabel);
+ lowerlayout->addWidget(m_imageLabel);
}
QVBoxLayout *outer = new QVBoxLayout;
@@ -108,7 +108,7 @@
window->setLayout(outer);
window->show();
if (!m_use_svg) {
- window->resize(650, 750);
+ window->resize(650, 750);
}
}
@@ -117,35 +117,35 @@
m_R["bw"] = m_bw;
m_R["kernel"] = kernelstrings[m_kernel]; // that passes the string to R
std::string cmd0;
- if (m_use_svg) { // select device based on whether cairoDevice is available or not
- cmd0 = "Cairo(width=6,height=6,pointsize=10,surface='svg',filename=tfile); ";
+ if (m_use_svg) { // select device based on whether cairoDevice is available or not
+ cmd0 = "Cairo(width=6,height=6,pointsize=10,surface='svg',filename=tfile); ";
} else {
- cmd0 = "png(filename=tfile,width=600,height=600);";
+ cmd0 = "png(filename=tfile,width=600,height=600);";
}
std::string cmd1 = "plot(density(y, bw=bw/100, kernel=kernel), xlim=range(y)+c(-2,2), main=\"Kernel: ";
std::string cmd2 = "\"); points(y, rep(0, length(y)), pch=16, col=rgb(0,0,0,1/4)); dev.off()";
std::string cmd = cmd0 + cmd1 + kernelstrings[m_kernel] + cmd2; // stick the selected kernel in the middle
m_R.parseEvalQ(cmd);
if (m_use_svg) {
- filterFile(); // we need to simplify the svg file for display by Qt
- m_svg->load(m_svgfile);
+ filterFile(); // we need to simplify the svg file for display by Qt
+ m_svg->load(m_svgfile);
} else {
- m_image->load(m_tempfile);
- m_imageLabel->setPixmap(QPixmap::fromImage(*m_image));
+ m_image->load(m_tempfile);
+ m_imageLabel->setPixmap(QPixmap::fromImage(*m_image));
}
}
void QtDensity::getBandwidth(int bw) {
if (bw != m_bw) {
- m_bw = bw;
- plot();
+ m_bw = bw;
+ plot();
}
}
void QtDensity::getKernel(int kernel) {
if (kernel != m_kernel) {
- m_kernel = kernel;
- plot();
+ m_kernel = kernel;
+ plot();
}
}
@@ -156,7 +156,7 @@
void QtDensity::runRandomDataCmd(void) {
std::string cmd = "y <- " + m_cmd.toStdString();
m_R.parseEvalQ(cmd);
- plot(); // after each random draw, update plot with estimate
+ plot(); // after each random draw, update plot with estimate
}
void QtDensity::filterFile() {
@@ -171,12 +171,12 @@
QTextStream in(&infile);
QTextStream out(&outfile);
QRegExp rx1("<symbol");
- QRegExp rx2("</symbol");
+ QRegExp rx2("</symbol");
while (!in.atEnd()) {
- QString line = in.readLine();
- line.replace(rx1, "<g"); // so '<symbol' becomes '<g ...'
- line.replace(rx2, "</g");// and '</symbol becomes '</g'
- out << line << "\n";
+ QString line = in.readLine();
+ line.replace(rx1, "<g"); // so '<symbol' becomes '<g ...'
+ line.replace(rx2, "</g");// and '</symbol becomes '</g'
+ out << line << "\n";
}
infile.close();
outfile.close();
Modified: pkg/inst/examples/qt/qtdensity.h
===================================================================
--- pkg/inst/examples/qt/qtdensity.h 2011-11-20 21:37:16 UTC (rev 214)
+++ pkg/inst/examples/qt/qtdensity.h 2011-11-24 17:18:27 UTC (rev 215)
@@ -1,4 +1,4 @@
-// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8; -*-
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
//
// Qt usage example for RInside, inspired by the standard 'density
// sliders' example for other GUI toolkits
@@ -22,7 +22,7 @@
{
Q_OBJECT
-public:
+ public:
QtDensity(RInside & R);
private slots:
@@ -32,21 +32,21 @@
void runRandomDataCmd(void);
private:
- void setupDisplay(void); // standard GUI boilderplate of arranging things
- void plot(void); // run a density plot in R and update the
- void filterFile(void); // modify the richer SVG produced by R
+ void setupDisplay(void); // standard GUI boilderplate of arranging things
+ void plot(void); // run a density plot in R and update the
+ void filterFile(void); // modify the richer SVG produced by R
- QSvgWidget *m_svg; // the SVG device
+ QSvgWidget *m_svg; // the SVG device
- QLabel *m_imageLabel; // image display in non-SVG case
+ QLabel *m_imageLabel; // image display in non-SVG case
QImage *m_image;
- RInside & m_R; // reference to the R instance passed to constructor
- QString m_tempfile; // name of file used by R for plots
- QString m_svgfile; // another temp file, this time from Qt
- int m_bw, m_kernel; // parameters used to estimate the density
- QString m_cmd; // random draw command string
- bool m_use_svg; // create SVG if cairoDevice can be loaded
+ RInside & m_R; // reference to the R instance passed to constructor
+ QString m_tempfile; // name of file used by R for plots
+ QString m_svgfile; // another temp file, this time from Qt
+ int m_bw, m_kernel; // parameters used to estimate the density
+ QString m_cmd; // random draw command string
+ bool m_use_svg; // create SVG if cairoDevice can be loaded
};
#endif
Added: pkg/inst/examples/wt/Makefile
===================================================================
--- pkg/inst/examples/wt/Makefile (rev 0)
+++ pkg/inst/examples/wt/Makefile 2011-11-24 17:18:27 UTC (rev 215)
@@ -0,0 +1,50 @@
+
+## comment this out if you need a different version of R,
+## and set set R_HOME accordingly as an environment variable
+R_HOME := $(shell R RHOME)
+
+## include headers and libraries for R
+RCPPFLAGS := $(shell $(R_HOME)/bin/R CMD config --cppflags)
+RLDFLAGS := $(shell $(R_HOME)/bin/R CMD config --ldflags)
+RBLAS := $(shell $(R_HOME)/bin/R CMD config BLAS_LIBS)
+RLAPACK := $(shell $(R_HOME)/bin/R CMD config LAPACK_LIBS)
+
+## if you need to set an rpath to R itself, also uncomment
+#RRPATH := -Wl,-rpath,$(R_HOME)/lib
+
+## include headers and libraries for Rcpp interface classes
+RCPPINCL := $(shell echo 'Rcpp:::CxxFlags()' | $(R_HOME)/bin/R --vanilla --slave)
+RCPPLIBS := $(shell echo 'Rcpp:::LdFlags()' | $(R_HOME)/bin/R --vanilla --slave)
+
+## include headers and libraries for RInside embedding classes
+RINSIDEINCL := $(shell echo 'RInside:::CxxFlags()' | $(R_HOME)/bin/R --vanilla --slave)
+RINSIDELIBS := $(shell echo 'RInside:::LdFlags()' | $(R_HOME)/bin/R --vanilla --slave)
+
+
+## minimal Wt libs -- works for me on Ubuntu, may need -L switches elsewhere...
+WITTYLIBS := -lwt -lwthttp -lboost_signals
+
+
+## compiler etc settings used in default make rules
+CXX := $(shell $(R_HOME)/bin/R CMD config CXX)
+CPPFLAGS := -Wall $(shell $(R_HOME)/bin/R CMD config CPPFLAGS)
+CXXFLAGS := $(RCPPFLAGS) $(RCPPINCL) $(RINSIDEINCL) $(shell $(R_HOME)/bin/R CMD config CXXFLAGS)
+LDLIBS := $(RLDFLAGS) $(RRPATH) $(RBLAS) $(RLAPACK) $(RCPPLIBS) $(RINSIDELIBS) $(WITTYLIBS)
+
+
+
+all: wtdensity
+
+wtdensity: wtdensity.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o wtdensity wtdensity.cpp $(LDLIBS)
+ ## optionally strip the binary
+ strip wtdensity
+
+run:
+ ## Wt resources location on Debian/Ubuntu; adjust as needed
+ test -L resources || ln -s /usr/lib/Wt/resources .
+ ## launch, pointing to resources linked and /tmp dir
+ ./wtdensity --docroot ".;/resources,/tmp" --http-addr 127.0.0.1 --http-port 8080
+
+clean:
+ rm wtdensity
\ No newline at end of file
Added: pkg/inst/examples/wt/wtdensity.cpp
===================================================================
--- pkg/inst/examples/wt/wtdensity.cpp (rev 0)
+++ pkg/inst/examples/wt/wtdensity.cpp 2011-11-24 17:18:27 UTC (rev 215)
@@ -0,0 +1,192 @@
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8; -*-
+//
+// Wt usage example for RInside, inspired by the standard 'density sliders' example
+//
+// Copyright (C) 2011 Dirk Eddelbuettel and Romain Francois
+//
+// This file is licensed under GPL 2 or later, as are the rest of RInside and Rcpp
+//
+// Derived from hello.C in the Wt sources
+// Copyright (C) 2008 Emweb bvba, Heverlee, Belgium.
+
+#include <cstdio>
+
+#include <Wt/WApplication>
+#include <Wt/WBreak>
+#include <Wt/WContainerWidget>
+#include <Wt/WLineEdit>
+#include <Wt/WPushButton>
+#include <Wt/WText>
+#include <Wt/WImage>
+#include <Wt/WSpinBox>
+#include <Wt/WGroupBox>
+#include <Wt/WButtonGroup>
+#include <Wt/WRadioButton>
+#include <Wt/WHBoxLayout>
+#include <Wt/WEnvironment>
+#include <Wt/WFileResource>
+
+#include <RInside.h>
+
+using namespace Wt;
+
+class DensityApp : public WApplication {
+public:
+ DensityApp(const WEnvironment& env, RInside & R);
+
+private:
+ WLineEdit *codeEdit_; // to edit the RNG draw expression
+ WButtonGroup *group_; // holds the radiobuttons
+ WSpinBox *spin_; // selects the density bandwidth
+ WImage *img_; // displays the image
+ WFileResource *imgfile_; // controls the file resources
+ WText *greeting_; // text label for status message
+
+ void reportButton(); // called when new button selected
+ void reportEdit(); // called when RNG expression edited
+ void reportSpinner(); // called when bandwidth changed
+ void plot(); // to call R for new plot
+
+ enum Kernel { Gaussian = 0, Epanechnikov = 1, Rectangular = 2,
+ Triangular = 3, Cosine = 4 };
+
+ RInside & R_; // reference to embedded R instance
+ std::string tempfile_; // name of file used by R for plots
+ int bw_, kernel_; // parameters used to estimate the density
+ std::string cmd_; // random draw command string
+ Rcpp::NumericVector Yvec_; // the random draw
+};
+
+// The env argument contains information about the new session, and the initial request.
+// It must be passed to the WApplication // constructor so it is typically also an argument
+// for your custom application constructor.
+DensityApp::DensityApp(const WEnvironment& env, RInside & R) : WApplication(env), R_(R) {
+//DensityApp::DensityApp(const WEnvironment& env) : WApplication(env) {
+
+ setTitle("Witty WebApp With RInside"); // application title
+ std::string tfcmd = "tfile <- tempfile(pattern=\"img\", tmpdir=\"/tmp\", fileext=\".png\")";
+ tempfile_ = Rcpp::as<std::string>(R_.parseEval(tfcmd)); // assign to 'tfile' in R, and report back
+ bw_ = 100;
+ kernel_ = 0; // parameters used to estimate the density
+ cmd_ = "c(rnorm(100,0,1), rnorm(50,5,1))"; // random draw command string
+
+ Wt::WGroupBox *wc = new Wt::WGroupBox("Density Estimation", root());
+
+ Wt::WHBoxLayout *layout = new Wt::WHBoxLayout();
+ Wt::WContainerWidget *midbox = new Wt::WContainerWidget(root());
+ layout->addWidget(midbox);
+ Wt::WContainerWidget *container = new Wt::WContainerWidget(root());
+ layout->addWidget(container);
+
+ wc->setLayout(layout, AlignTop | AlignJustify);
+
+ midbox->addWidget(new WText("Density estimation scale factor (div. by 100)"));
+ midbox->addWidget(new WBreak()); // insert a line break
+ spin_ = new WSpinBox(midbox);
+ spin_->setRange(1, 150);
+ spin_->setValue(bw_);
+ spin_->valueChanged().connect(this, &DensityApp::reportSpinner);
+
+ midbox->addWidget(new WBreak()); // insert a line break
+ midbox->addWidget(new WText("R Command for data generation")); // show some text
+ midbox->addWidget(new WBreak()); // insert a line break
+ codeEdit_ = new WLineEdit(midbox); // allow text input
+ codeEdit_->setTextSize(30);
+ codeEdit_->setText(cmd_);
+ codeEdit_->setFocus(); // give focus
+ codeEdit_->enterPressed().connect(this, &DensityApp::reportEdit);
+
+ group_ = new Wt::WButtonGroup(container); // use button group to arrange radio buttons
+
+ Wt::WRadioButton *button;
+ button = new Wt::WRadioButton("Gaussian", container);
+ new Wt::WBreak(container);
+ group_->addButton(button, Gaussian);
+
+ button = new Wt::WRadioButton("Epanechnikov", container);
+ new Wt::WBreak(container);
+ group_->addButton(button, Epanechnikov);
+
+ button = new Wt::WRadioButton("Rectangular", container);
+ new Wt::WBreak(container);
+ group_->addButton(button, Rectangular);
+
+ button = new Wt::WRadioButton("Triangular", container);
+ new Wt::WBreak(container);
+ group_->addButton(button, Triangular);
+
+ button = new Wt::WRadioButton("Cosine", container);
+ new Wt::WBreak(container);
+ group_->addButton(button, Cosine);
+
+ group_->setCheckedButton(group_->button(kernel_));
+ group_->checkedChanged().connect(this, &DensityApp::reportButton);
+
+ // --- image below
+ Wt::WGroupBox *botbox = new Wt::WGroupBox("Resulting chart", root());
+ imgfile_ = new Wt::WFileResource("image/png", tempfile_);
+ imgfile_->suggestFileName("density.png"); // name the clients sees of datafile
+ img_ = new Wt::WImage(imgfile_, "PNG version", botbox);
+
+ Wt::WGroupBox *stbox = new Wt::WGroupBox("Status", root());
+ greeting_ = new WText(stbox); // empty text
+ greeting_->setText("Setting up...");
+
+ reportEdit(); // create a new RNG draw in Yvec_
+ plot(); // and draw a new density plot
+}
+
+void DensityApp::reportButton() {
+ kernel_ = group_->checkedId(); // get id of selected kernel
+ plot();
+}
+
+void DensityApp::reportEdit() {
+ cmd_ = codeEdit_->text().toUTF8(); // get text written in box, as UTF-8, assigned to string
+ std::string rng = "y <- " + cmd_ + ";";
+ R_.parseEvalQ(rng); // evaluates expression, assigns to 'y'
+ Yvec_ = R_["y"]; // cache the y vector
+ plot();
+}
+
+void DensityApp::reportSpinner() {
+ bw_ = spin_->value(); // get the value of the spin selector
+ plot();
+}
+
+void DensityApp::plot() {
+ const char *kernelstr[] = { "gaussian", "epanechnikov", "rectangular", "triangular", "cosine" };
+ greeting_->setText("Starting R call");
+ R_["tfile"] = tempfile_;
+ R_["bw"] = bw_;
+ R_["kernel"] = kernelstr[kernel_]; // passes the string to R
+ R_["y"] = Yvec_;
+ std::string cmd0 = "png(filename=tfile,width=500,height=500); plot(density(y, bw=bw/100, kernel=kernel), xlim=range(y)+c(-2,2), main=\"Kernel: ";
+ std::string cmd1 = "\"); points(y, rep(0, length(y)), pch=16, col=rgb(0,0,0,1/4)); dev.off()";
+ std::string cmd = cmd0 + kernelstr[kernel_] + cmd1; // stick the selected kernel in the middle
+ R_.parseEvalQ(cmd); // evaluate command -- generates new density plot
+ imgfile_->setChanged(); // important: tells consumer that image has changed, forces refresh
+ greeting_->setText("Finished R call for request from " + this->environment().clientAddress());
+}
+
+WApplication *createApplication(const WEnvironment& env) {
+ // You could read information from the environment to decide whether
+ // the user has permission to start a new application
+ return new DensityApp(env, RInside::instance());
+}
+
+int main(int argc, char **argv) {
+
+ RInside R(argc, argv); // create the one embedded R instance
+
+ // Your main method may set up some shared resources, but should then
+ // start the server application (FastCGI or httpd) that starts listening
+ // for requests, and handles all of the application life cycles.
+ //
+ // The last argument to WRun specifies the function that will instantiate
+ // new application objects. That function is executed when a new user surfs
+ // to the Wt application, and after the library has negotiated browser
+ // support. The function should return a newly instantiated application
+ // object.
+ return WRun(argc, argv, createApplication);
+}
More information about the Rinside-commits
mailing list