Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTreeTableInterface.cxx
Go to the documentation of this file.
1 // Author: Roel Aaij 15/08/2007
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #include "TClass.h"
12 #include "Riostream.h"
13 #include "TSystem.h"
14 #include "TEnv.h"
15 #include "TGResourcePool.h"
16 #include "TTreeTableInterface.h"
17 #include "TTreeFormula.h"
18 #include "TError.h"
19 #include "TTree.h"
20 #include "TEntryList.h"
21 #include "TSelectorDraw.h"
22 #include "TTreeFormulaManager.h"
23 #include "TTreeFormula.h"
24 
25 ClassImp(TTreeTableInterface);
26 
27 /** \class TTreeTableInterface
28 
29 TTreeTableInterface is used to interface to data that is stored in a
30 TTree. When the interface is created, an expression can be
31 specified. This expression will define the columns to be shown.
32 
33 A selection criterium can also be specified. A TEntryList will be
34 created and applied to the TTree using this criterium.
35 a new TEntryList to use can be specified using SetEntryList.
36 TGTable->Update() will need to be called to show the effects.
37 
38 WARNING: Do not apply an entrylist to the tree in any other way than
39 through the interface, this will have undefined consequences.
40 
41 Columns can be manipulated using the appropriate methods. A
42 TGTable->Update is always needed afterwards to make the table aware
43 of the changes.
44 */
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// TTreeTableInterface constructor.
48 
49 TTreeTableInterface::TTreeTableInterface (TTree *tree, const char *varexp,
50  const char *selection, Option_t *option, Long64_t nentries,
51  Long64_t firstentry)
52  : TVirtualTableInterface(), fTree(tree), fFormulas(0), fEntry(0),
53  fNEntries(nentries), fFirstEntry(firstentry), fManager(0), fSelect(0), fSelector(0), fInput(0),
54  fForceDim(kFALSE), fEntries(0), fNRows(0), fNColumns(0)
55 {
56  if (fTree == 0) {
57  Error("TTreeTableInterface", "No tree supplied");
58  return;
59  }
60 
61  fFormulas= new TList();
62  fSelector = new TSelectorDraw();
63  fInput = new TList();
64  fInput->Add(new TNamed("varexp",""));
65  fInput->Add(new TNamed("selection",""));
66  fSelector->SetInputList(fInput);
67  fEntry=fFirstEntry;
68 
69  TString opt = option;
70 
71  if (nentries == 0) {
72  fNEntries = fTree->GetEntries();
73  Info("TTreeTableInterface", "nentries was 0, setting to maximum number"
74  " available in the tree");
75  }
76 
77  // Do stuff with opt.Contains() and options
78  SetVariablesExpression(varexp);
79  SetSelection(selection);
80 
81  if (fNRows == 0) {
82  Warning ("TTreeTableInterface::TTreeTableInterface", "nrows = 0");
83  }
84  if (fNColumns == 0) {
85  Warning ("TTreeTableInterface::TTreeTableInterface", "ncolumns = 0");
86  }
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// TTreeTableInterface destructor.
91 
92 TTreeTableInterface::~TTreeTableInterface()
93 {
94  fFormulas->Delete();
95  delete fFormulas;
96  delete fInput;
97  delete fSelector;
98 
99  if (fTree) fTree->SetEntryList(0);
100  delete fEntries;
101 }
102 
103 ////////////////////////////////////////////////////////////////////////////////
104 /// Compile the variables expression from the given varexp.
105 
106 void TTreeTableInterface::SetVariablesExpression(const char *varexp)
107 {
108  // FIXME check if enough protection against wrong expressions is in place
109 
110  Bool_t allvar = kFALSE;
111 
112  if (varexp) {
113  if (!strcmp(varexp, "*")) { allvar = kTRUE; }
114  } else {
115  // if varexp is empty, take all available leaves as a column
116  allvar = kTRUE;
117  }
118 
119  if (allvar) {
120  TObjArray *leaves = fTree->GetListOfLeaves();
121  UInt_t nleaves = leaves->GetEntries();
122  if (!nleaves) {
123  Error("TTreeTableInterface", "No leaves in Tree");
124  return;
125  }
126  fNColumns = nleaves;
127  for (UInt_t ui = 0; ui < fNColumns; ui++) {
128  TLeaf *lf = (TLeaf*)leaves->At(ui);
129  fFormulas->Add(new TTreeFormula("Var1", lf->GetName(), fTree));
130  }
131  // otherwise select only the specified columns
132  } else {
133  std::vector<TString> cnames;
134  fNColumns = fSelector->SplitNames(varexp,cnames);
135 
136  // Create the TreeFormula objects corresponding to each column
137  for (UInt_t ui = 0; ui < fNColumns; ui++) {
138  fFormulas->Add(new TTreeFormula("Var1", cnames[ui].Data(), fTree));
139  }
140  }
141 }
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 /// Set the selection expression.
145 
146 void TTreeTableInterface::SetSelection(const char *selection)
147 {
148  // FIXME verify functionality
149  if (fSelect) {
150  fFormulas->Remove(fSelect);
151  delete fSelect;
152  fSelect = 0;
153  }
154  if (selection && strlen(selection)) {
155  fSelect = new TTreeFormula("Selection", selection, fTree);
156  fFormulas->Add(fSelect);
157  }
158 
159  if (fManager) {
160  for (Int_t i = 0; i <= fFormulas->LastIndex(); i++) {
161  fManager->Remove((TTreeFormula*)fFormulas->At(i));
162  }
163  }
164 
165  // SyncFormulas() will update the formula manager if needed
166  SyncFormulas();
167  InitEntries();
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Sync the formulas using the TTreeFormulaManager.
172 
173 void TTreeTableInterface::SyncFormulas()
174 {
175  // FIXME verify functionality
176 
177  Int_t i = 0;
178  if (fFormulas->LastIndex() >= 0) {
179  if (fSelect) {
180  if (fSelect->GetManager()->GetMultiplicity() > 0 ) {
181  if (!fManager) fManager = new TTreeFormulaManager;
182  for (i = 0; i <= fFormulas->LastIndex(); i++) {
183  fManager->Add((TTreeFormula*)fFormulas->At(i));
184  }
185  fManager->Sync();
186  }
187  }
188  for (i = 0; i < fFormulas->LastIndex(); i++) {
189  TTreeFormula *form = ((TTreeFormula*)fFormulas->At(i));
190  switch (form->GetManager()->GetMultiplicity()) {
191  case 1:
192  case 2:
193  case -1:
194  fForceDim = kTRUE;
195  break;
196  case 0:
197  break;
198  }
199  }
200  }
201 }
202 
203 ////////////////////////////////////////////////////////////////////////////////
204 /// Initialise the TEntryList with the entries that match the
205 /// selection criterium.
206 
207 void TTreeTableInterface::InitEntries()
208 {
209  TEntryList *entrylist = new TEntryList(fTree);
210 
211  UInt_t ui = 0;
212  Int_t i = 0;
213 
214  Long64_t notSkipped = 0;
215  Int_t tnumber = -1;
216  Long64_t entry = fFirstEntry;
217  Int_t entriesToDisplay = fNEntries;
218 
219  while (entriesToDisplay != 0){
220 // entryNumber = fTree->GetEntryNumber(entry);
221 // if(entryNumber < 0) break;
222  Long64_t localEntry = fTree->LoadTree(entry);
223  if (localEntry < 0) break;
224  if (tnumber != fTree->GetTreeNumber()) {
225  tnumber = fTree->GetTreeNumber();
226  if (fManager) fManager->UpdateFormulaLeaves();
227  else {
228  for(i = 0; i < fFormulas->LastIndex(); i++)
229  ((TTreeFormula*)fFormulas->At(ui))->UpdateFormulaLeaves();
230  }
231  }
232  Int_t ndata = 1;
233  if (fForceDim){
234  if (fManager)
235  ndata = fManager->GetNdata(kTRUE);
236  else {
237  for (ui = 0; ui < fNColumns; ui++){
238  if (ndata < ((TTreeFormula*)fFormulas->At(ui))->GetNdata())
239  {
240  ndata = ((TTreeFormula*)fFormulas->At(ui))->GetNdata();
241  }
242  }
243  if (fSelect && fSelect->GetNdata() == 0)
244  ndata = 0;
245  }
246  }
247  Bool_t skip = kFALSE;
248 
249  // Loop over the instances of the selection condition
250  for (Int_t inst = 0; inst < ndata; inst++){
251  if (fSelect){
252  if (fSelect->EvalInstance(inst) == 0){
253  skip = kTRUE;
254  entry++;
255  }
256  }
257  }
258  if (!skip){
259  entrylist->Enter(entry);
260  notSkipped++;
261  entriesToDisplay--;
262  entry++;
263  }
264  }
265  SetEntryList(entrylist);
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Return the value of row,column. If the position does not exist
270 /// or does not contain a number, 0 is returned.
271 
272 Double_t TTreeTableInterface::GetValue(UInt_t row, UInt_t column)
273 {
274  static UInt_t prow = 0;
275 
276  if (row < fNRows) {
277  Long64_t entry = 0;
278  if (row == prow + 1) {
279  entry = fEntries->Next();
280  } else {
281  entry = fEntries->GetEntry(row);
282  }
283  prow = row;
284  fTree->LoadTree(entry);
285  } else {
286  Error("TTreeTableInterface", "Row requested does not exist");
287  return 0;
288  }
289  if (column < fNColumns) {
290  TTreeFormula *formula = (TTreeFormula *)fFormulas->At(column);
291  if (!formula->IsString()) {
292  return (Double_t)formula->EvalInstance();
293  } else {
294  Warning("TTreeTableInterface::GetValue", "Value requested is a "
295  "string, returning 0.");
296  return 0;
297  }
298  } else {
299  Error("TTreeTableInterface", "Column requested does not exist");
300  return 0;
301  }
302 }
303 
304 ////////////////////////////////////////////////////////////////////////////////
305 /// Return the content of row,column as string to use in a
306 /// TGTableCell label.
307 
308 const char *TTreeTableInterface::GetValueAsString(UInt_t row, UInt_t column)
309 {
310  static UInt_t prow = 0;
311 
312  if (row < fNRows) {
313  Long64_t entry = 0;
314  if (row == prow + 1) {
315  entry = fEntries->Next();
316  } else {
317  entry = fEntries->GetEntry(row);
318  }
319  prow = row;
320  fTree->LoadTree(entry);
321  } else {
322  Error("TTreeTableInterface", "Row requested does not exist");
323  return 0;
324  }
325  if (column < fNColumns) {
326  TTreeFormula *formula = (TTreeFormula *)fFormulas->At(column);
327  if(formula->IsString()) {
328  return Form("%s", formula->EvalStringInstance());
329  } else {
330  return Form("%5.2f", (Double_t)formula->EvalInstance());
331  }
332  } else {
333  Error("TTreeTableInterface", "Column requested does not exist");
334  return 0;
335  }
336 }
337 
338 ////////////////////////////////////////////////////////////////////////////////
339 /// Return a string to use as a label for rowheader at column.
340 
341 const char *TTreeTableInterface::GetRowHeader(UInt_t row)
342 {
343  if (row < fNRows) {
344  return Form("%lld", fEntries->GetEntry(row));
345  } else {
346  Error("TTreeTableInterface", "Row requested does not exist");
347  return "";
348  }
349 }
350 
351 ////////////////////////////////////////////////////////////////////////////////
352 /// Return a string to use as a label for columnheader at column.
353 
354 const char *TTreeTableInterface::GetColumnHeader(UInt_t column)
355 {
356  TTreeFormula *formula = (TTreeFormula *)fFormulas->At(column);
357  if (column < fNColumns) {
358  return formula->GetTitle();
359  } else {
360  Error("TTreeTableInterface", "Column requested does not exist");
361  return "";
362  }
363 }
364 
365 ////////////////////////////////////////////////////////////////////////////////
366 /// Return the amount of column available.
367 
368 UInt_t TTreeTableInterface::GetNColumns()
369 {
370  return fNColumns;
371 }
372 
373 ////////////////////////////////////////////////////////////////////////////////
374 /// Return the amount of rows in the Tree.
375 
376 UInt_t TTreeTableInterface::GetNRows()
377 {
378  return fNRows;
379 }
380 
381 ////////////////////////////////////////////////////////////////////////////////
382 /// Add column according ot expression at position,
383 /// TGTable->Update() is needed afterwards to apply the change to
384 /// the TGTable.
385 
386 void TTreeTableInterface::AddColumn(const char *expression, UInt_t position)
387 {
388  TString onerow = expression;
389 
390  if (onerow.Contains(':')) {
391  Error("TTreeTableInterface::AddColumn", "Only 1 expression allowed.");
392  return;
393  }
394 
395  // Create the TreeFormula objects corresponding to the new expression
396  TTreeFormula *formula = new TTreeFormula("Var1", expression, fTree);
397  fFormulas->AddAt(formula, position);
398 
399  if (fManager) {
400  fManager->Add(formula);
401  fManager->Sync();
402  }
403  fNColumns++;
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Add column with formula at position, TGTable->Update() is needed
408 /// afterwards to apply the change to the TGTable.
409 
410 void TTreeTableInterface::AddColumn(TTreeFormula *formula, UInt_t position)
411 {
412  if (position > fNColumns) {
413  Error("TTreeTableInterface::AddColumn", "Please specify a "
414  "valid position.");
415  return;
416  }
417  fFormulas->AddAt(formula, position);
418  if (fManager) {
419  fManager->Add(formula);
420  fManager->Sync();
421  }
422  fNColumns++;
423 }
424 
425 ////////////////////////////////////////////////////////////////////////////////
426 /// Remove column at position, TGTable->Update() is needed
427 /// afterwards to apply the change to the TGTable.
428 
429 void TTreeTableInterface::RemoveColumn(UInt_t position)
430 {
431  if (position >= fNColumns) {
432  Error("TTreeTableInterface::RemoveColumn", "Please specify a "
433  "valid column.");
434  return;
435  } else if (fNColumns == 1) {
436  Error("TTreeTableInterface::RemoveColumn", "Can't remove last column");
437  return;
438  }
439 
440  TTreeFormula *formula = (TTreeFormula *)fFormulas->RemoveAt(position);
441  if (fManager) {
442  fManager->Remove(formula);
443  fManager->Sync();
444  }
445 
446  if (formula) delete formula;
447  fNColumns--;
448 }
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Set the TTreeFormula of position to formula.
452 
453 void TTreeTableInterface::SetFormula(TTreeFormula *formula, UInt_t position)
454 {
455  if (position >= fNColumns) {
456  Error("TTreeTableInterface::SetFormula", "Please specify a "
457  "valid position.");
458  return;
459  }
460  TTreeFormula *form = (TTreeFormula *)fFormulas->RemoveAt(position);
461  if (fSelect) {
462  fManager->Remove(form);
463  }
464  if (form) delete form;
465  fFormulas->AddAt(formula, position);
466  if (fManager) {
467  fManager->Add(formula);
468  fManager->Sync();
469  }
470 
471 }
472 
473 ////////////////////////////////////////////////////////////////////////////////
474 /// Set the currently active entrylist.
475 
476 void TTreeTableInterface::SetEntryList(TEntryList *entrylist)
477 {
478  // Untested
479  if (fEntries) delete fEntries;
480  fEntries = entrylist;
481  fNRows = fEntries->GetN();
482  fTree->SetEntryList(entrylist);
483 }