// @(#)root/r:$Id$
// Author: Omar Zapata 29/05/2013
/*************************************************************************
* Copyright (C) 2013-2014, Omar Andres Zapata Mesa *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#ifndef ROOT_R_TRInterface
#define ROOT_R_TRInterface
#ifndef ROOT_R_TRObject
#include
#endif
#ifndef ROOT_R_TRDataFrame
#include
#endif
#ifndef ROOT_R_TFunctionExport
#include
#endif
#ifndef ROOT_R_TFunctionImport
#include
#endif
#ifndef ROOT_TThread
#include
#endif
/**
@namespace ROOT::R
namespace associated R package for ROOT.
@defgroup R R Interface for Statistical Computing
*/
namespace ROOT {
namespace R {
/**
\class TRInterface
ROOT R was implemented using the
R Project library and the modules
Rcpp and
RInside
Users Guide
http://oproject.org/tiki-index.php?page=ROOT+R+Users+Guide
https://root.cern.ch/drupal/content/how-use-r-root-root-r-interface
\ingroup R
*/
/**
TRInterface class
The TRInterface class lets you procces R code from ROOT.
You can call R libraries and their functions, plot results in R or ROOT,
and use the power of ROOT and R at the same time.
It also lets you pass scalars, vectors and matrices from ROOT to R
and from R to ROOT using TRObject; but you can to use overloaded opetarors [],<< and >>
to work with ROOTR like work with streams of data.
TRInterface class can not be instantiated directly, but you can create objects using the static methods
TRInterface& Instance() and TRInterface* InstancePtr() to create your own objects.
Show an example below:
Create an exponential fit, the idea is to create a set of numbers x,y with noise from ROOT,
pass them to R and fit the data to \f$ x^3 \f$, get the fitted coefficient(power) and plot the data,
the known function and the fitted function.
\code{.cpp}
TCanvas *c1 = new TCanvas("c1","Curve Fit",700,500);
c1->SetGrid();
// draw a frame for multiples graphs
TMultiGraph *mg = new TMultiGraph();
// create the first graph (points with gaussian noise)
const Int_t n = 24;
Double_t x[n] ;
Double_t y[n] ;
//Generate points along a X^3 with noise
TRandom rg;
rg.SetSeed(520);
for (Int_t i = 0; i < n; i++) {
x[i] = rg.Uniform(0, 1);
y[i] = TMath::Power(x[i], 3) + rg.Gaus() * 0.06;
}
TGraph *gr1 = new TGraph(n,x,y);
gr1->SetMarkerColor(kBlue);
gr1->SetMarkerStyle(8);
gr1->SetMarkerSize(1);
mg->Add(gr1);
// create second graph
TF1 *f_known=new TF1("f_known","pow(x,3)",0,1);
TGraph *gr2 = new TGraph(f_known);
gr2->SetMarkerColor(kRed);
gr2->SetMarkerStyle(8);
gr2->SetMarkerSize(1);
mg->Add(gr2);
//passing x and y values to R for fitting
ROOT::R::TRInterface &r=ROOT::R::TRInterface::Instance();
r["x"]<>power;
TF1 *f_fitted=new TF1("f_fitted","pow(x,[0])",0,1);
f_fitted->SetParameter(0,power);
//plotting the fitted function
TGraph *gr3 = new TGraph(f_fitted);
gr3->SetMarkerColor(kGreen);
gr3->SetMarkerStyle(8);
gr3->SetMarkerSize(1);
mg->Add(gr3);
mg->Draw("ap");
//displaying basic results
TPaveText *pt = new TPaveText(0.1,0.6,0.5,0.9,"brNDC");
pt->SetFillColor(18);
pt->SetTextAlign(12);
pt->AddText("Fitting x^power ");
pt->AddText(" \"Blue\" Points with gaussian noise to be fitted");
pt->AddText(" \"Red\" Known function x^3");
TString fmsg;
fmsg.Form(" \"Green\" Fitted function with power=%.4lf",power);
pt->AddText(fmsg);
pt->Draw();
c1->Update();
\endcode
@ingroup R
*/
class TRInterface: public TObject {
protected:
RInside *fR;
TThread *th;
public:
//Proxy class to use operators for assignation Ex: r["name"]=object
class Binding {
public:
Binding(TRInterface *rnt, TString name): fInterface(rnt), fName(name) {}
Binding &operator=(const Binding &obj)
{
fInterface = obj.fInterface;
fName = obj.fName;
return *this;
}
template Binding &operator=(const T &data)
{
fInterface->Assign(data, fName);
return *this;
}
Binding &operator=(const TRFunctionExport &fun)
{
//The method assign is not a template for a function
fInterface->Assign(fun, fName);
return *this;
}
Binding &operator<<(const TRFunctionExport &fun)
{
//The method assign is not a template for a function
fInterface->Assign(fun, fName);
return *this;
}
Binding &operator=(const TRDataFrame &df)
{
fInterface->Assign(df, fName);
return *this;
}
Binding &operator<<(const TRDataFrame &df)
{
fInterface->Assign(df, fName);
return *this;
}
template Binding &operator >>(T &var)
{
var = fInterface->Eval(fName).As();
return *this;
}
template Binding &operator <<(T var)
{
fInterface->Assign(var, fName);
return *this;
}
#include
template operator T()
{
return fInterface->Eval(fName);
}
private:
TRInterface *fInterface;
TString fName;
};
private:
/**
The command line arguments are by deafult argc=0 and argv=NULL,
The verbose mode is by default disabled but you can enable it to show procedures information in stdout/stderr \note some time can produce so much noise in the output
\param argc default 0
\param args default null
\param loadRcpp default true
\param verbose default false
\param interactive default true
*/
TRInterface(const int argc = 0, const char *argv[] = NULL, const bool loadRcpp = true, const bool verbose = false, const bool interactive = true);
public:
~TRInterface();
/**
Method to set verbose mode, that produce extra output
\note some time can produce so much noise in the output
\param status boolean to enable of disable
*/
void SetVerbose(Bool_t status);
/**
Method to eval R code and you get the result in a reference to TRObject
\param code R code
\param ands reference to TRObject
\return an true or false if the execution was sucessful or not.
*/
Int_t Eval(const TString &code, TRObject &ans); // parse line, returns in ans; error code rc
/**
Method to eval R code
\param code R code
*/
void Execute(const TString &code);
/**
Method to eval R code and you get the result in a TRObject
\param code R code
\return a TRObject with result
*/
TRObject Eval(const TString &code);
/**
Template method to assign C++ variables into R enviroment
\param var any R wrappable datatype
\param name name of the variable in R's enviroment
*/
templatevoid Assign(const T &var, const TString &name)
{
// This method lets you pass variables from ROOT to R.
// The template T should be a supported ROOT datatype and
// the TString's name is the name of the variable in the R enviroment.
fR->assign(var, name.Data());
}
/**
Method to assign TRFunctionExport in R's enviroment
\param fun TRFunctionExport
\param name name of the variable in R's enviroment
*/
void Assign(const TRFunctionExport &fun, const TString &name);
/**
Method to assign TRDataFrame in R's enviroment
\param df TRDataFrame
\param name name of the variable in R's enviroment
*/
void Assign(const TRDataFrame &df, const TString &name);
/**
Method to get a R prompt to work interactively with tab completation support
*/
void Interactive();
/**
Init event loop in a thread to support actions in windows from R graphics system
*/
void ProcessEventsLoop();
/**
Method to verify if a package is installed
\param pkg R's pkg name
\return true or false if the package is installed or not
*/
Bool_t IsInstalled(TString pkg);
/**
Method to load an R's package
\param pkg R's pkg name
\return true or false if the package was loaded or not
*/
Bool_t Require(TString pkg);
/**
Method to install an R's package
\param pkg R's pkg name
\param repos url for R's package repository
\return true or false if the package was installed or not
*/
Bool_t Install(TString pkg, TString repos = "http://cran.r-project.org");
Binding operator[](const TString &name);
/**
static method to get an TRInterface instance reference
\return TRInterface instance reference
*/
static TRInterface &Instance();
/**
static method to get an TRInterface instance pointer
\return TRInterface instance pointer
*/
static TRInterface *InstancePtr();
ClassDef(TRInterface, 0)
};
}
}
inline ROOT::R::TRInterface &operator<<(ROOT::R::TRInterface &r, TString code)
{
r.Execute(code);
return r;
}
#endif