AliRoot Core  edcc906 (edcc906)
AliTreePlayer.cxx
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  * *
4  * Author: The ALICE Off-line Project. *
5  * Contributors are mentioned in the code where appropriate. *
6  * *
7  * Permission to use, copy, modify and distribute this software and its *
8  * documentation strictly for non-commercial purposes is hereby granted *
9  * without fee, provided that the above copyright notice appears in all *
10  * copies and that both the copyright notice and this permission notice *
11  * appear in the supporting documentation. The authors make no claims *
12  * about the suitability of this software for any purpose. It is *
13  * provided "as is" without express or implied warranty. *
14  **************************************************************************/
15 
16 
17 
18 
19 #include "TStatToolkit.h"
20 #include "Riostream.h"
21 #include <iostream>
22 #include "TSystem.h"
23 #include "TNamed.h"
24 #include "TFile.h"
25 #include "TTree.h"
26 #include "TPRegexp.h"
27 #include "TFriendElement.h"
28 #include "AliExternalInfo.h"
29 #include "TTreeFormula.h"
30 #include "TTreeFormulaManager.h"
31 #include "AliTreePlayer.h"
32 #include "TEntryList.h"
33 #include "THn.h"
34 #include "TLegend.h"
35 #include "TBufferJSON.h"
36 #include "AliSysInfo.h"
37 #include <sstream>
38 #include <bitset>
39 #include "TTimeStamp.h"
40 using namespace std;
41 ClassImp(AliTreePlayer)
42 ClassImp(AliTreeFormulaF)
43 
44 
46 AliTreeFormulaF::AliTreeFormulaF() : TTreeFormula(), fTextArray(NULL), fFormatArray(NULL), fFormulaArray(NULL),fValue(""),fDebug(0) {
47 }
48 
53 AliTreeFormulaF::AliTreeFormulaF(const char *name, const char *formula, TTree *tree, Int_t debug):
54  TTreeFormula(), fTextArray(NULL), fFormatArray(NULL), fFormulaArray(NULL), fValue(""), fDebug(debug) {
55  SetName(name);
56  SetTitle(formula);
57  SetTree(tree);
58  Compile(formula);
59  SetBit(kIsCharacter);
60 
61 }
62 
65  delete fTextArray;
66  delete fFormulaArray;
67  delete fFormatArray;
68 }
69 
74 Int_t AliTreeFormulaF::Compile(const char *expression) {
75  TTree *tree = GetTree();
76  TString fquery = expression;
77  //
78  // 1. GetList of %format{variables} to query
79  // format: TStringf
80  // variable: TTreeFormula
81  // 3. GetFormatted string
82  //
83  Int_t sLength = fquery.Length(); // original format string
84  Int_t iVar = 0;
85  Int_t varBegin = -1;
87  fFormatArray = new TObjArray;
88  fTextArray = new TObjArray;
89  Int_t nVars = 0;
90  Int_t lastI = 0;
91  Int_t iChar = 0;
92  for (iChar = 0; iChar < fquery.Length(); iChar++) {
93  if (fquery[iChar] != '{') continue;
94  Int_t delta0 = 1, deltaf = 0;
95  for (delta0 = 1; delta0 + iChar < fquery.Length(); delta0++) if (fquery[iChar + delta0] == '}') break;
96  for (deltaf = -1; deltaf + iChar >= 0; deltaf--) if (fquery[iChar + deltaf] == '%') break;
97  TString stext(fquery(lastI, iChar + deltaf - lastI));
98  TString sformat(fquery(iChar + deltaf + 1, -(deltaf + 1)));
99  TString sformula(fquery(iChar + 1, delta0 - 1));
100  if (fDebug&4) {
101  printf("%d\t%d\t%d\n", iChar, deltaf, delta0);
102  printf("%d\t%s\t%s\t%s\n", nVars, stext.Data(), sformat.Data(), sformula.Data());
103  }
104  fFormatArray->AddAtAndExpand(new TObjString(sformat.Data()), nVars);
105  fTextArray->AddAtAndExpand(new TObjString(stext.Data()), nVars);
106  fFormulaArray->AddAtAndExpand(new TTreeFormula(sformula.Data(), sformula.Data(), tree), nVars);
107  nVars++;
108  lastI = iChar + delta0 + 1;
109  }
110  TString stext(fquery(lastI, fquery.Length() - lastI));
111  fTextArray->AddAtAndExpand(new TObjString(stext.Data()), nVars);
112 }
113 
117 char *AliTreeFormulaF::PrintValue(Int_t mode) const {
118  PrintValue(mode, 0, "");
119 }
120 
130 char *AliTreeFormulaF::PrintValue(Int_t mode, Int_t instance, const char *decform) const {
131  std::stringstream stream;
132  Int_t nVars = fFormulaArray->GetEntries();
133  const char *format=NULL;
134  for (Int_t iVar = 0; iVar <= nVars; iVar++) {
135  stream << fTextArray->At(iVar)->GetName();
136  if (fDebug&2) cout<<"T"<<iVar<<"\t\t"<<fTextArray->At(iVar)->GetName()<<endl;
137  if (fDebug&4) cout<<"F"<<iVar<<"\t\t"<<stream.str().data()<<endl;
138  if (iVar < nVars) {
139  TTreeFormula *treeFormula = (TTreeFormula *) fFormulaArray->At(iVar);
140  Bool_t isHex=TString(fFormatArray->At(iVar)->GetName()).Contains("x") || TString(fFormatArray->At(iVar)->GetName()).Contains("X");
141  if (isHex) { // TODO check 64bits/32 bits
142  char buffer[64];
143  Int_t value=treeFormula->EvalInstance();
144  //sprintf(format,"%s",fFormatArray->At(iVar)->GetName());
145  sprintf(buffer,"%X",(Int_t)value);
146  stream<<buffer;
147  continue;
148  }
149  if ((fFormatArray->At(iVar)->GetName()[0]=='b')) { //TODO parse number of bits
150  Long64_t value=treeFormula->EvalInstance();
151  bitset<32> b(value);
152  stream<<b.to_string();
153  continue;
154  }
155  if ((fFormatArray->At(iVar)->GetName()[0]=='t')) { //TODO use formats
156  Long64_t value=treeFormula->EvalInstance64();
157  TTimeStamp stamp(value);
158  stream<<stamp.AsString("s");
159  continue;
160  }
161  TString value=treeFormula->PrintValue(0, instance, fFormatArray->At(iVar)->GetName());
162  stream << value.Data();
163  if (fDebug&&1) cout<<"F"<<iVar<<"\t\t"<<value.Data()<<"\t"<<fFormatArray->At(iVar)->GetName()<<endl;
164  }
165  }
166  //const_cast<AliTreeFormulaF*>(this)->fValue=TString(stream.str().data()); /// TODO check compliation of mutable in old c++
167  fValue=stream.str().data();
168  return (char *) fValue.Data();
169 }
172  if (fFormulaArray==NULL) return;
173  return;
174  Int_t nVars = fFormulaArray->GetEntries();
175  for (Int_t iVar = 0; iVar <= nVars; iVar++) {
176  TTreeFormula *treeFormula = (TTreeFormula *) fFormulaArray->At(iVar);
177  treeFormula->UpdateFormulaLeaves();
178  }
179 }
180 
184 AliTreePlayer::AliTreePlayer(const char *name, const char *title)
185  :TNamed(name, title)
186 {
187  //
188  //
189 }
190 
191 
192 
199 
210 TObjArray * AliTreePlayer::selectMetadata(TTree * tree, TString query, Int_t verbose, TString *idList){
211  /*
212  query - case sensitive matching is done using Contains method (e.g N(Axis)<=N(xis) )
213  - WILL be case insesitive
214  */
215  //
216  // 1. Parse query and map query to TFormula selection
217  //
218  TObjArray *queryArray=query.Tokenize("[=]");
219  TObjArray *varArray=0;
220  TVectorD vecParam;
221  TFormula *pFormula=0;
222  if (queryArray->GetEntries()>1) {
223  TString stringFormula="";
224  varArray = TString(queryArray->At(1)->GetName()).Tokenize("\"&|!()[]+-/"); //find variable list
225  vecParam.ResizeTo(varArray->GetEntriesFast());
226  stringFormula=queryArray->At(1)->GetName();
227  stringFormula.ReplaceAll("\"","");
228  for (Int_t ivar=0; ivar<varArray->GetEntriesFast(); ivar++){
229  stringFormula.ReplaceAll(varArray->At(ivar)->GetName(),TString::Format("x[%d]",ivar).Data()); // Logic should be improved - to match only "full strings"
230  vecParam[ivar]=1;
231  }
232  pFormula= new TFormula("printMetadataFromula",stringFormula.Data());
233  if (verbose&0x2) pFormula->Print();
234  }
235  //
236  if (queryArray->GetEntriesFast()<=0 ){
237  return 0;
238  }else{
239  if (queryArray->GetEntriesFast()>2) {
240  return 0;
241  }
242  }
243  //
244  // 2.) Find selected data and add the to the list
245  //
246  TObjArray * metaData = (TObjArray*)tree->GetUserInfo()->FindObject("metaTable");
247  Int_t entries = metaData->GetEntries();
248  TObjArray *selected = new TObjArray(entries);
249  for (Int_t ientry=0;ientry<entries; ientry++){
250  TString index=metaData->At(ientry)->GetName();
251  if (strstr(metaData->At(ientry)->GetName(),queryArray->At(0)->GetName())==NULL) continue;
252  Bool_t isSelected=kTRUE;
253  if (queryArray->GetEntriesFast()>1){
254  for (Int_t ipar=0; ipar< vecParam.GetNrows(); ipar++){
255  vecParam[ipar]=strstr(metaData->At(ientry)->GetTitle(),varArray->At(ipar)->GetName())!=NULL;
256  }
257  isSelected=pFormula->EvalPar(vecParam.GetMatrixArray());
258  if (verbose&0x2){
259  vecParam.GetMatrixArray();
260  }
261  }
262  if (isSelected){
263  selected->AddLast(metaData->At(ientry));
264  if (idList){
265  TString id=metaData->At(ientry)->GetName();
266  id.Remove(id.Last('.'),id.Length());
267  if (id.Length()>0) {
268  (*idList) += id;
269  (*idList) +=":";
270  }
271  }
272  if (verbose&0x1){
273  printf("%s:%s:%d\n",metaData->At(ientry)->GetName(),metaData->At(ientry)->GetTitle(),isSelected);
274  }
275  }
276  }
277  if (idList!=NULL){
278  delete selected;
279  return NULL;
280  }
281  return selected;
282 }
283 
284 
295 
310 TObjArray * AliTreePlayer::selectTreeInfo(TTree* tree, TString query,Int_t verbose){
311  // 1.) Make a TFormula replacing logical operands with values
312  TObjArray *queryArray=query.Tokenize("&|()!");
313  Int_t formulaEntries=queryArray->GetEntries();
314  for (Int_t i=0;i<formulaEntries; i++){
315  if (TString(queryArray->At(i)->GetName()).ReplaceAll(" ","").Length()<=0) queryArray->RemoveAt(i);
316  }
317  queryArray->Compress();
318  formulaEntries=queryArray->GetEntries();
319  if (formulaEntries<=0){
320  ::Error("selectTreeInfo","Empty or wrong selection %s", query.Data());
321  return 0;
322  }
323 
324  TString stringFormula=query;
325  TVectorD formValue(formulaEntries); // boolen or weight value
326  TVectorF formType(formulaEntries); // type of formula - name or metadata
327  TVectorF formExact(formulaEntries); // type of formula - exact or contain
328  TObjArray formMatch(formulaEntries); // string to match
329  TObjArray formMatchType(formulaEntries); // type to match
330  for (Int_t ivar=0; ivar<formulaEntries; ivar++){
331  TString formName=queryArray->At(ivar)->GetName();
332  stringFormula.ReplaceAll(queryArray->At(ivar)->GetName(),TString::Format("x[%d]",ivar).Data()); // Logic should be improved - to match only "full strings"
333  formName.ReplaceAll(" ","");
334  formName.ReplaceAll("\t","");
335  TObjArray *tokenArray=formName.Tokenize("[=:]");
336  if (tokenArray->GetEntries()<2){
337  ::Error("selectTreeInfo","Wrong subformula %s",formName.Data());
338  ::Error("selectTreeInfo","Full formula was %s",query.Data());
339  tokenArray->Print();
340  queryArray->Print();
341  delete tokenArray;
342  delete queryArray;
343  return 0;
344  }
345  formMatch[ivar]=tokenArray->At(1);
346  formMatchType[ivar]=tokenArray->At(0);
347  TString queryType(tokenArray->At(0)->GetName());
348  queryType.ToLower();
349  formType[ivar]=1;
350  if (queryType.Contains(".name",TString::kIgnoreCase)){
351  formType[ivar]=0;
352  }
353  if (formName.Contains(":")){
354  formExact[ivar]=0;
355  }else{
356  formExact[ivar]=1;
357  }
358  }
359  //
360  TFormula *pFormula= new TFormula("printMetadataFormula",stringFormula.Data());
361  if (verbose&0x4){
362  ::Info("selectTreeInfo","Formula:");
363  pFormula->Print();
364  ::Info("selectTreeInfo","Query array:");
365  queryArray->Print();
366  ::Info("selectTreeInfo","To match array:");
367  formMatch.Print();
368  ::Info("selectTreeInfo","Exact type:");
369  formExact.Print();
370  }
371  //
372  // 2.) array loop and evaluate filters
373  //
374  TObjArray *selected = new TObjArray(10000); // TODO: we should get upper limit estimate from
375  Int_t nTrees=1;
376  if (tree->GetListOfFriends()!=NULL) nTrees+=tree->GetListOfFriends()->GetEntries();
377  for (Int_t iTree=0; iTree<nTrees; iTree++){
378  TTree * cTree = tree;
379  if (iTree>0) cTree=tree->GetFriend(tree->GetListOfFriends()->At(iTree-1)->GetName());
380  if (cTree==NULL) continue;
381  for (Int_t itype=0; itype<2; itype++){
382  // TTree::GetListOfAliases() is a TList
383  // TTree::GetListOfBranches is a TObjArray
384  TSeqCollection* elemList=0;
385  if (itype==0) elemList=cTree->GetListOfBranches();
386  if (itype==1) elemList=cTree->GetListOfAliases();
387  if (elemList==NULL) continue;
388  Int_t elemEntries=elemList->GetEntries();
389  for (Int_t ientry=0; ientry<elemEntries; ientry++){ // to be rewritten to TSeqColection iterator
390  TString elemName(elemList->At(ientry)->GetName());
391  //
392  for (Int_t icheck=0; icheck<formulaEntries; icheck++){ // check logical expression
393  formValue[icheck]=0;
394  if (formType[icheck]==0){ // check the name
395  if (formExact[icheck]==1) formValue[icheck]=(elemName==formMatch.At(icheck)->GetName());
396  if (formExact[icheck]==0) formValue[icheck]=(strstr(elemName.Data(),formMatch.UncheckedAt(icheck)->GetName())!=NULL);
397  }
398  if (formType[icheck]==1){ // check corresponding metadata
399  TObject* metaObject = TStatToolkit::GetMetadata(cTree,TString::Format("%s%s",elemName.Data(), formMatchType.UncheckedAt(icheck)->GetName()).Data());
400  if (metaObject){
401  TString metaName(metaObject->GetTitle());
402  if (formExact[icheck]==1) formValue[icheck]=(metaName==formMatch.At(icheck)->GetName());
403  if (formExact[icheck]==0) formValue[icheck]=(strstr(metaName.Data(),formMatch.UncheckedAt(icheck)->GetName())!=NULL);
404  }
405  }
406  }
407  Bool_t isSelected=pFormula->EvalPar(formValue.GetMatrixArray());
408  if (isSelected){
409  if (iTree==0) selected->AddLast(new TObjString(elemList->At(ientry)->GetName()));
410  if (iTree>0) selected->AddLast(new TObjString(TString::Format("%s.%s",tree->GetListOfFriends()->At(iTree-1)->GetName(),elemList->At(ientry)->GetName())));
411  if (verbose&0x1) printf("%s\n",elemName.Data());
412  }
413  }
414  }
415  }
416  return selected;
417 }
418 
419 
427 TString AliTreePlayer::printSelectedTreeInfo(TTree *tree, TString infoType, TString regExpFriend, TString regExpTag,
428  Int_t verbose) {
429  /*
430  Example usage:
431  AliExternalInfo info;
432  TTree * treeTPC = info.GetTree("QA.TPC","LHC15o","cpass1_pass1","QA.TRD;QA.TPC;QA.TOC;QA.TOF;Logbook");
433 
434  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch alias","","MIP",1);
435  -- print infoType ="branches or alias" containing regExpTag == MIP in the master tree
436  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch","QA.TRD","Eff",1);
437  -- print infoType ="branches" containing regExpTag == Eff in the QA.TRD tree
438  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch",".*","run",1)
439  -- print infoType ="branches" containing regExpTag == Eff in the all friend trees
440  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch",".*","^run$",1)
441  -- print infoType ="branches" containing regExpTag == run in the all friend trees
442 
443  In case arrays or function should be selected - use aliases:
444  treeTPC->SetAlias("meanMIPvsSectorArray","meanMIPvsSector.fElements")'
445  treeTPC->SetAlias("runTypeName","runType.GetName()")
446  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch alias",".*","meanMIPvsSectorArray",1); ==> meanMIPvsSectorArray
447  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch alias ",".*","Name$",1) ==> runTypeName
448  */
449  TString result = "";
450  TList *treeFriends = tree->GetListOfFriends();
451  Int_t ntrees = 1 + ((treeFriends != NULL) ? treeFriends->GetEntries() : 0);
452  TPRegexp pregExpFriend = regExpFriend;
453  TPRegexp pregExpTag = regExpTag;
454  const char *dataTypes[3] = {"branch", "alias", "metaData"};
455  for (Int_t itree = 0; itree < ntrees; itree++) {
456  TTree *currentTree = 0;
457  if (itree == 0) {
458  currentTree = tree;
459  if (pregExpFriend.Match(currentTree->GetName()) == 0) continue;
460  } else {
461  if (pregExpFriend.Match(treeFriends->At(itree - 1)->GetName()) == 0) continue;
462  currentTree = ((TFriendElement * )(treeFriends->At(itree - 1)))->GetTree();
463  }
464 
465  if (verbose & 0x1) {
466  ::Info("printSelectedTreeInfo", "tree %s selected", currentTree->GetName());
467  }
468  for (Int_t iDataType = 0; iDataType < 3; iDataType++) {
469  if (infoType.Contains(dataTypes[iDataType], TString::kIgnoreCase) == 0) continue;
470  TList *selList = 0;
471  if (iDataType == 0) selList = (TList *) currentTree->GetListOfBranches();
472  if (iDataType == 1) selList = (TList *) currentTree->GetListOfAliases();
473  if (iDataType == 2 && tree->GetUserInfo())
474  selList = (TList * )(currentTree->GetUserInfo()->FindObject("metaTable"));
475 
476  if (selList == NULL) continue;
477  Int_t selListEntries = selList->GetEntries();
478  for (Int_t iEntry = 0; iEntry < selListEntries; iEntry++) {
479  if (pregExpTag.Match(selList->At(iEntry)->GetName()) <= 0) continue;
480  if (verbose & 0x1) {
481  ::Info(" printSelectedTreeInfo", "%s.%s", currentTree->GetName(), selList->At(iEntry)->GetName());
482  }
483  if (result.Length() > 0) result += ":";
484  if (itree > 0) {
485  result += treeFriends->At(itree - 1)->GetName();
486  result += ".";
487  }
488  result += selList->At(iEntry)->GetName();
489  }
490  }
491  }
492  return result;
493 }
494 
504 Int_t AliTreePlayer::selectWhatWhereOrderBy(TTree * tree, TString what, TString where, TString /*orderBy*/, Int_t firstentry, Int_t nentries, TString outputFormat, TString outputName){
505  //
506  // Select entry similar to the SQL select
507  // tree instead - SQL FROM statement used
508  // - it is supposed that all information is contained in the tree and related friend trees
509  // - build tree with friends done in separate function
510  // what -
511  // code inspired by the TTreePlay::Scan but another treatment of arrays needed
512  // but wih few changes realted to different output formatting
513  // NOTICE:
514  // for the moment not all parameters used
515  // Example usage:
516  /*
517  AliTreePlayer::selectWhatWhereOrderBy(treeTPC,"run:Logbook.run:meanMIP:meanMIPele:meanMIPvsSector.fElements:fitMIP.fElements","meanMIP>0", "", 0,10,"html","qatpc.html");
518  */
519 
520  if (tree==NULL || tree->GetPlayer()==NULL){
521  ::Error("AliTreePlayer::selectWhatWhereOrderBy","Input tree not defiend");
522  return -1;
523  }
524  // limit number of entries - shorter version of the TTreePlayer::GetEntriesToProcess - but not fully correct ()
525  if (firstentry +nentries >tree->GetEntriesFriend()) nentries=tree->GetEntriesFriend()-firstentry;
526  if (tree->GetEntryList()){ //
527  if (tree->GetEntryList()->GetN()<nentries) nentries=tree->GetEntryList()->GetN();
528  }
529  //
530  Int_t tnumber = -1;
531  Bool_t isHTML=outputFormat.Contains("html",TString::kIgnoreCase );
532  Bool_t isCSV=outputFormat.Contains("csv",TString::kIgnoreCase);
533  Bool_t isElastic=outputFormat.Contains("elastic",TString::kIgnoreCase);
534  Bool_t isJSON=outputFormat.Contains("json",TString::kIgnoreCase)||isElastic;
535 
536  //
537  FILE *default_fp = stdout;
538  if (outputName.Length()>0){
539  default_fp=fopen (outputName.Data(),"w");
540  }
541  TObjArray *fArray=what.Tokenize(":");
542  Int_t nCols=fArray->GetEntries();
543  TObjArray *fFormulaList = new TObjArray(nCols+1);
544  TTreeFormula ** rFormulaList = new TTreeFormula*[nCols+1];
545  TObjString **printFormatList = new TObjString*[nCols]; // how to format variables
546  TObjString **columnNameList = new TObjString*[nCols];
547  TObjString **outputFormatList = new TObjString*[nCols]; // root header formatting
548  Bool_t isIndex[nCols];
549  Bool_t isParent[nCols];
550  TClass* isClass[nCols]; // is object
551  TPRegexp indexPattern("^%I"); // pattern for index
552  TPRegexp parentPattern("^%P"); // pattern for parent index
553  for (Int_t iCol=0; iCol<nCols; iCol++){
554  isClass[iCol]=NULL;
555  rFormulaList[iCol]=NULL;
556  TObjArray * arrayDesc = TString(fArray->At(iCol)->GetName()).Tokenize(";");
557  if (arrayDesc->GetEntries()<=0) {
558  ::Error("AliTreePlayer::selectWhatWhereOrderBy","Invalid descriptor %s", arrayDesc->At(iCol)->GetName());
559  //return -1;
560  }
561  TString fieldName=arrayDesc->At(0)->GetName(); // variable content
562  if (tree->GetBranch(fieldName.Data())){
563  if (TString(tree->GetBranch(fieldName.Data())->GetClassName()).Length()>0) {
564  isClass[iCol]=TClass::GetClass(tree->GetBranch(fieldName.Data())->GetClassName());
565  }
566  }
567  if (fieldName.Contains(indexPattern)){ // variable is index
568  isIndex[iCol]=kTRUE;
569  indexPattern.Substitute(fieldName,"");
570  }else{
571  isIndex[iCol]=kFALSE;
572  }
573  if (fieldName.Contains(parentPattern)){ // variable is parent
574  isParent[iCol]=kTRUE;
575  parentPattern.Substitute(fieldName,"");
576  }else{
577  isParent[iCol]=kFALSE;
578  }
579  TTreeFormula * formula = NULL;
580  TNamed* htmlTag=TStatToolkit::GetMetadata(tree,(fieldName+".html").Data());
581  Bool_t isFormulaF= (fieldName[0]=='#') || htmlTag!=NULL;
582 
583  if (!isFormulaF) {
584  formula=new TTreeFormula(fieldName.Data(), fieldName.Data(), tree);
585  }else {
586  TString fstring = fieldName;
587  if (htmlTag) {
588  fstring=htmlTag->GetTitle();
589  } else {
590  fieldName.Replace(0, 1, "");
591  if (tree->GetAlias(fieldName.Data())) {
592  fstring = tree->GetAlias(fieldName.Data());
593  }
594  }
595  formula=new AliTreeFormulaF(fieldName.Data(), fstring.Data(), tree);
596  }
597 
598  if (formula->GetTree()==NULL){
599  ::Error("AliTreePlayer::selectWhatWhereOrderBy","Invalid formula %s, parsed from the original string %s",fieldName.Data(),what.Data());
600  if (isJSON==kFALSE) return -1;
601  }
602  TString printFormat=""; // printing format - column 1 - use default if not specified
603  TString colName=arrayDesc->At(0)->GetName(); // variable name in ouptut - column 2 - using defaut ("variable name") as in input
604  TString outputFormat=""; // output column format specification for TLeaf (see also reading using TTree::ReadFile)
605  if (arrayDesc->At(1)!=NULL){ // format
606  printFormat=arrayDesc->At(1)->GetName();
607  }else{
608  if (formula->IsInteger()) {
609  printFormat="1.20";
610  }else{
611  printFormat="1.20";
612  }
613  }
614  if (arrayDesc->At(2)!=NULL) {
615  colName=arrayDesc->At(2)->GetName();
616  }else{
617  colName=arrayDesc->At(0)->GetName();
618  }
619  //colName = (arrayDesc->GetEntries()>1) ? arrayDesc->At(2)->GetName() : arrayDesc->At(0)->GetName();
620  if (arrayDesc->At(3)!=NULL){ //outputFormat (for csv)
621  outputFormat= arrayDesc->At(3)->GetName();
622  }else{
623  outputFormat="/D";
624  if (formula->IsInteger()) outputFormat="/I";
625  if (formula->IsString()) outputFormat="/C";
626  }
627  fFormulaList->AddAt(formula,iCol);
628  rFormulaList[iCol]=formula;
629  printFormatList[iCol]=new TObjString(printFormat);
630  outputFormatList[iCol]=new TObjString(outputFormat);
631  columnNameList[iCol]=new TObjString(colName);
632  }
633  TTreeFormula *select = new TTreeFormula("Selection",where.Data(),tree);
634  fFormulaList->AddLast(select);
635  rFormulaList[nCols]=select;
636 
637 
638  Bool_t hasArray = kFALSE;
639  Bool_t forceDim = kFALSE;
640  for (Int_t iCol=0; iCol<nCols; iCol++){
641  if (rFormulaList[iCol]!=NULL) rFormulaList[iCol]->UpdateFormulaLeaves();
642  if (rFormulaList[iCol]->GetManager()==NULL) continue; // TODO - check of needed for AliTreeFormulaF
643  // if ->GetManager()->GetMultiplicity()>0 mean there is at minimum one array
644  switch( rFormulaList[iCol]->GetManager()->GetMultiplicity() ) {
645  case 1:
646  case 2:
647  hasArray = kTRUE;
648  forceDim = kTRUE;
649  break;
650  case -1:
651  forceDim = kTRUE;
652  break;
653  case 0:
654  break;
655  }
656  }
657 
658 
659  // print header
660  if (isHTML){
661  fprintf(default_fp,"<table class=\"display\" cellspacing=\"0\" width=\"100%\">\n"); // add metadata info
662  fprintf(default_fp,"\t<thead class=\"header\">\n"); // add metadata info
663  fprintf(default_fp,"\t<tr>\n"); // add metadata info
664  for (Int_t iCol=0; iCol<nCols; iCol++){
665  TNamed *tHeadName = TStatToolkit::GetMetadata(tree,TString(columnNameList[iCol]->GetName())+".thead");
666  TNamed *tooltipName = TStatToolkit::GetMetadata(tree,TString(columnNameList[iCol]->GetName())+".tooltip");
667  TString sthName=(tHeadName!=NULL) ? tHeadName->GetTitle() : columnNameList[iCol]->GetName();
668  TNamed *descriptionName = TStatToolkit::GetMetadata(tree,TString(columnNameList[iCol]->GetName())+".headerTooltip");
669  fprintf(default_fp, "\t\t<th");
670  if (tooltipName!=0) fprintf(default_fp, " class=\"tooltip\" data-tooltip=\"%s\"", tooltipName->GetTitle());
671  if (descriptionName!=0) fprintf(default_fp, " title=\"%s\"", descriptionName->GetTitle());
672  fprintf(default_fp, ">%s</th>\n", sthName.Data()); // add metadata info
673 // if (tooltipName==NULL){
674 // fprintf(default_fp, "\t\t<th>%s</th>\n", sthName.Data()); // add metadata info
675 // }else {
676 // fprintf(default_fp, "\t\t<th class=\"tooltip\" data-tooltip=\"%s\">%s</th>\n", tooltipName->GetTitle(), sthName.Data()); // add metadata info
677 // }
678  }
679  fprintf(default_fp,"\t</tr>\n"); // add metadata info
680  fprintf(default_fp,"\t</thead>\n"); // add metadata info
681  //
682  fprintf(default_fp,"\t<tfoot class=\"header\">\n"); // add metadata info
683  fprintf(default_fp,"\t<tr>\n"); // add metadata info
684  for (Int_t iCol=0; iCol<nCols; iCol++){
685  fprintf(default_fp,"\t\t<th>%s</th>\n",columnNameList[iCol]->GetName()); // add metadata info
686  }
687  fprintf(default_fp,"\t</tr>\n"); // add metadata info
688  fprintf(default_fp,"\t</tfoot>\n"); // add metadata info
689  fprintf(default_fp,"\t<tbody>\n"); // add metadata info
690  }
691  if (isCSV){
692  // add header info
693  for (Int_t iCol=0; iCol<nCols; iCol++){
694  fprintf(default_fp,"%s%s",columnNameList[iCol]->GetName(), outputFormatList[iCol]->GetName());
695  if (iCol<nCols-1) {
696  fprintf(default_fp,":");
697  }else{
698  fprintf(default_fp,"\n"); // add metadata info
699  }
700  }
701  }
702 
703  Int_t selected=0;
704  for (Int_t ientry=firstentry; ientry<firstentry+nentries; ientry++){
705  Int_t entryNumber = tree->GetEntryNumber(ientry);
706  if (entryNumber < 0) break;
707  Long64_t localEntry = tree->LoadTree(entryNumber);
708  //
709  if (tnumber != tree->GetTreeNumber()) {
710  tnumber = tree->GetTreeNumber();
711  for(Int_t iCol=0;iCol<nCols;iCol++) {
712  rFormulaList[iCol]->UpdateFormulaLeaves();
713  }
714  select->UpdateFormulaLeaves();
715  }
716  if (select) {
717  // if (select->EvalInstance(inst) == 0) {
718  if (select->EvalInstance(0) == 0) { // for the moment simplified version of selection - not treating "array" selection
719  continue;
720  }
721  }
722  selected++;
723  // if json out
724  if (isJSON){
725  if (selected>1){
726  if (isElastic) {
727  fprintf(default_fp,"}\n{\"index\":{\"_id\": \"");
728  }
729  else{
730  fprintf(default_fp,"},\n{\n");
731  }
732  }else{
733  if (isElastic){
734  fprintf(default_fp,"{\"index\":{\"_id\": \"");
735  }else{
736  fprintf(default_fp,"{{\n");
737  }
738  }
739  for (Int_t icol=0; icol<nCols; icol++){
740  TString obuffer="";
741  if (isClass[icol]){
742  const char*bname=rFormulaList[icol]->GetName();
743  TBranch *br = tree->GetBranch(bname);
744  br->GetEntry(entryNumber); // not sure if the entry is loaded
745  void **ppobject=(void**)br->GetAddress();
746  if (ppobject) {
747  obuffer = TBufferJSON::ConvertToJSON(*ppobject, isClass[icol]);
748  if (isElastic) obuffer.ReplaceAll("\n","");
749  //fprintf(default_fp,"%s",clbuffer.Data());
750  }
751  }
752  if (rFormulaList[icol]->GetTree()==NULL) continue;
753  Int_t nData=rFormulaList[icol]->GetNdata();
754  if (isElastic==kFALSE){
755  fprintf(default_fp,"\t\"%s\":",rFormulaList[icol]->GetName());
756  }else{
757  if (isIndex[icol]==kFALSE && isParent[icol]==kFALSE){
758  TString fieldName(rFormulaList[icol]->GetName());
759  if (isClass[icol]) fieldName.Remove(fieldName.Length()-1);
760  fieldName.ReplaceAll(".","%_");
761  if (icol>0 && isIndex[icol-1]==kFALSE && isParent[icol-1]==kFALSE ){
762  fprintf(default_fp,"\t,\"%s\":",fieldName.Data());
763  }else{
764  fprintf(default_fp,"\t\"%s\":",fieldName.Data());
765  }
766  }
767  }
768  if (nData<=1){
769  if ((isIndex[icol]==kFALSE)&&(isParent[icol]==kFALSE)){
770  if (isClass[icol]!=NULL){
771  fprintf(default_fp,"%s",obuffer.Data());
772  }else {
773  if (isElastic && rFormulaList[icol]->IsString()) {
774  fprintf(default_fp, "\t\"%s\"",
775  rFormulaList[icol]->PrintValue(0, 0, printFormatList[icol]->GetName()));
776  } else {
777  fprintf(default_fp, "\t%s",
778  rFormulaList[icol]->PrintValue(0, 0, printFormatList[icol]->GetName()));
779  }
780  }
781  }
782  if (isIndex[icol]){
783  fprintf(default_fp,"%s",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
784  if (isIndex[icol+1]){
785  fprintf(default_fp,".");
786  }else
787  if (isParent[icol+1]==kFALSE){
788  fprintf(default_fp,"\"}}\n{");
789  }
790  }
791  if (isParent[icol]==kTRUE){
792  fprintf(default_fp,"\", \"parent\": \"%s\"}}\n{",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
793  }
794  }else{
795  fprintf(default_fp,"\t[");
796  for (Int_t iData=0; iData<nData;iData++){
797  fprintf(default_fp,"%f",rFormulaList[icol]->EvalInstance(iData));
798  if (iData<nData-1) {
799  fprintf(default_fp,",");
800  } else{
801  fprintf(default_fp,"]");
802  }
803  }
804  }
805  // if (icol<nCols-1 && (isIndex[icol]==kFALSE && isParent[icol]==kFALSE) ) fprintf(default_fp,",");
806  //fprintf(default_fp,"\n");
807  }
808  }
809 
810  //
811  if (isHTML){
812  fprintf(default_fp,"<tr>\n");
813  for (Int_t icol=0; icol<nCols; icol++){
814  Int_t nData=rFormulaList[icol]->GetNdata();
815  if (nData<=1){
816  fprintf(default_fp,"\t<td>%s</td>",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
817  }else{
818  fprintf(default_fp,"\t<td>");
819  for (Int_t iData=0; iData<nData;iData++){
820  fprintf(default_fp,"%f",rFormulaList[icol]->EvalInstance(iData));
821  if (iData<nData-1) {
822  fprintf(default_fp,",");
823  }else{
824  fprintf(default_fp,"</td>");
825  }
826  }
827  }
828  fprintf(default_fp,"\n");
829  }
830  fprintf(default_fp,"</tr>\n");
831  }
832  //
833  if (isCSV){
834  for (Int_t icol=0; icol<nCols; icol++){ // formula loop
835  Int_t nData=rFormulaList[icol]->GetNdata();
836  if (nData<=1){
837  fprintf(default_fp,"%s\t",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
838  }else{
839  for (Int_t iData=0; iData<nData;iData++){ // array loo
840  fprintf(default_fp,"%f",rFormulaList[icol]->EvalInstance(iData));
841  if (iData<nData-1) {
842  fprintf(default_fp,",");
843  }else{
844  fprintf(default_fp,"\t");
845  }
846  }
847  }
848  }
849  fprintf(default_fp,"\n");
850  }
851  }
852  if (isJSON) fprintf(default_fp,"}\n");
853  if (isHTML){
854  fprintf(default_fp,"\t</tbody>"); // add metadata info
855  fprintf(default_fp,"</table>"); // add metadata info
856  }
857 
858  if (default_fp!=stdout) fclose (default_fp);
859  return selected;
860 }
861 
862 
866 Int_t AliTreePlayer::GetStatType(const TString &stat){
867 
868  if(!stat.CompareTo("median",TString::kIgnoreCase)){
869  return kMedian;
870  } else if(!stat.CompareTo("medianLeft",TString::kIgnoreCase)){
871  return kMedianLeft;
872  } else if(!stat.CompareTo("medianRight",TString::kIgnoreCase)){
873  return kMedianRight;
874  } else if(!stat.CompareTo("RMS",TString::kIgnoreCase)){
875  return kRMS;
876  } else if(!stat.CompareTo("Mean",TString::kIgnoreCase)){
877  return kMean;
878  }else if(!stat.CompareTo("Max",TString::kIgnoreCase)){
879  return kMax;
880  }else if(!stat.CompareTo("Min",TString::kIgnoreCase)){
881  return kMin;
882  } else if(stat.BeginsWith("LTMRMS",TString::kIgnoreCase)){ // Least trimmed RMS, argument is LTMRMS0.95 or similar
883  return kLTMRMS;
884  } else if(stat.BeginsWith("LTM",TString::kIgnoreCase)){ // Least trimmed mean, argument is LTM0.95 or similar
885  return kLTM;
886  } else {
887  ::Error("GetStatType()","Cannot decode string \"%s\"."
888  " Use one of \"median\", \"medianLeft\", \"medianRight\", \"RMS\", or \"Mean\". "
889  " Also supported is \"LTM\", or \"LTMRMS\", which should be succeeded by a float like"
890  " \"LTM0.95\" or an integer (interpreted as percentage) like \"LTMRMS95\" to specify "
891  " the fraction of data to be kept."
892  " Use a colon separated list like \"median:medianLeft:medianRight:RMS\""
893  " as the fifth argument to the AddStatInfo().",stat.Data());
894  return kUndef;
895  }
896 }
904 void AliTreePlayer::AddStatInfo(TTree* treeLeft, TTree * treeRight , const TString refQuery, Double_t deltaT,
905  const TString statString,
906  Int_t maxEntries){
907 
908  //
909  // 1.) Get variables from the right tree, sort them according to the coordinate
910  //
911  Int_t entries = treeRight->Draw(refQuery.Data(),"","goffpara",maxEntries);
912  if(entries<1){
913  ::Error("AddStatInfo","No matching entries for query");
914  return;
915  }else if (entries>treeRight->GetEstimate()){
916  treeRight->SetEstimate(entries*2);
917  entries = treeRight->Draw(refQuery.Data(),"","goffpara",maxEntries);
918  }
919  Int_t * indexArr = new Int_t[entries];
920  TMath::Sort(entries, treeRight->GetV1(), indexArr,kFALSE);
921  Double_t * coordArray = new Double_t[entries];
922  for (Int_t icoord=0; icoord<entries; icoord++) coordArray[icoord]=treeRight->GetV1()[indexArr[icoord]];
923  //
924  // 2.) Attach the median,.. of the variables to the left tree
925  //
926  // The first token is the coordinate
927  TString var;
928  Ssiz_t from=0;
929  if(!refQuery.Tokenize(var,from,":")){
930  ::Error("AddStatInfo","Cannot tokenize query \'%s\'. Use colon separated list"
931  ,refQuery.Data());
932  delete[]indexArr;indexArr=0;
933  delete[]coordArray;coordArray=0;
934  return;
935  }
936  Int_t entriesCoord = treeLeft->GetEntries();
937  TBranch * br = treeLeft->GetBranch(var.Data());
938  Int_t coordValue;
939  br->SetAddress(&coordValue);
940  //TLeaf *coordLeaf = (TLeaf*)(br->GetListOfLeaves()->At(0));
941 
942  while(refQuery.Tokenize(var,from,":")){
943  // var="valueAnodeRaw.fElements[0]";
944  TString stat;
945  Ssiz_t fromStat=0;
946  while(statString.Tokenize(stat,fromStat,":")){
947  // stat = "median"; stat="medianLeft"; stat="medianRight";
948  // Int_t statType=TStatToolkit::GetStatType(stat);
949  Int_t statType=GetStatType(stat);
950  if(statType==kUndef)continue;
951  //printf("\n\n\n--- StatType %d ---\n\n\n\n",statType);
952 
953  // In case of LMS or LMR determine the fraction
954  Float_t frac=0.;
955  if(statType==kLTM || statType==kLTMRMS){ // stat="LTM0.95" or "LTMRMS0.95" similar
956  TString tmp= stat;
957  tmp.ReplaceAll("LTMRMS","");
958  tmp.ReplaceAll("LTM","");
959  frac = tmp.Atof(); // atof returns 0.0 on error
960  if(frac>1)frac/=100.; // allows "LTM95" for 95%
961  }
962 
963  // Determine the offset in coordinate to the left and right
964  Double_t leftOffset=-1e99,rightOffset=-1e99;
965  if(statType==kMedian||statType==kRMS || statType==kMean
966  || statType==kLTM || statType==kLTMRMS || statType==kMin || statType==kMax ){ // symmetric
967  leftOffset=-deltaT;rightOffset=deltaT;
968  } else if(statType==kMedianLeft){ //left
969  leftOffset=-2.*deltaT;rightOffset=0.;
970  } else if(statType==kMedianRight){ //right
971  leftOffset=0.;rightOffset=2.*deltaT;
972  }
973 
974  TString brName=Form("%s_%s",var.Data(),stat.Data());
975  brName.ReplaceAll("[","_");
976  brName.ReplaceAll("]","_");
977  brName.ReplaceAll(".","_");
978  Double_t statValue=0;
979  if (treeLeft->GetDirectory()) treeLeft->GetDirectory()->cd();
980  TBranch *brToFill = treeLeft->Branch(brName.Data(),&statValue, (brName+"/D").Data());
981  TVectorD dvalues(entries);
982 
983  for (Int_t icoord=0; icoord<entriesCoord; icoord++){
984  // Int_t icoord=0
985  br->GetEntry(icoord);
986  Double_t startCoord=coordValue+leftOffset;
987  Double_t endCoord =coordValue+rightOffset;
988  //Double_t startCoord=coordLeaf->GetValue()+leftOffset;
989  //Double_t endCoord =coordLeaf->GetValue()+rightOffset;
990 
991  // Binary search finds last element smaller or equal
992  Int_t index0=BinarySearchSmaller(entries, coordArray, startCoord)+1;
993  Int_t index1=TMath::BinarySearch(entries, coordArray, endCoord) +1;
994  statValue=0;
995  if (index1>=0 && index0>=0){
996  //if (values.capacity()<index1-index0) values.reserve(1.5*(index1-index0)); //resize of needed
997  if (index1-index0<=0){
998  index0--;
999  index1++;
1000  if (index0<0) index0=0;
1001  if (index1>=entries) index1=entries-1;
1002  }
1003  for (Int_t i=0; i<index1-index0; i++){
1004  dvalues[i]=treeRight->GetV2()[indexArr[i+index0]];
1005  }
1006  // Calculate
1007  if(statType==kMedian||statType==kMedianLeft||statType==kMedianRight){
1008  statValue=TMath::Median(index1-index0, dvalues.GetMatrixArray());
1009  } else if(statType==kRMS){
1010  statValue=TMath::RMS(index1-index0, dvalues.GetMatrixArray());
1011  } else if(statType==kMean){
1012  statValue=TMath::Mean(index1-index0, dvalues.GetMatrixArray());
1013  }else if(statType==kMin){
1014  statValue=TMath::MinElement(index1-index0, dvalues.GetMatrixArray());
1015  }else if(statType==kMax){
1016  statValue=TMath::MaxElement(index1-index0, dvalues.GetMatrixArray());
1017  } else if(statType==kLTM){
1018  TVectorD params(7);
1019  try {
1020  TStatToolkit::LTMUnbinned(index1 - index0, dvalues.GetMatrixArray(), params, frac);
1021  }
1022  catch (int e)
1023  {
1024  cout << "TStatToolkit::LTMUnbinned. Catch Exception Nr. " << e << '\n';
1025  continue;
1026  }
1027  statValue = params[1];
1028  } else if(statType==kLTMRMS){
1029  TVectorD params(7);
1030  try {
1031  TStatToolkit::LTMUnbinned(index1 - index0, dvalues.GetMatrixArray(), params, frac);
1032  }
1033  catch (int e)
1034  {
1035  cout << "TStatToolkit::LTMUnbinned. Catch Exception Nr. " << e << '\n';
1036  continue;
1037  }
1038  statValue = params[2];
1039  } else{
1040  ::Error("AddStatInfo()","String %s StatType %d not implemented",stat.Data(),statType);
1041  }
1042  }
1043  brToFill->Fill();
1044  } // Loop over coordinates
1045  brToFill->FlushBaskets();
1046  } // Loop over stat types
1047  } // Loop over variables
1048  treeLeft->Write();
1049  delete[]indexArr;indexArr=0;
1050  delete[]coordArray;coordArray=0;
1051 
1052 }
1053 
1054 
1077 
1087 
1113 TObjArray * AliTreePlayer::MakeHistograms(TTree * tree, TString hisString, TString defaultCut, Int_t firstEntry, Int_t lastEntry, Int_t chunkSize, Int_t verbose){
1114  // Algorithm:
1115  // 1.) Analyze formula, create minimal formula expression
1116  // 2.) Event loop
1117  // 3.) Filling of histograms
1118  //
1119 
1120  const Int_t kMaxDim=10;
1121  Int_t entriesAll=tree->GetEntriesFast();
1122  if (chunkSize<=0) chunkSize=entriesAll;
1123  if (lastEntry>entriesAll) lastEntry=entriesAll;
1124  //
1125  TObjArray *hisDescriptionList=hisString.Tokenize(";");
1126  Int_t nHistograms = hisDescriptionList->GetEntries();
1127  TObjArray * hisArray = new TObjArray(nHistograms);
1128  TObjArray * hisDescriptionArray=new TObjArray(nHistograms); // OWNER
1129  TObjArray * hisFormulaArray=new TObjArray(nHistograms); // array of TFomula arrays - Not OWNER
1130  TObjArray * hisWeightArray=new TObjArray(nHistograms); // array of TFomula arrays - Not OWNER
1131  TArrayI hisDims(nHistograms);
1132  //
1133  Int_t nExpressions=hisString.CountChar(':')+hisString.CountChar(';')+1;
1134  TObjArray * formulaArray = new TObjArray(nExpressions); // array of all expressions - OWNER
1135  TString queryString = "";
1136  Int_t hisSizeFull=0;
1137  //
1138  // 1.) Analyze formula, book list of TObjString
1139  //
1140  Bool_t isOK=kTRUE;
1141  for (Int_t iHis=0; iHis<nHistograms; iHis++){
1142  TString hisDescription = hisDescriptionList->At(iHis)->GetName();
1143  Int_t hisIndex=hisDescription.Index(">>");
1144  if (hisIndex<=0) {
1145  isOK=kFALSE;
1146  ::Error("AliTreePlayer::MakeHistograms","Invalid expression %s",hisDescription.Data());
1147  break;
1148  }else{
1149  hisDescriptionArray->AddAtAndExpand(new TObjString(((hisDescriptionList->At(iHis)->GetName()))+(hisIndex+2)),iHis);
1150  }
1151  hisDescription.Remove(hisIndex);
1152  TObjArray *hisDimArray=hisDescription.Tokenize(":");
1153  Int_t nDims=hisDimArray->GetEntries();
1154  if (nDims<=0){
1155  isOK=kFALSE;
1156  ::Error("AliTreePlayer::MakeHistograms","Invalid description %s",hisDescription.Data());
1157  delete hisDimArray;
1158  break;
1159  }
1160  TObjArray * varArray = new TObjArray(nDims);
1161  if (hisDimArray->At(nDims-1)->GetName()[0]=='#'){
1162  TString formulaName=&((hisDimArray->At(nDims-1)->GetName())[1]);
1163  nDims-=1;
1164  TObjString *tFormula = new TObjString(formulaName.Data());
1165  hisWeightArray->AddAt(tFormula,iHis);
1166  if (formulaArray->FindObject(formulaName.Data())==NULL){
1167  formulaArray->AddLast(tFormula);
1168  varArray->AddAt(tFormula,nDims);
1169  }
1170  }
1171  for (Int_t iDim=0; iDim<nDims;iDim++){
1172  TObjString *tFormula = (TObjString*) (formulaArray->FindObject(hisDimArray->At(iDim)->GetName()));
1173  if (tFormula==NULL){
1174  tFormula = new TObjString(hisDimArray->At(iDim)->GetName());
1175  formulaArray->AddLast(tFormula);
1176  }
1177  varArray->AddAt(tFormula,iDim);
1178  }
1179  hisFormulaArray->AddAt(varArray,iHis);
1180  hisDims[iHis]=nDims;
1181  delete hisDimArray;
1182  }
1183  queryString="";
1184  Int_t nFormulas=formulaArray->GetEntries();
1185  for (Int_t iFor=0; iFor<nFormulas; iFor++){
1186  queryString+=formulaArray->At(iFor)->GetName();
1187  queryString+=":";
1188  }
1189  queryString+=formulaArray->At(nFormulas-1)->GetName();
1190  if (verbose&0x2) hisDescriptionArray->Print();
1191  if (verbose&0x4) formulaArray->Print();
1192  //
1193  // 2.) Event loop
1194  //
1195  Int_t tNumber=-1;
1196  for (Int_t bEntry=firstEntry; bEntry<lastEntry; bEntry+=chunkSize){ // chunks loop
1197  AliSysInfo::AddStamp(TString::Format("Begin.%s",tree->GetName()).Data(),0, bEntry);
1198  Int_t toQuery=TMath::Min(chunkSize, lastEntry-bEntry);
1199  Int_t qLength = tree->Draw(queryString,defaultCut,"goffpara",toQuery, bEntry); // query varaibles
1200  if (qLength>tree->GetEstimate()){
1201  tree->SetEstimate(qLength*1.5);
1202  qLength = tree->Draw(queryString,defaultCut,"goffpara",chunkSize, bEntry);
1203  }
1204 
1205  // 2.2 fill histograms if not yet done
1206  if (hisArray->GetEntriesFast()==0){ // book histograms if not yet done
1207  for (Int_t iHis=0; iHis<nHistograms; iHis++){
1208  if (hisDescriptionArray->At(iHis)==NULL){
1209  ::Error("AliTreePlayer::MakeHistograms", "Empty description %d",iHis);
1210  continue;
1211  }
1212  TString hisDescription= hisDescriptionArray->At(iHis)->GetName();
1213  TString varDecription=hisDescriptionList->At(iHis)->GetName();
1214  TObjArray * descriptionArray=hisDescription.Tokenize("(,)");
1215  TObjArray * varArray= TString(hisDescriptionList->At(iHis)->GetName()).Tokenize(":");
1216  Int_t nLength=descriptionArray->GetEntries();
1217  if ((nLength-1)/3 < hisDims[iHis]){
1218  ::Error("AliTreePlayer::MakeHistograms", "Histogram dimension Mismatch %s", hisDescriptionArray->At(iHis)->GetName());
1219  return NULL;
1220  }
1221  if (varArray->GetEntries()<hisDims[iHis]){
1222  ::Error("AliTreePlayer::MakeHistograms", "Variable mismatch %s", hisDescriptionArray->At(iHis)->GetName());
1223  return NULL;
1224  }
1225  TString hName(descriptionArray->At(0)->GetName());
1226  THnBase * his = 0;
1227  Int_t nBins[kMaxDim];
1228  Double_t xMin[kMaxDim], xMax[kMaxDim];
1229  for (Int_t iDim=0; iDim<hisDims[iHis]; iDim++){
1230  nBins[iDim]= TString(descriptionArray->At(3*iDim+1)->GetName()).Atoi();
1231  if (descriptionArray->At(3*iDim+2)->GetName()[0]!='%'){
1232  xMin[iDim]= TString(descriptionArray->At(3*iDim+2)->GetName()).Atof();
1233  }else{
1234  if (descriptionArray->At(3*iDim+2)->GetName()[1]=='A'){ // %A - alias describing range
1235  TTreeFormula falias("falias",&(descriptionArray->At(3*iDim+2)->GetName()[2]),tree);
1236  xMin[iDim]=falias.EvalInstance();
1237  }
1238  }
1239  if (descriptionArray->At(3*iDim+3)->GetName()[0]!='%'){
1240  xMax[iDim]= TString(descriptionArray->At(3*iDim+3)->GetName()).Atof();
1241  }else{
1242  if (descriptionArray->At(3*iDim+3)->GetName()[1]=='A'){ // %A - alias describing range
1243  TTreeFormula falias("falias",&(descriptionArray->At(3*iDim+3)->GetName()[2]),tree);
1244  xMax[iDim]=falias.EvalInstance();
1245  }
1246  }
1247  if (xMax[iDim]<=xMin[iDim]){
1248  ::Error("AliTreePlayer::MakeHistograms","Invalid hstogram range specification for histogram %s: %s\t%s",hisDescription.Data(), \
1249  descriptionArray->At(3*iDim+2)->GetName(), descriptionArray->At(3*iDim+3)->GetName() );
1250  }
1251  }
1252  THnF * phis = new THnF(hName.Data(),hName.Data(), hisDims[iHis],nBins, xMin,xMax);
1253  hisArray->AddAt(phis,iHis);
1254  AliSysInfo::AddStamp(hName.Data(),10, phis->GetNbins());
1255  if (verbose&0x1) {
1256  ::Info("AliTreePlayer::MakeHistograms","%s: size=%lld",hisDescription.Data(), phis->GetNbins());
1257  }
1258  hisSizeFull+= phis->GetNbins();
1259  for (Int_t iDim=0;iDim<hisDims[iHis]; iDim++){
1260  phis->GetAxis(iDim)->SetName(varArray->At(iDim)->GetName());
1261  phis->GetAxis(iDim)->SetTitle(varArray->At(iDim)->GetName());
1262  TNamed *axisTitle=TStatToolkit::GetMetadata(tree,TString::Format("%s.AxisTitle",varArray->At(iDim)->GetName()).Data());
1263  if (axisTitle) phis->GetAxis(iDim)->SetTitle(axisTitle->GetTitle());
1264  }
1265  }
1266  if (verbose&0x1) {
1267  ::Info("AliTreePlayer::MakeHistograms","Total size=%d",hisSizeFull);
1268  }
1269  }
1270  // 2.3 fill histograms
1271  if (tree->GetVal(0)==NULL){
1272  ::Error(" AliTreePlayer::MakeHistograms","Info not available"); // TODO - fix the logic
1273  continue;
1274  }
1275  Double_t values[kMaxDim];
1276  for (Int_t iHis=0; iHis<nHistograms; iHis++){
1277  Int_t indeces[kMaxDim+1];
1278  TObjArray *formulaArrayHis = (TObjArray*) (hisFormulaArray->At(iHis));
1279  for (Int_t iVec=0; iVec<formulaArrayHis->GetEntriesFast(); iVec++){
1280  indeces[iVec]= formulaArray->IndexOf(formulaArray->FindObject(formulaArrayHis->At(iVec)->GetName()));
1281  }
1282  Int_t indexW=-1;
1283  if (hisWeightArray->GetEntriesFast()>=iHis){
1284  if (hisWeightArray->UncheckedAt(iHis)!=NULL){
1285  if (hisWeightArray->UncheckedAt(iHis)->GetName()){
1286  indexW= formulaArray->IndexOf(formulaArray->FindObject(hisWeightArray->UncheckedAt(iHis)->GetName()));
1287  }else{
1288  ::Error("xxx","Problem to find %s", hisWeightArray->UncheckedAt(iHis)->GetName());
1289  }
1290  }
1291  }
1292  THnBase * his = (THnBase*) hisArray->UncheckedAt(iHis);
1293  for (Int_t cEvent=0; cEvent<qLength; cEvent++){
1294  for (Int_t iDim=0; iDim<hisDims[iHis]; iDim++){
1295  if (tree->GetVal(indeces[iDim])==NULL){
1296  ::Error(" AliTreePlayer::MakeHistograms","Info %d not avaliable",iDim); // TODO - fix the logic
1297  continue;
1298  }
1299  values[iDim]=tree->GetVal(indeces[iDim])[cEvent];
1300  }
1301  Double_t weight=(indexW<0)? 1: tree->GetVal(indexW)[cEvent];
1302  if (weight>0) his->Fill(values,weight);
1303  }
1304  }
1305  AliSysInfo::AddStamp(TString::Format("End.%s",tree->GetName()).Data(),0, bEntry);
1306  }
1307  //
1308  delete hisDescriptionArray;
1309  delete formulaArray;
1310  return hisArray;
1311 
1312 }
1313 
1314 
1315 
1316 
1317 TPad * AliTreePlayer::DrawHistograms(TPad * pad, TObjArray * hisArray, TString drawExpression, TObjArray *keepArray, Int_t verbose){
1318  //
1319  //
1320  // Example usage:
1321  /*
1322  TPad *pad= 0; TString drawExpression="";
1323  drawExpression="[1,1,1]:"
1324  drawExpression+="hisPtAll(0,10)(0)(errpl);hisPtITS(0,10)(0)(err);hisPtPhiThetaAll(0,10,-3.2,3.2,-1.2,1.2)(0)(err):";
1325  drawExpression+="hisAlpha(-3.2,3.2)(0)(errpl);hisPtPhiThetaAll(0,10,-3.2,3.2,-1.2,1.2)(1)(err):";
1326  drawExpression+="hisTgl(-1,1)(0)(errpl);hisPtPhiThetaAll(0,10,-3.2,3.2,-1.2,1.2)(2)(err):";
1327  pad = AliTreePlayer::DrawHistograms(0,hisArray,drawExpression);
1328  */
1329  TString projType[8]={"f-mean","f-rms","f-ltm","f-ltmsigma","f-gmean","f-grms","f-median","f-gmean"};
1330 
1331  TObjArray *drawList=drawExpression.Tokenize(":");
1332  // structure pad
1333  TString padDescription=drawList->At(0)->GetName();
1334  if (pad==NULL){
1335  static Int_t counter=0;
1336  pad = new TCanvas(TString::Format("canvasCounter%d",counter).Data(), drawExpression,1000,800);
1337  counter++;
1338  }
1339  // divide pads
1340  Int_t nPads=0, nRows=0;
1341  TObjArray *padRows=padDescription.Tokenize("[](),");
1342  nRows=padRows->GetEntries();
1343  for (Int_t iRow=0; iRow<nRows; iRow++){
1344  Int_t nCols=TString(padRows->At(iRow)->GetName()).Atoi();
1345  for (Int_t iCol=0; iCol<nCols; iCol++){
1346  pad->cd();
1347  TPad * newPad=new TPad(Form("pad%d",nPads),Form("pad%d",nPads),iCol/Double_t(nCols),(nRows-iRow-1)/Double_t(nRows),(iCol+1)/Double_t(nCols),(nRows-iRow)/Double_t(nRows));
1348  newPad->Draw();
1349  nPads++;
1350  newPad->SetNumber(nPads);
1351  }
1352  }
1353  delete padRows;
1354  //
1355  //
1356  TPRegexp isPadOption("^%O");
1357  Bool_t isLogY=kFALSE;
1358  for (Int_t iPad=0; iPad<nPads; iPad++){
1359  Int_t nGraphs=0, nHistos=0;
1360  if (drawList->At(iPad+1)==NULL) break;
1361  //TVirtualPad *cPad =
1362  TVirtualPad *cPad = pad->cd(iPad+1);
1363  TLegend * legend = new TLegend(cPad->GetLeftMargin()+0.02,0.7,1-cPad->GetRightMargin()-0.02 ,1-cPad->GetTopMargin()-0.02, TString::Format("Pad%d",iPad));
1364  legend->SetNColumns(2);
1365  legend->SetBorderSize(0);
1366  TString padSetup=drawList->At(iPad+1)->GetName();
1367  TString padOption="";
1368  Bool_t isTimeX=kFALSE, isTimeY=kFALSE;
1369 
1370  if (padSetup.Contains(isPadOption)){
1371  padOption=TString(&padSetup[2]);
1372  padOption.Remove(padOption.First(";"));
1373  padOption.ToLower();
1374  if (padOption.Contains("logy")) {
1375  pad->cd(iPad+1)->SetLogy();
1376  isLogY=kTRUE;
1377  }
1378  if (padOption.Contains("logx")) {
1379  pad->cd(iPad+1)->SetLogx();
1380  }
1381  if (padOption.Contains("gridy")) pad->cd(iPad+1)->SetGridy();
1382  if (padOption.Contains("gridx")) pad->cd(iPad+1)->SetGridx();
1383  if (padOption.Contains("timex")) isTimeX=kTRUE;
1384  if (padOption.Contains("timey")) isTimeY=kTRUE;
1385  padSetup.Remove(0,padSetup.First(';')+1);
1386  }
1387 
1388  TObjArray * padDrawList= padSetup.Tokenize(";");
1389  Double_t hisMin=0, hisMax=-1;
1390  TH1 * hisToDraw=0;
1391  TGraphErrors * grToDraw=0;
1392  //
1393  for (Int_t ihis=0; ihis<padDrawList->GetEntries(); ihis++){
1394  TObjArray *hisDescription= TString(padDrawList->At(ihis)->GetName()).Tokenize("()");
1395  THn * his = (THn*)hisArray->FindObject(hisDescription->At(0)->GetName());
1396  if (his==NULL) continue;
1397  if (verbose&0x4){
1398  ::Info("AliTreePlayer::DrawHistograms","Pad %d. Processing his %s",iPad, hisDescription->At(0)->GetName());
1399  }
1400  Int_t ndim=his->GetNdimensions();
1401  TString rangeDescription(hisDescription->At(1)->GetName());
1402  Int_t ndimRange= (rangeDescription.CountChar(','));
1403  if (ndimRange>0) ndimRange=ndimRange/2+1;
1404  if (ndimRange>0){
1405  TObjArray *rangeArray=rangeDescription.Tokenize(",");
1406  for (Int_t iDim=0; iDim<ndimRange; iDim++){
1407  if (rangeArray->At(iDim*2)->GetName()[0]=='U') {
1408  Double_t min=TString(&(rangeArray->At(iDim*2)->GetName()[1])).Atof();
1409  Double_t max=TString(&(rangeArray->At(iDim*2+1)->GetName()[1])).Atof();
1410  if (verbose&0x8){
1411  ::Info("AliTreePlayer::DrawHistograms","Pad %d. %s.GetAxis(%d).SetRangeUser(%f,%f).",iPad,hisDescription->At(0)->GetName(), iDim, min,max);
1412  }
1413  his->GetAxis(iDim)->SetRangeUser(min,max);
1414  }else{
1415  Int_t min=TString((rangeArray->At(iDim*2)->GetName())).Atoi();
1416  Int_t max=TString((rangeArray->At(iDim*2+1)->GetName())).Atoi();
1417  if (verbose&0x8){
1418  ::Info("AliTreePlayer::DrawHistograms","Pad %d. %s.GetAxis(%d).SetRange(%d,%d).",iPad,hisDescription->At(0)->GetName(), iDim, min,max);
1419  }
1420  his->GetAxis(iDim)->SetRange(min,max);
1421  }
1422  }
1423  delete rangeArray;
1424  }
1425  TString drawOption = hisDescription->At(3)->GetName();
1426  drawOption.ToLower();
1427  TString projString=hisDescription->At(2)->GetName();
1428  Int_t nDims = projString.CountChar(',')+1;
1429  TH1 * hProj =0;
1430  TGraphErrors*gr=0;
1431  //
1432  if (nDims==1) {
1433  hProj=his->Projection(projString.Atoi());
1434  //hProj->SetName(Form("Pad%d_His%d",iPad,nHistos)); //
1435  nHistos++;
1436  }
1437  if (nDims==2) {
1438  Int_t dim0 = projString.Atoi();
1439  Int_t dim1 = TString(&(projString[2])).Atoi();
1440  TH2* his2D =his->Projection(dim0,dim1);
1441  for (Int_t iProj=0; iProj<8; iProj++){
1442  if (drawOption.Contains(projType[iProj])){
1443  gr=TStatToolkit::MakeStat1D(his2D,0,1.0,iProj,21+ihis,ihis+1);
1444  //gr->SetName(Form("gr_Pad%d_Graph%d",iPad,nGraphs)); //
1445  nGraphs++;
1446  // gr->SetTitle(Form("gr_Pad%d_Graph%d",iPad,nGraphs)); //
1447  gr->SetTitle(padDrawList->At(ihis)->GetName());
1448  gr->GetXaxis()->SetTitle(his2D->GetXaxis()->GetTitle());
1449  gr->GetYaxis()->SetTitle(his2D->GetYaxis()->GetTitle());
1450  drawOption.ReplaceAll(projType[iProj].Data(),"");
1451  }
1452  }
1453  delete his2D;
1454  }
1455  if (gr){
1456  Double_t grMinI=TMath::MinElement(gr->GetN(),gr->GetY())-3.*TMath::Median(gr->GetN(),gr->GetEY());
1457  Double_t grMaxI=TMath::MaxElement(gr->GetN(),gr->GetY())+3.*TMath::Median(gr->GetN(),gr->GetEY());
1458  if (hisMax<hisMin) {hisMin=grMinI; hisMax=grMaxI;}
1459  if (hisMax<grMaxI) hisMax=grMaxI;
1460  if (hisMin>grMinI) hisMin=grMinI;
1461  if (ihis==0) {
1462  grToDraw = gr;
1463  gr->Draw((drawOption+"a").Data());
1464  legend->AddEntry(gr,"","p");
1465  }
1466  else{
1467  gr->Draw(drawOption.Data());
1468  legend->AddEntry(gr,"", "p");
1469  }
1470  if (keepArray) keepArray->AddLast(gr);
1471  }
1472  if (hProj){
1473  hProj->SetMarkerColor(ihis+1);
1474  hProj->SetLineColor(ihis+1);
1475  hProj->SetMarkerStyle(21+ihis);
1476  if (keepArray) keepArray->AddLast(hProj);
1477  //
1478  if (hisMax<hisMin) {
1479  hisMin=hProj->GetMinimum();
1480  hisMax=hProj->GetMaximum();
1481  }
1482  if (hisMax<hProj->GetMaximum()) hisMax=hProj->GetMaximum();
1483  if (hisMin>hProj->GetMinimum()) hisMin=hProj->GetMinimum();
1484  if (ihis==0) {
1485  hisToDraw = hProj;
1486  hProj->Draw((TString(hisDescription->At(3)->GetName())+"").Data());
1487  legend->AddEntry(hProj);
1488  }
1489  else{
1490  hProj->Draw((TString(hisDescription->At(3)->GetName())+"same").Data());
1491  legend->AddEntry(hProj);
1492  }
1493  }
1494  }
1495  pad->cd(iPad+1);
1496  if (hisToDraw!=NULL){
1497  hisToDraw->SetMaximum(hisMax+(hisMax-hisMin)/2.);
1498  if (hisMin<=0) hisMin=TMath::Min(0.01, hisMax*0.01);
1499  hisToDraw->SetMinimum(hisMin);
1500  if (isLogY){
1501  hisToDraw->SetMaximum(hisMax*TMath::Max(10.,(hisMax/hisMin)/4.));
1502  }
1503 
1504  if ((verbose&0x8)>0){
1505  ::Info("AliTreePlayer::DrawHistograms:","Pad %d. %s SetMinimum(%f). SetMaximum(%f)",iPad,padDrawList->At(0)->GetName(), hisMin,hisMax+(hisMax-hisMin)/2.);
1506  }
1507  if (isTimeX) hisToDraw->GetXaxis()->SetTimeDisplay(1);
1508  if (isTimeY) hisToDraw->GetYaxis()->SetTimeDisplay(1);
1509  pad->cd(iPad+1)->Modified();
1510  pad->cd(iPad+1)->Update();
1511  legend->Draw("same");
1512  }
1513  if (grToDraw!=NULL){
1514  grToDraw->SetMaximum(hisMax+(hisMax-hisMin)/2.);
1515  grToDraw->SetMinimum(hisMin-(hisMax-hisMin)/3.);
1516  if (isTimeX) grToDraw->GetXaxis()->SetTimeDisplay(1);
1517  if (isTimeY) grToDraw->GetYaxis()->SetTimeDisplay(1);
1518 
1519  if ((verbose&0x8)>0){
1520  ::Info("AliTreePlayer::DrawHistograms:","Pad %d. %s SetMinimum(%f). SetMaximum(%f)",iPad,padDrawList->At(0)->GetName(), hisMax+(hisMax-hisMin)/2.,hisMin-(hisMax-hisMin)/3.);
1521  }
1522 
1523  pad->cd(iPad+1)->Modified();
1524  pad->cd(iPad+1)->Update();
1525  legend->Draw("same");
1526  }
1527  pad->cd(iPad+1);
1528  }
1529  return pad;
1530 
1531 }
1532 
1533 
1534 
1535 void AliTreePlayer::MakeCacheTree(TTree * tree, TString varList, TString outFile, TString outTree, TCut selection){
1536  //
1537  // Fill tree with information specified in varList of TTreeFormulas
1538  // In case input tree is "flat" - not array output tree can be used as a friend ....
1539  // Input:
1540  // tree - TTree with input
1541  // varList - list of TTreeFormulas
1542  // selection - tree selection
1543  // Output: tree
1544  // outFile - output file name
1545  // outTree - output tree name
1546  TTreeSRedirector *pcstream = new TTreeSRedirector(outFile,"recreate");
1547  if (tree->GetEstimate()<tree->GetEntries()) tree->SetEstimate(tree->GetEntries());
1548  Int_t entries=tree->Draw(varList.Data(),selection,"goffpara");
1549  TObjArray * varName=varList.Tokenize(":");
1550  const Int_t nVars=varName->GetEntries();
1551  Double_t vars[nVars];
1552  TTree *treeOut=NULL;
1553  for (Int_t iPoint=0; iPoint <entries; iPoint++){
1554  for (Int_t iVar=0; iVar<nVars; iVar++){
1555  vars[iVar]=tree->GetVal(iVar)[iPoint];
1556  if (iPoint==0) (*pcstream)<<outTree.Data()<<TString::Format("%s=",varName->At(iVar)->GetName()).Data()<<vars[iVar];
1557  }
1558  if (iPoint==0) {
1559  (*pcstream)<<outTree.Data()<<"\n";
1560  treeOut=((*pcstream)<<outTree.Data()).GetTree();
1561  }else{
1562  treeOut->Fill();
1563  }
1564  }
1565  delete pcstream;
1566 }
1567 
1568 
1569 
1570 
1571 
Int_t fDebug
current cache value of the formula
Definition: AliTreePlayer.h:89
static TString printSelectedTreeInfo(TTree *tree, TString infoType, TString regExpFriend, TString regExpTag, Int_t verbose)
TBrowser b
Definition: RunAnaESD.C:12
TNamed * GetMetadata(TTree *tree, const char *vartagName, TString *prefix=0, Bool_t fullMatch=kFALSE)
printf("Chi2/npoints = %f\n", TMath::Sqrt(chi2/npoints))
static TPad * DrawHistograms(TPad *pad, TObjArray *hisArray, TString drawExpression, TObjArray *keepArray=0, Int_t verbose=0)
TObjArray * fFormulaArray
array of format strings to draw
Definition: AliTreePlayer.h:87
#define TObjArray
static TObjArray * selectTreeInfo(TTree *tree, TString query, Int_t verbose)
static Int_t GetStatType(const TString &stat)
TObjArray * fFormatArray
array of text inputs
Definition: AliTreePlayer.h:86
TTreeSRedirector * pcstream
strP3 Tokenize("+") -> Print()
TObjArray * hisArray
virtual char * PrintValue(Int_t mode=0) const
virtual Int_t Compile(const char *expression="")
Helper class for AliTreePlayer - formatted string to query tree Example usageExample: Construct direc...
Definition: AliTreePlayer.h:74
TTree * tree
TStatToolkit stat
Definition: AnalyzeLaser.C:5
Set of functions to extend functionality of the TTreePlayer.
Definition: AliTreePlayer.h:94
static TObjArray * selectMetadata(TTree *tree, TString query, Int_t verbose, TString *idList=NULL)
TGraph * gr
Definition: CalibTime.C:25
static TObjArray * MakeHistograms(TTree *tree, TString hisString, TString defaultCut, Int_t firstEntry, Int_t lastEntry, Int_t chunkSize=-1, Int_t verbose=1)
TGraphErrors * MakeStat1D(TH2 *his, Int_t deltaBin, Double_t fraction, Int_t returnType, Int_t markerStyle, Int_t markerColor)
AliTreeFormulaF()
Default constructor.
static Long64_t BinarySearchSmaller(Long64_t n, const T *array, T value)
static Int_t selectWhatWhereOrderBy(TTree *tree, TString what, TString where, TString orderBy, Int_t firstentry, Int_t nentries, TString outputFormat, TString outputName)
static void AddStatInfo(TTree *treeLeft, TTree *treeRight, const TString refQuery, Double_t deltaT, const TString statString="median:medianLeft:medianRight:RMS:Mean:LTM0.60:LTMRMS0.60:Max:Min", Int_t maxEntries=100000000)
TObjArray * fTextArray
Definition: AliTreePlayer.h:85
Int_t nBins
TString fValue
array of TFormulas
Definition: AliTreePlayer.h:88
virtual void UpdateFormulaLeaves()
static void AddStamp(const char *sname, Int_t id0=-1, Int_t id1=-1, Int_t id2=-1, Int_t id3=-1)
Definition: AliSysInfo.cxx:179
class TVectorT< Double_t > TVectorD
Int_t * LTMUnbinned(int np, const T *arr, TVectorT< T > &params, Float_t keep=1.0)
Definition: TStatToolkit.h:626
TTree * GetTree(Int_t ievent)
Int_t debug
static void MakeCacheTree(TTree *tree, TString varList, TString outFile, TString outTree, TCut selection)