AliPhysics  9fe175b (9fe175b)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AliMTRChEffAnalysis.cxx
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright(c) 1998-2007, 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 #include "AliMTRChEffAnalysis.h"
17 
18 // ROOT includes
19 #include <Riostream.h>
20 #include "TObjString.h"
21 #include "TObjArray.h"
22 #include "TList.h"
23 #include "TSystem.h"
24 #include "TROOT.h"
25 #include "TPRegexp.h"
26 #include "TRegexp.h"
27 #include "TFile.h"
28 #include "TDirectory.h"
29 #include "TTree.h"
30 #include "TKey.h"
31 #include "TArrayI.h"
32 #include "TArrayD.h"
33 #include "TGrid.h"
34 #include "TGridResult.h"
35 #include "TGraphAsymmErrors.h"
36 #include "TH1.h"
37 #include "TH2.h"
38 #include "TAxis.h"
39 #include "TF1.h"
40 #include "TMath.h"
41 #include "TCanvas.h"
42 #include "TLegend.h"
43 #include "TLine.h"
44 #include "TLatex.h"
45 #include "TFileMerger.h"
46 #include "TFitResultPtr.h"
47 
48 #include "AliLog.h"
49 #include "AliMergeableCollection.h"
50 #include "AliCounterCollection.h"
51 
52 #include "AliAnalysisMuonUtility.h"
53 #include "AliTrigChEffOutput.h"
54 
55 #include "AliCDBManager.h"
56 #include "AliCDBStorage.h"
57 #include "AliCDBId.h"
58 #include "AliCDBEntry.h"
59 #include "AliMUONCDB.h"
60 #include "AliMUONTriggerEfficiencyCells.h"
61 
63 ClassImp(AliMTRChEffAnalysis) // Class implementation in ROOT context
65 
66 using std::cout;
67 using std::endl;
68 using std::cin;
69 using std::ofstream;
70 using std::ifstream;
71 
72 //________________________________________________________________________
74  TObject(),
75  fOutputs(0x0),
76  fConditions(0x0),
77  fMergedOutputs(0x0)
78 {
80 
81 }
82 
83 //________________________________________________________________________
84 AliMTRChEffAnalysis::AliMTRChEffAnalysis ( const char *localFileList, const char* outputName ) :
85  TObject(),
86  fOutputs(0x0),
87  fConditions(0x0),
88  fMergedOutputs(0x0)
89 {
91  SetOutList(localFileList,outputName);
92 }
93 
94 //________________________________________________________________________
96 {
97  //
99  //
100  delete fOutputs;
101  delete fConditions;
102  delete fMergedOutputs;
103 }
104 
105 //________________________________________________________________________
106 Bool_t AliMTRChEffAnalysis::AddSystematicCondition ( const char* physSel, const char* trigClassName, const char* centrality, Int_t itrackSel, Int_t imatch, Int_t imethod )
107 {
109  return SetCondition(physSel, trigClassName, centrality, itrackSel, imatch, imethod, kFALSE);
110 }
111 
112 //________________________________________________________________________
113 Bool_t AliMTRChEffAnalysis::AddToList ( const char *filename, const char *outputName )
114 {
116  AliTrigChEffOutput* trigOut = new AliTrigChEffOutput(filename,outputName);
117  if ( ! trigOut->GetMergeableCollection() ) {
118  AliError(Form("Cannot find %s in %s\n",outputName,filename));
119  return kFALSE;
120  }
121 
122  TObjArray* condition = static_cast<TObjArray*>(fConditions->At(0));
123 
124 // // Delete counter collection to save memory
125 // trigOut->RemoveFromList(trigOut->GetCounterCollection());
126  // Just keep counter and mergeable collections
127  TList* effHistoList = GetEffHistoList(trigOut,condition);
128  effHistoList->SetName(filename);
129  TString currRun = AliAnalysisMuonUtility::GetRunNumberAsString(filename);
130  effHistoList->SetUniqueID(currRun.Atoi());
131 
132  if ( ! fOutputs ) {
133  fOutputs = new TObjArray();
134  fOutputs->SetOwner();
135  fOutputs->SetName(outputName);
136  }
137  fOutputs->Add(effHistoList);
138  delete trigOut;
139  return kTRUE;
140 }
141 
142 //________________________________________________________________________
143 TArrayI AliMTRChEffAnalysis::BoardsInRPC ( Int_t irpc ) const
144 {
146 
147  // FIXME: ugly and hardcoded, but avoid loading the mapping
148 
149  TArrayI boards;
150  if ( irpc == 0 || irpc == 9 ) {
151  Int_t arr[] = {26,27,28,29,48,49,50,51,68,69,84,85,100,101,113};
152  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
153  boards.Set(nBoards,arr);
154  if ( irpc == 9 )
155  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
156  }
157  else if ( irpc == 1 || irpc == 8 ) {
158  Int_t arr[] = {9,10,11,30,31,32,33,52,53,54,55,70,71,86,87,102,103,114};
159  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
160  boards.Set(nBoards,arr);
161  if ( irpc == 8 )
162  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
163  }
164  else if ( irpc == 2 || irpc == 7 ) {
165  Int_t arr[] = {12,13,34,35,56,57,72,73,88,89,104,105,115};
166  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
167  boards.Set(nBoards,arr);
168  if ( irpc == 7 )
169  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
170  }
171  else if ( irpc == 3 || irpc == 6 ) {
172  Int_t arr[] = {14,15,36,37,58,59,74,75,90,91,106,107,116};
173  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
174  boards.Set(nBoards,arr);
175  if ( irpc == 6 )
176  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
177  }
178  else if ( irpc == 4 || irpc == 5 ) {
179  Int_t arr[] = {16,38,60,76,92,108,117};
180  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
181  boards.Set(nBoards,arr);
182  if ( irpc == 5 )
183  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
184  }
185  else if ( irpc == 17 || irpc == 10 ) {
186  Int_t arr[] = {6,7,8,22,23,24,25,44,45,46,47,66,67,82,83,98,99,112};
187  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
188  boards.Set(nBoards,arr);
189  if ( irpc == 10 )
190  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
191  }
192  else if ( irpc == 16 || irpc == 11 ) {
193  Int_t arr[] = {4,5,20,21,42,43,64,65,80,81,96,97,111};
194  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
195  boards.Set(nBoards,arr);
196  if ( irpc == 11 )
197  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
198  }
199  else if ( irpc == 15 || irpc == 12 ) {
200  Int_t arr[] = {2,3,18,19,40,41,62,63,78,79,94,95,110};
201  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
202  boards.Set(nBoards,arr);
203  if ( irpc == 12 )
204  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
205  }
206  else if ( irpc == 14 || irpc == 13 ) {
207  Int_t arr[] = {1,17,39,61,77,93,109};
208  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
209  boards.Set(nBoards,arr);
210  if ( irpc == 13 )
211  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
212  }
213 
214  return boards;
215 }
216 
217 //________________________________________________________________________
218 Int_t AliMTRChEffAnalysis::CompareEfficiencies ( const char* sources, const char* titles, const char* opt, const char* canvasNameSuffix ) const
219 {
221  TString srcs(sources);
222  if ( srcs.Contains("raw://") ) {
223  AliError("The method assumes that the specified storage is a SpecificStorage. Hence, please replace raw:// with the actual path in alien, e.g.: alien://folder=/alice/data/<year>/OCDB");
224  return -2;
225  }
226  TObjArray* sourceList = srcs.Tokenize(",");
227  TObjArray effMapList;
228  effMapList.SetOwner();
229 
230  TString trigEffCDBdir = "MUON/Calib/TriggerEfficiency";
231 
232  TIter next(sourceList);
233  TObjString* src = 0x0;
234  while ( (src = static_cast<TObjString*>(next())) ) {
235  TString currSrc = src->String();
236  if ( currSrc.BeginsWith("alien") && ! gGrid ) TGrid::Connect("alien://");
237 
238  AliMUONTriggerEfficiencyCells* effMap = 0x0;
239  if ( currSrc.EndsWith(".root") ) effMap = new AliMUONTriggerEfficiencyCells(currSrc.Data());
240  else {
241  TObjArray* dirRun = currSrc.Tokenize("?");
242  TString cdbPath = dirRun->UncheckedAt(0)->GetName();
243  TString runNum = ( dirRun->GetEntriesFast() > 1 ) ? dirRun->UncheckedAt(1)->GetName() : "";
244  AliCDBManager* mgr = AliCDBManager::Instance();
245  if ( ! mgr->GetDefaultStorage() ) mgr->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
246  if ( mgr->GetSpecificStorage(trigEffCDBdir.Data()) ) mgr->UnloadFromCache(trigEffCDBdir.Data());
247  mgr->SetSpecificStorage(trigEffCDBdir.Data(),cdbPath.Data());
248  Int_t runNumber = 0;
249  if ( runNum.IsNull() ) {
250  cout << "Please enter run number: " << endl;
251  cin >> runNumber;
252  }
253  else runNumber = runNum.Atoi();
254  mgr->SetRun(runNumber);
255  AliCDBEntry* cdbEntry = mgr->Get(trigEffCDBdir.Data());
256 
257  // The CDB manager replace the current effMap with another in case two specific storage are provided
258  // To avoid double deletion, the object must be cloned
259  effMap = static_cast<AliMUONTriggerEfficiencyCells*>(cdbEntry->GetObject()->Clone());
260  }
261  if ( ! effMap ) continue;
262  effMapList.Add(effMap);
263  }
264 
265  return CompareEfficiencies(&effMapList, titles, opt, canvasNameSuffix);
266 }
267 
268 //________________________________________________________________________
269 Int_t AliMTRChEffAnalysis::CompareEfficiencies ( TObjArray* effMapList, const char* titles, const char* opt, const char* canvasNameSuffix ) const
270 {
272 
273  TString sTitles(titles);
274  TObjArray* titleList = sTitles.Tokenize(",");
275 
276  Int_t nDiffs = 0;
277 
278  Int_t nLists = effMapList->GetEntriesFast();
279 
280  TString sCanvasNameSuffix(canvasNameSuffix);
281  if ( ! sCanvasNameSuffix.IsNull() && ! sCanvasNameSuffix.BeginsWith("_") ) sCanvasNameSuffix.Prepend("_");
282 
283  Double_t xpt, ypt, xref, yref;
284  enum {kEff, kDiff, kPull};
285  TString sOpt(opt);
286  sOpt.ToLower();
287  Int_t iopt = kEff;
288  TString yTitle = "Eff.";
289  if ( sOpt.Contains("diff") ) {
290  iopt = kDiff;
291  yTitle = "Eff. - (ref.Eff)";
292  }
293  else if ( sOpt.Contains("pull") ) {
294  iopt = kPull;
295  yTitle = "(Eff - (ref.Eff)) / err";
296  }
297  else nDiffs = -1;
298 
299  Bool_t needsLegend = ( nLists > 1 );
300 // if ( iopt != kEff ) needsLegend = nLists > 2;
301 
302  Int_t colors[] = {kBlack, kRed, kSpring, kTeal, kBlue, kViolet, kMagenta, kOrange, kGray};
303  Int_t ncolors = sizeof(colors)/sizeof(colors[0]);
304 
305  Int_t hTypes[2] = {AliMUONTriggerEfficiencyCells::kHboardCount,AliMUONTriggerEfficiencyCells::kHslatCount};
306  Int_t countTypes[3] = {AliMUONTriggerEfficiencyCells::kBendingEff,AliMUONTriggerEfficiencyCells::kNonBendingEff,AliMUONTriggerEfficiencyCells::kBothPlanesEff};
307 
308  TString currName = "";
309  Int_t ican = 0;
310  for ( Int_t itype=0; itype<2; itype++ ) {
311  TString xTitle = ( hTypes[itype] == AliMUONTriggerEfficiencyCells::kHslatCount ) ? "RPC" : "Board";
312  for ( Int_t icount=0; icount<3; icount++ ) {
313  TCanvas* can = 0x0;
314  for ( Int_t ich=0; ich<4; ich++ ) {
315  TLegend* leg = 0x0;
316 // Int_t hrefIdx = AliTrigChEffOutput::kNcounts + AliTrigChEffOutput::kNcounts*4*(itype-1) + 4*AliTrigChEffOutput::kAllTracks + ich;
317 // Int_t hIdx = AliTrigChEffOutput::kNcounts + AliTrigChEffOutput::kNcounts*4*(itype-1) + 4*icount + ich;
318  TGraphAsymmErrors* refGraph = 0x0;
319  for ( Int_t ilist=0; ilist<nLists; ilist++ ) {
320  TString currTitle = titleList->At(ilist)->GetName();
321  AliMUONTriggerEfficiencyCells* effMap = static_cast<AliMUONTriggerEfficiencyCells*>(effMapList->UncheckedAt(ilist));
322  currName = effMap->GetHistoName(hTypes[itype],AliMUONTriggerEfficiencyCells::kAllTracks,ich);
323  TH1* histoDen = static_cast<TH1*>(effMap->GetHistoList()->FindObject(currName.Data()));
324  currName = effMap->GetHistoName(hTypes[itype],countTypes[icount],ich);
325  TH1* histoNum = static_cast<TH1*>(effMap->GetHistoList()->FindObject(currName.Data()));
326  TGraphAsymmErrors* graph = new TGraphAsymmErrors(histoNum,histoDen,"e0");
327  currName = histoNum->GetName();
328  currName.ReplaceAll("Count","Eff");
329  currName.Append(Form("_%s",currTitle.Data()));
330  graph->SetName(currName.Data());
331 
332  if ( iopt != kEff ) {
333  if ( refGraph ) {
334  for ( Int_t ipt=0; ipt<graph->GetN(); ipt++ ) {
335  refGraph->GetPoint(ipt,xref,yref);
336  graph->GetPoint(ipt,xpt,ypt);
337  Double_t diff = ypt - yref;
338  if ( TMath::Abs(diff) > 1.e-4 ) nDiffs++;
339  if ( iopt == kDiff ) graph->SetPoint(ipt,xpt,diff);
340  else if ( iopt == kPull ) {
341  Double_t err = GetError(graph->GetErrorYlow(ipt),graph->GetErrorYhigh(ipt));
342  Double_t pull = ( err > 0. ) ? diff/err : 0.;
343  graph->SetPoint(ipt,xpt,pull);
344  }
345  } // loop on points
346  }
347  else {
348  refGraph = graph;
349  continue;
350  }
351  }
352 
353  if ( ! can ) {
354  currName = graph->GetName();
355  currName.Remove(currName.Length()-currTitle.Length()-5);
356  currName += sCanvasNameSuffix;
357  can = new TCanvas(currName.Data(),currName.Data(),20*ican,20*ican,600,600);
358  can->Divide(2,2);
359  ican++;
360  }
361  if ( needsLegend && ! leg ) {
362  leg = new TLegend(0.35, 0.15, 0.65, 0.45);
363  if ( refGraph ) leg->SetHeader(Form("Ref.: %s",titleList->At(0)->GetName()));
364  }
365  can->cd(ich+1);
366  gPad->SetGridy();
367  Int_t icolor = ( ilist < ncolors ) ? colors[ilist] : 20+ilist;
368  graph->SetLineColor(icolor);
369  graph->SetMarkerColor(icolor);
370  graph->SetMarkerStyle(20+ilist);
371  graph->SetMarkerSize(0.5);
372  graph->GetXaxis()->SetTitle(xTitle.Data());
373  graph->GetYaxis()->SetTitle(yTitle.Data());
374  graph->Draw((gPad->GetListOfPrimitives()->GetEntries()==0)?"ap":"p");
375  if ( leg ) leg->AddEntry(graph,titleList->At(ilist)->GetName(),"lp");
376  } // loop on lists
377  if (leg ) leg->Draw();
378  delete refGraph;
379  } // loop on chambers
380  } // loop on counts
381  } // loop on types
382 
383  delete titleList;
384 
385  return nDiffs;
386 }
387 
388 //________________________________________________________________________
389 Int_t AliMTRChEffAnalysis::CompareEfficiencyMethods ( const char* source, const char* opt, const char* canvasNameSuffix ) const
390 {
392  if ( ! fConditions ) {
393  AliWarning("No condition found! Please specify the default efficiency condition with SetEffConditions and then add additional tests with AddSystematicCondition");
394  return -1;
395  }
396 
397  AliTrigChEffOutput trigOut(source);
398 
399  Int_t nConditions = fConditions->GetEntriesFast();
400 
401  TObjArray condTitle(nConditions);
402  condTitle.SetOwner();
403  GetShortConditionTitles(&trigOut,condTitle);
404 
405  TString titles = "";
406  TObjArray effMapList;
407  effMapList.SetOwner();
408 
409  for ( Int_t icond=0; icond<nConditions; icond++ ) {
410  TObjArray* condition = static_cast<TObjArray*>(fConditions->UncheckedAt(icond));
411 
412  TList* effList = GetEffHistoList(&trigOut, condition);
413  AliMUONTriggerEfficiencyCells* effMap = new AliMUONTriggerEfficiencyCells(effList);
414  effMapList.Add(effMap);
415  titles += Form("%s,",condTitle.At(icond)->GetName());
416  }
417 
418  titles.Remove(TString::kTrailing,',');
419  return CompareEfficiencies(&effMapList, titles, opt, canvasNameSuffix);
420 }
421 
422 
423 //________________________________________________________________________
425 {
426  if ( ! HasMergedResults() ) return;
427 
428  TObjArray* condition = static_cast<TObjArray*>(fConditions->At(0));
429  TString titles = "";
430 
431  TObjArray effMapList;
432  effMapList.SetOwner();
433 
434  AliTrigChEffOutput* trigOut = 0x0;
435  TIter next(fMergedOutputs);
436  while ( (trigOut = static_cast<AliTrigChEffOutput*>(next())) ) {
437  TList* effList = GetEffHistoList(trigOut, condition);
438  AliMUONTriggerEfficiencyCells* effMap = new AliMUONTriggerEfficiencyCells(effList);
439  effMapList.Add(effMap);
440  titles += Form("%s,",trigOut->GetName());
441  }
442  titles.Remove(TString::kTrailing,',');
443 
444  CompareEfficiencies(&effMapList, titles.Data(), opt, "MergedComp");
445 }
446 
447 
448 //________________________________________________________________________
449 //TArrayI AliMTRChEffAnalysis::CheckHomogeneity ( const TGraphAsymmErrors* trendGraph, Double_t nSigmas, Bool_t revert ) const
450 //{
451 // /// Check efficiency homogeneity
452 // TArrayI ranges(trendGraph->GetN());
453 // Double_t xpt=0., ypt=0.;
454 //
455 // Double_t sumEffOverSigma2 = -10.;
456 // Double_t sumInvSimga2 = 0.001;
457 // Int_t irange = 0;
458 // Int_t npt = trendGraph->GetN();
459 // for ( Int_t ipt=0; ipt<npt; ipt++ ) {
460 // Int_t currPt = ( revert ) ? npt-1-ipt : ipt;
461 // trendGraph->GetPoint(currPt,xpt,ypt);
462 // Double_t err = GetError(trendGraph->GetErrorYlow(currPt),trendGraph->GetErrorYhigh(currPt));
463 // Double_t invSigma2 = 1./(err*err);
464 // Double_t effOverSigma2 = ypt*invSigma2;
465 //
466 // Double_t meanEff = sumEffOverSigma2 / sumInvSimga2;
467 // Double_t diff = ypt - meanEff;
468 // Double_t diffErr = TMath::Sqrt(err*err+1./sumInvSimga2);
470 // if ( TMath::Abs(diff)/diffErr > nSigmas ) {
471 // TString run = trendGraph->GetXaxis()->GetBinLabel(currPt+1);
472 // ranges[irange++] = run.Atoi();
473 // sumEffOverSigma2 = 0.;
474 // sumInvSimga2 = 0.;
475 // }
476 // sumEffOverSigma2 += effOverSigma2;
477 // sumInvSimga2 += invSigma2;
478 // }
479 // TString run = trendGraph->GetXaxis()->GetBinLabel(trendGraph->GetN());
480 // ranges[irange++] = run.Atoi();
481 // ranges.Set(irange);
482 // return ranges;
483 //}
484 
485 //________________________________________________________________________
486 void AliMTRChEffAnalysis::CopyDir(TDirectory *source) const
487 {
489  TDirectory *savdir = gDirectory;
490  TDirectory *adir = savdir->mkdir(source->GetName());
491  adir->cd();
492  //loop on all entries of this directory
493  TKey *key;
494  TIter nextkey(source->GetListOfKeys());
495  while ((key = (TKey*)nextkey())) {
496  const char *classname = key->GetClassName();
497  TClass *cl = gROOT->GetClass(classname);
498  if (!cl) continue;
499  if (cl->InheritsFrom(TDirectory::Class())) {
500  source->cd(key->GetName());
501  TDirectory *subdir = gDirectory;
502  adir->cd();
503  CopyDir(subdir);
504  adir->cd();
505  } else if (cl->InheritsFrom(TTree::Class())) {
506  TTree *T = (TTree*)source->Get(key->GetName());
507  adir->cd();
508  TTree *newT = T->CloneTree(-1,"fast");
509  newT->Write();
510  } else {
511  source->cd();
512  TObject *obj = key->ReadObj();
513  adir->cd();
514  obj->Write(obj->GetName(),TObject::kSingleKey);
515  delete obj;
516  }
517  }
518  adir->SaveSelf(kTRUE);
519  savdir->cd();
520 }
521 
522 
523 //________________________________________________________________________
524 Bool_t AliMTRChEffAnalysis::CopyLocally ( const char* runList, const char* path, const char* pattern, const char* localFileList, const char* outDir, const char* directory ) const
525 {
527  TString sPattern(pattern);
528  TString sOutDir(outDir);
529  TString sPath(path);
530  Bool_t isGrid = (! sPattern.IsNull());
531 
532  if ( sOutDir.IsNull() ) {
533  if ( isGrid ) {
534  TString data = sPath(TRegexp("/data/"));
535  TString year = sPath(TRegexp("/20[0-9][0-9]/"));
536  TString period = sPath(TRegexp("/LHC[0-9][0-9][a-z]"));
537  period.Append("/");
538  // TPRegexp re("/(muon|pass).*?/");
539  TString pass = AliAnalysisMuonUtility::GetPassName(path);
540  if ( pass.IsNull() ) pass = AliAnalysisMuonUtility::GetPassName(pattern);
541  sOutDir = data+year+period+pass;
542  sOutDir.ReplaceAll("//","/");
543  sOutDir.Remove(TString::kTrailing,'/');
544  sOutDir.Remove(TString::kLeading,'/');
545  }
546  else sOutDir = sPath;
547  sOutDir.Remove(TString::kTrailing,'/');
548  sOutDir.Remove(TString::kLeading,'/');
549  }
550 
551  TGridResult* res = 0x0;
552  if ( isGrid ) {
553  if ( ! gGrid ) TGrid::Connect("alien://");
554  res = gGrid->Query(path,pattern);
555  }
556 
557  TList* rl = GetRunList(runList);
558 
559  ofstream outFile(localFileList);
560  Bool_t allOk = kTRUE;
561  Bool_t prompt = kTRUE;
562  Bool_t overwrite = kFALSE;
563  for ( Int_t irun=0; irun<rl->GetEntries(); irun++ ) {
564  TString run = static_cast<TObjString*>(rl->At(irun))->String();
565  TString dest = Form("%s/%09i/QAresults.root",sOutDir.Data(),run.Atoi());
566  TString destDir = gSystem->DirName(dest.Data());
567  if ( gSystem->AccessPathName(destDir.Data()) ) ExecCommand(Form("mkdir -p %s",destDir.Data()),kFALSE);
568  Bool_t copyFile = kTRUE;
569  Bool_t isFileOk = kTRUE;
570  if ( gSystem->AccessPathName(dest) == 0 ) {
571  if ( prompt ) {
572  TString decision = "";
573  cout << "Local file " << dest.Data() << " already exist: overwrite? [y/n/ya/na (a=use decision for all)]" << endl;
574  cin >> decision;
575  if ( decision.EndsWith("a") ) prompt = kFALSE;
576  if ( decision.BeginsWith("y") ) overwrite = kTRUE;
577  else overwrite = kFALSE;
578  }
579  copyFile = overwrite;
580  }
581  if ( copyFile ) {
582  TString src = "";
583  if ( isGrid ) {
584  for ( Int_t ifile=0; ifile<res->GetEntries(); ifile++ ) {
585  TString inFilename = res->GetKey(ifile,"turl");
586  if ( inFilename.Contains(run.Data()) ) {
587  src = inFilename;
588  break;
589  }
590  }
591  if ( src.IsNull() ) {
592  AliWarning(Form("Cannot find output for run %s",run.Data()));
593  isFileOk = kFALSE;
594  }
595  else {
596  TFile* outFile = TFile::Open(dest,"RECREATE");
597  TFile* inFile = TFile::Open(src);
598  inFile->cd();
599  TDirectory* dir = static_cast<TDirectory*>(inFile->Get(directory));
600  if ( dir ) {
601  outFile->cd();
602  CopyDir(dir);
603  }
604  else isFileOk = kFALSE;
605  delete inFile;
606  delete outFile;
607  }
608  }
609  else {
610  src = Form("http://aliqamu.web.cern.ch/aliqamu/%s",dest.Data());
611  isFileOk = TFile::Cp(src.Data(),dest.Data());
612  }
613  }
614 
615  if ( isFileOk ) outFile << gSystem->pwd() << "/" << dest.Data() << endl;
616  else allOk = kFALSE;
617  }
618  delete rl;
619  outFile.close();
620  return allOk;
621 }
622 
623 //________________________________________________________________________
624 void AliMTRChEffAnalysis::DrawEffTrend ( Int_t itype, Int_t irpc, Double_t maxNsigmaOutliers, Double_t minEff, Double_t maxEff ) const
625 {
627  TString baseNames[3] = {"Chamber","RPC","Board"};
628  TString base = baseNames[itype] + "Eff";
629  if ( itype == AliTrigChEffOutput::kHboardEff ) {
630  if ( irpc < 0 ) {
631  AliWarning("Please specify RPC");
632  return;
633  }
634  base += Form("InRPC%i",irpc);
635  }
636 
637  Int_t nColumns = 2;
638  Int_t nRows = 2;
639  Int_t width = 600;
640  Int_t height = 600;
641  Int_t nDetEl = 4;
642  Int_t nCh = 1;
643  if ( itype != AliTrigChEffOutput::kHchamberEff ) {
644  nColumns = 6;
645  nRows = 3;
646  width = 1200;
647  height = 800;
648  nDetEl = 18;
649  nCh = 4;
650  }
651  TArrayI boards = BoardsInRPC(irpc);
652  if ( itype == AliTrigChEffOutput::kHboardEff ) nDetEl = boards.GetSize();
653 
654  for ( Int_t ich=0; ich<nCh; ich++ ) {
655  TString canName = base;
656  if ( itype != AliTrigChEffOutput::kHchamberEff ) canName += Form("Ch%i",11+ich);
657  TCanvas* can = new TCanvas(canName.Data(),canName.Data(),25*ich,25*ich,width,height);
658  can->Divide(nColumns,nRows,0,0);
659  // can->SetTopMargin(0.03);
660  // can->SetBottomMargin(0.1);
661  for ( Int_t idetelem=0; idetelem<nDetEl; idetelem++ ) {
662  can->cd(idetelem+1);
663  gPad->SetTicks(1,1);
664  gPad->SetGridy();
665  Int_t detElemId = idetelem;
666  if ( itype == AliTrigChEffOutput::kHchamberEff ) detElemId = 11+idetelem;
667  else if ( itype == AliTrigChEffOutput::kHboardEff ) detElemId = boards[idetelem];
668 
669  TString title = Form("%s %i",baseNames[itype].Data(),detElemId);
670  TLegend* leg = new TLegend(0.2,0.15,0.8,0.4);
671  leg->SetHeader(title.Data());
672  for ( Int_t icount=0; icount<2; icount++ ) {
673  TGraphAsymmErrors* gr = GetTrendEff(itype, icount, ich, detElemId);
674  gr->SetLineColor(icount+1);
675  gr->SetMarkerColor(icount+1);
676  gr->SetMarkerStyle(24+2*icount);
677  gr->GetYaxis()->SetRangeUser(minEff,maxEff);
678  // gr->GetYaxis()->SetLabelSize(0.025*nRows);
679  // gr->GetXaxis()->SetLabelSize(0.025*nColumns);
680  gr->SetTitle("");
681  gr->Draw(icount==0?"ap":"p");
682  TString legTitle = ( icount==0 ) ? "bending plane" : "non-bending plane";
683  leg->AddEntry(gr,legTitle.Data(),"lp");
684  if ( maxNsigmaOutliers > 0. ) {
685  TGraphAsymmErrors* outliers = GetOutliers(gr,maxNsigmaOutliers);
686  outliers->SetLineColor(6+icount);
687  outliers->SetMarkerColor(6+icount);
688  outliers->SetMarkerStyle(20+2*icount);
689  outliers->SetLineWidth(2);
690  outliers->Draw("p");
691  legTitle.ReplaceAll("plane","outliers");
692  leg->AddEntry(outliers,legTitle.Data(),"lp");
693  }
694  }
695  leg->Draw();
696  }
697  if ( itype == AliTrigChEffOutput::kHchamberEff ) break;
698  }
699 }
700 
701 //________________________________________________________________________
702 void AliMTRChEffAnalysis::DrawStatContribution ( Int_t itype, Int_t irpc, Double_t maxNsigmaOutliers, Double_t minY, Double_t maxY ) const
703 {
705  if ( itype == AliTrigChEffOutput::kHchamberEff ) {
706  AliWarning("This function is valid only for itype 1 and 2");
707  return;
708  }
709 
710  TString baseNames[3] = {"Chamber","RPC","Board"};
711  TString base = baseNames[itype] + "Stat";
712  if ( itype == AliTrigChEffOutput::kHboardEff ) {
713  if ( irpc < 0 ) {
714  AliWarning("Please specify RPC");
715  return;
716  }
717  base += Form("InRPC%i",irpc);
718  }
719 
720  Int_t nColumns = 6;
721  Int_t nRows = 3;
722  Int_t width = 1200;
723  Int_t height = 800;
724  Int_t nDetEl = 18;
725  Int_t nCh = 1;
726 
727  TArrayI boards = BoardsInRPC(irpc);
728  if ( itype == AliTrigChEffOutput::kHboardEff ) nDetEl = boards.GetSize();
729 
730  for ( Int_t ich=0; ich<nCh; ich++ ) {
731  TH1* histos[nDetEl];
732  TH1* sumHistos = 0x0;
733  for ( Int_t idetelem=0; idetelem<nDetEl; idetelem++ ) {
734  Int_t detElemId = idetelem;
735  if ( itype == AliTrigChEffOutput::kHboardEff ) detElemId = boards[idetelem];
736  histos[idetelem] = GetTrend(itype, AliTrigChEffOutput::kAllTracks, ich, detElemId);
737  histos[idetelem]->SetName(Form("%s_stat",histos[idetelem]->GetName()));
738  histos[idetelem]->SetStats(0);
739  if ( sumHistos ) sumHistos->Add(histos[idetelem]);
740  else sumHistos = static_cast<TH1*>(histos[idetelem]->Clone("sumHistos"));
741  }
742 
743  TString canName = base; //Form("%sCh%i",base.Data(),11+ich);
744  TCanvas* can = new TCanvas(canName.Data(),canName.Data(),25*ich,25*ich,width,height);
745  can->Divide(nColumns,nRows,0,0);
746  for ( Int_t idetelem=0; idetelem<nDetEl; idetelem++ ) {
747  can->cd(idetelem+1);
748  gPad->SetTicks(1,1);
749  gPad->SetGridy();
750  Int_t detElemId = idetelem;
751  if ( itype == AliTrigChEffOutput::kHboardEff ) detElemId = boards[idetelem];
752  TString title = Form("%s %i",baseNames[itype].Data(),detElemId);
753  TLegend* leg = new TLegend(0.2,0.65,0.8,0.9);
754  leg->SetHeader(title.Data());
755  TGraphAsymmErrors* gr = new TGraphAsymmErrors(histos[idetelem],sumHistos,"e0");
756  gr->SetHistogram(static_cast<TH1F*>(histos[idetelem]));
757 
758  gr->SetMarkerStyle(24);
759  gr->SetMarkerSize(0.5);
760  gr->GetYaxis()->SetRangeUser(minY,maxY);
761  gr->GetYaxis()->SetTitle(Form("Tracks in %s / Sum of tracks of %ss in %s",baseNames[itype].Data(),baseNames[itype].Data(),baseNames[itype-1].Data()));
762  gr->SetTitle("");
763  gr->Draw("ap");
764  TString legTitle = "stat";
765 // leg->AddEntry(gr,legTitle.Data(),"lp");
766  if ( maxNsigmaOutliers > 0. ) {
767  TGraphAsymmErrors* outliers = GetOutliers(gr,maxNsigmaOutliers);
768  outliers->SetLineColor(6);
769  outliers->SetMarkerColor(6);
770  outliers->SetMarkerStyle(20);
771  outliers->SetLineWidth(2);
772  outliers->Draw("p");
773  legTitle = "outliers";
774  leg->AddEntry(outliers,legTitle.Data(),"lp");
775  }
776 // }
777  leg->Draw();
778  }
779  delete sumHistos;
780  }
781 }
782 
783 //________________________________________________________________________
784 Bool_t AliMTRChEffAnalysis::DrawSystematicEnvelope ( Bool_t perRPC ) const
785 {
787  if ( ! HasMergedResults() ) return kFALSE;
788 
789  Int_t colors[] = {kBlack, kRed, kSpring, kTeal, kBlue, kViolet, kMagenta, kOrange, kGray};
790  Int_t ncolors = sizeof(colors)/sizeof(colors[0]);
791 
792  Int_t itype = ( perRPC ) ? AliMUONTriggerEfficiencyCells::kHslatCount : AliMUONTriggerEfficiencyCells::kHboardCount;
793  Int_t countTypes[2] = {AliMUONTriggerEfficiencyCells::kBendingEff,AliMUONTriggerEfficiencyCells::kNonBendingEff};
794 
795  Int_t nConditions = fConditions->GetEntriesFast();
796 
797  TObjArray condTitle(nConditions);
798  condTitle.SetOwner();
799 
800  Double_t xpt, ypt, xref, yref;
801  TArrayD eff(4), effErr(4);
802 
803  AliTrigChEffOutput* trigOut = 0x0;
804  TIter next(fMergedOutputs);
805  Int_t imerged = -1;
806  while ( (trigOut = static_cast<AliTrigChEffOutput*>(next())) ) {
807  imerged++;
808 
809  // Get meaningful short titles for each systematic
810  if ( imerged == 0 ) GetShortConditionTitles(trigOut,condTitle);
811 
812  TArrayI isEmpty(nConditions);
813 
814  // First get the needed graphs
815  Int_t nDE = 0;
816  TObjArray effGraphs[8];
817  for ( Int_t iplane=0; iplane<8; iplane++ ) {
818  effGraphs[iplane].SetOwner();
819  }
820  TString titles = "";
821  TObjArray effMapList;
822  effMapList.SetOwner();
823  for ( Int_t icond=0; icond<nConditions; icond++ ) {
824  TObjArray* condition = static_cast<TObjArray*>(fConditions->UncheckedAt(icond));
825 
826  TList* effList = GetEffHistoList(trigOut, condition);
827  AliMUONTriggerEfficiencyCells* effMap = new AliMUONTriggerEfficiencyCells(effList);
828  effMapList.Add(effMap);
829  titles += Form("%s,",condTitle.At(icond)->GetName());
830 
831  for ( Int_t ich=0; ich<4; ich++ ) {
832  TString currName = effMap->GetHistoName(itype,AliMUONTriggerEfficiencyCells::kAllTracks,ich);
833  TH1* histoDen = static_cast<TH1*>(effMap->GetHistoList()->FindObject(currName.Data()));
834  for ( Int_t icount=0; icount<2; icount++ ) {
835  Int_t iplane = 4*icount+ich;
836 
837  if ( histoDen->GetEntries() > 0 ) {
838  currName = effMap->GetHistoName(itype,countTypes[icount],ich);
839  TH1* histoNum = static_cast<TH1*>(effMap->GetHistoList()->FindObject(currName.Data()));
840  TGraphAsymmErrors* gr = new TGraphAsymmErrors(histoNum,histoDen,"e0");
841  nDE = gr->GetN();
842  effGraphs[iplane].AddAtAndExpand(gr,icond);
843  }
844  else {
845  isEmpty[icond] = 1;
846  AliWarning(Form("No entries in count %i and ch %i for %s\n",icount,ich,condTitle.At(icond)->GetName()));
847  }
848  }
849  }
850  }
851 
852  titles.Remove(TString::kTrailing,',');
853  CompareEfficiencies(&effMapList, titles, "diff", trigOut->GetName());
854 
855  // Draw average dispersion per plane
856  TString canName = Form("EffSyst_%s",trigOut->GetName());
857  Int_t pos = 25*(imerged+1);
858  TCanvas* can = new TCanvas(canName.Data(),canName.Data(),pos,pos,1200,800);
859  can->Divide(4,2,0,0);
860 
861  for ( Int_t icount=0; icount<2; icount++ ) {
862  for ( Int_t ich=0; ich<4; ich++ ) {
863  Int_t iplane = 4*icount+ich;
864  can->cd(iplane+1);
865  gPad->SetTicks(1,1);
866  gPad->SetLogy();
867  TLegend* leg = new TLegend(0.15,0.7,0.9,0.9);
868  leg->SetHeader(trigOut->GetHistoName(-1,icount,ich,-1,-1,-1));
869  TH1* sumHisto = 0x0;
870  for ( Int_t icond=1; icond<nConditions; icond++ ) {
871  if ( isEmpty[icond] == 1 ) continue;
872  TH1* histo = new TH1D(Form("syst_%s_%s_plane%i_ch%i",trigOut->GetName(),condTitle[icond]->GetName(),icount,11+ich),"",200,-0.1,0.1);
873  histo->GetXaxis()->SetTitle("Eff.-(ref.Eff.)");
874  histo->GetYaxis()->SetTitle("1/#sigma^{2}");
875 
876  TGraphAsymmErrors* gr = static_cast<TGraphAsymmErrors*>(effGraphs[iplane].UncheckedAt(icond));
877  TGraphAsymmErrors* grRef = static_cast<TGraphAsymmErrors*>(effGraphs[iplane].UncheckedAt(0));
878  for ( Int_t ipt=0; ipt<gr->GetN(); ipt++ ) {
879  gr->GetPoint(ipt,xpt,ypt);
880  Double_t err = GetError(gr->GetErrorYlow(ipt),gr->GetErrorYhigh(ipt));
881  Double_t invErr2 = ( err > 0. ) ? 1./(err*err) : 0.;
882  grRef->GetPoint(ipt,xref,yref);
883 
884  Double_t diff = ypt-yref;
885  histo->Fill(diff,invErr2);
886  }
887 
888  if ( ! sumHisto ) {
889  sumHisto = static_cast<TH1*>(histo->Clone(Form("syst_%s_plane%i_ch%i",trigOut->GetName(),icount,11+ich)));
890  sumHisto->SetLineColor(1);
891  sumHisto->Draw();
892  leg->AddEntry(sumHisto,"All systematics","l");
893  }
894  else sumHisto->Add(histo);
895  Int_t icolor = ( icond < ncolors ) ? colors[icond] : 20+icond;
896  histo->SetLineColor(icolor);
897  histo->Draw("same");
898  leg->AddEntry(histo,condTitle[icond]->GetName(),"l");
899  } // loop on conditions
900  leg->Draw();
901  } // loop on chambers
902  } // loop on counts
903 
904 
905  canName = Form("TriggerEff_3outOf4_syst_%s",trigOut->GetName());
906  pos += 50;
907  TCanvas* canSyst = new TCanvas(canName.Data(),canName.Data(),pos,pos,600,600);
908  canSyst->SetLogy();
909  TLegend* leg = new TLegend(0.15,0.7,0.9,0.4);
910 // leg->SetHeader(trigOut->GetHistoName(-1,icount,ich,-1,-1,-1));
911  TH1* histo[nConditions];
912  for ( Int_t icond=0; icond<nConditions; icond++ ) {
913  if ( isEmpty[icond] == 1 ) continue;
914  histo[icond] = new TH1D(Form("TriggerEff_syst_%s_%s",condTitle[icond]->GetName(),trigOut->GetName()),"Dispersion of trigger probability (3/4)",200,-0.1,0.1);
915  histo[icond]->GetXaxis()->SetTitle("Trig. prob. - (ref. trig. prob)");
916  histo[icond]->GetYaxis()->SetTitle("1/#sigma^{2}");
917  }
918 
919  for ( Int_t ipt=0; ipt<nDE; ipt++ ) {
920  Double_t refTrigProb = 0.; // refTrigProbErr = 0.;
921  for ( Int_t icond=0; icond<nConditions; icond++ ) {
922  if ( isEmpty[icond] == 1 ) continue;
923  Double_t trigProb = 1., trigProbErr2 = 0.;
924  for ( Int_t icount=0; icount<2; icount++ ) {
925  for ( Int_t ich=0; ich<4; ich++ ) {
926  Int_t iplane = 4*icount+ich;
927  TGraphAsymmErrors* gr = static_cast<TGraphAsymmErrors*>(effGraphs[iplane].UncheckedAt(icond));
928  gr->GetPoint(ipt,xpt,ypt);
929  eff[ich] = ypt;
930  effErr[ich] = GetError(gr->GetErrorYlow(ipt),gr->GetErrorYhigh(ipt));
931  } // loop on chambers
932  Double_t effErr34 = 0.;
933  Double_t eff34 = GetThreeOfFour(eff,effErr,effErr34);
934  trigProb *= eff34;
935  trigProbErr2 += effErr34*effErr34;
936  } // loop on counts
937 
938  if ( icond == 0 ) {
939  refTrigProb = trigProb;
940 // refTrigProbErr = trigProbErr;
941  }
942  else {
943  Double_t invErr2 = ( trigProbErr2>0. ) ? 1./trigProbErr2 : 0.;
944  histo[icond]->Fill(trigProb-refTrigProb,invErr2);
945  }
946  } // loop on conditions
947  } // loop on points
948 
949  for ( Int_t icond=0; icond<nConditions; icond++ ) {
950  if ( isEmpty[icond] == 1 ) continue;
951  TString title = ( icond == 0 ) ? "All systematics" : condTitle[icond]->GetName();
952  Int_t icolor = ( icond < ncolors ) ? colors[icond] : 20+icond;
953  histo[icond]->SetLineColor(icolor);
954  histo[icond]->Draw((icond == 0)?"":"same");
955  leg->AddEntry(histo[icond],title.Data(),"l");
956  if ( icond>0 ) histo[0]->Add(histo[icond]);
957  }
958  leg->Draw();
959  } // loop on merged output
960  return kTRUE;
961 }
962 
963 //________________________________________________________________________
964 Bool_t AliMTRChEffAnalysis::ExecCommand ( TString command, Bool_t prompt ) const
965 {
967  TString decision = "y";
968 
969  if ( gROOT->IsBatch() ) prompt = kFALSE; // To run with crontab
970 
971  if ( prompt ) {
972  cout << command.Data() << " ? [y/n]" << endl;
973  cin >> decision;
974  }
975 
976  decision.ToLower();
977  if ( decision == "y" ) {
978  cout << "Executing: " << command.Data() << endl;
979  gSystem->Exec(command.Data());
980  return kTRUE;
981  }
982 
983  return kFALSE;
984 }
985 
986 //________________________________________________________________________
987 Double_t AliMTRChEffAnalysis::FitRangesFunc ( Double_t* x, Double_t* par )
988 {
995 
996  Double_t xx = x[0];
997  Double_t val = par[1];
998  Int_t nChanges = par[0];
999  Double_t matchDiff = 123456789.;
1000  Int_t matchChange = -1;
1001  for ( Int_t iknot=0; iknot<nChanges; iknot++ ) {
1002  Int_t iparChange = 2*(iknot+1);
1003  Double_t diff = xx - par[iparChange];
1004  if ( diff >= 0. && diff < matchDiff ) {
1005  matchDiff = diff;
1006  matchChange = iparChange;
1007  }
1008  }
1009  if ( matchChange >= 0 ) val = par[matchChange+1];
1010 
1011  return val;
1012 }
1013 
1014 //________________________________________________________________________
1015 Double_t AliMTRChEffAnalysis::GetAverageStat ( Int_t firstRun, Int_t lastRun, Int_t itype,Bool_t excludePeriphericBoard ) const
1016 {
1017  TH1* statHisto = 0x0;
1018 
1019  UInt_t uFirstRun = (UInt_t)firstRun;
1020  UInt_t uLastRun = (UInt_t)lastRun;
1021 
1022  TIter next(fOutputs);
1023  TList* effHistoList = 0x0;
1024  while ( (effHistoList = static_cast<TList*>(next()) ) ) {
1025  UInt_t run = effHistoList->GetUniqueID();
1026  if ( run < uFirstRun || run > uLastRun ) continue;
1027  TH1* histo = GetHisto(effHistoList,itype,AliTrigChEffOutput::kAllTracks,0);
1028 // if ( ! histo ) continue;
1029  if ( statHisto ) statHisto->Add(histo);
1030  else statHisto = static_cast<TH1*>(histo->Clone("tmpStatHisto"));
1031 // delete histo;
1032  }
1033  if ( ! statHisto ) return 0.;
1034 
1035  Double_t statPerDE = 0.;
1036  Double_t nDe = 0.;
1037  if ( itype == AliTrigChEffOutput::kHboardEff && excludePeriphericBoard ) {
1038  Int_t excludeBoardsHalf[] = {1, 17, 39, 61, 77, 93,109,
1039  16, 38, 60, 76, 92, 108, 117,
1040  110, 111, 112, 113, 114, 115, 116};
1041  Int_t nExcludedHalf = sizeof(excludeBoardsHalf)/sizeof(excludeBoardsHalf[0]);
1042  for ( Int_t ibin=1; ibin<=statHisto->GetNbinsX(); ibin++ ) {
1043  Bool_t skip = kFALSE;
1044  for ( Int_t iexcl=0; iexcl<nExcludedHalf; iexcl++ ) {
1045  if ( ibin == excludeBoardsHalf[iexcl] || ibin == excludeBoardsHalf[iexcl]+117 ) {
1046  skip = kTRUE;
1047  break;
1048  }
1049  }
1050  if ( skip ) continue;
1051  statPerDE += statHisto->GetBinContent(ibin);
1052  nDe += 1.;
1053  }
1054  }
1055  else {
1056  statPerDE = statHisto->Integral();
1057  nDe = (Double_t)statHisto->GetNbinsX();
1058  }
1059  statPerDE = nDe > 0. ? statPerDE/nDe : -1.;
1060 
1061  delete statHisto;
1062  return statPerDE;
1063 }
1064 
1065 //________________________________________________________________________
1066 TList* AliMTRChEffAnalysis::GetEffHistoList ( AliTrigChEffOutput* trigOut, TObjArray* condition ) const
1067 {
1069  Int_t itrackSel = static_cast<TObjString*>(condition->At(3))->String().Atoi();
1070  Int_t imatch = static_cast<TObjString*>(condition->At(4))->String().Atoi();
1071  Int_t imethod = static_cast<TObjString*>(condition->At(5))->String().Atoi();
1072 
1073  return trigOut->GetEffHistoList(condition->At(0)->GetName(),condition->At(1)->GetName(),condition->At(2)->GetName(),itrackSel,imatch,imethod);
1074 }
1075 
1076 //________________________________________________________________________
1077 Double_t AliMTRChEffAnalysis::GetError ( Double_t errLow, Double_t errHigh ) const
1078 {
1080  return TMath::Max(errLow,errHigh);
1081 }
1082 
1083 //________________________________________________________________________
1084 TH1* AliMTRChEffAnalysis::GetHisto ( TList* effHistoList, Int_t itype, Int_t icount, Int_t ichamber ) const
1085 {
1087  Int_t ihisto = ( itype == AliTrigChEffOutput::kHchamberEff ) ? icount : AliTrigChEffOutput::kNcounts + 4*AliTrigChEffOutput::kNcounts*(itype-1) + 4*icount + ichamber;
1088  return static_cast<TH1*>(effHistoList->At(ihisto));
1089 }
1090 
1091 //________________________________________________________________________
1092 TArrayI AliMTRChEffAnalysis::GetHomogeneousRanges ( Double_t chi2Cut, Int_t maxNRanges, Double_t minEffVariation, Bool_t perRPC, TArrayI* forcedChanges, Double_t minEff, Double_t maxEff )
1093 {
1095 
1096  Int_t nRuns = fOutputs->GetEntriesFast();
1097 
1098  TH1F* hRunChangeCount = new TH1F("runChangeCount","Number of RPCs changing efficiency per run",nRuns,-0.5,-0.5+(Double_t)nRuns);
1099  hRunChangeCount->SetXTitle("Run num.");
1100  hRunChangeCount->SetYTitle("Num. of RPCs with change in eff.");
1101  for ( Int_t irun=0; irun<nRuns; irun++ ) {
1102  hRunChangeCount->GetXaxis()->SetBinLabel(irun+1,Form("%i",GetRunNumber(irun)));
1103  }
1104 
1106 
1107  Int_t nCanvas = perRPC ? 4 : 18;
1108  TObjArray canList(nCanvas);
1109 
1110  for ( Int_t irpc=0; irpc<18; irpc++ ) {
1111  Int_t icount = AliTrigChEffOutput::kBothPlanesEff;
1112  TArrayI boards = BoardsInRPC(irpc);
1113  Int_t firstDetEl = perRPC ? irpc : 0;
1114  Int_t lastDetEl = perRPC ? irpc : boards.GetSize()-1;
1115 
1116  for ( Int_t ich=0; ich<4; ich++ ) {
1117  Int_t ican = perRPC ? ich : irpc;
1118  TCanvas* can = static_cast<TCanvas*>(canList.At(ican));
1119  if ( ! can ) {
1120  TString canName = perRPC ? Form("testRanges_ch%i",11+ich) : Form("testRanges_RPC%i",irpc);
1121  can = new TCanvas(canName.Data(),canName.Data(),10*ich,10*ich,1200,800);
1122  can->Divide(6,3,0,0);
1123  can->SetMargin(0.,0.,0.,0.);
1124  canList.AddAt(can,ican);
1125  }
1126 
1127  for ( Int_t idetel=firstDetEl; idetel<=lastDetEl; idetel++ ) {
1128  Int_t currDE = ( perRPC ) ? idetel : boards[idetel];
1129 // for ( Int_t icount=0; icount<2; icount++ ) {
1130  TGraphAsymmErrors* trendGraph = GetTrendEff(itype,icount,ich,currDE);
1131  TArrayI range = GetHomogeneousRanges(trendGraph,chi2Cut,maxNRanges,minEffVariation,forcedChanges, kTRUE);
1132  trendGraph->GetYaxis()->SetRangeUser(minEff,maxEff);
1133 
1134  can->cd(idetel+1);
1135  gPad->SetTicks(1,1);
1136  gPad->SetMargin(0.08,0.,0.08,0.);
1137  TString drawOpt = ( gPad->GetListOfPrimitives()->GetEntries() == 0 ) ? "ap" : "p";
1138 
1139  TString legendName = Form("%s_%i",can->GetName(),currDE);
1140  TLegend* leg = static_cast<TLegend*>(gPad->GetListOfPrimitives()->FindObject(legendName.Data()));
1141  if ( ! leg ) {
1142  leg = new TLegend(0.2,0.15,0.8,0.4);
1143  leg->SetHeader(Form("%s %i",perRPC?"RPC":"Board",currDE));
1144  leg->SetName(legendName.Data());
1145  }
1146 
1147  if ( ! perRPC ) {
1148  Int_t icolor = ich+1;
1149  trendGraph->SetLineColor(icolor);
1150  trendGraph->SetMarkerColor(icolor);
1151  trendGraph->SetMarkerStyle(24+ich);
1152  TF1* func = static_cast<TF1*>(trendGraph->GetListOfFunctions()->At(0));
1153  if ( func ) {
1154  func->SetLineWidth(2);
1155  func->SetLineColor(icolor);
1156  }
1157  }
1158  trendGraph->GetXaxis()->SetLabelSize(0.07);
1159  trendGraph->SetTitle("");
1160 
1161  trendGraph->Draw(drawOpt.Data());
1162  leg->AddEntry(trendGraph,Form("Chamber %i",11+ich),"lp");
1163  leg->Draw();
1164  for ( Int_t ichange=2; ichange<range.GetSize(); ichange++ ) {
1165  // Store only the run when the change applies
1166  if ( ichange%2 == 1 ) continue;
1167  Int_t runIdx = range[ichange];
1168 // if ( ichange != 0 ) {
1169  TLine* line = new TLine(runIdx,minEff,runIdx,maxEff);
1170  line->SetLineStyle(2);
1171  line->Draw("same");
1172  TLatex text;
1173  text.DrawLatex((Double_t)(runIdx-3),maxEff-0.1*(maxEff-minEff)*(Double_t)(ichange/2),Form("%i",GetRunNumber(runIdx)));
1174 // }
1175  hRunChangeCount->Fill(runIdx);
1176  if ( hRunChangeCount->GetBinContent(runIdx+1) == 1 ) {
1177  TString infoMsg = Form("Efficiency change in %i triggered by ch %i RPC %i",GetRunNumber(runIdx),11+ich,irpc);
1178  if ( ! perRPC ) infoMsg += Form(" Board %i",currDE);
1179  AliInfo(infoMsg.Data());
1180  }
1181  } // loop on change
1182  } // loop on detection element
1183 // }
1184  } // loop on chambers
1185  } // loop on RPC
1186 
1187  // Clusterize contiguous runs
1188  TArrayI runChangeClust(nRuns);
1189  Double_t sumWgtRun = 0.;
1190  Double_t sumWgt = 0;
1191  for ( Int_t irun=0; irun<=nRuns; irun++ ) {
1192  if ( irun == nRuns || hRunChangeCount->GetBinContent(irun+1) == 0 ) {
1193  if ( sumWgt > 0. ) {
1194  Int_t averageRun = TMath::Nint(sumWgtRun / sumWgt);
1195  AliDebug(2,Form("Average run: %i => %i\n",averageRun,GetRunNumber(averageRun)));
1196  runChangeClust[averageRun]++;
1197  sumWgtRun = 0.;
1198  sumWgt = 0.;
1199  }
1200  }
1201  if ( irun == nRuns ) break;
1202 
1203  AliDebug(2,Form("irun %i => %i: wgt %g",irun,GetRunNumber(irun),hRunChangeCount->GetBinContent(irun+1)));
1204 
1205 // Double_t wgt = (Double_t)runChangeCount[irun];
1206  Double_t wgt = hRunChangeCount->GetBinContent(irun+1);
1207  if ( forcedChanges ) {
1208  for ( Int_t ichange=0; ichange<forcedChanges->GetSize(); ichange++ ) {
1209  if ( GetRunNumber(irun) == forcedChanges->At(ichange) ) wgt *= 10.;
1210  }
1211  }
1212  sumWgtRun += wgt*(Double_t)irun;
1213  sumWgt += wgt;
1214  }
1215 
1216  TCanvas* summaryCan = new TCanvas("effChangeSummary","effChangeSummary",50,50,600,600);
1217  summaryCan->SetLogy();
1218  hRunChangeCount->GetXaxis()->LabelsOption("v");
1219  hRunChangeCount->Draw();
1220 
1221  Int_t ientry = 0;
1222  TArrayI runRanges(nRuns);
1223  runRanges[ientry++] = GetRunNumber(0);
1224  for ( Int_t irun=1; irun<nRuns; irun++ ) {
1225  if ( runChangeClust[irun] > 0 ) {
1226  runRanges[ientry++] = GetRunNumber(irun-1);
1227  runRanges[ientry++] = GetRunNumber(irun);
1228  }
1229  }
1230  runRanges[ientry++] = GetRunNumber(nRuns-1);
1231  runRanges.Set(ientry);
1232  return runRanges;
1233 }
1234 
1235 //________________________________________________________________________
1236 TArrayI AliMTRChEffAnalysis::GetHomogeneousRanges ( TGraphAsymmErrors* trendGraph, Double_t chi2Cut, Int_t maxNRanges, Double_t minEffVariation, TArrayI* forcedChanges, Bool_t returnIndex )
1237 {
1239 
1240  TArrayI runRanges;
1241  TF1* func = 0x0;
1242  TArrayD forcedChangesBin;
1243  Int_t nForced = 0;
1244  if ( forcedChanges ) {
1245  forcedChangesBin.Set(forcedChanges->GetSize());
1246  for ( Int_t ichange=0; ichange<forcedChanges->GetSize(); ichange++ ) {
1247  Int_t idx = GetIndexFromRun(forcedChanges->At(ichange));
1248  if ( idx >= 0 ) forcedChangesBin[nForced++] = (Double_t)idx;
1249  else AliWarning(Form("Cannot find run %i\n",forcedChanges->At(ichange)));
1250  }
1251  }
1252 
1253  Double_t minNormChi2 = 123456789.;
1254  Int_t minNormChi2Step = -1;
1255  TString fitOpt = "NQ0";
1256 // Double_t fakeVal = -999.;
1257 // TArrayD params(2*maxNRanges);
1258 // params.Reset(fakeVal);
1259 
1260  for ( Int_t istep=0; istep<maxNRanges; istep++ ) {
1261  Int_t nPars = 2*(istep+1);
1262  Double_t xMin = trendGraph->GetXaxis()->GetXmin();
1263  Double_t xMax = trendGraph->GetXaxis()->GetXmax();
1264  func = new TF1("rangeFunc",this,&AliMTRChEffAnalysis::FitRangesFunc,xMin,xMax,nPars,"AliMTRChEffAnalysis","FitRanges");
1265  func->FixParameter(0,istep);
1266  for ( Int_t ipar=1; ipar<nPars; ipar++ ) {
1267 // if ( ipar >= 2*istep ) {
1268 // if ( TMath::Abs(params[ipar]-fakeVal) < 0.01 ) {
1269 // if ( ipar%2 == 1 ) params[ipar] = 0.95;
1270 // else params[ipar] = (xMax-xMin) * (Double_t)(ipar/2)/((Double_t)(istep+1));
1271 // }
1272 // func->SetParameter(ipar,params[ipar]);
1273  Double_t val = ( ipar%2 == 1 ) ? 0.95 : (xMax-xMin) * (Double_t)(ipar/2)/((Double_t)(istep+1));
1274  func->SetParameter(ipar,val);
1275  if ( ipar%2 == 0 ) func->SetParLimits(ipar,xMin,xMax);
1276  }
1277 
1278  TFitResultPtr fitResult = trendGraph->Fit(func,fitOpt.Data());
1279  // If fit converges close to a point where a break is forced
1280  // fix parameters and redo the fit
1281  if ( forcedChanges ) {
1282  Bool_t hasFixedPars = kFALSE;
1283  for ( Int_t iforced=0; iforced<nForced; iforced++ ) {
1284  for ( Int_t jstep=0; jstep<istep; jstep++ ) {
1285  Int_t ipar = 2*(jstep+1);
1286  if ( TMath::Abs(forcedChangesBin[iforced]-func->GetParameter(ipar)) > 2. ) continue;
1287  func->FixParameter(ipar,forcedChangesBin[iforced]);
1288  hasFixedPars = kTRUE;
1289  }
1290  }
1291  if ( hasFixedPars ) fitResult = trendGraph->Fit(func,fitOpt.Data());
1292  }
1293 
1294 // for ( Int_t ipar=1; ipar<nPars; ipar++ ) {
1295 // params[ipar] = func->GetParameter(ipar);
1296 // }
1297 
1298  Double_t normChi2 = func->GetChisquare() / ((Double_t)func->GetNDF());
1299  if ( normChi2 < minNormChi2 ) {
1300  minNormChi2 = normChi2;
1301  minNormChi2Step = istep;
1302  }
1303 // if ( static_cast<int>(fitResult) == 0 && normChi2 < chi2Cut ) break;
1304  if ( normChi2 < chi2Cut ) break; // REMEMBER TO CHECK
1305  delete func;
1306  func = 0x0;
1307  }
1308 
1309  if ( func ) {
1310  trendGraph->GetListOfFunctions()->Add(func->Clone());
1311  Int_t nSteps = (Int_t)func->GetParameter(0);
1312 
1313  // The runs for which the efficiency changes could be unsorted
1314  // (when forced values are requires)
1315  // Copy the parameters in arrays to sort them
1316  Int_t nPoints = nSteps+1;
1317  TArrayD parRunIdx(nPoints);
1318  TArrayD parEff(nPoints);
1319  for ( Int_t ipar=0; ipar<func->GetNpar(); ipar++ ) {
1320  Int_t istep = ipar/2;
1321  if ( ipar%2 == 0 ) parRunIdx[istep] = func->GetParameter(ipar);
1322  else parEff[istep] = func->GetParameter(ipar);
1323  }
1324  parRunIdx[0] = 0.;
1325  TArrayI sortIdx(nPoints);
1326  TMath::Sort(nPoints,parRunIdx.GetArray(),sortIdx.GetArray(),kFALSE);
1327 
1328  runRanges.Set(2*nPoints);
1329  Int_t irun = 0;
1330  runRanges[irun++] = returnIndex ? 0 : GetRunNumber(0);
1331  for ( Int_t ipoint=1; ipoint<nPoints; ipoint++ ) {
1332  Double_t deltaEff = TMath::Abs(parEff[sortIdx[ipoint]]-parEff[sortIdx[ipoint-1]]);
1333 // if ( ipoint>=2 ) deltaEff = TMath::Max(deltaEff,TMath::Abs(parEff[sortIdx[ipoint]]-parEff[sortIdx[ipoint-2]]));
1334  if ( deltaEff < minEffVariation ) {
1335  AliWarning(Form("Efficiency variation for %s is %g => consider uniform",trendGraph->GetName(),deltaEff));
1336  continue;
1337  }
1338  Int_t runChangeIdx = TMath::Nint(parRunIdx[sortIdx[ipoint]]);
1339  AliDebug(1,Form("Change run: %s => %g => %i %i",trendGraph->GetName(),parRunIdx[sortIdx[ipoint]],runChangeIdx,GetRunNumber(runChangeIdx)));
1340  runRanges[irun++] = returnIndex ? runChangeIdx-1 : GetRunNumber(runChangeIdx-1);
1341  runRanges[irun++] = returnIndex ? runChangeIdx : GetRunNumber(runChangeIdx);
1342  }
1343  Int_t lastPt = trendGraph->GetN()-1;
1344  runRanges[irun++] = returnIndex ? lastPt : GetRunNumber(lastPt);
1345  runRanges.Set(irun);
1346  }
1347  else {
1348  AliWarning(Form("Fit did not converge for %s (minimum chi2 %g for step %i)",trendGraph->GetName(),minNormChi2,minNormChi2Step));
1349  }
1350  return runRanges;
1351 }
1352 
1353 //________________________________________________________________________
1354 TString AliMTRChEffAnalysis::GetIdentifier ( AliTrigChEffOutput* trigOut, TObjArray* condition, Int_t itype, Int_t icount, Int_t ichamber ) const
1355 {
1357 // AliTrigChEffOutput* trigOut = static_cast<AliTrigChEffOutput*>(fOutputs->At(0));
1358 // if ( ! trigOut ) {
1359 // AliWarning("No output object found!");
1360 // delete arr;
1361 // return "";
1362 // }
1363  TString identifier = Form("/%s/%s/%s/",condition->At(0)->GetName(),condition->At(1)->GetName(),condition->At(2)->GetName());
1364  Int_t itrackSel = static_cast<TObjString*>(condition->At(3))->String().Atoi();
1365  Int_t imatch = static_cast<TObjString*>(condition->At(4))->String().Atoi();
1366  Int_t imethod = static_cast<TObjString*>(condition->At(5))->String().Atoi();
1367  TString objName = trigOut->GetHistoName(itype, icount, ichamber, itrackSel, imatch, imethod);
1368  identifier += objName;
1369  return identifier;
1370 }
1371 
1372 //________________________________________________________________________
1373 Int_t AliMTRChEffAnalysis::GetIndexFromRun ( UInt_t runNumber ) const
1374 {
1376  for ( Int_t ipt=0; ipt<fOutputs->GetEntriesFast(); ipt++ ) {
1377  UInt_t run = fOutputs->UncheckedAt(ipt)->GetUniqueID();
1378  if ( run == runNumber ) return ipt;
1379  }
1380  return -1;
1381 }
1382 
1383 //________________________________________________________________________
1384 TGraphAsymmErrors* AliMTRChEffAnalysis::GetOutliers ( TGraphAsymmErrors* graph, Double_t maxNsigmas ) const
1385 {
1387 // TGraphAsymmErrors* outliers = new TGraphAsymmErrors();
1388  TGraphAsymmErrors* outliers = new TGraphAsymmErrors(*graph);
1389  outliers->SetHistogram(static_cast<TH1F*>(graph->GetHistogram()->Clone(Form("%s_outliers",graph->GetHistogram()->GetName()))));
1390 // outliers->SetLineColor(graph->GetLineColor()+1);
1391  if ( graph->GetListOfFunctions()->GetEntries() == 0 ) graph->Fit("pol0","Q0");
1392  TF1* func = static_cast<TF1*>(graph->GetListOfFunctions()->At(0));
1393 
1394  Double_t xpt, ypt;
1395  Int_t nremoved = 0;
1396  for ( Int_t ipt=0; ipt<graph->GetN(); ipt++ ) {
1397  graph->GetPoint(ipt,xpt,ypt);
1398  Double_t diff = ypt - func->Eval(xpt);
1399  Double_t err = ( diff > 0. ) ? graph->GetErrorYlow(ipt) : graph->GetErrorYhigh(ipt);
1400  if ( err < 0. || TMath::Abs(diff)/err > maxNsigmas ) continue;
1401  outliers->RemovePoint(ipt-nremoved);
1402  nremoved++;
1403 // outliers->SetPoint(iopt,xpt,ypt);
1404  }
1405  return outliers;
1406 }
1407 
1408 //________________________________________________________________________
1409 Int_t AliMTRChEffAnalysis::GetRunNumber ( Int_t ipt ) const
1410 {
1412  if ( ipt < 0 || ipt >= fOutputs->GetEntriesFast() ) return -1;
1413  return fOutputs->UncheckedAt(ipt)->GetUniqueID();
1414 }
1415 
1416 //________________________________________________________________________
1417 TList* AliMTRChEffAnalysis::GetRunList ( const char* runList ) const
1418 {
1420  TList* rl = new TList;
1421  rl->SetOwner();
1422  TString sRunList = gSystem->ExpandPathName(runList);
1423  if ( gSystem->AccessPathName(sRunList) || sRunList.EndsWith(".root") ) {
1424  sRunList.ReplaceAll(","," ");
1425  if ( sRunList.IsDigit() ) {
1426  TObjArray* arr = sRunList.Tokenize(" ");
1427  for ( Int_t iarr=0; iarr<arr->GetEntries(); iarr++ ) {
1428  rl->Add(new TObjString(arr->At(iarr)->GetName()));
1429  }
1430  delete arr;
1431  }
1432  }
1433  else {
1434  ifstream inFile(sRunList.Data());
1435  TString currLine = "";
1436  while ( ! inFile.eof() ) {
1437  currLine.ReadLine(inFile);
1438  TString currRun = AliAnalysisMuonUtility::GetRunNumberAsString(currLine);
1439  if ( ! currRun.IsNull() ) rl->Add(new TObjString(currRun));
1440  }
1441  inFile.close();
1442  }
1443  rl->Sort();
1444  return rl;
1445 }
1446 
1447 //________________________________________________________________________
1448 Bool_t AliMTRChEffAnalysis::GetShortConditionTitles ( AliTrigChEffOutput* trigOut, TObjArray& condTitles ) const
1449 {
1451 
1452  Int_t nConditions = fConditions->GetEntriesFast();
1453  TObjArray* refCondition = 0x0;
1454 
1455  for ( Int_t icond=0; icond<nConditions; icond++ ) {
1456  TObjArray* condition = static_cast<TObjArray*>(fConditions->UncheckedAt(icond));
1457  TString title = "";
1458  if ( icond == 0 ) {
1459  refCondition = condition;
1460  title = condition->GetName();
1461  }
1462  for ( Int_t ic=0; ic<condition->GetEntriesFast(); ic++ ) {
1463  TString currCond = static_cast<TObjString*>(condition->UncheckedAt(ic))->String();
1464  TString refCond = static_cast<TObjString*>(refCondition->UncheckedAt(ic))->String();
1465  if ( currCond == refCond ) continue;
1466  TString add = currCond;
1467  if ( ic == 3 ) add = trigOut->GetHistoName(-1,-1,-1,currCond.Atoi(),-1,-1);
1468  else if ( ic == 4 ) add = trigOut->GetHistoName(-1,-1,-1,-1,currCond.Atoi(),-1);
1469  else if ( ic == 5 ) add = trigOut->GetHistoName(-1,-1,-1,-1,-1,currCond.Atoi());
1470  title += Form("_%s",add.Data());
1471  }
1472  title.Remove(TString::kLeading,'_');
1473  title.ReplaceAll(",","|");
1474  condTitles.AddAt(new TObjString(title),icond);
1475  }
1476 
1477  return kTRUE;
1478 }
1479 
1480 //________________________________________________________________________
1481 TH1* AliMTRChEffAnalysis::GetSum ( AliTrigChEffOutput* trigOut, TObjArray* condition, Int_t itype, Int_t icount, Int_t ichamber ) const
1482 {
1484  Int_t itrackSel = static_cast<TObjString*>(condition->At(3))->String().Atoi();
1485  Int_t imatch = static_cast<TObjString*>(condition->At(4))->String().Atoi();
1486  Int_t imethod = static_cast<TObjString*>(condition->At(5))->String().Atoi();
1487  TString objName = trigOut->GetHistoName(itype, icount, ichamber, itrackSel, imatch, imethod);
1488  return static_cast<TH1*>(trigOut->GetSum(condition->At(0)->GetName(),condition->At(1)->GetName(),condition->At(2)->GetName(),objName));
1489 }
1490 
1491 //________________________________________________________________________
1492 TH1* AliMTRChEffAnalysis::GetTrend ( Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem ) const
1493 {
1495  if ( itype == AliTrigChEffOutput::kHchamberEff ) {
1496  if ( idetelem < 0 && ichamber >=0 ) idetelem = 11+ichamber;
1497  }
1498  TH1* outHisto = 0x0;
1499 
1500  TIter next(fOutputs);
1501  TList* effHistoList = 0x0;
1502  Int_t ibin = 0;
1503  while ( (effHistoList = static_cast<TList*>(next()) ) ) {
1504  ibin++;
1505 // TString identifier = GetIdentifier(trigOut,condition,itype,icount,ichamber);
1506  if ( ! outHisto ) {
1507 // TString outName = identifier;
1508  TString outName = Form("histo_type%i_count%i_ch%i_",itype,icount,11+ichamber);
1509 // outName.ReplaceAll("/","_");
1510  outName += Form("%i_trend",idetelem);
1511  outHisto = new TH1D(outName.Data(),outName.Data(),fOutputs->GetEntriesFast(),0.,(Double_t)fOutputs->GetEntriesFast());
1512  outHisto->SetDirectory(0);
1513  outHisto->GetXaxis()->SetTitle("Run num.");
1514  }
1515  UInt_t run = effHistoList->GetUniqueID();
1516  outHisto->GetXaxis()->SetBinLabel(ibin,Form("%u",run));
1517  TH1* histo = GetHisto(effHistoList,itype,icount,ichamber);
1518  Int_t currBin = histo->GetXaxis()->FindBin(idetelem);
1519  outHisto->SetBinContent(ibin,histo->GetBinContent(currBin));
1520  outHisto->SetBinError(ibin,histo->GetBinError(currBin));
1521  }
1522  if ( outHisto ) outHisto->GetXaxis()->LabelsOption("v");
1523  return outHisto;
1524 }
1525 
1526 //________________________________________________________________________
1527 TGraphAsymmErrors* AliMTRChEffAnalysis::GetTrendEff ( Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem ) const
1528 {
1530  if ( icount == AliTrigChEffOutput::kAllTracks ) {
1531  AliWarning("Chose either bending plane, non-bending plane or both planes");
1532  return NULL;
1533  }
1534  TH1* histoNum = GetTrend(itype,icount,ichamber,idetelem);
1535  TH1* histoDen = GetTrend(itype,AliTrigChEffOutput::kAllTracks,ichamber,idetelem);
1536  TGraphAsymmErrors* graph = new TGraphAsymmErrors(histoNum,histoDen,"e0");
1537  histoNum->Reset();
1538  histoNum->SetStats(kFALSE);
1539  graph->SetHistogram(static_cast<TH1F*>(histoNum));
1540  graph->GetYaxis()->SetTitle("Efficiency");
1541  graph->SetMarkerSize(0.5);
1542 // for ( Int_t ibin=1; ibin<=histoNum->GetXaxis()->GetNbins(); ibin++ ) {
1543 // graph->GetXaxis()->SetBinLabel(ibin,histoNum->GetXaxis()->GetBinLabel(ibin));
1544 // }
1545 // delete histoNum;
1546  delete histoDen;
1547  return graph;
1548 }
1549 
1550 //________________________________________________________________________
1551 Double_t AliMTRChEffAnalysis::GetThreeOfFour ( TArrayD eff, TArrayD effErr, Double_t &probErr ) const
1552 {
1554  Double_t binomialEff = 0.;
1555  Double_t sumErr2 = 0.;
1556  for ( Int_t jch=-1; jch<4; jch++ ) {
1557  Double_t prodEff = 1.;
1558  Double_t prodErr2 = 0.;
1559  for ( Int_t ich=0; ich<4; ich++ ) {
1560  Double_t currEff = ( ich == jch ) ? 1.-eff[ich] : eff[ich];
1561  prodEff *= currEff;
1562  Double_t relErr = ( currEff>0. ) ? effErr[ich]/currEff : 0.;
1563  prodErr2 += relErr*relErr;
1564  }
1565  binomialEff += prodEff;
1566  sumErr2 += prodEff*prodEff*prodErr2;
1567  }
1568  probErr = TMath::Sqrt(sumErr2);
1569  return binomialEff;
1570 }
1571 
1572 //________________________________________________________________________
1574 {
1576  if ( ! fMergedOutputs || fMergedOutputs->IsEmpty() ) {
1577  AliError("You first need to merge efficiency objects with MergeOutput");
1578  return kFALSE;
1579  }
1580  return kTRUE;
1581 }
1582 
1583 //________________________________________________________________________
1584 Bool_t AliMTRChEffAnalysis::MergeOutput ( TArrayI runRanges, Double_t averageStatError, Bool_t isIndex )
1585 {
1587 
1588  if ( runRanges.GetSize()%2 == 1 ) {
1589  AliError("Run ranges expected in the form: start_period1,end_period1,start_period2,end_period2... => even number expected");
1590  return kFALSE;
1591  }
1592 
1593  TArrayI mergedRanges = MergeRangesForStat(runRanges, averageStatError);
1594 
1595  Int_t nRanges = mergedRanges.GetSize()/2;
1596 
1597 
1598  if ( fMergedOutputs ) fMergedOutputs->Delete();
1599  else {
1600  fMergedOutputs = new TObjArray(nRanges);
1601  fMergedOutputs->SetOwner();
1602  }
1603 
1604  TList* effHistoList = 0x0;
1605  for ( Int_t irange=0; irange<nRanges; irange++ ) {
1606  Int_t firstRun = mergedRanges[2*irange];
1607  Int_t lastRun = mergedRanges[2*irange+1];
1608  if ( isIndex ) {
1609  firstRun = GetRunNumber(firstRun);
1610  lastRun = GetRunNumber(lastRun);
1611  }
1612  UInt_t uFirstRun = (UInt_t)firstRun;
1613  UInt_t uLastRun = (UInt_t)lastRun;
1614 
1615  TString filename = "";
1616 
1617  TIter next(fOutputs);
1618  TFileMerger fileMerger;
1619  while ( (effHistoList = static_cast<TList*>(next()) ) ) {
1620  UInt_t run = effHistoList->GetUniqueID();
1621  if ( run < uFirstRun || run > uLastRun ) continue;
1622  filename = effHistoList->GetName();
1623  if ( firstRun == lastRun ) continue;
1624  fileMerger.AddFile(filename.Data(),kFALSE);
1625  }
1626 
1627  TString sRange = Form("%i_%i",firstRun,lastRun);
1628  TString mergedFilename = Form("mergedTrigEff_runs_%s.root",sRange.Data());
1629 
1630  if ( firstRun == lastRun ) TFile::Cp(filename.Data(),mergedFilename.Data(),kFALSE);
1631  else {
1632  fileMerger.OutputFile(mergedFilename.Data());
1633  fileMerger.Merge();
1634  }
1635  AliTrigChEffOutput* trigOut = new AliTrigChEffOutput(mergedFilename);
1636  trigOut->SetName(sRange.Data());
1637  fMergedOutputs->Add(trigOut);
1638  }
1639  return kTRUE;
1640 }
1641 
1642 //________________________________________________________________________
1643 TArrayI AliMTRChEffAnalysis::MergeRangesForStat ( TArrayI runRanges, Double_t averageStatError, Bool_t excludePeriphericBoards ) const
1644 {
1645  if ( averageStatError <= 0. || averageStatError >= 1. ) return runRanges;
1646 
1647  // FIXME: statstical error for binomial depends on the value of epsilon
1648  // for the moment let's assume an average efficiency of 0.9 (underestimated)
1649  // in the future one could maybe actually calculate it
1650  // (still we're working with average values...so the precision is limited)
1651  Double_t effForStatCalc = 0.9;
1652 
1653  Double_t averageStatNeeded = effForStatCalc*(1.-effForStatCalc)/(averageStatError*averageStatError);
1654 
1655  AliInfo(Form("Average statistics needed to reach precision of %g : %g",averageStatError,averageStatNeeded));
1656 
1657  Int_t nRanges = runRanges.GetSize()/2;
1658 
1659  TArrayD averageStat(nRanges);
1660  Double_t fullStat = 0.;
1661  for ( Int_t irange=0; irange<nRanges; irange++ ) {
1662  averageStat[irange] = GetAverageStat(runRanges[2*irange],runRanges[2*irange+1],AliTrigChEffOutput::kHboardEff,excludePeriphericBoards);
1663  fullStat += averageStat[irange];
1664  }
1665 
1666  TArrayI mergedRanges(runRanges.GetSize());
1667  Int_t imerged = 0;
1668  mergedRanges[imerged++] = runRanges[0];
1669  Double_t mergedAverageStat = 0., remainingStat = fullStat;
1670  for ( Int_t irange=0; irange<nRanges; irange++ ) {
1671  Int_t istart = 2*irange;
1672  Int_t iend = istart+1;
1673  mergedAverageStat += averageStat[irange];
1674  remainingStat -= averageStat[irange];
1675 
1676  AliInfo(Form("%i - %i => stat %g",runRanges[2*irange],runRanges[2*irange+1],averageStat[irange]));
1677 
1678  if ( ( mergedAverageStat >= averageStatNeeded && remainingStat >= averageStatNeeded ) || iend == runRanges.GetSize()-1 ) {
1679  mergedRanges[imerged++] = runRanges[iend];
1680  AliInfo(Form(" merged range %i - %i => stat %g",mergedRanges[imerged-2],mergedRanges[imerged-1],mergedAverageStat));
1681  mergedAverageStat = 0.;
1682  Int_t nextRun = iend+1;
1683  if ( nextRun < runRanges.GetSize() ) mergedRanges[imerged++] = runRanges[nextRun];
1684  }
1685  }
1686  mergedRanges.Set(imerged);
1687  return mergedRanges;
1688 }
1689 
1690 //________________________________________________________________________
1691 Bool_t AliMTRChEffAnalysis::SetCondition ( const char* physSel, const char* trigClassName, const char* centrality, Int_t itrackSel, Int_t imatch, Int_t imethod, Bool_t isBasic )
1692 {
1694  if ( ! fConditions ) {
1695  fConditions = new TObjArray();
1696  fConditions->SetOwner();
1697  }
1698 
1699  TString sCondition = Form("%s;%s;%s;%i;%i;%i",physSel,trigClassName,centrality,itrackSel,imatch,imethod);
1700  TObjArray* foundCondition = static_cast<TObjArray*>(fConditions->FindObject(sCondition.Data()));
1701  TObjArray* basicCondition = static_cast<TObjArray*>(fConditions->At(0));
1702 
1703  TObjArray* addCondition = 0x0;
1704 
1705  if ( foundCondition ) {
1706  if ( isBasic ) {
1707  if ( foundCondition == basicCondition ) return kFALSE;
1708  else {
1709  fConditions->Remove(foundCondition);
1710  addCondition = foundCondition;
1711  }
1712  }
1713  else {
1714  AliInfo("Systematic condition already added");
1715  return kFALSE;
1716  }
1717  }
1718  else {
1719  addCondition = sCondition.Tokenize(";");
1720  addCondition->SetName(sCondition.Data());
1721  }
1722 
1723 
1724  if ( isBasic ) {
1725  if ( basicCondition ) {
1726  AliInfo(Form("Changing current eff. condition: %s\n",basicCondition->GetName()));
1727  fConditions->Remove(basicCondition);
1728  delete basicCondition;
1729  }
1730  fConditions->AddAt(addCondition,0);
1731  fConditions->Compress();
1732 
1733  // Update outputs
1734  if ( fOutputs ) {
1735  TObjArray* tmpOutputs = static_cast<TObjArray*>(fOutputs->Clone());
1736  fOutputs->Delete();
1737  TIter next(tmpOutputs);
1738  TList* effHistiList = 0x0;
1739  while ( (effHistiList = static_cast<TList*>(next())) ) {
1740  AddToList(effHistiList->GetName(), fOutputs->GetName());
1741  }
1742  delete tmpOutputs;
1743  }
1744  }
1745  else fConditions->Add(addCondition);
1746 
1747  return kTRUE;
1748 }
1749 
1750 //________________________________________________________________________
1752 {
1755 }
1756 
1757 
1758 //________________________________________________________________________
1759 Bool_t AliMTRChEffAnalysis::SetEffConditions ( const char* physSel, const char* trigClassName, const char* centrality, Int_t itrackSel, Int_t imatch, Int_t imethod )
1760 {
1762  return SetCondition(physSel, trigClassName, centrality, itrackSel, imatch, imethod, kTRUE);
1763 }
1764 
1765 //________________________________________________________________________
1766 Bool_t AliMTRChEffAnalysis::SetOutList ( const char *localFileList, const char *outputName )
1767 {
1769 
1771 
1772  TString filename(localFileList);
1773  gSystem->ExpandPathName(filename);
1774  if ( gSystem->AccessPathName(filename.Data()) ) {
1775  AliWarning(Form("Cannot find %s",filename.Data()));
1776  return kFALSE;
1777  }
1778  if ( filename.EndsWith(".root") ) return AddToList(filename.Data(),outputName);
1779 
1780  Bool_t isOk = kTRUE;
1781  ifstream inFile(filename.Data());
1782  TString currLine = "";
1783  while ( ! inFile.eof() ) {
1784  currLine.ReadLine(inFile);
1785  if ( currLine.IsNull() ) continue;
1786  if ( gSystem->AccessPathName(currLine.Data()) ) continue;
1787  if ( ! AddToList(currLine.Data(), outputName) ) isOk = kFALSE;
1788  }
1789  inFile.close();
1790 
1791  return isOk;
1792 }
1793 
1794 //________________________________________________________________________
1795 Bool_t AliMTRChEffAnalysis::SetResultsFromGrid ( const char *runList, const char *path, const char *pattern, const char* localFileList, const char* outDir, const char *directory, const char* outputName )
1796 {
1798  CopyLocally(runList,path,pattern,localFileList,outDir,directory);
1799  return SetOutList(localFileList,outputName);
1800 }
1801 
1802 //________________________________________________________________________
1803 Bool_t AliMTRChEffAnalysis::SetResultsFromWeb ( const char *runList, const char *path, const char* localFileList, const char* outDir, const char *directory, const char* outputName )
1804 {
1806  CopyLocally(runList,path,"",localFileList,outDir,directory);
1807  return SetOutList(localFileList,outputName);
1808 }
1809 
1810 //________________________________________________________________________
1811 Bool_t AliMTRChEffAnalysis::WriteMergedToOCDB ( const char* outputCDB ) const
1812 {
1814  if ( ! HasMergedResults() ) return kFALSE;
1815  TString outCDBdir(outputCDB);
1816  if ( outCDBdir.Contains("://") && ! outCDBdir.BeginsWith("local") ) {
1817  AliError("A local directory is required to store the information");
1818  return kFALSE;
1819  }
1820  outCDBdir.ReplaceAll("local://","");
1821  if ( gSystem->AccessPathName(outCDBdir.Data()) ) {
1822  if ( ! ExecCommand(Form("mkdir -p %s",outCDBdir.Data()), kTRUE) ) {
1823  AliError(Form("Failed to create directory %s",outCDBdir.Data()));
1824  return kFALSE;
1825  }
1826  }
1827  TString outCDB = outCDBdir;
1828  outCDB.Prepend("local://");
1829 
1830  AliCDBManager* mgr = AliCDBManager::Instance();
1831  if ( ! mgr->GetDefaultStorage() ) mgr->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
1832 
1833  TString trigEffCDBdir = "MUON/Calib/TriggerEfficiency";
1834 
1835  mgr->SetSpecificStorage(trigEffCDBdir.Data(),outCDB.Data());
1836 
1837  AliCDBStorage* specificStorage = mgr->GetSpecificStorage(trigEffCDBdir.Data());
1838 
1839  TObjArray* condition = static_cast<TObjArray*>(fConditions->At(0));
1840 
1841  AliTrigChEffOutput* trigOut = 0x0;
1842  TIter next(fMergedOutputs);
1843  while ( (trigOut = static_cast<AliTrigChEffOutput*>(next())) ) {
1844  TList* effList = GetEffHistoList(trigOut,condition);
1845  TString runRange = trigOut->GetName();
1846 
1847 // // Write full merged output in file
1848 // TFile* file = TFile::Open(Form("mergedTrigEff_runs_%s.root",runRange.Data()),"RECREATE");
1849 // effList->Write("triggerChamberEff",TObject::kSingleKey);
1850 // trigOut->GetOutput()->Write(trigOut->GetOutput()->GetName(),TObject::kSingleKey);
1851 // file->Close();
1852 // delete file;
1853 
1854 
1855  // Write OCDB object
1856  TObjArray* currRange = runRange.Tokenize("_");
1857  Int_t firstRun = static_cast<TObjString*>(currRange->UncheckedAt(0))->String().Atoi();
1858  Int_t lastRun = static_cast<TObjString*>(currRange->UncheckedAt(1))->String().Atoi();
1859  delete currRange;
1860 
1861  // If an object is already there, ask to remove it or keep it
1862  for ( Int_t irun=0; irun<2; irun++ ) {
1863  Int_t runnr = ( irun == 0 ) ? firstRun : lastRun;
1864  specificStorage->QueryCDB(runnr);
1865  TObjArray* allIdsForRun = specificStorage->GetQueryCDBList();
1866  TIter nextId(allIdsForRun);
1867  AliCDBId* id = 0x0;
1868  while ((id = dynamic_cast<AliCDBId*>(nextId()))) {
1869  TString path(id->GetPath());
1870  Int_t foundFirst = id->GetFirstRun();
1871  Int_t foundLast = id->GetLastRun();
1872  Int_t version = id->GetVersion();
1873  Int_t subversion = id->GetSubVersion();
1874  TString locPath = Form("%s/%s/Run%d_%d_v%d_s%d.root",outCDBdir.Data(),path.Data(),foundFirst,foundLast,version,subversion);
1875  if ( ! gSystem->AccessPathName(locPath.Data()) ) {
1876  ExecCommand(Form("rm %s",locPath.Data()), kTRUE);
1877  }
1878  }
1879  }
1880 
1881  // Save the CDB object in the specific storage
1882  AliMUONTriggerEfficiencyCells* effMap = new AliMUONTriggerEfficiencyCells(effList);
1883  AliMUONCDB::WriteToCDB(effMap, "MUON/Calib/TriggerEfficiency", firstRun, lastRun, "Measured efficiencies");
1884  delete effMap; // CAVEAT: effMap is owner of efflist
1885  }
1886  return kTRUE;
1887 }
1888 
1889 //___________________________________________________________________________
1890 //Bool_t AliMTRChEffAnalysis::WriteMerged() const
1891 //{
1892 // /// Write merged efficiencies on file
1893 // if ( ! HasMergedResults ) return kFALSE;
1894 //
1895 // TObjArray* condition = static_cast<TObjArray*>(fConditions->At(0));
1896 //
1897 // AliTrigChEffOutput* trigOut = 0x0;
1898 // TIter next(fMergedOutputs);
1899 // while ( (trigOut = static_cast<AliTrigChEffOutput*>(next())) ) {
1900 // TFile* file = TFile::Open(Form("mergedTrigEff_runs_%s.root",trigOut->GetName()),"RECREATE");
1901 // TList* effList = GetEffHistoList(trigOut,condition);
1902 // effList->Write("triggerChamberEff",TObject::kSingleKey);
1903 // trigOut->GetOutput()->Write(trigOut->GetOutput()->GetName(),TObject::kSingleKey);
1904 // file->Close();
1905 // delete file;
1906 // delete effList;
1907 // }
1908 // return kTRUE;
1909 //}
Counts per cathode histogram index.
Int_t GetIndexFromRun(UInt_t runNumber) const
TList * GetEffHistoList(TString physSel, TString trigClassNames, TString centrality, Int_t itrackSel, Int_t imatch, Int_t imethod)
void CompareMergedEfficiencies(const char *opt) const
void CopyDir(TDirectory *source) const
Double_t GetError(Double_t errLow, Double_t errHigh) const
const char * title
Definition: MakeQAPdf.C:26
tracks used for calculation
Bool_t CopyLocally(const char *runList, const char *path, const char *pattern, const char *localFileList, const char *outDir, const char *directory) const
Hit pattern from tracker track extrapolation.
Double_t GetThreeOfFour(TArrayD eff, TArrayD effErr, Double_t &probErr) const
TSystem * gSystem
TGraphAsymmErrors * GetTrendEff(Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem) const
centrality
TArrayI MergeRangesForStat(TArrayI runRanges, Double_t averageStatError, Bool_t excludePeriphericBoards=kTRUE) const
Counts per slat histogram index.
Int_t CompareEfficiencies(const char *sources, const char *titles, const char *opt, const char *canvasNameSuffix="") const
Bool_t SetResultsFromGrid(const char *runList, const char *path, const char *pattern, const char *localFileList="localFileList.txt", const char *outDir="", const char *directory="MTR_ChamberEffMap", const char *outputName="testMTRChamberEff")
Int_t nDE
TList * GetEffHistoList(AliTrigChEffOutput *trigOut, TObjArray *condition) const
Number of count type.
Bool_t AddToList(const char *filename, const char *outputName)
TObjArray * fMergedOutputs
!<! List of conditions for trigger efficiency
Int_t CompareEfficiencyMethods(const char *source, const char *opt, const char *canvasNameSuffix="") const
Output for Trig chamber effieincy.
TArrayI GetHomogeneousRanges(Double_t chi2Cut=3, Int_t maxNRanges=4, Double_t minEffVariation=0.005, Bool_t perRPC=kTRUE, TArrayI *forcedChanges=0x0, Double_t minEff=0.85, Double_t maxEff=1.01)
Bool_t SetEffConditions(const char *physSel, const char *trigClassName, const char *centrality, Int_t itrackSel, Int_t imatch, Int_t imethod)
Output for Trig chamber effieincy.
void DrawStatContribution(Int_t itype, Int_t irpc, Double_t maxNsigmaOutliers=-1., Double_t minY=0., Double_t maxY=0.15) const
Double_t GetAverageStat(Int_t firstRun, Int_t lastRun, Int_t itype=AliTrigChEffOutput::kHboardEff, Bool_t excludePeriphericBoards=kTRUE) const
Bool_t SetOutList(const char *localFileList, const char *outputName)
TString GetIdentifier(AliTrigChEffOutput *trigOut, TObjArray *condition, Int_t itype, Int_t icount, Int_t ichamber) const
Bool_t Data(TH1F *h, Double_t *rangefit, Bool_t writefit, Double_t &sgn, Double_t &errsgn, Double_t &bkg, Double_t &errbkg, Double_t &sgnf, Double_t &errsgnf, Double_t &sigmafit, Int_t &status)
TH1 * GetHisto(TList *effHistoList, Int_t itype, Int_t icount, Int_t ichamber) const
Bool_t SetCondition(const char *physSel, const char *trigClassName, const char *centrality, Int_t itrackSel, Int_t imatch, Int_t imethod, Bool_t isBasic)
Bool_t WriteMergedToOCDB(const char *outputCDB="CDB") const
Bool_t GetShortConditionTitles(AliTrigChEffOutput *trigOut, TObjArray &condTitles) const
TList * GetRunList(const char *runList) const
ClassImp(AliAnalysisTaskCRC) AliAnalysisTaskCRC
Int_t GetRunNumber(Int_t ipt) const
Bool_t HasMergedResults() const
Bool_t ExecCommand(TString command, Bool_t prompt) const
TArrayI BoardsInRPC(Int_t irpc) const
Double_t FitRangesFunc(Double_t *x, Double_t *par)
Counts per board histogram index.
void DrawEffTrend(Int_t itype, Int_t irpc, Double_t maxNsigmasOutliers=-1., Double_t minEff=0.8, Double_t maxEff=1.01) const
TObjArray * fConditions
!<! List of outputs
TGraphAsymmErrors * GetOutliers(TGraphAsymmErrors *graph, Double_t maxNsigmas=3.) const
Bool_t AddSystematicCondition(const char *physSel, const char *trigClassName, const char *centrality, Int_t itrackSel, Int_t imatch, Int_t imethod)
Bool_t SetResultsFromWeb(const char *runList, const char *path, const char *localFileList="localFileList.txt", const char *outDir="", const char *directory="MTR_ChamberEffMap", const char *outputName="testMTRChamberEff")
Bool_t DrawSystematicEnvelope(Bool_t perRPC=kFALSE) const
Bool_t MergeOutput(TArrayI runRanges, Double_t averageStatError=0.01, Bool_t isIndex=kFALSE)
TString GetHistoName(Int_t itype, Int_t icount, Int_t ichamber, Int_t itrackSel, Int_t imatch, Int_t imethod)
TH1 * GetSum(AliTrigChEffOutput *trigOut, TObjArray *condition, Int_t itype, Int_t icount, Int_t ichamber) const
TH1 * GetTrend(Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem) const