ROOT
v6-36
Reference Guide
Loading...
Searching...
No Matches
TTreeFormula.cxx
Go to the documentation of this file.
1
// @(#)root/treeplayer:$Id$
2
// Author: Rene Brun 19/01/96
3
4
/*************************************************************************
5
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6
* All rights reserved. *
7
* *
8
* For the licensing terms see $ROOTSYS/LICENSE. *
9
* For the list of contributors see $ROOTSYS/README/CREDITS. *
10
*************************************************************************/
11
12
#include "
TROOT.h
"
13
#include "
TTreeFormula.h
"
14
#include "
TList.h
"
15
#include "
TTree.h
"
16
#include "
TBuffer.h
"
17
#include "
TBranch.h
"
18
#include "
TBranchObject.h
"
19
#include "
TBranchElement.h
"
20
#include "
TClonesArray.h
"
21
#include "
TLeafB.h
"
22
#include "
TLeafC.h
"
23
#include "
TLeafElement.h
"
24
#include "
TLeafObject.h
"
25
#include "
TMethodCall.h
"
26
#include "
TCutG.h
"
27
#include "
TRandom.h
"
28
#include "
TInterpreter.h
"
29
#include "
TDataType.h
"
30
#include "
TStreamerInfo.h
"
31
#include "
TStreamerElement.h
"
32
#include "
TArrayI.h
"
33
#include "
TAxis.h
"
34
#include "
TError.h
"
35
#include "
TVirtualCollectionProxy.h
"
36
#include "
TString.h
"
37
#include "
TMath.h
"
38
39
#include "
TVirtualRefProxy.h
"
40
#include "
TTreeFormulaManager.h
"
41
#include "
TFormLeafInfo.h
"
42
#include "
TMethod.h
"
43
#include "
TFormLeafInfoReference.h
"
44
#include "strlcpy.h"
45
#include "snprintf.h"
46
#include "
TEntryList.h
"
47
48
#include <cctype>
49
#include <cstdio>
50
#include <cmath>
51
#include <cstdlib>
52
#include <typeinfo>
53
#include <algorithm>
54
#include <sstream>
55
56
const
Int_t
kMaxLen
= 2048;
57
58
/** \class TTreeFormula
59
Used to pass a selection expression to the Tree drawing routine. See TTree::Draw
60
61
A TreeFormula can contain any arithmetic expression including
62
standard operators and mathematical functions separated by operators.
63
Examples of valid expression:
64
~~~{.cpp}
65
"x<y && sqrt(z)>3.2"
66
~~~
67
TTreeFormula now relies on a variety of TFormLeafInfo classes to handle the
68
reading of the information. Here is the list of theses classes:
69
- TFormLeafInfo
70
- TFormLeafInfoDirect
71
- TFormLeafInfoNumerical
72
- TFormLeafInfoClones
73
- TFormLeafInfoCollection
74
- TFormLeafInfoPointer
75
- TFormLeafInfoMethod
76
- TFormLeafInfoMultiVarDim
77
- TFormLeafInfoMultiVarDimDirect
78
- TFormLeafInfoCast
79
80
The following method are available from the TFormLeafInfo interface:
81
82
- AddOffset(Int_t offset, TStreamerElement* element)
83
- GetCounterValue(TLeaf* leaf) : return the size of the array pointed to.
84
- GetObjectAddress(TLeafElement* leaf) : Returns the location of the object pointed to.
85
- GetMultiplicity() : Returns info on the variability of the number of elements
86
- GetNdata(TLeaf* leaf) : Returns the number of elements
87
- GetNdata() : Used by GetNdata(TLeaf* leaf)
88
- GetValue(TLeaf *leaf, Int_t instance = 0) : Return the value
89
- GetValuePointer(TLeaf *leaf, Int_t instance = 0) : Returns the address of the value
90
- GetLocalValuePointer(TLeaf *leaf, Int_t instance = 0) : Returns the address of the value of 'this' LeafInfo
91
- IsString()
92
- ReadValue(char *where, Int_t instance = 0) : Internal function to interpret the location 'where'
93
- Update() : react to the possible loading of a shared library.
94
*/
95
96
ClassImp
(
TTreeFormula
);
97
98
////////////////////////////////////////////////////////////////////////////////
99
100
inline
static
void
R__LoadBranch
(
TBranch
*
br
,
Long64_t
entry
,
bool
quickLoad
)
101
{
102
if
(!
quickLoad
|| (
br
->GetReadEntry() !=
entry
)) {
103
br
->GetEntry(
entry
);
104
}
105
}
106
107
////////////////////////////////////////////////////////////////////////////////
108
/// \brief Helper function checking if a string contains a literal number.
109
/// Whitespaces are not allowed as part of a valid number-string
110
/// \return true if it can be converted to a valid number (floating or integer),
111
/// false otherwise.
112
113
bool
IsNumberConstant
(
const
std::string &str)
114
{
115
std::istringstream
iss
(str);
116
double
number;
117
return
iss
>> std::noskipws >> number &&
iss
.eof();
118
}
119
120
////////////////////////////////////////////////////////////////////////////////
121
/// \class TDimensionInfo
122
/// A small helper class to help in keeping track of the array
123
/// dimensions encountered in the analysis of the expression.
124
125
class
TDimensionInfo
:
public
TObject
{
126
public
:
127
Int_t
fCode
;
// Location of the leaf in TTreeFormula::fCode
128
Int_t
fOper
;
// Location of the Helper using the leaf in TTreeFormula::fOper
129
Int_t
fSize
;
130
TFormLeafInfoMultiVarDim
*
fMultiDim
;
131
TDimensionInfo
(
Int_t
code,
Int_t
oper
,
Int_t
size
,
TFormLeafInfoMultiVarDim
*
multiDim
)
132
:
fCode
(code),
fOper
(
oper
),
fSize
(
size
),
fMultiDim
(
multiDim
) {};
133
~TDimensionInfo
()
override
{};
134
};
135
136
////////////////////////////////////////////////////////////////////////////////
137
/// TreeFormula constructor only valid for ROOT I/O purposes.
138
139
TTreeFormula::TTreeFormula
(
TRootIOCtor
*):
ROOT
::v5::
TFormula
(), fQuickLoad(
false
), fNeedLoading(
true
),
140
fDidBooleanOptimization(
false
), fDimensionSetup(nullptr)
141
142
{
143
fTree
=
nullptr
;
144
fLookupType
=
nullptr
;
145
fNindex
= 0;
146
fNcodes
= 0;
147
fAxis
=
nullptr
;
148
fHasCast
=
false
;
149
fManager
=
nullptr
;
150
fMultiplicity
= 0;
151
fConstLD
=
nullptr
;
152
153
Int_t
j
,k;
154
for
(
j
=0;
j
<
kMAXCODES
;
j
++) {
155
fNdimensions
[
j
] = 0;
156
fCodes
[
j
] = 0;
157
fNdata
[
j
] = 1;
158
fHasMultipleVarDim
[
j
] =
false
;
159
for
(k = 0; k<
kMAXFORMDIM
; k++) {
160
fIndexes
[
j
][k] = -1;
161
fCumulSizes
[
j
][k] = 1;
162
fVarIndexes
[
j
][k] =
nullptr
;
163
}
164
}
165
}
166
167
////////////////////////////////////////////////////////////////////////////////
168
/// Normal TTree Formula Constructor
169
170
TTreeFormula::TTreeFormula
(
const
char
*
name
,
const
char
*expression,
TTree
*tree)
171
:
ROOT
::v5::
TFormula
(), fTree(tree), fQuickLoad(
false
), fNeedLoading(
true
),
172
fDidBooleanOptimization(
false
), fDimensionSetup(nullptr)
173
{
174
Init
(
name
,expression);
175
}
176
177
////////////////////////////////////////////////////////////////////////////////
178
/// Constructor used during the expansion of an alias
179
180
TTreeFormula::TTreeFormula
(
const
char
*
name
,
const
char
*expression,
TTree
*tree,
181
const
std::vector<std::string>&
aliases
)
182
:
ROOT
::v5::
TFormula
(), fTree(tree), fQuickLoad(
false
), fNeedLoading(
true
),
183
fDidBooleanOptimization(
false
), fDimensionSetup(nullptr), fAliasesUsed(
aliases
)
184
{
185
Init
(
name
,expression);
186
}
187
188
////////////////////////////////////////////////////////////////////////////////
189
/// Initialization called from the constructors.
190
191
void
TTreeFormula::Init
(
const
char
*
name
,
const
char
* expression)
192
{
193
TDirectory
*
const
savedir
=
gDirectory
;
194
195
fNindex
=
kMAXFOUND
;
196
fLookupType
=
new
Int_t
[
fNindex
];
197
fNcodes
= 0;
198
fMultiplicity
= 0;
199
fAxis
=
nullptr
;
200
fHasCast
=
false
;
201
fConstLD
=
nullptr
;
202
Int_t
i,
j
,k;
203
fManager
=
new
TTreeFormulaManager
;
204
fManager
->
Add
(
this
);
205
206
for
(
j
=0;
j
<
kMAXCODES
;
j
++) {
207
fNdimensions
[
j
] = 0;
208
fLookupType
[
j
] =
kDirect
;
209
fCodes
[
j
] = 0;
210
fNdata
[
j
] = 1;
211
fHasMultipleVarDim
[
j
] =
false
;
212
for
(k = 0; k<
kMAXFORMDIM
; k++) {
213
fIndexes
[
j
][k] = -1;
214
fCumulSizes
[
j
][k] = 1;
215
fVarIndexes
[
j
][k] =
nullptr
;
216
}
217
}
218
219
fDimensionSetup
=
new
TList
;
220
221
if
(
Compile
(expression)) {
222
fTree
=
nullptr
;
fNdim
= 0;
223
if
(
savedir
)
savedir
->cd();
224
return
;
225
}
226
227
if
(
fNcodes
>=
kMAXFOUND
) {
228
Warning
(
"TTreeFormula"
,
"Too many items in expression:%s"
,expression);
229
fNcodes
=
kMAXFOUND
;
230
}
231
SetName
(
name
);
232
233
for
(i=0;i<
fNoper
;i++) {
234
235
if
(
GetAction
(i)==
kDefinedString
) {
236
Int_t
string_code
=
GetActionParam
(i);
237
TLeaf
*
leafc
= (
TLeaf
*)
fLeaves
.
UncheckedAt
(
string_code
);
238
if
(!
leafc
)
continue
;
239
240
// We have a string used as a string
241
242
// This dormant portion of code would be used if (when?) we allow the histogramming
243
// of the integral content (as opposed to the string content) of strings
244
// held in a variable size container delimited by a null (as opposed to
245
// a fixed size container or variable size container whose size is controlled
246
// by a variable). In GetNdata, we will then use strlen to grab the current length.
247
//fCumulSizes[i][fNdimensions[i]-1] = 1;
248
//fUsedSizes[fNdimensions[i]-1] = -TMath::Abs(fUsedSizes[fNdimensions[i]-1]);
249
//fUsedSizes[0] = - TMath::Abs( fUsedSizes[0]);
250
251
if
(
fNoper
== 1) {
252
// If the string is by itself, then it can safely be histogrammed as
253
// in a string based axis. To histogram the number inside the string
254
// just make it part of a useless expression (for example: mystring+0)
255
SetBit
(
kIsCharacter
);
256
}
257
continue
;
258
}
259
if
(
GetAction
(i)==
kJump
&&
GetActionParam
(i)==(
fNoper
-1)) {
260
// We have cond ? string1 : string2
261
if
(
IsString
(
fNoper
-1))
SetBit
(
kIsCharacter
);
262
}
263
}
264
if
(
fNoper
== 1 &&
GetAction
(0)==
kStringConst
) {
265
SetBit
(
kIsCharacter
);
266
}
267
if
(
fNoper
==1 &&
GetAction
(0)==
kAliasString
) {
268
TTreeFormula
*
subform
=
static_cast<
TTreeFormula
*
>
(
fAliases
.
UncheckedAt
(0));
269
R__ASSERT
(
subform
);
270
if
(
subform
->IsString())
SetBit
(
kIsCharacter
);
271
}
else
if
(
fNoper
==2 &&
GetAction
(0)==
kAlternateString
) {
272
TTreeFormula
*
subform
=
static_cast<
TTreeFormula
*
>
(
fAliases
.
UncheckedAt
(0));
273
R__ASSERT
(
subform
);
274
if
(
subform
->IsString())
SetBit
(
kIsCharacter
);
275
}
276
277
fManager
->
Sync
();
278
279
// Let's verify the indexes and dies if we need to.
280
Int_t
k0
,
k1
;
281
for
(
k0
= 0;
k0
<
fNcodes
;
k0
++) {
282
for
(
k1
= 0;
k1
<
fNdimensions
[
k0
];
k1
++ ) {
283
// fprintf(stderr,"Saw %d dim %d and index %d\n",k1, fFixedSizes[k0][k1], fIndexes[k0][k1]);
284
if
(
fIndexes
[
k0
][
k1
]>=0 &&
fFixedSizes
[
k0
][
k1
]>=0
285
&&
fIndexes
[
k0
][
k1
]>=
fFixedSizes
[
k0
][
k1
]) {
286
Error
(
"TTreeFormula"
,
287
"Index %d for dimension #%d in %s is too high (max is %d)"
,
288
fIndexes
[
k0
][
k1
],
k1
+1, expression,
fFixedSizes
[
k0
][
k1
]-1);
289
fTree
=
nullptr
;
fNdim
= 0;
290
if
(
savedir
)
savedir
->cd();
291
return
;
292
}
293
}
294
}
295
296
// Create a list of unique branches to load.
297
for
(k=0; k<
fNcodes
; k++) {
298
TLeaf
*
leaf
= k <=
fLeaves
.
GetLast
() ? (
TLeaf
*)
fLeaves
.
UncheckedAt
(k) :
nullptr
;
299
TBranch
*
branch
=
nullptr
;
300
if
(
leaf
) {
301
branch
=
leaf
->GetBranch();
302
if
(
fBranches
.
FindObject
(
branch
))
branch
=
nullptr
;
303
}
304
fBranches
.
AddAtAndExpand
(
branch
,k);
305
}
306
307
if
(
IsInteger
(
false
))
SetBit
(
kIsInteger
);
308
309
if
(
TestBit
(
TTreeFormula::kNeedEntries
)) {
310
// Call TTree::GetEntries() to insure that it is already calculated.
311
// This will need to be done anyway at the first iteration and insure
312
// that it will not mess up the branch reading (because TTree::GetEntries
313
// opens all the file in the chain and 'stays' on the last file.
314
315
Long64_t
readentry
=
fTree
->
GetReadEntry
();
316
Int_t
treenumber
=
fTree
->
GetTreeNumber
();
317
fTree
->
GetEntries
();
318
if
(
treenumber
!=
fTree
->
GetTreeNumber
()) {
319
if
(
readentry
>= 0) {
320
fTree
->
LoadTree
(
readentry
);
321
}
322
UpdateFormulaLeaves
();
323
}
else
{
324
if
(
readentry
>= 0) {
325
fTree
->
LoadTree
(
readentry
);
326
}
327
}
328
329
}
330
331
if
(
savedir
)
savedir
->cd();
332
}
333
334
////////////////////////////////////////////////////////////////////////////////
335
/// Tree Formula default destructor.
336
337
TTreeFormula::~TTreeFormula
()
338
{
339
if
(
fManager
) {
340
fManager
->
Remove
(
this
);
341
if
(
fManager
->
fFormulas
.
GetLast
()<0) {
342
delete
fManager
;
343
fManager
=
nullptr
;
344
}
345
}
346
// Objects in fExternalCuts are not owned and should not be deleted
347
// fExternalCuts.Clear();
348
fLeafNames
.
Delete
();
349
fDataMembers
.
Delete
();
350
fMethods
.
Delete
();
351
fAliases
.
Delete
();
352
if
(
fLookupType
)
delete
[]
fLookupType
;
353
for
(
int
j
=0;
j
<
fNcodes
;
j
++) {
354
for
(
int
k = 0; k<
fNdimensions
[
j
]; k++) {
355
if
(
fVarIndexes
[
j
][k])
delete
fVarIndexes
[
j
][k];
356
fVarIndexes
[
j
][k] =
nullptr
;
357
}
358
}
359
if
(
fDimensionSetup
) {
360
fDimensionSetup
->
Delete
();
361
delete
fDimensionSetup
;
362
}
363
delete
[]
fConstLD
;
364
}
365
366
////////////////////////////////////////////////////////////////////////////////
367
/// This method is used internally to decode the dimensions of the variables.
368
369
void
TTreeFormula::DefineDimensions
(
Int_t
code,
Int_t
size
,
370
TFormLeafInfoMultiVarDim
*
info
,
371
Int_t
&
virt_dim
) {
372
if
(
info
) {
373
fManager
->
EnableMultiVarDims
();
374
//if (fIndexes[code][info->fDim]<0) { // removed because the index might be out of bounds!
375
info
->fVirtDim =
virt_dim
;
376
fManager
->
AddVarDims
(
virt_dim
);
// if (!fVarDims[virt_dim]) fVarDims[virt_dim] = new TArrayI;
377
//}
<