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