1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 #include "AliMUONTrackerQAChecker.h"
20 /// \class AliMUONTrackerQAChecker
22 /// Implementation of AliQACheckerBase for MCH and MTR
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.
27 /// \author Laurent Aphecetche, Subatech
29 #include "AliCDBManager.h"
30 #include "AliCodeTimer.h"
32 #include "AliMUONRecoParam.h"
33 #include "AliMUONTrackerQADataMakerRec.h"
34 #include "AliMpBusPatch.h"
35 #include "AliMpDDLStore.h"
38 #include "Riostream.h"
40 #include "TDirectory.h"
44 #include "TPaveText.h"
47 ClassImp(AliMUONTrackerQAChecker)
52 //___________________________________________________________________________
62 // Calculates the trimmed (tmean) mean
63 // of a sample (x) and estimates the variance (tvar)
67 // First check input parameters
69 // number of observations
75 if ( alpha < 0 || alpha >= 0.5 )
76 // proportion of observations
77 // to be trimmed at each end of the sorted sample
82 // Input parameters are good. Let's move on.
84 // Insure we use a sample sorted into ascending order.
86 Int_t* indices = new Int_t[n];
88 TMath::Sort(n,x,indices,kFALSE);
90 Double_t* sx = new Double_t[n];
92 for ( Int_t i = 0; i < n; ++i )
94 sx[i] = x[indices[i]];
99 // Number of observations trimmed at each end.
101 Int_t k = TMath::FloorNint(alpha * n);
105 for ( Int_t i = k; i < n - k ; ++i )
110 tmean = sum / ( n - 2 * k );
114 for ( Int_t i = k; i < n - k; ++i )
116 t2 += (sx[i] - tmean) * (sx[i] - tmean);
121 k * (sx[k] - tmean) * (sx[k] - tmean) +
122 k * (sx[n - k - 1] - tmean) * (sx[n - k - 1] - tmean)
125 // get the min and max for the non-rejected values
129 for ( Int_t i = k; i < n-k; ++i )
131 min = TMath::Min(min,sx[i]);
132 max = TMath::Max(max,sx[i]);
141 //__________________________________________________________________
142 AliMUONTrackerQAChecker::AliMUONTrackerQAChecker() : AliMUONVQAChecker()
147 //__________________________________________________________________
148 AliMUONTrackerQAChecker::~AliMUONTrackerQAChecker()
153 //__________________________________________________________________
154 AliMUONTrackerQAChecker::AliMUONTrackerQAChecker(const AliMUONTrackerQAChecker& qac) :
155 AliMUONVQAChecker(qac)
160 //______________________________________________________________________________
161 AliMUONVQAChecker::ECheckCode*
162 AliMUONTrackerQAChecker::CheckRecPoints(TObjArray ** list, AliMUONRecoParam* /*recoParam*/)
165 /// Very binary check for the moment.
167 AliCodeTimerAuto("",0);
169 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
170 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
171 rv[specie] = AliMUONVQAChecker::kInfo;
173 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
175 TH1* h = AliQAv1::GetData(list,AliMUONTrackerQADataMakerRec::kTrackerNumberOfClustersPerDE,AliRecoParam::ConvertIndex(specie));
177 if ( !h ) rv[specie] = AliMUONVQAChecker::kWarning; // only a warning if histo not found, in order not to kill anything because QA failed...
179 else if ( h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kFatal);
184 //______________________________________________________________________________
185 AliMUONVQAChecker::ECheckCode
186 AliMUONTrackerQAChecker::MarkHisto(TH1& histo, AliMUONVQAChecker::ECheckCode value) const
188 /// Mark histo as originator of some QA error/warning
190 if ( value != AliMUONVQAChecker::kInfo )
192 histo.SetBit(AliQAv1::GetQABit());
198 //______________________________________________________________________________
199 AliMUONVQAChecker::ECheckCode*
200 AliMUONTrackerQAChecker::CheckESD(TObjArray ** list, AliMUONRecoParam* /*recoParam*/)
204 AliCodeTimerAuto("",0);
206 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
207 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
208 rv[specie] = AliMUONVQAChecker::kInfo;
210 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
212 TH1* h = AliQAv1::GetData(list,AliMUONTrackerQADataMakerRec::kESDnTracks,AliRecoParam::ConvertIndex(specie));
214 if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
216 else if ( h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kFatal); // no track -> fatal
218 h = AliQAv1::GetData(list,AliMUONTrackerQADataMakerRec::kESDMatchTrig,AliRecoParam::ConvertIndex(specie));
220 if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
222 else if (h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kError); // no trigger matching -> error
227 //______________________________________________________________________________
228 AliMUONVQAChecker::ECheckCode*
229 AliMUONTrackerQAChecker::CheckRaws(TObjArray ** list, AliMUONRecoParam* recoParam)
233 AliCodeTimerAuto("",0);
235 if (!recoParam) return 0x0;
237 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
239 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
241 rv[specie] = AliMUONVQAChecker::kInfo;
244 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
246 TH1* hbp = AliQAv1::GetData(list,AliMUONTrackerQADataMakerRec::kTrackerBusPatchOccupancy,AliRecoParam::ConvertIndex(specie));
248 TH1* hnpads = AliQAv1::GetData(list,AliMUONTrackerQADataMakerRec::kTrackerBusPatchNofPads,AliRecoParam::ConvertIndex(specie));
250 TH1* hbpconfig = AliQAv1::GetData(list,AliMUONTrackerQADataMakerRec::kTrackerBusPatchConfig,AliRecoParam::ConvertIndex(specie));
252 if (!hbp || !hnpads )
257 rv[specie] = BeautifyTrackerBusPatchOccupancy(*hbp,hbpconfig,*hnpads,*recoParam);
263 //____________________________________________________________________________
264 AliMUONVQAChecker::ECheckCode
265 AliMUONTrackerQAChecker::BeautifyTrackerBusPatchOccupancy(TH1& hbp,
266 const TH1* hbuspatchconfig,
268 AliMUONRecoParam& recoParam)
270 /// Put labels, limits and so on on the TrackerBusPatchOccupancy histogram
271 /// hbuspatchconfig and hbp must have the same bin definitions
273 if ( hbuspatchconfig )
275 if ( hbp.GetNbinsX() != hbuspatchconfig->GetNbinsX() ||
276 hbp.GetXaxis()->GetXmin() != hbuspatchconfig->GetXaxis()->GetXmin() ||
277 hbp.GetXaxis()->GetXmax() != hbuspatchconfig->GetXaxis()->GetXmax() )
279 AliError("hbp and hbuspatchconfig histograms are not compatible !");
280 return AliMUONVQAChecker::kFatal;
284 hbp.SetXTitle("Absolute Bus Patch Id");
285 hbp.SetYTitle("Occupancy (percent)");
286 hbp.SetStats(kFALSE);
288 Double_t xmin = hbp.GetXaxis()->GetXmin();
289 Double_t xmax = hbp.GetXaxis()->GetXmax();
291 Double_t occMax(0.1); // 0.1% y-limit for the plot
292 Double_t maxToleratedOccupancy(recoParam.BuspatchOccupancyHighLimit()*100.0);
293 Double_t minToleratedOccupancy(recoParam.BuspatchOccupancyLowLimit()*100.0);
294 TLine* line1 = new TLine(xmin,maxToleratedOccupancy,xmax,maxToleratedOccupancy);
295 line1->SetLineColor(1);
296 line1->SetLineWidth(1);
298 TLine* line2 = new TLine(xmin,minToleratedOccupancy,xmax,minToleratedOccupancy);
299 line2->SetLineColor(1);
300 line2->SetLineWidth(1);
302 hbp.GetListOfFunctions()->Add(line1);
303 hbp.GetListOfFunctions()->Add(line2);
305 TIter next(AliMpDDLStore::Instance()->CreateBusPatchIterator());
306 AliMpBusPatch* bp(0x0);
308 Int_t nMissingPads(0);
310 Int_t nBusPatches(0);
311 Int_t nMissingBusPatches(0);
313 while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
315 Int_t bin = hbp.FindBin(bp->GetId());
316 Int_t n = hnpads.GetBinContent(bin);
322 if ( hbp.GetBinContent(bin) <= 0 )
325 ++nMissingBusPatches;
333 Int_t nBusPatchesAboveLimit(0);
334 Int_t nBusPatchesBelowLimit(0);
335 Double_t alpha(0.1); // trim 10% of data
336 Double_t tmean(0.0),tvar(0.0);
337 Double_t ymin(0.0),ymax(0.0);
338 AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kFatal); // default value = serious problem
342 Double_t* x = new Double_t[nBusPatches];
344 while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
346 Int_t bin = hbp.FindBin(bp->GetId());
347 if ( hbp.GetBinContent(bin) > 0 )
349 x[n] = hbp.GetBinContent(bin);
352 if ( hbp.GetBinContent(bin) > maxToleratedOccupancy )
354 ++nBusPatchesAboveLimit;
356 if ( hbp.GetBinContent(bin) < minToleratedOccupancy )
358 // check whether this buspatch has a reason to be absent (only valid
359 // if we got the config, otherwise we cannot do the test)
360 if ( hbuspatchconfig && hbuspatchconfig->GetBinContent(bin) > 0 )
362 // should be there, so it's an error
363 ++nBusPatchesBelowLimit;
368 // computed the truncated mean of the occupancy values, in order to get a
369 // reasonable y-range for the histogram (without giant peaks to the roof
370 // for misbehaving buspatches).
371 ok = trim(n,x,alpha,tmean,tvar,ymin,ymax);
382 ymax = TMath::Max(ymax,occMax);
385 hbp.SetMaximum(ymax*1.4);
387 TPaveText* text = new TPaveText(0.50,0.80,0.99,0.99,"NDC");
391 text->AddText("Could not compute truncated mean. Not enough events ?");
393 else if (!nPads || !nBusPatches)
395 text->AddText("Could not get the total number of pads. ERROR !!!");
399 Float_t missingPadFraction = nMissingPads*100.0/nPads;
400 Float_t missingBusPatchFraction = nMissingBusPatches*100.0/nBusPatches;
401 Float_t aboveLimitFraction = nBusPatchesAboveLimit*100.0/nBusPatches;
402 Float_t belowLimitFraction = nBusPatchesBelowLimit*100.0/nBusPatches;
404 text->AddText(Form("MCH RUN %d",AliCDBManager::Instance()->GetRun()));
405 text->AddText(Form("%5.2f %% of missing buspatches (%d out of %d)",missingBusPatchFraction,nMissingBusPatches,nBusPatches));
406 text->AddText(Form("%5.2f %% of missing pads (%d out of %d)",missingPadFraction,nMissingPads,nPads));
407 text->AddText(Form("%5.2f %% bus patches above the %5.2f %% limit",aboveLimitFraction,maxToleratedOccupancy));
408 text->AddText(Form("%5.2f %% bus patches below the %e %% limit",belowLimitFraction,minToleratedOccupancy));
409 text->AddText(Form("Truncated mean at %2d %% is %7.2f %%",(Int_t)(alpha*100),tmean));
411 if ( missingPadFraction >= 100.0 )
413 rv = AliMUONVQAChecker::kFatal;
416 else if ( missingPadFraction > recoParam.MissingPadFractionLimit()*100.0 ||
417 aboveLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 ||
418 belowLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 )
420 rv = AliMUONVQAChecker::kError;
424 rv = AliMUONVQAChecker::kInfo;
428 hbp.GetListOfFunctions()->Add(text);
430 if ( rv == AliMUONVQAChecker::kInfo )
432 text->SetFillColor(3); // green = INFO
434 else if ( rv == AliMUONVQAChecker::kWarning )
436 text->SetFillColor(5); // yellow = WARNING
438 else if ( rv == AliMUONVQAChecker::kFatal)
440 text->SetFillColor(2); // red = FATAL
444 text->SetFillColor(6); // pink = ERROR