forked from root-project/root
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TRInterface.h
331 lines (290 loc) · 11.2 KB
/
TRInterface.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// @(#)root/r:$Id$
// Author: Omar Zapata Omar.Zapata@cern.ch 29/05/2013
/*************************************************************************
* Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
* 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
#include <TRObject.h>
#include <TRDataFrame.h>
#include <TRFunctionExport.h>
#include <TRFunctionImport.h>
#include <TThread.h>
/**
@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
<A HREF="http://www.r-project.org/">R Project</A> library and the modules
<A HREF="http://cran.r-project.org/web/packages/Rcpp/index.html">Rcpp</A> and
<A HREF="http://cran.r-project.org/web/packages/RInside/index.html">RInside</A>
<h2>Users Guide </h2>
<a href="https://oproject.org/pages/ROOT%20R%20Users%20Guide"> https://oproject.org/pages/ROOT R Users Guide</a><br>
\ingroup R
*/
/**
<center><h2>TRInterface class</h2></center>
</p>
The TRInterface class lets you process R code from ROOT.<br>
You can call R libraries and their functions, plot results in R or ROOT,<br>
and use the power of ROOT and R at the same time.<br>
It also lets you pass scalars, vectors and matrices from ROOT to R<br>
and from R to ROOT using TRObject; but you can to use overloaded operators [],<< and >> <br>
to work with ROOTR like work with streams of data.<br>
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.<br>
<br>
</p>
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"]<<TVectorD(n, x);
r["y"]<<TVectorD(n, y);
//creating a R data frame
r<<"ds<-data.frame(x=x,y=y)";
//fitting x and y to X^power using Nonlinear Least Squares
r<<"m <- nls(y ~ I(x^power),data = ds, start = list(power = 1),trace = T)";
//getting the fitted value (power)
Double_t power;
r["summary(m)$coefficients[1]"]>>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(const Binding &obj) {
fInterface = obj.fInterface;
fName = obj.fName;
}
Binding &operator=(const Binding &obj)
{
fInterface = obj.fInterface;
fName = obj.fName;
return *this;
}
template <class T> Binding &operator=(const T &data)
{
fInterface->Assign<T>(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 <class T> Binding &operator >>(T &var)
{
var = fInterface->Eval(fName).As<T>();
return *this;
}
template <class T> Binding &operator <<(T var)
{
fInterface->Assign<T>(var, fName);
return *this;
}
#include<TRInterface_Binding.h>
template <class T> operator T()
{
return fInterface->Eval(fName);
}
private:
TRInterface *fInterface;
TString fName;
};
private:
/**
The command line arguments are by default 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 argv default null
\param loadRcpp default true
\param verbose default false
\param interactive default true
*/
TRInterface(const Int_t argc = 0, const Char_t *argv[] = NULL, const Bool_t loadRcpp = true,
const Bool_t verbose = false, const Bool_t 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 ans reference to TRObject
\return an true or false if the execution was successful 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);
// "unhide" TObject::Execute methods.
using TObject::Execute;
/**
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 environment
\param var any R wrappable datatype
\param name name of the variable in R's environment
*/
template<typename T >void 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 environment.
fR->assign<T>(var, name.Data());
}
/**
Method to assign TRFunctionExport in R's environment
\param fun TRFunctionExport
\param name name of the variable in R's environment
*/
void Assign(const TRFunctionExport &fun, const TString &name);
/**
Method to assign TRDataFrame in R's environment
\param df TRDataFrame
\param name name of the variable in R's environment
*/
void Assign(const TRDataFrame &df, const TString &name);
/**
Method to get a R prompt to work interactively with tab completion 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