a8b07738c0d1a84c1fedcd6379640094e31ee9f0
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerQAChecker.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, 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 // $Id$
17
18 #include "AliMUONTrackerQAChecker.h"
19
20 /// \class AliMUONTrackerQAChecker
21 ///
22 /// Implementation of AliQACheckerBase for MCH and MTR
23 ///
24 /// For the moment we only implement the checking of raw data QA for the tracker
25 /// by looking at the occupancy at the bus patch level.
26 ///
27 /// \author Laurent Aphecetche, Subatech
28
29 #include "AliCDBManager.h"
30 #include "AliCodeTimer.h"
31 #include "AliLog.h"
32 #include "AliMUONQAIndices.h"
33 #include "AliMUONRecoParam.h"
34 #include "AliMpBusPatch.h"
35 #include "AliMpDDLStore.h"
36 #include "AliQAv1.h"
37 #include "Riostream.h"
38 #include "TAxis.h"
39 #include "TDirectory.h"
40 #include "TGaxis.h"
41 #include "TH1.h"
42 #include "TLine.h"
43 #include "TMath.h"
44 #include "TPaveText.h"
45 #include "TVirtualPad.h"
46 #include "TStyle.h"
47 #include "TLatex.h"
48
49 /// \cond CLASSIMP
50 ClassImp(AliMUONTrackerQAChecker)
51 /// \endcond
52
53 namespace {
54   
55   //___________________________________________________________________________  
56   int trim(Int_t n, 
57            Double_t* x,
58            Double_t alpha,
59            Double_t& tmean,
60            Double_t& tvar,
61            Double_t& min,
62            Double_t& max)
63   {
64     //
65     // Calculates the trimmed (tmean) mean
66     // of a sample (x) and estimates the variance (tvar)
67     // of that mean.
68     //
69     
70     // First check input parameters
71     
72     // number of observations
73     if ( n < 2 )
74     {
75       return -1;
76     }
77     
78     if ( alpha < 0 || alpha >= 0.5 )
79       // proportion of observations
80       // to be trimmed at each end of the sorted sample
81     {
82       return -2;
83     }
84     
85     // Input parameters are good. Let's move on.
86     
87     // Insure we use a sample sorted into ascending order.
88     
89     Int_t* indices = new Int_t[n];
90     
91     TMath::Sort(n,x,indices,kFALSE);
92     
93     Double_t* sx = new Double_t[n];
94     
95     for ( Int_t i = 0; i < n; ++i )
96     {
97       sx[i] = x[indices[i]];
98     }
99     delete[] indices;
100     
101     
102     // Number of observations trimmed at each end.
103     
104     Int_t k = TMath::FloorNint(alpha * n);
105     
106     double sum = 0.0;
107     
108     for ( Int_t i = k; i < n - k ; ++i )
109     {
110       sum += sx[i];
111     }
112     
113     tmean = sum / ( n - 2 * k );
114     
115     double t2 = 0.0;
116     
117     for ( Int_t i = k; i < n - k; ++i )
118     {
119       t2 += (sx[i] - tmean) * (sx[i] - tmean);
120     }
121     
122     tvar = (
123             t2 +
124             k * (sx[k] - tmean) * (sx[k] - tmean) +
125             k * (sx[n - k - 1] - tmean) * (sx[n - k - 1] - tmean)
126             ) / (n * n);
127     
128     // get the min and max for the non-rejected values
129     min = DBL_MAX;
130     max = 0.0;
131     
132     for ( Int_t i = k; i < n-k; ++i ) 
133     {
134       min = TMath::Min(min,sx[i]);
135       max = TMath::Max(max,sx[i]);
136     }
137     
138     delete[] sx;
139     
140     return 0;
141   }
142
143   //___________________________________________________________________________  
144   Int_t GetColorFromCheckCode(AliMUONVQAChecker::ECheckCode code)
145   {
146     if ( code == AliMUONVQAChecker::kInfo ) return AliMUONVQAChecker::kInfoColor;
147     else if ( code == AliMUONVQAChecker::kWarning ) return AliMUONVQAChecker::kWarningColor;
148     else if ( code ==  AliMUONVQAChecker::kFatal) return AliMUONVQAChecker::kFatalColor;
149     else return AliMUONVQAChecker::kErrorColor;
150   }
151   
152   const char* NOTENOUGHEVENTMESSAGE = "Not enough event to judge. Please wait a bit";
153   const char* NOTIFYEXPERTMESSAGE = "PLEASE NOTIFY EXPERT !";
154   const char* ALLISFINEMESSAGE = "All is fine. Just enjoy.";
155   
156   const int NOTENOUGHEVENTLIMIT = 50;
157   
158   //___________________________________________________________________________  
159   void SetupHisto(Int_t neventsseen, Int_t neventsused, const TObjArray& messages, TH1& histo, AliMUONVQAChecker::ECheckCode code, const char* extraopt="")
160   {
161     Bool_t allIsFine(kFALSE);
162     
163     if ( code == AliMUONVQAChecker::kInfo ) 
164     {
165       allIsFine = kTRUE;
166     }    
167     
168     Double_t y1 = 0.99 - (messages.GetLast()+(allIsFine?1:0)+2)*0.075;
169     
170     TPaveText* text = new TPaveText(0.5,y1,0.99,0.99,"NDC");
171     
172     text->AddText(Form("MCH RUN %d - %d events seen - %d events used",AliCDBManager::Instance()->GetRun(),neventsseen,neventsused));
173     
174     TIter next(&messages);
175     TObjString* str;
176     
177     while ( ( str = static_cast<TObjString*>(next()) ) )
178     {
179       text->AddText(str->String());
180     }
181     
182     if ( allIsFine )
183     {
184       text->AddText(ALLISFINEMESSAGE);
185     }
186                     
187     text->SetFillColor(GetColorFromCheckCode(code));
188                       
189     Int_t color = GetColorFromCheckCode(code);
190     
191     histo.SetFillStyle(1001);
192     histo.SetFillColor(color);    
193     TString sopt("BAR");
194     sopt += extraopt;
195     histo.SetOption(sopt.Data());
196     
197     histo.SetBit(TH1::kNoTitle); 
198     
199     TList* lstF = histo.GetListOfFunctions();
200     TObject* title = lstF->FindObject("title");
201     if (title) delete lstF->Remove(title);
202     // 
203     lstF->Add(text);  
204     
205   }
206
207   //___________________________________________________________________________  
208   void ShowTrueValue(TH1& hrostatusnorm, Int_t v)
209   {
210     // For a bar > 100% we put the text inside the bar (as TEXT45 option is putting above which
211     // would go offscreen)
212     
213     Int_t bin = hrostatusnorm.FindBin(1.0*v);
214     
215     Double_t value = hrostatusnorm.GetBinContent(bin);
216     
217     if ( value > 100.0 ) 
218     {
219       TLatex* l = new TLatex(hrostatusnorm.GetBinCenter(bin),50,Form("%g",value));
220       l->SetTextFont(gStyle->GetTextFont());
221       l->SetTextAlign(22);
222       l->SetTextAngle(45);
223       l->SetTextSize(0.02*hrostatusnorm.GetMarkerSize());
224       hrostatusnorm.GetListOfFunctions()->Add(l);
225     }
226   }
227
228 }
229 //__________________________________________________________________
230 AliMUONTrackerQAChecker::AliMUONTrackerQAChecker() : AliMUONVQAChecker()
231 {
232         /// ctor
233 }          
234
235 //__________________________________________________________________
236 AliMUONTrackerQAChecker::~AliMUONTrackerQAChecker() 
237 {
238         /// dtor
239 }
240
241 //__________________________________________________________________
242 AliMUONTrackerQAChecker::AliMUONTrackerQAChecker(const AliMUONTrackerQAChecker& qac) : 
243     AliMUONVQAChecker(qac) 
244 {
245         /// copy ctor 
246 }   
247
248 //______________________________________________________________________________
249 AliMUONVQAChecker::ECheckCode*
250 AliMUONTrackerQAChecker::CheckRecPoints(TObjArray ** list, const AliMUONRecoParam* /*recoParam*/)
251 {
252   /// Check rec points
253   /// Very binary check for the moment. 
254   
255   AliCodeTimerAuto("",0);
256   
257   AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ; 
258   for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) 
259     rv[specie] =  AliMUONVQAChecker::kInfo; 
260   
261   
262   for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) 
263   {
264     TH1* h = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNumberOfClustersPerDE,AliRecoParam::ConvertIndex(specie));
265
266     if ( !h ) rv[specie] = AliMUONVQAChecker::kWarning; // only a warning if histo not found, in order not to kill anything because QA failed...
267   
268     else if ( h->GetMean() == 0.0 ) rv[specie] =  MarkHisto(*h,AliMUONVQAChecker::kFatal);
269   }
270   return rv;
271 }
272
273 //______________________________________________________________________________
274 AliMUONVQAChecker::ECheckCode 
275 AliMUONTrackerQAChecker::MarkHisto(TH1& histo, AliMUONVQAChecker::ECheckCode value) const
276 {
277   /// Mark histo as originator of some QA error/warning
278   
279   if ( value != AliMUONVQAChecker::kInfo )
280   {
281     histo.SetBit(AliQAv1::GetQABit());
282   }
283   
284   return value;
285 }
286
287 //______________________________________________________________________________
288 AliMUONVQAChecker::ECheckCode*
289 AliMUONTrackerQAChecker::CheckESD(TObjArray ** list, const AliMUONRecoParam* /*recoParam*/)
290 {
291   /// Check ESD
292   
293   AliCodeTimerAuto("",0);
294   
295   AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ; 
296   for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) 
297     rv[specie] = AliMUONVQAChecker::kInfo; 
298   
299   for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
300     
301     TH1* h = AliQAv1::GetData(list,AliMUONQAIndices::kESDnTracks,AliRecoParam::ConvertIndex(specie));
302   
303     if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
304   
305     else if ( h->GetMean() == 0.0 ) rv[specie] =  MarkHisto(*h,AliMUONVQAChecker::kFatal); // no track -> fatal
306   
307     h = AliQAv1::GetData(list,AliMUONQAIndices::kESDMatchTrig,AliRecoParam::ConvertIndex(specie));
308   
309     if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
310   
311     else if (h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kError); // no trigger matching -> error
312   }
313   return rv;
314 }
315
316 //______________________________________________________________________________
317 AliMUONVQAChecker::ECheckCode*
318 AliMUONTrackerQAChecker::CheckRaws(TObjArray ** list, const AliMUONRecoParam* recoParam)
319 {
320   /// Check raws
321
322   AliCodeTimerAuto("",0);
323   
324   if (!recoParam) return 0x0;
325   
326   AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ; 
327
328   for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) 
329   {
330     rv[specie] = AliMUONVQAChecker::kInfo; 
331   }
332   
333   for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) 
334   {
335     TH1* hneventsseen = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNofPhysicsEventsSeen,AliRecoParam::ConvertIndex(specie));
336     TH1* hneventsused = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNofGoodPhysicsEventsUsed,AliRecoParam::ConvertIndex(specie));
337
338     if (!hneventsseen || !hneventsused ) continue;
339     
340     Int_t neventsseen = TMath::Nint(hneventsseen->GetBinContent(1));
341     Int_t neventsused = TMath::Nint(hneventsused->GetBinContent(1));
342         
343     AliMUONVQAChecker::ECheckCode c1 = AliMUONVQAChecker::kInfo;
344     AliMUONVQAChecker::ECheckCode c2 = AliMUONVQAChecker::kInfo;
345     AliMUONVQAChecker::ECheckCode c3 = AliMUONVQAChecker::kInfo;
346     
347     TH1* hbp = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchOccupancy,AliRecoParam::ConvertIndex(specie));    
348     TH1* hbpconfig = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchConfig,AliRecoParam::ConvertIndex(specie));
349     TH1* hddl = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerDDLOccupancy,AliRecoParam::ConvertIndex(specie));    
350
351     if ( hbp && hbpconfig && hddl ) 
352     {
353       c1 = BeautifyOccupancyHistograms(*hddl,*hbp,hbpconfig,neventsseen,neventsused,*recoParam);  
354     }
355     else
356     {
357       AliError(Form("Could not BeautifyOccupancyHistograms : hddl=%p hbpconfig=%p hbp=%p",hddl,hbpconfig,hbp));
358     }
359     
360     TH1* hbuspatchtokenerrors = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchTokenLostErrors,AliRecoParam::ConvertIndex(specie));
361     TH1* hrostatus = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerReadoutStatus,AliRecoParam::ConvertIndex(specie));    
362     TH1* hrostatusnorm = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerReadoutStatusPerEvent,AliRecoParam::ConvertIndex(specie));
363     
364     if ( hrostatus && hrostatusnorm && hbuspatchtokenerrors )
365     {
366       c2 = BeautifyReadoutHistograms(*hrostatus,*hrostatusnorm,*hbuspatchtokenerrors,
367                                      neventsseen,neventsused,*recoParam);
368     }
369     else
370     {
371       AliError(Form("Could not BeautifyReadoutHistograms : hrostatus=%p hrostatusnorm=%p hbuspatchtokenerrors=%p",
372                     hrostatus,hrostatusnorm,hbuspatchtokenerrors));
373     }
374     
375     
376     TH1* heventsize = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerDDLEventSize,AliRecoParam::ConvertIndex(specie));    
377     TH1* heventsizeperevent = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerDDLEventSizePerEvent,AliRecoParam::ConvertIndex(specie));
378     
379     if ( heventsize && heventsizeperevent ) 
380     {
381       c3 = BeautifyEventsizeHistograms(*heventsize,*heventsizeperevent,
382                                        neventsseen,neventsused,*recoParam);
383     }
384     else
385     {
386       AliError(Form("Could not BeautifyEventsizeHistograms heventsize=%p heventsizeperevent=%p",heventsize,heventsizeperevent));
387     }
388     
389     if ( c1 == AliMUONVQAChecker::kFatal || c2 == AliMUONVQAChecker::kFatal || c3 == AliMUONVQAChecker::kFatal )
390     {
391       rv[specie] = AliMUONVQAChecker::kFatal;
392     }
393     else if ( c1 == AliMUONVQAChecker::kError || c2 == AliMUONVQAChecker::kError || c3 == AliMUONVQAChecker::kError )
394     {
395       rv[specie] = AliMUONVQAChecker::kError;
396     }
397     else if ( c1 == AliMUONVQAChecker::kWarning || c2 == AliMUONVQAChecker::kWarning || c3 == AliMUONVQAChecker::kWarning )
398     {
399       rv[specie] = AliMUONVQAChecker::kWarning;
400     }
401     else
402     {
403       rv[specie] = AliMUONVQAChecker::kInfo;
404     }
405   }
406   
407   return rv;
408 }
409
410 //____________________________________________________________________________ 
411 AliMUONVQAChecker::ECheckCode
412 AliMUONTrackerQAChecker::BeautifyOccupancyHistograms(TH1& hddl,
413                                                      TH1& hbp, 
414                                                      const TH1* hbuspatchconfig, 
415                                                      Int_t neventsseen,
416                                                      Int_t neventsused,
417                                                      const AliMUONRecoParam& recoParam)
418 {
419   /// Put labels, limits and so on on the TrackerBusPatchOccupancy histograms
420   /// hbuspatchconfig and hbp must have the same bin definitions
421   
422   if ( hbuspatchconfig )
423   {
424     if ( hbp.GetNbinsX() != hbuspatchconfig->GetNbinsX() ||
425         hbp.GetXaxis()->GetXmin() != hbuspatchconfig->GetXaxis()->GetXmin() ||
426         hbp.GetXaxis()->GetXmax() != hbuspatchconfig->GetXaxis()->GetXmax() )
427     {
428       AliError("hbp and hbuspatchconfig histograms are not compatible !");
429       return AliMUONVQAChecker::kFatal;
430     }
431   }
432   
433   hddl.SetStats(kFALSE);
434   hbp.SetXTitle("Absolute Bus Patch Id");
435   hbp.SetYTitle("Occupancy (percent)");
436   hbp.SetStats(kFALSE);
437   
438   Double_t xmin = hbp.GetXaxis()->GetXmin();
439   Double_t xmax = hbp.GetXaxis()->GetXmax();
440   
441   Double_t occMax(0.1); // 0.1% y-limit for the plot
442   Double_t maxToleratedOccupancy(recoParam.BuspatchOccupancyHighLimit()*100.0); 
443   Double_t minToleratedOccupancy(recoParam.BuspatchOccupancyLowLimit()*100.0);   
444   TLine* line1 = new TLine(xmin,maxToleratedOccupancy,xmax,maxToleratedOccupancy);
445   line1->SetLineColor(1);
446   line1->SetLineWidth(1);
447
448   TLine* line2 = new TLine(xmin,minToleratedOccupancy,xmax,minToleratedOccupancy);
449   line2->SetLineColor(1);
450   line2->SetLineWidth(1);
451   
452   TList* lstF = hbp.GetListOfFunctions();
453   if (lstF) {
454     TObject *stats = lstF->FindObject("stats");
455     lstF->Remove(stats);
456     TObject *obj;
457     while ((obj = lstF->First())) { while(lstF->Remove(obj)) { } delete obj; }
458     if (stats) lstF->Add(stats);
459   } 
460   
461   hbp.GetListOfFunctions()->Add(line1);
462   hbp.GetListOfFunctions()->Add(line2);
463     
464   TIter next(AliMpDDLStore::Instance()->CreateBusPatchIterator());
465   AliMpBusPatch* bp(0x0);
466
467   Int_t nBusPatches(0);
468   Int_t nMissingBusPatches(0);
469   
470   while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
471   {
472     ++nBusPatches;
473     
474     Int_t bin = hbp.FindBin(bp->GetId());
475     
476     if ( hbp.GetBinContent(bin) <= 0.0 ) 
477     {
478       ++nMissingBusPatches;
479     }
480   }
481   
482   next.Reset();
483   
484   Int_t ok(-1);
485   Int_t n(0);
486   Int_t nBusPatchesAboveLimit(0);
487   Int_t nBusPatchesBelowLimit(0);
488   Double_t alpha(0.1); // trim 10% of data
489   Double_t tmean(0.0),tvar(0.0);
490   Double_t ymin(0.0),ymax(0.0);
491   
492   if ( nBusPatches ) 
493   {
494     Double_t* x = new Double_t[nBusPatches];
495     
496     while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
497     {
498       Int_t bin = hbp.FindBin(bp->GetId());
499       if ( hbp.GetBinContent(bin) > 0 )
500       {
501         x[n] = hbp.GetBinContent(bin);
502         ++n;
503       }
504       if ( hbp.GetBinContent(bin) > maxToleratedOccupancy )
505       {
506         ++nBusPatchesAboveLimit;
507       }
508       if ( hbp.GetBinContent(bin) < minToleratedOccupancy )
509       {
510         // check whether this buspatch has a reason to be absent (only valid
511         // if we got the config, otherwise we cannot do the test)
512         if ( hbuspatchconfig && hbuspatchconfig->GetBinContent(bin) > 0 )
513         {
514           // should be there, so it's an error
515           ++nBusPatchesBelowLimit;
516         }
517       }
518     }
519     
520     // computed the truncated mean of the occupancy values, in order to get a 
521     // reasonable y-range for the histogram (without giant peaks to the roof 
522     // for misbehaving buspatches).
523     ok = trim(n,x,alpha,tmean,tvar,ymin,ymax);
524     
525     delete[] x;
526   }
527   
528   if ( ok < 0 ) 
529   {
530     ymax = occMax;
531   }
532   else
533   {
534     ymax = TMath::Max(ymax,occMax);
535   }
536   
537   hbp.SetMaximum(ymax*1.4);
538   
539   AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kInfo);
540
541   TObjArray messages;
542   messages.SetOwner(kTRUE);
543   
544   if ( neventsseen < NOTENOUGHEVENTLIMIT ) 
545   {
546     messages.Add(new TObjString(NOTENOUGHEVENTMESSAGE));
547   }
548   else
549   {
550     if ( ok < 0 ) 
551     {
552       messages.Add(new TObjString("Could not compute truncated mean. Not enough events ?"));
553       
554       if ( neventsused < TMath::Nint(0.1*neventsseen) )
555       {
556         messages.Add(new TObjString(Form("We've actually seen %d events, but used only %d !",neventsseen,neventsused)));
557         messages.Add(new TObjString("For a normal physics run, this is highly suspect !"));
558         messages.Add(new TObjString(NOTIFYEXPERTMESSAGE));
559         rv = AliMUONVQAChecker::kFatal;
560       }
561     }
562     else if (!nBusPatches)
563     {
564       messages.Add(new TObjString(Form("Could not get the total number of buspatches (%d). ERROR !!!",
565                          nBusPatches)));
566       messages.Add(new TObjString("Please check with expert !"));
567       rv = AliMUONVQAChecker::kFatal;
568     }
569     else
570     {
571       Float_t missingBusPatchFraction = nMissingBusPatches*100.0/nBusPatches;
572       Float_t aboveLimitFraction = nBusPatchesAboveLimit*100.0/nBusPatches;
573       Float_t belowLimitFraction = nBusPatchesBelowLimit*100.0/nBusPatches;
574       
575       messages.Add(new TObjString(Form("%5.2f %% of missing buspatches (%d out of %d)",missingBusPatchFraction,nMissingBusPatches,nBusPatches)));
576       messages.Add(new TObjString(Form("%5.2f %% bus patches above the %5.2f %% limit",aboveLimitFraction,maxToleratedOccupancy)));
577       messages.Add(new TObjString(Form("%5.2f %% bus patches below the %e %% limit",belowLimitFraction,minToleratedOccupancy)));
578       messages.Add(new TObjString(Form("Bus patch mean occupancy (truncated at %2d %%) is %7.2f %%",(Int_t)(alpha*100),tmean)));
579       
580       if ( aboveLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 || 
581           belowLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 ) 
582       {
583         rv = AliMUONVQAChecker::kError;
584       }
585       else
586       {
587         rv = AliMUONVQAChecker::kInfo;
588       }
589     }
590   }
591   
592   SetupHisto(neventsseen,neventsused,messages,hbp,rv);
593   
594   /// Make as well a version for DDL occupancy, that'll be used by the shifter
595   SetupHisto(neventsseen,neventsused,messages,hddl,rv);
596   
597   
598   hddl.SetStats(kFALSE);
599   
600   return rv;
601 }
602
603 //______________________________________________________________________________
604 AliMUONVQAChecker::ECheckCode 
605 AliMUONTrackerQAChecker::BeautifyReadoutHistograms(TH1& hrostatus,
606                                                    TH1& hrostatusnorm,
607                                                    const TH1& hbuspatchtokenerrors,
608                                                    Int_t neventsseen,
609                                                    Int_t neventsused,
610                                                    const AliMUONRecoParam& recoParam)
611 {
612   /// Normalize and put some text on the readout error histogram
613   /// Note in particular the treatment of tokenlost errors !
614   
615   hrostatusnorm.Reset();
616   
617   AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kInfo);
618   
619   TObjArray messages;
620   messages.SetOwner(kTRUE);
621   
622   if ( neventsseen < NOTENOUGHEVENTLIMIT )
623   {
624     messages.Add(new TObjString(NOTENOUGHEVENTMESSAGE));
625   }
626   else
627   {
628     hrostatusnorm.Add(&hrostatus,100.0/neventsseen);
629     hrostatusnorm.SetOption("TEXT45"); // note : cannot use HIST option, otherwise the associated function (i.e. the tpavetext) is not drawn...
630     hrostatusnorm.SetMinimum(0.0);
631     hrostatusnorm.SetMaximum(100.0);
632     
633     Double_t tokenLost = hrostatusnorm.GetBinContent(hrostatusnorm.FindBin(1.0*AliMUONQAIndices::kTrackerRawNofTokenLostErrors));
634     
635     if ( tokenLost > recoParam.TokenLostLimit() )
636     {
637       rv = AliMUONVQAChecker::kError;
638       
639       messages.Add(new TObjString("There are some token lost errors !"));
640       messages.Add(new TObjString("PLEASE CHECK THE BUSY TIME FOR MUON !"));
641       messages.Add(new TObjString("If above 5 ms please have the MUON expert"));
642       messages.Add(new TObjString("check the following bus patches :"));
643       
644       for ( Int_t i = 1; i <= hbuspatchtokenerrors.GetNbinsX(); ++i ) 
645       {
646         if ( hbuspatchtokenerrors.GetBinContent(i) > 0 ) 
647         {
648           messages.Add(new TObjString(Form("BP %4d",i)));
649         }
650       }
651     }
652     
653     if ( hrostatusnorm.GetBinContent(hrostatusnorm.FindBin(AliMUONQAIndices::kTrackerRawNofEmptyEvents)) > 25.0 )
654     {
655       messages.Add(new TObjString("Too many empty events !"));
656       messages.Add(new TObjString(NOTIFYEXPERTMESSAGE));
657       rv = AliMUONVQAChecker::kFatal;      
658     }    
659   }
660    
661   SetupHisto(neventsseen,neventsused,messages,hrostatusnorm,rv,"text45");
662   
663   ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofTokenLostErrors);
664   ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofParityErrors);
665   ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofPaddingErrors);
666   ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofGlitchErrors);
667   
668   return rv;
669 }
670
671 //______________________________________________________________________________
672 AliMUONVQAChecker::ECheckCode 
673 AliMUONTrackerQAChecker::BeautifyEventsizeHistograms(TH1& heventsize,
674                                                      TH1& heventsizeperevent,
675                                                      Int_t neventsseen,
676                                                      Int_t neventsused,
677                                                      const AliMUONRecoParam& recoParam)
678 {
679   /// Normalize and put some text on the event size histogram
680
681   AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kInfo);
682
683   heventsizeperevent.Reset();
684
685   TObjArray messages;
686   messages.SetOwner(kTRUE);
687   
688   if ( neventsseen < NOTENOUGHEVENTLIMIT )
689   {
690     messages.Add(new TObjString(NOTENOUGHEVENTMESSAGE));
691   }
692   else
693   {
694     heventsizeperevent.Add(&heventsize,1.0/neventsseen/1024.0);
695     heventsizeperevent.SetMinimum(0);
696     
697     Double_t totalEventSizePerEvent = heventsizeperevent.Integral();
698     
699     TString msg;
700     TString action;
701     
702     if ( totalEventSizePerEvent > recoParam.EventSizeHardLimit() ) 
703     {
704       rv = AliMUONVQAChecker::kError;
705       msg = "That is really too high.";
706       action = NOTIFYEXPERTMESSAGE;
707     }
708     else if ( totalEventSizePerEvent > recoParam.EventSizeSoftLimit() ) 
709     {
710       msg = "That is a bit high.";
711       action = "Please keep an eye on it.";
712       rv = AliMUONVQAChecker::kWarning;
713     }
714     else 
715     {
716       rv = AliMUONVQAChecker::kInfo;
717     }
718     
719     messages.Add(new TObjString(Form("<MCH event size> %5.1f KB/event\n",totalEventSizePerEvent)));
720     if (msg.Length()>0)
721     {
722       messages.Add(new TObjString(msg));
723       messages.Add(new TObjString(action));
724     }
725   }
726   
727   SetupHisto(neventsseen,neventsused,messages,heventsizeperevent,rv);
728   
729   return rv;
730 }
731
732
733