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 **************************************************************************/
16 // Checks the quality assurance.
17 // By comparing with reference data
19 //---------------------------------------------
20 //checkig without reference data:
21 //for RAW QA all histograms should have approximatly the same
22 //number of entries as RefPoint
23 //for Rec Points checks
24 // - amplitude measured by 2 methos
25 // - online and offline T0 measurements
26 // for ESD quality of reconstruction ( and measurements):
27 // RMS of vertex and T0 less than 75ps
29 // Alla.Maevskaya@cern.ch
32 // --- ROOT system ---
33 #include <Riostream.h>
37 #include <TFitResultPtr.h>
39 #include <TIterator.h>
44 #include <TPaveText.h>
46 // --- Standard library ---
48 // --- AliRoot header files ---
51 #include "AliQAChecker.h"
52 #include "AliCDBEntry.h"
53 #include "AliQAManager.h"
54 #include "AliT0QAChecker.h"
56 ClassImp(AliT0QAChecker)
57 //____________________________________________________________________________
58 AliT0QAChecker::AliT0QAChecker() :
59 AliQACheckerBase("T0","T0 Quality Assurance Checker")
62 // Standard constructor
66 //____________________________________________________________________________
67 AliT0QAChecker::AliT0QAChecker(const AliT0QAChecker& qac):
68 AliQACheckerBase(qac.GetName(), qac.GetTitle())
71 AliError("Copy should not be used with this class\n");
73 //____________________________________________________________________________
74 AliT0QAChecker& AliT0QAChecker::operator=(const AliT0QAChecker& qac){
75 // assignment operator
76 this->~AliT0QAChecker();
77 new(this)AliT0QAChecker(qac);
82 //____________________________________________________________________________
83 AliT0QAChecker::~AliT0QAChecker(){
88 //__________________________________________________________________
89 void AliT0QAChecker::Check(Double_t * test, AliQAv1::ALITASK_t index, TObjArray ** list, const AliDetectorRecoParam * /*recoParam*/)
91 // Super-basic check on the QA histograms on the input list:
92 // look whether they are empty!
94 char * detOCDBDir = Form("T0/%s/%s", AliQAv1::GetRefOCDBDirName(), AliQAv1::GetRefDataDirName()) ;
96 AliCDBEntry *QARefRec = AliQAManager::QAManager()->Get(detOCDBDir);
99 AliInfo("QA reference data NOT retrieved for Reconstruction check. No T0 reference distribution");
103 for(Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++){
104 test[specie] = 1.0; //FK// initiate qa flag for the whole set of histograms as good
108 for(Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
109 if(!(AliQAv1::Instance()->IsEventSpecieSet(specie) && list[specie]) || list[specie]->GetEntries() == 0) {
113 if(index == AliQAv1::kRAW){
115 if(AliRecoParam::ConvertIndex(specie) == AliRecoParam::kCalib){// if (index == AliQAv1::kRAW )
116 //check laser data efficiencies
117 Double_t qaFlag = CheckLaser(list[specie]);
118 if(qaFlag < test[specie]) test[specie] = qaFlag;
121 if(AliRecoParam::ConvertIndex(specie) == AliRecoParam::kCalib ||
122 AliRecoParam::ConvertIndex(specie) == AliRecoParam::kHighMult ||
123 AliRecoParam::ConvertIndex(specie) == AliRecoParam::kLowMult){
124 //AliRecoParam::ConvertIndex(specie) == AliRecoParam::kDefault ||
127 Double_t qaFlag = CheckBCID(list[specie]);
128 if(qaFlag < test[specie]) test[specie] = qaFlag;
131 if(AliRecoParam::ConvertIndex(specie) == AliRecoParam::kHighMult ||
132 AliRecoParam::ConvertIndex(specie) == AliRecoParam::kLowMult){
133 //AliRecoParam::ConvertIndex(specie) == AliRecoParam::kDefault ||
135 Double_t qaFlag = CheckRaw(list[specie]);
136 if(qaFlag < test[specie]) test[specie] = qaFlag;
140 if(index == AliQAv1::kESD && AliRecoParam::Convert(specie) != AliRecoParam::kCalib){
141 test[specie] = CheckESD(list[specie]);
146 //--------------------------------------------------------------------------
147 Double_t AliT0QAChecker::CheckLaser(TObjArray *listrec) const {
153 //thresholds for warning and error on efficiencies
154 Float_t thrWarning = 0.5; //FK// warning level
155 Float_t thrError = 0.2; //FK// error level
157 const int kNumberOfHistos = 3;
158 Int_t consecutiveHistoNumber[kNumberOfHistos] = { 207, 208, 209}; //Checked histos fhCDFeff, hEffLED, hEffQTC
159 Int_t qualityFlag[kNumberOfHistos]; //quality flag for a given histogram
161 for(Int_t ir=0; ir<kNumberOfHistos; ir++){
162 qualityFlag[ir] = kT0Info; //init quality flag for a given histogram
164 hdata = (TH1*) listrec->UncheckedAt(consecutiveHistoNumber[ir]);
166 fhRawEff[nEffHistos] = hdata;
171 TLine linelowyellow(0, thrWarning, 24, thrWarning);
172 linelowyellow.SetLineColor(5);
173 linelowyellow.SetLineStyle(3);
174 linelowyellow.SetLineWidth(4);
175 TLine linelowred(0, thrError, 24, thrError);
176 linelowred.SetLineColor(2);
177 linelowred.SetLineStyle(3);
178 linelowred.SetLineWidth(4);
180 Bool_t bEffHistosNotEmpty = kFALSE; //check if all histograms have some counts
182 for(Int_t ih = 0; ih < nEffHistos; ih++){
184 EraseOldMessages((TH1*) fhRawEff[ih]);// clean objects added at previous checks
186 fhRawEff[ih]->SetLineWidth(2);
187 fhRawEff[ih]->SetMaximum(2.);
188 fhRawEff[ih]->SetMinimum(0.);
189 fhRawEff[ih]->GetListOfFunctions()->Add((TLine*)linelowyellow.Clone());
190 fhRawEff[ih]->GetListOfFunctions()->Add((TLine*)linelowred.Clone());
192 if(fhRawEff[ih]->Integral()>0) bEffHistosNotEmpty = kTRUE; //this histo does have some counts in it
194 Int_t nbins= fhRawEff[ih]->GetNbinsX();
195 for(Int_t ib=1; ib<=nbins; ib++){ //loop over bins and check if the efficiency is above level
197 Float_t chcont = fhRawEff[ih]->GetBinContent(ib);
198 if(chcont < thrWarning && qualityFlag[ih] > kT0Error ) qualityFlag[ih] = kT0Warning;//Warning level
199 if(chcont < thrError) qualityFlag[ih] = kT0Error;//Error level
202 if(qualityFlag[ih] == kT0Info ){
203 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 efficiency %s is good", fhRawEff[ih]->GetName() ));
204 }else if(qualityFlag[ih] == kT0Warning){
205 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 efficiency %s is not so good", fhRawEff[ih]->GetName() ));
206 }else if(qualityFlag[ih] == kT0Error){
207 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 efficiency %s is not good", fhRawEff[ih]->GetName() ));
212 int lowestQualityFlag = (int) kT0Info;
213 for(Int_t ih = 0; ih < nEffHistos; ih++){
215 if(!bEffHistosNotEmpty){ //all laser efficiency plots are empty
217 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
218 text.AddText(Form("1) T0 is in BEAMTUNIG: empty plots are ok"));
219 text.AddText(Form("2) T0 is in READY: check calibriation trigger"));
220 text.AddText(Form("if also physics data are empty report"));
221 text.AddText(Form("readout problem to the T0 on-call expert"));
222 text.SetBorderSize(0);
223 text.SetFillStyle(0);
224 fhRawEff[ih]->GetListOfFunctions()->Add((TPaveText*)text.Clone());
227 if( qualityFlag[ih] <lowestQualityFlag ) lowestQualityFlag = qualityFlag[ih];
230 return ConvertQualityFlagToDouble(lowestQualityFlag);
232 //--------------------------------------------------------------------------
233 Double_t AliT0QAChecker::CheckBCID(TObjArray *listrec) const {
235 Int_t qualityFlagBCID = kT0Info; //init quality flag for a given histogram;
237 TH2F *hBCID = (TH2F*) listrec->UncheckedAt(224); //BCID versus TRM BCID
240 // clean objects added at previous checks
241 EraseOldMessages((TH1*)hBCID);
243 if(hBCID->Integral()>0){
244 //BCID does have some counts in it
246 Int_t nbinsX = hBCID->GetNbinsX();
247 Int_t nbinsY = hBCID->GetNbinsY();
248 double entriesOnDiagonal = 0; //count diagonal and off diagonal entries
249 double entriesOffDiagonal = 0;
253 for(Int_t itrm=1; itrm<=nbinsX; itrm++){ //BCID TRM
254 for(Int_t ibcid=1; ibcid<=nbinsY; ibcid++){ //BCID
255 if(TMath::Abs(itrm-ibcid)<6 || TMath::Abs( (itrm+offset)%period - ibcid)<2 ){
256 entriesOnDiagonal += hBCID->GetBinContent(itrm,ibcid); //On Diagonal
258 entriesOffDiagonal += hBCID->GetBinContent(itrm,ibcid); //Off Diagonal
262 if(entriesOnDiagonal<1 || entriesOffDiagonal>20){
263 qualityFlagBCID = kT0Warning; //no entries on diagonal
264 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 %s is not diagonal", hBCID->GetName() ));
266 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
267 text.AddText(Form("Check if entries are on a diagonal."));
268 text.AddText(Form("Report readout problem to the T0 on-call expert"));
269 text.SetBorderSize(0);
270 text.SetFillStyle(0);
271 hBCID->GetListOfFunctions()->Add((TPaveText*)text.Clone());
275 qualityFlagBCID = kT0Error;
276 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 : %s has NO entries", hBCID->GetName() ));
278 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
279 text.AddText(Form("NO ENTRIES!!!"));
280 text.AddText(Form("If T0 is READY report"));
281 text.AddText(Form("readout problem to the T0 on-call expert"));
282 text.SetBorderSize(0);
283 text.SetFillStyle(0);
284 hBCID->GetListOfFunctions()->Add((TPaveText*)text.Clone());
288 int lowestQualityFlag = (int) qualityFlagBCID;
290 return ConvertQualityFlagToDouble(lowestQualityFlag);
294 //--------------------------------------------------------------------------
295 Double_t AliT0QAChecker::CheckRaw(TObjArray *listrec) const {
298 Int_t qualityFlagTrigger = kT0Info; //init quality flag for a given histogram;
300 TH1F *hTrigger = (TH1F*) listrec->UncheckedAt(169);//hRawTrigger
303 // clean objects added at previous checks
304 EraseOldMessages((TH1*) hTrigger);
306 if(hTrigger->Integral()>0){
307 //trigger plot does have some counts in it
308 //are Mean, ORA and ORC not empty?
309 if( hTrigger->GetBinContent(1)<0.001 || hTrigger->GetBinContent(3)<0.001 || hTrigger->GetBinContent(4)<0.001){
310 qualityFlagTrigger = kT0Error; //no entries on diagonal
311 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0: too little ORA and ORC in %s", hTrigger->GetName() ));
313 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
314 text.AddText(Form("Check ORA and ORC"));
315 text.AddText(Form("Report problem to the T0 on-call expert"));
316 text.SetBorderSize(0);
317 text.SetFillStyle(0);
318 hTrigger->GetListOfFunctions()->Add((TPaveText*)text.Clone());
321 }else{ //Trigger histo empty
323 qualityFlagTrigger = kT0Error;
324 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 histogram %s has NO entries", hTrigger->GetName() ));
326 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
327 text.AddText(Form("NO ENTRIES!!!"));
328 text.AddText(Form("If T0 is READY report"));
329 text.AddText(Form("readout problem to the T0 on-call expert"));
330 text.SetBorderSize(0);
331 text.SetFillStyle(0);
332 hTrigger->GetListOfFunctions()->Add((TPaveText*)text.Clone());
336 //--------- timing plots ---------
337 Int_t qualityFlagMeanBest = kT0Info; //init quality flag for a given histogram;
338 TH1F *hMeanBest = (TH1F*) listrec->UncheckedAt(223); //fhMeanBest time
339 EraseOldMessages((TH1*) hMeanBest);
341 if(hMeanBest->Integral()<1){
342 qualityFlagMeanBest = kT0Error;
343 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 histogram %s has NO entries", hMeanBest->GetName() ));
345 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
346 text.AddText(Form("NO ENTRIES!!!"));
347 text.AddText(Form("If T0 is READY and beam is on report"));
348 text.AddText(Form("the problem to the T0 on-call expert"));
349 text.SetBorderSize(0);
350 text.SetFillStyle(0);
351 hMeanBest->GetListOfFunctions()->Add((TPaveText*)text.Clone());
357 //----------- vetext plots ---------
359 Int_t qualityFlagVetrexFirst = kT0Info; //init quality flag for a given histogram;
360 Int_t qualityFlagVetrexBest = kT0Info; //init quality flag for a given histogram;
362 TH1F *hVertexFirst = (TH1F*) listrec->UncheckedAt(225);//fhVertex1st
363 TH1F *hVertexBest = (TH1F*) listrec->UncheckedAt(226);//fhVertexBest
364 TH1F *hOrCminOrATvdcOn = (TH1F*) listrec->UncheckedAt(217);//vertex with TVDC on
366 // clean objects added at previous checks
367 EraseOldMessages((TH1*) hVertexFirst);
368 EraseOldMessages((TH1*) hVertexBest);
369 float errorLevelDifference = 400;
370 float warningLevelDifference = 200;
372 if(hVertexFirst->Integral()>0 && hOrCminOrATvdcOn->Integral()>0){
373 Float_t thr = 0.05 * hVertexFirst->GetBinContent(hVertexFirst->GetMaximumBin());
375 float meanVertexFirst = GetMeanAboveThreshold( hVertexFirst, thr);
376 float meanVertexTVDC = GetMeanAboveThreshold( hOrCminOrATvdcOn,thr);
377 float diff = TMath::Abs(meanVertexFirst - meanVertexTVDC);
378 if(diff > errorLevelDifference){
379 qualityFlagVetrexFirst = kT0Warning; //init quality flag for a given histogram;
381 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
382 text.AddText(Form("large diff. between TVDC vertex"));
383 text.AddText(Form("and the first vertex."));
384 text.SetBorderSize(0);
385 text.SetFillStyle(0);
386 hVertexFirst->GetListOfFunctions()->Add((TPaveText*)text.Clone());
388 }else if(diff > warningLevelDifference){
389 qualityFlagVetrexFirst = kT0Warning; //init quality flag for a given histogram;
391 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
392 text.AddText(Form("large diff. between TVDC vertex"));
393 text.AddText(Form("and the first vertex."));
394 text.SetBorderSize(0);
395 text.SetFillStyle(0);
396 hVertexFirst->GetListOfFunctions()->Add((TPaveText*)text.Clone());
400 qualityFlagVetrexFirst = kT0Error;
401 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 histogram %s has NO entries", hVertexFirst->GetName() ));
403 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
404 text.AddText(Form("NO ENTRIES!!!"));
405 text.AddText(Form("If T0 is READY and beam is on report"));
406 text.AddText(Form("the problem to the T0 on-call expert"));
407 text.SetBorderSize(0);
408 text.SetFillStyle(0);
409 hVertexFirst->GetListOfFunctions()->Add((TPaveText*)text.Clone());
412 if(hVertexBest->Integral()>0 && hOrCminOrATvdcOn->Integral()>0){
414 Float_t thr = 0.05 * hVertexBest->GetBinContent(hVertexBest->GetMaximumBin());
415 float meanVertexBest = GetMeanAboveThreshold(hVertexBest,thr);
416 float meanVertexTVDC = GetMeanAboveThreshold(hOrCminOrATvdcOn,thr);
417 float diff = TMath::Abs(meanVertexBest - meanVertexTVDC);
418 if(diff > errorLevelDifference){
419 qualityFlagVetrexBest = kT0Warning; //init quality flag for a given histogram;
421 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
422 text.AddText(Form("Large. diff. between TVDC vertex"));
423 text.AddText(Form("and the best vertex."));
424 text.SetBorderSize(0);
425 text.SetFillStyle(0);
426 hVertexBest->GetListOfFunctions()->Add((TPaveText*)text.Clone());
428 }else if(diff > warningLevelDifference){
429 qualityFlagVetrexBest = kT0Warning; //init quality flag for a given histogram;
431 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
432 text.AddText(Form("Large. diff. between TVDC vertex"));
433 text.AddText(Form("and the best vertex."));
434 text.SetBorderSize(0);
435 text.SetFillStyle(0);
436 hVertexBest->GetListOfFunctions()->Add((TPaveText*)text.Clone());
439 qualityFlagVetrexBest = kT0Error;
440 AliDebug(AliQAv1::GetQADebugLevel(), Form("T0 histogram %s has NO entries", hVertexBest->GetName() ));
442 TPaveText text(0.20,0.50,0.99,0.99,"NDC");
443 text.AddText(Form("NO ENTRIES!!!"));
444 text.AddText(Form("If T0 is READY and beam is on report"));
445 text.AddText(Form("the problem to the T0 on-call expert"));
446 text.SetBorderSize(0);
447 text.SetFillStyle(0);
448 hVertexBest->GetListOfFunctions()->Add((TPaveText*)text.Clone());
453 int lowestQualityFlag = (int) qualityFlagTrigger;
454 if(qualityFlagVetrexBest<lowestQualityFlag) lowestQualityFlag = qualityFlagVetrexBest;
455 if(qualityFlagVetrexFirst<lowestQualityFlag) lowestQualityFlag = qualityFlagVetrexFirst;
456 if(qualityFlagMeanBest <lowestQualityFlag) lowestQualityFlag = qualityFlagMeanBest;
459 return ConvertQualityFlagToDouble(lowestQualityFlag);
463 //--------------------------------------------------------------------------
464 Double_t AliT0QAChecker::CheckESD(TObjArray *listrec ) const
469 fhESD = (TH1*) listrec->UncheckedAt(2);
471 AliDebug(AliQAv1::GetQADebugLevel(), Form("count %s ", fhESD->GetName()) );
472 TF1 *f1 = new TF1("f1","gaus",-1,1);
473 fhESD->Fit("f1","R","Q", -1,1);
475 f1->GetParameters(&par[0]);
477 TPaveText text(0.30,0.50,0.99,0.99,"NDC");
479 text.AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));
481 AliDebug(AliQAv1::GetQADebugLevel(), Form("numentries %d mean %f #sigma %f", (int)fhESD->GetEntries(),par[1], par[2]));
484 if (par[2] > 0.07 && par[2] < 1.) {
486 text.AddText(Form("not good resolution :\n %f ns\n", par[2] ));
487 text.SetFillColor(5);
488 printf("T0 detector resolution is not good enouph: %f ns\n",par[2] );
490 if(TMath::Abs(par[1])>0.05) {
492 text.AddText(Form(" Check clock shift on %f ns", par[1]));
493 text.SetFillColor(5);
495 if (par[2] > 1. || TMath::Abs(par[1])>0.1) {
497 text.AddText(Form(" Bad resolution:\n mean %f ns sigma %f ns", par[1], par[2]));
498 text.SetFillColor(2);
499 { // RS Clean previous additions
500 TList* lstF = fhESD->GetListOfFunctions();
502 TObject *stats = lstF->FindObject("stats");
505 while ((obj = lstF->First())) {
506 while(lstF->Remove(obj)) { }
509 if (stats) lstF->Add(stats);
512 fhESD->GetListOfFunctions()->Add((TPaveText*)text.Clone());
513 AliDebug(AliQAv1::GetQADebugLevel(),
514 Form("Please, check calibration: shift= %f resolution %f test=%f\n",
515 par[1], par[2], checkr) ) ;
520 AliDebug(AliQAv1::GetQADebugLevel(),
521 Form("No ESD QA histogram found, nothing to check"));
530 //--------------------------------------------------------------------------
531 void AliT0QAChecker::EraseOldMessages(TH1* h) const
533 //erase the old captions
534 TList* lstF = h->GetListOfFunctions();
536 TObject *stats = lstF->FindObject("stats");
539 while ((obj = lstF->First())) {
540 while(lstF->Remove(obj)) { }
543 if (stats) lstF->Add(stats);
546 //--------------------------------------------------------------------------
547 Double_t AliT0QAChecker::ConvertQualityFlagToDouble(int qualityFlag) const
549 //covert quality flag to double
552 switch ( qualityFlag ){
556 checkr = 0.75; break;
558 checkr = 0.25; break;
560 checkr = -1.0; break;
562 AliError("Invalid ecc value. FIXME !");
563 checkr = 0.25; break;
569 //--------------------------------------------------------------------------
570 Float_t AliT0QAChecker::GetMeanAboveThreshold(TH1F* hV, Float_t thr) const{
571 //caculate mean value of histo bins above threshold
572 Int_t nBins = hV->GetNbinsX();
573 Int_t nBinsAboveThr = 0;
576 for(Int_t ib=1;ib<=nBins;ib++){
577 Float_t val = hV->GetBinContent(ib);
584 if(nBinsAboveThr>0) return sum/nBinsAboveThr;
585 else return hV->GetMean();