CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
QTest.cc
Go to the documentation of this file.
4 #include "Math/ProbFuncMathCore.h"
5 #include "TMath.h"
6 #include <cmath>
7 #include <iostream>
8 #include <sstream>
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
17  errorProb_ = ERROR_PROB_THRESHOLD;
18  warningProb_ = WARNING_PROB_THRESHOLD;
19  setAlgoName("NO_ALGORITHM");
20  status_ = dqm::qstatus::DID_NOT_RUN;
21  message_ = "NO_MESSAGE";
22  verbose_ = 0; // 0 = silent, 1 = algorithmic failures, 2 = info
23 }
24 
25 float QCriterion::runTest(const MonitorElement* /* me */) {
26  raiseDQMError("QCriterion", "virtual runTest method called");
27  return 0.;
28 }
29 //===================================================//
30 //================ QUALITY TESTS ====================//
31 //==================================================//
32 
33 //----------------------------------------------------//
34 //--------------- ContentsXRange ---------------------//
35 //----------------------------------------------------//
37  badChannels_.clear();
38 
39  if (!me)
40  return -1;
41  if (!me->getRootObject())
42  return -1;
43  TH1* h = nullptr;
44 
45  if (verbose_ > 1)
46  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
47  // -- TH1F
48  if (me->kind() == MonitorElement::Kind::TH1F) {
49  h = me->getTH1F();
50  }
51  // -- TH1S
52  else if (me->kind() == MonitorElement::Kind::TH1S) {
53  h = me->getTH1S();
54  }
55  // -- TH1D
56  else if (me->kind() == MonitorElement::Kind::TH1D) {
57  h = me->getTH1D();
58  } else {
59  if (verbose_ > 0)
60  std::cout << "QTest:ContentsXRange"
61  << " ME " << me->getFullname() << " does not contain TH1F/TH1S/TH1D, exiting\n";
62  return -1;
63  }
64 
65  if (!rangeInitialized_) {
66  if (h->GetXaxis())
67  setAllowedXRange(h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
68  else
69  return -1;
70  }
71  int ncx = h->GetXaxis()->GetNbins();
72  // use underflow bin
73  int first = 0; // 1
74  // use overflow bin
75  int last = ncx + 1; // ncx
76  // all entries
77  double sum = 0;
78  // entries outside X-range
79  double fail = 0;
80  int bin;
81  for (bin = first; bin <= last; ++bin) {
82  double contents = h->GetBinContent(bin);
83  double x = h->GetBinCenter(bin);
84  sum += contents;
85  if (x < xmin_ || x > xmax_)
86  fail += contents;
87  }
88 
89  if (sum == 0)
90  return 1;
91  // return fraction of entries within allowed X-range
92  return (sum - fail) / sum;
93 }
94 
95 //-----------------------------------------------------//
96 //--------------- ContentsYRange ---------------------//
97 //----------------------------------------------------//
99  badChannels_.clear();
100 
101  if (!me)
102  return -1;
103  if (!me->getRootObject())
104  return -1;
105  TH1* h = nullptr;
106 
107  if (verbose_ > 1)
108  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
109 
110  if (me->kind() == MonitorElement::Kind::TH1F) {
111  h = me->getTH1F(); //access Test histo
112  } else if (me->kind() == MonitorElement::Kind::TH1S) {
113  h = me->getTH1S(); //access Test histo
114  } else if (me->kind() == MonitorElement::Kind::TH1D) {
115  h = me->getTH1D(); //access Test histo
116  } else {
117  if (verbose_ > 0)
118  std::cout << "QTest:ContentsYRange"
119  << " ME " << me->getFullname() << " does not contain TH1F/TH1S/TH1D, exiting\n";
120  return -1;
121  }
122 
123  if (!rangeInitialized_ || !h->GetXaxis())
124  return 1; // all bins are accepted if no initialization
125  int ncx = h->GetXaxis()->GetNbins();
126  // do NOT use underflow bin
127  int first = 1;
128  // do NOT use overflow bin
129  int last = ncx;
130  // bins outside Y-range
131  int fail = 0;
132  int bin;
133 
134  if (useEmptyBins_)
135  {
136  for (bin = first; bin <= last; ++bin) {
137  double contents = h->GetBinContent(bin);
138  bool failure = false;
139  failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
140  if (failure) {
141  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
142  badChannels_.push_back(chan);
143  ++fail;
144  }
145  }
146  // return fraction of bins that passed test
147  return 1. * (ncx - fail) / ncx;
148  } else
149  {
150  for (bin = first; bin <= last; ++bin) {
151  double contents = h->GetBinContent(bin);
152  bool failure = false;
153  if (contents)
154  failure = (contents < ymin_ || contents > ymax_); // allowed y-range: [ymin_, ymax_]
155  if (failure)
156  ++fail;
157  }
158  // return fraction of bins that passed test
159  return 1. * (ncx - fail) / ncx;
160  }
161 }
162 
163 //-----------------------------------------------------//
164 //------------------ DeadChannel ---------------------//
165 //----------------------------------------------------//
167  badChannels_.clear();
168  if (!me)
169  return -1;
170  if (!me->getRootObject())
171  return -1;
172  TH1* h1 = nullptr;
173  TH2* h2 = nullptr; //initialize histogram pointers
174 
175  if (verbose_ > 1)
176  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
177  //TH1F
178  if (me->kind() == MonitorElement::Kind::TH1F) {
179  h1 = me->getTH1F(); //access Test histo
180  }
181  //TH1S
182  else if (me->kind() == MonitorElement::Kind::TH1S) {
183  h1 = me->getTH1S(); //access Test histo
184  }
185  //TH1D
186  else if (me->kind() == MonitorElement::Kind::TH1D) {
187  h1 = me->getTH1D(); //access Test histo
188  }
189  //-- TH2F
190  else if (me->kind() == MonitorElement::Kind::TH2F) {
191  h2 = me->getTH2F(); // access Test histo
192  }
193  //-- TH2S
194  else if (me->kind() == MonitorElement::Kind::TH2S) {
195  h2 = me->getTH2S(); // access Test histo
196  }
197  //-- TH2D
198  else if (me->kind() == MonitorElement::Kind::TH2D) {
199  h2 = me->getTH2D(); // access Test histo
200  } else {
201  if (verbose_ > 0)
202  std::cout << "QTest:DeadChannel"
203  << " ME " << me->getFullname() << " does not contain TH1F/TH1S/TH1D/TH2F/TH2S/TH2D, exiting\n";
204  return -1;
205  }
206 
207  int fail = 0; // number of failed channels
208 
209  //--------- do the quality test for 1D histo ---------------//
210  if (h1 != nullptr) {
211  if (!rangeInitialized_ || !h1->GetXaxis())
212  return 1; // all bins are accepted if no initialization
213  int ncx = h1->GetXaxis()->GetNbins();
214  int first = 1;
215  int last = ncx;
216  int bin;
217 
219  for (bin = first; bin <= last; ++bin) {
220  double contents = h1->GetBinContent(bin);
221  bool failure = false;
222  failure = contents <= ymin_; // dead channel: equal to or less than ymin_
223  if (failure) {
224  DQMChannel chan(bin, 0, 0, contents, h1->GetBinError(bin));
225  badChannels_.push_back(chan);
226  ++fail;
227  }
228  }
229  //return fraction of alive channels
230  return 1. * (ncx - fail) / ncx;
231  }
232  //----------------------------------------------------------//
233 
234  //--------- do the quality test for 2D -------------------//
235  else if (h2 != nullptr) {
236  int ncx = h2->GetXaxis()->GetNbins(); // get X bins
237  int ncy = h2->GetYaxis()->GetNbins(); // get Y bins
238 
240  for (int cx = 1; cx <= ncx; ++cx) {
241  for (int cy = 1; cy <= ncy; ++cy) {
242  double contents = h2->GetBinContent(h2->GetBin(cx, cy));
243  bool failure = false;
244  failure = contents <= ymin_; // dead channel: equal to or less than ymin_
245  if (failure) {
246  DQMChannel chan(cx, cy, 0, contents, h2->GetBinError(h2->GetBin(cx, cy)));
247  badChannels_.push_back(chan);
248  ++fail;
249  }
250  }
251  }
252  //return fraction of alive channels
253  return 1. * (ncx * ncy - fail) / (ncx * ncy);
254  } else {
255  if (verbose_ > 0)
256  std::cout << "QTest:DeadChannel"
257  << " TH1/TH2F are NULL, exiting\n";
258  return -1;
259  }
260 }
261 
262 //-----------------------------------------------------//
263 //---------------- NoisyChannel ---------------------//
264 //----------------------------------------------------//
265 // run the test (result: fraction of channels not appearing noisy or "hot")
266 // [0, 1] or <0 for failure
268  badChannels_.clear();
269  if (!me)
270  return -1;
271  if (!me->getRootObject())
272  return -1;
273  TH1* h = nullptr; //initialize histogram pointer
274  TH2* h2 = nullptr; //initialize histogram pointer
275 
276  if (verbose_ > 1)
277  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
278 
279  int nbins = 0;
280  int nbinsX = 0, nbinsY = 0;
281  //-- TH1F
282  if (me->kind() == MonitorElement::Kind::TH1F) {
283  nbins = me->getTH1F()->GetXaxis()->GetNbins();
284  h = me->getTH1F(); // access Test histo
285  }
286  //-- TH1S
287  else if (me->kind() == MonitorElement::Kind::TH1S) {
288  nbins = me->getTH1S()->GetXaxis()->GetNbins();
289  h = me->getTH1S(); // access Test histo
290  }
291  //-- TH1D
292  else if (me->kind() == MonitorElement::Kind::TH1D) {
293  nbins = me->getTH1D()->GetXaxis()->GetNbins();
294  h = me->getTH1D(); // access Test histo
295  }
296  //-- TH2
297  else if (me->kind() == MonitorElement::Kind::TH2F) {
298  nbinsX = me->getTH2F()->GetXaxis()->GetNbins();
299  nbinsY = me->getTH2F()->GetYaxis()->GetNbins();
300  h2 = me->getTH2F(); // access Test histo
301  }
302  //-- TH2
303  else if (me->kind() == MonitorElement::Kind::TH2S) {
304  nbinsX = me->getTH2S()->GetXaxis()->GetNbins();
305  nbinsY = me->getTH2S()->GetYaxis()->GetNbins();
306  h2 = me->getTH2S(); // access Test histo
307  }
308  //-- TH2
309  else if (me->kind() == MonitorElement::Kind::TH2D) {
310  nbinsX = me->getTH2F()->GetXaxis()->GetNbins();
311  nbinsY = me->getTH2F()->GetYaxis()->GetNbins();
312  h2 = me->getTH2D(); // access Test histo
313  } else {
314  if (verbose_ > 0)
315  std::cout << "QTest:NoisyChannel"
316  << " ME " << me->getFullname() << " does not contain TH1F/TH1S/TH1D or TH2F/TH2S/TH2D, exiting\n";
317  return -1;
318  }
319 
320  //-- QUALITY TEST itself
321 
322  // do NOT use underflow bin
323  int first = 1;
324  // do NOT use overflow bin
325  int last = nbins;
326  int lastX = nbinsX, lastY = nbinsY;
327  // bins outside Y-range
328  int fail = 0;
329  int bin;
330  int binX, binY;
331  if (h != nullptr) {
332  if (!rangeInitialized_ || !h->GetXaxis()) {
333  return 1; // all channels are accepted if tolerance has not been set
334  }
335  for (bin = first; bin <= last; ++bin) {
336  double contents = h->GetBinContent(bin);
337  double average = getAverage(bin, h);
338  bool failure = false;
339  if (average != 0)
340  failure = (((contents - average) / std::abs(average)) > tolerance_);
341 
342  if (failure) {
343  ++fail;
344  DQMChannel chan(bin, 0, 0, contents, h->GetBinError(bin));
345  badChannels_.push_back(chan);
346  }
347  }
348 
349  // return fraction of bins that passed test
350  return 1. * (nbins - fail) / nbins;
351  } else if (h2 != nullptr) {
352  for (binY = first; binY <= lastY; ++binY) {
353  for (binX = first; binX <= lastX; ++binX) {
354  double contents = h2->GetBinContent(binX, binY);
355  double average = getAverage2D(binX, binY, h2);
356  bool failure = false;
357  if (average != 0)
358  failure = (((contents - average) / std::abs(average)) > tolerance_);
359  if (failure) {
360  ++fail;
361  DQMChannel chan(binX, 0, 0, contents, h2->GetBinError(binX));
362  badChannels_.push_back(chan);
363  }
364  } //end x loop
365  } //end y loop
366  // return fraction of bins that passed test
367  return 1. * ((nbinsX * nbinsY) - fail) / (nbinsX * nbinsY);
368  } //end nullptr conditional
369  else {
370  if (verbose_ > 0)
371  std::cout << "QTest:NoisyChannel"
372  << " TH1/TH2F are NULL, exiting\n";
373  return -1;
374  }
375 }
376 
377 // get average for bin under consideration
378 // (see description of method setNumNeighbors)
379 double NoisyChannel::getAverage(int bin, const TH1* h) const {
380  int first = 1; // Do NOT use underflow bin
381  int ncx = h->GetXaxis()->GetNbins(); // Do NOT use overflow bin
382  double sum = 0;
383  int bin_start, bin_end;
384  int add_right = 0;
385  int add_left = 0;
386 
387  bin_start = bin - numNeighbors_; // First bin in integral
388  bin_end = bin + numNeighbors_; // Last bin in integral
389 
390  if (bin_start < first) { // If neighbors take you outside of histogram range shift integral right
391  add_right = first - bin_start; // How much to shift remembering we are not using underflow
392  bin_start = first; // Remember to reset the starting bin
393  bin_end += add_right;
394  if (bin_end > ncx)
395  bin_end = ncx; // If the test would be larger than histogram just sum histogram without overflow
396  }
397 
398  if (bin_end > ncx) { // Now we make sure doesn't run off right edge of histogram
399  add_left = bin_end - ncx;
400  bin_end = ncx;
401  bin_start -= add_left;
402  if (bin_start < first)
403  bin_start = first; // If the test would be larger than histogram just sum histogram without underflow
404  }
405 
406  sum += h->Integral(bin_start, bin_end);
407  sum -= h->GetBinContent(bin);
408 
409  int dimension = 2 * numNeighbors_ + 1;
410  if (dimension > h->GetNbinsX())
411  dimension = h->GetNbinsX();
412 
413  return sum / (dimension - 1);
414 }
415 
416 double NoisyChannel::getAverage2D(int binX, int binY, const TH2* h2) const {
418  int firstX = 1;
419  int firstY = 1;
420  double sum = 0;
421  int ncx = h2->GetXaxis()->GetNbins();
422  int ncy = h2->GetYaxis()->GetNbins();
423 
424  int neighborsX, neighborsY; // Convert unsigned input to int so we can use comparators
425  neighborsX = numNeighbors_;
426  neighborsY = numNeighbors_;
427  int bin_startX, bin_endX;
428  int add_rightX = 0; // Start shifts at 0
429  int add_leftX = 0;
430  int bin_startY, bin_endY;
431  int add_topY = 0;
432  int add_downY = 0;
433 
434  bin_startX = binX - neighborsX; // First bin in X
435  bin_endX = binX + neighborsX; // Last bin in X
436 
437  if (bin_startX < firstX) { // If neighbors take you outside of histogram range shift integral right
438  add_rightX = firstX - bin_startX; // How much to shift remembering we are no using underflow
439  bin_startX = firstX; // Remember to reset the starting bin
440  bin_endX += add_rightX;
441  if (bin_endX > ncx)
442  bin_endX = ncx;
443  }
444 
445  if (bin_endX > ncx) { // Now we make sure doesn't run off right edge of histogram
446  add_leftX = bin_endX - ncx;
447  bin_endX = ncx;
448  bin_startX -= add_leftX;
449  if (bin_startX < firstX)
450  bin_startX = firstX; // If the test would be larger than histogram just sum histogram without underflow
451  }
452 
453  bin_startY = binY - neighborsY; // First bin in Y
454  bin_endY = binY + neighborsY; // Last bin in Y
455 
456  if (bin_startY < firstY) { // If neighbors take you outside of histogram range shift integral up
457  add_topY = firstY - bin_startY; // How much to shift remembering we are no using underflow
458  bin_startY = firstY; // Remember to reset the starting bin
459  bin_endY += add_topY;
460  if (bin_endY > ncy)
461  bin_endY = ncy;
462  }
463 
464  if (bin_endY > ncy) { // Now we make sure doesn't run off top edge of histogram
465  add_downY = bin_endY - ncy;
466  bin_endY = ncy;
467  bin_startY -= add_downY;
468  if (bin_startY < firstY)
469  bin_startY = firstY; // If the test would be larger than histogram just sum histogram without underflow
470  }
471 
472  sum += h2->Integral(bin_startX, bin_endX, bin_startY, bin_endY);
473  sum -= h2->GetBinContent(binX, binY);
474 
475  int dimensionX = 2 * neighborsX + 1;
476  int dimensionY = 2 * neighborsY + 1;
477 
478  if (dimensionX > h2->GetNbinsX())
479  dimensionX = h2->GetNbinsX();
480  if (dimensionY > h2->GetNbinsY())
481  dimensionY = h2->GetNbinsY();
482 
483  return sum / (dimensionX * dimensionY - 1); // Average is sum over the # of bins used
484 
485 } // End getAverage2D
486 
487 //-----------------------------------------------------//
488 //-----Content Sigma (Emma Yeager and Chad Freer)------//
489 //----------------------------------------------------//
490 // run the test (result: fraction of channels with sigma that is not noisy or hot)
491 
493  badChannels_.clear();
494  if (!me)
495  return -1;
496  if (!me->getRootObject())
497  return -1;
498  TH1* h = nullptr; //initialize histogram pointer
499 
500  if (verbose_ > 1)
501  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
502 
503  unsigned nbinsX;
504  unsigned nbinsY;
505 
506  //-- TH1F
507  if (me->kind() == MonitorElement::Kind::TH1F) {
508  nbinsX = me->getTH1F()->GetXaxis()->GetNbins();
509  nbinsY = me->getTH1F()->GetYaxis()->GetNbins();
510  h = me->getTH1F(); // access Test histo
511  }
512  //-- TH1S
513  else if (me->kind() == MonitorElement::Kind::TH1S) {
514  nbinsX = me->getTH1S()->GetXaxis()->GetNbins();
515  nbinsY = me->getTH1S()->GetYaxis()->GetNbins();
516  h = me->getTH1S(); // access Test histo
517  }
518  //-- TH1D
519  else if (me->kind() == MonitorElement::Kind::TH1D) {
520  nbinsX = me->getTH1D()->GetXaxis()->GetNbins();
521  nbinsY = me->getTH1D()->GetYaxis()->GetNbins();
522  h = me->getTH1D(); // access Test histo
523  }
524  //-- TH2
525  else if (me->kind() == MonitorElement::Kind::TH2F) {
526  nbinsX = me->getTH2F()->GetXaxis()->GetNbins();
527  nbinsY = me->getTH2F()->GetYaxis()->GetNbins();
528  h = me->getTH2F(); // access Test histo
529  }
530  //-- TH2
531  else if (me->kind() == MonitorElement::Kind::TH2S) {
532  nbinsX = me->getTH2S()->GetXaxis()->GetNbins();
533  nbinsY = me->getTH2S()->GetYaxis()->GetNbins();
534  h = me->getTH2S(); // access Test histo
535  }
536  //-- TH2
537  else if (me->kind() == MonitorElement::Kind::TH2D) {
538  nbinsX = me->getTH2D()->GetXaxis()->GetNbins();
539  nbinsY = me->getTH2D()->GetYaxis()->GetNbins();
540  h = me->getTH2D(); // access Test histo
541  } else {
542  if (verbose_ > 0)
543  std::cout << "QTest:ContentSigma"
544  << " ME " << me->getFullname() << " does not contain TH1F/TH1S/TH1D or TH2F/TH2S/TH2D, exiting\n";
545  return -1;
546  }
547 
548  //-- QUALITY TEST itself
549 
550  if (!rangeInitialized_ || !h->GetXaxis())
551  return 1; // all channels are accepted if tolerance has not been set
552 
553  int fail = 0; // initialize bin failure count
554  unsigned xMin = 1; //initialize minimums and maximums with expected values
555  unsigned yMin = 1;
556  unsigned xMax = nbinsX;
557  unsigned yMax = nbinsY;
558  unsigned XBlocks = numXblocks_; //Initialize xml inputs blocks and neighbors
559  unsigned YBlocks = numYblocks_;
560  unsigned neighborsX = numNeighborsX_;
561  unsigned neighborsY = numNeighborsY_;
562  unsigned Xbinnum = 1;
563  unsigned Ybinnum = 1;
564  unsigned XWidth = 0;
565  unsigned YWidth = 0;
566 
567  if (neighborsX == 999) {
568  neighborsX = 0;
569  }
570  if (neighborsY == 999) {
571  neighborsY = 0;
572  }
573 
574  //give users option for automatic mininum and maximum selection by inputting 0 to any of the parameters
575  // check that user's parameters are completely in agreement with histogram
576  // for instance, if inputted xMax is out of range xMin will automatically be ignored
577  if (xMin_ != 0 && xMax_ != 0) {
578  if ((xMax_ <= nbinsX) && (xMin_ <= xMax_)) { // rescale area of histogram being analyzed
579  nbinsX = xMax_ - xMin_ + 1;
580  xMax = xMax_; // do NOT use overflow bin
581  xMin = xMin_; // do NOT use underflow bin
582  }
583  }
584  //give users option for automatic mininum and maximum selection by inputting 0 to any of the parameters
585  if (yMin_ != 0 && yMax_ != 0) {
586  if ((yMax_ <= nbinsY) && (yMin_ <= yMax_)) {
587  nbinsY = yMax_ - yMin_ + 1;
588  yMax = yMax_;
589  yMin = yMin_;
590  }
591  }
592 
593  if (neighborsX * 2 >= nbinsX) { //make sure neighbor check does not overlap with bin under consideration
594  if (nbinsX % 2 == 0) {
595  neighborsX = nbinsX / 2 - 1; //set neighbors for no overlap
596  } else {
597  neighborsX = (nbinsX - 1) / 2;
598  }
599  }
600 
601  if (neighborsY * 2 >= nbinsY) {
602  if (nbinsY % 2 == 0) {
603  neighborsY = nbinsY / 2 - 1;
604  } else {
605  neighborsY = (nbinsY - 1) / 2;
606  }
607  }
608 
609  if (XBlocks == 999) { //Setting 999 prevents blocks and does quality tests by bins only
610  XBlocks = nbinsX;
611  }
612  if (YBlocks == 999) {
613  YBlocks = nbinsY;
614  }
615 
616  Xbinnum = nbinsX / XBlocks;
617  Ybinnum = nbinsY / YBlocks;
618  for (unsigned groupx = 0; groupx < XBlocks; ++groupx) { //Test over all the blocks
619  for (unsigned groupy = 0; groupy < YBlocks; ++groupy) {
620  double blocksum = 0;
621  for (unsigned binx = 0; binx < Xbinnum; ++binx) { //Sum the contents of the block in question
622  for (unsigned biny = 0; biny < Ybinnum; ++biny) {
623  if (groupx * Xbinnum + xMin + binx <= xMax && groupy * Ybinnum + yMin + biny <= yMax) {
624  blocksum += abs(h->GetBinContent(groupx * Xbinnum + xMin + binx, groupy * Ybinnum + yMin + biny));
625  }
626  }
627  }
628 
629  double sum = getNeighborSum(groupx, groupy, XBlocks, YBlocks, neighborsX, neighborsY, h);
630  sum -= blocksum; //remove center block to test
631 
632  if (neighborsX > groupx) { //Find correct average at the edges
633  XWidth = neighborsX + groupx + 1;
634  } else if (neighborsX > (XBlocks - (groupx + 1))) {
635  XWidth = (XBlocks - groupx) + neighborsX;
636  } else {
637  XWidth = 2 * neighborsX + 1;
638  }
639  if (neighborsY > groupy) {
640  YWidth = neighborsY + groupy + 1;
641  } else if (neighborsY > (YBlocks - (groupy + 1))) {
642  YWidth = (YBlocks - groupy) + neighborsY;
643  } else {
644  YWidth = 2 * neighborsY + 1;
645  }
646 
647  double average = sum / (XWidth * YWidth - 1);
648  double sigma = getNeighborSigma(average, groupx, groupy, XBlocks, YBlocks, neighborsX, neighborsY, h);
649  //get rid of block being tested just like we did with the average
650  sigma -= (average - blocksum) * (average - blocksum);
651  double sigma_2 = sqrt(sigma) / sqrt(XWidth * YWidth - 2); //N-1 where N=XWidth*YWidth - 1
652  double sigma_real = sigma_2 / (XWidth * YWidth - 1);
653  //double avg_uncrt = average*sqrt(sum)/sum;//Obsolete now(Chad Freer)
654  double avg_uncrt = 3 * sigma_real;
655 
656  double probNoisy = ROOT::Math::poisson_cdf_c(blocksum - 1, average + avg_uncrt);
657  double probDead = ROOT::Math::poisson_cdf(blocksum, average - avg_uncrt);
658  double thresholdNoisy = ROOT::Math::normal_cdf_c(toleranceNoisy_);
659  double thresholdDead = ROOT::Math::normal_cdf(-1 * toleranceDead_);
660 
661  int failureNoisy = 0;
662  int failureDead = 0;
663 
664  if (average != 0) {
665  if (noisy_ && dead_) {
666  if (blocksum > average) {
667  failureNoisy = probNoisy < thresholdNoisy;
668  } else {
669  failureDead = probDead < thresholdDead;
670  }
671  } else if (noisy_) {
672  if (blocksum > average) {
673  failureNoisy = probNoisy < thresholdNoisy;
674  }
675  } else if (dead_) {
676  if (blocksum < average) {
677  failureDead = probDead < thresholdDead;
678  }
679  } else {
680  std::cout << "No test type selected!\n";
681  }
682  //Following lines useful for debugging using verbose (Chad Freer)
683  //string histName = h->GetName();
684  //if (histName == "emtfTrackBX") {
685  // std::printf("Chad says: %i XBlocks, %i XBlocks, %f Blocksum, %f Average", XBlocks,YBlocks,blocksum,average);}
686  }
687 
688  if (failureNoisy || failureDead) {
689  ++fail;
690  //DQMChannel chan(groupx*Xbinnum+xMin+binx, 0, 0, blocksum, h->GetBinError(groupx*Xbinnum+xMin+binx));
691  //badChannels_.push_back(chan);
692  }
693  }
694  }
695  return 1. * ((XBlocks * YBlocks) - fail) / (XBlocks * YBlocks);
696 }
697 
698 //Gets the sum of the bins surrounding the block to be tested (Chad Freer)
699 double ContentSigma::getNeighborSum(unsigned groupx,
700  unsigned groupy,
701  unsigned Xblocks,
702  unsigned Yblocks,
703  unsigned neighborsX,
704  unsigned neighborsY,
705  const TH1* h) const {
706  double sum = 0;
707  unsigned nbinsX = h->GetXaxis()->GetNbins();
708  unsigned nbinsY = h->GetYaxis()->GetNbins();
709  unsigned xMin = 1;
710  unsigned yMin = 1;
711  unsigned xMax = nbinsX;
712  unsigned yMax = nbinsY;
713  unsigned Xbinnum = 1;
714  unsigned Ybinnum = 1;
715 
716  //give users option for automatic mininum and maximum selection by inputting 0 to any of the parameters
717  // check that user's parameters are completely in agreement with histogram
718  // for instance, if inputted xMax is out of range xMin will automatically be ignored
719  if (xMin_ != 0 && xMax_ != 0) {
720  if ((xMax_ <= nbinsX) && (xMin_ <= xMax_)) {
721  nbinsX = xMax_ - xMin_ + 1;
722  xMax = xMax_; // do NOT use overflow bin
723  xMin = xMin_; // do NOT use underflow bin
724  }
725  }
726  if (yMin_ != 0 && yMax_ != 0) {
727  if ((yMax_ <= nbinsY) && (yMin_ <= yMax_)) {
728  nbinsY = yMax_ - yMin_ + 1;
729  yMax = yMax_;
730  yMin = yMin_;
731  }
732  }
733 
734  if (Xblocks == 999) { //Check to see if blocks should be ignored
735  Xblocks = nbinsX;
736  }
737  if (Yblocks == 999) {
738  Yblocks = nbinsY;
739  }
740 
741  Xbinnum = nbinsX / Xblocks;
742  Ybinnum = nbinsY / Yblocks;
743 
744  unsigned xLow, xHi, yLow, yHi; //Define the neighbor blocks edges to be summed
745  if (groupx > neighborsX) {
746  xLow = (groupx - neighborsX) * Xbinnum + xMin;
747  if (xLow < xMin) {
748  xLow = xMin; //If the neigbor block would go outside the histogram edge, set it the edge
749  }
750  } else {
751  xLow = xMin;
752  }
753  xHi = (groupx + 1 + neighborsX) * Xbinnum + xMin;
754  if (xHi > xMax) {
755  xHi = xMax;
756  }
757  if (groupy > neighborsY) {
758  yLow = (groupy - neighborsY) * Ybinnum + yMin;
759  if (yLow < yMin) {
760  yLow = yMin;
761  }
762  } else {
763  yLow = yMin;
764  }
765  yHi = (groupy + 1 + neighborsY) * Ybinnum + yMin;
766  if (yHi > yMax) {
767  yHi = yMax;
768  }
769 
770  for (unsigned xbin = xLow; xbin <= xHi; ++xbin) { //now sum over all the bins
771  for (unsigned ybin = yLow; ybin <= yHi; ++ybin) {
772  sum += h->GetBinContent(xbin, ybin);
773  }
774  }
775  return sum;
776 }
777 
778 //Similar to algorithm above but returns a version of standard deviation. Additional operations to return real standard deviation used above (Chad Freer)
780  unsigned groupx,
781  unsigned groupy,
782  unsigned Xblocks,
783  unsigned Yblocks,
784  unsigned neighborsX,
785  unsigned neighborsY,
786  const TH1* h) const {
787  double sigma = 0;
788  unsigned nbinsX = h->GetXaxis()->GetNbins();
789  unsigned nbinsY = h->GetYaxis()->GetNbins();
790  unsigned xMin = 1;
791  unsigned yMin = 1;
792  unsigned xMax = nbinsX;
793  unsigned yMax = nbinsY;
794  unsigned Xbinnum = 1;
795  unsigned Ybinnum = 1;
796  double block_sum;
797 
798  if (xMin_ != 0 && xMax_ != 0) {
799  if ((xMax_ <= nbinsX) && (xMin_ <= xMax_)) {
800  nbinsX = xMax_ - xMin_ + 1;
801  xMax = xMax_;
802  xMin = xMin_;
803  }
804  }
805  if (yMin_ != 0 && yMax_ != 0) {
806  if ((yMax_ <= nbinsY) && (yMin_ <= yMax_)) {
807  nbinsY = yMax_ - yMin_ + 1;
808  yMax = yMax_;
809  yMin = yMin_;
810  }
811  }
812  if (Xblocks == 999) {
813  Xblocks = nbinsX;
814  }
815  if (Yblocks == 999) {
816  Yblocks = nbinsY;
817  }
818 
819  Xbinnum = nbinsX / Xblocks;
820  Ybinnum = nbinsY / Yblocks;
821 
822  unsigned xLow, xHi, yLow, yHi;
823  for (unsigned x_block_count = 0; x_block_count <= 2 * neighborsX; ++x_block_count) {
824  for (unsigned y_block_count = 0; y_block_count <= 2 * neighborsY; ++y_block_count) {
825  //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.
826  if (groupx + x_block_count > neighborsX) {
827  xLow = (groupx + x_block_count - neighborsX) * Xbinnum + xMin;
828  if (xLow < xMin) {
829  xLow = xMin;
830  }
831  } else {
832  xLow = xMin;
833  }
834  xHi = xLow + Xbinnum;
835  if (xHi > xMax) {
836  xHi = xMax;
837  }
838  if (groupy + y_block_count > neighborsY) {
839  yLow = (groupy + y_block_count - neighborsY) * Ybinnum + yMin;
840  if (yLow < yMin) {
841  yLow = yMin;
842  }
843  } else {
844  yLow = yMin;
845  }
846  yHi = yLow + Ybinnum;
847  if (yHi > yMax) {
848  yHi = yMax;
849  }
850  block_sum = 0;
851  for (unsigned x_block_bin = xLow; x_block_bin <= xHi; ++x_block_bin) {
852  for (unsigned y_block_bin = yLow; y_block_bin <= yHi; ++y_block_bin) {
853  block_sum += h->GetBinContent(x_block_bin, y_block_bin);
854  }
855  }
856  sigma += (average - block_sum) * (average - block_sum); //will sqrt and divide by sqrt(N-1) outside of function
857  }
858  }
859  return sigma;
860 }
861 
862 //-----------------------------------------------------------//
863 //---------------- ContentsWithinExpected ---------------------//
864 //-----------------------------------------------------------//
865 // run the test (result: fraction of channels that passed test);
866 // [0, 1] or <0 for failure
868  badChannels_.clear();
869  if (!me)
870  return -1;
871  if (!me->getRootObject())
872  return -1;
873  TH1* h = nullptr; //initialize histogram pointer
874 
875  if (verbose_ > 1)
876  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
877 
878  int ncx;
879  int ncy;
880 
881  if (useEmptyBins_) {
882  //-- TH2
883  if (me->kind() == MonitorElement::Kind::TH2F) {
884  ncx = me->getTH2F()->GetXaxis()->GetNbins();
885  ncy = me->getTH2F()->GetYaxis()->GetNbins();
886  h = me->getTH2F(); // access Test histo
887  }
888  //-- TH2S
889  else if (me->kind() == MonitorElement::Kind::TH2S) {
890  ncx = me->getTH2S()->GetXaxis()->GetNbins();
891  ncy = me->getTH2S()->GetYaxis()->GetNbins();
892  h = me->getTH2S(); // access Test histo
893  }
894  //-- TH2D
895  else if (me->kind() == MonitorElement::Kind::TH2D) {
896  ncx = me->getTH2D()->GetXaxis()->GetNbins();
897  ncy = me->getTH2D()->GetYaxis()->GetNbins();
898  h = me->getTH2D(); // access Test histo
899  }
900  //-- TProfile
901  else if (me->kind() == MonitorElement::Kind::TPROFILE) {
902  ncx = me->getTProfile()->GetXaxis()->GetNbins();
903  ncy = 1;
904  h = me->getTProfile(); // access Test histo
905  }
906  //-- TProfile2D
907  else if (me->kind() == MonitorElement::Kind::TPROFILE2D) {
908  ncx = me->getTProfile2D()->GetXaxis()->GetNbins();
909  ncy = me->getTProfile2D()->GetYaxis()->GetNbins();
910  h = me->getTProfile2D(); // access Test histo
911  } else {
912  if (verbose_ > 0)
913  std::cout << "QTest:ContentsWithinExpected"
914  << " ME does not contain TH2F/TH2S/TH2D/TPROFILE/TPROFILE2D, exiting\n";
915  return -1;
916  }
917 
918  int nsum = 0;
919  double sum = 0.0;
920  double average = 0.0;
921 
922  if (checkMeanTolerance_) { // calculate average value of all bin contents
923 
924  for (int cx = 1; cx <= ncx; ++cx) {
925  for (int cy = 1; cy <= ncy; ++cy) {
926  if (me->kind() == MonitorElement::Kind::TH2F) {
927  sum += h->GetBinContent(h->GetBin(cx, cy));
928  ++nsum;
929  } else if (me->kind() == MonitorElement::Kind::TH2S) {
930  sum += h->GetBinContent(h->GetBin(cx, cy));
931  ++nsum;
932  } else if (me->kind() == MonitorElement::Kind::TH2D) {
933  sum += h->GetBinContent(h->GetBin(cx, cy));
934  ++nsum;
935  } else if (me->kind() == MonitorElement::Kind::TPROFILE) {
936  if (me->getTProfile()->GetBinEntries(h->GetBin(cx)) >= minEntries_ / (ncx)) {
937  sum += h->GetBinContent(h->GetBin(cx));
938  ++nsum;
939  }
940  } else if (me->kind() == MonitorElement::Kind::TPROFILE2D) {
941  if (me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) >= minEntries_ / (ncx * ncy)) {
942  sum += h->GetBinContent(h->GetBin(cx, cy));
943  ++nsum;
944  }
945  }
946  }
947  }
948 
949  if (nsum > 0)
950  average = sum / nsum;
951 
952  } // calculate average value of all bin contents
953 
954  int fail = 0;
955 
956  for (int cx = 1; cx <= ncx; ++cx) {
957  for (int cy = 1; cy <= ncy; ++cy) {
958  bool failMean = false;
959  bool failRMS = false;
960  bool failMeanTolerance = false;
961 
962  if (me->kind() == MonitorElement::Kind::TPROFILE &&
963  me->getTProfile()->GetBinEntries(h->GetBin(cx)) < minEntries_ / (ncx))
964  continue;
965 
966  if (me->kind() == MonitorElement::Kind::TPROFILE2D &&
967  me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy)) < minEntries_ / (ncx * ncy))
968  continue;
969 
970  if (checkMean_) {
971  double mean = h->GetBinContent(h->GetBin(cx, cy));
972  failMean = (mean < minMean_ || mean > maxMean_);
973  }
974 
975  if (checkRMS_) {
976  double rms = h->GetBinError(h->GetBin(cx, cy));
977  failRMS = (rms < minRMS_ || rms > maxRMS_);
978  }
979 
980  if (checkMeanTolerance_) {
981  double mean = h->GetBinContent(h->GetBin(cx, cy));
982  failMeanTolerance = (std::abs(mean - average) > toleranceMean_ * std::abs(average));
983  }
984 
985  if (failMean || failRMS || failMeanTolerance) {
986  if (me->kind() == MonitorElement::Kind::TH2F) {
987  DQMChannel chan(cx, cy, 0, h->GetBinContent(h->GetBin(cx, cy)), h->GetBinError(h->GetBin(cx, cy)));
988  badChannels_.push_back(chan);
989  } else if (me->kind() == MonitorElement::Kind::TH2S) {
990  DQMChannel chan(cx, cy, 0, h->GetBinContent(h->GetBin(cx, cy)), h->GetBinError(h->GetBin(cx, cy)));
991  badChannels_.push_back(chan);
992  } else if (me->kind() == MonitorElement::Kind::TH2D) {
993  DQMChannel chan(cx, cy, 0, h->GetBinContent(h->GetBin(cx, cy)), h->GetBinError(h->GetBin(cx, cy)));
994  badChannels_.push_back(chan);
995  } else if (me->kind() == MonitorElement::Kind::TPROFILE) {
997  cx, cy, int(me->getTProfile()->GetBinEntries(h->GetBin(cx))), 0, h->GetBinError(h->GetBin(cx)));
998  badChannels_.push_back(chan);
999  } else if (me->kind() == MonitorElement::Kind::TPROFILE2D) {
1000  DQMChannel chan(cx,
1001  cy,
1002  int(me->getTProfile2D()->GetBinEntries(h->GetBin(cx, cy))),
1003  h->GetBinContent(h->GetBin(cx, cy)),
1004  h->GetBinError(h->GetBin(cx, cy)));
1005  badChannels_.push_back(chan);
1006  }
1007  ++fail;
1008  }
1009  }
1010  }
1011  return 1. * (ncx * ncy - fail) / (ncx * ncy);
1012  }
1013 
1014  else
1015  {
1016  if (me->kind() == MonitorElement::Kind::TH2F) {
1017  ncx = me->getTH2F()->GetXaxis()->GetNbins();
1018  ncy = me->getTH2F()->GetYaxis()->GetNbins();
1019  h = me->getTH2F(); // access Test histo
1020  } else if (me->kind() == MonitorElement::Kind::TH2S) {
1021  ncx = me->getTH2S()->GetXaxis()->GetNbins();
1022  ncy = me->getTH2S()->GetYaxis()->GetNbins();
1023  h = me->getTH2S(); // access Test histo
1024  } else if (me->kind() == MonitorElement::Kind::TH2D) {
1025  ncx = me->getTH2D()->GetXaxis()->GetNbins();
1026  ncy = me->getTH2D()->GetYaxis()->GetNbins();
1027  h = me->getTH2D(); // access Test histo
1028  } else {
1029  if (verbose_ > 0)
1030  std::cout << "QTest:ContentsWithinExpected AS"
1031  << " ME does not contain TH2F/TH2S/TH2D, exiting\n";
1032  return -1;
1033  }
1034 
1035  // if (!rangeInitialized_) return 0; // all accepted if no initialization
1036  int fail = 0;
1037  for (int cx = 1; cx <= ncx; ++cx) {
1038  for (int cy = 1; cy <= ncy; ++cy) {
1039  bool failure = false;
1040  double Content = h->GetBinContent(h->GetBin(cx, cy));
1041  if (Content)
1042  failure = (Content < minMean_ || Content > maxMean_);
1043  if (failure)
1044  ++fail;
1045  }
1046  }
1047  return 1. * (ncx * ncy - fail) / (ncx * ncy);
1048  }
1049 }
1052  if (xmax < xmin)
1053  if (verbose_ > 0)
1054  std::cout << "QTest:ContentsWitinExpected"
1055  << " Illogical range: (" << xmin << ", " << xmax << "\n";
1056  minMean_ = xmin;
1057  maxMean_ = xmax;
1058  checkMean_ = true;
1059 }
1060 
1063  if (xmax < xmin)
1064  if (verbose_ > 0)
1065  std::cout << "QTest:ContentsWitinExpected"
1066  << " Illogical range: (" << xmin << ", " << xmax << "\n";
1067  minRMS_ = xmin;
1068  maxRMS_ = xmax;
1069  checkRMS_ = true;
1070 }
1071 
1072 //----------------------------------------------------------------//
1073 //-------------------- MeanWithinExpected ---------------------//
1074 //---------------------------------------------------------------//
1075 // run the test;
1076 // (a) if useRange is called: 1 if mean within allowed range, 0 otherwise
1077 // (b) is useRMS or useSigma is called: result is the probability
1078 // Prob(chi^2, ndof=1) that the mean of histogram will be deviated by more than
1079 // +/- delta from <expected_mean>, where delta = mean - <expected_mean>, and
1080 // chi^2 = (delta/sigma)^2. sigma is the RMS of the histogram ("useRMS") or
1081 // <expected_sigma> ("useSigma")
1082 // e.g. for delta = 1, Prob = 31.7%
1083 // for delta = 2, Prob = 4.55%
1084 // (returns result in [0, 1] or <0 for failure)
1086  if (!me)
1087  return -1;
1088  if (!me->getRootObject())
1089  return -1;
1090  TH1* h = nullptr;
1091 
1092  if (verbose_ > 1)
1093  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
1094 
1095  if (minEntries_ != 0 && me->getEntries() < minEntries_)
1096  return -1;
1097 
1098  if (me->kind() == MonitorElement::Kind::TH1F) {
1099  h = me->getTH1F(); //access Test histo
1100  } else if (me->kind() == MonitorElement::Kind::TH1S) {
1101  h = me->getTH1S(); //access Test histo
1102  } else if (me->kind() == MonitorElement::Kind::TH1D) {
1103  h = me->getTH1D(); //access Test histo
1104  } else {
1105  if (verbose_ > 0)
1106  std::cout << "QTest:MeanWithinExpected"
1107  << " ME " << me->getFullname() << " does not contain TH1F/TH1S/TH1D, exiting\n";
1108  return -1;
1109  }
1110 
1111  if (useRange_) {
1112  double mean = h->GetMean();
1113  if (mean <= xmax_ && mean >= xmin_)
1114  return 1;
1115  else
1116  return 0;
1117  } else if (useSigma_) {
1118  if (sigma_ != 0.) {
1119  double chi = (h->GetMean() - expMean_) / sigma_;
1120  return TMath::Prob(chi * chi, 1);
1121  } else {
1122  if (verbose_ > 0)
1123  std::cout << "QTest:MeanWithinExpected"
1124  << " Error, sigma_ is zero, exiting\n";
1125  return 0;
1126  }
1127  } else if (useRMS_) {
1128  if (h->GetRMS() != 0.) {
1129  double chi = (h->GetMean() - expMean_) / h->GetRMS();
1130  return TMath::Prob(chi * chi, 1);
1131  } else {
1132  if (verbose_ > 0)
1133  std::cout << "QTest:MeanWithinExpected"
1134  << " Error, RMS is zero, exiting\n";
1135  return 0;
1136  }
1137  } else {
1138  if (verbose_ > 0)
1139  std::cout << "QTest:MeanWithinExpected"
1140  << " Error, neither Range, nor Sigma, nor RMS, exiting\n";
1141  return -1;
1142  }
1143 }
1144 
1146  useRange_ = true;
1147  useSigma_ = useRMS_ = false;
1148  xmin_ = xmin;
1149  xmax_ = xmax;
1150  if (xmin_ > xmax_)
1151  if (verbose_ > 0)
1152  std::cout << "QTest:MeanWithinExpected"
1153  << " Illogical range: (" << xmin_ << ", " << xmax_ << "\n";
1154 }
1155 void MeanWithinExpected::useSigma(double expectedSigma) {
1156  useSigma_ = true;
1157  useRMS_ = useRange_ = false;
1158  sigma_ = expectedSigma;
1159  if (sigma_ == 0)
1160  if (verbose_ > 0)
1161  std::cout << "QTest:MeanWithinExpected"
1162  << " Expected sigma = " << sigma_ << "\n";
1163 }
1164 
1166  useRMS_ = true;
1167  useSigma_ = useRange_ = false;
1168 }
1169 
1170 //----------------------------------------------------------------//
1171 //------------------------ CompareToMedian ---------------------------//
1172 //----------------------------------------------------------------//
1173 /*
1174 Test for TProfile2D
1175 For each x bin, the median value is calculated and then each value is compared with the median.
1176 This procedure is repeated for each x-bin of the 2D profile
1177 The parameters used for this comparison are:
1178 MinRel and MaxRel to identify outliers wrt the median value
1179 An absolute value (MinAbs, MaxAbs) on the median is used to identify a full region out of specification
1180 */
1182  int32_t nbins = 0, failed = 0;
1183  badChannels_.clear();
1184 
1185  if (!me)
1186  return -1;
1187  if (!me->getRootObject())
1188  return -1;
1189  TH1* h = nullptr;
1190 
1191  if (verbose_ > 1) {
1192  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
1193  std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
1194  std::cout << "\tMinMedian = " << _minMed << "; MaxMedian = " << _maxMed << "\n";
1195  std::cout << "\tUseEmptyBins = " << (_emptyBins ? "Yes" : "No") << "\n";
1196  }
1197 
1198  if (me->kind() == MonitorElement::Kind::TPROFILE2D) {
1199  h = me->getTProfile2D(); // access Test histo
1200  } else {
1201  if (verbose_ > 0)
1202  std::cout << "QTest:ContentsWithinExpected"
1203  << " ME does not contain TPROFILE2D, exiting\n";
1204  return -1;
1205  }
1206 
1207  nBinsX = h->GetNbinsX();
1208  nBinsY = h->GetNbinsY();
1209  int entries = 0;
1210  float median = 0.0;
1211 
1212  //Median calculated with partially sorted vector
1213  for (int binX = 1; binX <= nBinsX; binX++) {
1214  reset();
1215  // Fill vector
1216  for (int binY = 1; binY <= nBinsY; binY++) {
1217  int bin = h->GetBin(binX, binY);
1218  auto content = (double)h->GetBinContent(bin);
1219  if (content == 0 && !_emptyBins)
1220  continue;
1221  binValues.push_back(content);
1222  entries = me->getTProfile2D()->GetBinEntries(bin);
1223  }
1224  if (binValues.empty())
1225  continue;
1226  nbins += binValues.size();
1227 
1228  //calculate median
1229  if (!binValues.empty()) {
1230  int medPos = (int)binValues.size() / 2;
1231  nth_element(binValues.begin(), binValues.begin() + medPos, binValues.end());
1232  median = *(binValues.begin() + medPos);
1233  }
1234 
1235  // if median == 0, use the absolute cut
1236  if (median == 0) {
1237  if (verbose_ > 0) {
1238  std::cout << "QTest: Median is 0; the fixed cuts: [" << _minMed << "; " << _maxMed << "] are used\n";
1239  }
1240  for (int binY = 1; binY <= nBinsY; binY++) {
1241  int bin = h->GetBin(binX, binY);
1242  auto content = (double)h->GetBinContent(bin);
1243  entries = me->getTProfile2D()->GetBinEntries(bin);
1244  if (entries == 0)
1245  continue;
1246  if (content > _maxMed || content < _minMed) {
1247  DQMChannel chan(binX, binY, 0, content, h->GetBinError(bin));
1248  badChannels_.push_back(chan);
1249  failed++;
1250  }
1251  }
1252  continue;
1253  }
1254 
1255  //Cut on stat: will mask rings with no enought of statistics
1256  if (median * entries < _statCut)
1257  continue;
1258 
1259  // If median is off the absolute cuts, declare everything bad (if bin has non zero entries)
1260  if (median > _maxMed || median < _minMed) {
1261  for (int binY = 1; binY <= nBinsY; binY++) {
1262  int bin = h->GetBin(binX, binY);
1263  auto content = (double)h->GetBinContent(bin);
1264  entries = me->getTProfile2D()->GetBinEntries(bin);
1265  if (entries == 0)
1266  continue;
1267  DQMChannel chan(binX, binY, 0, content / median, h->GetBinError(bin));
1268  badChannels_.push_back(chan);
1269  failed++;
1270  }
1271  continue;
1272  }
1273 
1274  // Test itself
1275  float minCut = median * _min;
1276  float maxCut = median * _max;
1277  for (int binY = 1; binY <= nBinsY; binY++) {
1278  int bin = h->GetBin(binX, binY);
1279  auto content = (double)h->GetBinContent(bin);
1280  entries = me->getTProfile2D()->GetBinEntries(bin);
1281  if (entries == 0)
1282  continue;
1283  if (content > maxCut || content < minCut) {
1284  DQMChannel chan(binX, binY, 0, content / median, h->GetBinError(bin));
1285  badChannels_.push_back(chan);
1286  failed++;
1287  }
1288  }
1289  }
1290 
1291  if (nbins == 0) {
1292  if (verbose_ > 0)
1293  std::cout << "QTest:CompareToMedian: Histogram is empty" << std::endl;
1294  return 1.;
1295  }
1296  return 1 - (float)failed / nbins;
1297 }
1298 //----------------------------------------------------------------//
1299 //------------------------ CompareLastFilledBin -----------------//
1300 //----------------------------------------------------------------//
1301 /*
1302 Test for TH1F and TH2F
1303 For the last filled bin the value is compared with specified upper and lower limits. If
1304 it is outside the limit the test failed test result is returned
1305 The parameters used for this comparison are:
1306 MinRel and MaxRel to check identify outliers wrt the median value
1307 */
1309  if (!me)
1310  return -1;
1311  if (!me->getRootObject())
1312  return -1;
1313  TH1* h1 = nullptr;
1314  TH2* h2 = nullptr;
1315  if (verbose_ > 1) {
1316  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
1317  std::cout << "\tMin = " << _min << "; Max = " << _max << "\n";
1318  }
1319  if (me->kind() == MonitorElement::Kind::TH1F) {
1320  h1 = me->getTH1F(); // access Test histo
1321  } else if (me->kind() == MonitorElement::Kind::TH2F) {
1322  h2 = me->getTH2F(); // access Test histo
1323  } else {
1324  if (verbose_ > 0)
1325  std::cout << "QTest:ContentsWithinExpected"
1326  << " ME does not contain TH1F or TH2F, exiting\n";
1327  return -1;
1328  }
1329  int lastBinX = 0;
1330  int lastBinY = 0;
1331  float lastBinVal;
1332 
1333  //--------- do the quality test for 1D histo ---------------//
1334  if (h1 != nullptr) {
1335  lastBinX = h1->FindLastBinAbove(_average, 1);
1336  lastBinVal = h1->GetBinContent(lastBinX);
1337  if (h1->GetEntries() == 0 || lastBinVal < 0)
1338  return 1;
1339  } else if (h2 != nullptr) {
1340  lastBinX = h2->FindLastBinAbove(_average, 1);
1341  lastBinY = h2->FindLastBinAbove(_average, 2);
1342  if (h2->GetEntries() == 0 || lastBinX < 0 || lastBinY < 0)
1343  return 1;
1344  lastBinVal = h2->GetBinContent(h2->GetBin(lastBinX, lastBinY));
1345  } else {
1346  if (verbose_ > 0)
1347  std::cout << "QTest:" << getAlgoName() << " Histogram does not exist" << std::endl;
1348  return 1;
1349  }
1350  if (verbose_ > 0)
1351  std::cout << "Min and Max values " << _min << " " << _max << " Av value " << _average << " lastBinX " << lastBinX
1352  << " lastBinY " << lastBinY << " lastBinVal " << lastBinVal << std::endl;
1353  if (lastBinVal > _min && lastBinVal <= _max)
1354  return 1;
1355  else
1356  return 0;
1357 }
1358 //----------------------------------------------------//
1359 //--------------- CheckVariance ---------------------//
1360 //----------------------------------------------------//
1362  badChannels_.clear();
1363 
1364  if (!me)
1365  return -1;
1366  if (!me->getRootObject())
1367  return -1;
1368  TH1* h = nullptr;
1369 
1370  if (verbose_ > 1)
1371  std::cout << "QTest:" << getAlgoName() << "::runTest called on " << me->getFullname() << "\n";
1372  // -- TH1F
1373  if (me->kind() == MonitorElement::Kind::TH1F) {
1374  h = me->getTH1F();
1375  }
1376  // -- TH1D
1377  else if (me->kind() == MonitorElement::Kind::TH1D) {
1378  h = me->getTH1D();
1379  } else if (me->kind() == MonitorElement::Kind::TPROFILE) {
1380  h = me->getTProfile(); // access Test histo
1381  } else {
1382  if (verbose_ > 0)
1383  std::cout << "QTest:CheckVariance"
1384  << " ME " << me->getFullname() << " does not contain TH1F/TH1D/TPROFILE, exiting\n";
1385  return -1;
1386  }
1387 
1388  int ncx = h->GetXaxis()->GetNbins();
1389 
1390  double sum = 0;
1391  double sum2 = 0;
1392  for (int bin = 1; bin <= ncx; ++bin) {
1393  double contents = h->GetBinContent(bin);
1394  sum += contents;
1395  }
1396  if (sum == 0)
1397  return -1;
1398  double avg = sum / ncx;
1399 
1400  for (int bin = 1; bin <= ncx; ++bin) {
1401  double contents = h->GetBinContent(bin);
1402  sum2 += (contents - avg) * (contents - avg);
1403  }
1404 
1405  double Variance = TMath::Sqrt(sum2 / ncx);
1406  return Variance;
1407 }
virtual TH2D * getTH2D() const
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
double getAverage(int bin, const TH1 *h) const
Definition: QTest.cc:379
virtual TH2F * getTH2F() const
double getAverage2D(int binX, int binY, const TH2 *h) const
Definition: QTest.cc:416
virtual TH1F * getTH1F() const
Kind kind() const
Get the type of the monitor element.
void setRMSRange(double xmin, double xmax)
set expected value for mean
Definition: QTest.cc:1062
void useSigma(double expectedSigma)
Definition: QTest.cc:1155
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1085
float runTest(const MonitorElement *me) override
Definition: QTest.cc:867
virtual TH1S * getTH1S() const
const std::string getFullname() const
get full name of ME including Pathname
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1361
void init()
initialize values
Definition: QTest.cc:16
virtual double getEntries() const
get # of entries
T sqrt(T t)
Definition: SSEVec.h:19
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static const int DID_NOT_RUN
static const float ERROR_PROB_THRESHOLD
Definition: QTest.h:143
float runTest(const MonitorElement *me) override
Definition: QTest.cc:267
virtual TProfile2D * getTProfile2D() const
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1308
virtual TH2S * getTH2S() const
void useRange(double xmin, double xmax)
Definition: QTest.cc:1145
double getNeighborSigma(double average, unsigned groupx, unsigned groupy, unsigned Xblocks, unsigned Yblocks, unsigned neighborsX, unsigned neighborsY, const TH1 *h) const
Definition: QTest.cc:779
float runTest(const MonitorElement *me) override
Definition: QTest.cc:36
float runTest(const MonitorElement *me) override
Definition: QTest.cc:1181
virtual TProfile * getTProfile() const
virtual TH1D * getTH1D() const
virtual float runTest(const MonitorElement *me)
Definition: QTest.cc:25
float runTest(const MonitorElement *me) override
Definition: QTest.cc:492
chan
lumi = TPaveText(lowX+0.38, lowY+0.061, lowX+0.45, lowY+0.161, "NDC") lumi.SetBorderSize( 0 ) lumi...
void setMeanRange(double xmin, double xmax)
set expected value for mean
Definition: QTest.cc:1051
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:699
float runTest(const MonitorElement *me) override
Definition: QTest.cc:166
TObject * getRootObject() const override
float runTest(const MonitorElement *me) override
Definition: QTest.cc:98
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
static const float WARNING_PROB_THRESHOLD
default "probability" values for setting warnings & errors when running tests
Definition: QTest.h:142
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:10