This is an attempt to create a wrapper for openturns using R. This is based on the wrapper template called wrapper_calling_shell_command available with openturns and somewhat inspired from the scilab example. Wrappers allow you to call an external program as the function through which you propagate uncertainty with openturns, so that you can write you function in the language you are familiar with (R here) but still take advantage of open turns. This was done in fedora with R and open turns installed (see this post for how to install open turns on a fedora 10 machine).
The first thing we need to do is to grab the template from the installed open turns.
$ mkdir ~/opwrappers
$ cp -fr /usr/local/share/openturns/WrapperTemplates/wrapper_calling_shell_command ~/opwrappers/rwrapper
$ cd ~/opwrappers/rwrapper/
$ ll
total 300
-rw-r--r-- 1 romain romain     27 2009-01-23 11:54 AUTHORS
-rwxr-xr-x 1 romain romain   1304 2009-01-23 11:54 bootstrap
-rw-r--r-- 1 romain romain 199260 2009-01-23 11:54 ChangeLog
-rw-r--r-- 1 romain romain    216 2009-01-23 11:54 code_C1.data
-rw-rw-r-- 1 romain romain   1594 2009-01-23 12:42 configure.ac
-rw-r--r-- 1 romain romain  18002 2009-01-23 11:54 COPYING
-rwxr-xr-x 1 romain romain   1794 2009-01-23 11:54 customize
-rw-r--r-- 1 romain romain   9498 2009-01-23 11:54 INSTALL
drwxr-xr-x 2 romain romain   4096 2009-01-23 11:54 m4
-rw-rw-r-- 1 romain romain    571 2009-01-23 12:42 Makefile.am
-rw-r--r-- 1 romain romain    447 2009-01-23 11:54 myCFunction.c
-rw-r--r-- 1 romain romain    455 2009-01-23 11:54 myCFunction.h
-rw-r--r-- 1 romain romain      0 2009-01-23 11:54 NEWS
-rw-r--r-- 1 romain romain    925 2009-01-23 11:54 README
-rwxrwxr-x 1 romain romain    435 2009-01-23 12:03 rwrapper.R
-rw-rw-r-- 1 romain romain   3722 2009-01-23 12:42 rwrapper.xml.in
-rw-rw-r-- 1 romain romain   1442 2009-01-23 12:42 test.py
-rw-rw-r-- 1 romain romain   9349 2009-01-23 12:42 wrapper.c
-rw-r--r-- 1 romain romain     27 2009-01-23 11:54 AUTHORS
The first thing to do is to customize the wrapper so that it is called rwrapper instead of the default wcode. This is achieved by the customize script:
$ ./customize rwrapper
The files myCFunction.* are useless and you can remove them at that point, we won't need the code_C1.c file either since we are going to write an R script instead.
$ rm myCFunction.* 
$ rm code_C1.c
$ ll
total 288
-rw-r--r-- 1 romain romain     27 2009-01-23 11:54 AUTHORS
-rwxr-xr-x 1 romain romain   1304 2009-01-23 11:54 bootstrap
-rw-r--r-- 1 romain romain 199260 2009-01-23 11:54 ChangeLog
-rw-r--r-- 1 romain romain    216 2009-01-23 11:54 code_C1.data
-rw-rw-r-- 1 romain romain   1594 2009-01-23 12:42 configure.ac
-rw-r--r-- 1 romain romain  18002 2009-01-23 11:54 COPYING
-rwxr-xr-x 1 romain romain   1794 2009-01-23 11:54 customize
-rw-r--r-- 1 romain romain   9498 2009-01-23 11:54 INSTALL
drwxr-xr-x 2 romain romain   4096 2009-01-23 11:54 m4
-rw-rw-r-- 1 romain romain    571 2009-01-23 12:42 Makefile.am
-rw-r--r-- 1 romain romain      0 2009-01-23 11:54 NEWS
-rw-r--r-- 1 romain romain    925 2009-01-23 11:54 README
-rwxrwxr-x 1 romain romain    435 2009-01-23 12:03 rwrapper.R
-rw-rw-r-- 1 romain romain   3722 2009-01-23 12:42 rwrapper.xml.in
-rw-rw-r-- 1 romain romain   1442 2009-01-23 12:42 test.py
-rw-rw-r-- 1 romain romain   9349 2009-01-23 12:42 wrapper.c
Next, we need to write the R script that does the actual work, it needs to grab input file and output file, read data from the input file and write data to the output file. Something like that :
#!/usr/bin/env Rscript

# grab arguments
argv <- commandArgs( TRUE )
datafile <- argv[1]
outfile  <- argv[2] 

# read data from data file 
rl <- readLines( datafile )
extract <- function( index = 1 ){
  rx <- sprintf( "^(I%d *= *)(.*)$", index )
  as.numeric( gsub( rx, "\\2", grep(rx, rl, value = TRUE ) ) ) 
}
x1 <- extract( 1 )
x2 <- extract( 2 )
x3 <- extract( 3 )

out <- x1 + x2 + x3
cat( "O1 = ", out, sep = "", file = outfile )

Next, we need to modify the Makefile.am file so that the make install step copies the rwrapper.R file into the wrappers/bin directory later.
ACLOCAL_AMFLAGS = -I m4

wrapperdir          = $(prefix)/wrappers

wrapper_LTLIBRARIES = rwrapper.la
wcode_la_SOURCES    = wrapper.c
wcode_la_CPPFLAGS   = $(OPENTURNS_WRAPPER_CPPFLAGS)
wcode_la_LDFLAGS    = -module -no-undefined -version-info 0:0:0
wcode_la_LDFLAGS   += $(OPENTURNS_WRAPPER_LDFLAGS)
wcode_la_LIBADD     = $(OPENTURNS_WRAPPER_LIBS)

XMLWRAPPERFILE      = rwrapper.xml
wrapper_DATA        = $(XMLWRAPPERFILE)
EXTRA_DIST          = $(XMLWRAPPERFILE).in test.py code_C1.data

execbindir          = $(prefix)/bin
execbin_DATA        = rwrapper.R
Then, we need to make a few changes to the rwrapper.xml.in file. Here is the definition of the output variable:
        <variable id="O1" type="out">
          <comment>Output 1</comment>
          <unit>none</unit>
          <regexp>O1\S*=\S*(\R)</regexp>
        </variable>

You also need to add the subst tag in the output file definition (at least with this version of openturns) :
      <!-- An output file -->
      <file id="result" type="out">
        <name>The output result file</name>
        <path>code_C1.result</path>
        <subst>O1</subst>
      </file>
 
and then change the command that invokes the script as follows:
    <command>Rscript @prefix@/bin/rwrapper.R code_C1.data code_C1.result</command>

Download the full rwrapper.xml.in file Once this is done (you can grab a tar.gz of the wrapper at that stage) , you can compile the wrapper by following these steps:
$ ./bootstrap
$ ./configure --prefix=/home/romain/openturns --with-openturns=/usr/local
$ make 
$ make install
If all goes well, you should have a rwrapper.R file in the ~/openturns/bin directory and a file rwrapper.xml in the ~/openturns/wrappers directory
Before trying the wrapper, we need to copy the input file in the directory where we are going to run openturns (say /tmp)
$ cp code_C1.data /tmp
$ cd /tmp
Now we are good to go and can start using the wrapper from open turns:
$ python
>>> from openturns import *
>>> p = NumericalPoint( (1,2,3))
>>> f = NumericalMathFunction( "rwrapper" )
>>> print f(p )
class=NumericalPoint name=Unnamed dimension=1 implementation=class=NumericalPointImplementation name=Unnamed dimension=1 values=[6]
>>> 1+2+3
6
The drawback of this approach is that each time the function needs to be evaluated, a new R session will be launched by Rscript, depending on the number of iterations we want to do this can affect seriously the run time of the study. A way to get around this is to use a single R session and let the wrapper communicate with it. I can see at least two ways to do it:
  • by writing the function in python and let python communicate with R (using rpy for instance)
  • by writing a c wrapper that would initialize a connection to an R server when the function is created, and call it whenever the function needs to be called
I'll try to tell these stories in another post