1 /**************************************************************************
2 * Copyright(c) 2004, 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 **************************************************************************/
15 //__________________________________________________________________
25 //__________________________________________________________________
27 // --- ROOT system ---
33 #include <TIterator.h>
38 #include <TPaveText.h>
41 #include <TFitResult.h>
42 #include <TParameter.h>
45 // --- AliRoot header files ---
48 #include "AliQAChecker.h"
49 #include "AliFMDQAChecker.h"
50 #include "AliRecoParam.h"
51 #include <AliCDBManager.h>
52 #include <AliCDBEntry.h>
54 #include <AliQAThresholds.h>
56 ClassImp(AliFMDQAChecker)
58 ; // This is for Emacs! - do not delete
62 void addFitsMacro(TList* l) {
63 TMacro* m = new TMacro("fits");
64 m->AddLine("void fits() {");
65 m->AddLine(" if (!gPad) { Printf(\"No gPad\"); return; }");
66 m->AddLine(" TList* lp = gPad->GetListOfPrimitives();");
67 m->AddLine(" if (!lp) return;");
68 m->AddLine(" TObject* po = 0;");
69 m->AddLine(" TIter next(lp);");
70 m->AddLine(" while ((po = next())) {");
71 m->AddLine(" if (!po->IsA()->InheritsFrom(TH1::Class())) continue;");
72 m->AddLine(" TH1* htmp = dynamic_cast<TH1*>(po);");
73 m->AddLine(" TList* lf = htmp->GetListOfFunctions();");
74 m->AddLine(" TObject* pso = (lf ? lf->FindObject(\"stats\") : 0);");
75 m->AddLine(" if (!pso) continue;");
76 m->AddLine(" TPaveStats* ps = static_cast<TPaveStats*>(pso);");
77 m->AddLine(" ps->SetOptFit(111);");
78 m->AddLine(" UShort_t qual = htmp->GetUniqueID();");
79 m->AddLine(" ps->SetFillColor(qual >= 3 ? kRed-4 : qual >= 2 ? kOrange-4 : qual >= 1 ? kYellow-4 : kGreen-4);");
80 // m->AddLine(" lf->Remove(lf->FindObject(\"fits\"));");
81 // m->AddLine(" ps->Paint();");
82 m->AddLine(" break;");
84 // m->AddLine(" gPad->Modified(); gPad->Update(); gPad->cd();");
87 TObject* old = l->FindObject(m->GetName());
88 if (old) l->Remove(old);
92 const Double_t kROErrorsLabelY = .30;
94 const Int_t kConvolutionSteps = 100;
95 const Double_t kConvolutionNSigma = 5;
98 // The shift of the most probable value for the ROOT function TMath::Landau
100 const Double_t kMpShift = -0.22278298;
102 // Integration normalisation
104 const Double_t kInvSq2Pi = 1. / TMath::Sqrt(2*TMath::Pi());
106 Double_t landau(Double_t x, Double_t delta, Double_t xi)
109 // Calculate the shifted Landau
111 // f'_{L}(x;\Delta,\xi) = f_L(x;\Delta+0.22278298\xi)
114 // where @f$ f_{L}@f$ is the ROOT implementation of the Landau
115 // distribution (known to have @f$ \Delta_{p}=-0.22278298@f$ for
116 // @f$\Delta=0,\xi=1@f$.
119 // x Where to evaluate @f$ f'_{L}@f$
120 // delta Most probable value
121 // xi The 'width' of the distribution
124 // @f$ f'_{L}(x;\Delta,\xi) @f$
126 return TMath::Landau(x, delta - xi * kMpShift, xi);
128 Double_t landauGaus(Double_t x, Double_t delta, Double_t xi,
129 Double_t sigma, Double_t sigmaN)
132 // Calculate the value of a Landau convolved with a Gaussian
135 // f(x;\Delta,\xi,\sigma') = \frac{1}{\sigma' \sqrt{2 \pi}}
136 // \int_{-\infty}^{+\infty} d\Delta' f'_{L}(x;\Delta',\xi)
137 // \exp{-\frac{(\Delta-\Delta')^2}{2\sigma'^2}}
140 // where @f$ f'_{L}@f$ is the Landau distribution, @f$ \Delta@f$
141 // the energy loss, @f$ \xi@f$ the width of the Landau, and @f$
142 // \sigma'^2=\sigma^2-\sigma_n^2 @f$. Here, @f$\sigma@f$ is the
143 // variance of the Gaussian, and @f$\sigma_n@f$ is a parameter
144 // modelling noise in the detector.
146 // Note that this function uses the constants kConvolutionSteps and
147 // kConvolutionNSigma
150 // - <a href="http://dx.doi.org/10.1016/0168-583X(84)90472-5">Nucl.Instrum.Meth.B1:16</a>
151 // - <a href="http://dx.doi.org/10.1103/PhysRevA.28.615">Phys.Rev.A28:615</a>
152 // - <a href="http://root.cern.ch/root/htmldoc/tutorials/fit/langaus.C.html">ROOT implementation</a>
155 // x where to evaluate @f$ f@f$
156 // delta @f$ \Delta@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$
157 // xi @f$ \xi@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$
158 // sigma @f$ \sigma@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$
159 // sigma_n @f$ \sigma_n@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$
162 // @f$ f@f$ evaluated at @f$ x@f$.
164 Double_t deltap = delta - xi * kMpShift;
165 Double_t sigma2 = sigmaN*sigmaN + sigma*sigma;
166 Double_t sigma1 = sigmaN == 0 ? sigma : TMath::Sqrt(sigma2);
167 Double_t xlow = x - kConvolutionNSigma * sigma1;
168 Double_t xhigh = x + kConvolutionNSigma * sigma1;
169 Double_t step = (xhigh - xlow) / kConvolutionSteps;
172 for (Int_t i = 0; i <= kConvolutionSteps/2; i++) {
173 Double_t x1 = xlow + (i - .5) * step;
174 Double_t x2 = xhigh - (i - .5) * step;
176 sum += TMath::Landau(x1, deltap, xi, kTRUE) * TMath::Gaus(x, x1, sigma1);
177 sum += TMath::Landau(x2, deltap, xi, kTRUE) * TMath::Gaus(x, x2, sigma1);
179 return step * sum * kInvSq2Pi / sigma1;
183 // Utility function to use in TF1 defintition
185 Double_t landauGaus1(Double_t* xp, Double_t* pp)
188 Double_t constant = pp[0];
189 Double_t delta = pp[1];
191 Double_t sigma = pp[3];
192 Double_t sigmaN = pp[4];
194 return constant * landauGaus(x, delta, xi, sigma, sigmaN);
197 //____________________________________________________________________
198 TF1* makeLandauGaus(const char* ,
200 Double_t delta=.5, Double_t xi=0.07,
201 Double_t sigma=.1, Double_t sigmaN=-1,
202 Double_t xmin=0, Double_t xmax=15)
205 // Generate a TF1 object of @f$ f_I@f$
209 // delta @f$ \Delta@f$
211 // sigma @f$ \sigma_1@f$
212 // sigma_n @f$ \sigma_n@f$
213 // xmin Least value of range
214 // xmax Largest value of range
217 // Newly allocated TF1 object
220 TF1* func = new TF1("landauGaus",
221 &landauGaus1,xmin,xmax,npar);
222 // func->SetLineStyle(((i-2) % 10)+2); // start at dashed
223 func->SetLineColor(kBlack);
224 func->SetLineWidth(2);
226 func->SetParNames("C","#Delta_{p}","#xi", "#sigma", "#sigma_{n}");
228 // Set the initial parameters from the seed fit
229 func->SetParameter(0, c);
230 func->SetParameter(1, delta);
231 func->SetParameter(2, xi);
232 func->SetParameter(3, sigma);
233 func->SetParameter(4, sigmaN);
235 func->SetParLimits(1, 0, xmax);
236 func->SetParLimits(2, 0, xmax);
237 func->SetParLimits(3, 0.01, 0.4);
239 if (sigmaN < 0) func->FixParameter(4, 0);
240 else func->SetParLimits(4, 0, xmax);
246 //__________________________________________________________________
247 AliFMDQAChecker::AliFMDQAChecker()
248 : AliQACheckerBase("FMD","FMD Quality Assurance Checker") ,
251 fShowFitResults(true),
255 fELossFkupChi2Nu(100),
256 fELossMinEntries(1000),
257 fELossMaxEntries(-1),
258 fELossGoodParError(0.1),
264 //__________________________________________________________________
266 AliFMDQAChecker::ProcessExternalParams()
268 ProcessExternalParam("ELossLowCut", fELossLowCut);
269 ProcessExternalParam("ELossNRMS", fELossNRMS);
270 ProcessExternalParam("ELossBadChi2Nu", fELossBadChi2Nu);
271 ProcessExternalParam("ELossFkupChi2Nu", fELossFkupChi2Nu);
272 ProcessExternalParam("ELossGoodParError", fELossGoodParError);
273 ProcessExternalParam("ROErrorsBad", fROErrorsBad);
274 ProcessExternalParam("ROErrorsFkup", fROErrorsFkup);
276 ProcessExternalParam("CommonScale", tmp);
278 ProcessExternalParam("ELossMinEntries", tmp);
279 fELossMinEntries = tmp;
280 ProcessExternalParam("ELossMaxEntries", tmp);
281 fELossMaxEntries = tmp;
287 //__________________________________________________________________
289 AliFMDQAChecker::ProcessExternalParam(const char* name, Double_t& v)
291 TObject* o = fExternParamList->FindObject(name);
293 TParameter<double>* p = static_cast<TParameter<double>*>(o);
295 AliDebugF(3, "External parameter: %-20s=%lf", name, v);
298 //__________________________________________________________________
300 AliFMDQAChecker::GetThresholds()
302 const char* path = "GRP/Calib/QAThresholds";
303 AliCDBManager* cdbMan = AliCDBManager::Instance();
304 AliCDBEntry* cdbEnt = cdbMan->Get(path);
306 AliWarningF("Failed to get CDB entry at %s", path);
310 TObjArray* cdbObj = static_cast<TObjArray*>(cdbEnt->GetObject());
312 AliWarningF("Failed to get CDB object at %s", path);
316 TObject* fmdObj = cdbObj->FindObject("FMD");
318 AliWarningF("Failed to get FMD object at from CDB %s", path);
322 AliQAThresholds* qaThr = static_cast<AliQAThresholds*>(fmdObj);
323 Int_t nThr = qaThr->GetSize();
324 for (Int_t i = 0; i < nThr; i++) {
325 TObject* thr = qaThr->GetThreshold(i);
328 TParameter<double>* d = dynamic_cast<TParameter<double>*>(thr);
330 AliWarningF("Parameter %s not of type double", thr->GetName());
333 Double_t val = d->GetVal();
334 TString name(thr->GetName());
335 if (name.EqualTo("ELossBadChi2Nu")) fELossBadChi2Nu = val;
336 else if (name.EqualTo("ELossFkupChi2Nu")) fELossFkupChi2Nu = val;
337 else if (name.EqualTo("ELossGoodParError")) fELossGoodParError = val;
338 else if (name.EqualTo("ROErrorsBad")) fROErrorsBad = val;
339 else if (name.EqualTo("ROErrorsFkup")) fROErrorsFkup = val;
340 AliDebugF(3, "Threshold %s=%f", name.Data(), val);
344 //__________________________________________________________________
346 AliFMDQAChecker::Quality2Bit(UShort_t value) const
348 AliQAv1::QABIT_t ret = AliQAv1::kINFO; // Assume success
349 if (value >= kWhatTheFk) ret = AliQAv1::kFATAL;
350 else if (value >= kBad) ret = AliQAv1::kERROR;
351 else if (value >= kProblem) ret = AliQAv1::kWARNING;
356 //__________________________________________________________________
358 AliFMDQAChecker::SetQA(AliQAv1::ALITASK_t index, Double_t* values) const
360 AliQAv1 * qa = AliQAv1::Instance(index) ;
362 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
363 // Check if specie is defined
364 if (!qa->IsEventSpecieSet(AliRecoParam::ConvertIndex(specie)))
367 // No checker is implemented, set all QA to Fatal
369 qa->Set(AliQAv1::kFATAL, specie) ;
373 UShort_t value = values[specie];
374 AliQAv1::QABIT_t ret = Quality2Bit(value);
376 qa->Set(ret, AliRecoParam::ConvertIndex(specie));
377 AliDebugF(3, "Quality of %s: %d -> %d",
378 AliRecoParam::GetEventSpecieName(specie), value, ret);
382 //__________________________________________________________________
384 AliFMDQAChecker::BasicCheck(TH1* hist) const
386 if (hist->GetEntries() <= 0) return kOK;
387 return (hist->GetMean() > 0 ? kOK : kProblem);
390 //__________________________________________________________________
392 AliFMDQAChecker::CheckOne(AliQAv1::ALITASK_t what,
393 AliRecoParam::EventSpecie_t specie,
396 if(what == AliQAv1::kESD) return CheckESD(specie, hist);
397 if(what == AliQAv1::kRAW) return CheckRaw(specie, hist);
398 if(what == AliQAv1::kSIM) return CheckSim(specie, hist);
399 if(what == AliQAv1::kREC) return CheckRec(specie, hist);
402 //__________________________________________________________________
404 AliFMDQAChecker::CheckESD(AliRecoParam::EventSpecie_t /* specie*/,
407 return BasicCheck(hist);
409 //__________________________________________________________________
411 AliFMDQAChecker::CheckFit(TH1* hist, const TFitResultPtr& res,
412 Double_t low, Double_t high, Int_t& color) const
417 Int_t nPar = res->NPar();
421 Double_t chi2 = res->Chi2();
422 Int_t nu = res->Ndf();
423 Double_t red = (nu == 0 ? fELossFkupChi2Nu : chi2 / nu);
424 TObjArray* lines = 0;
428 Double_t chi2Lim = fELossBadChi2Nu;
429 if (red > fELossBadChi2Nu) { // || res->Prob() < .01) {
430 // AliWarningF("Fit gave chi^2/nu=%f/%d=%f>%f (%f)",
431 // res->Chi2(), res->Ndf(), red, fELossBadChi2Nu,
432 // fELossFkupChi2Nu);
435 if (red > fELossFkupChi2Nu) {
437 chi2Lim = fELossFkupChi2Nu;
442 if (fShowFitResults) {
443 lines = new TObjArray(nPar+3);
444 lines->SetName("lines");
445 lines->SetOwner(true);
447 ltx = new TLatex(x, y, Form("#chi^{2}/#nu: %7.3f %c %6.2f",
448 red, chi2Check < 1 ? '<' : '>',
451 ltx->SetTextColor(chi2Check < 1 ? color :
452 chi2Check < 2 ? kOrange+2 : kRed+2);
453 // ltx->SetTextColor(color);
454 ltx->SetTextSize(dy-.01);
461 ltx = new TLatex(x1, y1, Form("[thresholds: %6.2f, %6.2f]",
462 fELossBadChi2Nu, fELossFkupChi2Nu));
463 ltx->SetTextColor(kGray+3);
464 ltx->SetTextSize(dy-.01);
466 ltx->SetTextAlign(31);
471 ltx = new TLatex(x1, y1, Form("Fit range: [%6.2f,%6.2f]", low, high));
472 ltx->SetTextColor(kGray+3);
473 ltx->SetTextSize(dy-.01);
474 ltx->SetTextAlign(31);
479 ltx = new TLatex(x1, y1, Form("Entries: %d (%d)",
480 Int_t(hist->GetEffectiveEntries()),
482 ltx->SetTextColor(kGray+3);
483 ltx->SetTextSize(dy-.01);
484 ltx->SetTextAlign(31);
489 // Now check the relative error on the fit parameters
491 for (Int_t i = 0; i < nPar; i++) {
492 if (res->IsParameterFixed(i)) continue;
493 Double_t thr = fELossGoodParError;
494 Double_t pv = res->Parameter(i);
495 Double_t pe = res->ParError(i);
496 Double_t rel = (pv == 0 ? 100 : pe / pv);
497 Bool_t ok = (i == 3) || (rel < thr);
500 TString txt(Form("#delta%s/%s: %7.3f ",
501 res->ParName(i).c_str(),
502 res->ParName(i).c_str(),
504 if (i != 3) txt.Append(Form("%c %4.2f", ok ? '<' : '>', thr));
505 else txt.Append("(ignored)");
506 ltx = new TLatex(x, y, txt);
508 ltx->SetTextSize(dy-.01);
509 ltx->SetTextColor(ok ? color : kOrange+2);
512 if (i == 3) continue; // Skip sigma
516 ret = TMath::Max(ret-(parsOk-1),0);
517 if (ret > 1) color = kRed+2;
518 if (ret > 0) color = kOrange+2;
520 TList* lf = hist->GetListOfFunctions();
521 TObject* old = lf->FindObject(lines->GetName());
527 hist->SetStats(false);
532 //__________________________________________________________________
534 AliFMDQAChecker::AddFitResults(TH1* hist, const TFitResultPtr& res,
535 Int_t color, Double_t low, Double_t high) const
537 // Obsolete - not used
538 if (!fShowFitResults) return;
540 Int_t nPar = res->NPar();
541 TObjArray* lines = new TObjArray(nPar+1);
542 lines->SetOwner(kTRUE);
543 lines->SetName("fitResults");
548 Double_t chi2 = res->Chi2();
549 Int_t nu = res->Ndf();
550 Double_t red = (nu == 0 ? fELossFkupChi2Nu : chi2 / nu);
552 TLatex* ltx = new TLatex(x, y, Form("#chi^{2}/#nu: %7.3f",red));
554 ltx->SetTextColor(color);
555 ltx->SetTextSize(dy-.01);
559 ltx = new TLatex(x, y, Form("[thresholds: %6.2f, %6.2f]",
560 fELossBadChi2Nu, fELossFkupChi2Nu));
561 ltx->SetTextColor(kGray+3);
562 ltx->SetTextSize(dy-.01);
567 ltx = new TLatex(x, y, Form("Fit range: [%6.2f,%6.2f]", low, high));
568 ltx->SetTextColor(kGray+3);
569 ltx->SetTextSize(dy-.01);
573 for (Int_t i = 0; i < nPar; i++) {
574 if (res->IsParameterFixed(i)) continue;
576 Double_t pv = res->Parameter(i);
577 Double_t pe = res->ParError(i);
578 Double_t rel = (pv == 0 ? 100 : pe / pv);
579 ltx = new TLatex(x, y, Form("#delta%s/%s: %7.3f",
580 res->ParName(i).c_str(),
581 res->ParName(i).c_str(),
584 ltx->SetTextColor(color);
585 ltx->SetTextSize(dy-.01);
588 TList* lf = hist->GetListOfFunctions();
589 TObject* old = lf->FindObject(lines->GetName());
595 hist->SetStats(false);
598 //__________________________________________________________________
600 AliFMDQAChecker::CheckRaw(AliRecoParam::EventSpecie_t specie,
603 Int_t ret = BasicCheck(hist);
604 TString name(hist->GetName());
605 if (name.Contains("readouterrors", TString::kIgnoreCase)) {
606 // Check the mean number of errors per event
607 TH2* roErrors = static_cast<TH2*>(hist);
608 Int_t nY = roErrors->GetNbinsY();
610 TLatex* ltx = new TLatex(.15, .9, Form("Thresholds: %5.2f,%5.2f",
611 fROErrorsBad, fROErrorsFkup));
612 ltx->SetName("thresholds");
613 ltx->SetTextColor(kGray+3);
616 TList* ll = hist->GetListOfFunctions();
617 TObject* old = ll->FindObject(ltx->GetName());
624 for (Int_t i = 1; i <= 3; i++) {
627 for (Int_t j = 1; j <= nY; j++) {
628 Int_t n = roErrors->GetBinContent(i, j);
629 sum += n * roErrors->GetYaxis()->GetBinCenter(j);
632 Double_t mean = sum / cnt;
633 Double_t x = ((i-.5) * (1-0.1-0.1) / 3 + 0.1);
635 ltx = new TLatex(x, kROErrorsLabelY, Form("Mean: %6.3f", mean));
636 ltx->SetName(Form("FMD%d", i));
638 ltx->SetTextAngle(90);
639 ltx->SetTextColor(kGreen+4);
640 old = ll->FindObject(ltx->GetName());
647 if (mean > fROErrorsBad) {
648 AliWarningF("Mean of readout errors for FMD%d = %f > %f (%f)",
649 i, mean, fROErrorsBad, fROErrorsFkup);
651 ltx->SetTextColor(kOrange+2);
652 if (mean > fROErrorsFkup) {
654 ltx->SetTextColor(kRed+2);
659 else if (name.Contains("eloss",TString::kIgnoreCase)) {
660 // Try to fit a function to the histogram
661 if (hist->GetEntries() < 1000) return ret;
662 if (specie == AliRecoParam::kCosmic ||
663 specie == AliRecoParam::kCalib) return ret;
665 Double_t xMin = hist->GetXaxis()->GetXmin();
666 Double_t xMax = hist->GetXaxis()->GetXmax();
668 hist->GetXaxis()->SetRangeUser(fELossLowCut, xMax);
669 Int_t bMaxY = hist->GetMaximumBin();
670 Double_t xMaxY = hist->GetXaxis()->GetBinCenter(bMaxY);
671 Double_t rms = hist->GetRMS();
672 Double_t low = hist->GetXaxis()->GetBinCenter(bMaxY-4);
673 hist->GetXaxis()->SetRangeUser(0.2, xMaxY+(fELossNRMS+1)*rms);
674 rms = hist->GetRMS();
675 hist->GetXaxis()->SetRange(0,-1);
676 TF1* func = makeLandauGaus(name);
677 func->SetParameter(1, xMaxY);
678 func->SetLineColor(kGreen+4);
679 // func->SetLineStyle(2);
680 Double_t high = xMax; // xMaxY+fELossNRMS*rms;
682 TFitResultPtr res = hist->Fit(func, "QS", "", low, high);
684 Int_t color = func->GetLineColor();
685 UShort_t qual = CheckFit(hist, res, low, high, color);
687 // Make sure we save the function in the full range of the histogram
688 func = hist->GetFunction("landauGaus");
689 func->SetRange(xMin, xMax);
690 // func->SetParent(hist);
691 func->Save(xMin, xMax, 0, 0, 0, 0);
692 func->SetLineColor(color);
694 // Now check if this histogram should be cleared or not
695 if (fELossMaxEntries > 0 && hist->GetEntries() > fELossMaxEntries)
696 hist->SetBit(BIT(23));
698 func->SetLineWidth(3);
699 func->SetLineStyle(1);
701 func->SetLineWidth(4);
708 //__________________________________________________________________
710 AliFMDQAChecker::CheckSim(AliRecoParam::EventSpecie_t /* specie*/,
713 return BasicCheck(hist);
715 //__________________________________________________________________
717 AliFMDQAChecker::CheckRec(AliRecoParam::EventSpecie_t /* specie*/,
720 return BasicCheck(hist);
723 //__________________________________________________________________
724 void AliFMDQAChecker::Check(Double_t* rv,
725 AliQAv1::ALITASK_t what,
727 const AliDetectorRecoParam* /*t*/)
730 // Member function called to do the actual checking
733 // rv Array of return values.
734 // what What to check
735 // list Array of arrays of histograms. There's one arrat for
737 // t Reconstruction parameters - not used.
739 // The bounds defined for RV are
742 // ERROR: (0.0, 0.002]
743 // WARNING: (0.002,0.5]
746 // Double_t* rv = new Double_t[AliRecoParam::kNSpecies] ;
748 if (!fDidExternal) ProcessExternalParams();
750 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
754 if (!AliQAv1::Instance()->IsEventSpecieSet(specie) )
757 if(!list[specie]) continue;
760 Int_t nHist = list[specie]->GetEntriesFast();
762 for(Int_t i= 0; i< nHist; i++) {
763 if (!(hist = static_cast<TH1*>(list[specie]->At(i)))) continue;
764 Int_t qual = CheckOne(what, AliRecoParam::ConvertIndex(specie), hist);
765 hist->SetUniqueID(Quality2Bit(qual));
769 // if (ret > kWhatTheFk) rv[specie] = fLowTestValue[AliQAv1::kFATAL];
770 // else if (ret > kBad) rv[specie] = fUpTestValue[AliQAv1::kERROR];
771 // else if (ret > kProblem) rv[specie] = fUpTestValue[AliQAv1::kWARNING];
772 // else rv[specie] = fUpTestValue[AliQAv1::kINFO];
773 AliDebugF(3, "Combined sum is %d -> %f", ret, rv[specie]);
775 // if (count != 0) rv[specie] /= count;
781 Int_t CheckForLog(TAxis* axis,
786 TString t(axis->GetTitle());
787 if (!t.Contains("[log]", TString::kIgnoreCase)) return 0;
788 t.ReplaceAll("[log]", "");
790 case 1: pad->SetLogx(); ret |= 0x1; break;
791 case 2: pad->SetLogy(); ret |= 0x2; break;
792 case 3: pad->SetLogz(); ret |= 0x4; break;
797 void RestoreLog(TAxis* axis, Bool_t log)
800 TString t(axis->GetTitle());
807 void FindMinMax(TH1* h, Double_t& min, Double_t& max)
811 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
812 Double_t c = h->GetBinContent(i);
813 if (c < 1e-8) continue;
814 tmin = TMath::Min(tmin, c);
815 tmax = TMath::Max(tmax, c);
821 //____________________________________________________________________________
823 AliFMDQAChecker::MakeImage(TObjArray** list,
824 AliQAv1::TASKINDEX_t task,
825 AliQAv1::MODE_t mode)
827 // makes the QA image for sim and rec
830 // task What to check
831 // list Array of arrays of histograms. There's one array for
833 // t Reconstruction parameters - not used.
837 Double_t min = 10000;
839 // Loop over all species
840 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
841 AliRecoParam::EventSpecie_t spe = AliRecoParam::ConvertIndex(specie);
842 if (!AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))
843 ->IsEventSpecieSet(spe))
846 // If nothing is defined for this specie, go on.
847 if(!list[specie] || list[specie]->GetEntriesFast() == 0) continue;
849 // Loop over the histograms and figure out how many histograms we
850 // have and the min/max
852 Int_t nHist = list[specie]->GetEntriesFast();
853 for(Int_t i= 0; i< nHist; i++) {
854 hist = static_cast<TH1F*>(list[specie]->At(i));
855 if (hist && hist->TestBit(AliQAv1::GetImageBit())) {
857 TString name(hist->GetName());
858 if (name.Contains("readouterrors", TString::kIgnoreCase)) continue;
860 // Double_t hMax = hist->GetMaximum();
861 // hist->GetBinContent(hist->GetMaximumBin());
862 // Double_t hMin = hist->GetMinimum();
863 // hist->GetBinContent(hist->GetMinimumBin());
865 FindMinMax(hist, hMin, hMax);
866 max = TMath::Max(max, hMax);
867 min = TMath::Min(min, hMin);
868 // AliInfoF("Min/max of %40s: %f/%f, global -> %f/%f",
869 // hist->GetName(), hMin, hMax, min, max);
874 // AliInfoF("Global min/max=%f/%f", min, max);
875 min = TMath::Max(1e-1, min);
876 max = TMath::Max(1e5, max);
878 // IF no images, go on.
880 AliDebug(AliQAv1::GetQADebugLevel(),
881 Form("No histogram will be plotted for %s %s\n", GetName(),
882 AliQAv1::GetTaskName(task).Data()));
886 AliDebug(AliQAv1::GetQADebugLevel(),
887 Form("%d histograms will be plotted for %s %s\n",
888 nImages, GetName(), AliQAv1::GetTaskName(task).Data()));
889 gStyle->SetOptStat(0);
891 // Again loop over species and draw a canvas
892 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
893 if (!AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))
894 ->IsEventSpecieSet(specie)) continue;
896 // if Nothing here, go on
897 if(!list[specie] || list[specie]->GetEntries() <= 0 ||
898 nImages <= 0) continue;
901 const Char_t * title = Form("QA_%s_%s_%s", GetName(),
902 AliQAv1::GetTaskName(task).Data(),
903 AliRecoParam::GetEventSpecieName(specie));
904 if (!fImage[specie]) fImage[specie] = new TCanvas(title, title) ;
905 fImage[specie]->Clear() ;
906 fImage[specie]->SetTitle(title) ;
907 fImage[specie]->cd() ;
909 // Put something in the canvas - even if empty
910 TPaveText someText(0.015, 0.015, 0.98, 0.98) ;
911 someText.AddText(title) ;
912 someText.SetFillColor(0);
913 someText.SetFillStyle(0);
914 someText.SetBorderSize(0);
915 someText.SetTextColor(kRed+1);
917 TString outName(Form("%s%s%d.%s", AliQAv1::GetImageFileName(),
918 AliQAv1::GetModeName(mode),
919 AliQAChecker::Instance()->GetRunNumber(),
920 AliQAv1::GetImageFileFormat()));
921 fImage[specie]->Print(outName, "ps") ;
923 // Now set some parameters on the canvas
924 fImage[specie]->Clear();
925 fImage[specie]->SetTopMargin(0.10);
926 fImage[specie]->SetBottomMargin(0.15);
927 fImage[specie]->SetLeftMargin(0.15);
928 fImage[specie]->SetRightMargin(0.05);
931 const char* topT = Form("Mode: %s, Task: %s, Specie: %s, Run: %d",
932 AliQAv1::GetModeName(mode),
933 AliQAv1::GetTaskName(task).Data(),
934 AliRecoParam::GetEventSpecieName(specie),
935 AliQAChecker::Instance()->GetRunNumber());
936 TLatex* topText = new TLatex(.5, .99, topT);
937 topText->SetTextAlign(23);
938 topText->SetTextSize(.038);
939 topText->SetTextFont(42);
940 topText->SetTextColor(kBlue+3);
945 Int_t nx = int(nImages + .5) / 2;
948 fImage[specie]->Divide(nx, ny, 0, 0);
949 // else fImage[specie]->Divide(nx, ny);
952 // Loop over histograms
954 Int_t nHist = list[specie]->GetEntriesFast();
956 for (Int_t i = 0; i < nHist; i++) {
957 hist = static_cast<TH1*>(list[specie]->At(i));
958 if (!hist || !hist->TestBit(AliQAv1::GetImageBit())) continue;
961 TVirtualPad* pad = fImage[specie]->cd(++j);
962 pad->SetRightMargin(0.01);
964 pad->SetLeftMargin(0.10);
965 pad->SetBottomMargin(0.10);
968 // Check for log scale
970 logOpts |= CheckForLog(hist->GetXaxis(), pad, 1);
971 logOpts |= CheckForLog(hist->GetYaxis(), pad, 2);
972 logOpts |= CheckForLog(hist->GetZaxis(), pad, 3);
974 // Figure out special cases
976 TString name(hist->GetName());
977 if (name.Contains("readouterrors", TString::kIgnoreCase)) {
978 pad->SetRightMargin(0.15);
979 pad->SetBottomMargin(0.10);
980 // pad->SetTopMargin(0.02);
987 hist->SetMinimum(min);
988 hist->SetMaximum(max);
999 if (name.Contains("readouterrors", TString::kIgnoreCase)) {
1001 for (Int_t kk = 1; kk <= 3; kk++) {
1002 TH1* proj = static_cast<TH2*>(hist)->ProjectionY("",kk,kk);
1003 Double_t m = proj->GetMean();
1004 TLatex* l = new TLatex(kk, 30, Form("Mean: %f", m));
1005 l->SetTextAngle(90);
1006 l->SetTextColor(m > 10 ? kRed+1 : m > .7 ? kOrange+2 :kGreen+2);
1012 gStyle->SetOptTitle(0);
1013 TPad* insert = new TPad("insert", "Zoom",
1014 .4,.4, .99, .95, 0, 0, 0);
1015 insert->SetTopMargin(0.01);
1016 insert->SetRightMargin(0.01);
1017 insert->SetFillColor(0);
1018 insert->SetBorderSize(1);
1019 insert->SetBorderMode(0);
1022 if (logOpts & 0x1) insert->SetLogx();
1023 if (logOpts & 0x2) insert->SetLogy();
1024 if (logOpts & 0x4) insert->SetLogz();
1025 hist->GetXaxis()->SetRange(1, hist->GetNbinsX()/8);
1026 TH1* copy = hist->DrawCopy(opt);
1027 copy->GetXaxis()->SetNdivisions(408, false);
1028 // Restore full range
1029 hist->GetXaxis()->SetRange(0, 0);
1030 gStyle->SetOptTitle(1);
1033 // Possibly restore the log options
1034 RestoreLog(hist->GetXaxis(), logOpts & 0x1);
1035 RestoreLog(hist->GetYaxis(), logOpts & 0x2);
1036 RestoreLog(hist->GetZaxis(), logOpts & 0x4);
1038 // Print to a post-script file
1039 fImage[specie]->Print(outName, "ps");
1041 fImage[specie]->Print(Form("%s_%d.png",
1042 AliRecoParam::GetEventSpecieName(specie),
1043 AliQAChecker::Instance()->GetRunNumber()));
1048 //__________________________________________________________________