]> git.uio.no Git - u/mrichter/AliRoot.git/blame - FMD/FMDrec/AliFMDQAChecker.cxx
Merge branch 'master' of https://git.cern.ch/reps/AliRoot
[u/mrichter/AliRoot.git] / FMD / FMDrec / AliFMDQAChecker.cxx
CommitLineData
c9dd1c4d 1/**************************************************************************
2 * Copyright(c) 2004, 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//
17// Yves?
18// What
19// is
20// this
21// class
22// supposed
23// to
24// do?
25//__________________________________________________________________
26//
27// --- ROOT system ---
28#include <TClass.h>
29#include <TH1F.h>
1306ba55 30#include <TF1.h>
9eb9c521 31#include <TH2.h>
c9dd1c4d 32#include <TH1I.h>
33#include <TIterator.h>
34#include <TKey.h>
35#include <TFile.h>
6ceca4ef 36#include <iostream>
1706c710 37#include <TCanvas.h>
05e5e0c1 38#include <TStyle.h>
9eb9c521 39#include <TLatex.h>
1306ba55 40#include <TFitResult.h>
41#include <TParameter.h>
42#include <TMacro.h>
a3e1fdcc 43#include <TPaveText.h>
550157b2 44#include <TVirtualFitter.h>
c9dd1c4d 45
46// --- AliRoot header files ---
47#include "AliLog.h"
4e25ac79 48#include "AliQAv1.h"
c9dd1c4d 49#include "AliQAChecker.h"
50#include "AliFMDQAChecker.h"
a3e1fdcc 51#include "AliFMDQADataMakerRec.h"
6ceca4ef 52#include "AliRecoParam.h"
1306ba55 53#include <AliCDBManager.h>
54#include <AliCDBEntry.h>
55#include <AliCDBId.h>
56#include <AliQAThresholds.h>
c9dd1c4d 57
58ClassImp(AliFMDQAChecker)
59#if 0
60; // This is for Emacs! - do not delete
61#endif
05e5e0c1 62
1306ba55 63namespace {
64 void addFitsMacro(TList* l) {
65 TMacro* m = new TMacro("fits");
66 m->AddLine("void fits() {");
67 m->AddLine(" if (!gPad) { Printf(\"No gPad\"); return; }");
68 m->AddLine(" TList* lp = gPad->GetListOfPrimitives();");
69 m->AddLine(" if (!lp) return;");
70 m->AddLine(" TObject* po = 0;");
71 m->AddLine(" TIter next(lp);");
72 m->AddLine(" while ((po = next())) {");
73 m->AddLine(" if (!po->IsA()->InheritsFrom(TH1::Class())) continue;");
74 m->AddLine(" TH1* htmp = dynamic_cast<TH1*>(po);");
75 m->AddLine(" TList* lf = htmp->GetListOfFunctions();");
76 m->AddLine(" TObject* pso = (lf ? lf->FindObject(\"stats\") : 0);");
77 m->AddLine(" if (!pso) continue;");
78 m->AddLine(" TPaveStats* ps = static_cast<TPaveStats*>(pso);");
79 m->AddLine(" ps->SetOptFit(111);");
80 m->AddLine(" UShort_t qual = htmp->GetUniqueID();");
81 m->AddLine(" ps->SetFillColor(qual >= 3 ? kRed-4 : qual >= 2 ? kOrange-4 : qual >= 1 ? kYellow-4 : kGreen-4);");
82 // m->AddLine(" lf->Remove(lf->FindObject(\"fits\"));");
83 // m->AddLine(" ps->Paint();");
84 m->AddLine(" break;");
85 m->AddLine(" }");
86 // m->AddLine(" gPad->Modified(); gPad->Update(); gPad->cd();");
87 m->AddLine("}");
88
89 TObject* old = l->FindObject(m->GetName());
90 if (old) l->Remove(old);
91 l->Add(m);
92 }
93
e0c60e77 94 const Double_t kROErrorsLabelY = .30;
1306ba55 95
96 const Int_t kConvolutionSteps = 100;
97 const Double_t kConvolutionNSigma = 5;
98
99 //
100 // The shift of the most probable value for the ROOT function TMath::Landau
101 //
102 const Double_t kMpShift = -0.22278298;
103 //
104 // Integration normalisation
105 //
106 const Double_t kInvSq2Pi = 1. / TMath::Sqrt(2*TMath::Pi());
107
108 Double_t landau(Double_t x, Double_t delta, Double_t xi)
109 {
110 //
111 // Calculate the shifted Landau
112 // @f[
113 // f'_{L}(x;\Delta,\xi) = f_L(x;\Delta+0.22278298\xi)
114 // @f]
115 //
116 // where @f$ f_{L}@f$ is the ROOT implementation of the Landau
117 // distribution (known to have @f$ \Delta_{p}=-0.22278298@f$ for
118 // @f$\Delta=0,\xi=1@f$.
119 //
120 // Parameters:
121 // x Where to evaluate @f$ f'_{L}@f$
122 // delta Most probable value
123 // xi The 'width' of the distribution
124 //
125 // Return:
126 // @f$ f'_{L}(x;\Delta,\xi) @f$
127 //
128 return TMath::Landau(x, delta - xi * kMpShift, xi);
129 }
130 Double_t landauGaus(Double_t x, Double_t delta, Double_t xi,
131 Double_t sigma, Double_t sigmaN)
132 {
133 //
134 // Calculate the value of a Landau convolved with a Gaussian
135 //
136 // @f[
137 // f(x;\Delta,\xi,\sigma') = \frac{1}{\sigma' \sqrt{2 \pi}}
138 // \int_{-\infty}^{+\infty} d\Delta' f'_{L}(x;\Delta',\xi)
139 // \exp{-\frac{(\Delta-\Delta')^2}{2\sigma'^2}}
140 // @f]
141 //
142 // where @f$ f'_{L}@f$ is the Landau distribution, @f$ \Delta@f$
143 // the energy loss, @f$ \xi@f$ the width of the Landau, and @f$
144 // \sigma'^2=\sigma^2-\sigma_n^2 @f$. Here, @f$\sigma@f$ is the
145 // variance of the Gaussian, and @f$\sigma_n@f$ is a parameter
146 // modelling noise in the detector.
147 //
148 // Note that this function uses the constants kConvolutionSteps and
149 // kConvolutionNSigma
150 //
151 // References:
152 // - <a href="http://dx.doi.org/10.1016/0168-583X(84)90472-5">Nucl.Instrum.Meth.B1:16</a>
153 // - <a href="http://dx.doi.org/10.1103/PhysRevA.28.615">Phys.Rev.A28:615</a>
154 // - <a href="http://root.cern.ch/root/htmldoc/tutorials/fit/langaus.C.html">ROOT implementation</a>
155 //
156 // Parameters:
157 // x where to evaluate @f$ f@f$
158 // delta @f$ \Delta@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$
159 // xi @f$ \xi@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$
160 // sigma @f$ \sigma@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$
161 // sigma_n @f$ \sigma_n@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$
162 //
163 // Return:
164 // @f$ f@f$ evaluated at @f$ x@f$.
165 //
166 Double_t deltap = delta - xi * kMpShift;
167 Double_t sigma2 = sigmaN*sigmaN + sigma*sigma;
168 Double_t sigma1 = sigmaN == 0 ? sigma : TMath::Sqrt(sigma2);
169 Double_t xlow = x - kConvolutionNSigma * sigma1;
170 Double_t xhigh = x + kConvolutionNSigma * sigma1;
171 Double_t step = (xhigh - xlow) / kConvolutionSteps;
172 Double_t sum = 0;
173
174 for (Int_t i = 0; i <= kConvolutionSteps/2; i++) {
175 Double_t x1 = xlow + (i - .5) * step;
176 Double_t x2 = xhigh - (i - .5) * step;
177
178 sum += TMath::Landau(x1, deltap, xi, kTRUE) * TMath::Gaus(x, x1, sigma1);
179 sum += TMath::Landau(x2, deltap, xi, kTRUE) * TMath::Gaus(x, x2, sigma1);
180 }
181 return step * sum * kInvSq2Pi / sigma1;
182 }
183
184 //
185 // Utility function to use in TF1 defintition
186 //
187 Double_t landauGaus1(Double_t* xp, Double_t* pp)
188 {
189 Double_t x = xp[0];
190 Double_t constant = pp[0];
191 Double_t delta = pp[1];
192 Double_t xi = pp[2];
193 Double_t sigma = pp[3];
194 Double_t sigmaN = pp[4];
195
196 return constant * landauGaus(x, delta, xi, sigma, sigmaN);
197 }
198
199 //____________________________________________________________________
200 TF1* makeLandauGaus(const char* ,
201 Double_t c=1,
202 Double_t delta=.5, Double_t xi=0.07,
203 Double_t sigma=.1, Double_t sigmaN=-1,
204 Double_t xmin=0, Double_t xmax=15)
205 {
206 //
207 // Generate a TF1 object of @f$ f_I@f$
208 //
209 // Parameters:
210 // c Constant
211 // delta @f$ \Delta@f$
212 // xi @f$ \xi_1@f$
213 // sigma @f$ \sigma_1@f$
214 // sigma_n @f$ \sigma_n@f$
215 // xmin Least value of range
216 // xmax Largest value of range
217 //
218 // Return:
219 // Newly allocated TF1 object
220 //
221 Int_t npar = 5;
222 TF1* func = new TF1("landauGaus",
223 &landauGaus1,xmin,xmax,npar);
224 // func->SetLineStyle(((i-2) % 10)+2); // start at dashed
225 func->SetLineColor(kBlack);
226 func->SetLineWidth(2);
227 func->SetNpx(500);
228 func->SetParNames("C","#Delta_{p}","#xi", "#sigma", "#sigma_{n}");
229
230 // Set the initial parameters from the seed fit
231 func->SetParameter(0, c);
232 func->SetParameter(1, delta);
233 func->SetParameter(2, xi);
234 func->SetParameter(3, sigma);
235 func->SetParameter(4, sigmaN);
236
237 func->SetParLimits(1, 0, xmax);
238 func->SetParLimits(2, 0, xmax);
550157b2 239 func->SetParLimits(3, 0.01, 1);
1306ba55 240
241 if (sigmaN < 0) func->FixParameter(4, 0);
242 else func->SetParLimits(4, 0, xmax);
243
244 return func;
245 }
246}
247
248//__________________________________________________________________
249AliFMDQAChecker::AliFMDQAChecker()
250 : AliQACheckerBase("FMD","FMD Quality Assurance Checker") ,
251 fDoScale(false),
252 fDidExternal(false),
253 fShowFitResults(true),
254 fELossLowCut(0.2),
255 fELossNRMS(3),
256 fELossBadChi2Nu(10),
257 fELossFkupChi2Nu(100),
258 fELossMinEntries(1000),
e0c60e77 259 fELossMaxEntries(-1),
1306ba55 260 fELossGoodParError(0.1),
550157b2 261 fELossMinSharing(0.1),
1306ba55 262 fROErrorsBad(0.3),
550157b2 263 fROErrorsFkup(0.5),
264 fMaxNProblem(10),
265 fMaxNBad(10),
266 fNoFits(false)
1306ba55 267{
268}
269
270//__________________________________________________________________
271void
272AliFMDQAChecker::ProcessExternalParams()
273{
274 ProcessExternalParam("ELossLowCut", fELossLowCut);
275 ProcessExternalParam("ELossNRMS", fELossNRMS);
276 ProcessExternalParam("ELossBadChi2Nu", fELossBadChi2Nu);
277 ProcessExternalParam("ELossFkupChi2Nu", fELossFkupChi2Nu);
278 ProcessExternalParam("ELossGoodParError", fELossGoodParError);
279 ProcessExternalParam("ROErrorsBad", fROErrorsBad);
280 ProcessExternalParam("ROErrorsFkup", fROErrorsFkup);
550157b2 281 ProcessExternalParam("ELossMinSharing", fELossMinSharing);
1306ba55 282 Double_t tmp = 0;
550157b2 283 ProcessExternalParam("CommonScale", tmp);
284 fDoScale = tmp > 0; tmp = fELossMinEntries;
285 ProcessExternalParam("ELossMinEntries", tmp);
286 fELossMinEntries = tmp; tmp = fELossMaxEntries;
287 ProcessExternalParam("ELossMaxEntries", tmp);
288 fELossMaxEntries = tmp; tmp = fMaxNProblem;
289 ProcessExternalParam("MaxNProblem", tmp);
290 fMaxNProblem = tmp; tmp = 0;
291 fELossMaxEntries = tmp; tmp = fMaxNBad;
292 ProcessExternalParam("MaxNBad", tmp);
293 fMaxNBad = tmp; tmp = 0;
294 ProcessExternalParam("NoFits", tmp);
295 fNoFits = tmp > 0; tmp = 0;
1306ba55 296
297 GetThresholds();
298
299 fDidExternal = true;
300}
301//__________________________________________________________________
302void
303AliFMDQAChecker::ProcessExternalParam(const char* name, Double_t& v)
304{
305 TObject* o = fExternParamList->FindObject(name);
306 if (!o) return;
307 TParameter<double>* p = static_cast<TParameter<double>*>(o);
308 v = p->GetVal();
309 AliDebugF(3, "External parameter: %-20s=%lf", name, v);
310}
311
312//__________________________________________________________________
313void
314AliFMDQAChecker::GetThresholds()
315{
316 const char* path = "GRP/Calib/QAThresholds";
317 AliCDBManager* cdbMan = AliCDBManager::Instance();
318 AliCDBEntry* cdbEnt = cdbMan->Get(path);
319 if (!cdbEnt) {
320 AliWarningF("Failed to get CDB entry at %s", path);
321 return;
322 }
323
324 TObjArray* cdbObj = static_cast<TObjArray*>(cdbEnt->GetObject());
325 if (!cdbObj) {
326 AliWarningF("Failed to get CDB object at %s", path);
327 return;
328 }
329
330 TObject* fmdObj = cdbObj->FindObject("FMD");
331 if (!fmdObj) {
332 AliWarningF("Failed to get FMD object at from CDB %s", path);
333 return;
334 }
335
336 AliQAThresholds* qaThr = static_cast<AliQAThresholds*>(fmdObj);
337 Int_t nThr = qaThr->GetSize();
338 for (Int_t i = 0; i < nThr; i++) {
339 TObject* thr = qaThr->GetThreshold(i);
340 if (!thr) continue;
341
342 TParameter<double>* d = dynamic_cast<TParameter<double>*>(thr);
343 if (!d) {
344 AliWarningF("Parameter %s not of type double", thr->GetName());
345 continue;
346 }
347 Double_t val = d->GetVal();
348 TString name(thr->GetName());
349 if (name.EqualTo("ELossBadChi2Nu")) fELossBadChi2Nu = val;
350 else if (name.EqualTo("ELossFkupChi2Nu")) fELossFkupChi2Nu = val;
351 else if (name.EqualTo("ELossGoodParError")) fELossGoodParError = val;
352 else if (name.EqualTo("ROErrorsBad")) fROErrorsBad = val;
353 else if (name.EqualTo("ROErrorsFkup")) fROErrorsFkup = val;
550157b2 354 else if (name.EqualTo("MaxNProblem")) fMaxNProblem = val;
355 else if (name.EqualTo("MaxNBad")) fMaxNBad = val;
1306ba55 356 AliDebugF(3, "Threshold %s=%f", name.Data(), val);
357 }
358}
359
360//__________________________________________________________________
361AliQAv1::QABIT_t
362AliFMDQAChecker::Quality2Bit(UShort_t value) const
363{
364 AliQAv1::QABIT_t ret = AliQAv1::kINFO; // Assume success
365 if (value >= kWhatTheFk) ret = AliQAv1::kFATAL;
366 else if (value >= kBad) ret = AliQAv1::kERROR;
367 else if (value >= kProblem) ret = AliQAv1::kWARNING;
368
369 return ret;
370}
371
372//__________________________________________________________________
373void
374AliFMDQAChecker::SetQA(AliQAv1::ALITASK_t index, Double_t* values) const
375{
376 AliQAv1 * qa = AliQAv1::Instance(index) ;
377
378 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
379 // Check if specie is defined
380 if (!qa->IsEventSpecieSet(AliRecoParam::ConvertIndex(specie)))
381 continue ;
382
383 // No checker is implemented, set all QA to Fatal
384 if (!values) {
385 qa->Set(AliQAv1::kFATAL, specie) ;
386 continue;
387 }
388
389 UShort_t value = values[specie];
390 AliQAv1::QABIT_t ret = Quality2Bit(value);
391
392 qa->Set(ret, AliRecoParam::ConvertIndex(specie));
393 AliDebugF(3, "Quality of %s: %d -> %d",
394 AliRecoParam::GetEventSpecieName(specie), value, ret);
395 }
396}
397
398//__________________________________________________________________
399UShort_t
400AliFMDQAChecker::BasicCheck(TH1* hist) const
401{
402 if (hist->GetEntries() <= 0) return kOK;
403 return (hist->GetMean() > 0 ? kOK : kProblem);
404}
405
05e5e0c1 406//__________________________________________________________________
1306ba55 407UShort_t
05e5e0c1 408AliFMDQAChecker::CheckOne(AliQAv1::ALITASK_t what,
409 AliRecoParam::EventSpecie_t specie,
410 TH1* hist) const
411{
412 if(what == AliQAv1::kESD) return CheckESD(specie, hist);
413 if(what == AliQAv1::kRAW) return CheckRaw(specie, hist);
414 if(what == AliQAv1::kSIM) return CheckSim(specie, hist);
415 if(what == AliQAv1::kREC) return CheckRec(specie, hist);
416 return 0;
417}
418//__________________________________________________________________
1306ba55 419UShort_t
05e5e0c1 420AliFMDQAChecker::CheckESD(AliRecoParam::EventSpecie_t /* specie*/,
421 TH1* hist) const
422{
1306ba55 423 return BasicCheck(hist);
424}
550157b2 425namespace {
426 Double_t Chi2Scale(TH1* h, Double_t base=10000)
427 {
428 return 1. / TMath::Max(1., h->GetEntries() / base);
429 }
430 void AddLine(TObjArray* lines,
431 Double_t x1, Double_t x2, Double_t x3,
432 Double_t y, Double_t dy,
433 const char* name, Double_t val, Double_t lim,
434 Bool_t ok, Int_t color)
435 {
436 TString n; n.Form("%s:", name);
437 TLatex* ltx = new TLatex(x1, y, n);
438 ltx->SetNDC(true);
439 ltx->SetTextSize(dy-0.01);
440 ltx->SetTextColor(color);
441 lines->Add(ltx);
442
443 n.Form("%7.3f", val);
444 ltx = new TLatex(x2, y, n);
445 ltx->SetNDC(true);
446 ltx->SetTextSize(dy-0.01);
447 ltx->SetTextColor(color);
448 lines->Add(ltx);
449
450 if (lim < 0) n = "(ignored)";
451 else n.Form("%c %4.2f", ok ? '<' : '>', lim);
452 ltx = new TLatex(x3, y, n);
453 ltx->SetNDC(true);
454 ltx->SetTextSize(dy-0.01);
455 ltx->SetTextColor(color);
456 lines->Add(ltx);
457 }
458}
459
1306ba55 460//__________________________________________________________________
461UShort_t
462AliFMDQAChecker::CheckFit(TH1* hist, const TFitResultPtr& res,
463 Double_t low, Double_t high, Int_t& color) const
464{
465 color = kGreen+4;
466
300e2129 467 // Check if there's indeed a result - if not, flag as OK
468 if (!res.Get()) return 0;
469
1306ba55 470 UShort_t ret = 0;
471 Int_t nPar = res->NPar();
472 Double_t dy = .06;
473 Double_t x = .2;
550157b2 474 Double_t x2 = .3;
475 Double_t x3 = .4;
1306ba55 476 Double_t y = .9-dy;
477 Double_t chi2 = res->Chi2();
478 Int_t nu = res->Ndf();
550157b2 479 Double_t s = Chi2Scale(hist,fELossMinEntries);
1306ba55 480 Double_t red = (nu == 0 ? fELossFkupChi2Nu : chi2 / nu);
481 TObjArray* lines = 0;
e0c60e77 482 // TLatex* lRed = 0;
1306ba55 483 TLatex* ltx = 0;
e0c60e77 484 Int_t chi2Check = 0;
485 Double_t chi2Lim = fELossBadChi2Nu;
550157b2 486 if (AliDebugLevel() > 0)
487 printf("FIT: %s, 1, %d, %f, %f\n", hist->GetName(),
488 Int_t(hist->GetEntries()), red, s * red);
489 red *= s;
e0c60e77 490 if (red > fELossBadChi2Nu) { // || res->Prob() < .01) {
491 // AliWarningF("Fit gave chi^2/nu=%f/%d=%f>%f (%f)",
492 // res->Chi2(), res->Ndf(), red, fELossBadChi2Nu,
493 // fELossFkupChi2Nu);
494 // res->Print();
495 chi2Check++;
496 if (red > fELossFkupChi2Nu) {
497 chi2Check++;
498 chi2Lim = fELossFkupChi2Nu;
499 }
500 }
501 ret += chi2Check;
502
1306ba55 503 if (fShowFitResults) {
504 lines = new TObjArray(nPar+3);
505 lines->SetName("lines");
506 lines->SetOwner(true);
550157b2 507
508 AddLine(lines, x, x2, x3, y, dy, "#chi^{2}/#nu", red, chi2Lim,
509 chi2Check < 1, chi2Check < 1 ? color :
510 chi2Check < 2 ? kOrange+2 : kRed+2);
1306ba55 511
512 Double_t x1 = .85;
513 Double_t y1 = .5;
1306ba55 514
e0c60e77 515 // y1 -= dy;
1306ba55 516 ltx = new TLatex(x1, y1, Form("Fit range: [%6.2f,%6.2f]", low, high));
517 ltx->SetTextColor(kGray+3);
518 ltx->SetTextSize(dy-.01);
519 ltx->SetTextAlign(31);
520 ltx->SetNDC(true);
521 lines->Add(ltx);
522
523 y1 -= dy;
e0c60e77 524 ltx = new TLatex(x1, y1, Form("Entries: %d (%d)",
525 Int_t(hist->GetEffectiveEntries()),
526 fELossMaxEntries));
1306ba55 527 ltx->SetTextColor(kGray+3);
528 ltx->SetTextSize(dy-.01);
529 ltx->SetTextAlign(31);
530 ltx->SetNDC(true);
531 lines->Add(ltx);
550157b2 532
533 y1 -= dy;
534 ltx = new TLatex(x1, y1, Form("%s: %f #pm %f",
535 res->ParName(1).c_str(),
536 res->Parameter(1),
537 res->ParError(1)));
538 ltx->SetTextColor(kGray+3);
539 ltx->SetTextSize(dy-.01);
540 ltx->SetTextAlign(31);
541 ltx->SetNDC(true);
542 lines->Add(ltx);
1306ba55 543 }
544
1306ba55 545 // Now check the relative error on the fit parameters
546 Int_t parsOk = 0;
547 for (Int_t i = 0; i < nPar; i++) {
548 if (res->IsParameterFixed(i)) continue;
e0c60e77 549 Double_t thr = fELossGoodParError;
1306ba55 550 Double_t pv = res->Parameter(i);
551 Double_t pe = res->ParError(i);
552 Double_t rel = (pv == 0 ? 100 : pe / pv);
e0c60e77 553 Bool_t ok = (i == 3) || (rel < thr);
1306ba55 554 if (lines) {
555 y -= dy;
550157b2 556 AddLine(lines, x, x2, x3, y, dy,Form("#delta%s/%s",
557 res->ParName(i).c_str(),
558 res->ParName(i).c_str()),
559 rel, (i == 3 ? -1 : thr), ok, ok ? color : kOrange+2);
1306ba55 560 }
561 if (i == 3) continue; // Skip sigma
e0c60e77 562 if (ok) parsOk++;
1306ba55 563 }
564 if (parsOk > 0)
565 ret = TMath::Max(ret-(parsOk-1),0);
566 if (ret > 1) color = kRed+2;
567 if (ret > 0) color = kOrange+2;
568
550157b2 569 if (lines) {
570 TList* lf = hist->GetListOfFunctions();
571 TObject* old = lf->FindObject(lines->GetName());
572 if (old) {
573 lf->Remove(old);
574 delete old;
575 }
576 lf->Add(lines);
1306ba55 577 }
1306ba55 578 hist->SetStats(false);
579
580 return ret;
581}
582
05e5e0c1 583//__________________________________________________________________
1306ba55 584UShort_t
e0c60e77 585AliFMDQAChecker::CheckRaw(AliRecoParam::EventSpecie_t specie,
05e5e0c1 586 TH1* hist) const
587{
1306ba55 588 Int_t ret = BasicCheck(hist);
589 TString name(hist->GetName());
590 if (name.Contains("readouterrors", TString::kIgnoreCase)) {
591 // Check the mean number of errors per event
592 TH2* roErrors = static_cast<TH2*>(hist);
593 Int_t nY = roErrors->GetNbinsY();
594
e0c60e77 595 TLatex* ltx = new TLatex(.15, .9, Form("Thresholds: %5.2f,%5.2f",
1306ba55 596 fROErrorsBad, fROErrorsFkup));
597 ltx->SetName("thresholds");
598 ltx->SetTextColor(kGray+3);
599 ltx->SetNDC();
600
601 TList* ll = hist->GetListOfFunctions();
602 TObject* old = ll->FindObject(ltx->GetName());
603 if (old) {
604 ll->Remove(old);
605 delete old;
606 }
607 ll->Add(ltx);
608
609 for (Int_t i = 1; i <= 3; i++) {
610 Double_t sum = 0;
611 Int_t cnt = 0;
612 for (Int_t j = 1; j <= nY; j++) {
613 Int_t n = roErrors->GetBinContent(i, j);
614 sum += n * roErrors->GetYaxis()->GetBinCenter(j);
615 cnt += n;
616 }
550157b2 617 Double_t mean = (cnt <= 0 ? 0 : sum / cnt);
e0c60e77 618 Double_t x = ((i-.5) * (1-0.1-0.1) / 3 + 0.1);
619
620 ltx = new TLatex(x, kROErrorsLabelY, Form("Mean: %6.3f", mean));
1306ba55 621 ltx->SetName(Form("FMD%d", i));
e0c60e77 622 ltx->SetNDC();
1306ba55 623 ltx->SetTextAngle(90);
624 ltx->SetTextColor(kGreen+4);
625 old = ll->FindObject(ltx->GetName());
626 if (old) {
627 ll->Remove(old);
628 delete old;
629 }
630 ll->Add(ltx);
631
632 if (mean > fROErrorsBad) {
633 AliWarningF("Mean of readout errors for FMD%d = %f > %f (%f)",
634 i, mean, fROErrorsBad, fROErrorsFkup);
635 ret++;
636 ltx->SetTextColor(kOrange+2);
637 if (mean > fROErrorsFkup) {
638 ret++;
639 ltx->SetTextColor(kRed+2);
640 }
641 }
642 }
643 }
644 else if (name.Contains("eloss",TString::kIgnoreCase)) {
550157b2 645 // If we' asked to not fit the data, return immediately
646 if (fNoFits) return ret;
647 // Do not fit cosmic or calibration data
e0c60e77 648 if (specie == AliRecoParam::kCosmic ||
649 specie == AliRecoParam::kCalib) return ret;
550157b2 650 // Do not fit `expert' histograms
651 if (hist->TestBit(AliQAv1::GetExpertBit())) return ret;
652 // Do not fit histograms with too little data
653 if (hist->GetEntries() < fELossMinEntries) return ret;
1306ba55 654
550157b2 655 // Try to fit a function to the histogram
1306ba55 656 Double_t xMin = hist->GetXaxis()->GetXmin();
657 Double_t xMax = hist->GetXaxis()->GetXmax();
658
659 hist->GetXaxis()->SetRangeUser(fELossLowCut, xMax);
660 Int_t bMaxY = hist->GetMaximumBin();
661 Double_t xMaxY = hist->GetXaxis()->GetBinCenter(bMaxY);
662 Double_t rms = hist->GetRMS();
663 Double_t low = hist->GetXaxis()->GetBinCenter(bMaxY-4);
664 hist->GetXaxis()->SetRangeUser(0.2, xMaxY+(fELossNRMS+1)*rms);
665 rms = hist->GetRMS();
666 hist->GetXaxis()->SetRange(0,-1);
667 TF1* func = makeLandauGaus(name);
668 func->SetParameter(1, xMaxY);
669 func->SetLineColor(kGreen+4);
670 // func->SetLineStyle(2);
671 Double_t high = xMax; // xMaxY+fELossNRMS*rms;
550157b2 672 if (fELossNRMS > 0) high = xMaxY+fELossNRMS*rms;
61d27864 673
674 // Check we don't have an empty fit range
675 if (low >= high) return ret;
676
677 // Check that we have enough counts in the fit range
678 Int_t bLow = hist->FindBin(low);
679 Int_t bHigh = hist->FindBin(high);
680 if (bLow >= bHigh || hist->Integral(bLow, bHigh) < fELossMinEntries)
681 return ret;
1306ba55 682
550157b2 683 // Set our fit function
684 TString fitOpt("QS");
300e2129 685 TFitResultPtr res = hist->Fit(func, fitOpt, "", low, high);
686 Int_t color = func->GetLineColor();
687 UShort_t qual = CheckFit(hist, res, low, high, color);
1306ba55 688
689 // Make sure we save the function in the full range of the histogram
690 func = hist->GetFunction("landauGaus");
550157b2 691 if (fELossNRMS <= 0) func->SetRange(xMin, xMax);
1306ba55 692 // func->SetParent(hist);
693 func->Save(xMin, xMax, 0, 0, 0, 0);
694 func->SetLineColor(color);
e0c60e77 695
550157b2 696 fitOpt.Append("+");
697 res = hist->Fit("pol2", fitOpt, "", fELossMinSharing, low-0.05);
698 func = hist->GetFunction("pol2");
699 Double_t s = Chi2Scale(hist,fELossMinEntries*100);
61d27864 700 Double_t chi2 = (!res.Get() ? 0 : res->Chi2());
701 Int_t nu = (!res.Get() ? 1 : res->Ndf());
550157b2 702 Double_t red = s * (nu == 0 ? fELossFkupChi2Nu : chi2 / nu);
703 if (AliDebugLevel())
704 printf("FIT: %s, 2, %d, %f, %f\n", hist->GetName(),
705 Int_t(hist->GetEntries()), red, s * red);
706 red *= s;
707 if (red > fELossFkupChi2Nu) func->SetLineColor(kRed);
708 else func->SetLineColor(kGreen+4);
709
e0c60e77 710 // Now check if this histogram should be cleared or not
711 if (fELossMaxEntries > 0 && hist->GetEntries() > fELossMaxEntries)
550157b2 712 hist->SetBit(AliFMDQADataMakerRec::kResetBit);
1306ba55 713 if (qual > 0) {
714 func->SetLineWidth(3);
715 func->SetLineStyle(1);
716 if (qual > 1)
717 func->SetLineWidth(4);
718 }
719 ret += qual;
720 }
721
722 return ret;
05e5e0c1 723}
724//__________________________________________________________________
1306ba55 725UShort_t
05e5e0c1 726AliFMDQAChecker::CheckSim(AliRecoParam::EventSpecie_t /* specie*/,
727 TH1* hist) const
728{
1d65d916 729 //
730 // Check simulated hits
731 //
1306ba55 732 return BasicCheck(hist);
05e5e0c1 733}
734//__________________________________________________________________
1306ba55 735UShort_t
05e5e0c1 736AliFMDQAChecker::CheckRec(AliRecoParam::EventSpecie_t /* specie*/,
737 TH1* hist) const
738{
1d65d916 739 //
740 // Check reconstructed data
741 //
1306ba55 742 return BasicCheck(hist);
05e5e0c1 743}
744
1d65d916 745//__________________________________________________________________
746void AliFMDQAChecker::AddStatusPave(TH1* hist, Int_t qual,
747 Double_t xl, Double_t yl,
748 Double_t xh, Double_t yh) const
749{
750 //
751 // Add a status pave to a plot
752 //
753 if (xh < 0) xh = gStyle->GetStatX();
754 if (xl < 0) xl = xh - gStyle->GetStatW();
755 if (yh < 0) yh = gStyle->GetStatY();
756 if (yl < 0) yl = xl - gStyle->GetStatH();
757
758 TPaveText* text = new TPaveText(xl, yl, xh, yh, "brNDC");
759 Int_t bg = kGreen-10;
760 Int_t fg = kBlack;
761 TString msg = "OK";
762 if (qual >= kWhatTheFk) { bg = kRed+1; fg = kWhite; msg = "Argh!"; }
763 else if (qual >= kBad) { bg = kRed-3; fg = kWhite; msg = "Bad"; }
764 else if (qual >= kProblem) { bg = kOrange-4; msg = "Warning"; }
765 text->AddText(msg);
766 text->SetTextFont(62);
767 text->SetTextColor(fg);
768 text->SetFillColor(bg);
769
770 TList* ll = hist->GetListOfFunctions();
771 TObject* old = ll->FindObject(text->GetName());
772 if (old) {
773 ll->Remove(old);
774 delete old;
775 }
776 ll->Add(text);
777}
778
c9dd1c4d 779//__________________________________________________________________
fa5a224b 780void AliFMDQAChecker::Check(Double_t* rv,
781 AliQAv1::ALITASK_t what,
782 TObjArray** list,
783 const AliDetectorRecoParam* /*t*/)
784{
785 //
786 // Member function called to do the actual checking
787 //
788 // Parameters:
789 // rv Array of return values.
790 // what What to check
791 // list Array of arrays of histograms. There's one arrat for
792 // each 'specie'
793 // t Reconstruction parameters - not used.
794 //
1306ba55 795 // The bounds defined for RV are
796 //
797 // FATAL: [-1, 0.0]
798 // ERROR: (0.0, 0.002]
799 // WARNING: (0.002,0.5]
800 // INFO: (0.5, 1.0]
801 //
fa5a224b 802 // Double_t* rv = new Double_t[AliRecoParam::kNSpecies] ;
1306ba55 803
804 if (!fDidExternal) ProcessExternalParams();
805
6ceca4ef 806 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
83dbc5b8 807 // Int_t count = 0;
fa5a224b 808 rv[specie] = 0.;
809
1706c710 810 if (!AliQAv1::Instance()->IsEventSpecieSet(specie) )
6ceca4ef 811 continue ;
812
813 if(!list[specie]) continue;
814
a3e1fdcc 815 TH1* hist = 0;
816 Int_t nHist = list[specie]->GetEntriesFast();
817
818 // Find the status histogram if any
819 TH2* status = 0;
820 Int_t istatus = AliFMDQADataMakerRec::GetHalfringIndex(4, 'i', 0, 0);
821 if (istatus < nHist)
822 status = dynamic_cast<TH2*>(list[specie]->At(istatus));
823
824 UShort_t ret = 0;
584d4c54 825 for(Int_t i= 0; i< nHist; i++) {
05e5e0c1 826 if (!(hist = static_cast<TH1*>(list[specie]->At(i)))) continue;
a3e1fdcc 827 if (hist == status) continue;
828
1306ba55 829 Int_t qual = CheckOne(what, AliRecoParam::ConvertIndex(specie), hist);
830 hist->SetUniqueID(Quality2Bit(qual));
1d65d916 831 hist->SetStats(0);
832 AddStatusPave(hist, qual);
1306ba55 833 ret += qual;
a3e1fdcc 834
835 if (!status) continue;
836
1d65d916 837 // Parse out the detector and ring, calculate the bin, and fill
838 // status histogram.
a3e1fdcc 839 TString nme(hist->GetName());
840 Char_t cD = nme[nme.Length()-2];
841 Char_t cR = nme[nme.Length()-1];
842 Int_t xbin = 0;
843 switch (cD) {
844 case '1': xbin = 1; break;
845 case '2': xbin = 2 + ((cR == 'i' || cR == 'I') ? 0 : 1); break;
846 case '3': xbin = 4 + ((cR == 'i' || cR == 'I') ? 0 : 1); break;
847 }
848 if (xbin == 0) continue;
849 status->Fill(xbin, qual);
850
fa5a224b 851 } // for (int i ...)
1306ba55 852 rv[specie] = ret;
853 // if (ret > kWhatTheFk) rv[specie] = fLowTestValue[AliQAv1::kFATAL];
854 // else if (ret > kBad) rv[specie] = fUpTestValue[AliQAv1::kERROR];
855 // else if (ret > kProblem) rv[specie] = fUpTestValue[AliQAv1::kWARNING];
856 // else rv[specie] = fUpTestValue[AliQAv1::kINFO];
857 AliDebugF(3, "Combined sum is %d -> %f", ret, rv[specie]);
858
a3e1fdcc 859 if (status) {
550157b2 860 Int_t nProblem = 0;
861 Int_t nBad = 0;
a3e1fdcc 862 for (Int_t i = 1; i < status->GetXaxis()->GetNbins(); i++) {
550157b2 863 nProblem += status->GetBinContent(i, 3);
864 nBad += status->GetBinContent(i, 4);
a3e1fdcc 865 }
550157b2 866 Int_t qual = 0;
867 if (nProblem > fMaxNProblem) qual++;
868 if (nBad > fMaxNBad) qual += 2;
a3e1fdcc 869 status->SetUniqueID(Quality2Bit(qual));
1d65d916 870 AddStatusPave(status, qual);
a3e1fdcc 871 }
83dbc5b8 872 // if (count != 0) rv[specie] /= count;
6ceca4ef 873 }
fa5a224b 874 // return rv;
6ceca4ef 875}
876
05e5e0c1 877namespace {
878 Int_t CheckForLog(TAxis* axis,
879 TVirtualPad* pad,
880 Int_t xyz)
881 {
882 Int_t ret = 0;
883 TString t(axis->GetTitle());
884 if (!t.Contains("[log]", TString::kIgnoreCase)) return 0;
885 t.ReplaceAll("[log]", "");
886 switch (xyz) {
887 case 1: pad->SetLogx(); ret |= 0x1; break;
888 case 2: pad->SetLogy(); ret |= 0x2; break;
889 case 3: pad->SetLogz(); ret |= 0x4; break;
890 }
891 axis->SetTitle(t);
892 return ret;
893 }
9eb9c521 894 void RestoreLog(TAxis* axis, Bool_t log)
895 {
896 if (!log) return;
897 TString t(axis->GetTitle());
898 t.Append("[log]");
899 axis->SetTitle(t);
900 }
05e5e0c1 901}
6ceca4ef 902
0f666f27 903namespace {
904 void FindMinMax(TH1* h, Double_t& min, Double_t& max)
905 {
906 Double_t tmin = 1e9;
907 Double_t tmax = 0;
908 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
909 Double_t c = h->GetBinContent(i);
910 if (c < 1e-8) continue;
911 tmin = TMath::Min(tmin, c);
912 tmax = TMath::Max(tmax, c);
913 }
914 min = tmin;
915 max = tmax;
916 }
917}
a3e1fdcc 918
919namespace {
920 Int_t GetHalfringPad(TH1* h) {
921 TString nme(h->GetName());
922 Char_t cD = nme[nme.Length()-2];
923 Char_t cR = nme[nme.Length()-1];
924 Int_t xbin = 0;
925 switch (cD) {
926 case '1': xbin = 1; break;
927 case '2': xbin = ((cR == 'i' || cR == 'I') ? 2 : 5); break;
928 case '3': xbin = ((cR == 'i' || cR == 'I') ? 3 : 6); break;
929 }
930 return xbin;
931 }
932}
933
1706c710 934//____________________________________________________________________________
935void
936AliFMDQAChecker::MakeImage(TObjArray** list,
937 AliQAv1::TASKINDEX_t task,
938 AliQAv1::MODE_t mode)
939{
940 // makes the QA image for sim and rec
941 //
942 // Parameters:
943 // task What to check
944 // list Array of arrays of histograms. There's one array for
945 // each 'specie'
946 // t Reconstruction parameters - not used.
947 //
948 Int_t nImages = 0 ;
949 Double_t max = 0;
950 Double_t min = 10000;
9eb9c521 951
952 // Loop over all species
1706c710 953 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
05e5e0c1 954 AliRecoParam::EventSpecie_t spe = AliRecoParam::ConvertIndex(specie);
955 if (!AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))
956 ->IsEventSpecieSet(spe))
544ed74f 957 continue;
9eb9c521 958
959 // If nothing is defined for this specie, go on.
05e5e0c1 960 if(!list[specie] || list[specie]->GetEntriesFast() == 0) continue;
1706c710 961
9eb9c521 962 // Loop over the histograms and figure out how many histograms we
963 // have and the min/max
05e5e0c1 964 TH1* hist = 0;
1706c710 965 Int_t nHist = list[specie]->GetEntriesFast();
966 for(Int_t i= 0; i< nHist; i++) {
967 hist = static_cast<TH1F*>(list[specie]->At(i));
ae559def 968 if (hist && hist->TestBit(AliQAv1::GetImageBit())) {
1706c710 969 nImages++;
05e5e0c1 970 TString name(hist->GetName());
a3e1fdcc 971 if (name.Contains("readouterrors", TString::kIgnoreCase) ||
972 name.Contains("status", TString::kIgnoreCase)) continue;
0f666f27 973
974 // Double_t hMax = hist->GetMaximum();
05e5e0c1 975 // hist->GetBinContent(hist->GetMaximumBin());
0f666f27 976 // Double_t hMin = hist->GetMinimum();
05e5e0c1 977 // hist->GetBinContent(hist->GetMinimumBin());
0f666f27 978 Double_t hMax, hMin;
979 FindMinMax(hist, hMin, hMax);
05e5e0c1 980 max = TMath::Max(max, hMax);
981 min = TMath::Min(min, hMin);
1306ba55 982 // AliInfoF("Min/max of %40s: %f/%f, global -> %f/%f",
983 // hist->GetName(), hMin, hMax, min, max);
1706c710 984 }
985 }
986 break ;
987 }
1306ba55 988 // AliInfoF("Global min/max=%f/%f", min, max);
9558fc76 989 min = TMath::Max(1e-1, min);
990 max = TMath::Max(1e5, max);
1706c710 991
9eb9c521 992 // IF no images, go on.
1706c710 993 if (nImages == 0) {
994 AliDebug(AliQAv1::GetQADebugLevel(),
995 Form("No histogram will be plotted for %s %s\n", GetName(),
996 AliQAv1::GetTaskName(task).Data()));
997 return;
998 }
999
1000 AliDebug(AliQAv1::GetQADebugLevel(),
1001 Form("%d histograms will be plotted for %s %s\n",
1002 nImages, GetName(), AliQAv1::GetTaskName(task).Data()));
05e5e0c1 1003 gStyle->SetOptStat(0);
9eb9c521 1004
1005 // Again loop over species and draw a canvas
1706c710 1006 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
05e5e0c1 1007 if (!AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))
1008 ->IsEventSpecieSet(specie)) continue;
1706c710 1009
9eb9c521 1010 // if Nothing here, go on
1011 if(!list[specie] || list[specie]->GetEntries() <= 0 ||
1012 nImages <= 0) continue;
1013
9558fc76 1014 // Form the title
1706c710 1015 const Char_t * title = Form("QA_%s_%s_%s", GetName(),
1016 AliQAv1::GetTaskName(task).Data(),
1017 AliRecoParam::GetEventSpecieName(specie));
9eb9c521 1018 if (!fImage[specie]) fImage[specie] = new TCanvas(title, title) ;
1706c710 1019 fImage[specie]->Clear() ;
1020 fImage[specie]->SetTitle(title) ;
1021 fImage[specie]->cd() ;
1022
9eb9c521 1023 // Put something in the canvas - even if empty
1706c710 1024 TPaveText someText(0.015, 0.015, 0.98, 0.98) ;
1025 someText.AddText(title) ;
9eb9c521 1026 someText.SetFillColor(0);
1027 someText.SetFillStyle(0);
1028 someText.SetBorderSize(0);
1029 someText.SetTextColor(kRed+1);
1706c710 1030 someText.Draw() ;
05e5e0c1 1031 TString outName(Form("%s%s%d.%s", AliQAv1::GetImageFileName(),
1032 AliQAv1::GetModeName(mode),
1033 AliQAChecker::Instance()->GetRunNumber(),
1034 AliQAv1::GetImageFileFormat()));
1035 fImage[specie]->Print(outName, "ps") ;
1706c710 1036
9eb9c521 1037 // Now set some parameters on the canvas
1038 fImage[specie]->Clear();
1039 fImage[specie]->SetTopMargin(0.10);
1040 fImage[specie]->SetBottomMargin(0.15);
1041 fImage[specie]->SetLeftMargin(0.15);
1042 fImage[specie]->SetRightMargin(0.05);
1043
1044 // Put title on top
1045 const char* topT = Form("Mode: %s, Task: %s, Specie: %s, Run: %d",
1046 AliQAv1::GetModeName(mode),
1047 AliQAv1::GetTaskName(task).Data(),
1048 AliRecoParam::GetEventSpecieName(specie),
1049 AliQAChecker::Instance()->GetRunNumber());
1050 TLatex* topText = new TLatex(.5, .99, topT);
1051 topText->SetTextAlign(23);
1052 topText->SetTextSize(.038);
1053 topText->SetTextFont(42);
1054 topText->SetTextColor(kBlue+3);
1055 topText->SetNDC();
1056 topText->Draw();
a3e1fdcc 1057
1058 // Find the status histogram if any
1059 TH2* status = 0;
1060 Int_t istatus = AliFMDQADataMakerRec::GetHalfringIndex(4, 'i', 0, 0);
1061 if (istatus < list[specie]->GetEntriesFast())
1062 status = dynamic_cast<TH2*>(list[specie]->At(istatus));
1063
9eb9c521 1064 // Divide canvas
9558fc76 1065 // if (fDoScale)
a3e1fdcc 1066 TVirtualPad* plots = fImage[specie];
1067 TVirtualPad* stat = 0;
1068 if (status) {
1069 // AliWarning("Drawing plots sub-pad");
1070 TPad* pM = new TPad("plots", "Plots Pad", 0, .2, 1., .9, 0, 0);
1071 fImage[specie]->cd();
1072 pM->Draw();
1073 plots = pM;
1074 // AliWarning("Drawing status sub-pad");
1075 TPad* pS = new TPad("status", "Status Pad", 0, 0, 1., .2, 0, 0);
1076 fImage[specie]->cd();
1077 pS->Draw();
1078 pS->SetLogz();
1079 stat = pS;
1080 // status->DrawCopy("colz");
1081 }
1082 // AliWarningF("fImage[specie]=%p, plots=%p", fImage[specie], plots);
1083 // plots->cd();
1084 Int_t nx = 3;
1085 Int_t ny = (nImages + .5) / nx;
1086 plots->Divide(nx, ny, 0, 0);
9558fc76 1087 // else fImage[specie]->Divide(nx, ny);
1706c710 1088
1089
9eb9c521 1090 // Loop over histograms
05e5e0c1 1091 TH1* hist = 0;
1706c710 1092 Int_t nHist = list[specie]->GetEntriesFast();
1706c710 1093 for (Int_t i = 0; i < nHist; i++) {
05e5e0c1 1094 hist = static_cast<TH1*>(list[specie]->At(i));
1095 if (!hist || !hist->TestBit(AliQAv1::GetImageBit())) continue;
a3e1fdcc 1096 if (hist == status) continue;
1097 TString name(hist->GetName());
1098 Bool_t isROE = name.Contains("readouterrors", TString::kIgnoreCase);
9eb9c521 1099
1100 // Go to sub-pad
a3e1fdcc 1101 TVirtualPad* pad = 0;
1102 if (isROE) pad = plots->cd(4);
1103 else pad = plots->cd(GetHalfringPad(hist));
1104
9eb9c521 1105 pad->SetRightMargin(0.01);
9558fc76 1106 if (!fDoScale) {
1107 pad->SetLeftMargin(0.10);
1108 pad->SetBottomMargin(0.10);
1109 }
9eb9c521 1110
1111 // Check for log scale
05e5e0c1 1112 Int_t logOpts = 0;
1113 logOpts |= CheckForLog(hist->GetXaxis(), pad, 1);
1114 logOpts |= CheckForLog(hist->GetYaxis(), pad, 2);
1115 logOpts |= CheckForLog(hist->GetZaxis(), pad, 3);
05e5e0c1 1116
9eb9c521 1117 // Figure out special cases
1306ba55 1118 TString opt("");
a3e1fdcc 1119 if (isROE) {
05e5e0c1 1120 pad->SetRightMargin(0.15);
1121 pad->SetBottomMargin(0.10);
9558fc76 1122 // pad->SetTopMargin(0.02);
05e5e0c1 1123 opt="COLZ";
1124 }
1125 else {
9eb9c521 1126 pad->SetGridx();
1127 pad->SetGridy();
9558fc76 1128 if (fDoScale) {
1129 hist->SetMinimum(min);
1130 hist->SetMaximum(max);
1131 }
1132 else {
1133 hist->SetMinimum();
1134 hist->SetMaximum();
1135 }
05e5e0c1 1136 }
9eb9c521 1137 // Draw (As a copy)
05e5e0c1 1138 hist->DrawCopy(opt);
1306ba55 1139
9eb9c521 1140 // Special cases
550157b2 1141 if (!name.Contains("readouterrors", TString::kIgnoreCase)) {
9eb9c521 1142 gStyle->SetOptTitle(0);
1143 TPad* insert = new TPad("insert", "Zoom",
a3e1fdcc 1144 .5,.5, .99, .95, 0, 0, 0);
9eb9c521 1145 insert->SetTopMargin(0.01);
1146 insert->SetRightMargin(0.01);
1147 insert->SetFillColor(0);
1148 insert->SetBorderSize(1);
1149 insert->SetBorderMode(0);
1150 insert->Draw();
1151 insert->cd();
1152 if (logOpts & 0x1) insert->SetLogx();
1153 if (logOpts & 0x2) insert->SetLogy();
1154 if (logOpts & 0x4) insert->SetLogz();
0f666f27 1155 hist->GetXaxis()->SetRange(1, hist->GetNbinsX()/8);
1156 TH1* copy = hist->DrawCopy(opt);
1157 copy->GetXaxis()->SetNdivisions(408, false);
9eb9c521 1158 // Restore full range
0f666f27 1159 hist->GetXaxis()->SetRange(0, 0);
9eb9c521 1160 gStyle->SetOptTitle(1);
1161 }
05e5e0c1 1162 pad->cd();
9eb9c521 1163 // Possibly restore the log options
1164 RestoreLog(hist->GetXaxis(), logOpts & 0x1);
1165 RestoreLog(hist->GetYaxis(), logOpts & 0x2);
1166 RestoreLog(hist->GetZaxis(), logOpts & 0x4);
1706c710 1167 }
a3e1fdcc 1168 if (status && stat) {
1169 stat->cd();
1170 status->DrawCopy("BOX TEXT");
1171 }
0f666f27 1172 // Print to a post-script file
05e5e0c1 1173 fImage[specie]->Print(outName, "ps");
550157b2 1174 if (AliDebugLevel() > 0)
a3e1fdcc 1175 fImage[specie]->Print(Form("%s_%d.png",
1176 AliRecoParam::GetEventSpecieName(specie),
1177 AliQAChecker::Instance()->GetRunNumber()));
1706c710 1178 }
1179}
c9dd1c4d 1180
1181//__________________________________________________________________
1182//
1183// EOF
1184//