CMS 3D CMS Logo

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