Logo ROOT  
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"
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"
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
56const Int_t kMaxLen = 2048;
57
58/** \class TTreeFormula
59Used to pass a selection expression to the Tree drawing routine. See TTree::Draw
60
61A TreeFormula can contain any arithmetic expression including
62standard operators and mathematical functions separated by operators.
63Examples of valid expression:
64~~~{.cpp}
65 "x<y && sqrt(z)>3.2"
66~~~
67TTreeFormula now relies on a variety of TFormLeafInfo classes to handle the
68reading 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
80The 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
97
98////////////////////////////////////////////////////////////////////////////////
99
100inline 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
113bool 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
125class TDimensionInfo : public TObject {
126public:
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
133 ~TDimensionInfo() override {};
134};
135
136////////////////////////////////////////////////////////////////////////////////
137/// TreeFormula constructor only valid for ROOT I/O purposes.
138
139TTreeFormula::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
170TTreeFormula::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
180TTreeFormula::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
191void TTreeFormula::Init(const char*name, const char* expression)
192{
194
197 fNcodes = 0;
198 fMultiplicity = 0;
199 fAxis = nullptr;
200 fHasCast = false;
201 fConstLD = nullptr;
202 Int_t i,j,k;
204 fManager->Add(this);
205
206 for (j=0; j<kMAXCODES; j++) {
207 fNdimensions[j] = 0;
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
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);
230 }
231 SetName(name);
232
233 for (i=0;i<fNoper;i++) {
234
235 if (GetAction(i)==kDefinedString) {
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)
256 }
257 continue;
258 }
259 if (GetAction(i)==kJump && GetActionParam(i)==(fNoper-1)) {
260 // We have cond ? string1 : string2
262 }
263 }
264 if (fNoper == 1 && GetAction(0)==kStringConst) {
266 }
267 if (fNoper==1 && GetAction(0)==kAliasString) {
270 if (subform->IsString()) SetBit(kIsCharacter);
271 } else if (fNoper==2 && GetAction(0)==kAlternateString) {
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 }
305 }
306
307 if (IsInteger(false)) SetBit(kIsInteger);
308
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
317 fTree->GetEntries();
318 if (treenumber != fTree->GetTreeNumber()) {
319 if (readentry >= 0) {
321 }
323 } else {
324 if (readentry >= 0) {
326 }
327 }
328
329 }
330
331 if(savedir) savedir->cd();
332}
333
334////////////////////////////////////////////////////////////////////////////////
335/// Tree Formula default destructor.
336
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();
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) {
361 delete fDimensionSetup;
362 }
363 delete[] fConstLD;
364}
365
366////////////////////////////////////////////////////////////////////////////////
367/// This method is used internally to decode the dimensions of the variables.
368
371 Int_t& virt_dim) {
372 if (info) {
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 //}