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 #include "Math/ProbFuncMathCore.h"
10 
11 using namespace std;
12 
13 const float QCriterion::ERROR_PROB_THRESHOLD = 0.50;
14 const float QCriterion::WARNING_PROB_THRESHOLD = 0.90;
15 
16 // initialize values
17 void
19 {
20  errorProb_ = ERROR_PROB_THRESHOLD;
21  warningProb_ = WARNING_PROB_THRESHOLD;
22  setAlgoName("NO_ALGORITHM");
23  status_ = dqm::qstatus::DID_NOT_RUN;
24  message_ = "NO_MESSAGE";
25  verbose_ = 0; // 0 = silent, 1 = algorithmic failures, 2 = info
26 }
27 
28 float QCriterion::runTest(const MonitorElement * /* me */)
29 {
30  raiseDQMError("QCriterion", "virtual runTest method called" );
31  return 0.;
32 }
33 //===================================================//
34 //================ QUALITY TESTS ====================//
35 //==================================================//
36 
37 //-------------------------------------------------------//
38 //----------------- Comp2RefEqualH base -----------------//
39 //-------------------------------------------------------//
40 // run the test (result: [0, 1] or <0 for failure)
42 {
43  badChannels_.clear();
44 
45  if (!me)
46  return -1;
47  if (!me->getRootObject() || !me->getRefRootObject())
48  return -1;
49  TH1* h=nullptr; //initialize histogram pointer
50  TH1* ref_=nullptr;
51 
52  if (verbose_>1)
53  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
54  << me-> getFullname() << "\n";
55 
56  int nbins=0;
57  int nbinsref=0;
58  //-- TH1F
60  {
61  nbins = me->getTH1F()->GetXaxis()->GetNbins();
62  nbinsref = me->getRefTH1F()->GetXaxis()->GetNbins();
63  h = me->getTH1F(); // access Test histo
64  ref_ = me->getRefTH1F(); //access Ref hiso
65  if (nbins != nbinsref) return -1;
66  }
67  //-- TH1S
68  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
69  {
70  nbins = me->getTH1S()->GetXaxis()->GetNbins();
71  nbinsref = me->getRefTH1S()->GetXaxis()->GetNbins();
72  h = me->getTH1S(); // access Test histo
73  ref_ = me->getRefTH1S(); //access Ref hiso
74  if (nbins != nbinsref) return -1;
75  }
76  //-- TH1D
77  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
78  {
79  nbins = me->getTH1D()->GetXaxis()->GetNbins();
80  nbinsref = me->getRefTH1D()->GetXaxis()->GetNbins();
81  h = me->getTH1D(); // access Test histo
82  ref_ = me->getRefTH1D(); //access Ref hiso
83  if (nbins != nbinsref) return -1;
84  }
85  //-- TPROFILE
87  {
88  nbins = me->getTProfile()->GetXaxis()->GetNbins();
89  nbinsref = me->getRefTProfile()->GetXaxis()->GetNbins();
90  h = me->getTProfile(); // access Test histo
91  ref_ = me->getRefTProfile(); //access Ref hiso
92  if (nbins != nbinsref) return -1;
93  }
94 
95  //-- TH2
96  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
97  {
98  nbins = me->getTH2F()->GetXaxis()->GetNbins() *
99  me->getTH2F()->GetYaxis()->GetNbins();
100  nbinsref = me->getRefTH2F()->GetXaxis()->GetNbins() *
101  me->getRefTH2F()->GetYaxis()->GetNbins();
102  h = me->getTH2F(); // access Test histo
103  ref_ = me->getRefTH2F(); //access Ref hiso
104  if (nbins != nbinsref) return -1;
105  }
106 
107  //-- TH2
108  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
109  {
110  nbins = me->getTH2S()->GetXaxis()->GetNbins() *
111  me->getTH2S()->GetYaxis()->GetNbins();
112  nbinsref = me->getRefTH2S()->GetXaxis()->GetNbins() *
113  me->getRefTH2S()->GetYaxis()->GetNbins();
114  h = me->getTH2S(); // access Test histo
115  ref_ = me->getRefTH2S(); //access Ref hiso
116  if (nbins != nbinsref) return -1;
117  }
118 
119  //-- TH2
120  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
121  {
122  nbins = me->getTH2D()->GetXaxis()->GetNbins() *
123  me->getTH2D()->GetYaxis()->GetNbins();
124  nbinsref = me->getRefTH2D()->GetXaxis()->GetNbins() *
125  me->getRefTH2D()->GetYaxis()->GetNbins();
126  h = me->getTH2D(); // access Test histo
127  ref_ = me->getRefTH2D(); //access Ref hiso
128  if (nbins != nbinsref) return -1;
129  }
130 
131  //-- TH3
132  else if (me->kind()==MonitorElement::DQM_KIND_TH3F)
133  {
134  nbins = me->getTH3F()->GetXaxis()->GetNbins() *
135  me->getTH3F()->GetYaxis()->GetNbins() *
136  me->getTH3F()->GetZaxis()->GetNbins();
137  nbinsref = me->getRefTH3F()->GetXaxis()->GetNbins() *
138  me->getRefTH3F()->GetYaxis()->GetNbins() *
139  me->getRefTH3F()->GetZaxis()->GetNbins();
140  h = me->getTH3F(); // access Test histo
141  ref_ = me->getRefTH3F(); //access Ref hiso
142  if (nbins != nbinsref) return -1;
143  }
144 
145  else
146  {
147  if (verbose_>0)
148  std::cout << "QTest:Comp2RefEqualH"
149  << " ME does not contain TH1F/TH1S/TH1D/TH2F/TH2S/TH2D/TH3F, exiting\n";
150  return -1;
151  }
152 
153  //-- QUALITY TEST itself
154  int first = 0; // 1 //(use underflow bin)
155  int last = nbins+1; //(use overflow bin)
156  bool failure = false;
157  for (int bin=first;bin<=last;bin++)
158  {
159  double contents = h->GetBinContent(bin);
160  if (contents != ref_->GetBinContent(bin))
161  {
162  failure = true;
163  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
164  badChannels_.push_back(chan);
165  }
166  }
167  if (failure) return 0;
168  return 1;
169 }
170 
171 //-------------------------------------------------------//
172 //----------------- Comp2RefChi2 --------------------//
173 //-------------------------------------------------------//
175 {
176  if (!me)
177  return -1;
178  if (!me->getRootObject() || !me->getRefRootObject())
179  return -1;
180  TH1* h=nullptr;
181  TH1* ref_=nullptr;
182 
183  if (verbose_>1)
184  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
185  << me-> getFullname() << "\n";
186  //-- TH1F
188  {
189  h = me->getTH1F(); // access Test histo
190  ref_ = me->getRefTH1F(); //access Ref histo
191  }
192  //-- TH1S
193  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
194  {
195  h = me->getTH1S(); // access Test histo
196  ref_ = me->getRefTH1S(); //access Ref histo
197  }
198  //-- TH1D
199  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
200  {
201  h = me->getTH1D(); // access Test histo
202  ref_ = me->getRefTH1D(); //access Ref histo
203  }
204  //-- TProfile
205  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
206  {
207  h = me->getTProfile(); // access Test histo
208  ref_ = me->getRefTProfile(); //access Ref histo
209  }
210  else
211  {
212  if (verbose_>0)
213  std::cout << "QTest::Comp2RefChi2"
214  << " ME does not contain TH1F/TH1S/TH1D/TProfile, exiting\n";
215  return -1;
216  }
217 
218  //-- isInvalid ? - Check consistency in number of channels
219  int ncx1 = h->GetXaxis()->GetNbins();
220  int ncx2 = ref_->GetXaxis()->GetNbins();
221  if ( ncx1 != ncx2)
222  {
223  if (verbose_>0)
224  std::cout << "QTest:Comp2RefChi2"
225  << " different number of channels! ("
226  << ncx1 << ", " << ncx2 << "), exiting\n";
227  return -1;
228  }
229 
230  //-- QUALITY TEST itself
231  //reset Results
232  Ndof_ = 0; chi2_ = -1.; ncx1 = ncx2 = -1;
233 
234  int i, i_start, i_end;
235  double chi2 = 0.; int ndof = 0; int constraint = 0;
236 
237  i_start = 1;
238  i_end = ncx1;
239  // if (fXaxis.TestBit(TAxis::kAxisRange)) {
240  i_start = h->GetXaxis()->GetFirst();
241  i_end = h->GetXaxis()->GetLast();
242  // }
243  ndof = i_end-i_start+1-constraint;
244 
245  //Compute the normalisation factor
246  double sum1=0, sum2=0;
247  for (i=i_start; i<=i_end; i++)
248  {
249  sum1 += h->GetBinContent(i);
250  sum2 += ref_->GetBinContent(i);
251  }
252 
253  //check that the histograms are not empty
254  if (sum1 == 0)
255  {
256  if (verbose_>0)
257  std::cout << "QTest:Comp2RefChi2"
258  << " Test Histogram " << h->GetName()
259  << " is empty, exiting\n";
260  return -1;
261  }
262  if (sum2 == 0)
263  {
264  if (verbose_>0)
265  std::cout << "QTest:Comp2RefChi2"
266  << " Ref Histogram " << ref_->GetName()
267  << " is empty, exiting\n";
268  return -1;
269  }
270 
271  double bin1, bin2, err1, err2, temp;
272  for (i=i_start; i<=i_end; i++)
273  {
274  bin1 = h->GetBinContent(i)/sum1;
275  bin2 = ref_->GetBinContent(i)/sum2;
276  if (bin1 ==0 && bin2==0)
277  {
278  --ndof; //no data means one less degree of freedom
279  }
280  else
281  {
282  temp = bin1-bin2;
283  err1=h->GetBinError(i); err2=ref_->GetBinError(i);
284  if (err1 == 0 && err2 == 0)
285  {
286  if (verbose_>0)
287  std::cout << "QTest:Comp2RefChi2"
288  << " bins with non-zero content and zero error, exiting\n";
289  return -1;
290  }
291  err1*=err1 ; err2*=err2;
292  err1/=sum1*sum1 ; err2/=sum2*sum2;
293  chi2 +=temp*temp/(err1+err2);
294  }
295  }
296  chi2_ = chi2; Ndof_ = ndof;
297  return TMath::Prob(0.5*chi2, int(0.5*ndof));
298 }
299 
300 //-------------------------------------------------------//
301 //----------------- Comp2Ref2DChi2 ---------------------//
302 //-------------------------------------------------------//
304 {
305  if (!me)
306  return -1;
307  if (!me->getRootObject() || !me->getRefRootObject())
308  return -1;
309  if (minEntries_ != 0 && me->getEntries() < minEntries_)
310  return -1;
311 
312  TH2* h=nullptr;
313  TH2* ref_=nullptr;
314 
315  if (verbose_>1)
316  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
317  << me-> getFullname() << "\n";
318  //-- TH2F
320  {
321  h = me->getTH2F(); // access Test histo
322  ref_ = me->getRefTH2F(); //access Ref histo
323  }
324  //-- TH2S
325  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
326  {
327  h = me->getTH2S(); // access Test histo
328  ref_ = me->getRefTH2S(); //access Ref histo
329  }
330  //-- TH2D
331  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
332  {
333  h = me->getTH2D(); // access Test histo
334  ref_ = me->getRefTH2D(); //access Ref histo
335  }
336  //-- TProfile
338  {
339  h = me->getTProfile2D(); // access Test histo
340  ref_ = me->getRefTProfile2D(); //access Ref histo
341  }
342  else
343  {
344  if (verbose_>0)
345  std::cout << "QTest::Comp2Ref2DChi2"
346  << " ME does not contain TH2F/TH2S/TH2D/TProfile2D, exiting\n";
347  return -1;
348  }
349 
350  //-- isInvalid ? - Check consistency in number of channels
351  int ncx1 = h->GetXaxis()->GetNbins();
352  int ncx2 = ref_->GetXaxis()->GetNbins();
353  int ncy1 = h->GetYaxis()->GetNbins();
354  int ncy2 = ref_->GetYaxis()->GetNbins();
355  if ( ( ncx1 != ncx2) || ( ncy1 != ncy2) )
356  {
357  if (verbose_>0)
358  std::cout << "QTest:Comp2Ref2DChi2"
359  << " different number of channels! ("
360  << ncx1 << ", " << ncx2 << "), ("
361  << ncy1 << ", " << ncy2 << "), exiting\n";
362  return -1;
363  }
364 
365  //-- QUALITY TEST itself
366  //reset Results
367  Ndof_ = 0; chi2_ = -1.;
368 
369  //check that the histograms are not empty
370  int i_start = h->GetXaxis()->GetFirst();
371  int i_end = h->GetXaxis()->GetLast();
372  int j_start = h->GetYaxis()->GetFirst();
373  int j_end = h->GetYaxis()->GetLast();
374  if (h->Integral(i_start, i_end, j_start, j_end) == 0)
375  {
376  if (verbose_>0)
377  std::cout << "QTest:Comp2Ref2DChi2"
378  << " Test Histogram " << h->GetName()
379  << " is empty, exiting\n";
380  return -1;
381  }
382  if (ref_->Integral(i_start, i_end, j_start, j_end) == 0)
383  {
384  if (verbose_>0)
385  std::cout << "QTest:Comp2Ref2DChi2"
386  << " Ref Histogram " << ref_->GetName()
387  << " is empty, exiting\n";
388  return -1;
389  }
390 
391  //use the chi2 test for 2D histograms defined in ROOT
392  int igood = 0;
393  double pValue = h->Chi2TestX(ref_, chi2_, Ndof_, igood, "");
394 
395  if (chi2_==-1. && Ndof_==0)
396  return -1;
397 
398  return pValue;
399 }
400 
401 //-------------------------------------------------------//
402 //----------------- Comp2RefKolmogorov --------------//
403 //-------------------------------------------------------//
404 
406 {
407  const double difprec = 1e-5;
408 
409  if (!me)
410  return -1;
411  if (!me->getRootObject() || !me->getRefRootObject())
412  return -1;
413  TH1* h=nullptr;
414  TH1* ref_=nullptr;
415 
416  if (verbose_>1)
417  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
418  << me-> getFullname() << "\n";
419  //-- TH1F
421  {
422  h = me->getTH1F(); // access Test histo
423  ref_ = me->getRefTH1F(); //access Ref histo
424  }
425  //-- TH1S
426  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
427  {
428  h = me->getTH1S(); // access Test histo
429  ref_ = me->getRefTH1S(); //access Ref histo
430  }
431  //-- TH1D
432  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
433  {
434  h = me->getTH1D(); // access Test histo
435  ref_ = me->getRefTH1D(); //access Ref histo
436  }
437  //-- TProfile
438  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
439  {
440  h = me->getTProfile(); // access Test histo
441  ref_ = me->getRefTProfile(); //access Ref histo
442  }
443  else
444  {
445  if (verbose_>0)
446  std::cout << "QTest:Comp2RefKolmogorov"
447  << " ME does not contain TH1F/TH1S/TH1D/TProfile, exiting\n";
448  return -1;
449  }
450 
451  //-- isInvalid ? - Check consistency in number of channels
452  int ncx1 = h->GetXaxis()->GetNbins();
453  int ncx2 = ref_->GetXaxis()->GetNbins();
454  if ( ncx1 != ncx2)
455  {
456  if (verbose_>0)
457  std::cout << "QTest:Comp2RefKolmogorov"
458  << " different number of channels! ("
459  << ncx1 << ", " << ncx2 << "), exiting\n";
460  return -1;
461  }
462  //-- isInvalid ? - Check consistency in channel edges
463  double diff1 = std::abs(h->GetXaxis()->GetXmin() - ref_->GetXaxis()->GetXmin());
464  double diff2 = std::abs(h->GetXaxis()->GetXmax() - ref_->GetXaxis()->GetXmax());
465  if (diff1 > difprec || diff2 > difprec)
466  {
467  if (verbose_>0)
468  std::cout << "QTest:Comp2RefKolmogorov"
469  << " histograms with different binning, exiting\n";
470  return -1;
471  }
472 
473  //-- QUALITY TEST itself
474  Bool_t afunc1 = kFALSE; Bool_t afunc2 = kFALSE;
475  double sum1 = 0, sum2 = 0;
476  double ew1, ew2, w1 = 0, w2 = 0;
477  int bin;
478  for (bin=1;bin<=ncx1;bin++)
479  {
480  sum1 += h->GetBinContent(bin);
481  sum2 += ref_->GetBinContent(bin);
482  ew1 = h->GetBinError(bin);
483  ew2 = ref_->GetBinError(bin);
484  w1 += ew1*ew1;
485  w2 += ew2*ew2;
486  }
487 
488  if (sum1 == 0)
489  {
490  if (verbose_>0)
491  std::cout << "QTest:Comp2RefKolmogorov"
492  << " Test Histogram: " << h->GetName()
493  << ": integral is zero, exiting\n";
494  return -1;
495  }
496  if (sum2 == 0)
497  {
498  if (verbose_>0)
499  std::cout << "QTest:Comp2RefKolmogorov"
500  << " Ref Histogram: " << ref_->GetName()
501  << ": integral is zero, exiting\n";
502  return -1;
503  }
504 
505  double tsum1 = sum1; double tsum2 = sum2;
506  tsum1 += h->GetBinContent(0);
507  tsum2 += ref_->GetBinContent(0);
508  tsum1 += h->GetBinContent(ncx1+1);
509  tsum2 += ref_->GetBinContent(ncx1+1);
510 
511  // Check if histograms are weighted.
512  // If number of entries = number of channels, probably histograms were
513  // not filled via Fill(), but via SetBinContent()
514  double ne1 = h->GetEntries();
515  double ne2 = ref_->GetEntries();
516  // look at first histogram
517  double difsum1 = (ne1-tsum1)/tsum1;
518  double esum1 = sum1;
519  if (difsum1 > difprec && int(ne1) != ncx1)
520  {
521  if (h->GetSumw2N() == 0)
522  {
523  if (verbose_>0)
524  std::cout << "QTest:Comp2RefKolmogorov"
525  << " Weighted events and no Sumw2 for "
526  << h->GetName() << "\n";
527  }
528  else
529  {
530  esum1 = sum1*sum1/w1; //number of equivalent entries
531  }
532  }
533  // look at second histogram
534  double difsum2 = (ne2-tsum2)/tsum2;
535  double esum2 = sum2;
536  if (difsum2 > difprec && int(ne2) != ncx1)
537  {
538  if (ref_->GetSumw2N() == 0)
539  {
540  if (verbose_>0)
541  std::cout << "QTest:Comp2RefKolmogorov"
542  << " Weighted events and no Sumw2 for "
543  << ref_->GetName() << "\n";
544  }
545  else
546  {
547  esum2 = sum2*sum2/w2; //number of equivalent entries
548  }
549  }
550 
551  double s1 = 1/tsum1; double s2 = 1/tsum2;
552  // Find largest difference for Kolmogorov Test
553  double dfmax =0, rsum1 = 0, rsum2 = 0;
554  // use underflow bin
555  int first = 0; // 1
556  // use overflow bin
557  int last = ncx1+1; // ncx1
558  for ( bin=first; bin<=last; bin++)
559  {
560  rsum1 += s1*h->GetBinContent(bin);
561  rsum2 += s2*ref_->GetBinContent(bin);
562  dfmax = TMath::Max(dfmax,std::abs(rsum1-rsum2));
563  }
564 
565  // Get Kolmogorov probability
566  double z = 0;
567  if (afunc1) z = dfmax*TMath::Sqrt(esum2);
568  else if (afunc2) z = dfmax*TMath::Sqrt(esum1);
569  else z = dfmax*TMath::Sqrt(esum1*esum2/(esum1+esum2));
570 
571  // This numerical error condition should never occur:
572  if (std::abs(rsum1-1) > 0.002)
573  if (verbose_>0)
574  std::cout << "QTest:Comp2RefKolmogorov"
575  << " Numerical problems with histogram "
576  << h->GetName() << "\n";
577  if (std::abs(rsum2-1) > 0.002)
578  if (verbose_>0)
579  std::cout << "QTest:Comp2RefKolmogorov"
580  << " Numerical problems with histogram "
581  << ref_->GetName() << "\n";
582 
583  return TMath::KolmogorovProb(z);
584 }
585 
586 //----------------------------------------------------//
587 //--------------- ContentsXRange ---------------------//
588 //----------------------------------------------------//
590 {
591  badChannels_.clear();
592 
593  if (!me)
594  return -1;
595  if (!me->getRootObject())
596  return -1;
597  TH1* h=nullptr;
598 
599  if (verbose_>1)
600  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
601  << me-> getFullname() << "\n";
602  // -- TH1F
603  if (me->kind()==MonitorElement::DQM_KIND_TH1F )
604  {
605  h = me->getTH1F();
606  }
607  // -- TH1S
608  else if ( me->kind()==MonitorElement::DQM_KIND_TH1S )
609  {
610  h = me->getTH1S();
611  }
612  // -- TH1D
613  else if ( me->kind()==MonitorElement::DQM_KIND_TH1D )
614  {
615  h = me->getTH1D();
616  }
617  else
618  {
619  if (verbose_>0) std::cout << "QTest:ContentsXRange"
620  << " ME " << me->getFullname()
621  << " does not contain TH1F/TH1S/TH1D, exiting\n";
622  return -1;
623  }
624 
625  if (!rangeInitialized_)
626  {
627  if ( h->GetXaxis() )
628  setAllowedXRange(h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
629  else
630  return -1;
631  }
632  int ncx = h->GetXaxis()->GetNbins();
633  // use underflow bin
634  int first = 0; // 1
635  // use overflow bin
636  int last = ncx+1; // ncx
637  // all entries
638  double sum = 0;
639  // entries outside X-range
640  double fail = 0;
641  int bin;
642  for (bin = first; bin <= last; ++bin)
643  {
644  double contents = h->GetBinContent(bin);
645  double x = h->GetBinCenter(bin);
646  sum += contents;
647  if (x < xmin_ || x > xmax_)fail += contents;
648  }
649 
650  if (sum==0) return 1;
651  // return fraction of entries within allowed X-range
652  return (sum - fail)/sum;
653 
654 }
655 
656 //-----------------------------------------------------//
657 //--------------- ContentsYRange ---------------------//
658 //----------------------------------------------------//
660 {
661  badChannels_.clear();
662 
663  if (!me)
664  return -1;
665  if (!me->getRootObject())
666  return -1;
667  TH1* h=nullptr;
668 
669  if (verbose_>1)
670  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
671  << me-> getFullname() << "\n";
672 
674  {
675  h = me->getTH1F(); //access Test histo
676  }
677  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
678  {
679  h = me->getTH1S(); //access Test histo
680  }
681  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
682  {
683  h = me->getTH1D(); //access Test histo
684  }
685  else
686  {
687  if (verbose_>0)
688  std::cout << "QTest:ContentsYRange"
689  << " ME " << me->getFullname()
690  << " does not contain TH1F/TH1S/TH1D, exiting\n";
691  return -1;
692  }
693 
694  if (!rangeInitialized_ || !h->GetXaxis()) return 1; // all bins are accepted if no initialization
695  int ncx = h->GetXaxis()->GetNbins();
696  // do NOT use underflow bin
697  int first = 1;
698  // do NOT use overflow bin
699  int last = ncx;
700  // bins outside Y-range
701  int fail = 0;
702  int bin;
703 
704  if (useEmptyBins_)
705  {
706  for (bin = first; bin <= last; ++bin)
707  {
708  double contents = h->GetBinContent(bin);
709  bool failure = false;
710  failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
711  if (failure)
712  {
713  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
714  badChannels_.push_back(chan);
715  ++fail;
716  }
717  }
718  // return fraction of bins that passed test
719  return 1.*(ncx - fail)/ncx;
720  }
721  else
722  {
723  for (bin = first; bin <= last; ++bin)
724  {
725  double contents = h->GetBinContent(bin);
726  bool failure = false;
727  if (contents) failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
728  if (failure) ++fail;
729  }
730  // return fraction of bins that passed test
731  return 1.*(ncx - fail)/ncx;
732  }
733 }
734 
735 //-----------------------------------------------------//
736 //------------------ DeadChannel ---------------------//
737 //----------------------------------------------------//
739 {
740  badChannels_.clear();
741  if (!me)
742  return -1;
743  if (!me->getRootObject())
744  return -1;
745  TH1* h1=nullptr;
746  TH2* h2=nullptr;//initialize histogram pointers
747 
748  if (verbose_>1)
749  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
750  << me-> getFullname() << "\n";
751  //TH1F
753  {
754  h1 = me->getTH1F(); //access Test histo
755  }
756  //TH1S
757  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
758  {
759  h1 = me->getTH1S(); //access Test histo
760  }
761  //TH1D
762  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
763  {
764  h1 = me->getTH1D(); //access Test histo
765  }
766  //-- TH2F
767  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
768  {
769  h2 = me->getTH2F(); // access Test histo
770  }
771  //-- TH2S
772  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
773  {
774  h2 = me->getTH2S(); // access Test histo
775  }
776  //-- TH2D
777  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
778  {
779  h2 = me->getTH2D(); // access Test histo
780  }
781  else
782  {
783  if (verbose_>0)
784  std::cout << "QTest:DeadChannel"
785  << " ME " << me->getFullname()
786  << " does not contain TH1F/TH1S/TH1D/TH2F/TH2S/TH2D, exiting\n";
787  return -1;
788  }
789 
790  int fail = 0; // number of failed channels
791 
792  //--------- do the quality test for 1D histo ---------------//
793  if (h1 != nullptr)
794  {
795  if (!rangeInitialized_ || !h1->GetXaxis() )
796  return 1; // all bins are accepted if no initialization
797  int ncx = h1->GetXaxis()->GetNbins();
798  int first = 1;
799  int last = ncx;
800  int bin;
801 
803  for (bin = first; bin <= last; ++bin)
804  {
805  double contents = h1->GetBinContent(bin);
806  bool failure = false;
807  failure = contents <= ymin_; // dead channel: equal to or less than ymin_
808  if (failure)
809  {
810  DQMChannel chan(bin, 0, 0, contents, h1->GetBinError(bin));
811  badChannels_.push_back(chan);
812  ++fail;
813  }
814  }
815  //return fraction of alive channels
816  return 1.*(ncx - fail)/ncx;
817  }
818  //----------------------------------------------------------//
819 
820  //--------- do the quality test for 2D -------------------//
821  else if (h2 !=nullptr )
822  {
823  int ncx = h2->GetXaxis()->GetNbins(); // get X bins
824  int ncy = h2->GetYaxis()->GetNbins(); // get Y bins
825 
827  for (int cx = 1; cx <= ncx; ++cx)
828  {
829  for (int cy = 1; cy <= ncy; ++cy)
830  {
831  double contents = h2->GetBinContent(h2->GetBin(cx, cy));
832  bool failure = false;
833  failure = contents <= ymin_; // dead channel: equal to or less than ymin_
834  if (failure)
835  {
836  DQMChannel chan(cx, cy, 0, contents, h2->GetBinError(h2->GetBin(cx, cy)));
837  badChannels_.push_back(chan);
838  ++fail;
839  }
840  }
841  }
842  //return fraction of alive channels
843  return 1.*(ncx*ncy - fail) / (ncx*ncy);
844  }
845  else
846  {
847  if (verbose_>0)
848  std::cout << "QTest:DeadChannel"
849  << " TH1/TH2F are NULL, exiting\n";
850  return -1;
851  }
852 }
853 
854 //-----------------------------------------------------//
855 //---------------- NoisyChannel ---------------------//
856 //----------------------------------------------------//
857 // run the test (result: fraction of channels not appearing noisy or "hot")
858 // [0, 1] or <0 for failure
860 {
861  badChannels_.clear();
862  if (!me)
863  return -1;
864  if (!me->getRootObject())
865  return -1;
866  TH1* h=nullptr;//initialize histogram pointer
867  TH2* h2=nullptr;//initialize histogram pointer
868 
869  if (verbose_>1)
870  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
871  << me-> getFullname() << "\n";
872 
873  int nbins=0;
874  int nbinsX=0, nbinsY=0;
875  //-- TH1F
877  {
878  nbins = me->getTH1F()->GetXaxis()->GetNbins();
879  h = me->getTH1F(); // access Test histo
880  }
881  //-- TH1S
882  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
883  {
884  nbins = me->getTH1S()->GetXaxis()->GetNbins();
885  h = me->getTH1S(); // access Test histo
886  }
887  //-- TH1D
888  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
889  {
890  nbins = me->getTH1D()->GetXaxis()->GetNbins();
891  h = me->getTH1D(); // access Test histo
892  }
893  //-- TH2
894  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
895  {
896  nbinsX = me->getTH2F()->GetXaxis()->GetNbins();
897  nbinsY = me->getTH2F()->GetYaxis()->GetNbins();
898  h2 = me->getTH2F(); // access Test histo
899  }
900  //-- TH2
901  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
902  {
903  nbinsX = me->getTH2S()->GetXaxis()->GetNbins();
904  nbinsY = me->getTH2S()->GetYaxis()->GetNbins();
905  h2 = me->getTH2S(); // access Test histo
906  }
907  //-- TH2
908  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
909  {
910  nbinsX = me->getTH2F()->GetXaxis()->GetNbins();
911  nbinsY = me->getTH2F()->GetYaxis()->GetNbins();
912  h2 = me->getTH2D(); // access Test histo
913  }
914  else
915  {
916  if (verbose_>0)
917  std::cout << "QTest:NoisyChannel"
918  << " ME " << me->getFullname()
919  << " does not contain TH1F/TH1S/TH1D or TH2F/TH2S/TH2D, exiting\n";
920  return -1;
921  }
922 
923  //-- QUALITY TEST itself
924 
925  // do NOT use underflow bin
926  int first = 1;
927  // do NOT use overflow bin
928  int last = nbins;
929  int lastX = nbinsX, lastY = nbinsY;
930  // bins outside Y-range
931  int fail = 0;
932  int bin;
933  int binX, binY;
934  if (h != nullptr) {
935  if ( !rangeInitialized_ || !h->GetXaxis() ){
936  return 1; // all channels are accepted if tolerance has not been set
937  }
938  for (bin = first; bin <= last; ++bin)
939  {
940  double contents = h->GetBinContent(bin);
941  double average = getAverage(bin, h);
942  bool failure = false;
943  if (average != 0)
944  failure = (((contents-average)/std::abs(average)) > tolerance_);
945 
946  if (failure)
947  {
948  ++fail;
949  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
950  badChannels_.push_back(chan);
951  }
952  }
953 
954  // return fraction of bins that passed test
955  return 1.*(nbins - fail)/nbins;
956  }
957  else if (h2 !=nullptr ) {
958  for (binY = first; binY <= lastY; ++binY) {
959  for (binX = first; binX <= lastX; ++binX) {
960  double contents = h2->GetBinContent(binX, binY);
961  double average = getAverage2D(binX, binY, h2);
962  bool failure = false;
963  if (average != 0)
964  failure = (((contents-average)/std::abs(average)) > tolerance_);
965  if (failure)
966  {
967  ++fail;
968  DQMChannel chan(binX, 0, 0, contents, h2->GetBinError(binX));
969  badChannels_.push_back(chan);
970  }
971  }//end x loop
972  }//end y loop
973  // return fraction of bins that passed test
974  return 1.*((nbinsX * nbinsY) - fail)/(nbinsX * nbinsY);
975  }//end nullptr conditional
976  else
977  {
978  if (verbose_>0)
979  std::cout << "QTest:NoisyChannel"
980  << " TH1/TH2F are NULL, exiting\n";
981  return -1;
982  }
983 }
984 
985 // get average for bin under consideration
986 // (see description of method setNumNeighbors)
987 double NoisyChannel::getAverage(int bin, const TH1 *h) const
988 {
989  int first = 1; // Do NOT use underflow bin
990  int ncx = h->GetXaxis()->GetNbins(); // Do NOT use overflow bin
991  double sum = 0;
992  int bin_start, bin_end;
993  int add_right = 0;
994  int add_left = 0;
995 
996  bin_start = bin - numNeighbors_; // First bin in integral
997  bin_end = bin + numNeighbors_; // Last bin in integral
998 
999  if (bin_start < first) { // If neighbors take you outside of histogram range shift integral right
1000  add_right = first - bin_start; // How much to shift remembering we are not using underflow
1001  bin_start = first; // Remember to reset the starting bin
1002  bin_end += add_right;
1003  if (bin_end > ncx) bin_end = ncx; // If the test would be larger than histogram just sum histogram without overflow
1004  }
1005 
1006  if (bin_end > ncx) { // Now we make sure doesn't run off right edge of histogram
1007  add_left = bin_end - ncx;
1008  bin_end = ncx;
1009  bin_start -= add_left;
1010  if (bin_start < first) bin_start = first; // If the test would be larger than histogram just sum histogram without underflow
1011  }
1012 
1013  sum += h->Integral(bin_start, bin_end);
1014  sum -= h->GetBinContent(bin);
1015 
1016  int dimension = 2 * numNeighbors_ + 1;
1017  if ( dimension > h->GetNbinsX() ) dimension = h->GetNbinsX();
1018 
1019  return sum / (dimension - 1);
1020 }
1021 
1022 double NoisyChannel::getAverage2D(int binX, int binY, const TH2 *h2) const
1023 {
1025  int firstX = 1;
1026  int firstY = 1;
1027  double sum = 0;
1028  int ncx = h2->GetXaxis()->GetNbins();
1029  int ncy = h2->GetYaxis()->GetNbins();
1030 
1031  int neighborsX, neighborsY; // Convert unsigned input to int so we can use comparators
1032  neighborsX = numNeighbors_;
1033  neighborsY = numNeighbors_;
1034  int bin_startX, bin_endX;
1035  int add_rightX = 0; // Start shifts at 0
1036  int add_leftX = 0;
1037  int bin_startY, bin_endY;
1038  int add_topY = 0;
1039  int add_downY = 0;
1040 
1041  bin_startX = binX - neighborsX; // First bin in X
1042  bin_endX = binX + neighborsX; // Last bin in X
1043 
1044  if (bin_startX < firstX) { // If neighbors take you outside of histogram range shift integral right
1045  add_rightX = firstX - bin_startX; // How much to shift remembering we are no using underflow
1046  bin_startX = firstX; // Remember to reset the starting bin
1047  bin_endX += add_rightX;
1048  if (bin_endX > ncx) bin_endX = ncx;
1049  }
1050 
1051  if (bin_endX > ncx) { // Now we make sure doesn't run off right edge of histogram
1052  add_leftX = bin_endX - ncx;
1053  bin_endX = ncx;
1054  bin_startX -= add_leftX;
1055  if (bin_startX < firstX) bin_startX = firstX; // If the test would be larger than histogram just sum histogram without underflow
1056  }
1057 
1058  bin_startY = binY - neighborsY; // First bin in Y
1059  bin_endY = binY + neighborsY; // Last bin in Y
1060 
1061  if (bin_startY < firstY) { // If neighbors take you outside of histogram range shift integral up
1062  add_topY = firstY - bin_startY; // How much to shift remembering we are no using underflow
1063  bin_startY = firstY; // Remember to reset the starting bin
1064  bin_endY += add_topY;
1065  if (bin_endY > ncy) bin_endY = ncy;
1066  }
1067 
1068  if (bin_endY > ncy){ // Now we make sure doesn't run off top edge of histogram
1069  add_downY = bin_endY - ncy;
1070  bin_endY = ncy;
1071  bin_startY -= add_downY;
1072  if (bin_startY < firstY) bin_startY = firstY; // If the test would be larger than histogram just sum histogram without underflow
1073  }
1074 
1075  sum += h2->Integral(bin_startX, bin_endX, bin_startY, bin_endY);
1076  sum -= h2->GetBinContent(binX, binY);
1077 
1078  int dimensionX = 2 * neighborsX + 1;
1079  int dimensionY = 2 * neighborsY + 1;
1080 
1081  if ( dimensionX > h2->GetNbinsX() ) dimensionX = h2->GetNbinsX();
1082  if ( dimensionY > h2->GetNbinsY() ) dimensionY = h2->GetNbinsY();
1083 
1084  return sum / (dimensionX * dimensionY - 1); // Average is sum over the # of bins used
1085 
1086 } // End getAverage2D
1087 
1088 //-----------------------------------------------------//
1089 //-----Content Sigma (Emma Yeager and Chad Freer)------//
1090 //----------------------------------------------------//
1091 // run the test (result: fraction of channels with sigma that is not noisy or hot)
1092 
1094 {
1095  badChannels_.clear();
1096  if (!me)
1097  return -1;
1098  if (!me->getRootObject())
1099  return -1;
1100  TH1* h=nullptr;//initialize histogram pointer
1101 
1102  if (verbose_>1)
1103  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1104  << me-> getFullname() << "\n";
1105 
1106  unsigned nbinsX;
1107  unsigned nbinsY;
1108 
1109  //-- TH1F
1111  {
1112  nbinsX = me->getTH1F()->GetXaxis()->GetNbins();
1113  nbinsY = me->getTH1F()->GetYaxis()->GetNbins();
1114  h = me->getTH1F(); // access Test histo
1115  }
1116  //-- TH1S
1117  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
1118  {
1119  nbinsX = me->getTH1S()->GetXaxis()->GetNbins();
1120  nbinsY = me->getTH1S()->GetYaxis()->GetNbins();
1121  h = me->getTH1S(); // access Test histo
1122  }
1123  //-- TH1D
1124  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
1125  {
1126  nbinsX = me->getTH1D()->GetXaxis()->GetNbins();
1127  nbinsY = me->getTH1D()->GetYaxis()->GetNbins();
1128  h = me->getTH1D(); // access Test histo
1129  }
1130  //-- TH2
1131  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
1132  {
1133  nbinsX = me->getTH2F()->GetXaxis()->GetNbins();
1134  nbinsY = me->getTH2F()->GetYaxis()->GetNbins();
1135  h = me->getTH2F(); // access Test histo
1136  }
1137  //-- TH2
1138  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
1139  {
1140  nbinsX = me->getTH2S()->GetXaxis()->GetNbins();
1141  nbinsY = me->getTH2S()->GetYaxis()->GetNbins();
1142  h = me->getTH2S(); // access Test histo
1143  }
1144  //-- TH2
1145  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
1146  {
1147  nbinsX = me->getTH2D()->GetXaxis()->GetNbins();
1148  nbinsY = me->getTH2D()->GetYaxis()->GetNbins();
1149  h = me->getTH2D(); // access Test histo
1150  }
1151  else
1152  {
1153  if (verbose_>0)
1154  std::cout << "QTest:ContentSigma"
1155  << " ME " << me->getFullname()
1156  << " does not contain TH1F/TH1S/TH1D or TH2F/TH2S/TH2D, exiting\n";
1157  return -1;
1158  }
1159 
1160  //-- QUALITY TEST itself
1161 
1162  if ( !rangeInitialized_ || !h->GetXaxis() )
1163  return 1; // all channels are accepted if tolerance has not been set
1164 
1165  int fail = 0; // initialize bin failure count
1166  unsigned xMin = 1; //initialize minimums and maximums with expected values
1167  unsigned yMin =1;
1168  unsigned xMax = nbinsX;
1169  unsigned yMax = nbinsY;
1170  unsigned XBlocks = numXblocks_; //Initialize xml inputs blocks and neighbors
1171  unsigned YBlocks = numYblocks_;
1172  unsigned neighborsX = numNeighborsX_;
1173  unsigned neighborsY = numNeighborsY_;
1174  unsigned Xbinnum = 1;
1175  unsigned Ybinnum =1;
1176  unsigned XWidth = 0;
1177  unsigned YWidth = 0;
1178 
1179  if (neighborsX==999){
1180  neighborsX=0;
1181  }
1182  if (neighborsY==999){
1183  neighborsY=0;
1184  }
1185 
1186  if (xMin_ != 0 && xMax_ != 0) { //give users option for automatic mininum and maximum selection by inputting 0 to any of the parameters
1187  // check that user's parameters are completely in agreement with histogram
1188  // for instance, if inputted xMax is out of range xMin will automatically be ignored
1189  if ((xMax_ <= nbinsX) && (xMin_ <= xMax_)) { // rescale area of histogram being analyzed
1190  nbinsX = xMax_ - xMin_ + 1;
1191  xMax = xMax_; // do NOT use overflow bin
1192  xMin = xMin_; // do NOT use underflow bin
1193  }
1194  }
1195  if (yMin_ != 0 && yMax_ != 0) { //give users option for automatic mininum and maximum selection by inputting 0 to any of the parameters
1196  if ((yMax_ <= nbinsY) && (yMin_ <= yMax_)) {
1197  nbinsY = yMax_ - yMin_ + 1;
1198  yMax = yMax_;
1199  yMin = yMin_;
1200  }
1201  }
1202 
1203  if (neighborsX*2 >= nbinsX) { //make sure neighbor check does not overlap with bin under consideration
1204  if (nbinsX%2 == 0) {
1205  neighborsX = nbinsX/2 - 1; //set neighbors for no overlap
1206  }
1207  else { neighborsX = (nbinsX - 1)/2; }
1208  }
1209 
1210  if (neighborsY*2 >= nbinsY) {
1211  if (nbinsY%2 == 0) {
1212  neighborsY = nbinsY/2 - 1;
1213  }
1214  else { neighborsY = (nbinsY - 1)/2; }
1215  }
1216 
1217  if (XBlocks==999){ //Setting 999 prevents blocks and does quality tests by bins only
1218  XBlocks=nbinsX;
1219  }
1220  if (YBlocks==999){
1221  YBlocks=nbinsY;
1222  }
1223 
1224  Xbinnum = nbinsX/XBlocks;
1225  Ybinnum = nbinsY/YBlocks;
1226  for (unsigned groupx=0; groupx<XBlocks; ++groupx){ //Test over all the blocks
1227  for (unsigned groupy=0; groupy<YBlocks; ++groupy){
1228 
1229  double blocksum = 0;
1230  for (unsigned binx=0; binx<Xbinnum; ++binx){ //Sum the contents of the block in question
1231  for (unsigned biny=0; biny<Ybinnum; ++biny){
1232  if (groupx*Xbinnum+xMin+binx<=xMax && groupy*Ybinnum+yMin+biny<=yMax){
1233  blocksum += abs(h->GetBinContent(groupx*Xbinnum+xMin+binx,groupy*Ybinnum+yMin+biny));
1234  }
1235  }
1236  }
1237 
1238  double sum = getNeighborSum(groupx, groupy, XBlocks, YBlocks, neighborsX, neighborsY, h);
1239  sum -= blocksum; //remove center block to test
1240 
1241  if (neighborsX>groupx){ //Find correct average at the edges
1242  XWidth = neighborsX + groupx + 1;
1243  }else if (neighborsX>(XBlocks-(groupx+1))){
1244  XWidth = (XBlocks-groupx)+neighborsX;
1245  }else {
1246  XWidth = 2*neighborsX+1;
1247  }
1248  if (neighborsY>groupy){
1249  YWidth = neighborsY + groupy + 1;
1250  }else if (neighborsY>(YBlocks-(groupy+1))){
1251  YWidth = (YBlocks-groupy)+neighborsY;
1252  }else {
1253  YWidth = 2*neighborsY+1;
1254  }
1255 
1256  double average = sum/(XWidth*YWidth - 1);
1257  double sigma = getNeighborSigma(average, groupx, groupy, XBlocks, YBlocks, neighborsX, neighborsY, h);
1258  sigma -= (average-blocksum) * (average-blocksum); //get rid of block being tested just like we did with the average
1259  double sigma_2 = sqrt(sigma)/sqrt(XWidth*YWidth - 2); //N-1 where N=XWidth*YWidth - 1
1260  double sigma_real = sigma_2/(XWidth*YWidth - 1);
1261  //double avg_uncrt = average*sqrt(sum)/sum;//Obsolete now(Chad Freer)
1262  double avg_uncrt = 3*sigma_real;
1263 
1264  double probNoisy = ROOT::Math::poisson_cdf_c(blocksum - 1, average + avg_uncrt);
1265  double probDead = ROOT::Math::poisson_cdf(blocksum, average - avg_uncrt);
1266  double thresholdNoisy = ROOT::Math::normal_cdf_c(toleranceNoisy_);
1267  double thresholdDead = ROOT::Math::normal_cdf(-1 * toleranceDead_);
1268 
1269  int failureNoisy = 0;
1270  int failureDead = 0;
1271 
1272  if (average != 0){
1273  if (noisy_ && dead_) {
1274  if (blocksum > average) {
1275  failureNoisy = probNoisy < thresholdNoisy;
1276  }else {
1277  failureDead = probDead < thresholdDead;
1278  }
1279  }else if (noisy_) {
1280  if (blocksum > average) {
1281  failureNoisy = probNoisy < thresholdNoisy;
1282  }
1283  }else if (dead_) {
1284  if (blocksum < average) {
1285  failureDead = probDead < thresholdDead;
1286  }
1287  }else { std::cout<<"No test type selected!\n"; }
1288  //Following lines useful for debugging using verbose (Chad Freer)
1289  //string histName = h->GetName();
1290  //if (histName == "emtfTrackBX") {
1291  // std::printf("Chad says: %i XBlocks, %i XBlocks, %f Blocksum, %f Average", XBlocks,YBlocks,blocksum,average);}
1292  }
1293 
1294  if (failureNoisy || failureDead) {
1295  ++fail;
1296  //DQMChannel chan(groupx*Xbinnum+xMin+binx, 0, 0, blocksum, h->GetBinError(groupx*Xbinnum+xMin+binx));
1297  //badChannels_.push_back(chan);
1298  }
1299  }
1300  }
1301  return 1.*((XBlocks*YBlocks)-fail)/(XBlocks*YBlocks);
1302 }
1303 
1304 
1305 //Gets the sum of the bins surrounding the block to be tested (Chad Freer)
1306 double ContentSigma::getNeighborSum(unsigned groupx, unsigned groupy, unsigned Xblocks, unsigned Yblocks, unsigned neighborsX, unsigned neighborsY, const TH1 *h) const {
1307  double sum = 0;
1308  unsigned nbinsX = h->GetXaxis()->GetNbins();
1309  unsigned nbinsY = h->GetYaxis()->GetNbins();
1310  unsigned xMin = 1;
1311  unsigned yMin = 1;
1312  unsigned xMax = nbinsX;
1313  unsigned yMax = nbinsY;
1314  unsigned Xbinnum = 1;
1315  unsigned Ybinnum = 1;
1316 
1317  if (xMin_ != 0 && xMax_ != 0) { //give users option for automatic mininum and maximum selection by inputting 0 to any of the parameters
1318  // check that user's parameters are completely in agreement with histogram
1319  // for instance, if inputted xMax is out of range xMin will automatically be ignored
1320  if ((xMax_ <= nbinsX) && (xMin_ <= xMax_)) {
1321  nbinsX = xMax_ - xMin_ + 1;
1322  xMax = xMax_; // do NOT use overflow bin
1323  xMin = xMin_; // do NOT use underflow bin
1324  }
1325  }
1326  if (yMin_ != 0 && yMax_ != 0) {
1327  if ((yMax_ <= nbinsY) && (yMin_ <= yMax_)) {
1328  nbinsY = yMax_ - yMin_ + 1;
1329  yMax = yMax_;
1330  yMin = yMin_;
1331  }
1332  }
1333 
1334  if (Xblocks==999){ //Check to see if blocks should be ignored
1335  Xblocks=nbinsX;
1336  }
1337  if (Yblocks==999){
1338  Yblocks=nbinsY;
1339  }
1340 
1341  Xbinnum = nbinsX/Xblocks;
1342  Ybinnum = nbinsY/Yblocks;
1343 
1344  unsigned xLow,xHi,yLow,yHi; //Define the neighbor blocks edges to be summed
1345  if (groupx>neighborsX){
1346  xLow=(groupx-neighborsX)*Xbinnum+xMin;
1347  if (xLow<xMin){
1348  xLow=xMin; //If the neigbor block would go outside the histogram edge, set it the edge
1349  }
1350  }else{
1351  xLow=xMin;
1352  }
1353  xHi=(groupx+1+neighborsX)*Xbinnum+xMin;
1354  if (xHi>xMax){
1355  xHi=xMax;
1356  }
1357  if (groupy>neighborsY){
1358  yLow=(groupy-neighborsY)*Ybinnum+yMin;
1359  if (yLow<yMin){
1360  yLow=yMin;
1361  }
1362  }else{
1363  yLow=yMin;
1364  }
1365  yHi=(groupy+1+neighborsY)*Ybinnum+yMin;
1366  if (yHi>yMax){
1367  yHi=yMax;
1368  }
1369 
1370  for (unsigned xbin=xLow; xbin<=xHi; ++xbin){ //now sum over all the bins
1371  for (unsigned ybin=yLow; ybin<=yHi; ++ybin){
1372  sum += h->GetBinContent(xbin,ybin);
1373  }
1374  }
1375  return sum;
1376 }
1377 
1378 //Similar to algorithm above but returns a version of standard deviation. Additional operations to return real standard deviation used above (Chad Freer)
1379 double ContentSigma::getNeighborSigma(double average, unsigned groupx, unsigned groupy, unsigned Xblocks, unsigned Yblocks, unsigned neighborsX, unsigned neighborsY, const TH1 *h) const {
1380  double sigma = 0;
1381  unsigned nbinsX = h->GetXaxis()->GetNbins();
1382  unsigned nbinsY = h->GetYaxis()->GetNbins();
1383  unsigned xMin = 1;
1384  unsigned yMin = 1;
1385  unsigned xMax = nbinsX;
1386  unsigned yMax = nbinsY;
1387  unsigned Xbinnum = 1;
1388  unsigned Ybinnum = 1;
1389  double block_sum;
1390 
1391  if (xMin_ != 0 && xMax_ != 0) {
1392  if ((xMax_ <= nbinsX) && (xMin_ <= xMax_)) {
1393  nbinsX = xMax_ - xMin_ + 1;
1394  xMax = xMax_;
1395  xMin = xMin_;
1396  }
1397  }
1398  if (yMin_ != 0 && yMax_ != 0) {
1399  if ((yMax_ <= nbinsY) && (yMin_ <= yMax_)) {
1400  nbinsY = yMax_ - yMin_ + 1;
1401  yMax = yMax_;
1402  yMin = yMin_;
1403  }
1404  }
1405  if (Xblocks==999){
1406  Xblocks=nbinsX;
1407  }
1408  if (Yblocks==999){
1409  Yblocks=nbinsY;
1410  }
1411 
1412  Xbinnum = nbinsX/Xblocks;
1413  Ybinnum = nbinsY/Yblocks;
1414 
1415  unsigned xLow,xHi,yLow,yHi;
1416  for (unsigned x_block_count=0; x_block_count<=2*neighborsX; ++x_block_count){
1417  for (unsigned y_block_count=0; y_block_count<=2*neighborsY; ++y_block_count){
1418  //Sum over blocks. Need to find standard deviation of average of blocksums. Set up low and hi values similar to sum but for blocks now.
1419  if (groupx + x_block_count > neighborsX){
1420  xLow=(groupx + x_block_count - neighborsX) * Xbinnum + xMin;
1421  if (xLow < xMin){
1422  xLow = xMin;
1423  }
1424  }else{
1425  xLow = xMin;
1426  }
1427  xHi = xLow + Xbinnum;
1428  if (xHi > xMax){
1429  xHi = xMax;
1430  }
1431  if (groupy + y_block_count > neighborsY){
1432  yLow=(groupy + y_block_count - neighborsY) * Ybinnum + yMin;
1433  if (yLow < yMin){
1434  yLow = yMin;
1435  }
1436  }else{
1437  yLow = yMin;
1438  }
1439  yHi = yLow + Ybinnum;
1440  if (yHi > yMax){
1441  yHi = yMax;
1442  }
1443  block_sum = 0;
1444  for (unsigned x_block_bin=xLow; x_block_bin<=xHi; ++x_block_bin){
1445  for (unsigned y_block_bin=yLow; y_block_bin<=yHi; ++y_block_bin){
1446  block_sum += h->GetBinContent(x_block_bin,y_block_bin);
1447  }
1448  }
1449  sigma += (average-block_sum)*(average-block_sum); //will sqrt and divide by sqrt(N-1) outside of function
1450  }
1451  }
1452  return sigma;
1453 }
1454 
1455 //-----------------------------------------------------------//
1456 //---------------- ContentsWithinExpected ---------------------//
1457 //-----------------------------------------------------------//
1458 // run the test (result: fraction of channels that passed test);
1459 // [0, 1] or <0 for failure
1461 {
1462  badChannels_.clear();
1463  if (!me)
1464  return -1;
1465  if (!me->getRootObject())
1466  return -1;
1467  TH1* h=nullptr; //initialize histogram pointer
1468 
1469  if (verbose_>1)
1470  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1471  << me-> getFullname() << "\n";
1472 
1473  int ncx;
1474  int ncy;
1475 
1476  if (useEmptyBins_)
1477  {
1478  //-- TH2
1480  {
1481  ncx = me->getTH2F()->GetXaxis()->GetNbins();
1482  ncy = me->getTH2F()->GetYaxis()->GetNbins();
1483  h = me->getTH2F(); // access Test histo
1484  }
1485  //-- TH2S
1486  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
1487  {
1488  ncx = me->getTH2S()->GetXaxis()->GetNbins();
1489  ncy = me->getTH2S()->GetYaxis()->GetNbins();
1490  h = me->getTH2S(); // access Test histo
1491  }
1492  //-- TH2D
1493  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
1494  {
1495  ncx = me->getTH2D()->GetXaxis()->GetNbins();
1496  ncy = me->getTH2D()->GetYaxis()->GetNbins();
1497  h = me->getTH2D(); // access Test histo
1498  }
1499  //-- TProfile
1500  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
1501  {
1502  ncx = me->getTProfile()->GetXaxis()->GetNbins();
1503  ncy = 1;
1504  h = me->getTProfile(); // access Test histo
1505  }
1506  //-- TProfile2D
1507  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE2D)
1508  {
1509  ncx = me->getTProfile2D()->GetXaxis()->GetNbins();
1510  ncy = me->getTProfile2D()->GetYaxis()->GetNbins();
1511  h = me->getTProfile2D(); // access Test histo
1512  }
1513  else
1514  {
1515  if (verbose_>0)
1516  std::cout << "QTest:ContentsWithinExpected"
1517  << " ME does not contain TH2F/TH2S/TH2D/TPROFILE/TPROFILE2D, exiting\n";
1518  return -1;
1519  }
1520 
1521  int nsum = 0;
1522  double sum = 0.0;
1523  double average = 0.0;
1524 
1525  if (checkMeanTolerance_)
1526  { // calculate average value of all bin contents
1527 
1528  for (int cx = 1; cx <= ncx; ++cx)
1529  {
1530  for (int cy = 1; cy <= ncy; ++cy)
1531  {
1532  if (me->kind() == MonitorElement::DQM_KIND_TH2F)
1533  {
1534  sum += h->GetBinContent(h->GetBin(cx, cy));
1535  ++nsum;
1536  }
1537  else if (me->kind() == MonitorElement::DQM_KIND_TH2S)
1538  {
1539  sum += h->GetBinContent(h->GetBin(cx, cy));
1540  ++nsum;
1541  }
1542  else if (me->kind() == MonitorElement::DQM_KIND_TH2D)
1543  {
1544  sum += h->GetBinContent(h->GetBin(cx, cy));
1545  ++nsum;
1546  }
1547  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE)
1548  {
1549  if (me->getTProfile()->GetBinEntries(h->GetBin(cx)) >= minEntries_/(ncx))
1550  {
1551  sum += h->GetBinContent(h->GetBin(cx));
1552  ++nsum;
1553  }
1554  }
1555  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D)
1556  {
1557  if (me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) >= minEntries_/(ncx*ncy))
1558  {
1559  sum += h->GetBinContent(h->GetBin(cx, cy));
1560  ++nsum;
1561  }
1562  }
1563  }
1564  }
1565 
1566  if (nsum > 0)
1567  average = sum/nsum;
1568 
1569  } // calculate average value of all bin contents
1570 
1571  int fail = 0;
1572 
1573  for (int cx = 1; cx <= ncx; ++cx)
1574  {
1575  for (int cy = 1; cy <= ncy; ++cy)
1576  {
1577  bool failMean = false;
1578  bool failRMS = false;
1579  bool failMeanTolerance = false;
1580 
1581  if (me->kind() == MonitorElement::DQM_KIND_TPROFILE &&
1582  me->getTProfile()->GetBinEntries(h->GetBin(cx)) < minEntries_/(ncx))
1583  continue;
1584 
1585  if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D &&
1586  me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) < minEntries_/(ncx*ncy))
1587  continue;
1588 
1589  if (checkMean_)
1590  {
1591  double mean = h->GetBinContent(h->GetBin(cx, cy));
1592  failMean = (mean < minMean_ || mean > maxMean_);
1593  }
1594 
1595  if (checkRMS_)
1596  {
1597  double rms = h->GetBinError(h->GetBin(cx, cy));
1598  failRMS = (rms < minRMS_ || rms > maxRMS_);
1599  }
1600 
1601  if (checkMeanTolerance_)
1602  {
1603  double mean = h->GetBinContent(h->GetBin(cx, cy));
1604  failMeanTolerance = (std::abs(mean - average) > toleranceMean_*std::abs(average));
1605  }
1606 
1607  if (failMean || failRMS || failMeanTolerance)
1608  {
1609 
1610  if (me->kind() == MonitorElement::DQM_KIND_TH2F)
1611  {
1612  DQMChannel chan(cx, cy, 0,
1613  h->GetBinContent(h->GetBin(cx, cy)),
1614  h->GetBinError(h->GetBin(cx, cy)));
1615  badChannels_.push_back(chan);
1616  }
1617  else if (me->kind() == MonitorElement::DQM_KIND_TH2S)
1618  {
1619  DQMChannel chan(cx, cy, 0,
1620  h->GetBinContent(h->GetBin(cx, cy)),
1621  h->GetBinError(h->GetBin(cx, cy)));
1622  badChannels_.push_back(chan);
1623  }
1624  else if (me->kind() == MonitorElement::DQM_KIND_TH2D)
1625  {
1626  DQMChannel chan(cx, cy, 0,
1627  h->GetBinContent(h->GetBin(cx, cy)),
1628  h->GetBinError(h->GetBin(cx, cy)));
1629  badChannels_.push_back(chan);
1630  }
1631  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE)
1632  {
1633  DQMChannel chan(cx, cy, int(me->getTProfile()->GetBinEntries(h->GetBin(cx))),
1634  0,
1635  h->GetBinError(h->GetBin(cx)));
1636  badChannels_.push_back(chan);
1637  }
1638  else if (me->kind() == MonitorElement::DQM_KIND_TPROFILE2D)
1639  {
1640  DQMChannel chan(cx, cy, int(me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy))),
1641  h->GetBinContent(h->GetBin(cx, cy)),
1642  h->GetBinError(h->GetBin(cx, cy)));
1643  badChannels_.push_back(chan);
1644  }
1645  ++fail;
1646  }
1647  }
1648  }
1649  return 1.*(ncx*ncy - fail)/(ncx*ncy);
1650  }
1651 
1652  else
1653  {
1655  {
1656  ncx = me->getTH2F()->GetXaxis()->GetNbins();
1657  ncy = me->getTH2F()->GetYaxis()->GetNbins();
1658  h = me->getTH2F(); // access Test histo
1659  }
1660  else if (me->kind()==MonitorElement::DQM_KIND_TH2S)
1661  {
1662  ncx = me->getTH2S()->GetXaxis()->GetNbins();
1663  ncy = me->getTH2S()->GetYaxis()->GetNbins();
1664  h = me->getTH2S(); // access Test histo
1665  }
1666  else if (me->kind()==MonitorElement::DQM_KIND_TH2D)
1667  {
1668  ncx = me->getTH2D()->GetXaxis()->GetNbins();
1669  ncy = me->getTH2D()->GetYaxis()->GetNbins();
1670  h = me->getTH2D(); // access Test histo
1671  }
1672  else
1673  {
1674  if (verbose_>0)
1675  std::cout << "QTest:ContentsWithinExpected AS"
1676  << " ME does not contain TH2F/TH2S/TH2D, exiting\n";
1677  return -1;
1678  }
1679 
1680  // if (!rangeInitialized_) return 0; // all accepted if no initialization
1681  int fail = 0;
1682  for (int cx = 1; cx <= ncx; ++cx)
1683  {
1684  for (int cy = 1; cy <= ncy; ++cy)
1685  {
1686  bool failure = false;
1687  double Content = h->GetBinContent(h->GetBin(cx, cy));
1688  if (Content)
1689  failure = (Content < minMean_ || Content > maxMean_);
1690  if (failure)
1691  ++fail;
1692  }
1693  }
1694  return 1.*(ncx*ncy-fail)/(ncx*ncy);
1695  }
1696 
1697 }
1700 {
1701  if (xmax < xmin)
1702  if (verbose_>0)
1703  std::cout << "QTest:ContentsWitinExpected"
1704  << " Illogical range: (" << xmin << ", " << xmax << "\n";
1705  minMean_ = xmin;
1706  maxMean_ = xmax;
1707  checkMean_ = true;
1708 }
1709 
1712 {
1713  if (xmax < xmin)
1714  if (verbose_>0)
1715  std::cout << "QTest:ContentsWitinExpected"
1716  << " Illogical range: (" << xmin << ", " << xmax << "\n";
1717  minRMS_ = xmin;
1718  maxRMS_ = xmax;
1719  checkRMS_ = true;
1720 }
1721 
1722 //----------------------------------------------------------------//
1723 //-------------------- MeanWithinExpected ---------------------//
1724 //---------------------------------------------------------------//
1725 // run the test;
1726 // (a) if useRange is called: 1 if mean within allowed range, 0 otherwise
1727 // (b) is useRMS or useSigma is called: result is the probability
1728 // Prob(chi^2, ndof=1) that the mean of histogram will be deviated by more than
1729 // +/- delta from <expected_mean>, where delta = mean - <expected_mean>, and
1730 // chi^2 = (delta/sigma)^2. sigma is the RMS of the histogram ("useRMS") or
1731 // <expected_sigma> ("useSigma")
1732 // e.g. for delta = 1, Prob = 31.7%
1733 // for delta = 2, Prob = 4.55%
1734 // (returns result in [0, 1] or <0 for failure)
1736 {
1737  if (!me)
1738  return -1;
1739  if (!me->getRootObject())
1740  return -1;
1741  TH1* h=nullptr;
1742 
1743  if (verbose_>1)
1744  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1745  << me-> getFullname() << "\n";
1746 
1747  if (minEntries_ != 0 && me->getEntries() < minEntries_) return -1;
1748 
1749  if (me->kind()==MonitorElement::DQM_KIND_TH1F)
1750  {
1751  h = me->getTH1F(); //access Test histo
1752  }
1753  else if (me->kind()==MonitorElement::DQM_KIND_TH1S)
1754  {
1755  h = me->getTH1S(); //access Test histo
1756  }
1757  else if (me->kind()==MonitorElement::DQM_KIND_TH1D)
1758  {
1759  h = me->getTH1D(); //access Test histo
1760  }
1761  else {
1762  if (verbose_>0)
1763  std::cout << "QTest:MeanWithinExpected"
1764  << " ME " << me->getFullname()
1765  << " does not contain TH1F/TH1S/TH1D, exiting\n";
1766  return -1;
1767  }
1768 
1769 
1770  if (useRange_) {
1771  double mean = h->GetMean();
1772  if (mean <= xmax_ && mean >= xmin_)
1773  return 1;
1774  else
1775  return 0;
1776  }
1777  else if (useSigma_)
1778  {
1779  if (sigma_ != 0.)
1780  {
1781  double chi = (h->GetMean() - expMean_)/sigma_;
1782  return TMath::Prob(chi*chi, 1);
1783  }
1784  else
1785  {
1786  if (verbose_>0)
1787  std::cout << "QTest:MeanWithinExpected"
1788  << " Error, sigma_ is zero, exiting\n";
1789  return 0;
1790  }
1791  }
1792  else if (useRMS_)
1793  {
1794  if (h->GetRMS() != 0.)
1795  {
1796  double chi = (h->GetMean() - expMean_)/h->GetRMS();
1797  return TMath::Prob(chi*chi, 1);
1798  }
1799  else
1800  {
1801  if (verbose_>0)
1802  std::cout << "QTest:MeanWithinExpected"
1803  << " Error, RMS is zero, exiting\n";
1804  return 0;
1805  }
1806  }
1807  else {
1808  if (verbose_>0)
1809  std::cout << "QTest:MeanWithinExpected"
1810  << " Error, neither Range, nor Sigma, nor RMS, exiting\n";
1811  return -1; }
1812 }
1813 
1815 {
1816  useRange_ = true;
1817  useSigma_ = useRMS_ = false;
1818  xmin_ = xmin; xmax_ = xmax;
1819  if (xmin_ > xmax_)
1820  if (verbose_>0)
1821  std::cout << "QTest:MeanWithinExpected"
1822  << " Illogical range: (" << xmin_ << ", " << xmax_ << "\n";
1823 }
1824 void MeanWithinExpected::useSigma(double expectedSigma)
1825 {
1826  useSigma_ = true;
1827  useRMS_ = useRange_ = false;
1828  sigma_ = expectedSigma;
1829  if (sigma_ == 0)
1830  if (verbose_>0)
1831  std::cout << "QTest:MeanWithinExpected"
1832  << " Expected sigma = " << sigma_ << "\n";
1833 }
1834 
1836 {
1837  useRMS_ = true;
1838  useSigma_ = useRange_ = false;
1839 }
1840 
1841 //----------------------------------------------------------------//
1842 //------------------------ CompareToMedian ---------------------------//
1843 //----------------------------------------------------------------//
1844 /*
1845 Test for TProfile2D
1846 For each x bin, the median value is calculated and then each value is compared with the median.
1847 This procedure is repeated for each x-bin of the 2D profile
1848 The parameters used for this comparison are:
1849 MinRel and MaxRel to identify outliers wrt the median value
1850 An absolute value (MinAbs, MaxAbs) on the median is used to identify a full region out of specification
1851 */
1853  int32_t nbins=0, failed=0;
1854  badChannels_.clear();
1855 
1856  if (!me)
1857  return -1;
1858  if (!me->getRootObject())
1859  return -1;
1860  TH1* h=nullptr;
1861 
1862  if (verbose_>1){
1863  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1864  << me-> getFullname() << "\n";
1865  std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
1866  std::cout << "\tMinMedian = " << _minMed << "; MaxMedian = " << _maxMed << "\n";
1867  std::cout << "\tUseEmptyBins = " << (_emptyBins?"Yes":"No" )<< "\n";
1868  }
1869 
1871  {
1872  h = me->getTProfile2D(); // access Test histo
1873  }
1874  else
1875  {
1876  if (verbose_>0)
1877  std::cout << "QTest:ContentsWithinExpected"
1878  << " ME does not contain TPROFILE2D, exiting\n";
1879  return -1;
1880  }
1881 
1882  nBinsX = h->GetNbinsX();
1883  nBinsY = h->GetNbinsY();
1884  int entries = 0;
1885  float median = 0.0;
1886 
1887  //Median calculated with partially sorted vector
1888  for (int binX = 1; binX <= nBinsX; binX++ ){
1889  reset();
1890  // Fill vector
1891  for (int binY = 1; binY <= nBinsY; binY++){
1892  int bin = h->GetBin(binX, binY);
1893  auto content = (double)h->GetBinContent(bin);
1894  if ( content == 0 && !_emptyBins)
1895  continue;
1896  binValues.push_back(content);
1897  entries = me->getTProfile2D()->GetBinEntries(bin);
1898  }
1899  if (binValues.empty())
1900  continue;
1901  nbins+=binValues.size();
1902 
1903  //calculate median
1904  if(!binValues.empty()){
1905  int medPos = (int)binValues.size()/2;
1906  nth_element(binValues.begin(),binValues.begin()+medPos,binValues.end());
1907  median = *(binValues.begin()+medPos);
1908  }
1909 
1910  // if median == 0, use the absolute cut
1911  if(median == 0){
1912  if (verbose_ > 0){
1913  std::cout << "QTest: Median is 0; the fixed cuts: [" << _minMed << "; " << _maxMed << "] are used\n";
1914  }
1915  for(int binY = 1; binY <= nBinsY; binY++){
1916  int bin = h->GetBin(binX, binY);
1917  auto content = (double)h->GetBinContent(bin);
1918  entries = me->getTProfile2D()->GetBinEntries(bin);
1919  if ( entries == 0 )
1920  continue;
1921  if (content > _maxMed || content < _minMed){
1922  DQMChannel chan(binX,binY, 0, content, h->GetBinError(bin));
1923  badChannels_.push_back(chan);
1924  failed++;
1925  }
1926  }
1927  continue;
1928  }
1929 
1930  //Cut on stat: will mask rings with no enought of statistics
1931  if (median*entries < _statCut )
1932  continue;
1933 
1934  // If median is off the absolute cuts, declare everything bad (if bin has non zero entries)
1935  if(median > _maxMed || median < _minMed){
1936  for(int binY = 1; binY <= nBinsY; binY++){
1937  int bin = h->GetBin(binX, binY);
1938  auto content = (double)h->GetBinContent(bin);
1939  entries = me->getTProfile2D()->GetBinEntries(bin);
1940  if ( entries == 0 )
1941  continue;
1942  DQMChannel chan(binX,binY, 0, content/median, h->GetBinError(bin));
1943  badChannels_.push_back(chan);
1944  failed++;
1945  }
1946  continue;
1947  }
1948 
1949  // Test itself
1950  float minCut = median*_min;
1951  float maxCut = median*_max;
1952  for(int binY = 1; binY <= nBinsY; binY++){
1953  int bin = h->GetBin(binX, binY);
1954  auto content = (double)h->GetBinContent(bin);
1955  entries = me->getTProfile2D()->GetBinEntries(bin);
1956  if ( entries == 0 )
1957  continue;
1958  if (content > maxCut || content < minCut){
1959  DQMChannel chan(binX,binY, 0, content/median, h->GetBinError(bin));
1960  badChannels_.push_back(chan);
1961  failed++;
1962  }
1963  }
1964  }
1965 
1966  if (nbins==0){
1967  if (verbose_ > 0)
1968  std::cout << "QTest:CompareToMedian: Histogram is empty" << std::endl;
1969  return 1.;
1970  }
1971  return 1 - (float)failed/nbins;
1972 }
1973 //----------------------------------------------------------------//
1974 //------------------------ CompareLastFilledBin -----------------//
1975 //----------------------------------------------------------------//
1976 /*
1977 Test for TH1F and TH2F
1978 For the last filled bin the value is compared with specified upper and lower limits. If
1979 it is outside the limit the test failed test result is returned
1980 The parameters used for this comparison are:
1981 MinRel and MaxRel to check identify outliers wrt the median value
1982 */
1984  if (!me)
1985  return -1;
1986  if (!me->getRootObject())
1987  return -1;
1988  TH1* h1=nullptr;
1989  TH2* h2=nullptr;
1990  if (verbose_>1){
1991  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
1992  << me-> getFullname() << "\n";
1993  std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
1994  }
1996  {
1997  h1 = me->getTH1F(); // access Test histo
1998  }
1999  else if (me->kind()==MonitorElement::DQM_KIND_TH2F)
2000  {
2001  h2 = me->getTH2F(); // access Test histo
2002  }
2003  else
2004  {
2005  if (verbose_>0)
2006  std::cout << "QTest:ContentsWithinExpected"
2007  << " ME does not contain TH1F or TH2F, exiting\n";
2008  return -1;
2009  }
2010  int lastBinX = 0;
2011  int lastBinY = 0;
2012  float lastBinVal;
2013 
2014  //--------- do the quality test for 1D histo ---------------//
2015  if (h1 != nullptr)
2016  {
2017  lastBinX = h1->FindLastBinAbove(_average,1);
2018  lastBinVal = h1->GetBinContent(lastBinX);
2019  if (h1->GetEntries() == 0 || lastBinVal < 0) return 1;
2020  }
2021  else if (h2 != nullptr)
2022  {
2023 
2024  lastBinX = h2->FindLastBinAbove(_average,1);
2025  lastBinY = h2->FindLastBinAbove(_average,2);
2026  if ( h2->GetEntries() == 0 || lastBinX < 0 || lastBinY < 0 ) return 1;
2027  lastBinVal = h2->GetBinContent(h2->GetBin(lastBinX,lastBinY));
2028  } else {
2029  if (verbose_ > 0) std::cout << "QTest:"<< getAlgoName() << " Histogram does not exist" << std::endl;
2030  return 1;
2031  }
2032  if (verbose_ > 0) std::cout << "Min and Max values " << _min << " " << _max << " Av value " << _average << " lastBinX " << lastBinX<< " lastBinY " << lastBinY << " lastBinVal " << lastBinVal << std::endl;
2033  if (lastBinVal > _min && lastBinVal <= _max)
2034  return 1;
2035  else
2036  return 0;
2037 }
2038 //----------------------------------------------------//
2039 //--------------- CheckVariance ---------------------//
2040 //----------------------------------------------------//
2042 {
2043  badChannels_.clear();
2044 
2045  if (!me)
2046  return -1;
2047  if (!me->getRootObject())
2048  return -1;
2049  TH1* h=nullptr;
2050 
2051  if (verbose_>1)
2052  std::cout << "QTest:" << getAlgoName() << "::runTest called on "
2053  << me-> getFullname() << "\n";
2054  // -- TH1F
2055  if (me->kind()==MonitorElement::DQM_KIND_TH1F )
2056  {
2057  h = me->getTH1F();
2058  }
2059  // -- TH1D
2060  else if ( me->kind()==MonitorElement::DQM_KIND_TH1D )
2061  {
2062  h = me->getTH1D();
2063  }
2064  else if (me->kind()==MonitorElement::DQM_KIND_TPROFILE)
2065  {
2066  h = me->getTProfile(); // access Test histo
2067  }
2068  else
2069  {
2070  if (verbose_>0) std::cout << "QTest:CheckVariance"
2071  << " ME " << me->getFullname()
2072  << " does not contain TH1F/TH1D/TPROFILE, exiting\n";
2073  return -1;
2074  }
2075 
2076  int ncx = h->GetXaxis()->GetNbins();
2077 
2078  double sum = 0;
2079  double sum2 = 0;
2080  for (int bin = 1; bin <= ncx; ++bin)
2081  {
2082  double contents = h->GetBinContent(bin);
2083  sum += contents;
2084  }
2085  if (sum==0) return -1;
2086  double avg = sum/ncx;
2087 
2088  for (int bin = 1; bin <= ncx; ++bin)
2089  {
2090  double contents = h->GetBinContent(bin);
2091  sum2 += (contents - avg)*(contents - avg);
2092  }
2093 
2094  double Variance = TMath::Sqrt(sum2/ncx);
2095  return Variance;
2096 }
TProfile * getTProfile() const
double getAverage(int bin, const TH1 *h) const
Definition: QTest.cc:987
double getAverage2D(int binX, int binY, const TH2 *h) const
Definition: QTest.cc:1022
common ppss p3p6s2 common epss epspn46 common const1 w2
Definition: inclppp.h:1
TProfile2D * getTProfile2D() const
float runTest(const MonitorElement *me) override
Definition: QTest.cc:303
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
TH1F * getTH1F() const
TH2S * getTH2S() const
TObject * getRootObject() const
void setRMSRange(double xmin, double xmax)
set expected value for mean
Definition: QTest.cc:1711
void useSigma(double expectedSigma)
Definition: QTest.cc:1824
TProfile2D * getRefTProfile2D() const
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1735
float runTest(const MonitorElement *me) override
Definition: QTest.cc:41
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1460
TObject * getRefRootObject() const
TH2S * getRefTH2S() const
float runTest(const MonitorElement *me) override
Definition: QTest.cc:2041
void init()
initialize values
Definition: QTest.cc:18
TH1F * getRefTH1F() const
T sqrt(T t)
Definition: SSEVec.h:18
TH1S * getRefTH1S() const
TH2D * getTH2D() const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
TH3F * getRefTH3F() const
static const int DID_NOT_RUN
static const float ERROR_PROB_THRESHOLD
Definition: QTest.h:125
float runTest(const MonitorElement *me) override
Definition: QTest.cc:859
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1983
TH2F * getTH2F() const
bin
set the eta bin as selection string.
const std::string getFullname() const
get full name of ME including Pathname
void useRange(double xmin, double xmax)
Definition: QTest.cc:1814
T Max(T a, T b)
Definition: MathUtil.h:44
double getEntries() const
get # of entries
double getNeighborSigma(double average, unsigned groupx, unsigned groupy, unsigned Xblocks, unsigned Yblocks, unsigned neighborsX, unsigned neighborsY, const TH1 *h) const
Definition: QTest.cc:1379
float runTest(const MonitorElement *me) override
Definition: QTest.cc:405
float runTest(const MonitorElement *me) override
Definition: QTest.cc:589
TH3F * getTH3F() const
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1852
virtual float runTest(const MonitorElement *me)
Definition: QTest.cc:28
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1093
TH2D * getRefTH2D() const
chan
lumi = TPaveText(lowX+0.38, lowY+0.061, lowX+0.45, lowY+0.161, "NDC") lumi.SetBorderSize( 0 ) lumi...
TH2F * getRefTH2F() const
void setMeanRange(double xmin, double xmax)
set expected value for mean
Definition: QTest.cc:1699
double getNeighborSum(unsigned groupx, unsigned groupy, unsigned Xblocks, unsigned Yblocks, unsigned neighborsX, unsigned neighborsY, const TH1 *h) const
for each bin get sum of the surrounding neighbors
Definition: QTest.cc:1306
float runTest(const MonitorElement *me) override
Definition: QTest.cc:738
TH1D * getTH1D() const
TH1D * getRefTH1D() const
TH1S * getTH1S() const
float runTest(const MonitorElement *me) override
Definition: QTest.cc:659
def fail(errstr="")
uint32_t dimension(pat::CandKinResolution::Parametrization parametrization)
Returns the number of free parameters in a parametrization (3 or 4)
void reset(double vett[256])
Definition: TPedValues.cc:11
TProfile * getRefTProfile() const
Kind kind() const
Get the type of the monitor element.
static const float WARNING_PROB_THRESHOLD
default "probability" values for setting warnings & errors when running tests
Definition: QTest.h:124
float runTest(const MonitorElement *me) override
Definition: QTest.cc:174
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:11