Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTreeFormulaManager.cxx
Go to the documentation of this file.
1 // @(#)root/treeplayer:$Id$
2 // Author: Philippe Canal 20/03/02
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers and al. *
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 "TTreeFormulaManager.h"
13 
14 #include "TArrayI.h"
15 #include "TError.h"
16 #include "TLeafElement.h"
17 
18 ClassImp(TTreeFormulaManager);
19 
20  /** \class TTreeFormulaManager
21  Used to coordinate one or more TTreeFormula objects.
22 
23  In particular it makes sure that the dimensions and size of all the formulas
24  is properly coordinated.
25  */
26 
27  ////////////////////////////////////////////////////////////////////////////////
28  /// Tree FormulaManger default constructor.
29 
30 TTreeFormulaManager::TTreeFormulaManager() : TObject()
31 {
32  fMultiplicity = 0;
33  fMultiVarDim = kFALSE;
34  fNeedSync = kFALSE;
35  fNdata = 1;
36 
37  for (Int_t i = 0; i < kMAXFORMDIM + 1; i++) {
38  fVarDims[i] = 0;
39  fCumulUsedSizes[i] = 1;
40  fUsedSizes[i] = 1;
41  fVirtUsedSizes[i] = 1;
42  }
43  fCumulUsedVarDims = 0;
44 }
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// Tree FormulaManager default destructor.
48 
49 TTreeFormulaManager::~TTreeFormulaManager()
50 {
51  for (int l = 0; l < kMAXFORMDIM; l++) {
52  if (fVarDims[l]) delete fVarDims[l];
53  fVarDims[l] = 0;
54  }
55  if (fCumulUsedVarDims) delete fCumulUsedVarDims;
56 }
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// Remove a formula from this manager
60 
61 void TTreeFormulaManager::Remove(TTreeFormula *adding)
62 {
63  fFormulas.Remove(adding);
64 }
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 /// Add a new formula to the list of formulas managed
68 /// The manager of the formula will be changed and the old one will be deleted
69 /// if it is empty.
70 
71 void TTreeFormulaManager::Add(TTreeFormula *adding)
72 {
73  TTreeFormulaManager *old = adding->fManager;
74 
75  if (old) {
76  if (old == this) {
77  if (fFormulas.FindObject(adding)) return;
78  } else {
79  old->fFormulas.Remove(adding);
80  if (old->fFormulas.GetLast() == -1) delete adding->fManager;
81  }
82  }
83 
84  if (adding->TestBit(TTreeFormula::kNeedEntries)) {
85  SetBit(TTreeFormula::kNeedEntries);
86  }
87 
88  fFormulas.Add(adding);
89  adding->fManager = this;
90  fNeedSync = kTRUE;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Add a variable dimension
95 
96 void TTreeFormulaManager::AddVarDims(Int_t virt_dim)
97 {
98  if (!fVarDims[virt_dim]) fVarDims[virt_dim] = new TArrayI;
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Cancel a dimension. This is usually called when an out-of-bounds index
103 /// is used.
104 
105 void TTreeFormulaManager::CancelDimension(Int_t virt_dim)
106 {
107  fCumulUsedSizes[virt_dim] = 0;
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Set the manager as handling a formula with multiple variable dimensions
112 
113 void TTreeFormulaManager::EnableMultiVarDims()
114 {
115  fMultiVarDim = kTRUE;
116  if (!fCumulUsedVarDims) fCumulUsedVarDims = new TArrayI;
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Return number of available instances in the formulas.
121 
122 Int_t TTreeFormulaManager::GetNdata(Bool_t forceLoadDim)
123 {
124  Int_t k;
125 
126  // new version of GetNData:
127  // Possible problem: we only allow one variable dimension so far.
128  if (fMultiplicity == 0) return fNdata;
129 
130  if (fMultiplicity == 2) return fNdata; // CumulUsedSizes[0];
131 
132  // We have at least one leaf with a variable size:
133 
134  // Reset the registers.
135  for (k = 0; k <= kMAXFORMDIM; k++) {
136  fUsedSizes[k] = TMath::Abs(fVirtUsedSizes[k]);
137  if (fVarDims[k]) {
138  for (Int_t i0 = 0; i0 < fVarDims[k]->GetSize(); i0++) {
139  fVarDims[k]->AddAt(0, i0);
140  }
141  }
142  }
143  if (fCumulUsedVarDims) {
144  for (Int_t i0 = 0; i0 < fCumulUsedVarDims->GetSize(); ++i0) {
145  fCumulUsedVarDims->AddAt(0, i0);
146  }
147  }
148 
149  TTreeFormula *current = 0;
150 
151  Int_t size = fFormulas.GetLast() + 1;
152 
153  for (Int_t i = 0; i < size; i++) {
154 
155  current = (TTreeFormula *)fFormulas.UncheckedAt(i);
156  if (current->fMultiplicity != 1 && !current->fHasCast) continue;
157  if (!current->LoadCurrentDim()) {
158  if (forceLoadDim) {
159  for (Int_t j = i + 1; j < size; j++) {
160  current = (TTreeFormula *)fFormulas.UncheckedAt(j);
161  if (current->fMultiplicity != 1 && !current->fHasCast) continue;
162  current->LoadCurrentDim();
163  }
164  }
165  fNdata = 0;
166  return 0;
167  }
168  }
169 
170  if (fMultiplicity == -1) {
171  fNdata = 1;
172  return fCumulUsedSizes[0];
173  }
174 
175  Int_t overall = 1;
176  if (!fMultiVarDim) {
177  for (k = kMAXFORMDIM; (k >= 0); k--) {
178  if (fUsedSizes[k] >= 0) {
179  overall *= fUsedSizes[k];
180  fCumulUsedSizes[k] = overall;
181  } else {
182  Error("GetNdata", "a dimension is still negative!");
183  }
184  }
185  } else {
186  overall = 0; // Since we work with additions in this section
187  if (fCumulUsedVarDims && fUsedSizes[0] > fCumulUsedVarDims->GetSize()) fCumulUsedVarDims->Set(fUsedSizes[0]);
188  for (Int_t i = 0; i < fUsedSizes[0]; i++) {
189  Int_t local_overall = 1;
190  for (k = kMAXFORMDIM; (k > 0); k--) {
191  if (fVarDims[k]) {
192  Int_t index = fVarDims[k]->At(i);
193  if (fCumulUsedVarDims && fCumulUsedVarDims->At(i) == 1 && index) index = 1;
194  if (fUsedSizes[k] == 1 || (index != 1 && index < fUsedSizes[k]))
195  local_overall *= index;
196  else
197  local_overall *= fUsedSizes[k];
198  } else {
199  local_overall *= fUsedSizes[k];
200  }
201  }
202  // a negative value indicates that this value of the primary index
203  // will lead to an invalid index; So we skip it.
204  if (fCumulUsedVarDims->At(i) < 0)
205  fCumulUsedVarDims->AddAt(0, i);
206  else {
207  fCumulUsedVarDims->AddAt(local_overall, i);
208  overall += local_overall;
209  }
210  }
211  }
212  fNdata = overall;
213  return overall;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Synchronize all the formulae.
218 
219 Bool_t TTreeFormulaManager::Sync()
220 {
221  if (!fNeedSync) return true;
222 
223  TTreeFormula *current = 0;
224  Bool_t hasCast = kFALSE;
225 
226  fMultiplicity = 0;
227  // We do not use an intermediary variable because ResetDimensions
228  // might add more formulas (TCutG).
229  for (Int_t i = 0; i < fFormulas.GetLast() + 1; i++) {
230  current = (TTreeFormula *)fFormulas.UncheckedAt(i);
231 
232  hasCast |= current->fHasCast;
233 
234  // We probably need to reset the formula's dimension
235 
236  current->ResetDimensions();
237  switch (current->GetMultiplicity()) {
238  case 0:
239  // nothing to do
240  break;
241  case 1: fMultiplicity = 1; break;
242  case 2:
243  if (fMultiplicity != 1) fMultiplicity = 2;
244  break;
245  default: Error("Sync", "Unexpected case!");
246  }
247 
248  } // end of for each formulas
249 
250  // For now we keep fCumulUsedSizes sign aware.
251  // This will be reset properly (if needed) by GetNdata.
252  fCumulUsedSizes[kMAXFORMDIM] = fUsedSizes[kMAXFORMDIM];
253  for (Int_t k = kMAXFORMDIM; (k > 0); k--) {
254  if (fUsedSizes[k - 1] >= 0) {
255  fCumulUsedSizes[k - 1] = fUsedSizes[k - 1] * fCumulUsedSizes[k];
256  } else {
257  fCumulUsedSizes[k - 1] = -TMath::Abs(fCumulUsedSizes[k]);
258  }
259  }
260 
261  // Now that we know the virtual dimension we know if a loop over EvalInstance
262  // is needed or not.
263  if (fCumulUsedSizes[0] == 1 && fMultiplicity > 0) {
264  // Case where even though we have an array. We know that they will always
265  // only be one element.
266  fMultiplicity -= 2;
267  } else if (fCumulUsedSizes[0] < 0 && fMultiplicity == 2) {
268  // Case of a fixed length array that have one of its indices given
269  // by a variable.
270  fMultiplicity = 1;
271  } else if (fMultiplicity == 0 && hasCast) {
272  fMultiplicity = -1;
273  }
274 
275  switch (fMultiplicity) {
276  case 0: fNdata = 1; break;
277  case 2: fNdata = fCumulUsedSizes[0]; break;
278  default: fNdata = 0;
279  }
280  fNeedSync = kFALSE;
281 
282  return true;
283 }
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 /// This function could be called TTreePlayer::UpdateFormulaLeaves, itself
287 /// called by TChain::LoadTree when a new Tree is loaded.
288 /// Because Trees in a TChain may have a different list of leaves, one
289 /// must update the leaves numbers in the TTreeFormula used by the TreePlayer.
290 
291 void TTreeFormulaManager::UpdateFormulaLeaves()
292 {
293  // A safer alternative would be to recompile the whole thing .... However
294  // currently compile HAS TO be called from the constructor!
295 
296  Int_t size = fFormulas.GetLast() + 1;
297 
298  for (Int_t i = 0; i < size; i++) {
299 
300  TTreeFormula *current = (TTreeFormula *)fFormulas.UncheckedAt(i);
301  current->UpdateFormulaLeaves();
302  }
303 }
304 
305 ////////////////////////////////////////////////////////////////////////////////
306 /// Reload the array sizes
307 
308 void TTreeFormulaManager::UpdateUsedSize(Int_t &virt_dim, Int_t vsize)
309 {
310  if (vsize < 0)
311  fVirtUsedSizes[virt_dim] = -1 * TMath::Abs(fVirtUsedSizes[virt_dim]);
312  else if (TMath::Abs(fVirtUsedSizes[virt_dim]) == 1 || (vsize < TMath::Abs(fVirtUsedSizes[virt_dim]))) {
313  // Absolute values represent the min of all real dimensions
314  // that are known. The fact that it is negatif indicates
315  // that one of the leaf has a variable size for this
316  // dimensions.
317  if (fVirtUsedSizes[virt_dim] < 0) {
318  fVirtUsedSizes[virt_dim] = -1 * vsize;
319  } else {
320  fVirtUsedSizes[virt_dim] = vsize;
321  }
322  }
323  fUsedSizes[virt_dim] = fVirtUsedSizes[virt_dim];
324  virt_dim++;
325 }