CMS 3D CMS Logo

QTest.cc
Go to the documentation of this file.
5 #include "TMath.h"
6 #include <iostream>
7 #include <sstream>
8 #include <math.h>
9 
10 using namespace std;
11 
12 const float QCriterion::ERROR_PROB_THRESHOLD = 0.50;
13 const float QCriterion::WARNING_PROB_THRESHOLD = 0.90;
14 
15 // initialize values
16 void
18 {
19  errorProb_ = ERROR_PROB_THRESHOLD;
20  warningProb_ = WARNING_PROB_THRESHOLD;
21  setAlgoName("NO_ALGORITHM");
22  status_ = dqm::qstatus::DID_NOT_RUN;
23  message_ = "NO_MESSAGE";
24  verbose_ = 0; // 0 = silent, 1 = algorithmic failures, 2 = info
25 }
26 
27 float QCriterion::runTest(const MonitorElement * /* me */)
28 {
29  raiseDQMError("QCriterion", "virtual runTest method called" );
30  return 0.;
31 }
32 //===================================================//
33 //================ QUALITY TESTS ====================//
34 //==================================================//
35 
36 //-------------------------------------------------------//
37 //----------------- Comp2RefEqualH base -----------------//
38 //-------------------------------------------------------//
39 // run the test (result: [0, 1] or <0 for failure)
41 {
42  badChannels_.clear();
43 
44  if (!me)
45  return -1;
46  if (!me->getRootObject() || !me->getRefRootObject())
47  return -1;
48  TH1* h=0; //initialize histogram pointer
49  TH1* ref_=0;
50 
51  if (verbose_>1)
52  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
53  << me-> getFullname() << "\n";
54 
55  int nbins=0;
56  int nbinsref=0;
57  //-- TH1F
59  {
60  nbins = me->getTH1F()->GetXaxis()->GetNbins();
61  nbinsref = me->getRefTH1F()->GetXaxis()->GetNbins();
62  h = me->getTH1F(); // access Test histo
63  ref_ = me->getRefTH1F(); //access Ref hiso
64  if (nbins != nbinsref) return -1;
65  }
66  //-- TH1S
67  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
68  {
69  nbins = me->getTH1S()->GetXaxis()->GetNbins();
70  nbinsref = me->getRefTH1S()->GetXaxis()->GetNbins();
71  h = me->getTH1S(); // access Test histo
72  ref_ = me->getRefTH1S(); //access Ref hiso
73  if (nbins != nbinsref) return -1;
74  }
75  //-- TH1D
76  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
77  {
78  nbins = me->getTH1D()->GetXaxis()->GetNbins();
79  nbinsref = me->getRefTH1D()->GetXaxis()->GetNbins();
80  h = me->getTH1D(); // access Test histo
81  ref_ = me->getRefTH1D(); //access Ref hiso
82  if (nbins != nbinsref) return -1;
83  }
84  //-- TH2
85  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
86  {
87  nbins = me->getTH2F()->GetXaxis()->GetNbins() *
88  me->getTH2F()->GetYaxis()->GetNbins();
89  nbinsref = me->getRefTH2F()->GetXaxis()->GetNbins() *
90  me->getRefTH2F()->GetYaxis()->GetNbins();
91  h = me->getTH2F(); // access Test histo
92  ref_ = me->getRefTH2F(); //access Ref hiso
93  if (nbins != nbinsref) return -1;
94  }
95 
96  //-- TH2
97  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
98  {
99  nbins = me->getTH2S()->GetXaxis()->GetNbins() *
100  me->getTH2S()->GetYaxis()->GetNbins();
101  nbinsref = me->getRefTH2S()->GetXaxis()->GetNbins() *
102  me->getRefTH2S()->GetYaxis()->GetNbins();
103  h = me->getTH2S(); // access Test histo
104  ref_ = me->getRefTH2S(); //access Ref hiso
105  if (nbins != nbinsref) return -1;
106  }
107 
108  //-- TH2
109  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
110  {
111  nbins = me->getTH2D()->GetXaxis()->GetNbins() *
112  me->getTH2D()->GetYaxis()->GetNbins();
113  nbinsref = me->getRefTH2D()->GetXaxis()->GetNbins() *
114  me->getRefTH2D()->GetYaxis()->GetNbins();
115  h = me->getTH2D(); // access Test histo
116  ref_ = me->getRefTH2D(); //access Ref hiso
117  if (nbins != nbinsref) return -1;
118  }
119 
120  //-- TH3
121  else if (me->kind()==MonitorElement::DQM_KIND_TH3F)
122  {
123  nbins = me->getTH3F()->GetXaxis()->GetNbins() *
124  me->getTH3F()->GetYaxis()->GetNbins() *
125  me->getTH3F()->GetZaxis()->GetNbins();
126  nbinsref = me->getRefTH3F()->GetXaxis()->GetNbins() *
127  me->getRefTH3F()->GetYaxis()->GetNbins() *
128  me->getRefTH3F()->GetZaxis()->GetNbins();
129  h = me->getTH3F(); // access Test histo
130  ref_ = me->getRefTH3F(); //access Ref hiso
131  if (nbins != nbinsref) return -1;
132  }
133 
134  else
135  {
136  if (verbose_>0)
137  std::cout << "QTest:Comp2RefEqualH"
138  << " ME does not contain TH1F/TH1S/TH1D/TH2F/TH2S/TH2D/TH3F, exiting\n";
139  return -1;
140  }
141 
142  //-- QUALITY TEST itself
143  int first = 0; // 1 //(use underflow bin)
144  int last = nbins+1; //(use overflow bin)
145  bool failure = false;
146  for (int bin=first;bin<=last;bin++)
147  {
148  double contents = h->GetBinContent(bin);
149  if (contents != ref_->GetBinContent(bin))
150  {
151  failure = true;
152  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
153  badChannels_.push_back(chan);
154  }
155  }
156  if (failure) return 0;
157  return 1;
158 }
159 
160 //-------------------------------------------------------//
161 //----------------- Comp2RefChi2 --------------------//
162 //-------------------------------------------------------//
164 {
165  if (!me)
166  return -1;
167  if (!me->getRootObject() || !me->getRefRootObject())
168  return -1;
169  TH1* h=0;
170  TH1* ref_=0;
171 
172  if (verbose_>1)
173  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
174  << me-> getFullname() << "\n";
175  //-- TH1F
177  {
178  h = me->getTH1F(); // access Test histo
179  ref_ = me->getRefTH1F(); //access Ref histo
180  }
181  //-- TH1S
182  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
183  {
184  h = me->getTH1S(); // access Test histo
185  ref_ = me->getRefTH1S(); //access Ref histo
186  }
187  //-- TH1D
188  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
189  {
190  h = me->getTH1D(); // access Test histo
191  ref_ = me->getRefTH1D(); //access Ref histo
192  }
193  //-- TProfile
194  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
195  {
196  h = me->getTProfile(); // access Test histo
197  ref_ = me->getRefTProfile(); //access Ref histo
198  }
199  else
200  {
201  if (verbose_>0)
202  std::cout << "QTest::Comp2RefChi2"
203  << " ME does not contain TH1F/TH1S/TH1D/TProfile, exiting\n";
204  return -1;
205  }
206 
207  //-- isInvalid ? - Check consistency in number of channels
208  int ncx1 = h->GetXaxis()->GetNbins();
209  int ncx2 = ref_->GetXaxis()->GetNbins();
210  if ( ncx1 != ncx2)
211  {
212  if (verbose_>0)
213  std::cout << "QTest:Comp2RefChi2"
214  << " different number of channels! ("
215  << ncx1 << ", " << ncx2 << "), exiting\n";
216  return -1;
217  }
218 
219  //-- QUALITY TEST itself
220  //reset Results
221  Ndof_ = 0; chi2_ = -1.; ncx1 = ncx2 = -1;
222 
223  int i, i_start, i_end;
224  double chi2 = 0.; int ndof = 0; int constraint = 0;
225 
226  i_start = 1;
227  i_end = ncx1;
228  // if (fXaxis.TestBit(TAxis::kAxisRange)) {
229  i_start = h->GetXaxis()->GetFirst();
230  i_end = h->GetXaxis()->GetLast();
231  // }
232  ndof = i_end-i_start+1-constraint;
233 
234  //Compute the normalisation factor
235  double sum1=0, sum2=0;
236  for (i=i_start; i<=i_end; i++)
237  {
238  sum1 += h->GetBinContent(i);
239  sum2 += ref_->GetBinContent(i);
240  }
241 
242  //check that the histograms are not empty
243  if (sum1 == 0)
244  {
245  if (verbose_>0)
246  std::cout << "QTest:Comp2RefChi2"
247  << " Test Histogram " << h->GetName()
248  << " is empty, exiting\n";
249  return -1;
250  }
251  if (sum2 == 0)
252  {
253  if (verbose_>0)
254  std::cout << "QTest:Comp2RefChi2"
255  << " Ref Histogram " << ref_->GetName()
256  << " is empty, exiting\n";
257  return -1;
258  }
259 
260  double bin1, bin2, err1, err2, temp;
261  for (i=i_start; i<=i_end; i++)
262  {
263  bin1 = h->GetBinContent(i)/sum1;
264  bin2 = ref_->GetBinContent(i)/sum2;
265  if (bin1 ==0 && bin2==0)
266  {
267  --ndof; //no data means one less degree of freedom
268  }
269  else
270  {
271  temp = bin1-bin2;
272  err1=h->GetBinError(i); err2=ref_->GetBinError(i);
273  if (err1 == 0 && err2 == 0)
274  {
275  if (verbose_>0)
276  std::cout << "QTest:Comp2RefChi2"
277  << " bins with non-zero content and zero error, exiting\n";
278  return -1;
279  }
280  err1*=err1 ; err2*=err2;
281  err1/=sum1*sum1 ; err2/=sum2*sum2;
282  chi2 +=temp*temp/(err1+err2);
283  }
284  }
285  chi2_ = chi2; Ndof_ = ndof;
286  return TMath::Prob(0.5*chi2, int(0.5*ndof));
287 }
288 
289 //-------------------------------------------------------//
290 //----------------- Comp2Ref2DChi2 ---------------------//
291 //-------------------------------------------------------//
293 {
294  if (!me)
295  return -1;
296  if (!me->getRootObject() || !me->getRefRootObject())
297  return -1;
298  if (minEntries_ != 0 && me->getEntries() < minEntries_)
299  return -1;
300 
301  TH2* h=0;
302  TH2* ref_=0;
303 
304  if (verbose_>1)
305  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
306  << me-> getFullname() << "\n";
307  //-- TH2F
309  {
310  h = me->getTH2F(); // access Test histo
311  ref_ = me->getRefTH2F(); //access Ref histo
312  }
313  //-- TH2S
314  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
315  {
316  h = me->getTH2S(); // access Test histo
317  ref_ = me->getRefTH2S(); //access Ref histo
318  }
319  //-- TH2D
320  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
321  {
322  h = me->getTH2D(); // access Test histo
323  ref_ = me->getRefTH2D(); //access Ref histo
324  }
325  //-- TProfile
327  {
328  h = me->getTProfile2D(); // access Test histo
329  ref_ = me->getRefTProfile2D(); //access Ref histo
330  }
331  else
332  {
333  if (verbose_>0)
334  std::cout << "QTest::Comp2Ref2DChi2"
335  << " ME does not contain TH2F/TH2S/TH2D/TProfile2D, exiting\n";
336  return -1;
337  }
338 
339  //-- isInvalid ? - Check consistency in number of channels
340  int ncx1 = h->GetXaxis()->GetNbins();
341  int ncx2 = ref_->GetXaxis()->GetNbins();
342  int ncy1 = h->GetYaxis()->GetNbins();
343  int ncy2 = ref_->GetYaxis()->GetNbins();
344  if ( ( ncx1 != ncx2) || ( ncy1 != ncy2) )
345  {
346  if (verbose_>0)
347  std::cout << "QTest:Comp2Ref2DChi2"
348  << " different number of channels! ("
349  << ncx1 << ", " << ncx2 << "), ("
350  << ncy1 << ", " << ncy2 << "), exiting\n";
351  return -1;
352  }
353 
354  //-- QUALITY TEST itself
355  //reset Results
356  Ndof_ = 0; chi2_ = -1.;
357 
358  //check that the histograms are not empty
359  int i_start = h->GetXaxis()->GetFirst();
360  int i_end = h->GetXaxis()->GetLast();
361  int j_start = h->GetYaxis()->GetFirst();
362  int j_end = h->GetYaxis()->GetLast();
363  if (h->Integral(i_start, i_end, j_start, j_end) == 0)
364  {
365  if (verbose_>0)
366  std::cout << "QTest:Comp2Ref2DChi2"
367  << " Test Histogram " << h->GetName()
368  << " is empty, exiting\n";
369  return -1;
370  }
371  if (ref_->Integral(i_start, i_end, j_start, j_end) == 0)
372  {
373  if (verbose_>0)
374  std::cout << "QTest:Comp2Ref2DChi2"
375  << " Ref Histogram " << ref_->GetName()
376  << " is empty, exiting\n";
377  return -1;
378  }
379 
380  //use the chi2 test for 2D histograms defined in ROOT
381  int igood = 0;
382  double pValue = h->Chi2TestX(ref_, chi2_, Ndof_, igood, "");
383 
384  if (chi2_==-1. && Ndof_==0)
385  return -1;
386 
387  return pValue;
388 }
389 
390 //-------------------------------------------------------//
391 //----------------- Comp2RefKolmogorov --------------//
392 //-------------------------------------------------------//
393 
395 {
396  const double difprec = 1e-5;
397 
398  if (!me)
399  return -1;
400  if (!me->getRootObject() || !me->getRefRootObject())
401  return -1;
402  TH1* h=0;
403  TH1* ref_=0;
404 
405  if (verbose_>1)
406  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
407  << me-> getFullname() << "\n";
408  //-- TH1F
410  {
411  h = me->getTH1F(); // access Test histo
412  ref_ = me->getRefTH1F(); //access Ref histo
413  }
414  //-- TH1S
415  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
416  {
417  h = me->getTH1S(); // access Test histo
418  ref_ = me->getRefTH1S(); //access Ref histo
419  }
420  //-- TH1D
421  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
422  {
423  h = me->getTH1D(); // access Test histo
424  ref_ = me->getRefTH1D(); //access Ref histo
425  }
426  //-- TProfile
427  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
428  {
429  h = me->getTProfile(); // access Test histo
430  ref_ = me->getRefTProfile(); //access Ref histo
431  }
432  else
433  {
434  if (verbose_>0)
435  std::cout << "QTest:Comp2RefKolmogorov"
436  << " ME does not contain TH1F/TH1S/TH1D/TProfile, exiting\n";
437  return -1;
438  }
439 
440  //-- isInvalid ? - Check consistency in number of channels
441  int ncx1 = h->GetXaxis()->GetNbins();
442  int ncx2 = ref_->GetXaxis()->GetNbins();
443  if ( ncx1 != ncx2)
444  {
445  if (verbose_>0)
446  std::cout << "QTest:Comp2RefKolmogorov"
447  << " different number of channels! ("
448  << ncx1 << ", " << ncx2 << "), exiting\n";
449  return -1;
450  }
451  //-- isInvalid ? - Check consistency in channel edges
452  double diff1 = TMath::Abs(h->GetXaxis()->GetXmin() - ref_->GetXaxis()->GetXmin());
453  double diff2 = TMath::Abs(h->GetXaxis()->GetXmax() - ref_->GetXaxis()->GetXmax());
454  if (diff1 > difprec || diff2 > difprec)
455  {
456  if (verbose_>0)
457  std::cout << "QTest:Comp2RefKolmogorov"
458  << " histograms with different binning, exiting\n";
459  return -1;
460  }
461 
462  //-- QUALITY TEST itself
463  Bool_t afunc1 = kFALSE; Bool_t afunc2 = kFALSE;
464  double sum1 = 0, sum2 = 0;
465  double ew1, ew2, w1 = 0, w2 = 0;
466  int bin;
467  for (bin=1;bin<=ncx1;bin++)
468  {
469  sum1 += h->GetBinContent(bin);
470  sum2 += ref_->GetBinContent(bin);
471  ew1 = h->GetBinError(bin);
472  ew2 = ref_->GetBinError(bin);
473  w1 += ew1*ew1;
474  w2 += ew2*ew2;
475  }
476 
477  if (sum1 == 0)
478  {
479  if (verbose_>0)
480  std::cout << "QTest:Comp2RefKolmogorov"
481  << " Test Histogram: " << h->GetName()
482  << ": integral is zero, exiting\n";
483  return -1;
484  }
485  if (sum2 == 0)
486  {
487  if (verbose_>0)
488  std::cout << "QTest:Comp2RefKolmogorov"
489  << " Ref Histogram: " << ref_->GetName()
490  << ": integral is zero, exiting\n";
491  return -1;
492  }
493 
494  double tsum1 = sum1; double tsum2 = sum2;
495  tsum1 += h->GetBinContent(0);
496  tsum2 += ref_->GetBinContent(0);
497  tsum1 += h->GetBinContent(ncx1+1);
498  tsum2 += ref_->GetBinContent(ncx1+1);
499 
500  // Check if histograms are weighted.
501  // If number of entries = number of channels, probably histograms were
502  // not filled via Fill(), but via SetBinContent()
503  double ne1 = h->GetEntries();
504  double ne2 = ref_->GetEntries();
505  // look at first histogram
506  double difsum1 = (ne1-tsum1)/tsum1;
507  double esum1 = sum1;
508  if (difsum1 > difprec && int(ne1) != ncx1)
509  {
510  if (h->GetSumw2N() == 0)
511  {
512  if (verbose_>0)
513  std::cout << "QTest:Comp2RefKolmogorov"
514  << " Weighted events and no Sumw2 for "
515  << h->GetName() << "\n";
516  }
517  else
518  {
519  esum1 = sum1*sum1/w1; //number of equivalent entries
520  }
521  }
522  // look at second histogram
523  double difsum2 = (ne2-tsum2)/tsum2;
524  double esum2 = sum2;
525  if (difsum2 > difprec && int(ne2) != ncx1)
526  {
527  if (ref_->GetSumw2N() == 0)
528  {
529  if (verbose_>0)
530  std::cout << "QTest:Comp2RefKolmogorov"
531  << " Weighted events and no Sumw2 for "
532  << ref_->GetName() << "\n";
533  }
534  else
535  {
536  esum2 = sum2*sum2/w2; //number of equivalent entries
537  }
538  }
539 
540  double s1 = 1/tsum1; double s2 = 1/tsum2;
541  // Find largest difference for Kolmogorov Test
542  double dfmax =0, rsum1 = 0, rsum2 = 0;
543  // use underflow bin
544  int first = 0; // 1
545  // use overflow bin
546  int last = ncx1+1; // ncx1
547  for ( bin=first; bin<=last; bin++)
548  {
549  rsum1 += s1*h->GetBinContent(bin);
550  rsum2 += s2*ref_->GetBinContent(bin);
551  dfmax = TMath::Max(dfmax,TMath::Abs(rsum1-rsum2));
552  }
553 
554  // Get Kolmogorov probability
555  double z = 0;
556  if (afunc1) z = dfmax*TMath::Sqrt(esum2);
557  else if (afunc2) z = dfmax*TMath::Sqrt(esum1);
558  else z = dfmax*TMath::Sqrt(esum1*esum2/(esum1+esum2));
559 
560  // This numerical error condition should never occur:
561  if (TMath::Abs(rsum1-1) > 0.002)
562  if (verbose_>0)
563  std::cout << "QTest:Comp2RefKolmogorov"
564  << " Numerical problems with histogram "
565  << h->GetName() << "\n";
566  if (TMath::Abs(rsum2-1) > 0.002)
567  if (verbose_>0)
568  std::cout << "QTest:Comp2RefKolmogorov"
569  << " Numerical problems with histogram "
570  << ref_->GetName() << "\n";
571 
572  return TMath::KolmogorovProb(z);
573 }
574 
575 //----------------------------------------------------//
576 //--------------- ContentsXRange ---------------------//
577 //----------------------------------------------------//
579 {
580  badChannels_.clear();
581 
582  if (!me)
583  return -1;
584  if (!me->getRootObject())
585  return -1;
586  TH1* h=0;
587 
588  if (verbose_>1)
589  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
590  << me-> getFullname() << "\n";
591  // -- TH1F
592  if (me->kind()==MonitorElement::DQM_KIND_TH1F )
593  {
594  h = me->getTH1F();
595  }
596  // -- TH1S
597  else if ( me->kind()==MonitorElement::DQM_KIND_TH1S )
598  {
599  h = me->getTH1S();
600  }
601  // -- TH1D
602  else if ( me->kind()==MonitorElement::DQM_KIND_TH1D )
603  {
604  h = me->getTH1D();
605  }
606  else
607  {
608  if (verbose_>0) std::cout << "QTest:ContentsXRange"
609  << " ME " << me->getFullname()
610  << " does not contain TH1F/TH1S/TH1D, exiting\n";
611  return -1;
612  }
613 
614  if (!rangeInitialized_)
615  {
616  if ( h->GetXaxis() )
617  setAllowedXRange(h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
618  else
619  return -1;
620  }
621  int ncx = h->GetXaxis()->GetNbins();
622  // use underflow bin
623  int first = 0; // 1
624  // use overflow bin
625  int last = ncx+1; // ncx
626  // all entries
627  double sum = 0;
628  // entries outside X-range
629  double fail = 0;
630  int bin;
631  for (bin = first; bin <= last; ++bin)
632  {
633  double contents = h->GetBinContent(bin);
634  double x = h->GetBinCenter(bin);
635  sum += contents;
636  if (x < xmin_ || x > xmax_)fail += contents;
637  }
638 
639  if (sum==0) return 1;
640  // return fraction of entries within allowed X-range
641  return (sum - fail)/sum;
642 
643 }
644 
645 //-----------------------------------------------------//
646 //--------------- ContentsYRange ---------------------//
647 //----------------------------------------------------//
649 {
650  badChannels_.clear();
651 
652  if (!me)
653  return -1;
654  if (!me->getRootObject())
655  return -1;
656  TH1* h=0;
657 
658  if (verbose_>1)
659  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
660  << me-> getFullname() << "\n";
661 
663  {
664  h = me->getTH1F(); //access Test histo
665  }
666  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
667  {
668  h = me->getTH1S(); //access Test histo
669  }
670  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
671  {
672  h = me->getTH1D(); //access Test histo
673  }
674  else
675  {
676  if (verbose_>0)
677  std::cout << "QTest:ContentsYRange"
678  << " ME " << me->getFullname()
679  << " does not contain TH1F/TH1S/TH1D, exiting\n";
680  return -1;
681  }
682 
683  if (!rangeInitialized_ || !h->GetXaxis()) return 1; // all bins are accepted if no initialization
684  int ncx = h->GetXaxis()->GetNbins();
685  // do NOT use underflow bin
686  int first = 1;
687  // do NOT use overflow bin
688  int last = ncx;
689  // bins outside Y-range
690  int fail = 0;
691  int bin;
692 
693  if (useEmptyBins_)
694  {
695  for (bin = first; bin <= last; ++bin)
696  {
697  double contents = h->GetBinContent(bin);
698  bool failure = false;
699  failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
700  if (failure)
701  {
702  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
703  badChannels_.push_back(chan);
704  ++fail;
705  }
706  }
707  // return fraction of bins that passed test
708  return 1.*(ncx - fail)/ncx;
709  }
710  else
711  {
712  for (bin = first; bin <= last; ++bin)
713  {
714  double contents = h->GetBinContent(bin);
715  bool failure = false;
716  if (contents) failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
717  if (failure) ++fail;
718  }
719  // return fraction of bins that passed test
720  return 1.*(ncx - fail)/ncx;
721  }
722 }
723 
724 //-----------------------------------------------------//
725 //------------------ DeadChannel ---------------------//
726 //----------------------------------------------------//
728 {
729  badChannels_.clear();
730  if (!me)
731  return -1;
732  if (!me->getRootObject())
733  return -1;
734  TH1* h1=0;
735  TH2* h2=0;//initialize histogram pointers
736 
737  if (verbose_>1)
738  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
739  << me-> getFullname() << "\n";
740  //TH1F
742  {
743  h1 = me->getTH1F(); //access Test histo
744  }
745  //TH1S
746  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
747  {
748  h1 = me->getTH1S(); //access Test histo
749  }
750  //TH1D
751  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
752  {
753  h1 = me->getTH1D(); //access Test histo
754  }
755  //-- TH2F
756  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
757  {
758  h2 = me->getTH2F(); // access Test histo
759  }
760  //-- TH2S
761  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
762  {
763  h2 = me->getTH2S(); // access Test histo
764  }
765  //-- TH2D
766  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
767  {
768  h2 = me->getTH2D(); // access Test histo
769  }
770  else
771  {
772  if (verbose_>0)
773  std::cout << "QTest:DeadChannel"
774  << " ME " << me->getFullname()
775  << " does not contain TH1F/TH1S/TH1D/TH2F/TH2S/TH2D, exiting\n";
776  return -1;
777  }
778 
779  int fail = 0; // number of failed channels
780 
781  //--------- do the quality test for 1D histo ---------------//
782  if (h1 != NULL)
783  {
784  if (!rangeInitialized_ || !h1->GetXaxis() )
785  return 1; // all bins are accepted if no initialization
786  int ncx = h1->GetXaxis()->GetNbins();
787  int first = 1;
788  int last = ncx;
789  int bin;
790 
792  for (bin = first; bin <= last; ++bin)
793  {
794  double contents = h1->GetBinContent(bin);
795  bool failure = false;
796  failure = contents <= ymin_; // dead channel: equal to or less than ymin_
797  if (failure)
798  {
799  DQMChannel chan(bin, 0, 0, contents, h1->GetBinError(bin));
800  badChannels_.push_back(chan);
801  ++fail;
802  }
803  }
804  //return fraction of alive channels
805  return 1.*(ncx - fail)/ncx;
806  }
807  //----------------------------------------------------------//
808 
809  //--------- do the quality test for 2D -------------------//
810  else if (h2 !=NULL )
811  {
812  int ncx = h2->GetXaxis()->GetNbins(); // get X bins
813  int ncy = h2->GetYaxis()->GetNbins(); // get Y bins
814 
816  for (int cx = 1; cx <= ncx; ++cx)
817  {
818  for (int cy = 1; cy <= ncy; ++cy)
819  {
820  double contents = h2->GetBinContent(h2->GetBin(cx, cy));
821  bool failure = false;
822  failure = contents <= ymin_; // dead channel: equal to or less than ymin_
823  if (failure)
824  {
825  DQMChannel chan(cx, cy, 0, contents, h2->GetBinError(h2->GetBin(cx, cy)));
826  badChannels_.push_back(chan);
827  ++fail;
828  }
829  }
830  }
831  //return fraction of alive channels
832  return 1.*(ncx*ncy - fail) / (ncx*ncy);
833  }
834  else
835  {
836  if (verbose_>0)
837  std::cout << "QTest:DeadChannel"
838  << " TH1/TH2F are NULL, exiting\n";
839  return -1;
840  }
841 }
842 
843 //-----------------------------------------------------//
844 //---------------- NoisyChannel ---------------------//
845 //----------------------------------------------------//
846 // run the test (result: fraction of channels not appearing noisy or "hot")
847 // [0, 1] or <0 for failure
849 {
850  badChannels_.clear();
851  if (!me)
852  return -1;
853  if (!me->getRootObject())
854  return -1;
855  TH1* h=0;//initialize histogram pointer
856 
857  if (verbose_>1)
858  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
859  << me-> getFullname() << "\n";
860 
861  int nbins=0;
862  //-- TH1F
864  {
865  nbins = me->getTH1F()->GetXaxis()->GetNbins();
866  h = me->getTH1F(); // access Test histo
867  }
868  //-- TH1S
869  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
870  {
871  nbins = me->getTH1S()->GetXaxis()->GetNbins();
872  h = me->getTH1S(); // access Test histo
873  }
874  //-- TH1D
875  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
876  {
877  nbins = me->getTH1D()->GetXaxis()->GetNbins();
878  h = me->getTH1D(); // access Test histo
879  }
880  //-- TH2
881  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
882  {
883  nbins = me->getTH2F()->GetXaxis()->GetNbins() *
884  me->getTH2F()->GetYaxis()->GetNbins();
885  h = me->getTH2F(); // access Test histo
886  }
887  //-- TH2
888  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
889  {
890  nbins = me->getTH2S()->GetXaxis()->GetNbins() *
891  me->getTH2S()->GetYaxis()->GetNbins();
892  h = me->getTH2S(); // access Test histo
893  }
894  //-- TH2
895  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
896  {
897  nbins = me->getTH2D()->GetXaxis()->GetNbins() *
898  me->getTH2D()->GetYaxis()->GetNbins();
899  h = me->getTH2D(); // access Test histo
900  }
901  else
902  {
903  if (verbose_>0)
904  std::cout << "QTest:NoisyChannel"
905  << " ME " << me->getFullname()
906  << " does not contain TH1F/TH1S/TH1D or TH2F/TH2S/TH2D, exiting\n";
907  return -1;
908  }
909 
910  //-- QUALITY TEST itself
911 
912  if ( !rangeInitialized_ || !h->GetXaxis() )
913  return 1; // all channels are accepted if tolerance has not been set
914 
915  // do NOT use underflow bin
916  int first = 1;
917  // do NOT use overflow bin
918  int last = nbins;
919  // bins outside Y-range
920  int fail = 0;
921  int bin;
922  for (bin = first; bin <= last; ++bin)
923  {
924  double contents = h->GetBinContent(bin);
925  double average = getAverage(bin, h);
926  bool failure = false;
927  if (average != 0)
928  failure = (((contents-average)/TMath::Abs(average)) > tolerance_);
929 
930  if (failure)
931  {
932  ++fail;
933  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
934  badChannels_.push_back(chan);
935  }
936  }
937 
938  // return fraction of bins that passed test
939  return 1.*(nbins - fail)/nbins;
940 }
941 
942 // get average for bin under consideration
943 // (see description of method setNumNeighbors)
944 double NoisyChannel::getAverage(int bin, const TH1 *h) const
945 {
947  int first = 1;
949  int ncx = h->GetXaxis()->GetNbins();
950  double sum = 0; int bin_low, bin_hi;
951  for (unsigned i = 1; i <= numNeighbors_; ++i)
952  {
954  bin_low = bin-i; bin_hi = bin+i;
957  while (bin_low < first) // shift bin by +ncx
958  bin_low = ncx + bin_low;
959  while (bin_hi > ncx) // shift bin by -ncx
960  bin_hi = bin_hi - ncx;
961  sum += h->GetBinContent(bin_low) + h->GetBinContent(bin_hi);
962  }
964  return sum/(numNeighbors_ * 2);
965 }
966 
967 
968 //-----------------------------------------------------------//
969 //---------------- ContentsWithinExpected ---------------------//
970 //-----------------------------------------------------------//
971 // run the test (result: fraction of channels that passed test);
972 // [0, 1] or <0 for failure
974 {
975  badChannels_.clear();
976  if (!me)
977  return -1;
978  if (!me->getRootObject())
979  return -1;
980  TH1* h=0; //initialize histogram pointer
981 
982  if (verbose_>1)
983  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
984  << me-> getFullname() << "\n";
985 
986  int ncx;
987  int ncy;
988 
989  if (useEmptyBins_)
990  {
991  //-- TH2
993  {
994  ncx = me->getTH2F()->GetXaxis()->GetNbins();
995  ncy = me->getTH2F()->GetYaxis()->GetNbins();
996  h = me->getTH2F(); // access Test histo
997  }
998  //-- TH2S
999  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
1000  {
1001  ncx = me->getTH2S()->GetXaxis()->GetNbins();
1002  ncy = me->getTH2S()->GetYaxis()->GetNbins();
1003  h = me->getTH2S(); // access Test histo
1004  }
1005  //-- TH2D
1006  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
1007  {
1008  ncx = me->getTH2D()->GetXaxis()->GetNbins();
1009  ncy = me->getTH2D()->GetYaxis()->GetNbins();
1010  h = me->getTH2D(); // access Test histo
1011  }
1012  //-- TProfile
1013  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
1014  {
1015  ncx = me->getTProfile()->GetXaxis()->GetNbins();
1016  ncy = 1;
1017  h = me->getTProfile(); // access Test histo
1018  }
1019  //-- TProfile2D
1020  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE2D)
1021  {
1022  ncx = me->getTProfile2D()->GetXaxis()->GetNbins();
1023  ncy = me->getTProfile2D()->GetYaxis()->GetNbins();
1024  h = me->getTProfile2D(); // access Test histo
1025  }
1026  else
1027  {
1028  if (verbose_>0)
1029  std::cout << "QTest:ContentsWithinExpected"
1030  << " ME does not contain TH2F/TH2S/TH2D/TPROFILE/TPROFILE2D, exiting\n";
1031  return -1;
1032  }
1033 
1034  int nsum = 0;
1035  double sum = 0.0;
1036  double average = 0.0;
1037 
1038  if (checkMeanTolerance_)
1039  { // calculate average value of all bin contents
1040 
1041  for (int cx = 1; cx <= ncx; ++cx)
1042  {
1043  for (int cy = 1; cy <= ncy; ++cy)
1044  {
1045  if (me->kind() == MonitorElement::DQM_KIND_TH2F)
1046  {
1047  sum += h->GetBinContent(h->GetBin(cx, cy));
1048  ++nsum;
1049  }
1050  else if (me->kind() == MonitorElement::DQM_KIND_TH2S)
1051  {
1052  sum += h->GetBinContent(h->GetBin(cx, cy));
1053  ++nsum;
1054  }
1055  else if (me->kind() == MonitorElement::DQM_KIND_TH2D)
1056  {
1057  sum += h->GetBinContent(h->GetBin(cx, cy));
1058  ++nsum;
1059  }
1060  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE)
1061  {
1062  if (me->getTProfile()->GetBinEntries(h->GetBin(cx)) >= minEntries_/(ncx))
1063  {
1064  sum += h->GetBinContent(h->GetBin(cx));
1065  ++nsum;
1066  }
1067  }
1068  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D)
1069  {
1070  if (me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) >= minEntries_/(ncx*ncy))
1071  {
1072  sum += h->GetBinContent(h->GetBin(cx, cy));
1073  ++nsum;
1074  }
1075  }
1076  }
1077  }
1078 
1079  if (nsum > 0)
1080  average = sum/nsum;
1081 
1082  } // calculate average value of all bin contents
1083 
1084  int fail = 0;
1085 
1086  for (int cx = 1; cx <= ncx; ++cx)
1087  {
1088  for (int cy = 1; cy <= ncy; ++cy)
1089  {
1090  bool failMean = false;
1091  bool failRMS = false;
1092  bool failMeanTolerance = false;
1093 
1094  if (me->kind() == MonitorElement::DQM_KIND_TPROFILE &&
1095  me->getTProfile()->GetBinEntries(h->GetBin(cx)) < minEntries_/(ncx))
1096  continue;
1097 
1098  if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D &&
1099  me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) < minEntries_/(ncx*ncy))
1100  continue;
1101 
1102  if (checkMean_)
1103  {
1104  double mean = h->GetBinContent(h->GetBin(cx, cy));
1105  failMean = (mean < minMean_ || mean > maxMean_);
1106  }
1107 
1108  if (checkRMS_)
1109  {
1110  double rms = h->GetBinError(h->GetBin(cx, cy));
1111  failRMS = (rms < minRMS_ || rms > maxRMS_);
1112  }
1113 
1114  if (checkMeanTolerance_)
1115  {
1116  double mean = h->GetBinContent(h->GetBin(cx, cy));
1117  failMeanTolerance = (TMath::Abs(mean - average) > toleranceMean_*TMath::Abs(average));
1118  }
1119 
1120  if (failMean || failRMS || failMeanTolerance)
1121  {
1122 
1123  if (me->kind() == MonitorElement::DQM_KIND_TH2F)
1124  {
1125  DQMChannel chan(cx, cy, 0,
1126  h->GetBinContent(h->GetBin(cx, cy)),
1127  h->GetBinError(h->GetBin(cx, cy)));
1128  badChannels_.push_back(chan);
1129  }
1130  else if (me->kind() == MonitorElement::DQM_KIND_TH2S)
1131  {
1132  DQMChannel chan(cx, cy, 0,
1133  h->GetBinContent(h->GetBin(cx, cy)),
1134  h->GetBinError(h->GetBin(cx, cy)));
1135  badChannels_.push_back(chan);
1136  }
1137  else if (me->kind() == MonitorElement::DQM_KIND_TH2D)
1138  {
1139  DQMChannel chan(cx, cy, 0,
1140  h->GetBinContent(h->GetBin(cx, cy)),
1141  h->GetBinError(h->GetBin(cx, cy)));
1142  badChannels_.push_back(chan);
1143  }
1144  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE)
1145  {
1146  DQMChannel chan(cx, cy, int(me->getTProfile()->GetBinEntries(h->GetBin(cx))),
1147  0,
1148  h->GetBinError(h->GetBin(cx)));
1149  badChannels_.push_back(chan);
1150  }
1151  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D)
1152  {
1153  DQMChannel chan(cx, cy, int(me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy))),
1154  h->GetBinContent(h->GetBin(cx, cy)),
1155  h->GetBinError(h->GetBin(cx, cy)));
1156  badChannels_.push_back(chan);
1157  }
1158  ++fail;
1159  }
1160  }
1161  }
1162  return 1.*(ncx*ncy - fail)/(ncx*ncy);
1163  }
1164 
1165  else
1166  {
1168  {
1169  ncx = me->getTH2F()->GetXaxis()->GetNbins();
1170  ncy = me->getTH2F()->GetYaxis()->GetNbins();
1171  h = me->getTH2F(); // access Test histo
1172  }
1173  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
1174  {
1175  ncx = me->getTH2S()->GetXaxis()->GetNbins();
1176  ncy = me->getTH2S()->GetYaxis()->GetNbins();
1177  h = me->getTH2S(); // access Test histo
1178  }
1179  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
1180  {
1181  ncx = me->getTH2D()->GetXaxis()->GetNbins();
1182  ncy = me->getTH2D()->GetYaxis()->GetNbins();
1183  h = me->getTH2D(); // access Test histo
1184  }
1185  else
1186  {
1187  if (verbose_>0)
1188  std::cout << "QTest:ContentsWithinExpected AS"
1189  << " ME does not contain TH2F/TH2S/TH2D, exiting\n";
1190  return -1;
1191  }
1192 
1193  // if (!rangeInitialized_) return 0; // all accepted if no initialization
1194  int fail = 0;
1195  for (int cx = 1; cx <= ncx; ++cx)
1196  {
1197  for (int cy = 1; cy <= ncy; ++cy)
1198  {
1199  bool failure = false;
1200  double Content = h->GetBinContent(h->GetBin(cx, cy));
1201  if (Content)
1202  failure = (Content < minMean_ || Content > maxMean_);
1203  if (failure)
1204  ++fail;
1205  }
1206  }
1207  return 1.*(ncx*ncy-fail)/(ncx*ncy);
1208  }
1209 
1210 }
1213 {
1214  if (xmax < xmin)
1215  if (verbose_>0)
1216  std::cout << "QTest:ContentsWitinExpected"
1217  << " Illogical range: (" << xmin << ", " << xmax << "\n";
1218  minMean_ = xmin;
1219  maxMean_ = xmax;
1220  checkMean_ = true;
1221 }
1222 
1225 {
1226  if (xmax < xmin)
1227  if (verbose_>0)
1228  std::cout << "QTest:ContentsWitinExpected"
1229  << " Illogical range: (" << xmin << ", " << xmax << "\n";
1230  minRMS_ = xmin;
1231  maxRMS_ = xmax;
1232  checkRMS_ = true;
1233 }
1234 
1235 //----------------------------------------------------------------//
1236 //-------------------- MeanWithinExpected ---------------------//
1237 //---------------------------------------------------------------//
1238 // run the test;
1239 // (a) if useRange is called: 1 if mean within allowed range, 0 otherwise
1240 // (b) is useRMS or useSigma is called: result is the probability
1241 // Prob(chi^2, ndof=1) that the mean of histogram will be deviated by more than
1242 // +/- delta from <expected_mean>, where delta = mean - <expected_mean>, and
1243 // chi^2 = (delta/sigma)^2. sigma is the RMS of the histogram ("useRMS") or
1244 // <expected_sigma> ("useSigma")
1245 // e.g. for delta = 1, Prob = 31.7%
1246 // for delta = 2, Prob = 4.55%
1247 // (returns result in [0, 1] or <0 for failure)
1249 {
1250  if (!me)
1251  return -1;
1252  if (!me->getRootObject())
1253  return -1;
1254  TH1* h=0;
1255 
1256  if (verbose_>1)
1257  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1258  << me-> getFullname() << "\n";
1259 
1260  if (minEntries_ != 0 && me->getEntries() < minEntries_) return -1;
1261 
1262  if (me->kind()==MonitorElement::DQM_KIND_TH1F)
1263  {
1264  h = me->getTH1F(); //access Test histo
1265  }
1266  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
1267  {
1268  h = me->getTH1S(); //access Test histo
1269  }
1270  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
1271  {
1272  h = me->getTH1D(); //access Test histo
1273  }
1274  else {
1275  if (verbose_>0)
1276  std::cout << "QTest:MeanWithinExpected"
1277  << " ME " << me->getFullname()
1278  << " does not contain TH1F/TH1S/TH1D, exiting\n";
1279  return -1;
1280  }
1281 
1282 
1283  if (useRange_) {
1284  double mean = h->GetMean();
1285  if (mean <= xmax_ && mean >= xmin_)
1286  return 1;
1287  else
1288  return 0;
1289  }
1290  else if (useSigma_)
1291  {
1292  if (sigma_ != 0.)
1293  {
1294  double chi = (h->GetMean() - expMean_)/sigma_;
1295  return TMath::Prob(chi*chi, 1);
1296  }
1297  else
1298  {
1299  if (verbose_>0)
1300  std::cout << "QTest:MeanWithinExpected"
1301  << " Error, sigma_ is zero, exiting\n";
1302  return 0;
1303  }
1304  }
1305  else if (useRMS_)
1306  {
1307  if (h->GetRMS() != 0.)
1308  {
1309  double chi = (h->GetMean() - expMean_)/h->GetRMS();
1310  return TMath::Prob(chi*chi, 1);
1311  }
1312  else
1313  {
1314  if (verbose_>0)
1315  std::cout << "QTest:MeanWithinExpected"
1316  << " Error, RMS is zero, exiting\n";
1317  return 0;
1318  }
1319  }
1320  else {
1321  if (verbose_>0)
1322  std::cout << "QTest:MeanWithinExpected"
1323  << " Error, neither Range, nor Sigma, nor RMS, exiting\n";
1324  return -1; }
1325 }
1326 
1328 {
1329  useRange_ = true;
1330  useSigma_ = useRMS_ = false;
1331  xmin_ = xmin; xmax_ = xmax;
1332  if (xmin_ > xmax_)
1333  if (verbose_>0)
1334  std::cout << "QTest:MeanWithinExpected"
1335  << " Illogical range: (" << xmin_ << ", " << xmax_ << "\n";
1336 }
1337 void MeanWithinExpected::useSigma(double expectedSigma)
1338 {
1339  useSigma_ = true;
1340  useRMS_ = useRange_ = false;
1341  sigma_ = expectedSigma;
1342  if (sigma_ == 0)
1343  if (verbose_>0)
1344  std::cout << "QTest:MeanWithinExpected"
1345  << " Expected sigma = " << sigma_ << "\n";
1346 }
1347 
1349 {
1350  useRMS_ = true;
1351  useSigma_ = useRange_ = false;
1352 }
1353 
1354 //----------------------------------------------------------------//
1355 //------------------------ CompareToMedian ---------------------------//
1356 //----------------------------------------------------------------//
1357 /*
1358 Test for TProfile2D
1359 For each x bin, the median value is calculated and then each value is compared with the median.
1360 This procedure is repeated for each x-bin of the 2D profile
1361 The parameters used for this comparison are:
1362 MinRel and MaxRel to identify outliers wrt the median value
1363 An absolute value (MinAbs, MaxAbs) on the median is used to identify a full region out of specification
1364 */
1366  int32_t nbins=0, failed=0;
1367  badChannels_.clear();
1368 
1369  if (!me)
1370  return -1;
1371  if (!me->getRootObject())
1372  return -1;
1373  TH1* h=0;
1374 
1375  if (verbose_>1){
1376  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1377  << me-> getFullname() << "\n";
1378  std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
1379  std::cout << "\tMinMedian = " << _minMed << "; MaxMedian = " << _maxMed << "\n";
1380  std::cout << "\tUseEmptyBins = " << (_emptyBins?"Yes":"No" )<< "\n";
1381  }
1382 
1384  {
1385  h = me->getTProfile2D(); // access Test histo
1386  }
1387  else
1388  {
1389  if (verbose_>0)
1390  std::cout << "QTest:ContentsWithinExpected"
1391  << " ME does not contain TPROFILE2D, exiting\n";
1392  return -1;
1393  }
1394 
1395  nBinsX = h->GetNbinsX();
1396  nBinsY = h->GetNbinsY();
1397  int entries = 0;
1398  float median = 0.0;
1399 
1400  //Median calculated with partially sorted vector
1401  for (int binX = 1; binX <= nBinsX; binX++ ){
1402  reset();
1403  // Fill vector
1404  for (int binY = 1; binY <= nBinsY; binY++){
1405  int bin = h->GetBin(binX, binY);
1406  double content = (double)h->GetBinContent(bin);
1407  if ( content == 0 && !_emptyBins)
1408  continue;
1409  binValues.push_back(content);
1410  entries = me->getTProfile2D()->GetBinEntries(bin);
1411  }
1412  if (binValues.empty())
1413  continue;
1414  nbins+=binValues.size();
1415 
1416  //calculate median
1417  if(binValues.size()>0){
1418  int medPos = (int)binValues.size()/2;
1419  nth_element(binValues.begin(),binValues.begin()+medPos,binValues.end());
1420  median = *(binValues.begin()+medPos);
1421  }
1422 
1423  // if median == 0, use the absolute cut
1424  if(median == 0){
1425  if (verbose_ > 0){
1426  std::cout << "QTest: Median is 0; the fixed cuts: [" << _minMed << "; " << _maxMed << "] are used\n";
1427  }
1428  for(int binY = 1; binY <= nBinsY; binY++){
1429  int bin = h->GetBin(binX, binY);
1430  double content = (double)h->GetBinContent(bin);
1431  entries = me->getTProfile2D()->GetBinEntries(bin);
1432  if ( entries == 0 )
1433  continue;
1434  if (content > _maxMed || content < _minMed){
1435  DQMChannel chan(binX,binY, 0, content, h->GetBinError(bin));
1436  badChannels_.push_back(chan);
1437  failed++;
1438  }
1439  }
1440  continue;
1441  }
1442 
1443  //Cut on stat: will mask rings with no enought of statistics
1444  if (median*entries < _statCut )
1445  continue;
1446 
1447  // If median is off the absolute cuts, declare everything bad (if bin has non zero entries)
1448  if(median > _maxMed || median < _minMed){
1449  for(int binY = 1; binY <= nBinsY; binY++){
1450  int bin = h->GetBin(binX, binY);
1451  double content = (double)h->GetBinContent(bin);
1452  entries = me->getTProfile2D()->GetBinEntries(bin);
1453  if ( entries == 0 )
1454  continue;
1455  DQMChannel chan(binX,binY, 0, content/median, h->GetBinError(bin));
1456  badChannels_.push_back(chan);
1457  failed++;
1458  }
1459  continue;
1460  }
1461 
1462  // Test itself
1463  float minCut = median*_min;
1464  float maxCut = median*_max;
1465  for(int binY = 1; binY <= nBinsY; binY++){
1466  int bin = h->GetBin(binX, binY);
1467  double content = (double)h->GetBinContent(bin);
1468  entries = me->getTProfile2D()->GetBinEntries(bin);
1469  if ( entries == 0 )
1470  continue;
1471  if (content > maxCut || content < minCut){
1472  DQMChannel chan(binX,binY, 0, content/median, h->GetBinError(bin));
1473  badChannels_.push_back(chan);
1474  failed++;
1475  }
1476  }
1477  }
1478 
1479  if (nbins==0){
1480  if (verbose_ > 0)
1481  std::cout << "QTest:CompareToMedian: Histogram is empty" << std::endl;
1482  return 1.;
1483  }
1484  return 1 - (float)failed/nbins;
1485 }
1486 //----------------------------------------------------------------//
1487 //------------------------ CompareLastFilledBin -----------------//
1488 //----------------------------------------------------------------//
1489 /*
1490 Test for TH1F and TH2F
1491 For the last filled bin the value is compared with specified upper and lower limits. If
1492 it is outside the limit the test failed test result is returned
1493 The parameters used for this comparison are:
1494 MinRel and MaxRel to check identify outliers wrt the median value
1495 */
1497  if (!me)
1498  return -1;
1499  if (!me->getRootObject())
1500  return -1;
1501  TH1* h1=0;
1502  TH2* h2=0;
1503  if (verbose_>1){
1504  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1505  << me-> getFullname() << "\n";
1506  std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
1507  }
1509  {
1510  h1 = me->getTH1F(); // access Test histo
1511  }
1512  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
1513  {
1514  h2 = me->getTH2F(); // access Test histo
1515  }
1516  else
1517  {
1518  if (verbose_>0)
1519  std::cout << "QTest:ContentsWithinExpected"
1520  << " ME does not contain TH1F or TH2F, exiting\n";
1521  return -1;
1522  }
1523  int lastBinX = 0;
1524  int lastBinY = 0;
1525  float lastBinVal;
1526 
1527  //--------- do the quality test for 1D histo ---------------//
1528  if (h1 != NULL)
1529  {
1530  lastBinX = h1->FindLastBinAbove(_average,1);
1531  lastBinVal = h1->GetBinContent(lastBinX);
1532  if (h1->GetEntries() == 0 || lastBinVal < 0) return 1;
1533  }
1534  else if (h2 != NULL)
1535  {
1536 
1537  lastBinX = h2->FindLastBinAbove(_average,1);
1538  lastBinY = h2->FindLastBinAbove(_average,2);
1539  if ( h2->GetEntries() == 0 || lastBinX < 0 || lastBinY < 0 ) return 1;
1540  lastBinVal = h2->GetBinContent(h2->GetBin(lastBinX,lastBinY));
1541  } else {
1542  if (verbose_ > 0) std::cout << "QTest:"<< getAlgoName() << " Histogram does not exist" << std::endl;
1543  return 1;
1544  }
1545  if (verbose_ > 0) std::cout << "Min and Max values " << _min << " " << _max << " Av value " << _average << " lastBinX " << lastBinX<< " lastBinY " << lastBinY << " lastBinVal " << lastBinVal << std::endl;
1546  if (lastBinVal > _min && lastBinVal <= _max)
1547  return 1;
1548  else
1549  return 0;
1550 }
1551 //----------------------------------------------------//
1552 //--------------- CheckVariance ---------------------//
1553 //----------------------------------------------------//
1555 {
1556  badChannels_.clear();
1557 
1558  if (!me)
1559  return -1;
1560  if (!me->getRootObject())
1561  return -1;
1562  TH1* h=0;
1563 
1564  if (verbose_>1)
1565  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1566  << me-> getFullname() << "\n";
1567  // -- TH1F
1568  if (me->kind()==MonitorElement::DQM_KIND_TH1F )
1569  {
1570  h = me->getTH1F();
1571  }
1572  // -- TH1D
1573  else if ( me->kind()==MonitorElement::DQM_KIND_TH1D )
1574  {
1575  h = me->getTH1D();
1576  }
1577  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
1578  {
1579  h = me->getTProfile(); // access Test histo
1580  }
1581  else
1582  {
1583  if (verbose_>0) std::cout << "QTest:CheckVariance"
1584  << " ME " << me->getFullname()
1585  << " does not contain TH1F/TH1D/TPROFILE, exiting\n";
1586  return -1;
1587  }
1588 
1589  int ncx = h->GetXaxis()->GetNbins();
1590 
1591  double sum = 0;
1592  double sum2 = 0;
1593  for (int bin = 1; bin <= ncx; ++bin)
1594  {
1595  double contents = h->GetBinContent(bin);
1596  sum += contents;
1597  }
1598  if (sum==0) return -1;
1599  double avg = sum/ncx;
1600 
1601  for (int bin = 1; bin <= ncx; ++bin)
1602  {
1603  double contents = h->GetBinContent(bin);
1604  sum2 += (contents - avg)*(contents - avg);
1605  }
1606 
1607  double Variance = TMath::Sqrt(sum2/ncx);
1608  return Variance;
1609 }
TH1F * getRefTH1F(void) const
TH2S * getTH2S(void) const
TH1S * getTH1S(void) const
double getAverage(int bin, const TH1 *h) const
Definition: QTest.cc:944
void useRMS(void)
Definition: QTest.cc:1348
float runTest(const MonitorElement *me)
Definition: QTest.cc:648
float runTest(const MonitorElement *me)
Definition: QTest.cc:973
common ppss p3p6s2 common epss epspn46 common const1 w2
Definition: inclppp.h:1
TProfile2D * getTProfile2D(void) const
float runTest(const MonitorElement *me)
Definition: QTest.cc:727
TProfile2D * getRefTProfile2D(void) const
TH3F * getTH3F(void) const
TH1D * getTH1D(void) const
#define NULL
Definition: scimark2.h:8
void setRMSRange(double xmin, double xmax)
set expected value for mean
Definition: QTest.cc:1224
void useSigma(double expectedSigma)
Definition: QTest.cc:1337
TH2D * getTH2D(void) const
double getEntries(void) const
get # of entries
TH3F * getRefTH3F(void) const
float runTest(const MonitorElement *me)
Definition: QTest.cc:394
float runTest(const MonitorElement *me)
Definition: QTest.cc:1496
T x() const
Cartesian x coordinate.
TH2F * getRefTH2F(void) const
T Abs(T a)
Definition: MathUtil.h:49
static const int DID_NOT_RUN
float runTest(const MonitorElement *me)
Definition: QTest.cc:292
static const float ERROR_PROB_THRESHOLD
Definition: QTest.h:123
Kind kind(void) const
Get the type of the monitor element.
float runTest(const MonitorElement *me)
Definition: QTest.cc:848
const std::string getFullname(void) const
get full name of ME including Pathname
TH2D * getRefTH2D(void) const
bin
set the eta bin as selection string.
void useRange(double xmin, double xmax)
Definition: QTest.cc:1327
T Max(T a, T b)
Definition: MathUtil.h:44
TObject * getRootObject(void) const
float runTest(const MonitorElement *me)
Definition: QTest.cc:163
virtual float runTest(const MonitorElement *me)
Definition: QTest.cc:27
TH1F * getTH1F(void) const
chan
lumi = TPaveText(lowX+0.38, lowY+0.061, lowX+0.45, lowY+0.161, "NDC") lumi.SetBorderSize( 0 ) lumi...
TProfile * getRefTProfile(void) const
void init(void)
initialize values
Definition: QTest.cc:17
void setMeanRange(double xmin, double xmax)
set expected value for mean
Definition: QTest.cc:1212
float runTest(const MonitorElement *me)
Definition: QTest.cc:1248
TProfile * getTProfile(void) const
TH2S * getRefTH2S(void) const
float runTest(const MonitorElement *me)
Definition: QTest.cc:40
float runTest(const MonitorElement *me)
Definition: QTest.cc:1365
TH2F * getTH2F(void) const
def fail(errstr="")
void reset(double vett[256])
Definition: TPedValues.cc:11
TObject * getRefRootObject(void) const
TH1S * getRefTH1S(void) const
float runTest(const MonitorElement *me)
Definition: QTest.cc:1554
float runTest(const MonitorElement *me)
Definition: QTest.cc:578
static const float WARNING_PROB_THRESHOLD
default "probability" values for setting warnings & errors when running tests
Definition: QTest.h:122
TH1D * getRefTH1D(void) const
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:11