AliPhysics  aaf9c62 (aaf9c62)
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 #include <array>
18 #include <vector>
19 
20 // ROOT includes
21 #include <Riostream.h>
22 #include "TObjString.h"
23 #include "TObjArray.h"
24 #include "TList.h"
25 #include "TSystem.h"
26 #include "TROOT.h"
27 #include "TRegexp.h"
28 #include "TFile.h"
29 #include "TDirectory.h"
30 #include "TTree.h"
31 #include "TKey.h"
32 #include "TArrayI.h"
33 #include "TArrayD.h"
34 #include "TGrid.h"
35 #include "TGridResult.h"
36 #include "TGraphAsymmErrors.h"
37 #include "TH1.h"
38 #include "TH2.h"
39 #include "TAxis.h"
40 #include "TF1.h"
41 #include "TMath.h"
42 #include "TCanvas.h"
43 #include "TLegend.h"
44 #include "TLine.h"
45 #include "TLatex.h"
46 #include "TFileMerger.h"
47 #include "TFitResultPtr.h"
48 #include "THashList.h"
49 
50 #include "AliLog.h"
51 #include "AliMergeableCollection.h"
52 #include "AliCounterCollection.h"
53 
54 #include "AliAnalysisMuonUtility.h"
55 #include "AliTrigChEffOutput.h"
56 
57 #include "AliCDBManager.h"
58 #include "AliCDBStorage.h"
59 #include "AliCDBId.h"
60 #include "AliCDBEntry.h"
61 #include "AliMUONCDB.h"
62 #include "AliMUONTriggerEfficiencyCells.h"
63 
65 ClassImp(AliMTRChEffAnalysis) // Class implementation in ROOT context
67 
68 using std::cout;
69 using std::endl;
70 using std::cin;
71 using std::ofstream;
72 using std::ifstream;
73 
74 //________________________________________________________________________
76  TObject(),
77  fConditions(0x0),
78  fNamer(0x0)
79 {
81 
82 }
83 
84 //________________________________________________________________________
85 AliMTRChEffAnalysis::AliMTRChEffAnalysis ( const char *localFileList, const char* outputName ) :
86  TObject(),
87  fConditions(0x0),
88  fNamer(0x0)
89 {
91  InitFromLocal(localFileList,outputName);
92 }
93 
94 //________________________________________________________________________
96 {
97  //
99  //
100  delete fConditions;
101  delete fNamer;
102  for ( AliMTRChEffAnalysis::AliMTRChEffInnerObj* obj : fRunMap ) delete obj;
103  for ( AliMTRChEffAnalysis::AliMTRChEffInnerObj* obj : fMergedMap ) delete obj;
104 }
105 
106 //________________________________________________________________________
107 Bool_t AliMTRChEffAnalysis::AddSystematicCondition ( const char* physSel, const char* trigClassName, const char* centrality, Int_t itrackSel, Int_t imatch, Int_t imethod )
108 {
110  return SetCondition(physSel, trigClassName, centrality, itrackSel, imatch, imethod, kFALSE);
111 }
112 
113 //________________________________________________________________________
114 Bool_t AliMTRChEffAnalysis::AddToList ( const char *filename, const char *outputName )
115 {
117  AliTrigChEffOutput* trigOut = new AliTrigChEffOutput(filename,outputName);
118  if ( ! trigOut->GetMergeableCollection() ) {
119  AliError(Form("Cannot find %s in %s",outputName,filename));
120  return kFALSE;
121  }
122 
123  TObjArray* condition = static_cast<TObjArray*>(fConditions->At(0));
124 
125 // // Delete counter collection to save memory
126 // trigOut->RemoveFromList(trigOut->GetCounterCollection());
127  // Just keep counter and mergeable collections
128  TList* effHistoList = GetEffHistoList(trigOut,condition);
129 // effHistoList->SetName(filename);
130  Int_t runNum = AliAnalysisMuonUtility::GetRunNumber(filename);
131 // effHistoList->SetUniqueID(currRun.Atoi());
132 
134  Int_t idxFromRun = GetIndexFromRun(runNum);
135  if ( idxFromRun >= 0 ) obj = fRunMap[idxFromRun];
136  else {
137  obj = new AliMTRChEffAnalysis::AliMTRChEffInnerObj(filename,outputName,runNum);
138  obj->SetUniqueID(fRunMap.size());
139  fRunMap.push_back(obj);
140  }
141 
142  obj->AddEffHistoList(condition->GetName(), effHistoList);
143 
144 
145  delete trigOut;
146  return kTRUE;
147 }
148 
149 //________________________________________________________________________
151 {
153 
154  // FIXME: ugly and hardcoded, but avoid loading the mapping
155 
156  TArrayI boards;
157  if ( irpc == 0 || irpc == 9 ) {
158  Int_t arr[] = {26,27,28,29,48,49,50,51,68,69,84,85,100,101,113};
159  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
160  boards.Set(nBoards,arr);
161  if ( irpc == 9 )
162  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
163  }
164  else if ( irpc == 1 || irpc == 8 ) {
165  Int_t arr[] = {9,10,11,30,31,32,33,52,53,54,55,70,71,86,87,102,103,114};
166  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
167  boards.Set(nBoards,arr);
168  if ( irpc == 8 )
169  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
170  }
171  else if ( irpc == 2 || irpc == 7 ) {
172  Int_t arr[] = {12,13,34,35,56,57,72,73,88,89,104,105,115};
173  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
174  boards.Set(nBoards,arr);
175  if ( irpc == 7 )
176  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
177  }
178  else if ( irpc == 3 || irpc == 6 ) {
179  Int_t arr[] = {14,15,36,37,58,59,74,75,90,91,106,107,116};
180  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
181  boards.Set(nBoards,arr);
182  if ( irpc == 6 )
183  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
184  }
185  else if ( irpc == 4 || irpc == 5 ) {
186  Int_t arr[] = {16,38,60,76,92,108,117};
187  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
188  boards.Set(nBoards,arr);
189  if ( irpc == 5 )
190  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
191  }
192  else if ( irpc == 17 || irpc == 10 ) {
193  Int_t arr[] = {6,7,8,22,23,24,25,44,45,46,47,66,67,82,83,98,99,112};
194  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
195  boards.Set(nBoards,arr);
196  if ( irpc == 10 )
197  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
198  }
199  else if ( irpc == 16 || irpc == 11 ) {
200  Int_t arr[] = {4,5,20,21,42,43,64,65,80,81,96,97,111};
201  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
202  boards.Set(nBoards,arr);
203  if ( irpc == 11 )
204  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
205  }
206  else if ( irpc == 15 || irpc == 12 ) {
207  Int_t arr[] = {2,3,18,19,40,41,62,63,78,79,94,95,110};
208  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
209  boards.Set(nBoards,arr);
210  if ( irpc == 12 )
211  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
212  }
213  else if ( irpc == 14 || irpc == 13 ) {
214  Int_t arr[] = {1,17,39,61,77,93,109};
215  Int_t nBoards = sizeof(arr)/sizeof(arr[0]);
216  boards.Set(nBoards,arr);
217  if ( irpc == 13 )
218  for ( Int_t iboard=0; iboard<nBoards; iboard++ ) boards[iboard] += 117;
219  }
220 
221  return boards;
222 }
223 
224 
225 //________________________________________________________________________
227 {
229  TList* clonedEffHistos = new TList();
230  clonedEffHistos->SetOwner();
231  TIter next(effHistos);
232  TObject* obj = 0x0;
233  while ( (obj = next()) ) {
234  clonedEffHistos->Add(obj->Clone());
235  }
236  return clonedEffHistos;
237 }
238 
239 //________________________________________________________________________
241 {
243  if ( ! HasMergedResults() ) return kFALSE;
244 
245  AliInfo("Building efficiency map for systematic uncertainties");
246 
247  TString currName = "";
248  Double_t xref=0., yref=0., xpt=0., ypt=0.;
249  Double_t nSigmas = 1.;
250 
252 
253  std::vector<std::string> systKeys = obj->GetSortKeys();
254  Int_t nSysts = systKeys.size();
255 
256  // Clone the histogram list that will contain the systematic uncertainties
257  TList* effHistos = obj->GetEffHistoList(fConditions->UncheckedAt(0)->GetName());
258  TList* systematicList = CloneEffHistoList(effHistos);
259 
260  for ( Int_t ich=0; ich<4; ich++ ) {
261  // Get the efficiency graph for the different conditions
262  // as well as the list of histograms to build the efficiency
263  TGraphAsymmErrors* checkEffList[nSysts];
264  TH1* histoList[nSysts*4];
265  TH1* systHistoList[4];
266  for ( Int_t isyst=0; isyst<nSysts; isyst++ ) {
267  effHistos = obj->GetEffHistoList(systKeys[isyst].c_str());
268  for ( Int_t icount=0; icount<4; icount++ ) {
269  currName = Namer()->GetHistoName(AliTrigChEffOutput::kHboardEff, icount, ich, -1, -1, -1);
270  histoList[4*isyst+icount] = static_cast<TH1*>(effHistos->FindObject(currName.Data()));
271  if ( isyst == 0 ) {
272  systHistoList[icount] = static_cast<TH1*>(systematicList->FindObject(currName.Data()));
273  }
274  }
275 
277  Int_t iden = 4*isyst+AliTrigChEffOutput::kAllTracks;
278  checkEffList[isyst] = new TGraphAsymmErrors(histoList[inum],histoList[iden],"e0");
279  } // loop on systematics
280  TGraphAsymmErrors* refEffList[3];
281  for ( Int_t icount=0; icount<3; icount++ ) {
282  refEffList[icount] = new TGraphAsymmErrors(histoList[icount],histoList[AliTrigChEffOutput::kAllTracks],"e0");
283  }
284 
285  // First check what condition to use for the systematic uncertainty
286  // We're searching for the one giving the maximum discrepancy from the reference
287  // not compatible with statistical uncertainty
288  // If this is not found, we'll just use the statistical uncertanty of the reference
289 
290  TGraphAsymmErrors* refGraph = checkEffList[0];
291  for ( Int_t ipt=0; ipt<refGraph->GetN(); ipt++ ) {
292  refGraph->GetPoint(ipt,xref,yref);
293  Int_t chosenSyst = -1;
294  Double_t foundAbsDiff = -1.;
295  for ( Int_t isyst=1; isyst<nSysts; isyst++ ) {
296  TGraphAsymmErrors* graph = checkEffList[isyst];
297  graph->GetPoint(ipt,xpt,ypt);
298  Double_t diff = ypt - yref;
299  Double_t err = (diff > 0.) ? graph->GetErrorYlow(ipt) : graph->GetErrorYhigh(ipt);
300  Double_t absDiff = TMath::Abs(diff);
301  if ( absDiff < nSigmas*err ) continue;
302  if ( foundAbsDiff < absDiff ) {
303  foundAbsDiff = absDiff;
304  chosenSyst = isyst;
305  }
306  } // loop on Systs
307 
308  Int_t ibin = ipt+1;
309  AliDebug(2,Form("Chamber %i board %i systematicCondition %i",11+ich,ibin,chosenSyst));
310  if ( chosenSyst >= 0 ) {
311  for ( Int_t icount=0; icount<4; icount++ ) {
312  systHistoList[icount]->SetBinContent(ibin,histoList[4*chosenSyst+icount]->GetBinContent(ibin));
313  }
314  }
315  else {
316  Double_t countAll = histoList[AliTrigChEffOutput::kAllTracks]->GetBinContent(ibin);
317  systHistoList[AliTrigChEffOutput::kAllTracks]->SetBinContent(ibin,countAll);
318  for ( Int_t icount=0; icount<3; icount++ ) {
319  TGraphAsymmErrors* graph = refEffList[icount];
320  graph->GetPoint(ipt,xpt,ypt);
321  Double_t errHigh = graph->GetErrorYhigh(ipt);
322  Double_t errLow = graph->GetErrorYlow(ipt);
323  Double_t newEff = ( errLow > errHigh ) ? ypt - errLow : ypt + errHigh;
324  Double_t newCount = TMath::Nint(newEff * countAll);
325  if ( newCount < 0 || newCount > countAll ) {
326  TString warning = Form("WARNING: ch %i board %i cath %i systDiff %g newEff %g / %g",11+ich,ibin,icount,newEff-yref,newCount,countAll);
327  if ( newCount < 0 ) newCount = 0;
328  else newCount = countAll;
329  warning += Form(" => setting numerator to %g",newCount);
330  AliWarning(warning.Data());
331  }
332  systHistoList[icount]->SetBinContent(ibin,newCount);
333  }
334  }
335  } // loop on points
336  for ( Int_t it=0; it<nSysts; it++ ) delete checkEffList[it];
337  for ( Int_t it=0; it<3; it++ ) delete refEffList[it];
338  } // loop on chambers
339  obj->AddEffHistoList("Systematics",systematicList);
340  } // loop on merged efficiencies
341 
342  return kTRUE;
343 }
344 
345 //________________________________________________________________________
347 {
349  if ( fRunMap.empty() ) {
350  AliError("The list of trigger efficiency object is not initialized. Please use either InitFromLocal, InitFromGrid or InitFromWeb");
351  return 1;
352  }
353  return 0;
354 }
355 
356 //________________________________________________________________________
357 Int_t AliMTRChEffAnalysis::CompareEfficiencies ( const char* sources, const char* titles, const char* opt, const char* canvasNameSuffix ) const
358 {
360  TString srcs(sources);
361  if ( srcs.Contains("raw://") ) {
362  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");
363  return -2;
364  }
365  TObjArray* sourceList = srcs.Tokenize(",");
366  TObjArray effHistoLists;
367  effHistoLists.SetOwner();
368 
369  TIter next(sourceList);
370  TObjString* src = 0x0;
371  while ( (src = static_cast<TObjString*>(next())) ) {
372  TList* readList = ReadEffHistoList(src->String().Data());
373  if ( ! readList ) continue;
374  effHistoLists.Add(readList);
375  }
376 
377  return CompareEfficiencies(&effHistoLists, titles, opt, canvasNameSuffix);
378 }
379 
380 //________________________________________________________________________
381 Int_t AliMTRChEffAnalysis::CompareEfficiencies ( TObjArray* effHistoLists, const char* titles, const char* opt, const char* canvasNameSuffix ) const
382 {
384 
385  TString sTitles(titles);
386  TObjArray* titleList = sTitles.Tokenize(",");
387 
388  Int_t nDiffs = 0;
389 
390  Int_t nLists = effHistoLists->GetEntriesFast();
391 
392  TString sCanvasNameSuffix(canvasNameSuffix);
393  if ( ! sCanvasNameSuffix.IsNull() && ! sCanvasNameSuffix.BeginsWith("_") ) sCanvasNameSuffix.Prepend("_");
394 
395  Double_t xpt, ypt, xref, yref;
396  enum {kEff, kDiff, kPull};
397  TString sOpt(opt);
398  sOpt.ToLower();
399  Int_t iopt = kEff;
400  TString yTitle = "Eff.";
401  if ( sOpt.Contains("diff") ) {
402  iopt = kDiff;
403  yTitle = "Eff. - (ref.Eff)";
404  }
405  else if ( sOpt.Contains("pull") ) {
406  iopt = kPull;
407  yTitle = "(Eff - (ref.Eff)) / err";
408  }
409  else nDiffs = -1;
410 
411  if ( iopt != kEff && nLists <2 ) {
412  AliError(Form("You ask for %s but you only provided one set of histograms: nothing done",opt));
413  return -1;
414  }
415 
416  Bool_t needsLegend = ( nLists > 1 );
417 // if ( iopt != kEff ) needsLegend = nLists > 2;
418 
419  Int_t colors[] = {kBlack, kRed, kSpring, kTeal, kBlue, kViolet, kMagenta, kOrange, kGray};
420  Int_t ncolors = sizeof(colors)/sizeof(colors[0]);
421 
423 
424  TString currName = "";
425  Int_t ican = 0;
426  for ( Int_t itype=0; itype<2; itype++ ) {
427  TString xTitle = ( hTypes[itype] == AliTrigChEffOutput::kHslatEff ) ? "RPC" : "Board";
428  for ( Int_t icount=0; icount<3; icount++ ) {
429  TCanvas* can = 0x0;
430  for ( Int_t ich=0; ich<4; ich++ ) {
431  TLegend* leg = 0x0;
432 // Int_t hrefIdx = AliTrigChEffOutput::kNcounts + AliTrigChEffOutput::kNcounts*4*(itype-1) + 4*AliTrigChEffOutput::kAllTracks + ich;
433 // Int_t hIdx = AliTrigChEffOutput::kNcounts + AliTrigChEffOutput::kNcounts*4*(itype-1) + 4*icount + ich;
434  TGraphAsymmErrors* refGraph = 0x0;
435  for ( Int_t ilist=0; ilist<nLists; ilist++ ) {
436  TString currTitle = titleList->At(ilist)->GetName();
437  TList* effHistos = static_cast<TList*>(effHistoLists->UncheckedAt(ilist));
438  currName = Namer()->GetHistoName(hTypes[itype], AliTrigChEffOutput::kAllTracks, ich, -1, -1, -1);
439  TH1* histoDen = static_cast<TH1*>(effHistos->FindObject(currName.Data()));
440  currName = Namer()->GetHistoName(hTypes[itype], icount, ich, -1, -1, -1);
441  TH1* histoNum = static_cast<TH1*>(effHistos->FindObject(currName.Data()));
442  TGraphAsymmErrors* graph = new TGraphAsymmErrors(histoNum,histoDen,"e0");
443  currName = histoNum->GetName();
444  currName.ReplaceAll("Count","Eff");
445  currName.Append(Form("_%s",currTitle.Data()));
446  graph->SetName(currName.Data());
447 
448  if ( iopt != kEff ) {
449  if ( refGraph ) {
450  for ( Int_t ipt=0; ipt<graph->GetN(); ipt++ ) {
451  refGraph->GetPoint(ipt,xref,yref);
452  graph->GetPoint(ipt,xpt,ypt);
453  Double_t diff = ypt - yref;
454  if ( TMath::Abs(diff) > 1.e-4 ) nDiffs++;
455  if ( iopt == kDiff ) graph->SetPoint(ipt,xpt,diff);
456  else if ( iopt == kPull ) {
457  Double_t err = GetError(graph->GetErrorYlow(ipt),graph->GetErrorYhigh(ipt));
458  Double_t pull = ( err > 0. ) ? diff/err : 0.;
459  graph->SetPoint(ipt,xpt,pull);
460  }
461  } // loop on points
462  }
463  else {
464  refGraph = graph;
465  continue;
466  }
467  }
468 
469  if ( ! can ) {
470  currName = graph->GetName();
471  currName.Remove(currName.Length()-currTitle.Length()-5);
472  currName += sCanvasNameSuffix;
473  can = new TCanvas(currName.Data(),currName.Data(),20*ican,20*ican,600,600);
474  can->Divide(2,2);
475  ican++;
476  }
477  if ( needsLegend && ! leg ) {
478  leg = new TLegend(0.35, 0.15, 0.65, 0.45);
479  if ( refGraph ) leg->SetHeader(Form("Ref.: %s",titleList->At(0)->GetName()));
480  }
481  can->cd(ich+1);
482  gPad->SetGridy();
483  Int_t icolor = ( ilist < ncolors ) ? colors[ilist] : 20+ilist;
484  graph->SetLineColor(icolor);
485  graph->SetMarkerColor(icolor);
486  graph->SetMarkerStyle(20+ilist);
487  graph->SetMarkerSize(0.5);
488  graph->GetXaxis()->SetTitle(xTitle.Data());
489  graph->GetYaxis()->SetTitle(yTitle.Data());
490  graph->Draw((gPad->GetListOfPrimitives()->GetEntries()==0)?"ap":"p");
491  if ( leg ) leg->AddEntry(graph,titleList->At(ilist)->GetName(),"lp");
492  } // loop on lists
493  if (leg ) leg->Draw();
494  delete refGraph;
495  } // loop on chambers
496  } // loop on counts
497  } // loop on types
498 
499  delete titleList;
500 
501  return nDiffs;
502 }
503 
504 //________________________________________________________________________
505 Int_t AliMTRChEffAnalysis::CompareEfficiencyMethods ( const char* source, const char* opt, const char* canvasNameSuffix ) const
506 {
508  if ( ! fConditions ) {
509  AliWarning("No condition found! Please specify the default efficiency condition with SetEffConditions and then add additional tests with AddSystematicCondition");
510  return -1;
511  }
512 
513  AliTrigChEffOutput trigOut(source);
514 
515  Int_t nConditions = fConditions->GetEntriesFast();
516 
517  TString titles = "";
518  TObjArray effHistoLists;
519  effHistoLists.SetOwner();
520 
521  for ( Int_t icond=0; icond<nConditions; icond++ ) {
522  TObjArray* condition = static_cast<TObjArray*>(fConditions->UncheckedAt(icond));
523  TString condTitle = GetShortConditionTitle(condition->GetName());
524 
525  TList* effHistos = GetEffHistoList(&trigOut, condition);
526  effHistoLists.Add(effHistos);
527  titles += Form("%s,",condTitle.Data());
528  }
529 
530  titles.Remove(TString::kTrailing,',');
531  return CompareEfficiencies(&effHistoLists, titles, opt, canvasNameSuffix);
532 }
533 
534 
535 //________________________________________________________________________
537 {
538  if ( ! HasMergedResults() ) return;
539 
540  if ( fMergedMap.size() < 2 ) {
541  AliWarning("There is only one merged object: nothing to compare to");
542  return;
543  }
544 
545  AliInfo("Comparing the merged efficiencies");
546 
547  TObjArray* condition = static_cast<TObjArray*>(fConditions->At(0));
548  TString titles = "";
549 
550  TObjArray effHistoList;
552  TList* effHistos = obj->GetEffHistoList(condition->GetName());
553  effHistoList.Add(effHistos);
554  titles += Form("%i_%i,",obj->GetMinRun(),obj->GetMaxRun());
555  }
556  titles.Remove(TString::kTrailing,',');
557 
558  CompareEfficiencies(&effHistoList, titles.Data(), opt, "MergedComp");
559 }
560 
561 //________________________________________________________________________
562 Int_t AliMTRChEffAnalysis::ComputeAndCompareEfficiencies ( const char* sources, const char* titles, const char* opt, const char* canvasNameSuffix ) const
563 {
565  TString srcs(sources);
566  TObjArray* sourceList = srcs.Tokenize(",");
567  TObjArray effHistoLists;
568  effHistoLists.SetOwner();
569 
570  TObjArray* condition = static_cast<TObjArray*>(fConditions->At(0));
571  if ( ! condition ) {
572  AliError("The method requires to set an efficiency confition with SetEffConditions");
573  return -1;
574  }
575 
576  TIter next(sourceList);
577  TObjString* src = 0x0;
578  while ( (src = static_cast<TObjString*>(next())) ) {
579  if ( ! src->String().EndsWith(".root") ) {
580  AliError("The method reads files with the output of AliAnalysisTaskTrigChEff and re-compute the efficiency");
581  return -1;
582  }
583  AliTrigChEffOutput trigOut(src->GetName());
584  TList* readList = GetEffHistoList(&trigOut,condition);
585  if ( ! readList ) continue;
586  effHistoLists.Add(readList);
587  }
588 
589  return CompareEfficiencies(&effHistoLists, titles, opt, canvasNameSuffix);
590 }
591 
592 
593 //________________________________________________________________________
594 //TArrayI AliMTRChEffAnalysis::CheckHomogeneity ( const TGraphAsymmErrors* trendGraph, Double_t nSigmas, Bool_t revert ) const
595 //{
596 // /// Check efficiency homogeneity
597 // TArrayI ranges(trendGraph->GetN());
598 // Double_t xpt=0., ypt=0.;
599 //
600 // Double_t sumEffOverSigma2 = -10.;
601 // Double_t sumInvSimga2 = 0.001;
602 // Int_t irange = 0;
603 // Int_t npt = trendGraph->GetN();
604 // for ( Int_t ipt=0; ipt<npt; ipt++ ) {
605 // Int_t currPt = ( revert ) ? npt-1-ipt : ipt;
606 // trendGraph->GetPoint(currPt,xpt,ypt);
607 // Double_t err = GetError(trendGraph->GetErrorYlow(currPt),trendGraph->GetErrorYhigh(currPt));
608 // Double_t invSigma2 = 1./(err*err);
609 // Double_t effOverSigma2 = ypt*invSigma2;
610 //
611 // Double_t meanEff = sumEffOverSigma2 / sumInvSimga2;
612 // Double_t diff = ypt - meanEff;
613 // Double_t diffErr = TMath::Sqrt(err*err+1./sumInvSimga2);
615 // if ( TMath::Abs(diff)/diffErr > nSigmas ) {
616 // TString run = trendGraph->GetXaxis()->GetBinLabel(currPt+1);
617 // ranges[irange++] = run.Atoi();
618 // sumEffOverSigma2 = 0.;
619 // sumInvSimga2 = 0.;
620 // }
621 // sumEffOverSigma2 += effOverSigma2;
622 // sumInvSimga2 += invSigma2;
623 // }
624 // TString run = trendGraph->GetXaxis()->GetBinLabel(trendGraph->GetN());
625 // ranges[irange++] = run.Atoi();
626 // ranges.Set(irange);
627 // return ranges;
628 //}
629 
630 //________________________________________________________________________
631 void AliMTRChEffAnalysis::CopyDir(TDirectory *source) const
632 {
634  TDirectory *savdir = gDirectory;
635  TDirectory *adir = savdir->mkdir(source->GetName());
636  adir->cd();
637  //loop on all entries of this directory
638  TKey *key;
639  TIter nextkey(source->GetListOfKeys());
640  while ((key = (TKey*)nextkey())) {
641  const char *classname = key->GetClassName();
642  TClass *cl = gROOT->GetClass(classname);
643  if (!cl) continue;
644  if (cl->InheritsFrom(TDirectory::Class())) {
645  source->cd(key->GetName());
646  TDirectory *subdir = gDirectory;
647  adir->cd();
648  CopyDir(subdir);
649  adir->cd();
650  } else if (cl->InheritsFrom(TTree::Class())) {
651  TTree *T = (TTree*)source->Get(key->GetName());
652  adir->cd();
653  TTree *newT = T->CloneTree(-1,"fast");
654  newT->Write();
655  } else {
656  source->cd();
657  TObject *obj = key->ReadObj();
658  adir->cd();
659  obj->Write(obj->GetName(),TObject::kSingleKey);
660  delete obj;
661  }
662  }
663  adir->SaveSelf(kTRUE);
664  savdir->cd();
665 }
666 
667 
668 //________________________________________________________________________
669 Bool_t AliMTRChEffAnalysis::CopyLocally ( const char* runList, const char* path, const char* pattern, const char* localFileList, const char* outDir, const char* directory ) const
670 {
672  TString sPattern(pattern);
673  TString sOutDir(outDir);
674  TString sPath(path);
675  Bool_t isGrid = (! sPattern.IsNull());
676 
677  if ( sOutDir.IsNull() ) {
678  if ( isGrid ) {
679  TString data = sPath(TRegexp("/data/"));
680  TString year = sPath(TRegexp("/20[0-9][0-9]/"));
681  TString period = sPath(TRegexp("/LHC[0-9][0-9][a-z]"));
682  period.Append("/");
683  TString pass = AliAnalysisMuonUtility::GetPassName(path);
684  if ( pass.IsNull() ) pass = AliAnalysisMuonUtility::GetPassName(pattern);
685  sOutDir = data+year+period+pass;
686  sOutDir.ReplaceAll("//","/");
687  sOutDir.Remove(TString::kTrailing,'/');
688  sOutDir.Remove(TString::kLeading,'/');
689  }
690  else sOutDir = sPath;
691  sOutDir.Remove(TString::kTrailing,'/');
692  sOutDir.Remove(TString::kLeading,'/');
693  }
694 
695  TGridResult* res = 0x0;
696  Bool_t hasCurl = kFALSE;
697  if ( isGrid ) {
698  if ( ! gGrid ) TGrid::Connect("alien://");
699  res = gGrid->Query(path,pattern);
700  }
701  else {
702  if ( gSystem->Exec("which curl &> /dev/null") == 0 ) hasCurl = kTRUE;
703  }
704 
705  TList* rl = GetRunList(runList);
706 
707  ofstream outFile(localFileList);
708  Bool_t allOk = kTRUE;
709  Bool_t prompt = kTRUE;
710  Bool_t overwrite = kFALSE;
711  for ( Int_t irun=0; irun<rl->GetEntries(); irun++ ) {
712  TString run = static_cast<TObjString*>(rl->At(irun))->String();
713  TString dest = Form("%s/%09i/QAresults.root",sOutDir.Data(),run.Atoi());
714  TString destDir = gSystem->DirName(dest.Data());
715  if ( gSystem->AccessPathName(destDir.Data()) ) ExecCommand(Form("mkdir -p %s",destDir.Data()),kFALSE);
716  Bool_t copyFile = kTRUE;
717  Bool_t isFileOk = kTRUE;
718  if ( gSystem->AccessPathName(dest) == 0 ) {
719  if ( prompt ) {
720  TString decision = "";
721  cout << "Local file " << dest.Data() << " already exist: overwrite? [y/n/ya/na (a=use decision for all)]" << endl;
722  cin >> decision;
723  if ( decision.EndsWith("a") ) prompt = kFALSE;
724  if ( decision.BeginsWith("y") ) overwrite = kTRUE;
725  else overwrite = kFALSE;
726  }
727  copyFile = overwrite;
728  }
729  if ( copyFile ) {
730  TString src = "";
731  if ( isGrid ) {
732  for ( Int_t ifile=0; ifile<res->GetEntries(); ifile++ ) {
733  TString inFilename = res->GetKey(ifile,"turl");
734  if ( inFilename.Contains(run.Data()) ) {
735  src = inFilename;
736  break;
737  }
738  }
739  if ( src.IsNull() ) {
740  AliWarning(Form("Cannot find output for run %s",run.Data()));
741  isFileOk = kFALSE;
742  }
743  else {
744  TFile* outFile = TFile::Open(dest,"RECREATE");
745  TFile* inFile = TFile::Open(src);
746  inFile->cd();
747  TDirectory* dir = static_cast<TDirectory*>(inFile->Get(directory));
748  if ( dir ) {
749  outFile->cd();
750  CopyDir(dir);
751  }
752  else isFileOk = kFALSE;
753  delete inFile;
754  delete outFile;
755  }
756  }
757  else {
758  src = Form("http://aliqamu.web.cern.ch/aliqamu/%s",dest.Data());
759  // TFile::Cp was having some issue lately.
760  // If curl is found on the system, let's use it instead...
761  if ( hasCurl ) {
762  Int_t cmdOut = gSystem->Exec(Form("curl -f -# -o %s %s",dest.Data(),src.Data()));
763  isFileOk = ( cmdOut == 0 );
764  }
765  else isFileOk = TFile::Cp(src.Data(),dest.Data());
766  }
767  }
768 
769  if ( isFileOk ) outFile << gSystem->pwd() << "/" << dest.Data() << endl;
770  else {
771  AliWarning(Form("Problem getting run %s",run.Data()));
772  allOk = kFALSE;
773  }
774  }
775  delete rl;
776  outFile.close();
777  return allOk;
778 }
779 
780 //________________________________________________________________________
781 void AliMTRChEffAnalysis::DrawEffTrend ( Int_t itype, Int_t irpc, Double_t maxNsigmaOutliers, Double_t minEff, Double_t maxEff ) const
782 {
784  if ( Check() ) return;
785 
786  TString baseNames[3] = {"Chamber","RPC","Board"};
787  TString base = baseNames[itype] + "Eff";
788  if ( itype == AliTrigChEffOutput::kHboardEff ) {
789  if ( irpc < 0 ) {
790  AliWarning("Please specify RPC");
791  return;
792  }
793  base += Form("InRPC%i",irpc);
794  }
795 
796  Int_t nColumns = 2;
797  Int_t nRows = 2;
798  Int_t width = 600;
799  Int_t height = 600;
800  Int_t nDetEl = 4;
801  Int_t nCh = 1;
802  Double_t legYmin = 0.65;
803  Double_t legYmax = 0.9;
804  if ( itype != AliTrigChEffOutput::kHchamberEff ) {
805  nColumns = 6;
806  nRows = 3;
807  width = 1200;
808  height = 800;
809  nDetEl = 18;
810  nCh = 4;
811  legYmin = 0.15;
812  legYmax = 0.4;
813  }
814  TArrayI boards = BoardsInRPC(irpc);
815  if ( itype == AliTrigChEffOutput::kHboardEff ) nDetEl = boards.GetSize();
816 
817  for ( Int_t ich=0; ich<nCh; ich++ ) {
818  TString canName = base;
819  if ( itype != AliTrigChEffOutput::kHchamberEff ) canName += Form("Ch%i",11+ich);
820  TCanvas* can = new TCanvas(canName.Data(),canName.Data(),25*ich,25*ich,width,height);
821  can->Divide(nColumns,nRows,0,0);
822  can->SetTopMargin(0.);
823  can->SetBottomMargin(0.);
824  for ( Int_t idetelem=0; idetelem<nDetEl; idetelem++ ) {
825  can->cd(idetelem+1);
826  if ( idetelem/nColumns == nRows - 1 ) gPad->SetBottomMargin(0.15);
827  if ( gPad->GetListOfExecs()->GetEntries() == 0 ) gPad->AddExec("ZoomPad","AliMTRChEffAnalysis::ZoomPad()");
828  gPad->SetTicks(1,1);
829  gPad->SetGridy();
830  Int_t detElemId = idetelem;
831  if ( itype == AliTrigChEffOutput::kHchamberEff ) detElemId = 11+idetelem;
832  else if ( itype == AliTrigChEffOutput::kHboardEff ) detElemId = boards[idetelem];
833 
834  TString title = Form("%s %i",baseNames[itype].Data(),detElemId);
835  TLegend* leg = new TLegend(0.2,legYmin,0.8,legYmax);
836  leg->SetHeader(title.Data());
837  for ( Int_t icount=0; icount<2; icount++ ) {
838  TGraphAsymmErrors* gr = GetTrendEff(itype, icount, ich, detElemId);
839  gr->SetLineColor(icount+1);
840  gr->SetMarkerColor(icount+1);
841  gr->SetMarkerStyle(24+2*icount);
842  gr->GetYaxis()->SetRangeUser(minEff,maxEff);
843  gr->GetXaxis()->SetLabelSize(0.07);
844  gr->GetXaxis()->SetTitle("");
845  // gr->GetYaxis()->SetLabelSize(0.025*nRows);
846  // gr->GetXaxis()->SetLabelSize(0.025*nColumns);
847  gr->SetTitle("");
848  gr->Draw(icount==0?"ap":"p");
849  TString legTitle = ( icount==0 ) ? "bending plane" : "non-bending plane";
850  leg->AddEntry(gr,legTitle.Data(),"lp");
851  if ( maxNsigmaOutliers > 0. ) {
852  TGraphAsymmErrors* outliers = GetOutliers(gr,maxNsigmaOutliers);
853  outliers->SetLineColor(6+icount);
854  outliers->SetMarkerColor(6+icount);
855  outliers->SetMarkerStyle(20+2*icount);
856  outliers->SetLineWidth(2);
857  outliers->Draw("p");
858  legTitle.ReplaceAll("plane","outliers");
859  leg->AddEntry(outliers,legTitle.Data(),"lp");
860  }
861  }
862  leg->Draw();
863  }
864  if ( itype == AliTrigChEffOutput::kHchamberEff ) break;
865  }
866 }
867 
868 //________________________________________________________________________
869 void AliMTRChEffAnalysis::DrawStatContribution ( Int_t itype, Int_t irpc, Double_t maxNsigmaOutliers, Double_t minY, Double_t maxY ) const
870 {
872  if ( itype == AliTrigChEffOutput::kHchamberEff ) {
873  AliWarning("This function is valid only for itype 1 and 2");
874  return;
875  }
876 
877  TString baseNames[3] = {"Chamber","RPC","Board"};
878  TString base = baseNames[itype] + "Stat";
879  if ( itype == AliTrigChEffOutput::kHboardEff ) {
880  if ( irpc < 0 ) {
881  AliWarning("Please specify RPC");
882  return;
883  }
884  base += Form("InRPC%i",irpc);
885  }
886 
887  Int_t nColumns = 6;
888  Int_t nRows = 3;
889  Int_t width = 1200;
890  Int_t height = 800;
891  Int_t nDetEl = 18;
892  Int_t nCh = 1;
893 
894  TArrayI boards = BoardsInRPC(irpc);
895  if ( itype == AliTrigChEffOutput::kHboardEff ) nDetEl = boards.GetSize();
896 
897  for ( Int_t ich=0; ich<nCh; ich++ ) {
898  TH1* histos[nDetEl];
899  TH1* sumHistos = 0x0;
900  for ( Int_t idetelem=0; idetelem<nDetEl; idetelem++ ) {
901  Int_t detElemId = idetelem;
902  if ( itype == AliTrigChEffOutput::kHboardEff ) detElemId = boards[idetelem];
903  histos[idetelem] = GetTrend(itype, AliTrigChEffOutput::kAllTracks, ich, detElemId);
904  histos[idetelem]->SetName(Form("%s_stat",histos[idetelem]->GetName()));
905  histos[idetelem]->SetStats(0);
906  if ( sumHistos ) sumHistos->Add(histos[idetelem]);
907  else sumHistos = static_cast<TH1*>(histos[idetelem]->Clone("sumHistos"));
908  }
909 
910  TString canName = base; //Form("%sCh%i",base.Data(),11+ich);
911  TCanvas* can = new TCanvas(canName.Data(),canName.Data(),25*ich,25*ich,width,height);
912  can->Divide(nColumns,nRows,0,0);
913  for ( Int_t idetelem=0; idetelem<nDetEl; idetelem++ ) {
914  can->cd(idetelem+1);
915  if ( gPad->GetListOfExecs()->GetEntries() == 0 ) gPad->AddExec("ZoomPad","AliMTRChEffAnalysis::ZoomPad()");
916  gPad->SetTicks(1,1);
917  gPad->SetGridy();
918  Int_t detElemId = idetelem;
919  if ( itype == AliTrigChEffOutput::kHboardEff ) detElemId = boards[idetelem];
920  TString title = Form("%s %i",baseNames[itype].Data(),detElemId);
921  TLegend* leg = new TLegend(0.2,0.65,0.8,0.9);
922  leg->SetHeader(title.Data());
923  TGraphAsymmErrors* gr = new TGraphAsymmErrors(histos[idetelem],sumHistos,"e0");
924  gr->SetHistogram(static_cast<TH1F*>(histos[idetelem]));
925 
926  gr->SetMarkerStyle(24);
927  gr->SetMarkerSize(0.5);
928  gr->GetYaxis()->SetRangeUser(minY,maxY);
929  gr->GetYaxis()->SetTitle(Form("Tracks in %s / Sum of tracks of %ss in %s",baseNames[itype].Data(),baseNames[itype].Data(),baseNames[itype-1].Data()));
930  gr->SetTitle("");
931  gr->Draw("ap");
932  TString legTitle = "stat";
933 // leg->AddEntry(gr,legTitle.Data(),"lp");
934  if ( maxNsigmaOutliers > 0. ) {
935  TGraphAsymmErrors* outliers = GetOutliers(gr,maxNsigmaOutliers);
936  outliers->SetLineColor(6);
937  outliers->SetMarkerColor(6);
938  outliers->SetMarkerStyle(20);
939  outliers->SetLineWidth(2);
940  outliers->Draw("p");
941  legTitle = "outliers";
942  leg->AddEntry(outliers,legTitle.Data(),"lp");
943  }
944 // }
945  leg->Draw();
946  }
947  delete sumHistos;
948  }
949 }
950 
951 //________________________________________________________________________
953 {
955  if ( ! HasMergedResults() ) return kFALSE;
956 
957  AliInfo("Drawing the systematic variations");
958 
959  Int_t colors[] = {kBlack, kRed, kSpring, kTeal, kBlue, kViolet, kMagenta, kOrange, kGray};
960  Int_t ncolors = sizeof(colors)/sizeof(colors[0]);
961 
964 
965  Double_t xpt, ypt, xref, yref;
966  TArrayD eff(4), effErr(4);
967 
968  Int_t imerged = -1;
970  imerged++;
971  std::vector<std::string> systKeys = obj->GetSortKeys();
972  std::vector<std::string> shortSystName;
973  for ( std::string str : systKeys ) {
974  shortSystName.push_back(GetShortConditionTitle(str.c_str()).Data());
975  }
976  Int_t nSysts = systKeys.size();
977 
978  TString baseName = Form("mergedTrigEff_%i_%i",obj->GetMinRun(),obj->GetMaxRun());
979 
980  TArrayI isEmpty(nSysts);
981 
982  // First get the needed graphs
983  Int_t nDE = 0;
984  TObjArray effGraphs[8];
985  for ( Int_t iplane=0; iplane<8; iplane++ ) {
986  effGraphs[iplane].SetOwner();
987  }
988  TString titles = "";
989  TObjArray effHistoLists;
990 // effHistoLists.SetOwner();
991  for ( Int_t isyst=0; isyst<nSysts; isyst++ ) {
992  TList* effHistos = obj->GetEffHistoList(systKeys[isyst].c_str());
993  effHistoLists.Add(effHistos);
994  titles += Form("%s,",shortSystName[isyst].c_str());
995 
996  for ( Int_t ich=0; ich<4; ich++ ) {
997  TString currName = Namer()->GetHistoName(itype, AliTrigChEffOutput::kAllTracks, ich, -1, -1, -1);
998  TH1* histoDen = static_cast<TH1*>(effHistos->FindObject(currName.Data()));
999  for ( Int_t icount=0; icount<2; icount++ ) {
1000  Int_t iplane = 4*icount+ich;
1001 
1002  if ( histoDen->GetEntries() > 0 ) {
1003  currName = Namer()->GetHistoName(itype, countTypes[icount], ich, -1, -1, -1);
1004  TH1* histoNum = static_cast<TH1*>(effHistos->FindObject(currName.Data()));
1005  TGraphAsymmErrors* gr = new TGraphAsymmErrors(histoNum,histoDen,"e0");
1006  nDE = gr->GetN();
1007  effGraphs[iplane].AddAtAndExpand(gr,isyst);
1008  }
1009  else {
1010  isEmpty[isyst] = 1;
1011  AliWarning(Form("No entries in count %i and ch %i for %s",countTypes[icount],ich,shortSystName[isyst].c_str()));
1012  }
1013  }
1014  }
1015  }
1016 
1017  titles.Remove(TString::kTrailing,',');
1018  CompareEfficiencies(&effHistoLists, titles, "diff", baseName.Data());
1019 
1020  // Draw average dispersion per plane
1021  TString canName = Form("EffSyst_%s",baseName.Data());
1022  Int_t pos = 25*(imerged+1);
1023  TCanvas* can = new TCanvas(canName.Data(),canName.Data(),pos,pos,1200,800);
1024  can->Divide(4,2,0,0);
1025 
1026  for ( Int_t icount=0; icount<2; icount++ ) {
1027  for ( Int_t ich=0; ich<4; ich++ ) {
1028  Int_t iplane = 4*icount+ich;
1029  can->cd(iplane+1);
1030  if ( gPad->GetListOfExecs()->GetEntries() == 0 ) gPad->AddExec("ZoomPad","AliMTRChEffAnalysis::ZoomPad()");
1031  gPad->SetTicks(1,1);
1032  gPad->SetLogy();
1033  TLegend* leg = new TLegend(0.15,0.7,0.9,0.9);
1034  leg->SetHeader(Namer()->GetHistoName(-1,icount,ich,-1,-1,-1));
1035  TH1* sumHisto = 0x0;
1036  for ( Int_t isyst=1; isyst<nSysts; isyst++ ) {
1037  if ( isEmpty[isyst] == 1 ) continue;
1038  TH1* histo = new TH1D(Form("syst_%s_%s_plane%i_ch%i",baseName.Data(),shortSystName[isyst].c_str(),icount,11+ich),"",200,-0.1,0.1);
1039  histo->GetXaxis()->SetTitle("Eff.-(ref.Eff.)");
1040  histo->GetYaxis()->SetTitle("1/#sigma^{2}");
1041 
1042  TGraphAsymmErrors* gr = static_cast<TGraphAsymmErrors*>(effGraphs[iplane].UncheckedAt(isyst));
1043  TGraphAsymmErrors* grRef = static_cast<TGraphAsymmErrors*>(effGraphs[iplane].UncheckedAt(0));
1044  for ( Int_t ipt=0; ipt<gr->GetN(); ipt++ ) {
1045  gr->GetPoint(ipt,xpt,ypt);
1046  Double_t err = GetError(gr->GetErrorYlow(ipt),gr->GetErrorYhigh(ipt));
1047  Double_t invErr2 = ( err > 0. ) ? 1./(err*err) : 0.;
1048  grRef->GetPoint(ipt,xref,yref);
1049 
1050  Double_t diff = ypt-yref;
1051  histo->Fill(diff,invErr2);
1052  }
1053 
1054  if ( ! sumHisto ) {
1055  sumHisto = static_cast<TH1*>(histo->Clone(Form("syst_%s_plane%i_ch%i",baseName.Data(),icount,11+ich)));
1056  sumHisto->SetLineColor(1);
1057  sumHisto->Draw();
1058  leg->AddEntry(sumHisto,"All systematics","l");
1059  }
1060  else sumHisto->Add(histo);
1061  Int_t icolor = ( isyst < ncolors ) ? colors[isyst] : 20+isyst;
1062  histo->SetLineColor(icolor);
1063  histo->Draw("same");
1064  leg->AddEntry(histo,shortSystName[isyst].c_str(),"l");
1065  } // loop on conditions
1066  leg->Draw();
1067  } // loop on chambers
1068  } // loop on counts
1069 
1070 
1071  canName = Form("TriggerEff_3outOf4_syst_%s",baseName.Data());
1072  pos += 50;
1073  TCanvas* canSyst = new TCanvas(canName.Data(),canName.Data(),pos,pos,600,600);
1074  canSyst->SetLogy();
1075  TLegend* leg = new TLegend(0.15,0.7,0.9,0.4);
1076 // leg->SetHeader(trigOut->GetHistoName(-1,icount,ich,-1,-1,-1));
1077  TH1* histo[nSysts];
1078  for ( Int_t isyst=0; isyst<nSysts; isyst++ ) {
1079  if ( isEmpty[isyst] == 1 ) continue;
1080  histo[isyst] = new TH1D(Form("TriggerEff_syst_%s_%s",shortSystName[isyst].c_str(),baseName.Data()),"Dispersion of trigger probability (3/4)",200,-0.1,0.1);
1081  histo[isyst]->GetXaxis()->SetTitle("Trig. prob. - (ref. trig. prob)");
1082  histo[isyst]->GetYaxis()->SetTitle("1/#sigma^{2}");
1083  }
1084 
1085  for ( Int_t ipt=0; ipt<nDE; ipt++ ) {
1086  Double_t refTrigProb = 0.; // refTrigProbErr = 0.;
1087  for ( Int_t isyst=0; isyst<nSysts; isyst++ ) {
1088  if ( isEmpty[isyst] == 1 ) continue;
1089  Double_t trigProb = 1., trigProbErr2 = 0.;
1090  for ( Int_t icount=0; icount<2; icount++ ) {
1091  for ( Int_t ich=0; ich<4; ich++ ) {
1092  Int_t iplane = 4*icount+ich;
1093  TGraphAsymmErrors* gr = static_cast<TGraphAsymmErrors*>(effGraphs[iplane].UncheckedAt(isyst));
1094  gr->GetPoint(ipt,xpt,ypt);
1095  eff[ich] = ypt;
1096  effErr[ich] = GetError(gr->GetErrorYlow(ipt),gr->GetErrorYhigh(ipt));
1097  } // loop on chambers
1098  Double_t effErr34 = 0.;
1099  Double_t eff34 = GetThreeOfFour(eff,effErr,effErr34);
1100  trigProb *= eff34;
1101  trigProbErr2 += effErr34*effErr34;
1102  } // loop on counts
1103 
1104  if ( isyst == 0 ) {
1105  refTrigProb = trigProb;
1106 // refTrigProbErr = trigProbErr;
1107  }
1108  else {
1109  Double_t invErr2 = ( trigProbErr2>0. ) ? 1./trigProbErr2 : 0.;
1110  histo[isyst]->Fill(trigProb-refTrigProb,invErr2);
1111  }
1112  } // loop on conditions
1113  } // loop on points
1114 
1115  for ( Int_t isyst=0; isyst<nSysts; isyst++ ) {
1116  if ( isEmpty[isyst] == 1 ) continue;
1117  TString title = ( isyst == 0 ) ? "All systematics" : shortSystName[isyst].c_str();
1118  Int_t icolor = ( isyst < ncolors ) ? colors[isyst] : 20+isyst;
1119  histo[isyst]->SetLineColor(icolor);
1120  histo[isyst]->Draw((isyst == 0)?"":"same");
1121  leg->AddEntry(histo[isyst],title.Data(),"l");
1122  if ( isyst>0 ) histo[0]->Add(histo[isyst]);
1123  }
1124  leg->Draw();
1125  } // loop on merged output
1126  return kTRUE;
1127 }
1128 
1129 //________________________________________________________________________
1131 {
1133  TString decision = "y";
1134 
1135  if ( gROOT->IsBatch() ) prompt = kFALSE; // To run with crontab
1136 
1137  if ( prompt ) {
1138  cout << command.Data() << " ? [y/n]" << endl;
1139  cin >> decision;
1140  }
1141 
1142  decision.ToLower();
1143  if ( decision == "y" ) {
1144  cout << "Executing: " << command.Data() << endl;
1145  gSystem->Exec(command.Data());
1146  return kTRUE;
1147  }
1148 
1149  return kFALSE;
1150 }
1151 
1152 //________________________________________________________________________
1154 {
1161 
1162  Double_t xx = x[0];
1163  Double_t val = par[1];
1164  Int_t nChanges = par[0];
1165  Double_t matchDiff = 123456789.;
1166  Int_t matchChange = -1;
1167  for ( Int_t iknot=0; iknot<nChanges; iknot++ ) {
1168  Int_t iparChange = 2*(iknot+1);
1169  Double_t diff = xx - par[iparChange];
1170  if ( diff >= 0. && diff < matchDiff ) {
1171  matchDiff = diff;
1172  matchChange = iparChange;
1173  }
1174  }
1175  if ( matchChange >= 0 ) val = par[matchChange+1];
1176 
1177  return val;
1178 }
1179 
1180 //________________________________________________________________________
1181 Double_t AliMTRChEffAnalysis::GetAverageStat ( Int_t firstRun, Int_t lastRun, Int_t itype,Bool_t excludePeriphericBoard ) const
1182 {
1184 
1185  TH1* statHisto = 0x0;
1186 
1188  TList* effHistoList = obj->GetEffHistoList(fConditions->UncheckedAt(0)->GetName());
1189  Int_t run = obj->GetMinRun();
1190  if ( run < firstRun || run > lastRun ) continue;
1191  TH1* histo = GetHisto(effHistoList,itype,AliTrigChEffOutput::kAllTracks,0);
1192 // if ( ! histo ) continue;
1193  if ( statHisto ) statHisto->Add(histo);
1194  else statHisto = static_cast<TH1*>(histo->Clone("tmpStatHisto"));
1195 // delete histo;
1196  }
1197  if ( ! statHisto ) return 0.;
1198 
1199  Double_t statPerDE = 0.;
1200  Double_t nDe = 0.;
1201  if ( itype == AliTrigChEffOutput::kHboardEff && excludePeriphericBoard ) {
1202  Int_t excludeBoardsHalf[] = {1, 17, 39, 61, 77, 93,109,
1203  16, 38, 60, 76, 92, 108, 117,
1204  110, 111, 112, 113, 114, 115, 116};
1205  Int_t nExcludedHalf = sizeof(excludeBoardsHalf)/sizeof(excludeBoardsHalf[0]);
1206  for ( Int_t ibin=1; ibin<=statHisto->GetNbinsX(); ibin++ ) {
1207  Bool_t skip = kFALSE;
1208  for ( Int_t iexcl=0; iexcl<nExcludedHalf; iexcl++ ) {
1209  if ( ibin == excludeBoardsHalf[iexcl] || ibin == excludeBoardsHalf[iexcl]+117 ) {
1210  skip = kTRUE;
1211  break;
1212  }
1213  }
1214  if ( skip ) continue;
1215  statPerDE += statHisto->GetBinContent(ibin);
1216  nDe += 1.;
1217  }
1218  }
1219  else {
1220  statPerDE = statHisto->Integral();
1221  nDe = (Double_t)statHisto->GetNbinsX();
1222  }
1223  statPerDE = nDe > 0. ? statPerDE/nDe : -1.;
1224 
1225  delete statHisto;
1226  return statPerDE;
1227 }
1228 
1229 //________________________________________________________________________
1231 {
1233  Int_t itrackSel = condition->UncheckedAt(3)->GetUniqueID();
1234  Int_t imatch = condition->UncheckedAt(4)->GetUniqueID();
1235  Int_t imethod = condition->UncheckedAt(5)->GetUniqueID();
1236 
1237  return trigOut->GetEffHistoList(condition->At(0)->GetName(),condition->At(1)->GetName(),condition->At(2)->GetName(),itrackSel,imatch,imethod);
1238 }
1239 
1240 //________________________________________________________________________
1242 {
1244  return TMath::Max(errLow,errHigh);
1245 }
1246 
1247 //________________________________________________________________________
1248 TH1* AliMTRChEffAnalysis::GetHisto ( TList* effHistoList, Int_t itype, Int_t icount, Int_t ichamber ) const
1249 {
1251  Int_t ihisto = ( itype == AliTrigChEffOutput::kHchamberEff ) ? icount : AliTrigChEffOutput::kNcounts + 4*AliTrigChEffOutput::kNcounts*(itype-1) + 4*icount + ichamber;
1252  return static_cast<TH1*>(effHistoList->At(ihisto));
1253 }
1254 
1255 //________________________________________________________________________
1256 TArrayI AliMTRChEffAnalysis::GetHomogeneousRanges ( Double_t chi2Cut, Int_t maxNRanges, Double_t minEffVariation, Bool_t perRPC, TArrayI* forcedChanges, Double_t minEff, Double_t maxEff )
1257 {
1259 
1260  AliInfo("Selecting ranges with homogeneous efficiency");
1261 
1262  Int_t nRuns = fRunMap.size();
1263 
1264  TH1F* hRunChangeCount = new TH1F("runChangeCount","Number of RPCs changing efficiency per run",nRuns,-0.5,-0.5+(Double_t)nRuns);
1265  hRunChangeCount->SetXTitle("Run num.");
1266  hRunChangeCount->SetYTitle("Num. of RPCs with change in eff.");
1267  for ( Int_t irun=0; irun<nRuns; irun++ ) {
1268  hRunChangeCount->GetXaxis()->SetBinLabel(irun+1,Form("%i",GetRunNumber(irun)));
1269  }
1270 
1272 
1273  Int_t nCanvas = perRPC ? 4 : 18;
1274  TObjArray canList(nCanvas);
1275  THashList legList;
1276 
1277  for ( Int_t irpc=0; irpc<18; irpc++ ) {
1279  TArrayI boards = BoardsInRPC(irpc);
1280  Int_t firstDetEl = perRPC ? irpc : 0;
1281  Int_t lastDetEl = perRPC ? irpc : boards.GetSize()-1;
1282 
1283  for ( Int_t ich=0; ich<4; ich++ ) {
1284  Int_t ican = perRPC ? ich : irpc;
1285  TCanvas* can = static_cast<TCanvas*>(canList.At(ican));
1286  if ( ! can ) {
1287  TString canName = perRPC ? Form("testRanges_ch%i",11+ich) : Form("testRanges_RPC%i",irpc);
1288  can = new TCanvas(canName.Data(),canName.Data(),10*ich,10*ich,1200,800);
1289  can->Divide(6,3,0,0);
1290  can->SetMargin(0.,0.,0.,0.);
1291  canList.AddAt(can,ican);
1292  }
1293 
1294  for ( Int_t idetel=firstDetEl; idetel<=lastDetEl; idetel++ ) {
1295  Int_t currDE = ( perRPC ) ? idetel : boards[idetel];
1296 // for ( Int_t icount=0; icount<2; icount++ ) {
1297  TGraphAsymmErrors* trendGraph = GetTrendEff(itype,icount,ich,currDE);
1298  TArrayI range = GetHomogeneousRanges(trendGraph,chi2Cut,maxNRanges,minEffVariation,forcedChanges, kTRUE);
1299  trendGraph->GetYaxis()->SetRangeUser(minEff,maxEff);
1300 
1301  can->cd(idetel+1);
1302  if ( gPad->GetListOfExecs()->GetEntries() == 0 ) gPad->AddExec("ZoomPad","AliMTRChEffAnalysis::ZoomPad()");
1303  gPad->SetTicks(1,1);
1304  gPad->SetMargin(0.08,0.,0.08,0.);
1305  TString drawOpt = ( gPad->GetListOfPrimitives()->GetEntries() == 0 ) ? "ap" : "p";
1306 
1307  TString legendName = Form("%s_%i",can->GetName(),currDE);
1308  TLegend* leg = static_cast<TLegend*>(legList.FindObject(legendName.Data()));
1309  if ( ! leg ) {
1310  leg = new TLegend(0.2,0.15,0.8,0.4);
1311  leg->SetHeader(Form("%s %i",perRPC?"RPC":"Board",currDE));
1312  leg->SetName(legendName.Data());
1313  legList.Add(leg);
1314  }
1315 
1316  if ( ! perRPC ) {
1317  Int_t icolor = ich+1;
1318  trendGraph->SetLineColor(icolor);
1319  trendGraph->SetMarkerColor(icolor);
1320  trendGraph->SetMarkerStyle(24+ich);
1321  TF1* func = static_cast<TF1*>(trendGraph->GetListOfFunctions()->At(0));
1322  if ( func ) {
1323  func->SetLineWidth(2);
1324  func->SetLineColor(icolor);
1325  }
1326  }
1327  trendGraph->GetXaxis()->SetLabelSize(0.07);
1328  trendGraph->SetTitle("");
1329 
1330  trendGraph->Draw(drawOpt.Data());
1331  leg->AddEntry(trendGraph,Form("Chamber %i",11+ich),"lp");
1332  if ( perRPC || ich == 3 ) leg->Draw();
1333  for ( Int_t ichange=2; ichange<range.GetSize(); ichange++ ) {
1334  // Store only the run when the change applies
1335  if ( ichange%2 == 1 ) continue;
1336  Int_t runIdx = range[ichange];
1337 // if ( ichange != 0 ) {
1338  TLine* line = new TLine(runIdx,minEff,runIdx,maxEff);
1339  line->SetLineStyle(2);
1340  line->Draw("same");
1341  TLatex text;
1342  text.DrawLatex((Double_t)(runIdx-3),maxEff-0.1*(maxEff-minEff)*(Double_t)(ichange/2),Form("%i",GetRunNumber(runIdx)));
1343 // }
1344  hRunChangeCount->Fill(runIdx);
1345  if ( hRunChangeCount->GetBinContent(runIdx+1) == 1 ) {
1346  TString infoMsg = Form("Efficiency change in %i triggered by ch %i RPC %i",GetRunNumber(runIdx),11+ich,irpc);
1347  if ( ! perRPC ) infoMsg += Form(" Board %i",currDE);
1348  AliInfo(infoMsg.Data());
1349  }
1350  } // loop on change
1351  } // loop on detection element
1352 // }
1353  } // loop on chambers
1354  } // loop on RPC
1355 
1356  // Clusterize contiguous runs
1357  TArrayI runChangeClust(nRuns);
1358  Double_t sumWgtRun = 0.;
1359  Double_t sumWgt = 0;
1360  for ( Int_t irun=0; irun<=nRuns; irun++ ) {
1361  if ( irun == nRuns || hRunChangeCount->GetBinContent(irun+1) == 0 ) {
1362  if ( sumWgt > 0. ) {
1363  Int_t averageRun = TMath::Nint(sumWgtRun / sumWgt);
1364  AliDebug(2,Form("Average run: %i => %i",averageRun,GetRunNumber(averageRun)));
1365  runChangeClust[averageRun]++;
1366  sumWgtRun = 0.;
1367  sumWgt = 0.;
1368  }
1369  }
1370  if ( irun == nRuns ) break;
1371 
1372  AliDebug(2,Form("irun %i => %i: wgt %g",irun,GetRunNumber(irun),hRunChangeCount->GetBinContent(irun+1)));
1373 
1374 // Double_t wgt = (Double_t)runChangeCount[irun];
1375  Double_t wgt = hRunChangeCount->GetBinContent(irun+1);
1376  if ( forcedChanges ) {
1377  for ( Int_t ichange=0; ichange<forcedChanges->GetSize(); ichange++ ) {
1378  if ( GetRunNumber(irun) == forcedChanges->At(ichange) ) wgt *= 10.;
1379  }
1380  }
1381  sumWgtRun += wgt*(Double_t)irun;
1382  sumWgt += wgt;
1383  }
1384 
1385  TCanvas* summaryCan = new TCanvas("effChangeSummary","effChangeSummary",50,50,600,600);
1386  summaryCan->SetLogy();
1387  hRunChangeCount->GetXaxis()->LabelsOption("v");
1388  hRunChangeCount->Draw();
1389 
1390  Int_t ientry = 0;
1391  TArrayI runRanges(nRuns);
1392  runRanges[ientry++] = GetRunNumber(0);
1393  for ( Int_t irun=1; irun<nRuns; irun++ ) {
1394  if ( runChangeClust[irun] > 0 ) {
1395  runRanges[ientry++] = GetRunNumber(irun-1);
1396  runRanges[ientry++] = GetRunNumber(irun);
1397  }
1398  }
1399  runRanges[ientry++] = GetRunNumber(nRuns-1);
1400  runRanges.Set(ientry);
1401  return runRanges;
1402 }
1403 
1404 //________________________________________________________________________
1405 TArrayI AliMTRChEffAnalysis::GetHomogeneousRanges ( TGraphAsymmErrors* trendGraph, Double_t chi2Cut, Int_t maxNRanges, Double_t minEffVariation, TArrayI* forcedChanges, Bool_t returnIndex )
1406 {
1408 
1409  TArrayI runRanges;
1410  TF1* func = 0x0;
1411  TArrayD forcedChangesBin;
1412  Int_t nForced = 0;
1413  if ( forcedChanges ) {
1414  forcedChangesBin.Set(forcedChanges->GetSize());
1415  for ( Int_t ichange=0; ichange<forcedChanges->GetSize(); ichange++ ) {
1416  Int_t idx = GetIndexFromRun(forcedChanges->At(ichange));
1417  if ( idx >= 0 ) forcedChangesBin[nForced++] = (Double_t)idx;
1418  else AliWarning(Form("Cannot find run %i",forcedChanges->At(ichange)));
1419  }
1420  }
1421 
1422  Double_t minNormChi2 = 123456789.;
1423  Int_t minNormChi2Step = -1;
1424  TString fitOpt = "NQ0";
1425 // Double_t fakeVal = -999.;
1426 // TArrayD params(2*maxNRanges);
1427 // params.Reset(fakeVal);
1428 
1429  for ( Int_t istep=0; istep<maxNRanges; istep++ ) {
1430  Int_t nPars = 2*(istep+1);
1431  Double_t xMin = trendGraph->GetXaxis()->GetXmin();
1432  Double_t xMax = trendGraph->GetXaxis()->GetXmax();
1433  func = new TF1("rangeFunc",this,&AliMTRChEffAnalysis::FitRangesFunc,xMin,xMax,nPars,"AliMTRChEffAnalysis","FitRanges");
1434  func->FixParameter(0,istep);
1435  for ( Int_t ipar=1; ipar<nPars; ipar++ ) {
1436 // if ( ipar >= 2*istep ) {
1437 // if ( TMath::Abs(params[ipar]-fakeVal) < 0.01 ) {
1438 // if ( ipar%2 == 1 ) params[ipar] = 0.95;
1439 // else params[ipar] = (xMax-xMin) * (Double_t)(ipar/2)/((Double_t)(istep+1));
1440 // }
1441 // func->SetParameter(ipar,params[ipar]);
1442  Double_t val = ( ipar%2 == 1 ) ? 0.95 : (xMax-xMin) * (Double_t)(ipar/2)/((Double_t)(istep+1));
1443  func->SetParameter(ipar,val);
1444  if ( ipar%2 == 0 ) func->SetParLimits(ipar,xMin,xMax);
1445  }
1446 
1447  TFitResultPtr fitResult = trendGraph->Fit(func,fitOpt.Data());
1448  // If fit converges close to a point where a break is forced
1449  // fix parameters and redo the fit
1450  if ( forcedChanges ) {
1451  Bool_t hasFixedPars = kFALSE;
1452  for ( Int_t iforced=0; iforced<nForced; iforced++ ) {
1453  for ( Int_t jstep=0; jstep<istep; jstep++ ) {
1454  Int_t ipar = 2*(jstep+1);
1455  if ( TMath::Abs(forcedChangesBin[iforced]-func->GetParameter(ipar)) > 2. ) continue;
1456  func->FixParameter(ipar,forcedChangesBin[iforced]);
1457  hasFixedPars = kTRUE;
1458  }
1459  }
1460  if ( hasFixedPars ) fitResult = trendGraph->Fit(func,fitOpt.Data());
1461  }
1462 
1463 // for ( Int_t ipar=1; ipar<nPars; ipar++ ) {
1464 // params[ipar] = func->GetParameter(ipar);
1465 // }
1466 
1467  Double_t normChi2 = func->GetChisquare() / ((Double_t)func->GetNDF());
1468  if ( normChi2 < minNormChi2 ) {
1469  minNormChi2 = normChi2;
1470  minNormChi2Step = istep;
1471  }
1472 // if ( static_cast<int>(fitResult) == 0 && normChi2 < chi2Cut ) break;
1473  if ( normChi2 < chi2Cut ) break; // REMEMBER TO CHECK
1474  delete func;
1475  func = 0x0;
1476  }
1477 
1478  if ( func ) {
1479  trendGraph->GetListOfFunctions()->Add(func->Clone());
1480  Int_t nSteps = (Int_t)func->GetParameter(0);
1481 
1482  // The runs for which the efficiency changes could be unsorted
1483  // (when forced values are requires)
1484  // Copy the parameters in arrays to sort them
1485  Int_t nPoints = nSteps+1;
1486  TArrayD parRunIdx(nPoints);
1487  TArrayD parEff(nPoints);
1488  for ( Int_t ipar=0; ipar<func->GetNpar(); ipar++ ) {
1489  Int_t istep = ipar/2;
1490  if ( ipar%2 == 0 ) parRunIdx[istep] = func->GetParameter(ipar);
1491  else parEff[istep] = func->GetParameter(ipar);
1492  }
1493  parRunIdx[0] = 0.;
1494  TArrayI sortIdx(nPoints);
1495  TMath::Sort(nPoints,parRunIdx.GetArray(),sortIdx.GetArray(),kFALSE);
1496 
1497  runRanges.Set(2*nPoints);
1498  Int_t irun = 0;
1499  runRanges[irun++] = returnIndex ? 0 : GetRunNumber(0);
1500  for ( Int_t ipoint=1; ipoint<nPoints; ipoint++ ) {
1501  Double_t deltaEff = TMath::Abs(parEff[sortIdx[ipoint]]-parEff[sortIdx[ipoint-1]]);
1502 // if ( ipoint>=2 ) deltaEff = TMath::Max(deltaEff,TMath::Abs(parEff[sortIdx[ipoint]]-parEff[sortIdx[ipoint-2]]));
1503  if ( deltaEff < minEffVariation ) {
1504  AliWarning(Form("Efficiency variation for %s is %g => consider uniform",trendGraph->GetName(),deltaEff));
1505  continue;
1506  }
1507  Int_t runChangeIdx = TMath::Nint(parRunIdx[sortIdx[ipoint]]);
1508  AliDebug(1,Form("Change run: %s => %g => %i %i",trendGraph->GetName(),parRunIdx[sortIdx[ipoint]],runChangeIdx,GetRunNumber(runChangeIdx)));
1509  runRanges[irun++] = returnIndex ? runChangeIdx-1 : GetRunNumber(runChangeIdx-1);
1510  runRanges[irun++] = returnIndex ? runChangeIdx : GetRunNumber(runChangeIdx);
1511  }
1512  Int_t lastPt = trendGraph->GetN()-1;
1513  runRanges[irun++] = returnIndex ? lastPt : GetRunNumber(lastPt);
1514  runRanges.Set(irun);
1515  }
1516  else {
1517  AliWarning(Form("Fit did not converge for %s (minimum chi2 %g for step %i)",trendGraph->GetName(),minNormChi2,minNormChi2Step));
1518  }
1519  return runRanges;
1520 }
1521 
1522 //________________________________________________________________________
1523 TString AliMTRChEffAnalysis::GetId ( const char* condition, Int_t minRun, Int_t maxRun ) const
1524 {
1526  if ( maxRun < minRun ) maxRun = minRun;
1527  return Form("%s_%i_%i",condition,minRun,maxRun);
1528 }
1529 
1530 //________________________________________________________________________
1532 {
1535  if ( obj->GetMinRun() == runNumber ) {
1536  return obj->GetUniqueID();
1537  break;
1538  }
1539  }
1540  return -1;
1541 }
1542 
1543 //________________________________________________________________________
1545 {
1547 // TGraphAsymmErrors* outliers = new TGraphAsymmErrors();
1548  TGraphAsymmErrors* outliers = new TGraphAsymmErrors(*graph);
1549  outliers->SetHistogram(static_cast<TH1F*>(graph->GetHistogram()->Clone(Form("%s_outliers",graph->GetHistogram()->GetName()))));
1550 // outliers->SetLineColor(graph->GetLineColor()+1);
1551  if ( graph->GetListOfFunctions()->GetEntries() == 0 ) graph->Fit("pol0","Q0");
1552  TF1* func = static_cast<TF1*>(graph->GetListOfFunctions()->At(0));
1553 
1554  Double_t xpt, ypt;
1555  Int_t nremoved = 0;
1556  for ( Int_t ipt=0; ipt<graph->GetN(); ipt++ ) {
1557  graph->GetPoint(ipt,xpt,ypt);
1558  Double_t diff = ypt - func->Eval(xpt);
1559  Double_t err = ( diff > 0. ) ? graph->GetErrorYlow(ipt) : graph->GetErrorYhigh(ipt);
1560  if ( err <= 0. || TMath::Abs(diff)/err > maxNsigmas ) continue;
1561  outliers->RemovePoint(ipt-nremoved);
1562  nremoved++;
1563 // outliers->SetPoint(iopt,xpt,ypt);
1564  }
1565  return outliers;
1566 }
1567 
1568 //________________________________________________________________________
1570 {
1572  if ( ipt < 0 || ipt >= fRunMap.size() ) return -1;
1573  return fRunMap[ipt]->GetMinRun();
1574 }
1575 
1576 //________________________________________________________________________
1577 TList* AliMTRChEffAnalysis::GetRunList ( const char* runList ) const
1578 {
1580  TList* rl = new TList;
1581  rl->SetOwner();
1582  TString sRunList = gSystem->ExpandPathName(runList);
1583  if ( gSystem->AccessPathName(sRunList) || sRunList.EndsWith(".root") ) {
1584  sRunList.ReplaceAll(","," ");
1585  if ( sRunList.IsDigit() ) {
1586  TObjArray* arr = sRunList.Tokenize(" ");
1587  for ( Int_t iarr=0; iarr<arr->GetEntries(); iarr++ ) {
1588  rl->Add(new TObjString(arr->At(iarr)->GetName()));
1589  }
1590  delete arr;
1591  }
1592  }
1593  else {
1594  ifstream inFile(sRunList.Data());
1595  TString currLine = "";
1596  while ( ! inFile.eof() ) {
1597  currLine.ReadLine(inFile);
1598  TString currRun = AliAnalysisMuonUtility::GetRunNumberAsString(currLine);
1599  if ( ! currRun.IsNull() ) rl->Add(new TObjString(currRun));
1600  }
1601  inFile.close();
1602  }
1603  rl->Sort();
1604  return rl;
1605 }
1606 
1607 //________________________________________________________________________
1608 TString AliMTRChEffAnalysis::GetShortConditionTitle ( const char* conditionName ) const
1609 {
1611 
1612  TString sCond(conditionName);
1613  TObjArray* refCondition = static_cast<TObjArray*>(fConditions->UncheckedAt(0));
1614  TString sRef(refCondition->GetName());
1615 
1616  TObjArray* condition = static_cast<TObjArray*>(fConditions->FindObject(conditionName));
1617  TString title = "";
1618  if ( ! condition || sCond == sRef ) {
1619  title = sCond;
1620  }
1621  else {
1622  for ( Int_t ic=0; ic<condition->GetEntriesFast(); ic++ ) {
1623  TString currCond = static_cast<TObjString*>(condition->UncheckedAt(ic))->String();
1624  TString refCond = static_cast<TObjString*>(refCondition->UncheckedAt(ic))->String();
1625  if ( currCond == refCond ) continue;
1626  title += ";" + currCond;
1627  }
1628  title.Remove(TString::kLeading,';');
1629  }
1630  title.ReplaceAll(",","+");
1631 
1632  return title;
1633 }
1634 
1635 //________________________________________________________________________
1636 TH1* AliMTRChEffAnalysis::GetSum ( AliTrigChEffOutput* trigOut, TObjArray* condition, Int_t itype, Int_t icount, Int_t ichamber ) const
1637 {
1639  TString objName = "";
1640  for ( Int_t ic=3; ic<6; ic++ ) {
1641  objName += condition->UncheckedAt(ic)->GetName();
1642  }
1643  return static_cast<TH1*>(trigOut->GetSum(condition->At(0)->GetName(),condition->At(1)->GetName(),condition->At(2)->GetName(),objName));
1644 }
1645 
1646 //________________________________________________________________________
1647 TH1* AliMTRChEffAnalysis::GetTrend ( Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem ) const
1648 {
1650  if ( itype == AliTrigChEffOutput::kHchamberEff ) {
1651  if ( idetelem < 0 && ichamber >=0 ) idetelem = 11+ichamber;
1652  }
1653  TH1* outHisto = 0x0;
1654 
1655  Int_t nRuns = fRunMap.size();
1656 
1657  Int_t ibin = 0;
1659  ibin++;
1660  TList* effHistoList = obj->GetEffHistoList(fConditions->UncheckedAt(0)->GetName());
1661  if ( ! outHisto ) {
1662 // TString outName = identifier;
1663  TString outName = Form("histo_type%i_count%i_ch%i_",itype,icount,11+ichamber);
1664 // outName.ReplaceAll("/","_");
1665  outName += Form("%i_trend",idetelem);
1666  outHisto = new TH1D(outName.Data(),outName.Data(),nRuns,0.,(Double_t)nRuns);
1667  outHisto->SetDirectory(0);
1668  outHisto->GetXaxis()->SetTitle("Run num.");
1669  }
1670  Int_t run = obj->GetMinRun();
1671  outHisto->GetXaxis()->SetBinLabel(ibin,Form("%i",run));
1672  TH1* histo = GetHisto(effHistoList,itype,icount,ichamber);
1673  Int_t currBin = histo->GetXaxis()->FindBin(idetelem);
1674  outHisto->SetBinContent(ibin,histo->GetBinContent(currBin));
1675  outHisto->SetBinError(ibin,histo->GetBinError(currBin));
1676  // if ( idetelem == 99 ) printf("Type %i count %i ch %i bin %i (%i) val %g\n",itype,icount,ichamber,ibin,currBin,histo->GetBinContent(currBin)); // REMEMBER TO CUT
1677  }
1678  if ( outHisto ) outHisto->GetXaxis()->LabelsOption("v");
1679  return outHisto;
1680 }
1681 
1682 //________________________________________________________________________
1683 TGraphAsymmErrors* AliMTRChEffAnalysis::GetTrendEff ( Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem ) const
1684 {
1686  if ( Check() ) return NULL;
1687  if ( icount == AliTrigChEffOutput::kAllTracks ) {
1688  AliWarning("Chose either bending plane, non-bending plane or both planes");
1689  return NULL;
1690  }
1691  TH1* histoNum = GetTrend(itype,icount,ichamber,idetelem);
1692  TH1* histoDen = GetTrend(itype,AliTrigChEffOutput::kAllTracks,ichamber,idetelem);
1693  TGraphAsymmErrors* graph = new TGraphAsymmErrors(histoNum,histoDen,"e0");
1694  histoNum->Reset();
1695  histoNum->SetStats(kFALSE);
1696  // Solves crash when saving the canvas as a root file
1697  graph->SetHistogram(new TH1F(*static_cast<TH1F*>(histoNum)));
1698  graph->GetHistogram()->SetDirectory(0);
1699  graph->GetYaxis()->SetTitle("Efficiency");
1700  graph->SetMarkerSize(0.5);
1701 // for ( Int_t ibin=1; ibin<=histoNum->GetXaxis()->GetNbins(); ibin++ ) {
1702 // graph->GetXaxis()->SetBinLabel(ibin,histoNum->GetXaxis()->GetBinLabel(ibin));
1703 // }
1704  delete histoNum;
1705  delete histoDen;
1706  return graph;
1707 }
1708 
1709 //________________________________________________________________________
1711 {
1713  Double_t binomialEff = 0.;
1714  Double_t sumErr2 = 0.;
1715  for ( Int_t jch=-1; jch<4; jch++ ) {
1716  Double_t prodEff = 1.;
1717  Double_t prodErr2 = 0.;
1718  for ( Int_t ich=0; ich<4; ich++ ) {
1719  Double_t currEff = ( ich == jch ) ? 1.-eff[ich] : eff[ich];
1720  prodEff *= currEff;
1721  Double_t relErr = ( currEff>0. ) ? effErr[ich]/currEff : 0.;
1722  prodErr2 += relErr*relErr;
1723  }
1724  binomialEff += prodEff;
1725  sumErr2 += prodEff*prodEff*prodErr2;
1726  }
1727  probErr = TMath::Sqrt(sumErr2);
1728  return binomialEff;
1729 }
1730 
1731 //________________________________________________________________________
1733 {
1735  if ( fMergedMap.empty() ) {
1736  AliError("You first need to merge efficiency objects with MergeOutput");
1737  return kFALSE;
1738  }
1739  return kTRUE;
1740 }
1741 
1742 //________________________________________________________________________
1743 Bool_t AliMTRChEffAnalysis::InitFromLocal ( const char *localFileList, const char *outputName )
1744 {
1746 
1747  AliInfo("Reading efficiency objects");
1748 
1750 
1751  TString filename(localFileList);
1752  gSystem->ExpandPathName(filename);
1753  if ( gSystem->AccessPathName(filename.Data()) ) {
1754  AliWarning(Form("Cannot find %s",filename.Data()));
1755  return kFALSE;
1756  }
1757  if ( filename.EndsWith(".root") ) return AddToList(filename.Data(),outputName);
1758 
1759  Bool_t isOk = kTRUE;
1760  // std::vector<Int_t> orderedRuns;
1761  std::map<int,std::string> tmpMap;
1762  ifstream inFile(filename.Data());
1763  TString currLine = "";
1764  while ( ! inFile.eof() ) {
1765  currLine.ReadLine(inFile);
1766  if ( currLine.IsNull() ) continue;
1767  if ( gSystem->AccessPathName(currLine.Data()) ) continue;
1768  int currRun = AliAnalysisMuonUtility::GetRunNumber ( currLine );
1769  tmpMap[currRun] = std::string(currLine.Data());
1770  // orderedRuns.push_back(currRun);
1771  }
1772  inFile.close();
1773 
1774  for ( auto it = tmpMap.begin(); it != tmpMap.end(); ++it ) {
1775  if ( ! AddToList(it->second.c_str(), outputName) ) isOk = kFALSE;
1776  }
1777 
1778  return isOk;
1779 }
1780 
1781 //________________________________________________________________________
1782 Bool_t AliMTRChEffAnalysis::InitFromGrid ( const char *runList, const char *path, const char *pattern, const char* localFileList, const char* outDir, const char *directory, const char* outputName )
1783 {
1785  CopyLocally(runList,path,pattern,localFileList,outDir,directory);
1786  return InitFromLocal(localFileList,outputName);
1787 }
1788 
1789 //________________________________________________________________________
1790 Bool_t AliMTRChEffAnalysis::InitFromWeb ( const char *runList, const char *path, const char* localFileList, const char* outDir, const char *directory, const char* outputName )
1791 {
1793  CopyLocally(runList,path,"",localFileList,outDir,directory);
1794  return InitFromLocal(localFileList,outputName);
1795 }
1796 
1797 //________________________________________________________________________
1798 Bool_t AliMTRChEffAnalysis::MergeOutput ( TArrayI runRanges, Double_t averageStatError, Bool_t isIndex )
1799 {
1801 
1802  if ( runRanges.GetSize()%2 == 1 ) {
1803  AliError("Run ranges expected in the form: start_period1,end_period1,start_period2,end_period2... => even number expected");
1804  return kFALSE;
1805  }
1806 
1807  TArrayI mergedRanges = MergeRangesForStat(runRanges, averageStatError);
1808 
1809  AliInfo("Merging efficiencies");
1810 
1811  Int_t nRanges = mergedRanges.GetSize()/2;
1812 
1813 
1814  if ( fMergedMap.size() > 0 ) {
1815  for ( AliMTRChEffAnalysis::AliMTRChEffInnerObj* obj : fMergedMap ) delete obj;
1816  fMergedMap.clear();
1817  }
1818 
1819  for ( Int_t irange=0; irange<nRanges; irange++ ) {
1820  Int_t firstRun = mergedRanges[2*irange];
1821  Int_t lastRun = mergedRanges[2*irange+1];
1822  if ( isIndex ) {
1823  firstRun = GetRunNumber(firstRun);
1824  lastRun = GetRunNumber(lastRun);
1825  }
1826 
1827  TString filename = "", outputname = "";
1828 
1829  TFileMerger fileMerger;
1831  Int_t run = obj->GetMinRun();
1832  if ( run < firstRun || run > lastRun ) continue;
1833  filename = obj->GetFilename();
1834  outputname = obj->GetOutputname();
1835  if ( firstRun == lastRun ) continue;
1836  fileMerger.AddFile(filename.Data(),kFALSE);
1837  }
1838 
1839  TString sRange = Form("%i_%i",firstRun,lastRun);
1840  TString mergedFilename = Form("mergedTrigEff_runs_%s.root",sRange.Data());
1841 
1842  if ( firstRun == lastRun ) TFile::Cp(filename.Data(),mergedFilename.Data(),kFALSE);
1843  else {
1844  fileMerger.OutputFile(mergedFilename.Data());
1845  fileMerger.Merge();
1846  }
1847  AliTrigChEffOutput* trigOut = new AliTrigChEffOutput(mergedFilename,outputname);
1848  AliMTRChEffInnerObj* mergedObj = new AliMTRChEffInnerObj(mergedFilename.Data(),outputname.Data(),firstRun,lastRun);
1849  for ( Int_t icond=0; icond<fConditions->GetEntriesFast(); icond++ ) {
1850  TObjArray* condition = static_cast<TObjArray*>(fConditions->UncheckedAt(icond));
1851  TList* effHistoList = GetEffHistoList(trigOut,condition);
1852  mergedObj->AddEffHistoList(condition->GetName(), effHistoList);
1853  }
1854  fMergedMap.push_back(mergedObj);
1855  delete trigOut;
1856  }
1857  return kTRUE;
1858 }
1859 
1860 //________________________________________________________________________
1862 {
1864 
1865  Bool_t isOk = kTRUE;
1866 
1867  std::vector<bool> rangeOk;
1868  for ( Int_t irun=0; irun<runRanges.GetSize(); ++irun ) {
1869  rangeOk.push_back(false);
1870  }
1871 
1872  Int_t nRanges = runRanges.GetSize()/2;
1873 
1875  Int_t run = obj->GetMinRun();
1876  bool isInside = false;
1877  for ( Int_t irange=0; irange<nRanges; ++irange ) {
1878  Int_t istart = 2*irange;
1879  Int_t iend = istart+1;
1880  Int_t firstRun = runRanges[istart];
1881  Int_t lastRun = runRanges[iend];
1882  if ( run == firstRun ) rangeOk[istart] = true;
1883  else if ( run == lastRun ) rangeOk[iend] = true;
1884  if ( run >= firstRun && run <= lastRun ) {
1885  isInside = true;
1886  break;
1887  }
1888  }
1889  if ( ! isInside ) {
1890  AliWarning(Form("Warning: run %i is not inside range!",run));
1891  isOk = kFALSE;
1892  }
1893  }
1894 
1895  for ( int irun=0; irun<rangeOk.size(); ++irun ) {
1896  if ( ! rangeOk[irun] ) {
1897  AliWarning(Form("Warning: range limit %i not taken from the list of runs",runRanges[irun]));
1898  isOk = kFALSE;
1899  }
1900  }
1901 
1902  return isOk;
1903 }
1904 
1905 //________________________________________________________________________
1906 TArrayI AliMTRChEffAnalysis::MergeRangesForStat ( TArrayI runRanges, Double_t averageStatError, Bool_t excludePeriphericBoards ) const
1907 {
1908  if ( averageStatError <= 0. || averageStatError >= 1. ) return runRanges;
1909 
1910  // FIXME: statstical error for binomial depends on the value of epsilon
1911  // for the moment let's assume an average efficiency of 0.9 (underestimated)
1912  // in the future one could maybe actually calculate it
1913  // (still we're working with average values...so the precision is limited)
1914  Double_t effForStatCalc = 0.9;
1915 
1916  Double_t averageStatNeeded = effForStatCalc*(1.-effForStatCalc)/(averageStatError*averageStatError);
1917 
1918  AliInfo(Form("Average statistics needed to reach precision of %g : %g",averageStatError,averageStatNeeded));
1919 
1920  Int_t nRanges = runRanges.GetSize()/2;
1921 
1922  TArrayD averageStat(nRanges);
1923  Double_t fullStat = 0.;
1924  for ( Int_t irange=0; irange<nRanges; irange++ ) {
1925  averageStat[irange] = GetAverageStat(runRanges[2*irange],runRanges[2*irange+1],AliTrigChEffOutput::kHboardEff,excludePeriphericBoards);
1926  fullStat += averageStat[irange];
1927  }
1928 
1929  TArrayI mergedRanges(runRanges.GetSize());
1930  Int_t imerged = 0;
1931  mergedRanges[imerged++] = runRanges[0];
1932  Double_t mergedAverageStat = 0., remainingStat = fullStat;
1933  for ( Int_t irange=0; irange<nRanges; irange++ ) {
1934  Int_t istart = 2*irange;
1935  Int_t iend = istart+1;
1936  mergedAverageStat += averageStat[irange];
1937  remainingStat -= averageStat[irange];
1938 
1939  AliInfo(Form("%i - %i => stat %g",runRanges[2*irange],runRanges[2*irange+1],averageStat[irange]));
1940 
1941  if ( ( mergedAverageStat >= averageStatNeeded && remainingStat >= averageStatNeeded ) || iend == runRanges.GetSize()-1 ) {
1942  mergedRanges[imerged++] = runRanges[iend];
1943  AliInfo(Form(" merged range %i - %i => stat %g",mergedRanges[imerged-2],mergedRanges[imerged-1],mergedAverageStat));
1944  mergedAverageStat = 0.;
1945  Int_t nextRun = iend+1;
1946  if ( nextRun < runRanges.GetSize() ) mergedRanges[imerged++] = runRanges[nextRun];
1947  }
1948  }
1949  mergedRanges.Set(imerged);
1950  return mergedRanges;
1951 }
1952 
1953 //________________________________________________________________________
1955 {
1957  if ( fNamer ) return fNamer;
1958 
1959  TObjArray arr;
1960  fNamer = new AliTrigChEffOutput(&arr,"dummy");
1961 
1962  return fNamer;
1963 }
1964 
1965 //________________________________________________________________________
1966 Bool_t AliMTRChEffAnalysis::PatchEffLists ( TList* listToModify, TList* fromList, const char* boardsToPatch ) const
1967 {
1974 
1975  if ( ! listToModify || ! fromList ) return kFALSE;
1976  ifstream inFile(gSystem->ExpandPathName(boardsToPatch));
1977  if ( ! inFile.is_open() ) {
1978  AliError(Form("Cannot open %s",boardsToPatch));
1979  return kFALSE;
1980  }
1981  TString line;
1982  while ( ! inFile.eof() ) {
1983  line.ReadLine(inFile);
1984  if ( line.IsNull() ) continue;
1985  TObjArray* arr = line.Tokenize(" ");
1986  Int_t iboard = static_cast<TObjString*>(arr->UncheckedAt(0))->String().Atoi();
1987  if ( iboard <= 0 ) continue;
1988  Int_t firstCh = 11, lastCh = 14;
1989  if ( arr->GetEntries() == 2 ) {
1990  Int_t currCh = static_cast<TObjString*>(arr->UncheckedAt(1))->String().Atoi();
1991  if ( currCh >= firstCh && currCh <= lastCh ) {
1992  firstCh = currCh;
1993  lastCh = currCh;
1994  }
1995  }
1996  firstCh -= 11;
1997  lastCh -= 11;
1998  for ( Int_t ich=firstCh; ich<=lastCh; ich++ ) {
1999  AliInfo(Form("Patching efficiency of board %i in ch %i",iboard,11+ich));
2000  for ( Int_t icount=0; icount<4; icount++ ) {
2001  TString currName = Namer()->GetHistoName(AliTrigChEffOutput::kHboardEff, icount, ich, -1, -1, -1);
2002  TH1* histoToPatch = static_cast<TH1*>(listToModify->FindObject(currName.Data()));
2003  TH1* fromHisto = static_cast<TH1*>(fromList->FindObject(currName.Data()));
2004  histoToPatch->SetBinContent(iboard,fromHisto->GetBinContent(iboard));
2005  }
2006  }
2007  }
2008  inFile.close();
2009 
2010  return kTRUE;
2011 }
2012 
2013 //________________________________________________________________________
2014 Bool_t AliMTRChEffAnalysis::AdditionalSystematics ( const char* additionalSystematics, const char* affectedBoards ) const
2015 {
2017  if ( ! HasMergedResults() ) return kFALSE;
2018 
2019  AliInfo(Form("Additional systematic uncertainties from %s",additionalSystematics));
2020 
2021  TList* additionalSystList = ReadEffHistoList(additionalSystematics);
2022  TString systName = gSystem->BaseName(additionalSystematics);
2023  systName.Remove(0,systName.Index("?")+1);
2024  systName.Prepend("added_syst_from_");
2025 
2027  TList* effList = obj->GetEffHistoList(fConditions->UncheckedAt(0)->GetName());
2028  TList* newSyst = CloneEffHistoList(effList);
2029  newSyst->SetName(systName.Data());
2030  if ( PatchEffLists(newSyst,additionalSystList,affectedBoards) ) {
2031  obj->AddEffHistoList(systName.Data(),newSyst);
2032  }
2033  else delete newSyst;
2034  }
2035 
2036  return kTRUE;
2037 }
2038 
2039 //________________________________________________________________________
2040 Bool_t AliMTRChEffAnalysis::PatchEfficiency ( const char* effToModify, const char* fromEff, const char* boardsToPatch, const char* outFilename ) const
2041 {
2045 
2046  TList* listToModify = ReadEffHistoList(effToModify);
2047  TList* fromList = ReadEffHistoList(fromEff);
2048 
2049  Bool_t isOk = PatchEffLists(listToModify,fromList,boardsToPatch);
2050 
2051  if ( isOk ) {
2052  TFile* outFile = TFile::Open(gSystem->ExpandPathName(outFilename),"create");
2053  listToModify->Write("triggerChamberEff",TObject::kSingleKey);
2054  outFile->Close();
2055  }
2056 
2057  return isOk;
2058 }
2059 
2060 //________________________________________________________________________
2062 {
2064  TString currSrc(src);
2065  TString trigEffCDBdir = "MUON/Calib/TriggerEfficiency";
2066 
2067  if ( currSrc.BeginsWith("alien") && ! gGrid ) TGrid::Connect("alien://");
2068 
2069  AliMUONTriggerEfficiencyCells* effMap = 0x0;
2070  Bool_t deleteMap = kTRUE;
2071  if ( currSrc.EndsWith(".root") ) effMap = new AliMUONTriggerEfficiencyCells(currSrc.Data());
2072  else {
2073  TObjArray* dirRun = currSrc.Tokenize("?");
2074  TString cdbPath = dirRun->UncheckedAt(0)->GetName();
2075  TString runNum = ( dirRun->GetEntriesFast() > 1 ) ? dirRun->UncheckedAt(1)->GetName() : "";
2076  AliCDBManager* mgr = AliCDBManager::Instance();
2077  if ( ! mgr->GetDefaultStorage() ) mgr->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
2078  if ( mgr->GetEntryCache()->Contains(trigEffCDBdir.Data()) ) mgr->UnloadFromCache(trigEffCDBdir.Data());
2079  mgr->SetSpecificStorage(trigEffCDBdir.Data(),cdbPath.Data());
2080  Int_t runNumber = 0;
2081  if ( runNum.IsNull() ) {
2082  cout << "Please enter run number: " << endl;
2083  cin >> runNumber;
2084  }
2085  else runNumber = runNum.Atoi();
2086  mgr->SetRun(runNumber);
2087  AliCDBEntry* cdbEntry = mgr->Get(trigEffCDBdir.Data());
2088 
2089  // The CDB manager replace the current effMap with another in case two specific storage are provided
2090  // To avoid double deletion, do not delete the object
2091  deleteMap = kFALSE;
2092  effMap = static_cast<AliMUONTriggerEfficiencyCells*>(cdbEntry->GetObject());
2093  }
2094 
2095  if ( ! effMap ) {
2096  AliError(Form("Cannot find effieciency map in %s",src));
2097  return 0x0;
2098  }
2099 
2100  TList* effHistoList = CloneEffHistoList(effMap->GetHistoList());
2101  if ( deleteMap ) delete effMap;
2102 
2103  return effHistoList;
2104 }
2105 
2106 //________________________________________________________________________
2107 Bool_t AliMTRChEffAnalysis::RecoverEfficiency ( const char* runList, const char* ocdb, const char* systOcdb, Int_t referenceRun )
2108 {
2116 
2117  if ( ! HasMergedResults() ) return kFALSE;
2118 
2119  AliInfo("Check for local boards where the efficiency could not be computed and recover it from other maps");
2120 
2121  TList* rList = 0x0;
2122  std::vector<TList*> readEffLists;
2123  std::vector<TList*> systLists;
2124 
2125  TString refRun = "";
2126  if ( referenceRun >= 0 ) refRun = Form("%i",referenceRun);
2127  TList *refRead = 0x0, *refSyst = 0x0;
2128 
2129  // Search for chambers with missing efficiencies
2130  TString currName = "";
2132  TList* effList = obj->GetEffHistoList(fConditions->UncheckedAt(0)->GetName());
2133  std::array<TH1*,16> histoList;
2134  for ( Int_t ich=0; ich<4; ich++ ) {
2135  for ( Int_t icount=0; icount<4; icount++ ) {
2136  currName = Namer()->GetHistoName(AliTrigChEffOutput::kHboardEff, icount, ich, -1, -1, -1);
2137  histoList[4*ich+icount] = static_cast<TH1*>(effList->FindObject(currName.Data()));
2138  }
2139  }
2140  for ( Int_t ibin=1; ibin<=histoList[0]->GetXaxis()->GetNbins(); ibin++ ) {
2141  Bool_t isUnknown[4] = {0,0,0,0};
2142  Int_t nDead = 0, nUnknown = 0;
2143  for ( Int_t ich=0; ich<4; ich++ ) {
2144  Double_t countAll = histoList[4*ich+AliTrigChEffOutput::kAllTracks]->GetBinContent(ibin);
2145  if ( countAll > 10 ) {
2146  Double_t eff = histoList[4*ich+AliTrigChEffOutput::kBothPlanesEff]->GetBinContent(ibin) / countAll;
2147  if ( eff<0.1 ) nDead++;
2148  }
2149  else {
2150  isUnknown[ich] = 1;
2151  nUnknown++;
2152  }
2153  }
2154  if ( nDead > 0 ) {
2155  if ( nUnknown == 3 ) {
2156  for ( Int_t ich=0; ich<4; ich++ ) {
2157  if ( ! isUnknown[ich] ) continue;
2158  AliInfo(Form("Recovering board %i in ch %i",ibin,11+ich));
2159  if ( readEffLists.size() == 0 ) {
2160  // Initialize once all needed objects for recovery
2161  rList = GetRunList(runList);
2162  if ( rList->GetEntries() == 0 ) {
2163  AliError("A recovery is needed, but no run list is specified: please specify it");
2164  return kFALSE;
2165  }
2166  if ( refRun.IsNull() ) refRun = rList->Last()->GetName();
2167  else if ( ! rList->FindObject(refRun.Data()) ) rList->Add(new TObjString(refRun));
2168  AliInfo(Form("Using efficiency of run %s",refRun.Data()));
2169  for ( Int_t itype=0; itype<2; itype++ ) {
2170  // Loop once on standard efficiency and another time for systematic efficiency
2171  TString currOcdb = ( itype == 0 ) ? ocdb : systOcdb;
2172  TString baseName = ( itype == 0 ) ? "RecoveredFrom" : "RecoveredSystFrom";
2173  TIter next(rList);
2174  TObjString* runObj = 0x0;
2175  while ( (runObj = static_cast<TObjString*>(next())) ) {
2176  Bool_t isRefRun = ( runObj->String() == refRun );
2177  // We only need the systematics for the chosen run
2178  if ( itype == 1 && ! isRefRun ) continue;
2179  TList* readList = ReadEffHistoList(Form("%s?%s",currOcdb.Data(),runObj->GetName()));
2180  readList->SetName(Form("%s_%s",baseName.Data(),runObj->GetName()));
2181  readEffLists.push_back(readList);
2182 
2183  if ( isRefRun && itype == 0 ) {
2184  refRead = readList;
2185  }
2186  } // loop on runs
2187  } // loop on standard or systematic OCDB
2188  }
2189 
2190  if ( systLists.size() == 0 ) {
2191  for ( UInt_t imap=0; imap<readEffLists.size(); imap++ ) {
2192  // The systematic efficiency list is a clone of the merged efficiency object
2193  // where we only modify the efficiency of the recovered board with either:
2194  // - the systematic uncertainty of the reference efficiency
2195  // - the efficiency for the other runs
2196  // (in this way the fluctuations of the efficiency with time
2197  // will be treated as systematic variations)
2198  TList* systEffList = CloneEffHistoList(effList);
2199  systEffList->SetName(readEffLists[imap]->GetName());
2200  systLists.push_back(systEffList);
2201  // This is dummy. The read efficiency is the one we will use to patch
2202  // the missing efficiency. So it will not enter the systematic uncertainties
2203  if ( readEffLists[imap] == refRead ) refSyst = systEffList;
2204  }
2205  }
2206 
2207  for ( UInt_t imap=0; imap<readEffLists.size(); imap++ ) {
2208  TList* readList = readEffLists[imap];
2209  for ( Int_t icount=0; icount<4; icount++ ) {
2210  currName = Namer()->GetHistoName(AliTrigChEffOutput::kHboardEff, icount, ich, -1, -1, -1);
2211  TH1* histoFrom = static_cast<TH1*>(readList->FindObject(currName.Data()));
2212  TH1* histoTo = ( readList == refRead ) ? histoList[4*ich+icount] : static_cast<TH1*>(systLists[imap]->FindObject(currName.Data()));
2213  histoTo->SetBinContent(ibin,histoFrom->GetBinContent(ibin));
2214  } // loop on counts
2215  } // loop on maps
2216  } // loop on chambers
2217  } // needs recovery
2218  else AliWarning(Form("Local board %i: unknown efficiency: %i %i %i %i",ibin,isUnknown[0],isUnknown[1],isUnknown[2],isUnknown[3]));
2219  }
2220  } // loop on local boards
2221  for ( TList* systEffHistoList : systLists ) {
2222  if ( systEffHistoList == refSyst ) {
2223  delete systEffHistoList;
2224  // Otherwise it will never be deleted since this "systematic" is dummy
2225  // and will not be added to the object
2226  continue;
2227  }
2228  obj->AddEffHistoList(systEffHistoList->GetName(),systEffHistoList);
2229  }
2230  // CAVEAT: we do not delete the objects in systLists
2231  // since they where added to the list of systematics uncertainties of the merged object
2232  // If we delete them, this will result in memory issues
2233  // when building the systematic uncertainties
2234  systLists.clear();
2235  } // loop on merged objects
2236 
2237  // Delete objects
2238  readEffLists.clear();
2239  delete rList;
2240 
2241  return kTRUE;
2242 }
2243 
2244 //________________________________________________________________________
2245 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 )
2246 {
2248  if ( ! fConditions ) {
2249  fConditions = new TObjArray();
2250  fConditions->SetOwner();
2251  }
2252 
2253 
2254  TString sCondition = Form("%s;%s;%s",physSel,trigClassName,centrality);
2255  sCondition += ";" + Namer()->GetHistoName(-1,-1,-1,itrackSel,-1,-1);
2256  sCondition += ";" + Namer()->GetHistoName(-1,-1,-1,-1,imatch,-1);
2257  sCondition += ";" + Namer()->GetHistoName(-1,-1,-1,-1,-1,imethod);
2258 
2259  TObjArray* foundCondition = static_cast<TObjArray*>(fConditions->FindObject(sCondition.Data()));
2260  TObjArray* basicCondition = static_cast<TObjArray*>(fConditions->At(0));
2261 
2262  TObjArray* addCondition = 0x0;
2263 
2264  if ( foundCondition ) {
2265  if ( isBasic ) {
2266  if ( foundCondition == basicCondition ) return kFALSE;
2267  else {
2268  fConditions->Remove(foundCondition);
2269  addCondition = foundCondition;
2270  }
2271  }
2272  else {
2273  AliInfo("Systematic condition already added");
2274  return kFALSE;
2275  }
2276  }
2277  else {
2278  addCondition = sCondition.Tokenize(";");
2279  addCondition->SetName(sCondition.Data());
2280  addCondition->UncheckedAt(3)->SetUniqueID(itrackSel);
2281  addCondition->UncheckedAt(4)->SetUniqueID(imatch);
2282  addCondition->UncheckedAt(5)->SetUniqueID(imethod);
2283  }
2284 
2285 
2286  if ( isBasic ) {
2287  if ( basicCondition ) {
2288  AliInfo(Form("Changing current eff. condition: %s",basicCondition->GetName()));
2289  fConditions->Remove(basicCondition);
2290  delete basicCondition;
2291  }
2292  fConditions->AddAt(addCondition,0);
2293  fConditions->Compress();
2294 
2295  // Update outputs
2297  obj->RemoveEffHistoList(sCondition.Data());
2298  AddToList(obj->GetFilename(), obj->GetOutputname());
2299  }
2300  }
2301  else fConditions->Add(addCondition);
2302 
2303  return kTRUE;
2304 }
2305 
2306 //________________________________________________________________________
2308 {
2311 }
2312 
2313 
2314 //________________________________________________________________________
2315 Bool_t AliMTRChEffAnalysis::SetEffConditions ( const char* physSel, const char* trigClassName, const char* centrality, Int_t itrackSel, Int_t imatch, Int_t imethod )
2316 {
2318  return SetCondition(physSel, trigClassName, centrality, itrackSel, imatch, imethod, kTRUE);
2319 }
2320 
2321 //________________________________________________________________________
2322 Bool_t AliMTRChEffAnalysis::WriteMergedToOCDB ( const char* outputCDB, Bool_t writeSystematics ) const
2323 {
2325  if ( ! HasMergedResults() ) return kFALSE;
2326 
2327  AliInfo("Writing merged efficiencies to OCDB");
2328 
2329  TString outCDB(outputCDB);
2330  if ( ! outCDB.Contains("://") || outCDB == "raw://" ) {
2331  AliError("Invalid CDB output dir");
2332  return kFALSE;
2333  }
2334 
2335  TString rmCommand = "rm";
2336  if ( outCDB.BeginsWith("alien://") && ! gGrid ) {
2337  TGrid::Connect("alien://");
2338  rmCommand = "alien_rm";
2339  if ( ! gGrid ) {
2340  AliError("Cannot open grid connection");
2341  return kFALSE;
2342  }
2343  }
2344 
2345  AliCDBManager* mgr = AliCDBManager::Instance();
2346  if ( ! mgr->GetDefaultStorage() ) mgr->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
2347 
2348  TString trigEffCDBdir = "MUON/Calib/TriggerEfficiency";
2349 
2350  mgr->SetSpecificStorage(trigEffCDBdir.Data(),outCDB.Data());
2351 
2352  AliCDBStorage* specificStorage = mgr->GetSpecificStorage(trigEffCDBdir.Data());
2353  TString baseOutDir = specificStorage->GetBaseFolder();
2354 
2355  TString condName = ( writeSystematics ) ? "Systematics" : fConditions->UncheckedAt(0)->GetName();
2356 
2358  TList* effHistos = obj->GetEffHistoList(condName.Data());
2359  if ( ! effHistos ) {
2360  AliWarning("No systematic condition found: you should first run BuildSystematicMap");
2361  continue;
2362  }
2363 
2364  WriteToOCDB(effHistos,outputCDB,obj->GetMinRun(),obj->GetMaxRun());
2365  }
2366  return kTRUE;
2367 }
2368 
2369 //________________________________________________________________________
2370 Bool_t AliMTRChEffAnalysis::WriteToOCDB ( const char* inFilename, const char* outputCDB, Int_t firstRun, Int_t lastRun, const char* defaultOCDB ) const
2371 {
2373  TList* effHistos = ReadEffHistoList ( inFilename );
2374  if ( ! effHistos ) return kFALSE;
2375  return WriteToOCDB(effHistos,outputCDB,firstRun,lastRun,defaultOCDB);
2376 }
2377 
2378 //________________________________________________________________________
2379 Bool_t AliMTRChEffAnalysis::WriteToOCDB ( TList* effHistos, const char* outputCDB, Int_t firstRun, Int_t lastRun, const char* defaultOCDB ) const
2380 {
2382  AliInfo("Writing merged efficiencies to OCDB");
2383 
2384  TString outCDB(outputCDB);
2385  if ( ! outCDB.Contains("://") || outCDB == "raw://" ) {
2386  AliError("Invalid CDB output dir");
2387  return kFALSE;
2388  }
2389 
2390  TString rmCommand = "rm";
2391  if ( outCDB.BeginsWith("alien://") ) {
2392  rmCommand = "alien_rm";
2393  if ( ! gGrid ) {
2394  if ( ! TGrid::Connect("alien://") ) {
2395  AliError("Cannot open grid connection");
2396  return kFALSE;
2397  }
2398  }
2399  }
2400 
2401  AliCDBManager* mgr = AliCDBManager::Instance();
2402  if ( ! mgr->GetDefaultStorage() ) mgr->SetDefaultStorage(defaultOCDB);
2403 
2404  TString trigEffCDBdir = "MUON/Calib/TriggerEfficiency";
2405  mgr->SetSpecificStorage(trigEffCDBdir.Data(),outCDB.Data());
2406 
2407  AliCDBStorage* specificStorage = mgr->GetSpecificStorage(trigEffCDBdir.Data());
2408  TString baseOutDir = specificStorage->GetBaseFolder();
2409 
2410  // If an object is already there, ask to remove it or keep it
2411  for ( Int_t irun=0; irun<2; irun++ ) {
2412  Int_t runnr = ( irun == 0 ) ? firstRun : lastRun;
2413  specificStorage->QueryCDB(runnr);
2414  TObjArray* allIdsForRun = specificStorage->GetQueryCDBList();
2415  TIter nextId(allIdsForRun);
2416  AliCDBId* id = 0x0;
2417  while ((id = static_cast<AliCDBId*>(nextId()))) {
2418  TString path(id->GetPath());
2419  Int_t foundFirst = id->GetFirstRun();
2420  Int_t foundLast = id->GetLastRun();
2421  Int_t version = id->GetVersion();
2422  Int_t subversion = TMath::Max(id->GetSubVersion(),0);
2423  TString fullPath = Form("%s/%s/Run%d_%d_v%d_s%d.root",baseOutDir.Data(),path.Data(),foundFirst,foundLast,version,subversion);
2424  ExecCommand(Form("%s %s",rmCommand.Data(),fullPath.Data()), kTRUE);
2425  }
2426  }
2427 
2428  // Save the CDB object in the specific storage
2429  AliMUONTriggerEfficiencyCells* effMap = new AliMUONTriggerEfficiencyCells(CloneEffHistoList(effHistos));
2430  AliMUONCDB::WriteToCDB(effMap, "MUON/Calib/TriggerEfficiency", firstRun, lastRun, "Measured efficiencies");
2431  delete effMap; // CAVEAT: effMap is owner of effHistos
2432 
2433  return kTRUE;
2434 }
2435 
2436 //________________________________________________________________________
2438 {
2439  if ( gPad->GetEvent() != kButton1Double ) return;
2440  TVirtualPad* pad = gPad;
2441  Int_t px = pad->GetEventX();
2442  Int_t py = pad->GetEventY();
2443  TCanvas* can = new TCanvas("zoom","zoom",px,py,600,600);
2444  for ( Int_t iobj=0; iobj<pad->GetListOfPrimitives()->GetEntries(); iobj++ ) {
2445  TObject* obj = pad->GetListOfPrimitives()->At(iobj);
2446  obj = obj->Clone(Form("%s_zoom",obj->GetName()));
2447  TString drawOpt = obj->GetOption();
2448  if ( drawOpt.IsNull() ) {
2449  if ( obj->InheritsFrom(TGraph::Class()) ) {
2450  drawOpt = "p";
2451  if ( iobj == 1 ) drawOpt.Append("a");
2452  static_cast<TGraph*>(obj)->GetXaxis()->SetLabelSize();
2453  }
2454  else if ( obj->InheritsFrom(TH1::Class()) ) {
2455  drawOpt = "e";
2456  if ( iobj == 1 ) drawOpt.Append("same");
2457  static_cast<TH1*>(obj)->GetXaxis()->SetLabelSize();
2458  }
2459  }
2460  obj->Draw(drawOpt.Data());
2461  }
2462  can->Modified();
2463  can->Update();
2464 }
2465 
2466 //___________________________________________________________________________
2467 AliMTRChEffAnalysis::AliMTRChEffInnerObj::AliMTRChEffInnerObj ( const char* filename, const char* outputname, Int_t minRun, Int_t maxRun ) :
2468  TObject(),
2469  fFilename(filename),
2470  fOutputname(outputname),
2471  fMinRun(minRun),
2472  fMaxRun(maxRun)
2473 {
2475  if ( fMaxRun < fMinRun ) fMaxRun = fMinRun;
2476 }
2477 
2478 //___________________________________________________________________________
2480 {
2482  for ( auto& mapEntry : fEffLists ) {
2483  delete mapEntry.second;
2484  }
2485  fEffLists.clear();
2486 }
2487 
2488 //___________________________________________________________________________
2490 {
2492  auto const& mapEntry = fEffLists.find(condition);
2493  if ( mapEntry == fEffLists.end() ) return 0x0;
2494  return mapEntry->second;
2495 }
2496 
2497 //___________________________________________________________________________
2499 {
2501  if ( fEffLists.find(condition) != fEffLists.end() ) {
2502  AliWarning(Form("Condition %s already present: nothing done",condition));
2503  return kFALSE;
2504  }
2505  fEffLists.insert({condition,effHistoList});
2506  fSortKeys.push_back(condition);
2507  return kTRUE;
2508 }
2509 
2510 //___________________________________________________________________________
2512 {
2514  auto const& mapEntry = fEffLists.find(condition);
2515  if ( mapEntry == fEffLists.end() ) return kFALSE;
2516  delete mapEntry->second;
2517  return fEffLists.erase(condition);
2518 }
const char * filename
Definition: TestFCM.C:1
Hit pattern from tracker track extrapolation.
TList * GetEffHistoList(TString physSel, TString trigClassNames, TString centrality, Int_t itrackSel, Int_t imatch, Int_t imethod)
void CompareMergedEfficiencies(const char *opt) const
double Double_t
Definition: External.C:58
void CopyDir(TDirectory *source) const
Double_t GetError(Double_t errLow, Double_t errHigh) const
Bool_t AdditionalSystematics(const char *additionalSystematics, const char *affectedBoards) const
const char * title
Definition: MakeQAPdf.C:27
std::map< std::string, TList * > fEffLists
const char * cdbPath
Definition: AOD.C:26
Bool_t CopyLocally(const char *runList, const char *path, const char *pattern, const char *localFileList, const char *outDir, const char *directory) const
Double_t GetThreeOfFour(TArrayD eff, TArrayD effErr, Double_t &probErr) const
AliRunLoader * rl
TSystem * gSystem
TGraphAsymmErrors * GetTrendEff(Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem) const
centrality
Bool_t RemoveEffHistoList(const char *condition)
AliMTRChEffInnerObj(const char *filename, const char *outputname, Int_t minRun, Int_t maxRun=-1)
TArrayI MergeRangesForStat(TArrayI runRanges, Double_t averageStatError, Bool_t excludePeriphericBoards=kTRUE) const
Int_t ComputeAndCompareEfficiencies(const char *sources, const char *titles, const char *opt, const char *canvasNameSuffix="") const
Counts per board histogram index.
Bool_t CheckRanges(TArrayI runRanges) const
Bool_t InitFromWeb(const char *runList, const char *path, const char *localFileList="localFileList.txt", const char *outDir="", const char *directory="MTR_ChamberEffMap", const char *outputName="testMTRChamberEff")
Int_t CompareEfficiencies(const char *sources, const char *titles, const char *opt, const char *canvasNameSuffix="") const
TList * GetEffHistoList(const char *condition) const
TLatex * text[5]
option to what and if export to output file
tracks used for calculation
Int_t nDE
Bool_t PatchEfficiency(const char *effToModify, const char *fromEff, const char *boardsToPatch, const char *outFilename) const
UShort_t T(UShort_t m, UShort_t t)
Definition: RingBits.C:60
TList * GetEffHistoList(AliTrigChEffOutput *trigOut, TObjArray *condition) const
int Int_t
Definition: External.C:63
Bool_t WriteMergedToOCDB(const char *outputCDB="CDB", Bool_t writeSystematics=kFALSE) const
unsigned int UInt_t
Definition: External.C:33
Bool_t AddToList(const char *filename, const char *outputName)
Number of count type.
Int_t CompareEfficiencyMethods(const char *source, const char *opt, const char *canvasNameSuffix="") const
Output for Trig chamber effieincy.
Bool_t InitFromLocal(const char *localFileList, const char *outputName="testMTRChamberEff")
Definition: External.C:212
Bool_t AddEffHistoList(const char *condition, TList *effHistoList)
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.
AliTrigChEffOutput * fNamer
! Namer for histograms
void DrawStatContribution(Int_t itype, Int_t irpc, Double_t maxNsigmaOutliers=-1., Double_t minY=0., Double_t maxY=0.15) const
Bool_t PatchEffLists(TList *listToModify, TList *fromList, const char *boardsToPatch) const
Double_t GetAverageStat(Int_t firstRun, Int_t lastRun, Int_t itype=AliTrigChEffOutput::kHboardEff, Bool_t excludePeriphericBoards=kTRUE) 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)
TString GetId(const char *condition, Int_t minRun, Int_t maxRun=-1) const
TObject * FindObject(int bin, const char *nameH, const TList *lst, Bool_t normPerEvent=kTRUE)
AliTrigChEffOutput * Namer() const
std::vector< AliMTRChEffAnalysis::AliMTRChEffInnerObj * > fRunMap
! Map of internal objects per run
Int_t colors[nPtBins]
std::vector< AliMTRChEffAnalysis::AliMTRChEffInnerObj * > fMergedMap
! Map of merged internal objects
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 WriteToOCDB(const char *inFilename, const char *outputCDB, Int_t firstRun, Int_t lastRun, const char *defaultOCDB="local://$ALIROOT_OCDB_ROOT/OCDB") const
Counts per cathode histogram index.
TList * GetRunList(const char *runList) const
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
Bool_t RecoverEfficiency(const char *runList, const char *ocdb, const char *systOcdb, Int_t referenceRun=-1)
Int_t GetIndexFromRun(Int_t runNumber) const
Double_t FitRangesFunc(Double_t *x, Double_t *par)
Int_t GetRunNumber(TString)
Definition: PlotMuonQA.C:2235
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 conditions for trigger efficiency
Bool_t InitFromGrid(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")
TList * CloneEffHistoList(TList *effHistos) const
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 Bool_t
Definition: External.C:53
TString GetShortConditionTitle(const char *conditionName) const
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)
Definition: External.C:196
TH1 * GetSum(AliTrigChEffOutput *trigOut, TObjArray *condition, Int_t itype, Int_t icount, Int_t ichamber) const
TDirectoryFile * dir
TList * ReadEffHistoList(const char *src) const
Counts per slat histogram index.
TH1 * GetTrend(Int_t itype, Int_t icount, Int_t ichamber, Int_t idetelem) const