]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGPP/MUON/lite/trigEffQA.C
ce1a325d0bd822e2059703fda9c0af5b3ae7f2f2
[u/mrichter/AliRoot.git] / PWGPP / MUON / lite / trigEffQA.C
1
2 #if !defined(__CINT__) || defined(__MAKECINT__)
3 // ROOT includes
4 #include "TFile.h"
5 #include "TH1.h"
6 #include "TH2.h"
7 #include "TGraphAsymmErrors.h"
8 #include "TSystem.h"
9 #include "Riostream.h"
10 #include "TCanvas.h"
11 #include "TStyle.h"
12 #include "TROOT.h"
13 #include "TLegend.h"
14 #include "TMath.h"
15 #include "TObjArray.h"
16 #include "TList.h"
17 #include "TObjString.h"
18 #include "TString.h"
19 #include "TGrid.h"
20 #include "TArrayD.h"
21 #include "TArrayI.h"
22 #include "TMap.h"
23 #include "TGridResult.h"
24
25 #include "AliCDBManager.h"
26 #include "AliCDBEntry.h"
27 #include "AliCDBPath.h"
28 #include "AliCDBStorage.h"
29 #include "AliMUONTriggerEfficiencyCells.h"
30 #include "AliMUONTriggerChamberEfficiency.h"
31 #include "AliMUONTriggerUtilities.h"
32 #include "AliMUONDigitMaker.h"
33 #include "AliMUONVDigit.h"
34 #include "AliMUONDigitStoreV2R.h"
35 #include "AliMUONCalibrationData.h"
36 #include "AliAnalysisTriggerScalers.h"
37 #include "AliCounterCollection.h"
38 #include "AliTriggerConfiguration.h"
39 #endif
40
41 const Int_t kNch = 4;
42 const Double_t kZero = 1.e-7; // Avoid problems when comparing to 0.
43
44 //_____________________________________________________________________________
45 void SetMyStyle()
46 {
47   /// Set graphic style
48   gStyle->SetCanvasColor(10);
49   gStyle->SetFrameFillColor(10);
50   gStyle->SetStatColor(10);
51   gStyle->SetFillColor(10);
52   gStyle->SetTitleFillColor(10);
53   
54   gStyle->SetTitleXSize(0.03);
55   gStyle->SetTitleXOffset(1.1);
56   gStyle->SetTitleYSize(0.03);
57   gStyle->SetTitleYOffset(1.9);
58   
59   gStyle->SetMarkerSize(0.7);
60   gStyle->SetHistLineWidth(2);
61   
62   gStyle->SetPadLeftMargin(0.12);
63   gStyle->SetPadRightMargin(0.04);
64   gStyle->SetPadBottomMargin(0.08);
65   gStyle->SetPadTopMargin(0.08);
66   
67   gROOT->ForceStyle();
68 }
69
70
71 //_____________________________________________________________________________
72 void SetRunAxisRange ( TAxis* axis )
73 {
74   /// Set axis range
75   for ( Int_t ibin=1; ibin<=axis->GetNbins(); ibin++ ) {
76     TString binLabel = axis->GetBinLabel(ibin);
77     if ( ! binLabel.IsNull()) continue;
78     axis->SetRange(1, ibin-1);
79     return;
80   }
81 }
82
83 //_____________________________________________________________________________
84 Int_t GetRunNumber(TString filePath)
85 {
86   /// Get run number from file path
87   TObjArray* array = filePath.Tokenize("/");
88   array->SetOwner();
89   TString auxString = "";
90   Int_t runNum = -1;
91   for ( Int_t ientry=0; ientry<array->GetEntries(); ientry++ ) {
92     auxString = array->At(ientry)->GetName();
93     if ( auxString.IsDigit() && auxString.Length()>=6 && auxString.Length()<=9 ) {
94       runNum = auxString.Atoi();
95       break;
96     }
97   }
98   delete array;
99   
100   if ( runNum < 0 ) {
101     array = auxString.Tokenize("_");
102     array->SetOwner();
103     auxString = array->Last()->GetName();
104     auxString.ReplaceAll(".root","");
105     runNum = auxString.Atoi();
106     delete array;
107   }
108   
109   return runNum;
110 }
111
112 //_____________________________________________________________________________
113 Bool_t ChangeFilenames ( TObjArray &fileNameArray )
114 {
115   /// Use custom output
116   /// We used to perform the QA on the MTR chamber efficiency
117   /// but since it is obtained form tracks matching with the tracker
118   /// it is not that good for QA since we are dependent on the tracker status.
119   /// In recent versions, the task also calculates the efficiency from all trigger tracks
120   /// (including ghosts). Analyse this output instead.
121   for ( Int_t ifile=0; ifile<fileNameArray.GetEntries(); ifile++ ) {
122     TObjString* currObjString = static_cast<TObjString*>(fileNameArray.At(ifile));
123     TString currFile = currObjString->GetString();
124     TString dirName = gSystem->DirName(currFile.Data());
125     TString fileName = gSystem->BaseName(currFile.Data());
126     Int_t runNum = GetRunNumber(fileName);
127     TString newFilename = Form("%s/terminateRuns/%i/trigChEff_ANY_Apt_allTrig.root",dirName.Data(),runNum);
128     if ( ! gSystem->AccessPathName(newFilename.Data()) ) {
129       printf("New output not found. Use the standard efficiency instead\n");
130       return kFALSE;
131     }
132     currObjString->SetString(newFilename);
133   }
134   return kTRUE;
135 }
136
137 //_____________________________________________________________________________
138 Double_t* GetProdErr(Double_t* effErr, Int_t exclude, Int_t nFactors = kNch)
139 {
140   /// Error of product
141   Double_t prod = 1.;
142   Double_t relErr = 0., relProdErrSquare = 0.;
143   for ( Int_t iprod=0; iprod<nFactors; iprod++ ) {
144     if ( iprod == exclude ) continue;
145     prod *= effErr[iprod];
146     relErr = ( effErr[iprod] > kZero ) ? effErr[iprod+nFactors]/effErr[iprod] : 0.;
147     relProdErrSquare += relErr*relErr;
148     //printf("%f +- %f  ", effErr[iprod], effErr[iprod+nFactors]); // alBER TO CUT
149   }
150   Double_t* prodErr = new Double_t[2];
151   prodErr[0] = prod;
152   prodErr[1] = prod*TMath::Sqrt(relProdErrSquare);
153   //printf("-> %f %f\n", prodErr[0], prodErr[1]); // REMEMBER TO CUT
154   return prodErr;
155 }
156
157
158 //_____________________________________________________________________________
159 Double_t* GetConditionalEffErr(Double_t* effErr1, Double_t* effErr2, Double_t* effErrBoth, Int_t exclude = -1)
160 {
161   /// Error on conditional efficiency
162   Double_t* effErr = new Double_t[2*kNch];
163   for ( Int_t ich=0; ich<kNch; ich++ ) {
164     if ( ich == exclude ) {
165       effErr[ich] = ( effErr1[ich] < 1. ) ? ( effErr2[ich] - effErrBoth[ich] ) / ( 1. - effErr1[ich] ) : 0.;
166       effErr[ich+kNch] = 0;
167       if ( effErr1[ich] < 1. ) {
168         Double_t err2 = effErr2[ich+kNch] / ( 1. - effErr1[ich] );
169         Double_t errBoth = effErrBoth[ich+kNch] / ( 1. - effErr1[ich] );
170         Double_t err1 = effErr1[ich+kNch] * effErr[ich] / ( 1. - effErr1[ich] );
171         effErr[ich+kNch] = TMath::Sqrt(err2*err2 + errBoth*errBoth + err1*err1);
172       }
173     }
174     else {
175       effErr[ich] = ( effErr1[ich] > kZero ) ? effErrBoth[ich]/effErr1[ich] : 0.;
176       Double_t relErr1 = ( effErr1[ich] > kZero ) ? effErr1[ich+kNch]/effErr1[ich] : 0.;
177       Double_t relErrBoth = ( effErrBoth[ich] > kZero ) ? effErrBoth[ich+kNch]/effErrBoth[ich] : 0.;
178       effErr[ich+kNch] = effErr[ich] * TMath::Sqrt(relErr1*relErr1 + relErrBoth*relErrBoth);
179     }
180     //printf("%f  %f  %f -> %f\n", effErr1[ich], effErr2[ich], effErrBoth[ich], effErr[ich]); // REMEMBER TO CUT
181   } // loop on chambers
182   return effErr;
183 }
184
185
186 //_____________________________________________________________________________
187 Double_t* GetBinomial(Double_t* effErr1, Double_t* effErr2 = 0x0, Double_t* effErrBoth = 0x0)
188 {
189   /// Binomial error
190   Double_t effProd[4];
191   Double_t defaultEffErr[2] = {1.,0.};
192   Double_t* auxBinomial = 0x0;
193   Double_t* currEffErr44 = 0x0;
194   Double_t* effErrBinomial = new Double_t[2];
195   effErrBinomial[0] = 0.;
196   effErrBinomial[1] = 0.;
197   
198   for ( Int_t ich = -1; ich<kNch; ich++ ) {
199     Double_t* currEffErr = GetProdErr(effErr1, ich);
200     if ( ich >= 0 ) {
201       currEffErr[0] = currEffErr[0] - currEffErr44[0];
202       currEffErr[1] = TMath::Sqrt(currEffErr[1]*currEffErr[1] + currEffErr44[1]*currEffErr44[1]);
203     }
204     if ( effErr2 ) {
205       Double_t* auxEffErr = GetConditionalEffErr(effErr1, effErr2, effErrBoth, ich);
206       auxBinomial = GetBinomial(auxEffErr);
207       delete auxEffErr;
208     }
209     for ( Int_t ival=0; ival<2; ival++ ) {
210       effProd[2*ival] = currEffErr[ival];
211       effProd[2*ival+1] = ( effErr2 ) ? auxBinomial[ival] : defaultEffErr[ival];
212     }
213     if ( ich < 0 ) currEffErr44 = currEffErr;
214     else delete currEffErr;
215     delete auxBinomial;
216     
217     Double_t* effErr = GetProdErr(effProd, -1, 2);
218     //printf("%f * %f = %f\n", effProd[0], effProd[1], effErr[0]); // REMEMBER TO CUT
219     effErrBinomial[0] += effErr[0];
220     effErrBinomial[1] += effErr[1]*effErr[1];
221     delete effErr;
222   } // loop on chambers
223   
224   delete currEffErr44;
225   
226   effErrBinomial[1] = TMath::Sqrt(effErrBinomial[1]);
227   
228   return effErrBinomial;
229 }
230
231
232 //_____________________________________________________________________________
233 TH1* GetHisto(TString histoName, TFile* file, TList* histoList)
234 {
235   /// Get histogram
236   TH1* histo = 0x0;
237   if ( histoList )
238     histo = (TH1*)histoList->FindObject(histoName.Data());
239   else
240     histo = (TH1*)file->FindObjectAny(histoName.Data());
241   
242   return histo;
243 }
244
245 //_____________________________________________________________________________
246 Int_t GetEffIndex ( Int_t iel, Int_t icount, Int_t ich = -1 )
247 {
248   /// Get efficienct histogram index
249   if ( iel == 0 ) return icount;
250   return 3 + 4*3*(iel-1) + 3*ich + icount;
251 }
252
253 //_____________________________________________________________________________
254 TList* GetOCDBList ( )
255 {
256   /// Get list of CDB objetcs
257   TString storageType = AliCDBManager::Instance()->GetDefaultStorage()->GetType();
258   Bool_t isGrid = storageType.Contains("alien");
259   TString baseFolder = AliCDBManager::Instance()->GetDefaultStorage()->GetBaseFolder();
260   
261   TList* outList = new TList();
262   outList->SetOwner();
263   TString dirName[3] = {"GlobalTriggerCrateConfig", "RegionalTriggerConfig", "LocalTriggerBoardMasks"};
264   for ( Int_t idir=0; idir<3; idir++ ) {
265     if ( isGrid ) {
266       TGridResult *res = gGrid->Ls(Form("%s/MUON/Calib/%s", baseFolder.Data(), dirName[idir].Data()));
267       if (!res) return 0x0;
268       for ( Int_t ires=0; ires<res->GetEntries(); ires++ ) {
269         TString currFile = static_cast<TMap*>(res->At(ires))->GetValue("name")->GetName();
270         outList->Add(new TObjString(currFile));
271       }
272     }
273     else {
274       TString fileListStr = gSystem->GetFromPipe(Form("ls %s/MUON/Calib/%s", baseFolder.Data(), dirName[idir].Data()));
275       TObjArray* fileList = fileListStr.Tokenize("\n");
276       for ( Int_t ires=0; ires<fileList->GetEntries(); ires++ ) {
277         TString currFile = fileList->At(ires)->GetName();
278         outList->Add(new TObjString(currFile));
279       }
280       delete fileList;
281     }
282   }
283   return outList;
284 }
285
286 //_____________________________________________________________________________
287 Bool_t IsOCDBChanged ( Int_t currRun, Int_t previousRun, TList* fileList )
288 {
289   /// Check if the OCDB object is changed w.r.t. the previous run
290   if ( ! fileList ) return kTRUE;
291   for ( Int_t ifile=0; ifile<fileList->GetEntries(); ifile++ ) {
292     TString filename = static_cast<TObjString*>(fileList->At(ifile))->GetString();
293     filename.ReplaceAll("Run","");
294     TObjArray* array = filename.Tokenize("_");
295     Int_t firstRun = static_cast<TObjString*>(array->At(0))->GetString().Atoi();
296     Int_t lastRun = static_cast<TObjString*>(array->At(1))->GetString().Atoi();
297     delete array;
298     Bool_t isCurrRunInside = ( currRun >= firstRun && currRun <= lastRun );
299     Bool_t isPreviousRunInside = ( previousRun >= firstRun && previousRun <= lastRun );
300     if ( isCurrRunInside != isPreviousRunInside ) return kTRUE;
301   }
302   return kFALSE;
303 }
304
305 //_____________________________________________________________________________
306 void TrigEffTrending(TObjArray runNumArray, TObjArray fileNameArray, TList& outCanList, TList& outList)
307 {
308   /// Get the efficiency vs. run number
309   TString elementName[3] = { "Chamber", "RPC", "Board" };
310   TString countTypeName[4] = { "allTracks", "bendPlane", "nonBendPlane", "bothPlanes" };
311
312   TString filename = "", effName = "", effTitle = "";
313
314   SetMyStyle();
315   Double_t effValues[3][2*kNch];
316   const Int_t kNgraphs = kNch*3*2+3;
317   TObjArray effList(kNgraphs);
318   const Int_t kNeffVsRun = kNgraphs+1;
319   TObjArray effVsRunList(kNeffVsRun);
320   
321   effName = "totalEffEvolution";
322   effTitle = "Multinomial probability of firing at least 3/4 chambers";
323   TH1D* totalEff = new TH1D(effName.Data(), effTitle.Data(), 0, 0., 1.);
324   effVsRunList.AddAt(totalEff, kNeffVsRun-1);
325
326   TString runNumString = "";
327   for ( Int_t irun=0; irun<runNumArray.GetEntries(); irun++ ) {
328     runNumString = runNumArray.At(irun)->GetName();
329
330     // Search corresponding file (for sorting)
331     for ( Int_t ifile=0; ifile<fileNameArray.GetEntries(); ifile++ ) {
332       filename = fileNameArray.At(ifile)->GetName();
333       if ( filename.Contains(runNumString.Data()) ) break;
334     }
335
336     if ( filename.Contains("alien://") && ! gGrid ) gGrid->Connect("alien://");
337     
338     //
339     // First get the list of efficiency graphs
340     //
341     
342     // Chamber efficiency
343     TFile* file = TFile::Open(filename.Data());
344     if ( ! file ) {
345       printf("Warning: cannot find %s\n", filename.Data());
346       continue;
347     }
348     
349     TList* trigEffList = (TList*)file->FindObjectAny("triggerChamberEff");
350     if ( ! trigEffList ) printf("Warning: histo list not found in %s. Check directly in file\n", filename.Data());
351     
352     TH1* histoDen = 0x0;
353     for ( Int_t icount=0; icount<AliMUONTriggerEfficiencyCells::kNcounts; icount++ ) {
354       effName = countTypeName[icount] + "Count" + elementName[0];
355       if ( icount == 0 ) {
356         histoDen = GetHisto(effName, file, trigEffList);
357         continue;
358       }
359       
360       TH1* histoNum = GetHisto(effName, file, trigEffList);
361       TGraphAsymmErrors* graph = new TGraphAsymmErrors(histoNum, histoDen);
362       effName.ReplaceAll("Count","Eff");
363       graph->SetName(effName.Data());
364       effList.AddAt(graph, GetEffIndex(0, icount-1));
365     }
366     file->Close();
367   
368     if ( ! histoDen ) {
369       printf("Error: cannot find histograms in file %s. Skip to next\n", filename.Data());
370       continue;
371     }
372   
373     // RPC/board efficiency
374     AliMUONTriggerChamberEfficiency trigChEff(filename);
375     for ( Int_t iel=1; iel<3; iel++ ) {
376       for ( Int_t ich=0; ich<kNch; ich++ ) {
377         for ( Int_t icount=0; icount<AliMUONTriggerEfficiencyCells::kNcounts-1; icount++ ) {
378           TObject* obj = trigChEff.GetEffObject(2-iel, icount, ich);
379           effList.AddAt(obj, GetEffIndex(iel, icount, ich));
380         }
381       }
382     }
383     
384     // Fill efficiency vs run
385     for ( Int_t iel=0; iel<3; iel++ ) {
386       for ( Int_t ich=0; ich<kNch; ich++ ) {
387         for ( Int_t icount=0; icount<AliMUONTriggerEfficiencyCells::kNcounts-1; icount++ ) {
388           TGraphAsymmErrors* graph = static_cast<TGraphAsymmErrors*>(effList.At(GetEffIndex(iel, icount, ich)));
389           Int_t nPoints = ( iel == 0 ) ? 1 : graph->GetN();
390           for ( Int_t ipoint=0; ipoint<nPoints; ipoint++ ) {
391             Int_t currPoint = ( iel == 0 ) ? ich : ipoint;
392             Double_t xpt, ypt;
393             graph->GetPoint(currPoint, xpt, ypt);
394             effValues[icount][ich] = ypt;
395             Int_t ihisto = GetEffIndex(iel,icount,ich);
396             TH2* effHisto = static_cast<TH2*>(effVsRunList.At(ihisto));
397             if ( ! effHisto ) {
398               effName = Form("effEvolution%s%s", countTypeName[icount+1].Data(), elementName[iel].Data());
399               effTitle = Form("Trigger chamber efficiency vs run");
400               if ( iel>0 ) {
401                 effName += Form("Ch%i", 11+ich);
402                 effTitle += Form(" for chamber %i", 11+ich);
403               }
404               effHisto = new TH2D(effName.Data(), effTitle.Data(), 0, 0., 1., graph->GetN(), xpt-0.5, xpt-0.5+(Double_t)graph->GetN());
405               effVsRunList.AddAt(effHisto, ihisto);
406             }
407             Int_t currBin = effHisto->Fill(runNumString.Data(), xpt, ypt);
408             Double_t err = 0.5*(graph->GetErrorYlow(ipoint) + graph->GetErrorYhigh(ipoint));
409             Int_t binx, biny, binz;
410             effHisto->GetBinXYZ(currBin, binx, biny, binz);
411             effHisto->SetBinError(binx, biny, err);
412             effValues[icount][ich+kNch] = err;
413           } // loop on points
414         } // loop on counts
415       } // loop on chambers
416       if ( iel > 0 ) continue;
417       Double_t* binomialEff = GetBinomial(effValues[0], effValues[1], effValues[2]);
418       Int_t currBin = totalEff->Fill(runNumString, binomialEff[0]);
419       // CAVEAT!!!!
420       // Well, error calculation of the binomial efficiency is a mess...
421       // Sometimes it happens that efficiency + error > 1.
422       // In that case reduce the error.
423       totalEff->SetBinError(currBin, TMath::Min(binomialEff[1], 1.-binomialEff[0]));
424       delete binomialEff;
425     } // loop on detection elements
426   } // loop on runs
427   
428   // Set correct range (do not show last empty bins)
429   for ( Int_t ihisto=0; ihisto<effVsRunList.GetEntries(); ihisto++ ) {
430     TH1* histo = static_cast<TH1*>(effVsRunList.At(ihisto));
431     SetRunAxisRange(histo->GetXaxis());
432     outList.Add(histo);
433     //histo->GetXaxis()->SetLabelSize(0.03);
434   }
435
436   TString canName = "totalEff";
437   TCanvas* can = new TCanvas(canName.Data(), canName.Data(), 200, 10, 600, 600);
438   TH1* totEff = (TH1*)effVsRunList.At(kNeffVsRun-1);
439   totEff->GetYaxis()->SetRangeUser(0.9,1.05);
440   totEff->GetYaxis()->SetTitle("Probability to satisfy trigger conditions (3/4)");
441   totEff->SetStats(kFALSE);
442   totEff->DrawCopy();
443   outCanList.Add(can);
444
445   Int_t color[3] = {kBlack, kRed, kBlue};
446   Int_t markStyle[3] = {20, 24, 26};
447   TLegend* leg = 0x0;
448
449   for ( Int_t ich=0; ich<kNch; ich++ ) {
450     canName = Form("trigEffCh%i", 11+ich);
451     can = new TCanvas(canName.Data(), canName.Data(), 200, 10, 600, 600);
452     can->SetGridy();
453     leg = new TLegend(0.6, 0.2, 0.9, 0.4);
454     leg->SetBorderSize(1);
455     //can->Divide(2,2);
456     TString drawOpt = "e";
457     for(Int_t icount=0; icount<AliMUONTriggerEfficiencyCells::kNcounts-1; icount++) {
458       //can->cd(icount+1);
459       TH2* histo = static_cast<TH2*>(effVsRunList.At(GetEffIndex(0, icount)));
460       TH1* chEff = histo->ProjectionX(Form("effEvolutionCh%i",11+ich), ich+1, ich+1);
461       chEff->SetTitle(Form("%s for chamber %i", histo->GetTitle(), 11+ich));
462       chEff->GetYaxis()->SetRangeUser(0.9,1.);
463       chEff->SetStats(kFALSE);
464       chEff->GetYaxis()->SetTitle("Trigger chamber efficiency");
465       TH1* copyEff = chEff->DrawCopy(drawOpt.Data());
466       copyEff->SetLineColor(color[icount]);
467       copyEff->SetMarkerColor(color[icount]);
468       copyEff->SetMarkerStyle(markStyle[icount]);
469       leg->AddEntry(copyEff, countTypeName[icount+1].Data(), "lp");
470       drawOpt = "esame";
471     } // loop on counts
472     leg->Draw("same");
473     outCanList.Add(can);
474   } // loop on chambers
475   
476   for ( Int_t iel=1; iel<3; iel++ ) {
477     for ( Int_t ich=0; ich<kNch; ich++ ) {
478       Int_t icount = AliMUONTriggerEfficiencyCells::kBothPlanesEff; // Just plot the efficiency for both
479 //      for ( Int_t icount=0; icount<AliMUONTriggerEfficiencyCells::kNcounts-1; icount++ ) {
480         canName = Form("trigEff%sCh%i", elementName[iel].Data(), 11+ich);
481         can = new TCanvas(canName.Data(), canName.Data(), 200, 10, 600, 600);
482         can->SetRightMargin(0.14);
483         TH2* histo = static_cast<TH2*>(effVsRunList.At(GetEffIndex(iel, icount,ich)));
484         histo->SetStats(kFALSE);
485         histo->GetYaxis()->SetTitle(elementName[iel].Data());
486         histo->DrawCopy("COLZ");
487 //      } // loop on counts
488       outCanList.Add(can);
489     } // loop on chambers
490   } // loop on detection element type
491 }
492
493 //_____________________________________________________________________________
494 void MaskTrending ( TObjArray runNumArray, TString defaultStorage, TList& outCanList, TList& outList )
495 {
496   /// Get the masks vs. run number
497   if ( defaultStorage.Contains("alien://") || defaultStorage.Contains("raw://") ) {
498     if ( ! gGrid ) TGrid::Connect("alien://");
499     if ( ! gGrid ) {
500       printf("Error: Problem connetting to grid: nothing done");
501       return;
502     }
503   }
504   
505   
506   TObjArray maskedList(8);
507   TObjArray auxList(8);
508   auxList.SetOwner();
509   TString histoName = "", histoTitle = "";
510   for(Int_t icath=0; icath<2; icath++){
511     TString cathName = ( icath==0 ) ? "bendPlane" : "nonBendPlane";
512     for(Int_t ich=0; ich<kNch; ich++){
513       histoName = Form("%sMaskCh%i", cathName.Data(), 11+ich);
514       histoTitle = Form("Chamber %i - %s: fraction of masked channels", 11+ich, cathName.Data());
515       TH2* histo = new TH2D(histoName.Data(), histoTitle.Data(),0,0.,1., 234, 0.5, 234. + 0.5);
516       histo->GetYaxis()->SetTitle("Board Id");
517       histo->SetOption("COLZ");
518       Int_t imask = 2*ich + icath;
519       maskedList.AddAt(histo, imask);
520       auxList.AddAt(histo->Clone(Form("%s_aux",histoName.Data())), imask);
521     } // loop on chambers
522   } // loop on cathodes
523   
524   TArrayS xyPatternAll[2];
525   for(Int_t icath=0; icath<2; icath++){
526     xyPatternAll[icath].Set(kNch);
527     xyPatternAll[icath].Reset(0xFFFF);
528   }
529   
530   if ( ! AliCDBManager::Instance()->IsDefaultStorageSet() ) AliCDBManager::Instance()->SetDefaultStorage(defaultStorage.Data());
531   TList* ocdbFileList = 0x0;
532   Int_t previousRun = -1;
533   AliMUONDigitMaker* digitMaker = 0x0;
534   AliMUONDigitStoreV2R digitStore;
535   
536   AliMUONCalibrationData* calibData = 0x0;
537   AliMUONTriggerUtilities* trigUtilities = 0x0;
538   for ( Int_t irun=0; irun<runNumArray.GetEntries(); irun++ ) {
539     TString runNumString = runNumArray.At(irun)->GetName();
540     Int_t runNumber = runNumString.Atoi();
541     
542     if ( IsOCDBChanged(runNumber, previousRun, ocdbFileList) ) {
543       AliCDBManager::Instance()->SetRun(runNumber);
544       
545       if ( ! digitMaker ) {
546         digitMaker = new AliMUONDigitMaker(kFALSE);
547         // Create a store with all digits in trigger
548         for ( Int_t iboard=1; iboard<=234; iboard++ ) {
549           digitMaker->TriggerDigits(iboard, xyPatternAll, digitStore, kFALSE);
550         }
551       }
552       
553       if ( ! ocdbFileList ) ocdbFileList = GetOCDBList();
554   
555       delete calibData;
556       calibData = new AliMUONCalibrationData (runNumber);
557       delete trigUtilities;
558       trigUtilities = new AliMUONTriggerUtilities (calibData);
559     }
560     
561     previousRun = runNumber;
562     
563     TIter next(digitStore.CreateIterator());
564     AliMUONVDigit* dig = 0x0;
565     while ( ( dig = static_cast<AliMUONVDigit*>(next()) ) ) {
566       Int_t icath = dig->Cathode();
567       Int_t detElemId = dig->DetElemId();
568       Int_t ich = detElemId/100-11;
569       Int_t iboard = dig->ManuId();
570       Int_t imask = 2*ich + icath;
571       static_cast<TH2*>(auxList.At(imask))->Fill(runNumString.Data(),iboard,1.);
572       static_cast<TH2*>(maskedList.At(imask))->Fill(runNumString.Data(),iboard,(Double_t)trigUtilities->IsMasked(*dig));
573     }
574   } // loop on runs
575   delete calibData;
576   delete trigUtilities;
577   delete digitMaker;
578
579   TString canName = "";
580   for ( Int_t imask=0; imask<maskedList.GetEntries(); imask++ ) {
581     TH2* histo = static_cast<TH2*>(maskedList.At(imask));
582     histo->Divide(static_cast<TH2*>(auxList.At(imask)));
583     SetRunAxisRange(histo->GetXaxis());
584     outList.Add(histo);
585     
586     canName = Form("%sCan", histo->GetName());
587     TCanvas* can = new TCanvas(canName.Data(), canName.Data(), 200, 10, 600, 600);
588     can->SetRightMargin(0.14);
589     histo->SetStats(kFALSE);
590     histo->DrawCopy("COLZ");
591     outCanList.Add(can);
592   }
593 }
594
595 //_____________________________________________________________________________
596 Bool_t CheckPattern ( TString trigName, TObjArray* keepArray, TObjArray* rejectArray )
597 {
598   /// Check pattern
599   for ( Int_t ipat=0; ipat<rejectArray->GetEntries(); ++ipat ) {
600     if ( trigName.Contains(rejectArray->At(ipat)->GetName() ) ) return kFALSE;
601   } // loop on reject pattern
602   
603   for ( Int_t ipat=0; ipat<keepArray->GetEntries(); ++ipat ) {
604     if ( trigName.Contains(keepArray->At(ipat)->GetName() ) ) return kTRUE;
605   } // loop on keep pattern
606   
607   return ( keepArray->GetEntries() == 0 ) ? kTRUE : kFALSE;
608 }
609
610 //_____________________________________________________________________________
611 TObjArray* BuildListOfTrigger ( const TObjArray* triggerArray, TString keepPattern = "", TString rejectPattern="OTHER,TRUE,PHI,ANY,EMC,-ACE-,-ABCE-,WU,MUP,SPI,SHM" )
612 {
613   /// Build list of trigger classes
614   TObjArray* selectedList = new TObjArray();
615   selectedList->SetOwner();
616   TObjArray* rejectArray = rejectPattern.Tokenize(",");
617   TObjArray* keepArray = keepPattern.Tokenize(",");
618   
619   for ( Int_t iTrig = 0; iTrig < triggerArray->GetEntries(); iTrig++ ){
620     TString currTrigName = ((TObjString*)triggerArray->At(iTrig))->GetName();
621     if ( CheckPattern(currTrigName, keepArray, rejectArray) ) selectedList->AddLast(new TObjString(currTrigName.Data()));
622   }
623
624   delete rejectArray;
625   delete keepArray;
626
627   return selectedList;
628
629 }
630
631 //_____________________________________________________________________________
632 TString FindCorrespondingTrigger ( TString checkTrigger, TObjArray* triggerArray )
633 {
634   /// Find trigger from pattern
635   TString foundName = "";
636   for ( Int_t iTrig = 0; iTrig < triggerArray->GetEntries(); iTrig++ ){
637     TString currTrigName = ((TObjString*)triggerArray->At(iTrig))->GetName();
638     TObjArray* array = currTrigName.Tokenize("-");
639     TString collisionType = array->At(1)->GetName();
640     delete array;
641     collisionType.Append("-");
642     collisionType.Prepend("-");
643     if ( checkTrigger.Contains(collisionType.Data()) ) {
644       foundName = currTrigName;
645       break;
646     }
647   }
648
649   return foundName;
650 }
651   
652 //_____________________________________________________________________________
653 void ScalerTrending ( TObjArray runNumArray, TString mergedFileName, TString defaultStorage, TList& outCanList, TList& outList )
654 {
655   /// Get the scalers vs. run number
656   if ( defaultStorage.Contains("alien://") || defaultStorage.Contains("raw://") ) {
657     if ( ! gGrid ) TGrid::Connect("alien://");
658     if ( ! gGrid ) {
659       printf("Error: Problem connetting to grid: nothing done");
660       return;
661     }
662   }
663   
664   if ( ! AliCDBManager::Instance()->IsDefaultStorageSet() ) AliCDBManager::Instance()->SetDefaultStorage(defaultStorage.Data());
665
666   //trigger count from ESDs
667   TFile *file = TFile::Open(mergedFileName.Data());
668   AliCounterCollection* ccol = (AliCounterCollection*)((TDirectoryFile*)file->FindObjectAny("MUON_QA"))->FindObjectAny("eventCounters");
669   
670   //Build the trigger list for trigger with muon only in readout and min. bias triggers
671   TString triggerListName = ccol->GetKeyWords("trigger");
672   
673   TObjArray selectedTriggerArray, selectedL0TriggerArray;
674   selectedTriggerArray.SetOwner();
675   selectedL0TriggerArray.SetOwner();
676   
677   const Int_t nScaler = 3;
678   TString sScaler[nScaler] = {"L0B","L2A","L0BRATE"};
679   enum eScaler {kL0B = 0, kL2A=1, kL0BRATE=2};
680   Float_t maxScaler[nScaler] = {1e8,1e7,1e6};
681   TObjArray hFromQA;
682   TObjArray hFromScalers; 
683   TObjArray hOutput;
684   
685   
686   TString sHistName, sHistNameFull, sTitleName;
687   Int_t nRuns = runNumArray.GetEntries();
688
689   //
690   //Fill histos for Scalers and QA
691   //
692   //loop on run list
693   for ( Int_t iRun = 0; iRun < runNumArray.GetEntries(); iRun++ ) {
694     
695     TString sRunNr = ((TObjString*)runNumArray.At(iRun))->GetString();
696     Int_t runNr = sRunNr.Atoi();
697     AliAnalysisTriggerScalers triggerScaler(runNr);
698     AliTriggerConfiguration* tc = static_cast<AliTriggerConfiguration*>(triggerScaler.GetOCDBObject("GRP/CTP/Config",runNr));
699     const TObjArray& trClasses = tc->GetClasses();
700     
701     Int_t ibin = iRun+1;
702     
703     for ( Int_t itype=0; itype<2; itype++ ) {
704       TObjArray* currSelectedList = ( itype == 0 ) ? &selectedTriggerArray : &selectedL0TriggerArray;
705       TString matchTrig = ( itype == 0 ) ? "" : "C0TVX";
706       TObjArray* selectedTrigArrayForRun = BuildListOfTrigger(&trClasses, matchTrig);
707       
708       //loop on trigger list
709       for ( Int_t iTrig = 0; iTrig < selectedTrigArrayForRun->GetEntries(); iTrig++ ) {
710       
711         TString currTrigName = selectedTrigArrayForRun->At(iTrig)->GetName();
712         if ( itype == 0 && ! triggerListName.Contains(currTrigName.Data()) ) continue;
713         if ( ! currSelectedList->FindObject(currTrigName.Data()) ) currSelectedList->Add(new TObjString(currTrigName));
714         
715         //loop on scaler list
716         for ( Int_t iScaler = 0; iScaler < nScaler; iScaler++ ) {
717         
718           if ( itype == 1 && iScaler != kL0B ) continue;
719           
720           //from Scalers
721           TGraph* graph = triggerScaler.PlotTrigger(currTrigName.Data(),sScaler[iScaler].Data());
722         
723           sHistName = Form("%s_%s",currTrigName.Data(),sScaler[iScaler].Data());
724           sHistNameFull = Form("Scalers_%s",sHistName.Data());
725           
726           TH1* hist = (TH1*) hFromScalers.FindObject(sHistNameFull);
727           if ( ! hist ) {
728             hist = new TH1D(sHistNameFull,sHistName,nRuns,1.,1.+(Double_t)nRuns);
729             hist->SetDirectory(0);
730             hist->SetMinimum(1);
731             hist->SetMaximum(maxScaler[0]);
732             hFromScalers.AddLast(hist);
733             hOutput.AddLast(hist);
734             if ( iScaler == kL2A ) {
735               sHistNameFull = "QA_" + sHistName;
736               hFromQA.AddLast(hist->Clone(sHistNameFull.Data()));
737             }
738           }
739           Double_t *tab = (Double_t*) graph->GetY();
740           if ( tab ) hist->SetBinContent(ibin,tab[0]);
741           hist->GetXaxis()->SetBinLabel(ibin,sRunNr.Data());
742           delete graph;
743           
744           //from QA
745           if ( iScaler != kL2A ) continue;
746           TH1* histCounters = static_cast<TH1*>(ccol->Get("run",Form("run:%s/trigger:%s",sRunNr.Data(),currTrigName.Data())));
747           sHistNameFull = sHistNameFull = "QA_" + sHistName;
748           hist = (TH1*) hFromQA.FindObject(sHistNameFull);
749           if ( histCounters ) hist->SetBinContent(ibin,histCounters->GetSumOfWeights());
750           hist->GetXaxis()->SetBinLabel(ibin,sRunNr.Data());
751           delete histCounters;
752         }//end loop on scaler list
753       }//end loop on trigger list
754     } // end loop on type
755   }//end loop on run list
756   
757   
758   if ( selectedTriggerArray.GetEntries() == 0 ) {
759     printf("No trigger selected from trigger list %s\n",triggerListName.Data());
760     return;
761   }
762   printf("Nr of triggers selected %i\n",selectedTriggerArray.GetEntries());
763   
764   printf("Nr of T0 triggers selected %i\n",selectedL0TriggerArray.GetEntries());
765   
766   //Set options for QA and Scalers histos
767
768   for ( Int_t itype=0; itype<2; itype++ ) {
769     TObjArray* currList = ( itype == 0 ) ? &hFromScalers : &hFromQA;
770     for ( Int_t ihisto=0; ihisto<currList->GetEntriesFast(); ihisto++ ) {
771       TH1* histo = static_cast<TH1*> ( currList->At(ihisto) );
772       if (!histo) continue;
773       // Write run number to each bin
774       for ( Int_t iRun = 0; iRun < runNumArray.GetEntries(); iRun++ ) {
775         TString sRunNr = ((TObjString*)runNumArray.At(iRun))->GetString();
776         Int_t ibin = iRun+1;
777         TString binLabel = histo->GetXaxis()->GetBinLabel(ibin);
778         if ( ! binLabel.IsNull() ) continue;
779         histo->GetXaxis()->SetBinLabel(ibin,sRunNr.Data());
780       }
781       histo->SetStats(kFALSE);
782     }
783   }
784
785   
786   //Loop on histos from scalers and QA and create resulting histos from scalers
787   const Int_t nHisto = 3;
788   TString sHisto[nHisto] = {"L0BoverL0BC0TVX","L2AoverL0B","L2AQAoverSCALERS"};
789   TString sTitleHisto[nHisto] = {"L0B trigger / L0BC0TVX","L2A / L0B","L2A from QA / L2A from SCALERS"};
790   //  TString sHisto[nHisto] = {"L2AoverL0B","L2AQAoverSCALERS"};
791   
792   //loop on trigger list
793   for ( Int_t iTrig = 0; iTrig < selectedTriggerArray.GetEntries(); iTrig++ ) {
794
795     sHistNameFull = Form("Scalers_%s_L0B",((TObjString*) selectedTriggerArray.At(iTrig))->GetName());
796     TH1* histo1 = static_cast<TH1*> ( hFromScalers.FindObject(sHistNameFull) );
797     if (!histo1) continue;
798     
799     
800     //C0TVX
801     TString sTrig = ( (TObjString*) selectedTriggerArray.At(iTrig) )->GetName();
802     TString sL0Trig = FindCorrespondingTrigger(sTrig, &selectedL0TriggerArray);
803
804     sHistNameFull = Form("Scalers_%s_L0B",sL0Trig.Data());
805
806     TH1* histo0 = static_cast<TH1*> ( hFromScalers.FindObject(sHistNameFull) );
807     if ( histo0 ) {
808       sHistNameFull = Form("%s_%s",sHisto[0].Data(),((TObjString*) selectedTriggerArray.At(iTrig))->GetName());
809       TH1* histo10 = (TH1*) histo1->Clone(sHistNameFull);
810       histo10->SetTitle(sTitleHisto[0].Data());
811       histo10->Sumw2();
812       histo10->Divide(histo0);
813       histo10->SetMaximum(10);
814       histo10->SetMinimum(1e-5);
815       //outList.Add(histo10);
816       hOutput.AddLast(histo10);
817       //outList.Add(histo0);
818       //outList.Add(histo1);
819     }
820
821     //DEADTIME    
822     sHistNameFull = Form("Scalers_%s_L2A",((TObjString*) selectedTriggerArray.At(iTrig))->GetName());
823     TH1* histo2 = static_cast<TH1*> ( hFromScalers.FindObject(sHistNameFull) );
824     if (!histo2) continue;
825     
826     sHistNameFull = Form("%s_%s",sHisto[1].Data(),((TObjString*) selectedTriggerArray.At(iTrig))->GetName());
827     TH1* histo3 = (TH1*) histo2->Clone(sHistNameFull);
828     histo3->SetTitle(sTitleHisto[1]);
829     histo3->Sumw2();
830     histo3->Divide(histo1);
831     histo3->SetMaximum(1.2);
832     histo3->SetMinimum(1e-5);
833     //outList.Add(histo3);
834     hOutput.AddLast(histo3);
835     
836     //QA over Scalers
837     sHistNameFull = Form("QA_%s_L2A",((TObjString*) selectedTriggerArray.At(iTrig))->GetName());
838     TH1* histo4 = static_cast<TH1*> ( hFromQA.FindObject(sHistNameFull) );
839     if (!histo4) continue;
840     
841     sHistNameFull = Form("%s_%s",sHisto[2].Data(),((TObjString*) selectedTriggerArray.At(iTrig))->GetName());
842     TH1* histo5 = (TH1*) histo4->Clone(sHistNameFull);
843     histo5->SetTitle(sTitleHisto[2]);
844     histo5->Sumw2();
845     histo5->Divide(histo2);
846     histo5->SetMaximum(1.2);
847     histo5->SetMinimum(5e-1);
848     //outList.Add(histo5);
849     hOutput.AddLast(histo5);
850   }
851   
852   // Plot all on canvases (only canvases will be saved)
853   const Int_t nCanvases = nScaler + nHisto;
854   TString sCanvases[nCanvases];
855   for (Int_t iScaler = 0; iScaler < nScaler; iScaler++) sCanvases[iScaler] = sScaler[iScaler];
856   for (Int_t iHisto = 0; iHisto < nHisto; iHisto++) sCanvases[nScaler+iHisto] = sHisto[iHisto];
857   
858   //loop on canvases
859   for ( Int_t iCan = 0; iCan < nCanvases; iCan++) {
860     TCanvas* canvas = new TCanvas(sCanvases[iCan],sCanvases[iCan],200,10,600,600);
861     TLegend* leg  = new TLegend(0.72,0.7,0.9,0.85);
862     leg->SetBorderSize(1);
863     if ( iCan != 4 ) canvas->SetLogy();
864     TString optDraw = "e";
865     
866     //loop on trigger list
867     Int_t icolor = 1;
868     for ( Int_t iTrig = 0; iTrig < selectedTriggerArray.GetEntries(); iTrig++ ) {
869       
870       if ( iCan < nScaler ) sHistNameFull = Form("Scalers_%s_%s",selectedTriggerArray.At(iTrig)->GetName(),sCanvases[iCan].Data());
871       else sHistNameFull = Form("%s_%s",sCanvases[iCan].Data(),selectedTriggerArray.At(iTrig)->GetName());
872       TH1* histo1 = static_cast<TH1*> ( hOutput.FindObject(sHistNameFull) );
873       if (!histo1) continue;
874       
875       if ( icolor == 10 ) icolor++;
876       histo1->SetLineColor(icolor++);
877       histo1->Draw(optDraw);
878       optDraw = "esame";
879       
880       leg->AddEntry(histo1,selectedTriggerArray.At(iTrig)->GetName(),"l");
881     }
882     
883     leg->Draw();
884     outList.Add(canvas);
885     outCanList.Add(canvas);
886   }
887   
888   file->Close();
889 }
890
891 //_____________________________________________________________________________
892 void trigEffQA(TString fileListName, TString outFilename = "", TString defaultStorage = "raw://", Bool_t doScalers = kFALSE)
893 {
894   /// Main function
895   ifstream inFile(fileListName.Data());
896   TObjArray fileNameArray, runNumArray;
897   fileNameArray.SetOwner();
898   runNumArray.SetOwner();
899   TString currString = "";
900   if (inFile.is_open()) {
901     while (! inFile.eof() ) {
902       currString.ReadLine(inFile,kTRUE); // Read line
903       if ( currString.IsNull() || ! currString.Contains(".root") ||
904           currString.BeginsWith("#") ) continue;
905       fileNameArray.AddLast(new TObjString(currString.Data()));
906       Int_t runNum = GetRunNumber(currString);
907       runNumArray.AddLast(new TObjString(Form("%i",runNum)));
908     }
909     inFile.close();
910   }
911   else {
912     printf("Fatal: cannot open input file %s\n",fileListName.Data());
913     return;
914   }
915   
916   runNumArray.Sort();
917   
918   // Instead of using the efficiency stored in the QA output
919   // search for the new efficiency produced with trigger tracks only
920   TObjArray tmpArray = fileNameArray;
921   TObjArray* finalFileNameArray =  ChangeFilenames(tmpArray) ? &tmpArray : &fileNameArray;
922   
923   TList outCanList, outList;
924   TrigEffTrending(runNumArray, *finalFileNameArray, outCanList, outList);
925   if ( ! defaultStorage.IsNull() ) MaskTrending(runNumArray, defaultStorage, outCanList, outList);
926   if ( ! defaultStorage.IsNull() && doScalers ) ScalerTrending(runNumArray, "QAresults_Merged.root", defaultStorage, outCanList, outList);
927   
928   if ( outFilename.IsNull() ) return;
929   
930   TString outCanName = outFilename;
931   outCanName.ReplaceAll(".root",".pdf");
932   for ( Int_t ican=0; ican<outCanList.GetEntries(); ican++ ) {
933     TString canName = outCanName;
934     if ( ican == 0 ) canName.Append("("); // open pdf file
935     else if ( ican == outCanList.GetEntries()-1 ) canName.Append(")"); // close pdf file
936     static_cast<TCanvas*>(outCanList.At(ican))->Print(canName.Data());
937   }
938   // There is a bug when creating a pdf
939   // So create a ps and then convert via epstopdf
940   if ( outCanName.Contains(".ps") || outCanName.Contains(".eps") ) {
941     gSystem->Exec(Form("epstopdf %s", outCanName.Data()));
942     gSystem->Exec(Form("rm %s", outCanName.Data()));
943   }
944
945   TFile* outFile = new TFile(outFilename.Data(), "recreate");
946   outList.Write();
947   outFile->Close();
948 }