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