Ruby on Rails and some Ruby extensions

2010-04-10

After a long week of borrying daily activities at work, I take the opportunity of this week end to take a look at Ruby on Rails.

Following any online tutorial, we already know that a simple RoR application can be built using very few commands, namely:

$ rails test
$ cd test
$ rake db:create
$ script/server

The last command should fire the Mongrel webserver:

=> Booting Mongrel 
=> Rails 2.3.5 application starting on http://0.0.0.0:3000 
=> Call with -d to detach 
=> Ctrl-C to shutdown server 

As my main idea was to use RoR to build online web form, I also tried to install surveyor. Thus, I followed the help instructions and just created a simple application, as follows:

$ gem install haml
$ rails webform
$ cd webform/
$ script/plugin install git://github.com/breakpointer/surveyor.git -r \
  ‘tag v0.10.0’Initialized empty Git repository in 
  /Users/chl/webform/vendor/plugins/surveyor/.git/
remote: Counting objects: 202, done.
remote: Compressing objects: 100% (188/188), done.
remote: Total 202 (delta 13), reused 95 (delta 0)
Receiving objects: 100% (202/202), 182.05 KiB | 332 KiB/s, done.
Resolving deltas: 100% (13/13), done.
From git://github.com/breakpointer/surveyor
 * [new tag]         v0.10.0    -> v0.10.0
$ script/generate surveyor
$ rake db:migrate

Then I tested the example proposed on surveyor help page

$ rake surveyor FILE=surveys/kitchen_sink_survey.rb
$ script/server
=> Booting Mongrel
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server

and point my browser to http://localhost:3000/surveys to see how it looks:

Well, this looks impressive…

R and ImageMagick

I used ImageMagick whenever I have to convert image from one format to another, and to process images in batch (e.g. create thumbnails, make an animation in gif). As I initially thought ImageMagick interface to Ruby was used by rsruby (which is another interface to the open-source R statistical language, but see RubyForge) as a graphical backend, I first tried to install RImageMagick, but without success. After googling about problem related to InitializeMagick(), I didn’t find any conclusive result about my install problem.

$ Magick-config —libs 
-L/usr/local/ImageMagick-6.5.8/lib -lMagickCore -llcms -ltiff 
-lfreetype -ljpeg -lXext -lSM -lICE -lX11 -lXt -lbz2 -lz 
-lm -lgomp -lpthread

Hopefully, the rsruby install worked fine for me, though I cannot compile the source code itself (see below) and I finally used the gem package.

$ gem install rsruby-0.5.1.1.gem — —with-R-dir=$R_HOME
WARNING:  Installing to ~/.gem since /Library/Ruby/Gems/1.8 and
      /usr/bin aren’t both writable.
Building native extensions.  This could take a while…
Successfully installed rsruby-0.5.1.1
1 gem installed
Installing ri documentation for rsruby-0.5.1.1…
Installing RDoc documentation for rsruby-0.5.1.1…

Note that you may need to adjust your environment variables, e.g. in your .profile, just add these two lines:

export R_HOME=’/Library/Frameworks/R.framework/Resources’
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$R_HOME/bin

Just to roughly check the installation, I started irb (irb -rrsruby) and ran some examples proposed in the rsruby manual, e.g.

irb(main):001:0> r = RSRuby.instance
=> ##, “helpfun”=>#, 
	“help”=>#, “NaN”=>NaN, “FALSE”=>false, “TRUE”=>true, 
	“F”=>false, “NA”=>-2147483648, “eval”=>#, “T”=>true, 
	“parse”=>#}, @proc_table={}>
irb(main):002:0> r.wilcox_test([1,2,3],[4,5,6])
=> {“parameter”=>nil, “p.value”=>0.1, “method”=>“Wilcoxon rank sum test”,
	“null.value”=>{“location shift”=>0.0}, “data.name”=>“1:3 and 4:6”, 
	“alternative”=>“two.sided”, “statistic”=>{“W”=>0.0}}
irb(main):003:0> r.sum(1,2,3)
=> 6
irb(main):004:0> 

The output isn’t very pretty but a better way to generate nice output in the irb console is described in Chapter 5 of the manual.

Note: When trying to manually install the package, the initial setup went fine

$ ruby setup.rb config — —with-R-dir=$R_HOME

whereas

$ ruby setup.rb setup

failed on Mac OS X because Ruby was looking for Rdevices.h in /Library/Frameworks/R.framework/Resources/include while this file actually sits in another place:

$ locate Rdevices.h
/Library/Frameworks/R.framework/Versions/2.10/PrivateHeaders/Rdevices.h
/Library/Frameworks/R.framework/Versions/2.11/PrivateHeaders/Rdevices.h

So, I tried to manually adjust the Makefile in ext/ to update CPPFLAGS accordingly

CPPFLAGS = -DHAVE_R_H -I/Library/Frameworks/R.framework/Resources/include \
  -I/Library/Frameworks/R.framework/PrivateHeaders -D_XOPEN_SOURCE \
  -D_DARWIN_C_SOURCE

While I was in, I also delete the -arch i386 for CFLAGS, ldflags and LDSHARED variables since I am using Snow Leopard in 64 bits mode only. But this fails too.

Ruby/GSL

I get more success with Ruby/GSL which is a pure Ruby implementation of GSL. I installed it from source and tested some of the examples which worked fine for me.

$ cd examples
$ ./cdf.rb 
prob(x < 2.000000) = 0.977250
prob(x > 2.000000) = 0.022750
Pinv(0.977250) = 2.000000
Qinv(0.022750) = 2.000000

where cdf.rb returns several quantiles/probabilities from a Gaussian distribution, see Gist 549213.

The X interface works quite well too,

./butterfly.rb

gives the nice picture shown below.

Doing (some) statistics in Ruby

I came across statsample webpage, which provide a lot of information about this (yet unknown to me) Ruby package. Installation is delightful: everything goes right out of the box (12 gems installed).

$ gem install statsample
$ gem install statsample-optimization
$ gem install alglib

There is even reporting in the reportbuilder package. My next report should be written with Ruby :-)

As a little check, I adapted the example of Dominance Analysis (DA) and just focused on the regression part, see regress.rb below. DA is a method used to compare the relative importance of predictors in multiple regression. DA determines the dominance of one predictor over another by comparing their additional R2 contributions across all subset models. Useful references include:

  1. R Azen & D V Budescu, Comparing Predictors in Multivariate Regression Models: An Extension of Dominance Analysis, Journal of Educational and Behavioral Statistics, 31(2): 157-180 (2006).
  2. R Azen & D V Budescu, The dominance analysis approach for comparing predictors in multiple regression, Psychological Methods, 8(2): 129-148 (2003).

Running regress.rb yields the following output:

. a b c d y
a 1.000 -.018 -.046 -.069 .789
b -.018 1.000 -.007 -.006 .461
c -.046 -.007 1.000 -.081 .274
d -.069 -.006 -.081 1.000 .087
y .789 .461 .274 .087 1.000


= Multiple reggresion of a,b,c,d on y
  Engine: Statsample::Regression::Multiple::RubyEngine
  Cases(listwise)=200(200)
  R=0.989
  R^2=0.978
  R^2 Adj=0.977
  Std.Error R=0.268
  Equation=0.465 + 4.920a + 2.986b + 2.082c + 1.040d
  == ANOVA
source ss df ms f p
Regression 608.145 4 152.036 2120.755 0.000
Error 13.979 195 0.072 . .
Total 622.125 199 152.108 . .


coeff b beta se t
Constant 0.465 0.073 6.376
a 4.920 0.825 0.064 76.576
b 2.986 0.479 0.067 44.623
c 2.082 0.330 0.068 30.565
d 1.040 0.173 0.065 16.064


Note that you may need to add require 'rubygems' at the top of the Ruby file, unless you have something like export RUBYOPT=rubygems in your .profile.

Here is the file regress.rb that was used as Gist 549216.

The script allows to build nice report tables in RTF and HTML (see below).

Finally, I compared Ruby and R output for the computation of a polychoric correlation matrix. You may recall that polychoric correlation are used with ordinal variables. In the simplest case, when we have two binary variables, we speak of a tetrachoric correlation. As an illustration, look at the picture below wich is an excerpt from my course notes in Psychometrics.

Here is the R version:

library(polycor)
data <- rmvnorm(1000, c(0, 0), matrix(c(1, .5, .5, 1), 2, 2))
x <- data[,1]; y <- data[,2]
x <- cut(x, c(-Inf, -1, 1, Inf))
y <- cut(y, c(-Inf, -1, 1, Inf))
table(x,y)

This gives:

           y
x           (-Inf,-1] (-1,1] (1, Inf]
  (-Inf,-1]        63     97        7
  (-1,1]           99    490       99
  (1, Inf]          5     87       53

and

polychor(x, y, std.err=T)

is

Polychoric Correlation, 2-step est. = 0.439 (0.03585)
Test of bivariate normality: Chisquare = 0.3323, df = 3, p = 0.9538

And here is the ruby console (I delete part of the output for clarity):

irb(main):009:0> ct=Matrix[[63,97,7],[99,490,99],[5,87,53]]
irb(main):010:0> poly=Statsample::Bivariate::Polychoric.new(ct)
irb(main):011:0> puts poly.summary
= Polychoric correlation
. Y=0 Y=1 Y=2 Total
X = 0 63 97 7 167
X = 1 99 490 99 688
X = 2 5 87 53 145
T 167 674 159 1000


Threshold X 0 -0.9661
Threshold X 1 1.0581
Threshold Y 0 -0.9661
Threshold Y 1 0.9986


The test of bivariate normality yields: X2 = 0.332, df = 3, p= 0.95385.

JRuby and Ruby-Processing

Quoting a post found on stackoverflow.com, JRuby is the ruby implementation that runs on JVM (Matz’s ruby is C implementation). The main differences are

  • Jruby runs on Java VM and it’s either compiled or interpreted down to Java byte code.
  • JRuby can integrate with Java code. Let’s say if you have java class library (.jar), you can reference and use classes from that library within ruby code if you use JRuby. On the other hand, you can also call Jruby code from java as well. JRuby can also take advantage of the JVM and application server.
  • JRuby is usually hosted within Java application server such as Sun’s glassfish or even Tomcat web server.
  • You cannot use native ruby gem with JRuby. However, there are jruby implementation for most of the popular ruby libraries.
  • There are other differences, you can refer to JRuby wiki

I installed it from the source tarball, with

$ ant
$ ant test
$ ant spec-short

The ant test command gave me some errors, but otherwise the installation seems to be ok.

Why installing another Ruby? Because, JRuby is used as an interface to Processing, a wonderful visualization software. See it in action: ruby-processing.

For those interested in seeing what can be done using Processing, go to openprocessing.org. For instance, here is a nice picture of de Jong attractor:

This was produced using very few lines of code,


deJongAttractor dj;
boolean stop;
int stepCounter;

void setup() { size(640, 640); noFill(); smooth(); colorMode(HSB, 255); dj = new deJongAttractor(); dj.reparam();
}

void draw() { if (!stop) { stepCounter++; if (stepCounter > 127) { stop = true; return; } dj.incrementalupdate(); } image(dj.pi, 0, 0, width, height);
}

void mouseDragged() { noLoop(); stop = true; dj.reparam(); redraw();
}

void mouseReleased() { loop(); stop = false; stepCounter = 0; dj.updateloop();
}

Other nice fractals can be found on Peter de Jong website.




---

Articles with the same tag(s):

Dive into Ruby on Mac OS X

---