AliRoot Core  837871f (837871f)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  Set of functions to extend functionality of the TTreePlayer
19  data source (tree+friend trees) configured independently in AliExternalInfo
20 
21  Functionality:
22  * function to support metadata and collumns annotation
23  * filtering function (branch, aliases metadata)
24  * select function - export to (json, csv, html, JIRA) + metadata (not yet implemented)
25  ** subset of metadata for columns included in select export outputName.metadata
26  * select function - for root trees
27  ** to be done using TTree::CopyTree functionality swithing ON/OFF selected branches - metadata should be exported automatically (to check)
28 
29  See example usage in the test macro AliTreePlayerTest.C
30  * AliTreePlayerTest.C::testAll();
31  * AliTreePlayerTest.C::testSelectMetadata()
32  * AliTreePlayerTest.C::testselectTreeInfo()
33  * AliTreePlayerTest.C:testselectWhatWhereOrderByForTRD()
34 
35 */
36 
37 #include "TStatToolkit.h"
38 #include "Riostream.h"
39 #include <iostream>
40 #include "TSystem.h"
41 #include "TNamed.h"
42 #include "TFile.h"
43 #include "TTree.h"
44 #include "TPRegexp.h"
45 #include "TFriendElement.h"
46 #include "AliExternalInfo.h"
47 #include "TTreeFormula.h"
48 #include "TTreeFormulaManager.h"
49 #include "AliTreePlayer.h"
50 #include "TEntryList.h"
51 #include "THn.h"
52 #include "TLegend.h"
53 #include "AliSysInfo.h"
54 
56 
57 //_____________________________________________________________________________
58 AliTreePlayer::AliTreePlayer(const char *name, const char *title)
59  :TNamed(name, title)
60 {
61  //
62  //
63 }
64 
65 //_____________________________________________________________________________
66 
67 
68 
73 
74 
75 TObjArray * AliTreePlayer::selectMetadata(TTree * tree, TString query, Int_t verbose){
76  /*
77  query - case sensitive matching is done using Contains method (e.g N(Axis)<=N(xis) )
78  - WILL be case insesitive
79 
80  Example usage:
81  query="[AxisTitle]"; // only metadata with metadata axis existing
82  query="[class]"; // only metadata with metadata class existing
83  query="[class==\"Base&&Log&&Stat\"]"; // metadata class contains
84  //
85  AliTreePlayer::selectMetadata(treeLogbook, "[class==\"Logbook&&(Stat||Base)\"]",0)->Print();
86  AliTreePlayer::selectMetadata(testTree, "[Axis==\"counts\"]",0)->Print();
87  */
88  //
89  // 1. Parse query and map query to TFormula selection
90  //
91  TObjArray *queryArray=query.Tokenize("[=]");
92  TObjArray *varArray=0;
93  TVectorD vecParam;
94  TFormula *pFormula=0;
95  if (queryArray->GetEntries()>1) {
96  TString stringFormula="";
97  varArray = TString(queryArray->At(1)->GetName()).Tokenize("\"&|!()[]+-/"); //find variable list
98  vecParam.ResizeTo(varArray->GetEntriesFast());
99  stringFormula=queryArray->At(1)->GetName();
100  stringFormula.ReplaceAll("\"","");
101  for (Int_t ivar=0; ivar<varArray->GetEntriesFast(); ivar++){
102  stringFormula.ReplaceAll(varArray->At(ivar)->GetName(),TString::Format("x[%d]",ivar).Data()); // Logic should be improved - to match only "full strings"
103  vecParam[ivar]=1;
104  }
105  pFormula= new TFormula("printMetadataFromula",stringFormula.Data());
106  if (verbose&0x2) pFormula->Print();
107  }
108  //
109  if (queryArray->GetEntriesFast()<=0 ){
110  return 0;
111  }else{
112  if (queryArray->GetEntriesFast()>2) {
113  return 0;
114  }
115  }
116  //
117  // 2.) Find selected data and add the to the list
118  //
119  TObjArray * metaData = (TObjArray*)tree->GetUserInfo()->FindObject("metaTable");
120  Int_t entries = metaData->GetEntries();
121  TObjArray *selected = new TObjArray(entries);
122  for (Int_t ientry=0;ientry<entries; ientry++){
123  TString index=metaData->At(ientry)->GetName();
124  if (strstr(metaData->At(ientry)->GetName(),queryArray->At(0)->GetName())==NULL) continue;
125  Bool_t isSelected=kTRUE;
126  if (queryArray->GetEntriesFast()>1){
127  for (Int_t ipar=0; ipar< vecParam.GetNrows(); ipar++){
128  vecParam[ipar]=strstr(metaData->At(ientry)->GetTitle(),varArray->At(ipar)->GetName())!=NULL;
129  }
130  isSelected=pFormula->EvalPar(vecParam.GetMatrixArray());
131  if (verbose&0x2){
132  vecParam.GetMatrixArray();
133  }
134  }
135  if (isSelected){
136  selected->AddLast(metaData->At(ientry));
137  if (verbose&0x1){
138  printf("%s:%s:%d\n",metaData->At(ientry)->GetName(),metaData->At(ientry)->GetTitle(),isSelected);
139  }
140  }
141  }
142  return selected;
143 }
144 
145 TObjArray * AliTreePlayer::selectTreeInfo(TTree* tree, TString query,Int_t verbose){
146  /*
147  Find all branches containing "Data string" and having class base
148  search follow only branches - doesn not enter into classes
149  - WILL be not case sensitive (should be part of unit test)
150  == - for exact match
151  : - for contain
152  Implemented using TFormula interpeter:
153  TString query="([.name==Data])&&([.class==base]||[.class==Data])";
154  ==>
155  TFormula (x[0])&&(x[1]||x[2])
156 
157  Example cases :
158  AliTreePlayer::selectTreeInfo(treeTPC, "([.name:mean] && [.name:MIP])",0)->Print();
159  AliTreePlayer:: selectTreeInfo(treeLogbook, "([.name:ata] && [.AxisTitle:size])",0)->Print();
160  In case of problems unit test in separate file
161  -- AliTreePlayerTest.C::testselectTreeInfo()
162  //
163 
164 
165  */
166  // 1.) Make a TFormula replacing logical operands with values
167  TObjArray *queryArray=query.Tokenize("&|()!");
168  Int_t formulaEntries=queryArray->GetEntries();
169  for (Int_t i=0;i<formulaEntries; i++){
170  if (TString(queryArray->At(i)->GetName()).ReplaceAll(" ","").Length()<=0) queryArray->RemoveAt(i);
171  }
172  queryArray->Compress();
173  formulaEntries=queryArray->GetEntries();
174  if (formulaEntries<=0){
175  ::Error("selectTreeInfo","Empty or wrong selection %s", query.Data());
176  return 0;
177  }
178 
179 
180  TString stringFormula=query;
181  TVectorD formValue(formulaEntries); // boolen or weight value
182  TVectorF formType(formulaEntries); // type of formula - name or metadata
183  TVectorF formExact(formulaEntries); // type of formula - exact or contain
184  TObjArray formMatch(formulaEntries); // string to match
185  TObjArray formMatchType(formulaEntries); // type to match
186  for (Int_t ivar=0; ivar<formulaEntries; ivar++){
187  TString formName=queryArray->At(ivar)->GetName();
188  stringFormula.ReplaceAll(queryArray->At(ivar)->GetName(),TString::Format("x[%d]",ivar).Data()); // Logic should be improved - to match only "full strings"
189  formName.ReplaceAll(" ","");
190  formName.ReplaceAll("\t","");
191  TObjArray *tokenArray=formName.Tokenize("[=:]");
192  if (tokenArray->GetEntries()<2){
193  ::Error("selectTreeInfo","Wrong subformula %s",formName.Data());
194  ::Error("selectTreeInfo","Full formula was %s",query.Data());
195  tokenArray->Print();
196  queryArray->Print();
197  delete tokenArray;
198  delete queryArray;
199  return 0;
200  }
201  formMatch[ivar]=tokenArray->At(1);
202  formMatchType[ivar]=tokenArray->At(0);
203  TString queryType(tokenArray->At(0)->GetName());
204  queryType.ToLower();
205  formType[ivar]=1;
206  if (queryType.Contains(".name",TString::kIgnoreCase)){
207  formType[ivar]=0;
208  }
209  if (formName.Contains(":")){
210  formExact[ivar]=0;
211  }else{
212  formExact[ivar]=1;
213  }
214  }
215  //
216  TFormula *pFormula= new TFormula("printMetadataFormula",stringFormula.Data());
217  if (verbose&0x4){
218  ::Info("selectTreeInfo","Formula:");
219  pFormula->Print();
220  ::Info("selectTreeInfo","Query array:");
221  queryArray->Print();
222  ::Info("selectTreeInfo","To match array:");
223  formMatch.Print();
224  ::Info("selectTreeInfo","Exact type:");
225  formExact.Print();
226  }
227  //
228  // 2.) array loop and evaluate filters
229  //
230  TObjArray *selected = new TObjArray(10000); // TODO: we should get upper limit estimate from
231  Int_t nTrees=1;
232  if (tree->GetListOfFriends()!=NULL) nTrees+=tree->GetListOfFriends()->GetEntries();
233  for (Int_t iTree=0; iTree<nTrees; iTree++){
234  TTree * cTree = tree;
235  if (iTree>0) cTree=tree->GetFriend(tree->GetListOfFriends()->At(iTree-1)->GetName());
236  if (cTree==NULL) continue;
237  for (Int_t itype=0; itype<2; itype++){
238  // TTree::GetListOfAliases() is a TList
239  // TTree::GetListOfBranches is a TObjArray
240  TSeqCollection* elemList=0;
241  if (itype==0) elemList=cTree->GetListOfBranches();
242  if (itype==1) elemList=cTree->GetListOfAliases();
243  if (elemList==NULL) continue;
244  Int_t elemEntries=elemList->GetEntries();
245  for (Int_t ientry=0; ientry<elemEntries; ientry++){ // to be rewritten to TSeqColection iterator
246  TString elemName(elemList->At(ientry)->GetName());
247  //
248  for (Int_t icheck=0; icheck<formulaEntries; icheck++){ // check logical expression
249  formValue[icheck]=0;
250  if (formType[icheck]==0){ // check the name
251  if (formExact[icheck]==1) formValue[icheck]=(elemName==formMatch.At(icheck)->GetName());
252  if (formExact[icheck]==0) formValue[icheck]=(strstr(elemName.Data(),formMatch.UncheckedAt(icheck)->GetName())!=NULL);
253  }
254  if (formType[icheck]==1){ // check corresponding metadata
255  TObject* metaObject = TStatToolkit::GetMetadata(cTree,TString::Format("%s%s",elemName.Data(), formMatchType.UncheckedAt(icheck)->GetName()).Data());
256  if (metaObject){
257  TString metaName(metaObject->GetTitle());
258  if (formExact[icheck]==1) formValue[icheck]=(metaName==formMatch.At(icheck)->GetName());
259  if (formExact[icheck]==0) formValue[icheck]=(strstr(metaName.Data(),formMatch.UncheckedAt(icheck)->GetName())!=NULL);
260  }
261  }
262  }
263  Bool_t isSelected=pFormula->EvalPar(formValue.GetMatrixArray());
264  if (isSelected){
265  if (iTree==0) selected->AddLast(new TObjString(elemList->At(ientry)->GetName()));
266  if (iTree>0) selected->AddLast(new TObjString(TString::Format("%s.%s",tree->GetListOfFriends()->At(iTree-1)->GetName(),elemList->At(ientry)->GetName())));
267  if (verbose&0x1) printf("%s\n",elemName.Data());
268  }
269  }
270  }
271  }
272  return selected;
273 }
274 
275 
276 
277 
278 TString AliTreePlayer::printSelectedTreeInfo(TTree*tree, TString infoType, TString regExpFriend, TString regExpTag, Int_t verbose){
279  //
280  //
281  //
282  // tree - input master tree pointer
283  // infoType - array in which information is queried - "branch" "alias" "metaData" and logical or
284  // regExpFriend - regeular expression patter, where to seek (default empty - master tree)
285  // regExpTag - regula expression tag to be queried - use non case sensitive Contain ( use as ^regExpTag$ to get full match )
286  //
287  /*
288  Example usage:
289  AliExternalInfo info;
290  TTree * treeTPC = info.GetTree("QA.TPC","LHC15o","cpass1_pass1","QA.TRD;QA.TPC;QA.TOC;QA.TOF;Logbook");
291 
292  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch alias","","MIP",1);
293  -- print infoType ="branches or alias" containing regExpTag == MIP in the master tree
294  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch","QA.TRD","Eff",1);
295  -- print infoType ="branches" containing regExpTag == Eff in the QA.TRD tree
296  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch",".*","run",1)
297  -- print infoType ="branches" containing regExpTag == Eff in the all friend trees
298  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch",".*","^run$",1)
299  -- print infoType ="branches" containing regExpTag == run in the all friend trees
300 
301  In case arrays or function should be selected - use aliases:
302  treeTPC->SetAlias("meanMIPvsSectorArray","meanMIPvsSector.fElements")'
303  treeTPC->SetAlias("runTypeName","runType.GetName()")
304  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch alias",".*","meanMIPvsSectorArray",1); ==> meanMIPvsSectorArray
305  AliTreePlayer::printSelectedTreeInfo(treeTPC,"branch alias ",".*","Name$",1) ==> runTypeName
306  */
307  TString result="";
308  TList * treeFriends = tree->GetListOfFriends();
309  Int_t ntrees = 1+( (treeFriends!=NULL)?treeFriends->GetEntries():0 );
310  TPRegexp pregExpFriend=regExpFriend;
311  TPRegexp pregExpTag=regExpTag;
312  const char* dataTypes[3]={"branch","alias", "metaData"};
313  for (Int_t itree=0; itree<ntrees; itree++){
314  TTree * currentTree = 0;
315  if (itree==0){
316  currentTree=tree;
317  if (pregExpFriend.Match(currentTree->GetName())==0) continue;
318  }else{
319  if (pregExpFriend.Match(treeFriends->At(itree-1)->GetName())==0) continue;
320  currentTree = ((TFriendElement*)(treeFriends->At(itree-1)))->GetTree();
321  }
322 
323  if (verbose&0x1){
324  ::Info("printSelectedTreeInfo","tree %s selected", currentTree->GetName());
325  }
326  for (Int_t iDataType=0; iDataType<3; iDataType++){
327  if (infoType.Contains(dataTypes[iDataType], TString::kIgnoreCase)==0) continue;
328  TList * selList = 0;
329  if (iDataType==0) selList=(TList*)currentTree->GetListOfBranches();
330  if (iDataType==1) selList=(TList*)currentTree->GetListOfAliases();
331  if (iDataType==2 && tree->GetUserInfo()) selList=(TList*)(currentTree->GetUserInfo()->FindObject("metaTable"));
332 
333  if (selList==NULL) continue;
334  Int_t selListEntries=selList->GetEntries();
335  for (Int_t iEntry=0; iEntry<selListEntries; iEntry++){
336  if (pregExpTag.Match(selList->At(iEntry)->GetName())<=0) continue;
337  if (verbose&0x1){
338  ::Info(" printSelectedTreeInfo","%s.%s", currentTree->GetName(),selList->At(iEntry)->GetName());
339  }
340  if (result.Length()>0) result+=":";
341  if (itree>0) {
342  result+=treeFriends->At(itree-1)->GetName();
343  result+=".";
344  }
345  result+=selList->At(iEntry)->GetName();
346  }
347  }
348  }
349  return result;
350 }
351 
352 
353 Int_t AliTreePlayer::selectWhatWhereOrderBy(TTree * tree, TString what, TString where, TString /*orderBy*/, Int_t firstentry, Int_t nentries, TString outputFormat, TString outputName){
354  //
355  // Select entry similar to the SQL select
356  // tree instead - SQL FROM statement used
357  // - it is supposed that all infomtation is contained in the tree and related friend trees
358  // - build tree with friends done in separate function
359  // what -
360  // code inspired by the TTreePlay::Scan but another tretment of arrays needed
361  // but wih few changes realted to different output formating
362  // NOTICE:
363  // for the moment not all parameters used
364  // Example usage:
365  /*
366  AliTreePlayer::selectWhatWhereOrderBy(treeTPC,"run:Logbook.run:meanMIP:meanMIPele:meanMIPvsSector.fElements:fitMIP.fElements","meanMIP>0", "", 0,10,"html","qatpc.html");
367 
368  */
369  if (tree==NULL || tree->GetPlayer()==NULL){
370  ::Error("AliTreePlayer::selectWhatWhereOrderBy","Input tree not defiend");
371  return -1;
372  }
373  // limit number of entries - shorter version of the TTreePlayer::GetEntriesToProcess - but not fully correct ()
374  if (firstentry +nentries >tree->GetEntriesFriend()) nentries=tree->GetEntriesFriend()-firstentry;
375  if (tree->GetEntryList()){ //
376  if (tree->GetEntryList()->GetN()<nentries) nentries=tree->GetEntryList()->GetN();
377  }
378  //
379  Int_t tnumber = -1;
380  Bool_t isHTML=outputFormat.Contains("html",TString::kIgnoreCase );
381  Bool_t isCSV=outputFormat.Contains("csv",TString::kIgnoreCase);
382  Bool_t isElastic=outputFormat.Contains("elastic",TString::kIgnoreCase);
383  Bool_t isJSON=outputFormat.Contains("json",TString::kIgnoreCase)||isElastic;
384 
385  //
386  FILE *default_fp = stdout;
387  if (outputName.Length()>0){
388  default_fp=fopen (outputName.Data(),"w");
389  }
390  TObjArray *fArray=what.Tokenize(":");
391  Int_t nCols=fArray->GetEntries();
392  TObjArray *fFormulaList = new TObjArray(nCols+1);
393  TTreeFormula ** rFormulaList = new TTreeFormula*[nCols+1];
394  TObjString **printFormatList = new TObjString*[nCols]; // how to format variables
395  TObjString **columnNameList = new TObjString*[nCols];
396  TObjString **outputFormatList = new TObjString*[nCols]; // root header formatting
397  Bool_t isIndex[nCols];
398  Bool_t isParent[nCols];
399  TPRegexp indexPattern("^%I"); // pattern for index
400  TPRegexp parentPattern("^%P"); // pattern for parent index
401  for (Int_t iCol=0; iCol<nCols; iCol++){
402  TObjArray * arrayDesc = TString(fArray->At(iCol)->GetName()).Tokenize(";");
403  if (arrayDesc->GetEntries()<=0) {
404  ::Error("AliTreePlayer::selectWhatWhereOrderBy","Invalid descriptor %s", arrayDesc->At(iCol)->GetName());
405  //return -1;
406  }
407  TString fieldName=arrayDesc->At(0)->GetName(); // variable content
408  if (fieldName.Contains(indexPattern)){ // variable is index
409  isIndex[iCol]=kTRUE;
410  indexPattern.Substitute(fieldName,"");
411  }else{
412  isIndex[iCol]=kFALSE;
413  }
414  if (fieldName.Contains(parentPattern)){ // variable is parent
415  isParent[iCol]=kTRUE;
416  parentPattern.Substitute(fieldName,"");
417  }else{
418  isParent[iCol]=kFALSE;
419  }
420 
421  TTreeFormula * formula = new TTreeFormula(fieldName.Data(), fieldName.Data(), tree);
422  if (formula->GetTree()==NULL){
423  ::Error("AliTreePlayer::selectWhatWhereOrderBy","Invalid formula %s, parsed from the original string %s",fieldName.Data(),what.Data());
424  if (isJSON==kFALSE) return -1;
425  }
426  TString printFormat=""; // printing format - column 1 - use default if not specified
427  TString colName=arrayDesc->At(0)->GetName(); // variable name in ouptut - column 2 - using defaut ("variable name") as in input
428  TString outputFormat=""; // output column format specification for TLeaf (see also reading using TTree::ReadFile)
429 
430  if (arrayDesc->At(1)!=NULL){ // format
431  printFormat=arrayDesc->At(1)->GetName();
432  }else{
433  if (formula->IsInteger()) {
434  printFormat="1.20";
435  }else{
436  printFormat="1.20";
437  }
438  }
439  if (arrayDesc->At(2)!=NULL) {
440  colName=arrayDesc->At(2)->GetName();
441  }else{
442  colName=arrayDesc->At(0)->GetName();
443  }
444  //colName = (arrayDesc->GetEntries()>1) ? arrayDesc->At(2)->GetName() : arrayDesc->At(0)->GetName();
445  if (arrayDesc->At(3)!=NULL){ //outputFormat (for csv)
446  outputFormat= arrayDesc->At(3)->GetName();
447  }else{
448  outputFormat="/D";
449  if (formula->IsInteger()) outputFormat="/I";
450  if (formula->IsString()) outputFormat="/C";
451  }
452  fFormulaList->AddLast(formula);
453  rFormulaList[iCol]=formula;
454  printFormatList[iCol]=new TObjString(printFormat);
455  outputFormatList[iCol]=new TObjString(outputFormat);
456  columnNameList[iCol]=new TObjString(colName);
457  }
458  TTreeFormula *select = new TTreeFormula("Selection",where.Data(),tree);
459  fFormulaList->AddLast(select);
460  rFormulaList[nCols]=select;
461 
462 
463  Bool_t hasArray = kFALSE;
464  Bool_t forceDim = kFALSE;
465  for (Int_t iCol=0; iCol<nCols; iCol++){
466  rFormulaList[iCol]->UpdateFormulaLeaves();
467  // if ->GetManager()->GetMultiplicity()>0 mean there is at minimum one array
468  switch( rFormulaList[iCol]->GetManager()->GetMultiplicity() ) {
469  case 1:
470  case 2:
471  hasArray = kTRUE;
472  forceDim = kTRUE;
473  break;
474  case -1:
475  forceDim = kTRUE;
476  break;
477  case 0:
478  break;
479  }
480  }
481 
482 
483  // print header
484  if (isHTML){
485  fprintf(default_fp,"<table>"); // add metadata info
486  fprintf(default_fp,"<tr>"); // add metadata info
487  for (Int_t iCol=0; iCol<nCols; iCol++){
488  fprintf(default_fp,"<th>%s</th>",columnNameList[iCol]->GetName()); // add metadata info
489  }
490  fprintf(default_fp,"<tr>"); // add metadata info
491  }
492  if (isCSV){
493  // add header info
494  for (Int_t iCol=0; iCol<nCols; iCol++){
495  fprintf(default_fp,"%s%s",columnNameList[iCol]->GetName(), outputFormatList[iCol]->GetName());
496  if (iCol<nCols-1) {
497  fprintf(default_fp,":");
498  }else{
499  fprintf(default_fp,"\n"); // add metadata info
500  }
501  }
502  }
503 
504  Int_t selected=0;
505  for (Int_t ientry=firstentry; ientry<firstentry+nentries; ientry++){
506  Int_t entryNumber = tree->GetEntryNumber(ientry);
507  if (entryNumber < 0) break;
508  Long64_t localEntry = tree->LoadTree(entryNumber);
509  //
510  if (tnumber != tree->GetTreeNumber()) {
511  tnumber = tree->GetTreeNumber();
512  for(Int_t iCol=0;iCol<nCols;iCol++) {
513  rFormulaList[iCol]->UpdateFormulaLeaves();
514  }
515  select->UpdateFormulaLeaves();
516  }
517  if (select) {
518  // if (select->EvalInstance(inst) == 0) {
519  if (select->EvalInstance(0) == 0) { // for the moment simplified version of selection - not treating "array" selection
520  continue;
521  }
522  }
523  selected++;
524  // if json out
525  if (isJSON){
526  if (selected>1){
527  if (isElastic) {
528  fprintf(default_fp,"}\n{\"index\":{\"_id\": \"");
529  }
530  else{
531  fprintf(default_fp,"},\n{\n");
532  }
533  }else{
534  if (isElastic){
535  fprintf(default_fp,"{\"index\":{\"_id\": \"");
536  }else{
537  fprintf(default_fp,"{{\n");
538  }
539  }
540  for (Int_t icol=0; icol<nCols; icol++){
541  if (rFormulaList[icol]->GetTree()==NULL) continue;
542  Int_t nData=rFormulaList[icol]->GetNdata();
543  if (isElastic==kFALSE){
544  fprintf(default_fp,"\t\"%s\":",rFormulaList[icol]->GetName());
545  }else{
546  if (isIndex[icol]==kFALSE && isParent[icol]==kFALSE){
547  TString fieldName(rFormulaList[icol]->GetName());
548  fieldName.ReplaceAll(".","%_");
549  if (icol>0 && isIndex[icol-1]==kFALSE && isParent[icol-1]==kFALSE ){
550  fprintf(default_fp,"\t,\"%s\":",fieldName.Data());
551  }else{
552  fprintf(default_fp,"\t\"%s\":",fieldName.Data());
553  }
554  }
555  }
556  if (nData<=1){
557  if ((isIndex[icol]==kFALSE)&&(isParent[icol]==kFALSE)){
558  if (isElastic && rFormulaList[icol]->IsString()){
559  fprintf(default_fp,"\t\"%s\"",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
560  }else{
561  fprintf(default_fp,"\t%s",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
562  }
563  }
564  if (isIndex[icol]){
565  fprintf(default_fp,"%s",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
566  if (isIndex[icol+1]){
567  fprintf(default_fp,".");
568  }else
569  if (isParent[icol+1]==kFALSE){
570  fprintf(default_fp,"\"}}\n{");
571  }
572  }
573  if (isParent[icol]==kTRUE){
574  fprintf(default_fp,"\", \"parent\": \"%s\"}}\n{",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
575  }
576  }else{
577  fprintf(default_fp,"\t[");
578  for (Int_t iData=0; iData<nData;iData++){
579  fprintf(default_fp,"%f",rFormulaList[icol]->EvalInstance(iData));
580  if (iData<nData-1) {
581  fprintf(default_fp,",");
582  } else{
583  fprintf(default_fp,"]");
584  }
585  }
586  }
587  // if (icol<nCols-1 && (isIndex[icol]==kFALSE && isParent[icol]==kFALSE) ) fprintf(default_fp,",");
588  //fprintf(default_fp,"\n");
589  }
590  }
591 
592  //
593  if (isHTML){
594  fprintf(default_fp,"<tr>\n");
595  for (Int_t icol=0; icol<nCols; icol++){
596  Int_t nData=rFormulaList[icol]->GetNdata();
597  if (nData<=1){
598  fprintf(default_fp,"\t<td>%s</td>",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
599  }else{
600  fprintf(default_fp,"\t<td>");
601  for (Int_t iData=0; iData<nData;iData++){
602  fprintf(default_fp,"%f",rFormulaList[icol]->EvalInstance(iData));
603  if (iData<nData-1) {
604  fprintf(default_fp,",");
605  }else{
606  fprintf(default_fp,"</td>");
607  }
608  }
609  }
610  fprintf(default_fp,"\n");
611  }
612  fprintf(default_fp,"</tr>\n");
613  }
614  //
615  if (isCSV){
616  for (Int_t icol=0; icol<nCols; icol++){ // formula loop
617  Int_t nData=rFormulaList[icol]->GetNdata();
618  if (nData<=1){
619  fprintf(default_fp,"%s\t",rFormulaList[icol]->PrintValue(0,0,printFormatList[icol]->GetName()));
620  }else{
621  for (Int_t iData=0; iData<nData;iData++){ // array loo
622  fprintf(default_fp,"%f",rFormulaList[icol]->EvalInstance(iData));
623  if (iData<nData-1) {
624  fprintf(default_fp,",");
625  }else{
626  fprintf(default_fp,"\t");
627  }
628  }
629  }
630  }
631  fprintf(default_fp,"\n");
632  }
633  }
634  if (isJSON) fprintf(default_fp,"}\n");
635  if (isHTML){
636  fprintf(default_fp,"</table>"); // add metadata info
637  }
638 
639  if (default_fp!=stdout) fclose (default_fp);
640  return selected;
641 }
642 
643 
644 
645 
646 
647 
648 
649 
650 
651 
652 
653 
654 // Get the enumeration type from a string
655 Int_t AliTreePlayer::GetStatType(const TString &stat){
656 
657  if(!stat.CompareTo("median",TString::kIgnoreCase)){
658  return kMedian;
659  } else if(!stat.CompareTo("medianLeft",TString::kIgnoreCase)){
660  return kMedianLeft;
661  } else if(!stat.CompareTo("medianRight",TString::kIgnoreCase)){
662  return kMedianRight;
663  } else if(!stat.CompareTo("RMS",TString::kIgnoreCase)){
664  return kRMS;
665  } else if(!stat.CompareTo("Mean",TString::kIgnoreCase)){
666  return kMean;
667  } else if(stat.BeginsWith("LTMRMS",TString::kIgnoreCase)){ // Least trimmed RMS, argument is LTMRMS0.95 or similar
668  return kLTMRMS;
669  } else if(stat.BeginsWith("LTM",TString::kIgnoreCase)){ // Least trimmed mean, argument is LTM0.95 or similar
670  return kLTM;
671  } else {
672  ::Error("GetStatType()","Cannot decode string \"%s\"."
673  " Use one of \"median\", \"medianLeft\", \"medianRight\", \"RMS\", or \"Mean\". "
674  " Also supported is \"LTM\", or \"LTMRMS\", which should be succeeded by a float like"
675  " \"LTM0.95\" or an integer (interpreted as percentage) like \"LTMRMS95\" to specify "
676  " the fraction of data to be kept."
677  " Use a colon separated list like \"median:medianLeft:medianRight:RMS\""
678  " as the fifth argument to the AddStatInfo().",stat.Data());
679  return kUndef;
680  }
681 }
682 //__________________________________________________________
683 void AliTreePlayer::AddStatInfo(TTree* treeLeft, TTree * treeRight , const TString refQuery, Double_t deltaT,
684  const TString statString,
685  Int_t maxEntries){
686 
687 
688  //
689  // 1.) Get variables from the right tree, sort them according to the coordinate
690  //
691  treeRight->SetEstimate(treeRight->GetEntries()*540);
692  Int_t entries = treeRight->Draw(refQuery.Data(),"","goffpara",maxEntries);
693  if(entries<1){
694  ::Error("AddStatInfo","No matching entries for query");
695  return;
696  }
697  Int_t * indexArr = new Int_t[entries];
698  TMath::Sort(entries, treeRight->GetV1(), indexArr,kFALSE);
699  Double_t * coordArray = new Double_t[entries];
700  for (Int_t icoord=0; icoord<entries; icoord++) coordArray[icoord]=treeRight->GetV1()[indexArr[icoord]];
701 
702 
703  //
704  // 2.) Attach the median,.. of the variables to the left tree
705  //
706  // The first token is the coordinate
707  TString var;
708  Ssiz_t from=0;
709  if(!refQuery.Tokenize(var,from,":")){
710  ::Error("AddStatInfo","Cannot tokenize query \'%s\'. Use colon separated list"
711  ,refQuery.Data());
712  delete[]indexArr;indexArr=0;
713  delete[]coordArray;coordArray=0;
714  return;
715  }
716  Int_t entriesCoord = treeLeft->GetEntries();
717  TBranch * br = treeLeft->GetBranch(var.Data());
718  Int_t coordValue;
719  br->SetAddress(&coordValue);
720  //TLeaf *coordLeaf = (TLeaf*)(br->GetListOfLeaves()->At(0));
721 
722  while(refQuery.Tokenize(var,from,":")){
723  // var="valueAnodeRaw.fElements[0]";
724  TString stat;
725  Ssiz_t fromStat=0;
726  while(statString.Tokenize(stat,fromStat,":")){
727  // stat = "median"; stat="medianLeft"; stat="medianRight";
728  // Int_t statType=TStatToolkit::GetStatType(stat);
729  Int_t statType=GetStatType(stat);
730  if(statType==kUndef)continue;
731  //printf("\n\n\n--- StatType %d ---\n\n\n\n",statType);
732 
733  // In case of LMS or LMR determine the fraction
734  Float_t frac=0.;
735  if(statType==kLTM || statType==kLTMRMS){ // stat="LTM0.95" or "LTMRMS0.95" similar
736  TString tmp= stat;
737  tmp.ReplaceAll("LTMRMS","");
738  tmp.ReplaceAll("LTM","");
739  frac = tmp.Atof(); // atof returns 0.0 on error
740  if(frac>1)frac/=100.; // allows "LTM95" for 95%
741  }
742 
743  // Determine the offset in coordinate to the left and right
744  Double_t leftOffset=-1e99,rightOffset=-1e99;
745  if(statType==kMedian||statType==kRMS || statType==kMean
746  || statType==kLTM || statType==kLTMRMS){ // symmetric
747  leftOffset=-deltaT;rightOffset=deltaT;
748  } else if(statType==kMedianLeft){ //left
749  leftOffset=-2.*deltaT;rightOffset=0.;
750  } else if(statType==kMedianRight){ //right
751  leftOffset=0.;rightOffset=2.*deltaT;
752  }
753 
754  TString brName=Form("%s_%s",var.Data(),stat.Data());
755  brName.ReplaceAll("[","_");
756  brName.ReplaceAll("]","_");
757  brName.ReplaceAll(".","_");
758  Double_t statValue=0;
759  TBranch *brToFill = treeLeft->Branch(brName.Data(),&statValue, (brName+"/D").Data());
760  TVectorD dvalues(entries/10+1);
761 
762  for (Int_t icoord=0; icoord<entriesCoord; icoord++){
763  // Int_t icoord=0
764  br->GetEntry(icoord);
765  Double_t startCoord=coordValue+leftOffset;
766  Double_t endCoord =coordValue+rightOffset;
767  //Double_t startCoord=coordLeaf->GetValue()+leftOffset;
768  //Double_t endCoord =coordLeaf->GetValue()+rightOffset;
769 
770  // Binary search finds last element smaller or equal
771  Int_t index0=BinarySearchSmaller(entries, coordArray, startCoord)+1;
772  Int_t index1=TMath::BinarySearch(entries, coordArray, endCoord) +1;
773  statValue=0;
774  if (index1>=0 && index0>=0){
775  //if (values.capacity()<index1-index0) values.reserve(1.5*(index1-index0)); //resize of needed
776  for (Int_t i=0; i<index1-index0; i++){
777  dvalues[i]=treeRight->GetV2()[indexArr[i+index0]];
778  }
779 
780  // Calculate
781  if(statType==kMedian||statType==kMedianLeft||statType==kMedianRight){
782  statValue=TMath::Median(index1-index0, dvalues.GetMatrixArray());
783  } else if(statType==kRMS){
784  statValue=TMath::RMS(index1-index0, dvalues.GetMatrixArray());
785  } else if(statType==kMean){
786  statValue=TMath::Mean(index1-index0, dvalues.GetMatrixArray());
787  } else if(statType==kLTM){
788  TVectorD params(7);
789  TStatToolkit::LTMUnbinned(index1-index0, dvalues.GetMatrixArray()
790  ,params,frac);
791  statValue = params[1];
792  } else if(statType==kLTMRMS){
793  TVectorD params(7);
794  TStatToolkit::LTMUnbinned(index1-index0, dvalues.GetMatrixArray()
795  ,params,frac);
796  statValue = params[2];
797  } else{
798  ::Error("AddStatInfo()","String %s StatType %d not implemented",stat.Data(),statType);
799  }
800 
801  // // debug
802  // printf("startCoord=%.3e, endCoord=%.3e, median=%.3e, index0=%d, index1=%d "
803  // ,startCoord,endCoord,statValue,index0,index1);
804  // for(Int_t i=0;i<index1-index0;i++){
805  // printf("dvalues[%d]=%.3e "
806  // ,i,dvalues[i]);
807  // }
808  // printf("\n");
809 
810 
811  }
812  brToFill->Fill();
813  } // Loop over cordinates
814  brToFill->FlushBaskets();
815  } // Loop over stat types
816  } // Loop over variables
817  treeLeft->Write();
818  delete[]indexArr;indexArr=0;
819  delete[]coordArray;coordArray=0;
820 
821 }
822 
823 
824 
825 
826 TObjArray * AliTreePlayer::MakeHistograms(TTree * tree, TString hisString, TString defaultCut, Int_t firstEntry, Int_t lastEntry, Int_t chunkSize, Int_t verbose){
827  //
828  // Return list of histograms specified by selection
829  // Should be rough equivalent of the "ALICE train" TTree->Draw();
830  // a.) Data are read only once
831  // b.) values expression are reused (evaluated only once)
832  // default cut
833  // default selection applied common for all histrograms (can be empty)
834  //
835  // hislist:
836  // his0;his1; ...; hisN
837  // histogram syntax:
838  // var0:var1:...:<#weight>>>hisName(bins0,min0,max0,bins1,min0,min, minValue,maxValue)
839  // Syntax:
840  // vari are histogramming expression
841  // weight (or cut) entry is optional
842  // - default cut is always applied, weight is applied on top
843  // ranges syntax:
844  // nbins,max,min where max and min are double or format strings
845  // in case format string % specified using (Fraction, mean,meanFraction, rms, rmsFraction)
846  // %fraction.sigma
847  // #cumulant
848  // range for bin content can be specified in the same format (by default is not set)
849  // Algortihm:
850  // 1.) Analyze formula, create minimal formula expression
851  // 2.) Event loop
852  // 3.) Filling of histograms
853  //
854  // Example usage:
855  /*
856  chunkSize=10000;
857  verbose=7;
858  chinput=gSystem->ExpandPathName("$NOTES/JIRA/PWGPP-227/data/2016/LHC16t/000267161/pass1_CENT_wSDD/filteredLocal.list");
859  TString defaultCut="esdTrack.fTPCncls>70";
860  TTree *tree=(TTree*)AliXRDPROOFtoolkit::MakeChain(chinput, "highPt", 0, 1000000000,0);
861  TString hisString="";
862  hisString+="esdTrack.Pt():#esdTrack.fTPCncls>70>>hisPtAll(100,0,30);";
863  hisString+="esdTrack.GetAlpha():#esdTrack.fTPCncls>70>>hisAlpha(90,-3.2,3.2);";
864  hisString+="esdTrack.GetTgl():#esdTrack.fTPCncls>70>>hisTgl(20,-1.2,1.2);";
865  hisString+="esdTrack.Pt():esdTrack.GetAlpha():esdTrack.GetTgl():#esdTrack.fTPCncls>70>>hisPtPhiThetaAll(100,0,30,90,-3.2,3.2,20,-1.2,1.2);";
866  hisString+="esdTrack.Pt():#(esdTrack.fFlags&0x4)>0>>hisPtITS(100,1,10);";
867  hisString+="esdTrack.fIp.Pt():#(esdTrack.fFlags&0x4)>0>>hisPtTPCOnly(100,1,10);";
868  TStopwatch timer; hisArray = AliTreePlayer::MakeHistograms(tree, hisString, "(esdTrack.fFlags&0x40)>0&&esdTrack.fTPCncls>70",0,60000,100000); timer.Print();
869  */
870  // CPU time to process one histogram or set of histograms (in paricular case of esdTrack queries) is the same - and it is determined (90 %) by tree->GetEntry
871  /*
872  THn * his0= (THn*)hisArray->At(0);
873  his0->Projection(0)->Draw("");
874  tree->SetLineColor(2);
875  TStopwatch timer; tree->Draw("esdTrack.Pt()","(esdTrack.fFlags&0x40)>0&&esdTrack.fTPCncls>70","same",60000); timer.Print();
876  */
877  const Int_t kMaxDim=10;
878  Int_t entriesAll=tree->GetEntriesFast();
879  if (chunkSize<=0) chunkSize=entriesAll;
880  if (lastEntry>entriesAll) lastEntry=entriesAll;
881  //
882  TObjArray *hisDescriptionList=hisString.Tokenize(";");
883  Int_t nHistograms = hisDescriptionList->GetEntries();
884  TObjArray * hisArray = new TObjArray(nHistograms);
885  TObjArray * hisDescriptionArray=new TObjArray(nHistograms); // OWNER
886  TObjArray * hisFormulaArray=new TObjArray(nHistograms); // array of TFomula arrays - Not OWNER
887  TObjArray * hisWeightArray=new TObjArray(nHistograms); // array of TFomula arrays - Not OWNER
888  TArrayI hisDims(nHistograms);
889  //
890  Int_t nExpressions=hisString.CountChar(':')+hisString.CountChar(';')+1;
891  TObjArray * formulaArray = new TObjArray(nExpressions); // array of all expressions - OWNER
892  TString queryString = "";
893  Int_t hisSizeFull=0;
894  //
895  // 1.) Analyze formula, book list of TObjString
896  //
897  Bool_t isOK=kTRUE;
898  for (Int_t iHis=0; iHis<nHistograms; iHis++){
899  TString hisDescription = hisDescriptionList->At(iHis)->GetName();
900  Int_t hisIndex=hisDescription.Index(">>");
901  if (hisIndex<=0) {
902  isOK=kFALSE;
903  ::Error("AliTreePlayer::MakeHistograms","Invalid expression %s",hisDescription.Data());
904  break;
905  }else{
906  hisDescriptionArray->AddAtAndExpand(new TObjString(((hisDescriptionList->At(iHis)->GetName()))+(hisIndex+2)),iHis);
907  }
908  hisDescription.Remove(hisIndex);
909  TObjArray *hisDimArray=hisDescription.Tokenize(":");
910  Int_t nDims=hisDimArray->GetEntries();
911  if (nDims<=0){
912  isOK=kFALSE;
913  ::Error("AliTreePlayer::MakeHistograms","Invalid description %s",hisDescription.Data());
914  delete hisDimArray;
915  break;
916  }
917  TObjArray * varArray = new TObjArray(nDims);
918  if (hisDimArray->At(nDims-1)->GetName()[0]=='#'){
919  TString formulaName=&((hisDimArray->At(nDims-1)->GetName())[1]);
920  nDims-=1;
921  TObjString *tFormula = new TObjString(formulaName.Data());
922  hisWeightArray->AddAt(tFormula,iHis);
923  if (formulaArray->FindObject(formulaName.Data())==NULL){
924  formulaArray->AddLast(tFormula);
925  varArray->AddAt(tFormula,nDims);
926  }
927  }
928  for (Int_t iDim=0; iDim<nDims;iDim++){
929  TObjString *tFormula = (TObjString*) (formulaArray->FindObject(hisDimArray->At(iDim)->GetName()));
930  if (tFormula==NULL){
931  tFormula = new TObjString(hisDimArray->At(iDim)->GetName());
932  formulaArray->AddLast(tFormula);
933  }
934  varArray->AddAt(tFormula,iDim);
935  }
936  hisFormulaArray->AddAt(varArray,iHis);
937  hisDims[iHis]=nDims;
938  delete hisDimArray;
939  }
940  queryString="";
941  Int_t nFormulas=formulaArray->GetEntries();
942  for (Int_t iFor=0; iFor<nFormulas; iFor++){
943  queryString+=formulaArray->At(iFor)->GetName();
944  queryString+=":";
945  }
946  queryString+=formulaArray->At(nFormulas-1)->GetName();
947  if (verbose&0x2) hisDescriptionArray->Print();
948  if (verbose&0x4) formulaArray->Print();
949  //
950  // 2.) Event loop
951  //
952  Int_t tNumber=-1;
953  for (Int_t bEntry=firstEntry; bEntry<lastEntry; bEntry+=chunkSize){ // chunks loop
954  AliSysInfo::AddStamp(TString::Format("Begin.%s",tree->GetName()).Data(),0, bEntry);
955  Int_t toQuery=TMath::Min(chunkSize, lastEntry-bEntry);
956  Int_t qLength = tree->Draw(queryString,defaultCut,"goffpara",toQuery, bEntry); // query varaibles
957  if (qLength>tree->GetEstimate()){
958  tree->SetEstimate(qLength*1.5);
959  qLength = tree->Draw(queryString,defaultCut,"goffpara",chunkSize, bEntry);
960  }
961 
962  // 2.2 fill histograms if not yet done
963  if (hisArray->GetEntriesFast()==0){ // book histograms if not yet done
964  for (Int_t iHis=0; iHis<nHistograms; iHis++){
965  if (hisDescriptionArray->At(iHis)==NULL){
966  ::Error("AliTreePlayer::MakeHistograms", "Empty description %d",iHis);
967  continue;
968  }
969  TString hisDescription= hisDescriptionArray->At(iHis)->GetName();
970  TString varDecription=hisDescriptionList->At(iHis)->GetName();
971  TObjArray * descriptionArray=hisDescription.Tokenize("(,)");
972  TObjArray * varArray= TString(hisDescriptionList->At(iHis)->GetName()).Tokenize(":");
973  Int_t nLength=descriptionArray->GetEntries();
974  if ((nLength-1)/3 < hisDims[iHis]){
975  ::Error("AliTreePlayer::MakeHistograms", "Histogram dimension Mismatch %s", hisDescriptionArray->At(iHis)->GetName());
976  return NULL;
977  }
978  if (varArray->GetEntries()<hisDims[iHis]){
979  ::Error("AliTreePlayer::MakeHistograms", "Variable mismatch %s", hisDescriptionArray->At(iHis)->GetName());
980  return NULL;
981  }
982  TString hName(descriptionArray->At(0)->GetName());
983  THnBase * his = 0;
984  Int_t nBins[kMaxDim];
985  Double_t xMin[kMaxDim], xMax[kMaxDim];
986  for (Int_t iDim=0; iDim<hisDims[iHis]; iDim++){
987  nBins[iDim]= TString(descriptionArray->At(3*iDim+1)->GetName()).Atoi();
988  if (descriptionArray->At(3*iDim+2)->GetName()[0]!='%'){
989  xMin[iDim]= TString(descriptionArray->At(3*iDim+2)->GetName()).Atof();
990  }else{
991  if (descriptionArray->At(3*iDim+2)->GetName()[1]=='A'){ // %A - alias describing range
992  TTreeFormula falias("falias",&(descriptionArray->At(3*iDim+2)->GetName()[2]),tree);
993  xMin[iDim]=falias.EvalInstance();
994  }
995  }
996  if (descriptionArray->At(3*iDim+3)->GetName()[0]!='%'){
997  xMax[iDim]= TString(descriptionArray->At(3*iDim+3)->GetName()).Atof();
998  }else{
999  if (descriptionArray->At(3*iDim+3)->GetName()[1]=='A'){ // %A - alias describing range
1000  TTreeFormula falias("falias",&(descriptionArray->At(3*iDim+3)->GetName()[2]),tree);
1001  xMax[iDim]=falias.EvalInstance();
1002  }
1003  }
1004  if (xMax[iDim]<=xMin[iDim]){
1005  ::Error("AliTreePlayer::MakeHistograms","Invalid hstogram range specification for histogram %s: %s\t%s",hisDescription.Data(), \
1006  descriptionArray->At(3*iDim+2)->GetName(), descriptionArray->At(3*iDim+3)->GetName() );
1007  }
1008  }
1009  THnF * phis = new THnF(hName.Data(),hName.Data(), hisDims[iHis],nBins, xMin,xMax);
1010  hisArray->AddAt(phis,iHis);
1011  AliSysInfo::AddStamp(hName.Data(),10, phis->GetNbins());
1012  if (verbose&0x1) {
1013  ::Info("AliTreePlayer::MakeHistograms","%s: size=%d",hisDescription.Data(), phis->GetNbins());
1014  }
1015  hisSizeFull+= phis->GetNbins();
1016  for (Int_t iDim=0;iDim<hisDims[iHis]; iDim++){
1017  phis->GetAxis(iDim)->SetName(varArray->At(iDim)->GetName());
1018  phis->GetAxis(iDim)->SetTitle(varArray->At(iDim)->GetName());
1019  TNamed *axisTitle=TStatToolkit::GetMetadata(tree,TString::Format("%s.AxisTitle",varArray->At(iDim)->GetName()).Data());
1020  if (axisTitle) phis->GetAxis(iDim)->SetTitle(axisTitle->GetTitle());
1021  }
1022  }
1023  if (verbose&0x1) {
1024  ::Info("AliTreePlayer::MakeHistograms","Total size=%d",hisSizeFull);
1025  }
1026  }
1027  // 2.3 fill histograms
1028  Double_t values[kMaxDim];
1029  for (Int_t iHis=0; iHis<nHistograms; iHis++){
1030  Int_t indeces[kMaxDim+1];
1031  TObjArray *formulaArrayHis = (TObjArray*) (hisFormulaArray->At(iHis));
1032  for (Int_t iVec=0; iVec<formulaArrayHis->GetEntriesFast(); iVec++){
1033  indeces[iVec]= formulaArray->IndexOf(formulaArray->FindObject(formulaArrayHis->At(iVec)->GetName()));
1034  }
1035  Int_t indexW=-1;
1036  if (hisWeightArray->GetEntriesFast()>=iHis){
1037  if (hisWeightArray->UncheckedAt(iHis)!=NULL){
1038  if (hisWeightArray->UncheckedAt(iHis)->GetName()){
1039  indexW= formulaArray->IndexOf(formulaArray->FindObject(hisWeightArray->UncheckedAt(iHis)->GetName()));
1040  }else{
1041  ::Error("xxx","Problem to find %s", hisWeightArray->UncheckedAt(iHis)->GetName());
1042  }
1043  }
1044  }
1045  THnBase * his = (THnBase*) hisArray->UncheckedAt(iHis);
1046  for (Int_t cEvent=0; cEvent<qLength; cEvent++){
1047  for (Int_t iDim=0; iDim<hisDims[iHis]; iDim++){
1048  values[iDim]=tree->GetVal(indeces[iDim])[cEvent];
1049  }
1050  Double_t weight=(indexW<0)? 1: tree->GetVal(indexW)[cEvent];
1051  if (weight>0) his->Fill(values,weight);
1052  }
1053  }
1054  AliSysInfo::AddStamp(TString::Format("End.%s",tree->GetName()).Data(),0, bEntry);
1055  }
1056  //
1057  delete hisDescriptionArray;
1058  delete formulaArray;
1059  return hisArray;
1060 
1061 }
1062 
1063 
1064 
1065 
1066 TPad * AliTreePlayer::DrawHistograms(TPad * pad, TObjArray * hisArray, TString drawExpression, TObjArray *keepArray, Int_t verbose){
1067  //
1068  //
1069  // Example usage:
1070  /*
1071  TPad *pad= 0; TString drawExpression="";
1072  drawExpression="[1,1,1]:"
1073  drawExpression+="hisPtAll(0,10)(0)(errpl);hisPtITS(0,10)(0)(err);hisPtPhiThetaAll(0,10,-3.2,3.2,-1.2,1.2)(0)(err):";
1074  drawExpression+="hisAlpha(-3.2,3.2)(0)(errpl);hisPtPhiThetaAll(0,10,-3.2,3.2,-1.2,1.2)(1)(err):";
1075  drawExpression+="hisTgl(-1,1)(0)(errpl);hisPtPhiThetaAll(0,10,-3.2,3.2,-1.2,1.2)(2)(err):";
1076  pad = AliTreePlayer::DrawHistograms(0,hisArray,drawExpression);
1077  */
1078  TString projType[8]={"f-mean","f-rms","f-ltm","f-ltmsigma","f-gmean","f-grms","f-median","f-gmean"};
1079 
1080  TObjArray *drawList=drawExpression.Tokenize(":");
1081  // structure pad
1082  TString padDescription=drawList->At(0)->GetName();
1083  if (pad==NULL){
1084  pad = new TCanvas(drawExpression, drawExpression,1000,800);
1085  }
1086  // divide pads
1087  Int_t nPads=0, nRows=0;
1088  TObjArray *padRows=padDescription.Tokenize("[](),");
1089  nRows=padRows->GetEntries();
1090  for (Int_t iRow=0; iRow<nRows; iRow++){
1091  Int_t nCols=TString(padRows->At(iRow)->GetName()).Atoi();
1092  for (Int_t iCol=0; iCol<nCols; iCol++){
1093  pad->cd();
1094  TPad * newPad=new TPad("pad","pad",iCol/Double_t(nCols),(nRows-iRow-1)/Double_t(nRows),(iCol+1)/Double_t(nCols),(nRows-iRow)/Double_t(nRows));
1095  newPad->Draw();
1096  nPads++;
1097  newPad->SetNumber(nPads);
1098  }
1099  }
1100  delete padRows;
1101  //
1102  //
1103  TPRegexp isPadOption("^%O");
1104  Bool_t isLogY=kFALSE;
1105  for (Int_t iPad=0; iPad<nPads; iPad++){
1106  if (drawList->At(iPad+1)==NULL) break;
1107  //TVirtualPad *cPad =
1108  pad->cd(iPad+1);
1109  TLegend * legend = new TLegend(0.11,0.85, 0.89,0.99, TString::Format("Pad%d",iPad));
1110  legend->SetNColumns(2);
1111  legend->SetBorderSize(0);
1112  TString padSetup=drawList->At(iPad+1)->GetName();
1113  TString padOption="";
1114  Bool_t isTimeX=kFALSE, isTimeY=kFALSE;
1115 
1116  if (padSetup.Contains(isPadOption)){
1117  padOption=TString(&padSetup[2]);
1118  padOption.Remove(padOption.First(";"));
1119  padOption.ToLower();
1120  if (padOption.Contains("logy")) {
1121  pad->cd(iPad+1)->SetLogy();
1122  isLogY=kTRUE;
1123  }
1124  if (padOption.Contains("logx")) {
1125  pad->cd(iPad+1)->SetLogx();
1126  }
1127  if (padOption.Contains("gridy")) pad->cd(iPad+1)->SetGridy();
1128  if (padOption.Contains("gridx")) pad->cd(iPad+1)->SetGridx();
1129  if (padOption.Contains("timex")) isTimeX=kTRUE;
1130  if (padOption.Contains("timey")) isTimeY=kTRUE;
1131  padSetup.Remove(0,padSetup.First(';')+1);
1132  }
1133 
1134  TObjArray * padDrawList= padSetup.Tokenize(";");
1135  Double_t hisMin=0, hisMax=-1;
1136  TH1 * hisToDraw=0;
1137  TGraphErrors * grToDraw=0;
1138  //
1139  for (Int_t ihis=0; ihis<padDrawList->GetEntries(); ihis++){
1140  TObjArray *hisDescription= TString(padDrawList->At(ihis)->GetName()).Tokenize("()");
1141  THn * his = (THn*)hisArray->FindObject(hisDescription->At(0)->GetName());
1142  if (his==NULL) continue;
1143  if (verbose&0x4){
1144  ::Info("AliTreePlayer::DrawHistograms","Pad %d. Processing his %s",iPad, hisDescription->At(0)->GetName());
1145  }
1146  Int_t ndim=his->GetNdimensions();
1147  TString rangeDescription(hisDescription->At(1)->GetName());
1148  Int_t ndimRange= (rangeDescription.CountChar(','));
1149  if (ndimRange>0) ndimRange=ndimRange/2+1;
1150  if (ndimRange>0){
1151  TObjArray *rangeArray=rangeDescription.Tokenize(",");
1152  for (Int_t iDim=0; iDim<ndimRange; iDim++){
1153  if (rangeArray->At(iDim*2)->GetName()[0]=='U') {
1154  Double_t min=TString(&(rangeArray->At(iDim*2)->GetName()[1])).Atof();
1155  Double_t max=TString(&(rangeArray->At(iDim*2+1)->GetName()[1])).Atof();
1156  if (verbose&0x8){
1157  ::Info("AliTreePlayer::DrawHistograms","Pad %d. %s.GetAxis(%d).SetRangeUser(%f,%f).",iPad,hisDescription->At(0)->GetName(), iDim, min,max);
1158  }
1159  his->GetAxis(iDim)->SetRangeUser(min,max);
1160  }else{
1161  Int_t min=TString((rangeArray->At(iDim*2)->GetName())).Atoi();
1162  Int_t max=TString((rangeArray->At(iDim*2+1)->GetName())).Atoi();
1163  if (verbose&0x8){
1164  ::Info("AliTreePlayer::DrawHistograms","Pad %d. %s.GetAxis(%d).SetRange(%d,%d).",iPad,hisDescription->At(0)->GetName(), iDim, min,max);
1165  }
1166  his->GetAxis(iDim)->SetRange(min,max);
1167  }
1168  }
1169  delete rangeArray;
1170  }
1171  TString drawOption = hisDescription->At(3)->GetName();
1172  drawOption.ToLower();
1173  TString projString=hisDescription->At(2)->GetName();
1174  Int_t nDims = projString.CountChar(',')+1;
1175  TH1 * hProj =0;
1176  TGraphErrors*gr=0;
1177  //
1178  if (nDims==1) hProj=his->Projection(projString.Atoi());
1179  if (nDims==2) {
1180  Int_t dim0 = projString.Atoi();
1181  Int_t dim1 = TString(&(projString[2])).Atoi();
1182  TH2* his2D =his->Projection(dim0,dim1);
1183  for (Int_t iProj=0; iProj<8; iProj++){
1184  if (drawOption.Contains(projType[iProj])){
1185  gr=TStatToolkit::MakeStat1D(his2D,0,1.0,iProj,21+ihis,ihis+1);
1186  gr->SetName(padDrawList->At(ihis)->GetName());
1187  gr->SetTitle(padDrawList->At(ihis)->GetName());
1188  gr->GetXaxis()->SetTitle(his2D->GetXaxis()->GetTitle());
1189  gr->GetYaxis()->SetTitle(his2D->GetYaxis()->GetTitle());
1190  drawOption.ReplaceAll(projType[iProj].Data(),"");
1191  }
1192  }
1193  delete his2D;
1194  }
1195  if (gr){
1196  Double_t grMinI=TMath::MinElement(gr->GetN(),gr->GetY())-3.*TMath::Median(gr->GetN(),gr->GetEY());
1197  Double_t grMaxI=TMath::MaxElement(gr->GetN(),gr->GetY())+3.*TMath::Median(gr->GetN(),gr->GetEY());
1198  if (hisMax<hisMin) {hisMin=grMinI; hisMax=grMaxI;}
1199  if (hisMax<grMaxI) hisMax=grMaxI;
1200  if (hisMin>grMinI) hisMin=grMinI;
1201  if (ihis==0) {
1202  grToDraw = gr;
1203  gr->Draw((drawOption+"a").Data());
1204  legend->AddEntry(gr,"","p");
1205  }
1206  else{
1207  gr->Draw(drawOption.Data());
1208  legend->AddEntry(gr,"", "p");
1209  }
1210  if (keepArray) keepArray->AddLast(gr);
1211  }
1212  if (hProj){
1213  hProj->SetMarkerColor(ihis+1);
1214  hProj->SetLineColor(ihis+1);
1215  hProj->SetMarkerStyle(21+ihis);
1216  if (keepArray) keepArray->AddLast(hProj);
1217  //
1218  if (hisMax<hisMin) {
1219  hisMin=hProj->GetMinimum();
1220  hisMax=hProj->GetMaximum();
1221  }
1222  if (hisMax<hProj->GetMaximum()) hisMax=hProj->GetMaximum();
1223  if (hisMin>hProj->GetMinimum()) hisMin=hProj->GetMinimum();
1224  if (ihis==0) {
1225  hisToDraw = hProj;
1226  hProj->Draw((TString(hisDescription->At(3)->GetName())+"").Data());
1227  legend->AddEntry(hProj);
1228  }
1229  else{
1230  hProj->Draw((TString(hisDescription->At(3)->GetName())+"same").Data());
1231  legend->AddEntry(hProj);
1232  }
1233  }
1234  }
1235  pad->cd(iPad+1);
1236  if (hisToDraw!=NULL){
1237  hisToDraw->SetMaximum(hisMax+(hisMax-hisMin)/2.);
1238  if (hisMin<=0) hisMin=TMath::Min(0.01, hisMax*0.01);
1239  hisToDraw->SetMinimum(hisMin);
1240  if (isLogY){
1241  hisToDraw->SetMaximum(hisMax*TMath::Max(10.,(hisMax/hisMin)/4.));
1242  }
1243 
1244  if ((verbose&0x8)>0){
1245  ::Info("AliTreePlayer::DrawHistograms:","Pad %d. %s SetMinimum(%f). SetMaximum(%f)",iPad,padDrawList->At(0)->GetName(), hisMin,hisMax+(hisMax-hisMin)/2.);
1246  }
1247  if (isTimeX) hisToDraw->GetXaxis()->SetTimeDisplay(1);
1248  if (isTimeY) hisToDraw->GetYaxis()->SetTimeDisplay(1);
1249  pad->cd(iPad+1)->Modified();
1250  pad->cd(iPad+1)->Update();
1251  legend->Draw("same");
1252  }
1253  if (grToDraw!=NULL){
1254  grToDraw->SetMaximum(hisMax+(hisMax-hisMin)/2.);
1255  grToDraw->SetMinimum(hisMin-(hisMax-hisMin)/3.);
1256  if (isTimeX) grToDraw->GetXaxis()->SetTimeDisplay(1);
1257  if (isTimeY) grToDraw->GetYaxis()->SetTimeDisplay(1);
1258 
1259  if ((verbose&0x8)>0){
1260  ::Info("AliTreePlayer::DrawHistograms:","Pad %d. %s SetMinimum(%f). SetMaximum(%f)",iPad,padDrawList->At(0)->GetName(), hisMax+(hisMax-hisMin)/2.,hisMin-(hisMax-hisMin)/3.);
1261  }
1262 
1263  pad->cd(iPad+1)->Modified();
1264  pad->cd(iPad+1)->Update();
1265  legend->Draw("same");
1266  }
1267  pad->cd(iPad+1);
1268  }
1269  return pad;
1270 
1271 }
1272 
1273 
1274 
1275 void AliTreePlayer::MakeCacheTree(TTree * tree, TString varList, TString outFile, TString outTree, TCut selection){
1276  //
1277  // Fill tree with information specified in varList of TTreeFormulas
1278  // In case input tree is "flat" - not array output tree can be used as a friend ....
1279  // Input:
1280  // tree - TTree with input
1281  // varList - list of TTreeFormulas
1282  // selection - tree selection
1283  // Output: tree
1284  // outFile - output file name
1285  // outTree - output tree name
1286  TTreeSRedirector *pcstream = new TTreeSRedirector(outFile,"recreate");
1287  if (tree->GetEstimate()<tree->GetEntries()) tree->SetEstimate(tree->GetEntries());
1288  Int_t entries=tree->Draw(varList.Data(),selection,"goffpara");
1289  TObjArray * varName=varList.Tokenize(":");
1290  const Int_t nVars=varName->GetEntries();
1291  Double_t vars[nVars];
1292  TTree *treeOut=NULL;
1293  for (Int_t iPoint=0; iPoint <entries; iPoint++){
1294  for (Int_t iVar=0; iVar<nVars; iVar++){
1295  vars[iVar]=tree->GetVal(iVar)[iPoint];
1296  if (iPoint==0) (*pcstream)<<outTree.Data()<<TString::Format("%s=",varName->At(iVar)->GetName()).Data()<<vars[iVar];
1297  }
1298  if (iPoint==0) {
1299  (*pcstream)<<outTree.Data()<<"\n";
1300  treeOut=((*pcstream)<<outTree.Data()).GetTree();
1301  }else{
1302  treeOut->Fill();
1303  }
1304  }
1305  delete pcstream;
1306 }
1307 
1308 
1309 
1310 
1311 
static TString printSelectedTreeInfo(TTree *tree, TString infoType, TString regExpFriend, TString regExpTag, Int_t verbose)
printf("Chi2/npoints = %f\n", TMath::Sqrt(chi2/npoints))
static TObjArray * selectMetadata(TTree *tree, TString query, Int_t verbose)
static TPad * DrawHistograms(TPad *pad, TObjArray *hisArray, TString drawExpression, TObjArray *keepArray=0, Int_t verbose=0)
#define TObjArray
static TObjArray * selectTreeInfo(TTree *tree, TString query, Int_t verbose)
static Int_t GetStatType(const TString &stat)
TTreeSRedirector * pcstream
strP3 Tokenize("+") -> Print()
TTree * tree
TGraphErrors * MakeStat1D(TH2 *his, Int_t deltaBin, Double_t fraction, Int_t returnType, Int_t markerStyle, Int_t markerColor)
TStatToolkit stat
Definition: AnalyzeLaser.C:5
ClassImp(AliTreePlayer) AliTreePlayer
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)
static Long64_t BinarySearchSmaller(Long64_t n, const T *array, T value)
Definition: AliTreePlayer.h:57
static Int_t selectWhatWhereOrderBy(TTree *tree, TString what, TString where, TString orderBy, Int_t firstentry, Int_t nentries, TString outputFormat, TString outputName)
Int_t * LTMUnbinned(int np, const T *arr, TVectorT< T > &params, Float_t keep=1.0)
Int_t nBins
class TVectorT< Double_t > TVectorD
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", Int_t maxEntries=100000000)
TTree * GetTree(Int_t ievent)
TNamed * GetMetadata(TTree *tree, const char *vartagName, TString *prefix=0)
static void MakeCacheTree(TTree *tree, TString varList, TString outFile, TString outTree, TCut selection)
return kTRUE
Definition: AliFMDv1.cxx:97