[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