LCOV - code coverage report
Current view: top level - FMD/FMDrec - AliFMDQAChecker.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 98 600 16.3 %
Date: 2016-06-14 17:26:59 Functions: 10 28 35.7 %

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

Generated by: LCOV version 1.11