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