// @(#)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