]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONTrackerQAChecker.cxx
Adding a protection against division by zero in Fcn1();
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerQAChecker.cxx
CommitLineData
ece56eb9 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"
6482f70b 32#include "AliMUONQAIndices.h"
ece56eb9 33#include "AliMUONRecoParam.h"
ece56eb9 34#include "AliMpBusPatch.h"
35#include "AliMpDDLStore.h"
36#include "AliQAv1.h"
37#include "AliQAv1.h"
38#include "Riostream.h"
39#include "TAxis.h"
40#include "TDirectory.h"
41#include "TH1.h"
42#include "TLine.h"
43#include "TMath.h"
44#include "TPaveText.h"
b71c3d2d 45#include "TGaxis.h"
46#include "TVirtualPad.h"
ece56eb9 47
48/// \cond CLASSIMP
49ClassImp(AliMUONTrackerQAChecker)
50/// \endcond
51
52namespace {
53
54 //___________________________________________________________________________
55 int trim(Int_t n,
56 Double_t* x,
57 Double_t alpha,
58 Double_t& tmean,
59 Double_t& tvar,
60 Double_t& min,
61 Double_t& max)
62 {
63 //
64 // Calculates the trimmed (tmean) mean
65 // of a sample (x) and estimates the variance (tvar)
66 // of that mean.
67 //
68
69 // First check input parameters
70
71 // number of observations
72 if ( n < 2 )
73 {
74 return -1;
75 }
76
77 if ( alpha < 0 || alpha >= 0.5 )
78 // proportion of observations
79 // to be trimmed at each end of the sorted sample
80 {
81 return -2;
82 }
83
84 // Input parameters are good. Let's move on.
85
86 // Insure we use a sample sorted into ascending order.
87
88 Int_t* indices = new Int_t[n];
89
90 TMath::Sort(n,x,indices,kFALSE);
91
92 Double_t* sx = new Double_t[n];
93
94 for ( Int_t i = 0; i < n; ++i )
95 {
96 sx[i] = x[indices[i]];
97 }
98 delete[] indices;
99
100
101 // Number of observations trimmed at each end.
102
103 Int_t k = TMath::FloorNint(alpha * n);
104
105 double sum = 0.0;
106
107 for ( Int_t i = k; i < n - k ; ++i )
108 {
109 sum += sx[i];
110 }
111
112 tmean = sum / ( n - 2 * k );
113
114 double t2 = 0.0;
115
116 for ( Int_t i = k; i < n - k; ++i )
117 {
118 t2 += (sx[i] - tmean) * (sx[i] - tmean);
119 }
120
121 tvar = (
122 t2 +
123 k * (sx[k] - tmean) * (sx[k] - tmean) +
124 k * (sx[n - k - 1] - tmean) * (sx[n - k - 1] - tmean)
125 ) / (n * n);
126
127 // get the min and max for the non-rejected values
128 min = DBL_MAX;
129 max = 0.0;
130
131 for ( Int_t i = k; i < n-k; ++i )
132 {
133 min = TMath::Min(min,sx[i]);
134 max = TMath::Max(max,sx[i]);
135 }
136
137 delete[] sx;
138
139 return 0;
140 }
f2e6387f 141
142 //___________________________________________________________________________
143 void SetPaveColor(TPaveText& text, AliMUONVQAChecker::ECheckCode code)
144 {
145 const Int_t INFOCOLOR(3); // green = INFO
146 const Int_t WARNINGCOLOR(5); // yellow = WARNING
147 const Int_t ERRORCOLOR(6); // pink = ERROR
148 const Int_t FATALCOLOR(2); // red = FATAL
149
150 if ( code == AliMUONVQAChecker::kInfo ) text.SetFillColor(INFOCOLOR);
151 else if ( code == AliMUONVQAChecker::kWarning ) text.SetFillColor(WARNINGCOLOR);
152 else if ( code == AliMUONVQAChecker::kFatal) text.SetFillColor(FATALCOLOR);
153 else text.SetFillColor(ERRORCOLOR);
154 }
155
ece56eb9 156}
157
158//__________________________________________________________________
159AliMUONTrackerQAChecker::AliMUONTrackerQAChecker() : AliMUONVQAChecker()
160{
161 /// ctor
162}
163
164//__________________________________________________________________
165AliMUONTrackerQAChecker::~AliMUONTrackerQAChecker()
166{
167 /// dtor
168}
169
170//__________________________________________________________________
171AliMUONTrackerQAChecker::AliMUONTrackerQAChecker(const AliMUONTrackerQAChecker& qac) :
172 AliMUONVQAChecker(qac)
173{
174 /// copy ctor
175}
176
177//______________________________________________________________________________
178AliMUONVQAChecker::ECheckCode*
486788fc 179AliMUONTrackerQAChecker::CheckRecPoints(TObjArray ** list, const AliMUONRecoParam* /*recoParam*/)
ece56eb9 180{
181 /// Check rec points
182 /// Very binary check for the moment.
183
184 AliCodeTimerAuto("",0);
185
186 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
187 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
188 rv[specie] = AliMUONVQAChecker::kInfo;
189
6482f70b 190
ece56eb9 191 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
192 {
6482f70b 193 TH1* h = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNumberOfClustersPerDE,AliRecoParam::ConvertIndex(specie));
ece56eb9 194
195 if ( !h ) rv[specie] = AliMUONVQAChecker::kWarning; // only a warning if histo not found, in order not to kill anything because QA failed...
196
197 else if ( h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kFatal);
198 }
199 return rv;
200}
201
202//______________________________________________________________________________
203AliMUONVQAChecker::ECheckCode
204AliMUONTrackerQAChecker::MarkHisto(TH1& histo, AliMUONVQAChecker::ECheckCode value) const
205{
206 /// Mark histo as originator of some QA error/warning
207
208 if ( value != AliMUONVQAChecker::kInfo )
209 {
210 histo.SetBit(AliQAv1::GetQABit());
211 }
212
213 return value;
214}
215
216//______________________________________________________________________________
217AliMUONVQAChecker::ECheckCode*
486788fc 218AliMUONTrackerQAChecker::CheckESD(TObjArray ** list, const AliMUONRecoParam* /*recoParam*/)
ece56eb9 219{
220 /// Check ESD
221
222 AliCodeTimerAuto("",0);
223
224 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
225 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
226 rv[specie] = AliMUONVQAChecker::kInfo;
227
228 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
229
6482f70b 230 TH1* h = AliQAv1::GetData(list,AliMUONQAIndices::kESDnTracks,AliRecoParam::ConvertIndex(specie));
ece56eb9 231
232 if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
233
234 else if ( h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kFatal); // no track -> fatal
235
6482f70b 236 h = AliQAv1::GetData(list,AliMUONQAIndices::kESDMatchTrig,AliRecoParam::ConvertIndex(specie));
ece56eb9 237
238 if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
239
240 else if (h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kError); // no trigger matching -> error
241 }
242 return rv;
243}
244
245//______________________________________________________________________________
246AliMUONVQAChecker::ECheckCode*
486788fc 247AliMUONTrackerQAChecker::CheckRaws(TObjArray ** list, const AliMUONRecoParam* recoParam)
ece56eb9 248{
249 /// Check raws
250
251 AliCodeTimerAuto("",0);
252
253 if (!recoParam) return 0x0;
254
255 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
256
257 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
258 {
259 rv[specie] = AliMUONVQAChecker::kInfo;
260 }
261
262 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
263 {
6482f70b 264 TH1* hbp = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchOccupancy,AliRecoParam::ConvertIndex(specie));
ece56eb9 265
6482f70b 266 TH1* hnpads = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchNofPads,AliRecoParam::ConvertIndex(specie));
ece56eb9 267
6482f70b 268 TH1* hbpconfig = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchConfig,AliRecoParam::ConvertIndex(specie));
ece56eb9 269
64c2397e 270 TH1* hnevents = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNofRawEventSeen,AliRecoParam::ConvertIndex(specie));
271
b71c3d2d 272 TH1* hddl = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerDDLOccupancy,AliRecoParam::ConvertIndex(specie));
f2e6387f 273
274 TH1* hroe = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerReadoutErrors,AliRecoParam::ConvertIndex(specie));
275
276 TH1* hbuspatchtokenerrors = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchTokenLostErrors,AliRecoParam::ConvertIndex(specie));
b71c3d2d 277
f2e6387f 278 if ( !hbp || !hnpads || !hnevents || !hddl || !hroe || ! hbuspatchtokenerrors )
ece56eb9 279 {
280 continue;
281 }
64c2397e 282
b71c3d2d 283 Int_t nevents = TMath::Nint(hnevents->GetBinContent(1));
284
f2e6387f 285 rv[specie] = BeautifyHistograms(*hddl,*hbp,*hroe,hbpconfig,*hnpads,*hbuspatchtokenerrors,nevents,*recoParam);
ece56eb9 286 }
287
288 return rv;
289}
290
291//____________________________________________________________________________
292AliMUONVQAChecker::ECheckCode
f2e6387f 293AliMUONTrackerQAChecker::BeautifyHistograms(TH1& hddl,
294 TH1& hbp,
295 TH1& hroe,
296 const TH1* hbuspatchconfig,
297 const TH1& hnpads,
298 const TH1& hbuspatchtokenerrors,
299 Int_t nevents,
300 const AliMUONRecoParam& recoParam)
ece56eb9 301{
f2e6387f 302 /// Put labels, limits and so on on the TrackerBusPatchOccupancy and TrackerReadoutErrors histograms
ece56eb9 303 /// hbuspatchconfig and hbp must have the same bin definitions
304
305 if ( hbuspatchconfig )
306 {
307 if ( hbp.GetNbinsX() != hbuspatchconfig->GetNbinsX() ||
308 hbp.GetXaxis()->GetXmin() != hbuspatchconfig->GetXaxis()->GetXmin() ||
309 hbp.GetXaxis()->GetXmax() != hbuspatchconfig->GetXaxis()->GetXmax() )
310 {
311 AliError("hbp and hbuspatchconfig histograms are not compatible !");
312 return AliMUONVQAChecker::kFatal;
313 }
314 }
315
316 hbp.SetXTitle("Absolute Bus Patch Id");
317 hbp.SetYTitle("Occupancy (percent)");
318 hbp.SetStats(kFALSE);
319
320 Double_t xmin = hbp.GetXaxis()->GetXmin();
321 Double_t xmax = hbp.GetXaxis()->GetXmax();
322
323 Double_t occMax(0.1); // 0.1% y-limit for the plot
324 Double_t maxToleratedOccupancy(recoParam.BuspatchOccupancyHighLimit()*100.0);
325 Double_t minToleratedOccupancy(recoParam.BuspatchOccupancyLowLimit()*100.0);
326 TLine* line1 = new TLine(xmin,maxToleratedOccupancy,xmax,maxToleratedOccupancy);
327 line1->SetLineColor(1);
328 line1->SetLineWidth(1);
329
330 TLine* line2 = new TLine(xmin,minToleratedOccupancy,xmax,minToleratedOccupancy);
331 line2->SetLineColor(1);
332 line2->SetLineWidth(1);
333
334 hbp.GetListOfFunctions()->Add(line1);
335 hbp.GetListOfFunctions()->Add(line2);
336
337 TIter next(AliMpDDLStore::Instance()->CreateBusPatchIterator());
338 AliMpBusPatch* bp(0x0);
339
340 Int_t nMissingPads(0);
341 Int_t nPads(0);
342 Int_t nBusPatches(0);
343 Int_t nMissingBusPatches(0);
344
345 while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
346 {
347 Int_t bin = hbp.FindBin(bp->GetId());
b1f9e9c3 348 Int_t n = TMath::Nint(hnpads.GetBinContent(bin));
ece56eb9 349
350 ++nBusPatches;
351
352 nPads += n;
353
354 if ( hbp.GetBinContent(bin) <= 0 )
355 {
356 nMissingPads += n;
357 ++nMissingBusPatches;
358 }
359 }
360
361 next.Reset();
362
363 Int_t ok(-1);
364 Int_t n(0);
365 Int_t nBusPatchesAboveLimit(0);
366 Int_t nBusPatchesBelowLimit(0);
367 Double_t alpha(0.1); // trim 10% of data
368 Double_t tmean(0.0),tvar(0.0);
369 Double_t ymin(0.0),ymax(0.0);
370 AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kFatal); // default value = serious problem
371
372 if ( nBusPatches )
373 {
374 Double_t* x = new Double_t[nBusPatches];
375
376 while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
377 {
378 Int_t bin = hbp.FindBin(bp->GetId());
379 if ( hbp.GetBinContent(bin) > 0 )
380 {
381 x[n] = hbp.GetBinContent(bin);
382 ++n;
383 }
384 if ( hbp.GetBinContent(bin) > maxToleratedOccupancy )
385 {
386 ++nBusPatchesAboveLimit;
387 }
388 if ( hbp.GetBinContent(bin) < minToleratedOccupancy )
389 {
390 // check whether this buspatch has a reason to be absent (only valid
391 // if we got the config, otherwise we cannot do the test)
392 if ( hbuspatchconfig && hbuspatchconfig->GetBinContent(bin) > 0 )
393 {
394 // should be there, so it's an error
395 ++nBusPatchesBelowLimit;
396 }
397 }
398 }
399
400 // computed the truncated mean of the occupancy values, in order to get a
401 // reasonable y-range for the histogram (without giant peaks to the roof
402 // for misbehaving buspatches).
403 ok = trim(n,x,alpha,tmean,tvar,ymin,ymax);
404
405 delete[] x;
406 }
407
408 if ( ok < 0 )
409 {
410 ymax = occMax;
411 }
412 else
413 {
414 ymax = TMath::Max(ymax,occMax);
415 }
416
417 hbp.SetMaximum(ymax*1.4);
418
b71c3d2d 419 TPaveText* text = new TPaveText(0.30,0.50,0.99,0.99,"NDC");
ece56eb9 420
64c2397e 421 text->AddText(Form("MCH RUN %d - %d events",AliCDBManager::Instance()->GetRun(),nevents));
422
423 if ( ok < 0 )
ece56eb9 424 {
425 text->AddText("Could not compute truncated mean. Not enough events ?");
64c2397e 426 text->AddText(Form("nBusPatches=%d n=%d",nBusPatches,n));
ece56eb9 427 }
428 else if (!nPads || !nBusPatches)
429 {
64c2397e 430 text->AddText(Form("Could not get the total number of pads (%d) or total number of buspatches (%d). ERROR !!!",
431 nPads,nBusPatches));
ece56eb9 432 }
433 else
434 {
435 Float_t missingPadFraction = nMissingPads*100.0/nPads;
436 Float_t missingBusPatchFraction = nMissingBusPatches*100.0/nBusPatches;
437 Float_t aboveLimitFraction = nBusPatchesAboveLimit*100.0/nBusPatches;
438 Float_t belowLimitFraction = nBusPatchesBelowLimit*100.0/nBusPatches;
439
ece56eb9 440 text->AddText(Form("%5.2f %% of missing buspatches (%d out of %d)",missingBusPatchFraction,nMissingBusPatches,nBusPatches));
441 text->AddText(Form("%5.2f %% of missing pads (%d out of %d)",missingPadFraction,nMissingPads,nPads));
442 text->AddText(Form("%5.2f %% bus patches above the %5.2f %% limit",aboveLimitFraction,maxToleratedOccupancy));
443 text->AddText(Form("%5.2f %% bus patches below the %e %% limit",belowLimitFraction,minToleratedOccupancy));
b71c3d2d 444 text->AddText(Form("Bus patch mean occupancy (truncated at %2d %%) is %7.2f %%",(Int_t)(alpha*100),tmean));
ece56eb9 445
446 if ( missingPadFraction >= 100.0 )
447 {
448 rv = AliMUONVQAChecker::kFatal;
449 }
450
451 else if ( missingPadFraction > recoParam.MissingPadFractionLimit()*100.0 ||
452 aboveLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 ||
453 belowLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 )
454 {
455 rv = AliMUONVQAChecker::kError;
456 }
457 else
458 {
459 rv = AliMUONVQAChecker::kInfo;
460 }
461 }
462
463 hbp.GetListOfFunctions()->Add(text);
464
ece56eb9 465
f2e6387f 466 SetPaveColor(*text,rv);
467
b71c3d2d 468 /// Make as well a version for DDL occupancy, that'll be used by the shifter
469
470 hddl.GetListOfFunctions()->Add(text->Clone());
471
472 Bool_t aboveOnePercent(kFALSE);
473 Bool_t aboveTwoPercent(kFALSE);
474
475 for ( Int_t i = 1; i <= hddl.GetXaxis()->GetNbins(); ++i )
476 {
477 Double_t b = hddl.GetBinContent(i);
478 if ( b > 1.0 ) aboveOnePercent = kTRUE;
479 if ( b > 2.0 ) aboveTwoPercent = kTRUE;
480
481 }
482
483 hddl.SetMaximum(2);
484 hddl.SetFillStyle(0);
485 if ( aboveOnePercent )
486 {
487 hddl.SetFillStyle(1001);
488 hddl.SetFillColor(kOrange);
489 }
490 if ( aboveTwoPercent )
491 {
492 hddl.SetFillStyle(1001);
493 hddl.SetFillColor(kRed);
494 }
495 hddl.SetLineWidth(3);
496 hddl.SetStats(kFALSE);
497
f2e6387f 498 /// Finally make another pavetext for readout errors, in particular TokenLost ones !
499
500 Double_t tokenLost = hroe.GetBinContent(hroe.FindBin(1.0*AliMUONQAIndices::kTrackerRawNofTokenLostErrors));
501
502 AliInfo(Form("tokenLost=%e",tokenLost));
503
504 if ( tokenLost > 0 )
505 {
506 TPaveText* errText = new TPaveText(0.30,0.50,0.9,0.9,"NDC");
507
508 errText->AddText(Form("MCH RUN %d - %d events",AliCDBManager::Instance()->GetRun(),nevents));
509 errText->AddText("There are some token lost errors !");
510 errText->AddText("PLEASE CHECK THE BUSY TIME FOR MUON !");
511 errText->AddText("If above 5 ms please have the MUON expert");
512 errText->AddText("check the following bus patches :");
513
514 for ( Int_t i = 1; i <= hbuspatchtokenerrors.GetNbinsX(); ++i )
515 {
516 if ( hbuspatchtokenerrors.GetBinContent(i) > 0 )
517 {
518 errText->AddText(Form("BP %4d",i));
519 }
520 }
521
522 hroe.GetListOfFunctions()->Add(errText);
523
524 rv = AliMUONVQAChecker::kFatal;
525
526 SetPaveColor(*errText,rv);
527 }
528
ece56eb9 529 return rv;
530}