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