CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/DQMServices/Core/src/QTest.cc

Go to the documentation of this file.
00001 #include "DQMServices/Core/interface/QTest.h"
00002 #include "DQMServices/Core/interface/DQMStore.h"
00003 #include "DQMServices/Core/src/QStatisticalTests.h"
00004 #include "DQMServices/Core/src/DQMError.h"
00005 #include "TMath.h"
00006 #include <iostream>
00007 #include <sstream>
00008 #include <math.h>
00009 
00010 using namespace std;
00011 
00012 const float QCriterion::ERROR_PROB_THRESHOLD = 0.50;
00013 const float QCriterion::WARNING_PROB_THRESHOLD = 0.90;
00014 
00015 // initialize values
00016 void
00017 QCriterion::init(void)
00018 {
00019   errorProb_ = ERROR_PROB_THRESHOLD;
00020   warningProb_ = WARNING_PROB_THRESHOLD;
00021   setAlgoName("NO_ALGORITHM");
00022   status_ = dqm::qstatus::DID_NOT_RUN;
00023   message_ = "NO_MESSAGE";
00024   verbose_ = 0; // 0 = silent, 1 = algorithmic failures, 2 = info
00025 }
00026 
00027 float QCriterion::runTest(const MonitorElement * /* me */)
00028 {
00029   raiseDQMError("QCriterion", "virtual runTest method called" );
00030   return 0.;
00031 }
00032 //===================================================//
00033 //================ QUALITY TESTS ====================//
00034 //==================================================//
00035 
00036 //-------------------------------------------------------//
00037 //----------------- Comp2RefEqualH base -----------------//
00038 //-------------------------------------------------------//
00039 // run the test (result: [0, 1] or <0 for failure)
00040 float Comp2RefEqualH::runTest(const MonitorElement*me)
00041 {
00042   badChannels_.clear();
00043 
00044   if (!me) 
00045     return -1;
00046   if (!me->getRootObject() || !me->getRefRootObject()) 
00047     return -1;
00048   TH1* h=0; //initialize histogram pointer
00049   TH1* ref_=0;
00050   
00051   if (verbose_>1) 
00052     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00053               << me-> getFullname() << "\n";
00054 
00055   int nbins=0;
00056   int nbinsref=0;
00057   //-- TH1F
00058   if (me->kind()==MonitorElement::DQM_KIND_TH1F)
00059   { 
00060     nbins = me->getTH1F()->GetXaxis()->GetNbins(); 
00061     nbinsref = me->getRefTH1F()->GetXaxis()->GetNbins();
00062     h  = me->getTH1F(); // access Test histo
00063     ref_ = me->getRefTH1F(); //access Ref hiso 
00064     if (nbins != nbinsref) return -1;
00065   } 
00066   //-- TH1S
00067   else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
00068   { 
00069     nbins = me->getTH1S()->GetXaxis()->GetNbins(); 
00070     nbinsref = me->getRefTH1S()->GetXaxis()->GetNbins();
00071     h  = me->getTH1S(); // access Test histo
00072     ref_ = me->getRefTH1S(); //access Ref hiso 
00073     if (nbins != nbinsref) return -1;
00074   } 
00075   //-- TH1D
00076   else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
00077   { 
00078     nbins = me->getTH1D()->GetXaxis()->GetNbins(); 
00079     nbinsref = me->getRefTH1D()->GetXaxis()->GetNbins();
00080     h  = me->getTH1D(); // access Test histo
00081     ref_ = me->getRefTH1D(); //access Ref hiso 
00082     if (nbins != nbinsref) return -1;
00083   } 
00084   //-- TH2
00085   else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
00086   { 
00087     nbins = me->getTH2F()->GetXaxis()->GetNbins() *
00088             me->getTH2F()->GetYaxis()->GetNbins();
00089     nbinsref = me->getRefTH2F()->GetXaxis()->GetNbins() *
00090                me->getRefTH2F()->GetYaxis()->GetNbins();
00091     h = me->getTH2F(); // access Test histo
00092     ref_ = me->getRefTH2F(); //access Ref hiso 
00093     if (nbins != nbinsref) return -1;
00094   } 
00095 
00096   //-- TH2
00097   else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
00098   { 
00099     nbins = me->getTH2S()->GetXaxis()->GetNbins() *
00100             me->getTH2S()->GetYaxis()->GetNbins();
00101     nbinsref = me->getRefTH2S()->GetXaxis()->GetNbins() *
00102                me->getRefTH2S()->GetYaxis()->GetNbins();
00103     h = me->getTH2S(); // access Test histo
00104     ref_ = me->getRefTH2S(); //access Ref hiso 
00105     if (nbins != nbinsref) return -1;
00106   } 
00107 
00108   //-- TH2
00109   else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
00110   { 
00111     nbins = me->getTH2D()->GetXaxis()->GetNbins() *
00112             me->getTH2D()->GetYaxis()->GetNbins();
00113     nbinsref = me->getRefTH2D()->GetXaxis()->GetNbins() *
00114                me->getRefTH2D()->GetYaxis()->GetNbins();
00115     h = me->getTH2D(); // access Test histo
00116     ref_ = me->getRefTH2D(); //access Ref hiso 
00117     if (nbins != nbinsref) return -1;
00118   } 
00119 
00120   //-- TH3
00121   else if (me->kind()==MonitorElement::DQM_KIND_TH3F)
00122   { 
00123     nbins = me->getTH3F()->GetXaxis()->GetNbins() *
00124             me->getTH3F()->GetYaxis()->GetNbins() *
00125             me->getTH3F()->GetZaxis()->GetNbins();
00126     nbinsref = me->getRefTH3F()->GetXaxis()->GetNbins() *
00127                me->getRefTH3F()->GetYaxis()->GetNbins() *
00128                me->getRefTH3F()->GetZaxis()->GetNbins();
00129     h = me->getTH3F(); // access Test histo
00130     ref_ = me->getRefTH3F(); //access Ref hiso 
00131     if (nbins != nbinsref) return -1;
00132   } 
00133 
00134   else
00135   { 
00136     if (verbose_>0) 
00137       std::cout << "QTest:Comp2RefEqualH" 
00138         << " ME does not contain TH1F/TH1S/TH1D/TH2F/TH2S/TH2D/TH3F, exiting\n"; 
00139     return -1;
00140   } 
00141 
00142   //--  QUALITY TEST itself 
00143   int first = 0; // 1 //(use underflow bin)
00144   int last  = nbins+1; //(use overflow bin)
00145   bool failure = false;
00146   for (int bin=first;bin<=last;bin++) 
00147   {
00148     double contents = h->GetBinContent(bin);
00149     if (contents != ref_->GetBinContent(bin)) 
00150     {
00151       failure = true;
00152       DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
00153       badChannels_.push_back(chan);
00154     }
00155   }
00156   if (failure) return 0;
00157   return 1;
00158 }
00159 
00160 //-------------------------------------------------------//
00161 //-----------------  Comp2RefChi2    --------------------//
00162 //-------------------------------------------------------//
00163 float Comp2RefChi2::runTest(const MonitorElement *me)
00164 {
00165   if (!me) 
00166     return -1;
00167   if (!me->getRootObject() || !me->getRefRootObject()) 
00168     return -1;
00169   TH1* h=0;
00170   TH1* ref_=0;
00171  
00172   if (verbose_>1) 
00173     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00174               << me-> getFullname() << "\n";
00175   //-- TH1F
00176   if (me->kind()==MonitorElement::DQM_KIND_TH1F)
00177   { 
00178     h = me->getTH1F(); // access Test histo
00179     ref_ = me->getRefTH1F(); //access Ref histo
00180   } 
00181   //-- TH1S
00182   else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
00183   { 
00184     h = me->getTH1S(); // access Test histo
00185     ref_ = me->getRefTH1S(); //access Ref histo
00186   } 
00187   //-- TH1D
00188   else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
00189   { 
00190     h = me->getTH1D(); // access Test histo
00191     ref_ = me->getRefTH1D(); //access Ref histo
00192   } 
00193   //-- TProfile
00194   else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
00195   {
00196     h = me->getTProfile(); // access Test histo
00197     ref_ = me->getRefTProfile(); //access Ref histo
00198   } 
00199   else
00200   { 
00201     if (verbose_>0) 
00202       std::cout << "QTest::Comp2RefChi2"
00203                 << " ME does not contain TH1F/TH1S/TH1D/TProfile, exiting\n"; 
00204     return -1;
00205   } 
00206 
00207    //-- isInvalid ? - Check consistency in number of channels
00208   int ncx1  = h->GetXaxis()->GetNbins(); 
00209   int ncx2  = ref_->GetXaxis()->GetNbins();
00210   if ( ncx1 !=  ncx2)
00211   {
00212     if (verbose_>0) 
00213       std::cout << "QTest:Comp2RefChi2"
00214                 << " different number of channels! ("
00215                 << ncx1 << ", " << ncx2 << "), exiting\n";
00216     return -1;
00217   } 
00218 
00219   //--  QUALITY TEST itself 
00220   //reset Results
00221   Ndof_ = 0; chi2_ = -1.; ncx1 = ncx2 = -1;
00222 
00223   int i, i_start, i_end;
00224   double chi2 = 0.;  int ndof = 0; int constraint = 0;
00225 
00226   i_start = 1;  
00227   i_end = ncx1;
00228   //  if (fXaxis.TestBit(TAxis::kAxisRange)) {
00229   i_start = h->GetXaxis()->GetFirst();
00230   i_end   = h->GetXaxis()->GetLast();
00231   //  }
00232   ndof = i_end-i_start+1-constraint;
00233 
00234   //Compute the normalisation factor
00235   double sum1=0, sum2=0;
00236   for (i=i_start; i<=i_end; i++)
00237   {
00238     sum1 += h->GetBinContent(i);
00239     sum2 += ref_->GetBinContent(i);
00240   }
00241 
00242   //check that the histograms are not empty
00243   if (sum1 == 0)
00244   {
00245     if (verbose_>0) 
00246       std::cout << "QTest:Comp2RefChi2"
00247                 << " Test Histogram " << h->GetName() 
00248                 << " is empty, exiting\n";
00249     return -1;
00250   }
00251   if (sum2 == 0)
00252   {
00253     if (verbose_>0) 
00254       std::cout << "QTest:Comp2RefChi2"
00255                 << " Ref Histogram " << ref_->GetName() 
00256                 << " is empty, exiting\n";
00257     return -1;
00258   }
00259 
00260   double bin1, bin2, err1, err2, temp;
00261   for (i=i_start; i<=i_end; i++)
00262   {
00263     bin1 = h->GetBinContent(i)/sum1;
00264     bin2 = ref_->GetBinContent(i)/sum2;
00265     if (bin1 ==0 && bin2==0)
00266     {
00267       --ndof; //no data means one less degree of freedom
00268     } 
00269     else 
00270     {
00271       temp  = bin1-bin2;
00272       err1=h->GetBinError(i); err2=ref_->GetBinError(i);
00273       if (err1 == 0 && err2 == 0)
00274       {
00275         if (verbose_>0) 
00276           std::cout << "QTest:Comp2RefChi2"
00277                     << " bins with non-zero content and zero error, exiting\n";
00278         return -1;
00279       }
00280       err1*=err1      ; err2*=err2;
00281       err1/=sum1*sum1 ; err2/=sum2*sum2;
00282       chi2 +=temp*temp/(err1+err2);
00283     }
00284   }
00285   chi2_ = chi2;  Ndof_ = ndof;
00286   return TMath::Prob(0.5*chi2, int(0.5*ndof));
00287 }
00288 
00289 //-------------------------------------------------------//
00290 //-----------------  Comp2RefKolmogorov    --------------//
00291 //-------------------------------------------------------//
00292 
00293 float Comp2RefKolmogorov::runTest(const MonitorElement *me)
00294 {
00295   const double difprec = 1e-5;
00296    
00297   if (!me) 
00298     return -1;
00299   if (!me->getRootObject() || !me->getRefRootObject()) 
00300     return -1;
00301   TH1* h=0;
00302   TH1* ref_=0;
00303 
00304   if (verbose_>1) 
00305     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00306               << me-> getFullname() << "\n";
00307   //-- TH1F
00308   if (me->kind()==MonitorElement::DQM_KIND_TH1F)
00309   { 
00310     h = me->getTH1F(); // access Test histo
00311     ref_ = me->getRefTH1F(); //access Ref histo
00312   } 
00313   //-- TH1S
00314   else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
00315   { 
00316     h = me->getTH1S(); // access Test histo
00317     ref_ = me->getRefTH1S(); //access Ref histo
00318   } 
00319   //-- TH1D
00320   else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
00321   { 
00322     h = me->getTH1D(); // access Test histo
00323     ref_ = me->getRefTH1D(); //access Ref histo
00324   } 
00325   //-- TProfile
00326   else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
00327   {
00328     h = me->getTProfile(); // access Test histo
00329     ref_ = me->getRefTProfile(); //access Ref histo
00330   }
00331   else
00332   { 
00333     if (verbose_>0) 
00334       std::cout << "QTest:Comp2RefKolmogorov"
00335                 << " ME does not contain TH1F/TH1S/TH1D/TProfile, exiting\n"; 
00336     return -1;
00337   } 
00338    
00339   //-- isInvalid ? - Check consistency in number of channels
00340   int ncx1 = h->GetXaxis()->GetNbins(); 
00341   int ncx2 = ref_->GetXaxis()->GetNbins();
00342   if ( ncx1 !=  ncx2)
00343   {
00344     if (verbose_>0) 
00345       std::cout << "QTest:Comp2RefKolmogorov"
00346                 << " different number of channels! ("
00347                 << ncx1 << ", " << ncx2 << "), exiting\n";
00348     return -1;
00349   } 
00350   //-- isInvalid ? - Check consistency in channel edges
00351   double diff1 = TMath::Abs(h->GetXaxis()->GetXmin() - ref_->GetXaxis()->GetXmin());
00352   double diff2 = TMath::Abs(h->GetXaxis()->GetXmax() - ref_->GetXaxis()->GetXmax());
00353   if (diff1 > difprec || diff2 > difprec)
00354   {
00355     if (verbose_>0) 
00356       std::cout << "QTest:Comp2RefKolmogorov"
00357                 << " histograms with different binning, exiting\n";
00358     return -1;
00359   }
00360 
00361   //--  QUALITY TEST itself 
00362   Bool_t afunc1 = kFALSE; Bool_t afunc2 = kFALSE;
00363   double sum1 = 0, sum2 = 0;
00364   double ew1, ew2, w1 = 0, w2 = 0;
00365   int bin;
00366   for (bin=1;bin<=ncx1;bin++)
00367   {
00368     sum1 += h->GetBinContent(bin);
00369     sum2 += ref_->GetBinContent(bin);
00370     ew1   = h->GetBinError(bin);
00371     ew2   = ref_->GetBinError(bin);
00372     w1   += ew1*ew1;
00373     w2   += ew2*ew2;
00374   }
00375   
00376   if (sum1 == 0)
00377   {
00378     if (verbose_>0) 
00379       std::cout << "QTest:Comp2RefKolmogorov"
00380                 << " Test Histogram: " << h->GetName() 
00381                 << ": integral is zero, exiting\n";
00382     return -1;
00383   }
00384   if (sum2 == 0)
00385   {
00386     if (verbose_>0) 
00387       std::cout << "QTest:Comp2RefKolmogorov"
00388                 << " Ref Histogram: " << ref_->GetName() 
00389                 << ": integral is zero, exiting\n";
00390     return -1;
00391   }
00392 
00393   double tsum1 = sum1; double tsum2 = sum2;
00394   tsum1 += h->GetBinContent(0);
00395   tsum2 += ref_->GetBinContent(0);
00396   tsum1 += h->GetBinContent(ncx1+1);
00397   tsum2 += ref_->GetBinContent(ncx1+1);
00398 
00399   // Check if histograms are weighted.
00400   // If number of entries = number of channels, probably histograms were
00401   // not filled via Fill(), but via SetBinContent()
00402   double ne1 = h->GetEntries();
00403   double ne2 = ref_->GetEntries();
00404   // look at first histogram
00405   double difsum1 = (ne1-tsum1)/tsum1;
00406   double esum1 = sum1;
00407   if (difsum1 > difprec && int(ne1) != ncx1)
00408   {
00409     if (h->GetSumw2N() == 0)
00410     {
00411       if (verbose_>0) 
00412         std::cout << "QTest:Comp2RefKolmogorov"
00413                   << " Weighted events and no Sumw2 for "
00414                   << h->GetName() << "\n";
00415     }
00416     else
00417     {
00418       esum1 = sum1*sum1/w1;  //number of equivalent entries
00419     }
00420   }
00421   // look at second histogram
00422   double difsum2 = (ne2-tsum2)/tsum2;
00423   double esum2   = sum2;
00424   if (difsum2 > difprec && int(ne2) != ncx1)
00425   {
00426     if (ref_->GetSumw2N() == 0)
00427     {
00428       if (verbose_>0) 
00429         std::cout << "QTest:Comp2RefKolmogorov"
00430                   << " Weighted events and no Sumw2 for "
00431                   << ref_->GetName() << "\n";
00432     }
00433     else
00434     {
00435       esum2 = sum2*sum2/w2;  //number of equivalent entries
00436     }
00437   }
00438 
00439   double s1 = 1/tsum1; double s2 = 1/tsum2;
00440   // Find largest difference for Kolmogorov Test
00441   double dfmax =0, rsum1 = 0, rsum2 = 0;
00442   // use underflow bin
00443   int first = 0; // 1
00444   // use overflow bin
00445   int last  = ncx1+1; // ncx1
00446   for ( bin=first; bin<=last; bin++)
00447   {
00448     rsum1 += s1*h->GetBinContent(bin);
00449     rsum2 += s2*ref_->GetBinContent(bin);
00450     dfmax = TMath::Max(dfmax,TMath::Abs(rsum1-rsum2));
00451   }
00452 
00453   // Get Kolmogorov probability
00454   double z = 0;
00455   if (afunc1)      z = dfmax*TMath::Sqrt(esum2);
00456   else if (afunc2) z = dfmax*TMath::Sqrt(esum1);
00457   else             z = dfmax*TMath::Sqrt(esum1*esum2/(esum1+esum2));
00458 
00459   // This numerical error condition should never occur:
00460   if (TMath::Abs(rsum1-1) > 0.002)
00461     if (verbose_>0) 
00462       std::cout << "QTest:Comp2RefKolmogorov" 
00463                 << " Numerical problems with histogram "
00464                 << h->GetName() << "\n";
00465   if (TMath::Abs(rsum2-1) > 0.002)
00466     if (verbose_>0) 
00467       std::cout << "QTest:Comp2RefKolmogorov" 
00468                 << " Numerical problems with histogram "
00469                 << ref_->GetName() << "\n";
00470 
00471   return TMath::KolmogorovProb(z);
00472 }
00473 
00474 //----------------------------------------------------//
00475 //--------------- ContentsXRange ---------------------//
00476 //----------------------------------------------------//
00477 float ContentsXRange::runTest(const MonitorElement*me)
00478 {
00479   badChannels_.clear();
00480 
00481   if (!me) 
00482     return -1;
00483   if (!me->getRootObject()) 
00484     return -1;
00485   TH1* h=0; 
00486 
00487   if (verbose_>1) 
00488     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00489               << me-> getFullname() << "\n";
00490   // -- TH1F
00491   if (me->kind()==MonitorElement::DQM_KIND_TH1F ) 
00492   {
00493     h = me->getTH1F();
00494   } 
00495   // -- TH1S
00496   else if ( me->kind()==MonitorElement::DQM_KIND_TH1S ) 
00497   {
00498     h = me->getTH1S();
00499   } 
00500   // -- TH1D
00501   else if ( me->kind()==MonitorElement::DQM_KIND_TH1D ) 
00502   {
00503     h = me->getTH1D();
00504   } 
00505   else 
00506   {
00507     if (verbose_>0) std::cout << "QTest:ContentsXRange"
00508          << " ME " << me->getFullname() 
00509          << " does not contain TH1F/TH1S/TH1D, exiting\n"; 
00510     return -1;
00511   } 
00512 
00513   if (!rangeInitialized_)
00514   {
00515     if ( h->GetXaxis() ) 
00516       setAllowedXRange(h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
00517     else 
00518       return -1;
00519   }
00520   int ncx = h->GetXaxis()->GetNbins();
00521   // use underflow bin
00522   int first = 0; // 1
00523   // use overflow bin
00524   int last  = ncx+1; // ncx
00525   // all entries
00526   double sum = 0;
00527   // entries outside X-range
00528   double fail = 0;
00529   int bin;
00530   for (bin = first; bin <= last; ++bin)
00531   {
00532     double contents = h->GetBinContent(bin);
00533     double x = h->GetBinCenter(bin);
00534     sum += contents;
00535     if (x < xmin_ || x > xmax_)fail += contents;
00536   }
00537 
00538   if (sum==0) return 1;
00539   // return fraction of entries within allowed X-range
00540   return (sum - fail)/sum; 
00541 
00542 }
00543 
00544 //-----------------------------------------------------//
00545 //--------------- ContentsYRange ---------------------//
00546 //----------------------------------------------------//
00547 float ContentsYRange::runTest(const MonitorElement*me)
00548 {
00549   badChannels_.clear();
00550 
00551   if (!me) 
00552     return -1;
00553   if (!me->getRootObject()) 
00554     return -1;
00555   TH1* h=0; 
00556 
00557   if (verbose_>1) 
00558     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00559               << me-> getFullname() << "\n";
00560 
00561   if (me->kind()==MonitorElement::DQM_KIND_TH1F) 
00562   { 
00563     h = me->getTH1F(); //access Test histo
00564   } 
00565   else if (me->kind()==MonitorElement::DQM_KIND_TH1S) 
00566   { 
00567     h = me->getTH1S(); //access Test histo
00568   } 
00569   else if (me->kind()==MonitorElement::DQM_KIND_TH1D) 
00570   { 
00571     h = me->getTH1D(); //access Test histo
00572   } 
00573   else 
00574   {
00575     if (verbose_>0) 
00576       std::cout << "QTest:ContentsYRange" 
00577                 << " ME " << me->getFullname() 
00578                 << " does not contain TH1F/TH1S/TH1D, exiting\n"; 
00579     return -1;
00580   } 
00581 
00582   if (!rangeInitialized_ || !h->GetXaxis()) return 1; // all bins are accepted if no initialization
00583   int ncx = h->GetXaxis()->GetNbins();
00584   // do NOT use underflow bin
00585   int first = 1;
00586   // do NOT use overflow bin
00587   int last  = ncx;
00588   // bins outside Y-range
00589   int fail = 0;
00590   int bin;
00591   
00592   if (useEmptyBins_)
00593   {
00594     for (bin = first; bin <= last; ++bin)
00595     {
00596       double contents = h->GetBinContent(bin);
00597       bool failure = false;
00598       failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
00599       if (failure) 
00600       { 
00601         DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
00602         badChannels_.push_back(chan);
00603         ++fail;
00604       }
00605     }
00606     // return fraction of bins that passed test
00607     return 1.*(ncx - fail)/ncx;
00608   }
00609   else 
00610   {
00611     for (bin = first; bin <= last; ++bin)
00612     {
00613       double contents = h->GetBinContent(bin);
00614       bool failure = false;
00615       if (contents) failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
00616       if (failure) ++fail;
00617     }
00618     // return fraction of bins that passed test
00619     return 1.*(ncx - fail)/ncx;
00620   } 
00621 }
00622 
00623 //-----------------------------------------------------//
00624 //------------------ DeadChannel ---------------------//
00625 //----------------------------------------------------//
00626 float DeadChannel::runTest(const MonitorElement*me)
00627 {
00628   badChannels_.clear();
00629   if (!me) 
00630     return -1;
00631   if (!me->getRootObject()) 
00632     return -1;
00633   TH1* h1=0;
00634   TH2* h2=0;//initialize histogram pointers
00635 
00636   if (verbose_>1) 
00637     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00638               << me-> getFullname() << "\n";
00639   //TH1F
00640   if (me->kind()==MonitorElement::DQM_KIND_TH1F) 
00641   { 
00642     h1 = me->getTH1F(); //access Test histo
00643   } 
00644   //TH1S
00645   else if (me->kind()==MonitorElement::DQM_KIND_TH1S) 
00646   { 
00647     h1 = me->getTH1S(); //access Test histo
00648   } 
00649   //TH1D
00650   else if (me->kind()==MonitorElement::DQM_KIND_TH1D) 
00651   { 
00652     h1 = me->getTH1D(); //access Test histo
00653   } 
00654   //-- TH2F
00655   else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
00656   { 
00657     h2  = me->getTH2F(); // access Test histo
00658   } 
00659   //-- TH2S
00660   else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
00661   { 
00662     h2  = me->getTH2S(); // access Test histo
00663   } 
00664   //-- TH2D
00665   else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
00666   { 
00667     h2  = me->getTH2D(); // access Test histo
00668   } 
00669   else 
00670   {
00671     if (verbose_>0) 
00672       std::cout << "QTest:DeadChannel"
00673          << " ME " << me->getFullname() 
00674          << " does not contain TH1F/TH1S/TH1D/TH2F/TH2S/TH2D, exiting\n"; 
00675     return -1;
00676   } 
00677 
00678   int fail = 0; // number of failed channels
00679 
00680   //--------- do the quality test for 1D histo ---------------//
00681   if (h1 != NULL)  
00682   {
00683     if (!rangeInitialized_ || !h1->GetXaxis() ) 
00684       return 1; // all bins are accepted if no initialization
00685     int ncx = h1->GetXaxis()->GetNbins();
00686     int first = 1;
00687     int last  = ncx;
00688     int bin;
00689 
00691     for (bin = first; bin <= last; ++bin)
00692     {
00693       double contents = h1->GetBinContent(bin);
00694       bool failure = false;
00695       failure = contents <= ymin_; // dead channel: equal to or less than ymin_
00696       if (failure)
00697       { 
00698         DQMChannel chan(bin, 0, 0, contents, h1->GetBinError(bin));
00699         badChannels_.push_back(chan);
00700         ++fail;
00701       }
00702     }
00703     //return fraction of alive channels
00704     return 1.*(ncx - fail)/ncx;
00705   }
00706   //----------------------------------------------------------//
00707  
00708   //--------- do the quality test for 2D -------------------//
00709   else if (h2 !=NULL )
00710   {
00711     int ncx = h2->GetXaxis()->GetNbins(); // get X bins
00712     int ncy = h2->GetYaxis()->GetNbins(); // get Y bins
00713 
00715     for (int cx = 1; cx <= ncx; ++cx)
00716     {
00717       for (int cy = 1; cy <= ncy; ++cy)
00718       {
00719         double contents = h2->GetBinContent(h2->GetBin(cx, cy));
00720         bool failure = false;
00721         failure = contents <= ymin_; // dead channel: equal to or less than ymin_
00722         if (failure)
00723         { 
00724           DQMChannel chan(cx, cy, 0, contents, h2->GetBinError(h2->GetBin(cx, cy)));
00725           badChannels_.push_back(chan);
00726           ++fail;
00727         }
00728       }
00729     }
00730     //return fraction of alive channels
00731     return 1.*(ncx*ncy - fail) / (ncx*ncy);
00732   }
00733   else 
00734   {
00735     if (verbose_>0) 
00736       std::cout << "QTest:DeadChannel"
00737                 << " TH1/TH2F are NULL, exiting\n"; 
00738     return -1;
00739   }
00740 }
00741 
00742 //-----------------------------------------------------//
00743 //----------------  NoisyChannel ---------------------//
00744 //----------------------------------------------------//
00745 // run the test (result: fraction of channels not appearing noisy or "hot")
00746 // [0, 1] or <0 for failure
00747 float NoisyChannel::runTest(const MonitorElement *me)
00748 {
00749   badChannels_.clear();
00750   if (!me) 
00751     return -1;
00752   if (!me->getRootObject()) 
00753     return -1; 
00754   TH1* h=0;//initialize histogram pointer
00755 
00756   if (verbose_>1) 
00757     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00758               << me-> getFullname() << "\n";
00759 
00760   int nbins=0;
00761   //-- TH1F
00762   if (me->kind()==MonitorElement::DQM_KIND_TH1F)
00763   { 
00764     nbins = me->getTH1F()->GetXaxis()->GetNbins(); 
00765     h  = me->getTH1F(); // access Test histo
00766   } 
00767   //-- TH1S
00768   else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
00769   { 
00770     nbins = me->getTH1S()->GetXaxis()->GetNbins(); 
00771     h  = me->getTH1S(); // access Test histo
00772   } 
00773   //-- TH1D
00774   else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
00775   { 
00776     nbins = me->getTH1D()->GetXaxis()->GetNbins(); 
00777     h  = me->getTH1D(); // access Test histo
00778   } 
00779   //-- TH2
00780   else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
00781   { 
00782     nbins = me->getTH2F()->GetXaxis()->GetNbins() *
00783             me->getTH2F()->GetYaxis()->GetNbins();
00784     h  = me->getTH2F(); // access Test histo
00785   } 
00786   //-- TH2
00787   else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
00788   { 
00789     nbins = me->getTH2S()->GetXaxis()->GetNbins() *
00790             me->getTH2S()->GetYaxis()->GetNbins();
00791     h  = me->getTH2S(); // access Test histo
00792   } 
00793   //-- TH2
00794   else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
00795   { 
00796     nbins = me->getTH2D()->GetXaxis()->GetNbins() *
00797             me->getTH2D()->GetYaxis()->GetNbins();
00798     h  = me->getTH2D(); // access Test histo
00799   } 
00800   else 
00801   {  
00802     if (verbose_>0) 
00803       std::cout << "QTest:NoisyChannel"
00804         << " ME " << me->getFullname() 
00805         << " does not contain TH1F/TH1S/TH1D or TH2F/TH2S/TH2D, exiting\n"; 
00806     return -1;
00807   }
00808 
00809   //--  QUALITY TEST itself 
00810 
00811   if ( !rangeInitialized_ || !h->GetXaxis() ) 
00812     return 1; // all channels are accepted if tolerance has not been set
00813 
00814   // do NOT use underflow bin
00815   int first = 1;
00816   // do NOT use overflow bin
00817   int last  = nbins;
00818   // bins outside Y-range
00819   int fail = 0;
00820   int bin;
00821   for (bin = first; bin <= last; ++bin)
00822   {
00823     double contents = h->GetBinContent(bin);
00824     double average = getAverage(bin, h);
00825     bool failure = false;
00826     if (average != 0)
00827        failure = (((contents-average)/TMath::Abs(average)) > tolerance_);
00828 
00829     if (failure)
00830     {
00831       ++fail;
00832       DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
00833       badChannels_.push_back(chan);
00834     }
00835   }
00836 
00837   // return fraction of bins that passed test
00838   return 1.*(nbins - fail)/nbins;
00839 }
00840 
00841 // get average for bin under consideration
00842 // (see description of method setNumNeighbors)
00843 double NoisyChannel::getAverage(int bin, const TH1 *h) const
00844 {
00846   int first = 1;
00848   int ncx  = h->GetXaxis()->GetNbins();
00849   double sum = 0; int bin_low, bin_hi;
00850   for (unsigned i = 1; i <= numNeighbors_; ++i)
00851   {
00853     bin_low = bin-i;  bin_hi = bin+i;
00856     while (bin_low < first) // shift bin by +ncx
00857       bin_low = ncx + bin_low;
00858     while (bin_hi > ncx) // shift bin by -ncx
00859       bin_hi = bin_hi - ncx;
00860       sum += h->GetBinContent(bin_low) + h->GetBinContent(bin_hi);
00861   }
00863   return sum/(numNeighbors_ * 2);
00864 }
00865 
00866 
00867 //-----------------------------------------------------------//
00868 //----------------  ContentsWithinExpected ---------------------//
00869 //-----------------------------------------------------------//
00870 // run the test (result: fraction of channels that passed test);
00871 // [0, 1] or <0 for failure
00872 float ContentsWithinExpected::runTest(const MonitorElement*me)
00873 {
00874   badChannels_.clear();
00875   if (!me) 
00876     return -1;
00877   if (!me->getRootObject()) 
00878     return -1;
00879   TH1* h=0; //initialize histogram pointer
00880 
00881   if (verbose_>1) 
00882     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
00883               << me-> getFullname() << "\n";
00884 
00885   int ncx;
00886   int ncy;
00887 
00888   if (useEmptyBins_)
00889   {
00890     //-- TH2
00891     if (me->kind()==MonitorElement::DQM_KIND_TH2F)
00892     {
00893       ncx = me->getTH2F()->GetXaxis()->GetNbins();
00894       ncy = me->getTH2F()->GetYaxis()->GetNbins(); 
00895       h  = me->getTH2F(); // access Test histo
00896     }
00897     //-- TH2S
00898     else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
00899     {
00900       ncx = me->getTH2S()->GetXaxis()->GetNbins();
00901       ncy = me->getTH2S()->GetYaxis()->GetNbins(); 
00902       h  = me->getTH2S(); // access Test histo
00903     }
00904     //-- TH2D
00905     else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
00906     {
00907       ncx = me->getTH2D()->GetXaxis()->GetNbins();
00908       ncy = me->getTH2D()->GetYaxis()->GetNbins(); 
00909       h  = me->getTH2D(); // access Test histo
00910     }
00911     //-- TProfile
00912     else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
00913     {
00914       ncx = me->getTProfile()->GetXaxis()->GetNbins();
00915       ncy = 1;
00916       h  = me->getTProfile(); // access Test histo
00917     }
00918     //-- TProfile2D
00919     else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE2D)
00920     {
00921       ncx = me->getTProfile2D()->GetXaxis()->GetNbins();
00922       ncy = me->getTProfile2D()->GetYaxis()->GetNbins();
00923       h  = me->getTProfile2D(); // access Test histo
00924     }
00925     else
00926     {
00927       if (verbose_>0) 
00928         std::cout << "QTest:ContentsWithinExpected" 
00929          << " ME does not contain TH2F/TH2S/TH2D/TPROFILE/TPROFILE2D, exiting\n"; 
00930       return -1;
00931     } 
00932 
00933     int nsum = 0;
00934     double sum = 0.0;
00935     double average = 0.0;
00936 
00937     if (checkMeanTolerance_)
00938     { // calculate average value of all bin contents
00939 
00940       for (int cx = 1; cx <= ncx; ++cx)
00941       {
00942         for (int cy = 1; cy <= ncy; ++cy)
00943         {
00944           if (me->kind() == MonitorElement::DQM_KIND_TH2F)
00945           {
00946             sum += h->GetBinContent(h->GetBin(cx, cy));
00947             ++nsum;
00948           }
00949           else if (me->kind() == MonitorElement::DQM_KIND_TH2S)
00950           {
00951             sum += h->GetBinContent(h->GetBin(cx, cy));
00952             ++nsum;
00953           }
00954           else if (me->kind() == MonitorElement::DQM_KIND_TH2D)
00955           {
00956             sum += h->GetBinContent(h->GetBin(cx, cy));
00957             ++nsum;
00958           }
00959           else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE)
00960           {
00961             if (me->getTProfile()->GetBinEntries(h->GetBin(cx)) >= minEntries_/(ncx))
00962             {
00963               sum += h->GetBinContent(h->GetBin(cx));
00964               ++nsum;
00965             }
00966           }
00967           else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D)
00968           {
00969             if (me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) >= minEntries_/(ncx*ncy))
00970             {
00971               sum += h->GetBinContent(h->GetBin(cx, cy));
00972               ++nsum;
00973             }
00974           }
00975         }
00976       }
00977 
00978       if (nsum > 0) 
00979         average = sum/nsum;
00980 
00981     } // calculate average value of all bin contents
00982 
00983     int fail = 0;
00984 
00985     for (int cx = 1; cx <= ncx; ++cx)
00986     {
00987       for (int cy = 1; cy <= ncy; ++cy)
00988       {
00989         bool failMean = false;
00990         bool failRMS = false;
00991         bool failMeanTolerance = false;
00992 
00993         if (me->kind() == MonitorElement::DQM_KIND_TPROFILE && 
00994             me->getTProfile()->GetBinEntries(h->GetBin(cx)) < minEntries_/(ncx))
00995           continue;
00996 
00997         if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D && 
00998             me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) < minEntries_/(ncx*ncy)) 
00999           continue;
01000 
01001         if (checkMean_)
01002         {
01003           double mean = h->GetBinContent(h->GetBin(cx, cy));
01004           failMean = (mean < minMean_ || mean > maxMean_);
01005         }
01006 
01007         if (checkRMS_)
01008         {
01009           double rms = h->GetBinError(h->GetBin(cx, cy));
01010           failRMS = (rms < minRMS_ || rms > maxRMS_);
01011         }
01012 
01013         if (checkMeanTolerance_)
01014         {
01015           double mean = h->GetBinContent(h->GetBin(cx, cy));
01016           failMeanTolerance = (TMath::Abs(mean - average) > toleranceMean_*TMath::Abs(average));
01017         }
01018 
01019         if (failMean || failRMS || failMeanTolerance)
01020         {
01021 
01022           if (me->kind() == MonitorElement::DQM_KIND_TH2F) 
01023           {
01024             DQMChannel chan(cx, cy, 0,
01025                             h->GetBinContent(h->GetBin(cx, cy)),
01026                             h->GetBinError(h->GetBin(cx, cy)));
01027             badChannels_.push_back(chan);
01028           }
01029           else if (me->kind() == MonitorElement::DQM_KIND_TH2S) 
01030           {
01031             DQMChannel chan(cx, cy, 0,
01032                             h->GetBinContent(h->GetBin(cx, cy)),
01033                             h->GetBinError(h->GetBin(cx, cy)));
01034             badChannels_.push_back(chan);
01035           }
01036           else if (me->kind() == MonitorElement::DQM_KIND_TH2D) 
01037           {
01038             DQMChannel chan(cx, cy, 0,
01039                             h->GetBinContent(h->GetBin(cx, cy)),
01040                             h->GetBinError(h->GetBin(cx, cy)));
01041             badChannels_.push_back(chan);
01042           }
01043           else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE) 
01044           {
01045             DQMChannel chan(cx, cy, int(me->getTProfile()->GetBinEntries(h->GetBin(cx))),
01046                             0,
01047                             h->GetBinError(h->GetBin(cx)));
01048             badChannels_.push_back(chan);
01049           }
01050           else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D) 
01051           {
01052             DQMChannel chan(cx, cy, int(me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy))),
01053                             h->GetBinContent(h->GetBin(cx, cy)),
01054                             h->GetBinError(h->GetBin(cx, cy)));
01055             badChannels_.push_back(chan);
01056           }
01057           ++fail;
01058         }
01059       }
01060     }
01061     return 1.*(ncx*ncy - fail)/(ncx*ncy);
01062   } 
01063 
01064   else     
01065   {
01066     if (me->kind()==MonitorElement::DQM_KIND_TH2F)
01067     {
01068       ncx = me->getTH2F()->GetXaxis()->GetNbins();
01069       ncy = me->getTH2F()->GetYaxis()->GetNbins();
01070       h  = me->getTH2F(); // access Test histo
01071     }
01072     else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
01073     {
01074       ncx = me->getTH2S()->GetXaxis()->GetNbins();
01075       ncy = me->getTH2S()->GetYaxis()->GetNbins();
01076       h  = me->getTH2S(); // access Test histo
01077     }
01078     else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
01079     {
01080       ncx = me->getTH2D()->GetXaxis()->GetNbins();
01081       ncy = me->getTH2D()->GetYaxis()->GetNbins();
01082       h  = me->getTH2D(); // access Test histo
01083     }
01084     else 
01085     {
01086       if (verbose_>0) 
01087         std::cout << "QTest:ContentsWithinExpected AS" 
01088                   << " ME does not contain TH2F/TH2S/TH2D, exiting\n"; 
01089       return -1;
01090     } 
01091 
01092     // if (!rangeInitialized_) return 0; // all accepted if no initialization
01093     int fail = 0;
01094     for (int cx = 1; cx <= ncx; ++cx)
01095     {
01096       for (int cy = 1; cy <= ncy; ++cy)
01097       {
01098         bool failure = false;
01099         double Content = h->GetBinContent(h->GetBin(cx, cy));
01100         if (Content) 
01101           failure = (Content <  minMean_ || Content >  maxMean_);
01102         if (failure) 
01103           ++fail;
01104       }
01105     }
01106     return 1.*(ncx*ncy-fail)/(ncx*ncy);
01107   } 
01108 
01109 }
01111 void ContentsWithinExpected::setMeanRange(double xmin, double xmax)
01112 {
01113   if (xmax < xmin)
01114     if (verbose_>0) 
01115       std::cout << "QTest:ContentsWitinExpected" 
01116                 << " Illogical range: (" << xmin << ", " << xmax << "\n";
01117   minMean_ = xmin;
01118   maxMean_ = xmax;
01119   checkMean_ = true;
01120 }
01121 
01123 void ContentsWithinExpected::setRMSRange(double xmin, double xmax)
01124 {
01125   if (xmax < xmin)
01126     if (verbose_>0) 
01127       std::cout << "QTest:ContentsWitinExpected" 
01128                 << " Illogical range: (" << xmin << ", " << xmax << "\n";
01129   minRMS_ = xmin;
01130   maxRMS_ = xmax;
01131   checkRMS_ = true;
01132 }
01133 
01134 //----------------------------------------------------------------//
01135 //--------------------  MeanWithinExpected  ---------------------//
01136 //---------------------------------------------------------------//
01137 // run the test;
01138 //   (a) if useRange is called: 1 if mean within allowed range, 0 otherwise
01139 //   (b) is useRMS or useSigma is called: result is the probability
01140 //   Prob(chi^2, ndof=1) that the mean of histogram will be deviated by more than
01141 //   +/- delta from <expected_mean>, where delta = mean - <expected_mean>, and
01142 //   chi^2 = (delta/sigma)^2. sigma is the RMS of the histogram ("useRMS") or
01143 //   <expected_sigma> ("useSigma")
01144 //   e.g. for delta = 1, Prob = 31.7%
01145 //  for delta = 2, Prob = 4.55%
01146 //   (returns result in [0, 1] or <0 for failure) 
01147 float MeanWithinExpected::runTest(const MonitorElement *me )
01148 {
01149   if (!me) 
01150     return -1;
01151   if (!me->getRootObject()) 
01152     return -1;
01153   TH1* h=0;
01154    
01155   if (verbose_>1) 
01156     std::cout << "QTest:" << getAlgoName() << "::runTest called on " 
01157               << me-> getFullname() << "\n";
01158 
01159   if (minEntries_ != 0 && me->getEntries() < minEntries_) return -1;
01160 
01161   if (me->kind()==MonitorElement::DQM_KIND_TH1F) 
01162   { 
01163     h = me->getTH1F(); //access Test histo
01164   }
01165   else if (me->kind()==MonitorElement::DQM_KIND_TH1S) 
01166   { 
01167     h = me->getTH1S(); //access Test histo
01168   }
01169   else if (me->kind()==MonitorElement::DQM_KIND_TH1D) 
01170   { 
01171     h = me->getTH1D(); //access Test histo
01172   }
01173   else {
01174     if (verbose_>0) 
01175       std::cout << "QTest:MeanWithinExpected"
01176                 << " ME " << me->getFullname() 
01177                 << " does not contain TH1F/TH1S/TH1D, exiting\n"; 
01178     return -1;
01179   } 
01180  
01181   
01182   if (useRange_) {
01183     double mean = h->GetMean();
01184     if (mean <= xmax_ && mean >= xmin_) 
01185       return 1;
01186     else
01187       return 0;
01188   }
01189   else if (useSigma_) 
01190   {
01191     if (sigma_ != 0.) 
01192     {
01193       double chi = (h->GetMean() - expMean_)/sigma_;
01194       return TMath::Prob(chi*chi, 1);
01195     }
01196     else
01197     {
01198       if (verbose_>0) 
01199         std::cout << "QTest:MeanWithinExpected"
01200                   << " Error, sigma_ is zero, exiting\n";
01201       return 0;
01202     }
01203   }
01204   else if (useRMS_) 
01205   {
01206     if (h->GetRMS() != 0.) 
01207     {
01208       double chi = (h->GetMean() - expMean_)/h->GetRMS();
01209       return TMath::Prob(chi*chi, 1);
01210     }
01211     else
01212     {
01213       if (verbose_>0) 
01214         std::cout << "QTest:MeanWithinExpected"
01215                   << " Error, RMS is zero, exiting\n";
01216       return 0;
01217     }
01218   }
01219   else 
01220     if (verbose_>0) 
01221       std::cout << "QTest:MeanWithinExpected"
01222                 << " Error, neither Range, nor Sigma, nor RMS, exiting\n";
01223     return -1; 
01224 }
01225 
01226 void MeanWithinExpected::useRange(double xmin, double xmax)
01227 {
01228     useRange_ = true;
01229     useSigma_ = useRMS_ = false;
01230     xmin_ = xmin; xmax_ = xmax;
01231     if (xmin_ > xmax_)  
01232       if (verbose_>0) 
01233         std::cout << "QTest:MeanWithinExpected"
01234                   << " Illogical range: (" << xmin_ << ", " << xmax_ << "\n";
01235 }
01236 void MeanWithinExpected::useSigma(double expectedSigma)
01237 {
01238   useSigma_ = true;
01239   useRMS_ = useRange_ = false;
01240   sigma_ = expectedSigma;
01241   if (sigma_ == 0) 
01242     if (verbose_>0) 
01243       std::cout << "QTest:MeanWithinExpected"
01244                 << " Expected sigma = " << sigma_ << "\n";
01245 }
01246 
01247 void MeanWithinExpected::useRMS()
01248 {
01249   useRMS_ = true;
01250   useSigma_ = useRange_ = false;
01251 }
01252 
01253 //----------------------------------------------------------------//
01254 //------------------------  CompareToMedian  ---------------------------//
01255 //----------------------------------------------------------------//
01256 /* 
01257 Test for TProfile2D
01258 For each x bin, the median value is calculated and then each value is compared with the median.
01259 This procedure is repeated for each x-bin of the 2D profile
01260 The parameters used for this comparison are:
01261 MinRel and MaxRel to identify outliers wrt the median value
01262 An absolute value (MinAbs, MaxAbs) on the median is used to identify a full region out of specification 
01263 */
01264 float CompareToMedian::runTest(const MonitorElement *me){
01265   int32_t nbins=0, failed=0;
01266   badChannels_.clear();
01267 
01268   if (!me)
01269     return -1;
01270   if (!me->getRootObject())
01271     return -1;
01272   TH1* h=0;
01273 
01274   if (verbose_>1){
01275     std::cout << "QTest:" << getAlgoName() << "::runTest called on "
01276               << me-> getFullname() << "\n";
01277     std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
01278     std::cout << "\tMinMedian = " << _minMed << "; MaxMedian = " << _maxMed << "\n";
01279     std::cout << "\tUseEmptyBins = " << (_emptyBins?"Yes":"No" )<< "\n";
01280   }
01281 
01282   if (me->kind()==MonitorElement::DQM_KIND_TPROFILE2D)
01283     {
01284       h  = me->getTProfile2D(); // access Test histo
01285     }
01286   else
01287     {
01288       if (verbose_>0) 
01289         std::cout << "QTest:ContentsWithinExpected" 
01290          << " ME does not contain TPROFILE2D, exiting\n"; 
01291       return -1;
01292     }
01293   
01294   nBinsX = h->GetNbinsX();
01295   nBinsY = h->GetNbinsY();
01296   int entries = 0;
01297   float median = 0.0;
01298 
01299   //Median calculated with partially sorted vector
01300   for (int binX = 1; binX <= nBinsX; binX++ ){
01301     reset();
01302     // Fill vector
01303     for (int binY = 1; binY <= nBinsY; binY++){
01304       int bin = h->GetBin(binX, binY);
01305       double content = (double)h->GetBinContent(bin);
01306       if ( content == 0 && !_emptyBins)
01307         continue;
01308       binValues.push_back(content);
01309       entries = me->getTProfile2D()->GetBinEntries(bin);
01310     }
01311     if (binValues.empty())
01312       continue;
01313     nbins+=binValues.size();
01314 
01315     //calculate median
01316     if(binValues.size()>0){
01317       int medPos = (int)binValues.size()/2;
01318       nth_element(binValues.begin(),binValues.begin()+medPos,binValues.end());
01319       median = *(binValues.begin()+medPos);
01320     }
01321 
01322     // if median == 0, use the absolute cut
01323     if(median == 0){
01324       if (verbose_ > 0){
01325         std::cout << "QTest: Median is 0; the fixed cuts: [" << _minMed << "; " << _maxMed << "]  are used\n";
01326       }
01327       for(int  binY = 1; binY <= nBinsY; binY++){
01328         int bin = h->GetBin(binX, binY);
01329         double content = (double)h->GetBinContent(bin);
01330         entries = me->getTProfile2D()->GetBinEntries(bin);
01331         if ( entries == 0 )
01332           continue;
01333         if (content > _maxMed || content < _minMed){ 
01334             DQMChannel chan(binX,binY, 0, content, h->GetBinError(bin));
01335             badChannels_.push_back(chan);
01336             failed++;
01337         }
01338       }
01339       continue;
01340     }
01341 
01342     //Cut on stat: will mask rings with no enought of statistics
01343     if (median*entries < _statCut )
01344       continue;
01345      
01346     // If median is off the absolute cuts, declare everything bad (if bin has non zero entries)
01347     if(median > _maxMed || median < _minMed){
01348       for(int  binY = 1; binY <= nBinsY; binY++){
01349         int bin = h->GetBin(binX, binY);
01350         double content = (double)h->GetBinContent(bin);
01351         entries = me->getTProfile2D()->GetBinEntries(bin);
01352          if ( entries == 0 )
01353           continue;
01354          DQMChannel chan(binX,binY, 0, content/median, h->GetBinError(bin));
01355          badChannels_.push_back(chan);
01356          failed++;
01357       }
01358       continue;
01359     }
01360 
01361     // Test itself  
01362     float minCut = median*_min;
01363     float maxCut = median*_max;
01364     for(int  binY = 1; binY <= nBinsY; binY++){
01365         int bin = h->GetBin(binX, binY);
01366         double content = (double)h->GetBinContent(bin);
01367         entries = me->getTProfile2D()->GetBinEntries(bin);
01368         if ( entries == 0 )
01369           continue;
01370         if (content > maxCut || content < minCut){
01371           DQMChannel chan(binX,binY, 0, content/median, h->GetBinError(bin));
01372           badChannels_.push_back(chan);
01373           failed++;
01374         }
01375     }
01376   }
01377 
01378   if (nbins==0){
01379     if (verbose_ > 0)
01380       std::cout << "QTest:CompareToMedian: Histogram is empty" << std::endl;
01381     return 1.;
01382     }
01383   return 1 - (float)failed/nbins;
01384 }
01385 //----------------------------------------------------------------//
01386 //------------------------  CompareLastFilledBin -----------------//
01387 //----------------------------------------------------------------//
01388 /* 
01389 Test for TH1F and TH2F
01390 For the last filled bin the value is compared with specified upper and lower limits. If 
01391 it is outside the limit the test failed test result is returned
01392 The parameters used for this comparison are:
01393 MinRel and MaxRel to check identify outliers wrt the median value
01394 */
01395 float CompareLastFilledBin::runTest(const MonitorElement *me){
01396   if (!me)
01397     return -1;
01398   if (!me->getRootObject())
01399     return -1;
01400   TH1* h1=0;
01401   TH2* h2=0;
01402   if (verbose_>1){
01403     std::cout << "QTest:" << getAlgoName() << "::runTest called on "
01404               << me-> getFullname() << "\n";
01405     std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
01406   }
01407   if (me->kind()==MonitorElement::DQM_KIND_TH1F)
01408     {
01409       h1  = me->getTH1F(); // access Test histo
01410     }
01411   else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
01412     {
01413       h2  = me->getTH2F(); // access Test histo
01414     }
01415   else
01416     {
01417       if (verbose_>0) 
01418         std::cout << "QTest:ContentsWithinExpected" 
01419          << " ME does not contain TH1F or TH2F, exiting\n"; 
01420       return -1;
01421     }
01422   int lastBinX = 0;
01423   int lastBinY = 0;
01424   float lastBinVal; 
01425 
01426   //--------- do the quality test for 1D histo ---------------// 
01427   if (h1 != NULL) 
01428   { 
01429     lastBinX = h1->FindLastBinAbove(_average,1);
01430     lastBinVal = h1->GetBinContent(lastBinX);
01431     if (h1->GetEntries() == 0 || lastBinVal < 0) return 1;
01432   } 
01433   else if (h2 != NULL) 
01434   {   
01435     
01436     lastBinX = h2->FindLastBinAbove(_average,1);
01437     lastBinY = h2->FindLastBinAbove(_average,2);
01438     if ( h2->GetEntries() == 0 || lastBinX < 0 || lastBinY < 0 )  return 1;
01439     lastBinVal = h2->GetBinContent(h2->GetBin(lastBinX,lastBinY));
01440   } else {
01441     if (verbose_ > 0) std::cout << "QTest:"<< getAlgoName() << " Histogram does not exist" << std::endl;
01442     return 1;
01443   } 
01444   if (verbose_ > 0) std::cout << "Min and Max values " << _min << " " << _max << " Av value " << _average << " lastBinX " << lastBinX<<  " lastBinY " << lastBinY <<  " lastBinVal " << lastBinVal << std::endl;
01445   if (lastBinVal > _min && lastBinVal <= _max)
01446     return 1;
01447   else
01448     return 0;
01449 }