CMS 3D CMS Logo

MonitorElement.cc
Go to the documentation of this file.
1 #define __STDC_FORMAT_MACROS 1
3 #include "TClass.h"
4 #include "TMath.h"
5 #include "TList.h"
6 #include "THashList.h"
7 #include <iostream>
8 #include <cassert>
9 #include <cfloat>
10 #include <cinttypes>
11 
13 
14 namespace dqm::impl {
15 
16  static TH1 *checkRootObject(const std::string &name, TObject *tobj, const char *func, int reqdim) {
17  if (!tobj)
18  throw cms::Exception("MonitorElementError") << "Method '" << func
19  << "' cannot be invoked on monitor"
20  " element '"
21  << name << "' because it is not a ROOT object.";
22 
23  auto *h = static_cast<TH1 *>(tobj);
24  int ndim = h->GetDimension();
25  if (reqdim < 0 || reqdim > ndim)
26  throw cms::Exception("MonitorElementError") << "Method '" << func
27  << "' cannot be invoked on monitor"
28  " element '"
29  << name << "' because it requires " << reqdim
30  << " dimensions; this"
31  " object of type '"
32  << typeid(*h).name() << "' has " << ndim << " dimensions";
33 
34  return h;
35  }
36 
38  this->mutable_ = std::make_shared<MutableMonitorElementData>();
39  this->mutable_->data_ = std::move(data);
41  }
42  MonitorElement::MonitorElement(std::shared_ptr<MutableMonitorElementData> data) { switchData(std::move(data)); }
44 
47  auto access = this->access();
48  out.key_ = access.key;
49  out.value_.scalar_ = access.value.scalar_;
50  if (access.value.object_) {
51  out.value_.object_ = std::unique_ptr<TH1>(static_cast<TH1 *>(access.value.object_->Clone()));
52  }
53  return out;
54  }
55 
56  std::shared_ptr<MutableMonitorElementData> MonitorElement::release() {
57  auto data = this->mutable_;
58  this->mutable_.reset();
59  return data;
60  }
61 
63  assert(other);
64  this->mutable_ = other->mutable_;
66  }
67 
68  void MonitorElement::switchData(std::shared_ptr<MutableMonitorElementData> data) {
69  this->mutable_ = std::move(data);
71  }
72 
73  void MonitorElement::switchObject(std::unique_ptr<TH1> &&newobject) {
74  auto access = this->accessMut();
75  // Assume kind etc. matches.
76  // This should free the old object.
77  access.value.object_ = std::move(newobject);
78  }
79 
81  auto access = this->accessMut();
83  }
84 
86  data_.flags &= ~DQMNet::DQM_PROP_TYPE_MASK;
88 
89  // mark as updated.
91 
92  // lumi flag is approximately equivalent to Scope::LUMI.
94  if (access.key.scope_ == MonitorElementData::Scope::LUMI) {
96  }
97 
98  // these are unsupported and always off.
99  data_.flags &= ~DQMNet::DQM_PROP_HAS_REFERENCE;
100  data_.flags &= ~DQMNet::DQM_PROP_TAGGED;
101  data_.flags &= ~DQMNet::DQM_PROP_RESET;
102  data_.flags &= ~DQMNet::DQM_PROP_ACCUMULATE;
103 
104  // we use ROOT's internal efficiency flag as the truth
105  data_.flags &= ~DQMNet::DQM_PROP_EFFICIENCY_PLOT;
106  if (access.value.object_ && access.value.object_->TestBit(TH1::kIsAverage)) {
108  }
109 
110  data_.tag = 0;
111 
112  // don't touch version (a timestamp).
113 
114  // we could set proper values here, but nobody should use them.
115  data_.run = 0;
116  data_.lumi = 0;
117 
118  // these are relics from the threaded migration and should not be used anywhere.
119  data_.streamId = 0;
120  data_.moduleId = 0;
121 
122  // leaking a pointer here, but that should be fine.
124 
126 
127  data_.flags &= ~DQMNet::DQM_PROP_REPORT_ALARM;
128  data_.qreports.clear();
129  for (QReport const &qr : access.value.qreports_) {
130  data_.qreports.push_back(qr.getValue());
131  switch (qr.getStatus()) {
133  break;
136  break;
137  case dqm::qstatus::ERROR:
139  break;
140  default:
142  break;
143  }
144  }
145  }
146 
148 
149  //utility function to check the consistency of the axis labels
150  //taken from TH1::CheckBinLabels which is not public
151  bool MonitorElement::CheckBinLabels(const TAxis *a1, const TAxis *a2) {
152  // check that axis have same labels
153  THashList *l1 = (const_cast<TAxis *>(a1))->GetLabels();
154  THashList *l2 = (const_cast<TAxis *>(a2))->GetLabels();
155 
156  if (!l1 && !l2)
157  return true;
158  if (!l1 || !l2) {
159  return false;
160  }
161  // check now labels sizes are the same
162  if (l1->GetSize() != l2->GetSize()) {
163  return false;
164  }
165  for (int i = 1; i <= a1->GetNbins(); ++i) {
166  TString label1 = a1->GetBinLabel(i);
167  TString label2 = a2->GetBinLabel(i);
168  if (label1 != label2) {
169  return false;
170  }
171  }
172  return true;
173  }
174 
177  auto access = this->accessMut();
178  update();
179  if (kind() == Kind::STRING) {
181  } else {
182  incompatible(__PRETTY_FUNCTION__);
183  }
184  }
185 
187  void MonitorElement::Fill(double x) {
188  auto access = this->accessMut();
189  update();
190  if (kind() == Kind::INT)
191  access.value.scalar_.num = static_cast<int64_t>(x);
192  else if (kind() == Kind::REAL)
194  else if (kind() == Kind::TH1F)
195  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
196  else if (kind() == Kind::TH1S)
197  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
198  else if (kind() == Kind::TH1I)
199  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
200  else if (kind() == Kind::TH1D)
201  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
202  else
203  incompatible(__PRETTY_FUNCTION__);
204  }
205 
207  void MonitorElement::doFill(int64_t x) {
208  auto access = this->accessMut();
209  update();
210  if (kind() == Kind::INT)
211  access.value.scalar_.num = static_cast<int64_t>(x);
212  else if (kind() == Kind::REAL)
213  access.value.scalar_.real = static_cast<double>(x);
214  else if (kind() == Kind::TH1F)
215  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
216  else if (kind() == Kind::TH1S)
217  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
218  else if (kind() == Kind::TH1I)
219  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
220  else if (kind() == Kind::TH1D)
221  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
222  else
223  incompatible(__PRETTY_FUNCTION__);
224  }
225 
227  void MonitorElement::Fill(double x, double yw) {
228  auto access = this->accessMut();
229  update();
230  if (kind() == Kind::TH1F)
231  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
232  else if (kind() == Kind::TH1S)
233  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
234  else if (kind() == Kind::TH1D)
235  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
236  else if (kind() == Kind::TH1I)
237  accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
238  else if (kind() == Kind::TH2F)
239  static_cast<TH2F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
240  else if (kind() == Kind::TH2S)
241  static_cast<TH2S *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
242  else if (kind() == Kind::TH2D)
243  static_cast<TH2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
244  else if (kind() == Kind::TH2I)
245  static_cast<TH2I *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
246  else if (kind() == Kind::TPROFILE)
247  static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->Fill(x, yw, 1);
248  else
249  incompatible(__PRETTY_FUNCTION__);
250  }
251 
255  void MonitorElement::ShiftFillLast(double y, double ye, int xscale) {
256  // TODO: this should take the lock only once to be actually safe.
257  // But since it is not const, we don't even claim it is thread-safe.
258  update();
259  if (kind() == Kind::TH1F || kind() == Kind::TH1S || kind() == Kind::TH1D || kind() == Kind::TH1I) {
260  int nbins = getNbinsX();
261  auto entries = (int)getEntries();
262  // first fill bins from left to right
263  int index = entries + 1;
264  int xlow = 2;
265  int xup = nbins;
266  // if more entries than bins then start shifting
267  if (entries >= nbins) {
268  index = nbins;
269  xlow = entries - nbins + 3;
270  xup = entries + 1;
271  // average first bin
272  double y1 = getBinContent(1);
273  double y2 = getBinContent(2);
274  double y1err = getBinError(1);
275  double y2err = getBinError(2);
276  double N = entries - nbins + 1.;
277  if (ye == 0. || y1err == 0. || y2err == 0.) {
278  // for errors zero calculate unweighted mean and its error
279  double sum = N * y1 + y2;
280  y1 = sum / (N + 1.);
281  // FIXME check if correct
282  double s = (N + 1.) * (N * y1 * y1 + y2 * y2) - sum * sum;
283  if (s >= 0.)
284  y1err = sqrt(s) / (N + 1.);
285  else
286  y1err = 0.;
287  } else {
288  // for errors non-zero calculate weighted mean and its error
289  double denom = (1. / y1err + 1. / y2err);
290  double mean = (y1 / y1err + y2 / y2err) / denom;
291  // FIXME check if correct
292  y1err = sqrt(((y1 - mean) * (y1 - mean) / y1err + (y2 - mean) * (y2 - mean) / y2err) / denom / 2.);
293  y1 = mean; // set y1 to mean for filling below
294  }
295  setBinContent(1, y1);
296  setBinError(1, y1err);
297  // shift remaining bins to the left
298  for (int i = 3; i <= nbins; i++) {
300  setBinError(i - 1, getBinError(i));
301  }
302  }
303  // fill last bin with new values
304  setBinContent(index, y);
305  setBinError(index, ye);
306  // set entries
307  setEntries(entries + 1);
308  // set axis labels and reset drawing option
309  char buffer[10];
310  sprintf(buffer, "%d", xlow * xscale);
312  setBinLabel(2, a);
313  sprintf(buffer, "%d", xup * xscale);
315  setBinLabel(nbins, b);
316  setBinLabel(1, "av.");
317  } else
318  incompatible(__PRETTY_FUNCTION__);
319  }
321  void MonitorElement::Fill(double x, double y, double zw) {
322  auto access = this->accessMut();
323  update();
324  if (kind() == Kind::TH2F)
325  static_cast<TH2F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
326  else if (kind() == Kind::TH2S)
327  static_cast<TH2S *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
328  else if (kind() == Kind::TH2D)
329  static_cast<TH2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
330  else if (kind() == Kind::TH2I)
331  static_cast<TH2I *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
332  else if (kind() == Kind::TH3F)
333  static_cast<TH3F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw, 1);
334  else if (kind() == Kind::TPROFILE)
335  static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
336  else if (kind() == Kind::TPROFILE2D)
337  static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw, 1);
338  else
339  incompatible(__PRETTY_FUNCTION__);
340  }
341 
343  void MonitorElement::Fill(double x, double y, double z, double w) {
344  auto access = this->accessMut();
345  update();
346  if (kind() == Kind::TH3F)
347  static_cast<TH3F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, z, w);
348  else if (kind() == Kind::TPROFILE2D)
349  static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, z, w);
350  else
351  incompatible(__PRETTY_FUNCTION__);
352  }
353 
356  auto access = this->accessMut();
357  update();
358  if (kind() == Kind::INT)
359  access.value.scalar_.num = 0;
360  else if (kind() == Kind::REAL)
361  access.value.scalar_.real = 0;
362  else if (kind() == Kind::STRING)
363  access.value.scalar_.str.clear();
364  else
365  return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Reset();
366  }
367 
369  void MonitorElement::packScalarData(std::string &into, const char *prefix) const {
370  auto access = this->access();
371  char buf[64];
372  if (kind() == Kind::INT) {
373  snprintf(buf, sizeof(buf), "%s%" PRId64, prefix, access.value.scalar_.num);
374  into = buf;
375  } else if (kind() == Kind::REAL) {
376  snprintf(buf, sizeof(buf), "%s%.*g", prefix, DBL_DIG + 2, access.value.scalar_.real);
377  into = buf;
378  } else if (kind() == Kind::STRING) {
379  into.reserve(strlen(prefix) + access.value.scalar_.str.size());
380  into += prefix;
381  into += access.value.scalar_.str;
382  } else
383  incompatible(__PRETTY_FUNCTION__);
384  }
385 
388 
393  if (kind() == Kind::INT)
394  packScalarData(result, "i=");
395  else if (kind() == Kind::REAL)
396  packScalarData(result, "f=");
397  else if (kind() == Kind::STRING)
398  packScalarData(result, "s=");
399  else
400  incompatible(__PRETTY_FUNCTION__);
401 
402  return result;
403  }
404 
411  result.reserve(6 + 2 * data_.objname.size() + val.size());
412  result += '<';
413  result += data_.objname;
414  result += '>';
415  result += val;
416  result += '<';
417  result += '/';
418  result += data_.objname;
419  result += '>';
420  return result;
421  }
422 
425  char buf[32];
427  size_t len = sprintf(buf, "t=%" PRIu32, data_.tag);
428 
429  result.reserve(6 + 2 * data_.objname.size() + len);
430  result += '<';
431  result += data_.objname;
432  result += '>';
433  result += buf;
434  result += '<';
435  result += '/';
436  result += data_.objname;
437  result += '>';
438  return result;
439  }
440 
444 
445  result.reserve(6 + 2 * data_.objname.size() + 3);
446  result += '<';
447  result += data_.objname;
448  result += '>';
449  result += "e=1";
450  result += '<';
451  result += '/';
452  result += data_.objname;
453  result += '>';
454  return result;
455  }
456 
458  char buf[64];
460  size_t titlelen = data_.objname.size() + qv.qtname.size() + 1;
461  size_t buflen = sprintf(buf, "qr=st:%d:%.*g:", qv.code, DBL_DIG + 2, qv.qtresult);
462 
463  result.reserve(7 + 2 * titlelen + buflen + qv.algorithm.size() + qv.message.size());
464  result += '<';
465  result += data_.objname;
466  result += '.';
467  result += qv.qtname;
468  result += '>';
469  result += buf;
470  result += qv.algorithm;
471  result += ':';
472  result += qv.message;
473  result += '<';
474  result += '/';
475  result += data_.objname;
476  result += '.';
477  result += qv.qtname;
478  result += '>';
479  return result;
480  }
481 
484  DQMNet::QValue *qv;
485  const_cast<MonitorElement *>(this)->getQReport(false, qtname, qr, qv);
486  return qr;
487  }
488 
489  template <typename FILTER>
490  std::vector<MonitorElementData::QReport *> MonitorElement::filterQReports(FILTER filter) const {
491  auto access = this->access();
492  std::vector<MonitorElementData::QReport *> result;
494  if (filter(qr)) {
495  // const_cast here because this API always violated cons'ness. Should
496  // make the result type const and fix all usages.
497  result.push_back(const_cast<MonitorElementData::QReport *>(&qr));
498  }
499  }
500  return result;
501  }
502 
503  std::vector<MonitorElementData::QReport *> MonitorElement::getQReports() const {
504  return filterQReports([](MonitorElementData::QReport const &qr) { return true; });
505  }
506 
507  std::vector<MonitorElementData::QReport *> MonitorElement::getQWarnings() const {
508  return filterQReports(
509  [](MonitorElementData::QReport const &qr) { return qr.getStatus() == dqm::qstatus::WARNING; });
510  }
511 
512  std::vector<MonitorElementData::QReport *> MonitorElement::getQErrors() const {
513  return filterQReports([](MonitorElementData::QReport const &qr) { return qr.getStatus() == dqm::qstatus::ERROR; });
514  }
515 
516  std::vector<MonitorElementData::QReport *> MonitorElement::getQOthers() const {
517  return filterQReports([](MonitorElementData::QReport const &qr) {
520  });
521  }
522 
523  void MonitorElement::incompatible(const char *func) const {
524  throw cms::Exception("MonitorElementError") << "Method '" << func
525  << "' cannot be invoked on monitor"
526  " element '"
527  << data_.objname << "'";
528  }
529 
530  TH1 const *MonitorElement::accessRootObject(Access const &access, const char *func, int reqdim) const {
531  if (kind() < Kind::TH1F)
532  throw cms::Exception("MonitorElement") << "Method '" << func
533  << "' cannot be invoked on monitor"
534  " element '"
535  << data_.objname << "' because it is not a root object";
536  return access.value.object_.get();
537  }
538  TH1 *MonitorElement::accessRootObject(AccessMut const &access, const char *func, int reqdim) const {
539  if (kind() < Kind::TH1F)
540  throw cms::Exception("MonitorElement") << "Method '" << func
541  << "' cannot be invoked on monitor"
542  " element '"
543  << data_.objname << "' because it is not a root object";
544  return checkRootObject(data_.objname, access.value.object_.get(), func, reqdim);
545  }
546 
547  /*** getter methods (wrapper around ROOT methods) ****/
548  //
550  double MonitorElement::getMean(int axis /* = 1 */) const {
551  auto access = this->access();
552  return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetMean(axis);
553  }
554 
557  double MonitorElement::getMeanError(int axis /* = 1 */) const {
558  auto access = this->access();
559  return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetMeanError(axis);
560  }
561 
563  double MonitorElement::getRMS(int axis /* = 1 */) const {
564  auto access = this->access();
565  return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetRMS(axis);
566  }
567 
569  double MonitorElement::getRMSError(int axis /* = 1 */) const {
570  auto access = this->access();
571  return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetRMSError(axis);
572  }
573 
576  auto access = this->access();
577  return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetNbinsX();
578  }
579 
582  auto access = this->access();
583  return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNbinsY();
584  }
585 
588  auto access = this->access();
589  return accessRootObject(access, __PRETTY_FUNCTION__, 3)->GetNbinsZ();
590  }
591 
593  double MonitorElement::getBinContent(int binx) const {
594  auto access = this->access();
595  return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetBinContent(binx);
596  }
597 
599  double MonitorElement::getBinContent(int binx, int biny) const {
600  auto access = this->access();
601  return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetBinContent(binx, biny);
602  }
603 
605  double MonitorElement::getBinContent(int binx, int biny, int binz) const {
606  auto access = this->access();
607  return accessRootObject(access, __PRETTY_FUNCTION__, 3)->GetBinContent(binx, biny, binz);
608  }
609 
611  double MonitorElement::getBinError(int binx) const {
612  auto access = this->access();
613  return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetBinError(binx);
614  }
615 
617  double MonitorElement::getBinError(int binx, int biny) const {
618  auto access = this->access();
619  return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetBinError(binx, biny);
620  }
621 
623  double MonitorElement::getBinError(int binx, int biny, int binz) const {
624  auto access = this->access();
625  return accessRootObject(access, __PRETTY_FUNCTION__, 3)->GetBinError(binx, biny, binz);
626  }
627 
629  double MonitorElement::getEntries() const {
630  auto access = this->access();
631  return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetEntries();
632  }
633 
635  int MonitorElement::getBin(int binx, int biny) const {
636  auto access = this->access();
637  if (kind() == Kind::TPROFILE2D)
638  return static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBin(binx, biny);
639  else {
640  incompatible(__PRETTY_FUNCTION__);
641  return 0;
642  }
643  }
644 
646  double MonitorElement::getBinEntries(int bin) const {
647  auto access = this->access();
648  if (kind() == Kind::TPROFILE)
649  return static_cast<TProfile const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBinEntries(bin);
650  else if (kind() == Kind::TPROFILE2D)
651  return static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBinEntries(bin);
652  else {
653  incompatible(__PRETTY_FUNCTION__);
654  return 0;
655  }
656  }
657 
659  double MonitorElement::getBinEntries(int binx, int biny) const {
660  auto access = this->access();
661  if (kind() == Kind::TPROFILE2D) {
662  int globBin =
663  static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBin(binx, biny);
664  return static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBinEntries(globBin);
665  } else {
666  incompatible(__PRETTY_FUNCTION__);
667  return 0;
668  }
669  }
670 
672  double MonitorElement::integral() const {
673  auto access = this->access();
674  return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Integral();
675  }
676 
678  std::string MonitorElement::getAxisTitle(int axis /* = 1 */) const {
679  auto access = this->access();
680  return getAxis(access, __PRETTY_FUNCTION__, axis)->GetTitle();
681  }
682 
685  auto access = this->access();
686  return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetTitle();
687  }
688 
689  /*** setter methods (wrapper around ROOT methods) ****/
690  //
692  void MonitorElement::setBinContent(int binx, double content) {
693  auto access = this->accessMut();
694  accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetBinContent(binx, content);
695  }
696 
698  void MonitorElement::setBinContent(int binx, int biny, double content) {
699  auto access = this->accessMut();
700  accessRootObject(access, __PRETTY_FUNCTION__, 2)->SetBinContent(binx, biny, content);
701  }
702 
704  void MonitorElement::setBinContent(int binx, int biny, int binz, double content) {
705  auto access = this->accessMut();
706  accessRootObject(access, __PRETTY_FUNCTION__, 3)->SetBinContent(binx, biny, binz, content);
707  }
708 
710  void MonitorElement::setBinError(int binx, double error) {
711  auto access = this->accessMut();
712  accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetBinError(binx, error);
713  }
714 
716  void MonitorElement::setBinError(int binx, int biny, double error) {
717  auto access = this->accessMut();
718  accessRootObject(access, __PRETTY_FUNCTION__, 2)->SetBinError(binx, biny, error);
719  }
720 
722  void MonitorElement::setBinError(int binx, int biny, int binz, double error) {
723  auto access = this->accessMut();
724  accessRootObject(access, __PRETTY_FUNCTION__, 3)->SetBinError(binx, biny, binz, error);
725  }
726 
728  void MonitorElement::setBinEntries(int bin, double nentries) {
729  auto access = this->accessMut();
730  if (kind() == Kind::TPROFILE)
731  static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->SetBinEntries(bin, nentries);
732  else if (kind() == Kind::TPROFILE2D)
733  static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->SetBinEntries(bin, nentries);
734  else
735  incompatible(__PRETTY_FUNCTION__);
736  }
737 
739  void MonitorElement::setEntries(double nentries) {
740  auto access = this->accessMut();
741  accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetEntries(nentries);
742  }
743 
746  const MonitorElement *num, const MonitorElement *denom, double c1, double c2, const char *options) {
747  if (num->kind() < Kind::TH1F)
748  num->incompatible(__PRETTY_FUNCTION__);
749  if (denom->kind() < Kind::TH1F)
750  denom->incompatible(__PRETTY_FUNCTION__);
751 
752  TH1 const *numH = static_cast<TH1 const *>(num->getRootObject());
753  TH1 const *denomH = static_cast<TH1 const *>(denom->getRootObject());
754  TH1 *thisH = getTH1();
755 
756  //Need to take locks in a consistent order to avoid deadlocks. Use pointer value order of underlying ROOT object..
757  //This is known as the monitor pattern.
758  std::array<const MonitorElement *, 3> order{{this, num, denom}};
759  std::sort(order.begin(), order.end(), [](auto const *lhs, auto const *rhs) {
760  return lhs->mutable_->data_.value_.object_.get() < rhs->mutable_->data_.value_.object_.get();
761  });
762 
763  auto a0 = order[0]->access();
764  auto a1 = order[1]->access();
765  auto a2 = order[2]->access();
766 
767  //Have ROOT do check that the types are compatible
768  thisH->Divide(numH, denomH, c1, c2, options);
769  }
770 
772  void MonitorElement::setBinLabel(int bin, const std::string &label, int axis /* = 1 */) {
773  bool fail = false;
774  {
775  auto access = this->accessMut();
776  update();
777  if (getAxis(access, __PRETTY_FUNCTION__, axis)->GetNbins() >= bin) {
778  getAxis(access, __PRETTY_FUNCTION__, axis)->SetBinLabel(bin, label.c_str());
779  } else {
780  fail = true;
781  }
782  }
783  // do this with the ME lock released to prevent a deadlock
784  if (fail) {
785  // this also takes the lock, make sure to release it before going to edm
786  // (which might take more locks)
787  auto name = getFullname();
788  edm::LogWarning("MonitorElement") << "*** MonitorElement: WARNING:"
789  << "setBinLabel: attempting to set label of non-existent bin number for ME: "
790  << name << " \n";
791  }
792  }
793 
795  void MonitorElement::setAxisRange(double xmin, double xmax, int axis /* = 1 */) {
796  auto access = this->accessMut();
797  getAxis(access, __PRETTY_FUNCTION__, axis)->SetRangeUser(xmin, xmax);
798  }
799 
801  void MonitorElement::setAxisTitle(const std::string &title, int axis /* = 1 */) {
802  auto access = this->accessMut();
803  getAxis(access, __PRETTY_FUNCTION__, axis)->SetTitle(title.c_str());
804  }
805 
807  void MonitorElement::setAxisTimeDisplay(int value, int axis /* = 1 */) {
808  auto access = this->accessMut();
809  getAxis(access, __PRETTY_FUNCTION__, axis)->SetTimeDisplay(value);
810  }
811 
813  void MonitorElement::setAxisTimeFormat(const char *format /* = "" */, int axis /* = 1 */) {
814  auto access = this->accessMut();
815  getAxis(access, __PRETTY_FUNCTION__, axis)->SetTimeFormat(format);
816  }
817 
820  auto access = this->accessMut();
821  accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetTitle(title.c_str());
822  }
823 
824  TAxis *MonitorElement::getAxis(AccessMut const &access, const char *func, int axis) const {
825  TH1 *h = accessRootObject(access, func, axis - 1);
826  TAxis *a = nullptr;
827  if (axis == 1)
828  a = h->GetXaxis();
829  else if (axis == 2)
830  a = h->GetYaxis();
831  else if (axis == 3)
832  a = h->GetZaxis();
833 
834  if (!a)
835  throw cms::Exception("MonitorElementError") << "No such axis " << axis
836  << " in monitor element"
837  " '"
838  << data_.objname << "' of type '" << typeid(*h).name() << "'";
839 
840  return a;
841  }
842 
843  TAxis const *MonitorElement::getAxis(Access const &access, const char *func, int axis) const {
844  TH1 const *h = accessRootObject(access, func, axis - 1);
845  TAxis const *a = nullptr;
846  if (axis == 1)
847  a = h->GetXaxis();
848  else if (axis == 2)
849  a = h->GetYaxis();
850  else if (axis == 3)
851  a = h->GetZaxis();
852 
853  if (!a)
854  throw cms::Exception("MonitorElementError") << "No such axis " << axis
855  << " in monitor element"
856  " '"
857  << data_.objname << "' of type '" << typeid(*h).name() << "'";
858 
859  return a;
860  }
861 
863  auto access = this->accessMut();
864  update();
865  access.value.object_->SetXTitle(title.c_str());
866  }
868  auto access = this->accessMut();
869  update();
870  access.value.object_->SetYTitle(title.c_str());
871  }
872 
874  auto access = this->accessMut();
875  update();
876  if (access.value.object_->GetSumw2() == nullptr) {
877  access.value.object_->Sumw2();
878  }
879  }
880 
882  auto access = this->accessMut();
883  update();
884  access.value.object_->GetXaxis()->SetNoAlphanumeric(false);
885  access.value.object_->GetYaxis()->SetNoAlphanumeric(false);
886  }
887 
888  void MonitorElement::setOption(const char *option) {
889  auto access = this->accessMut();
890  update();
891  access.value.object_->SetOption(option);
892  }
893  double MonitorElement::getAxisMin(int axis) const {
894  auto access = this->access();
895  return getAxis(access, __PRETTY_FUNCTION__, axis)->GetXmin();
896  }
897 
898  double MonitorElement::getAxisMax(int axis) const {
899  auto access = this->access();
900  return getAxis(access, __PRETTY_FUNCTION__, axis)->GetXmax();
901  }
902 
903  void MonitorElement::setCanExtend(unsigned int value) {
904  auto access = this->accessMut();
905  access.value.object_->SetCanExtend(value);
906  }
907 
909  auto access = this->accessMut();
910  if (value == kTRUE)
911  access.value.object_->SetStatOverflows(TH1::kConsider);
912  else
913  access.value.object_->SetStatOverflows(TH1::kIgnore);
914  }
915 
917  auto access = this->accessMut();
918  auto value = access.value.object_->GetStatOverflows();
919  if (value == TH1::kConsider)
920  return true;
921  else
922  return false;
923  }
924 
925  int64_t MonitorElement::getIntValue() const {
926  assert(kind() == Kind::INT);
927  auto access = this->access();
928  return access.value.scalar_.num;
929  }
931  assert(kind() == Kind::REAL);
932  auto access = this->access();
933  return access.value.scalar_.real;
934  }
936  assert(kind() == Kind::STRING);
937  auto access = this->access();
938  return access.value.scalar_.str;
939  }
940 
942  const std::string &qtname,
944  DQMNet::QValue *&qv) {
945  auto access = this->accessMut();
946 
948 
949  assert(access.value.qreports_.size() == data_.qreports.size());
950 
951  qr = nullptr;
952  qv = nullptr;
953 
954  size_t pos = 0, end = access.value.qreports_.size();
955  while (pos < end && data_.qreports[pos].qtname != qtname)
956  ++pos;
957 
958  if (pos == end && !create)
959  return;
960  else if (pos == end) {
963  q.qtresult = 0;
964  q.qtname = qtname;
965  q.message = "NO_MESSAGE_ASSIGNED";
966  q.algorithm = "UNKNOWN_ALGORITHM";
969  }
970 
971  qr = &access.value.qreports_[pos];
972  qv = &(qr->getValue());
973  }
974 
975  // -------------------------------------------------------------------
976  // TODO: all of these are UNSAFE and have to be NON-const.
977  TObject const *MonitorElement::getRootObject() const {
978  auto access = this->access();
979  return access.value.object_.get();
980  }
981 
983  auto access = this->accessMut();
984  return accessRootObject(access, __PRETTY_FUNCTION__, 0);
985  }
986 
988  auto access = this->accessMut();
989  assert(kind() == Kind::TH1F);
990  return static_cast<TH1F *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
991  }
992 
994  auto access = this->accessMut();
995  assert(kind() == Kind::TH1S);
996  return static_cast<TH1S *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
997  }
998 
1000  auto access = this->accessMut();
1001  assert(kind() == Kind::TH1I);
1002  return static_cast<TH1I *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1003  }
1004 
1006  auto access = this->accessMut();
1007  assert(kind() == Kind::TH1D);
1008  return static_cast<TH1D *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1009  }
1010 
1012  auto access = this->accessMut();
1013  assert(kind() == Kind::TH2F);
1014  return static_cast<TH2F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1015  }
1016 
1018  auto access = this->accessMut();
1019  assert(kind() == Kind::TH2S);
1020  return static_cast<TH2S *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1021  }
1022 
1024  auto access = this->accessMut();
1025  assert(kind() == Kind::TH2I);
1026  return static_cast<TH2I *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1027  }
1028 
1030  auto access = this->accessMut();
1031  assert(kind() == Kind::TH2D);
1032  return static_cast<TH2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1033  }
1034 
1036  auto access = this->accessMut();
1037  assert(kind() == Kind::TH3F);
1038  return static_cast<TH3F *>(accessRootObject(access, __PRETTY_FUNCTION__, 3));
1039  }
1040 
1042  auto access = this->accessMut();
1043  assert(kind() == Kind::TPROFILE);
1044  return static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1045  }
1046 
1048  auto access = this->accessMut();
1050  return static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1051  }
1052 
1053 } // namespace dqm::impl
static const uint32_t DQM_PROP_REPORT_WARN
Definition: DQMNet.h:51
virtual void setTitle(const std::string &title)
set (ie. change) histogram/profile title
std::shared_ptr< MutableMonitorElementData > mutable_
uint32_t moduleId
Definition: DQMNet.h:96
std::string tagLabelString() const
return label string for the monitor element tag (eg. <name>t=12345</name>)
QReports qreports
Definition: DQMNet.h:99
virtual int getNbinsZ() const
get # of bins in Z-axis
virtual DQM_DEPRECATED void setCanExtend(unsigned int value)
virtual double getBinEntries(int bin) const
get # of bin entries (for profiles)
virtual void disableAlphanumeric()
std::shared_ptr< MutableMonitorElementData > release()
def create(alignables, pedeDump, additionalData, outputFile, config)
DQMNet::CoreObject data_
virtual double integral() const
get integral of bins
virtual void setEntries(double nentries)
set # of entries
virtual void setAxisTimeDisplay(int value, int axis=1)
set x-, y-, or z-axis to display time values
T w() const
MonitorElementData::Key const & key
Definition: DQMNet.h:25
virtual void setOption(const char *option)
virtual void setAxisTimeFormat(const char *format="", int axis=1)
set the format of the time values that are displayed on an axis
std::vector< MonitorElementData::QReport * > getQReports() const
get map of QReports
virtual double getRMSError(int axis=1) const
get RMS uncertainty of histogram along x, y or z axis(axis=1,2,3 respectively)
uint32_t flags
Definition: DQMNet.h:90
edm::propagate_const< std::unique_ptr< TH1 > > object_
std::vector< MonitorElementData::QReport * > getQOthers() const
from last set of quality tests
static bool CheckBinLabels(const TAxis *a1, const TAxis *a2)
Check the consistency of the axis labels.
std::vector< MonitorElementData::QReport * > filterQReports(FILTER filter) const
virtual std::string getAxisTitle(int axis=1) const
get x-, y- or z-axis title (axis=1, 2, 3 respectively)
Kind kind() const
Get the type of the monitor element.
static const int WARNING
static const uint32_t DQM_PROP_EFFICIENCY_PLOT
Definition: DQMNet.h:65
std::string effLabelString() const
return label string for the monitor element tag (eg. <name>t=12345</name>)
uint32_t tag
Definition: DQMNet.h:91
virtual bool getStatOverflows()
MonitorElement(MonitorElementData &&data)
assert(be >=bs)
const Access access() const
std::vector< MonitorElementData::QReport * > getQErrors() const
get errors from last set of quality tests
uint32_t run
Definition: DQMNet.h:93
void switchData(MonitorElement *other)
std::string valueString() const
constexpr element_type const * get() const
void Fill(long long x)
virtual void Reset()
Remove all data from the ME, keept the empty histogram with all its settings.
DQM_DEPRECATED void ShiftFillLast(double y, double ye=0., int32_t xscale=1)
char const * label
MonitorElementData::QReport QReport
virtual double getRMS(int axis=1) const
get RMS of histogram along x, y or z axis (axis=1, 2, 3 respectively)
virtual void setXTitle(std::string const &title)
virtual TProfile2D * getTProfile2D()
virtual void setAxisRange(double xmin, double xmax, int axis=1)
set x-, y- or z-axis range (axis=1, 2, 3 respectively)
const MonitorElementData::QReport * getQReport(const std::string &qtname) const
get QReport corresponding to <qtname> (null pointer if QReport does not exist)
virtual double getFloatValue() const
T sqrt(T t)
Definition: SSEVec.h:19
uint32_t lumi
Definition: DQMNet.h:94
void switchObject(std::unique_ptr< TH1 > &&newobject)
void doFill(int64_t x)
"Fill" ME method for int64_t
MonitorElementData cloneMEData()
std::string const & getDirname() const
TH1 const * accessRootObject(Access const &access, const char *func, int reqdim) const
void packScalarData(std::string &into, const char *prefix) const
convert scalar data into a string.
static const int DID_NOT_RUN
static const uint32_t DQM_PROP_REPORT_ERROR
Definition: DQMNet.h:50
TAxis const * getAxis(Access const &access, const char *func, int axis) const
std::string dirname
Definition: DQMNet.h:97
virtual double getEntries() const
get # of entries
Definition: value.py:1
static const uint32_t DQM_PROP_REPORT_OTHER
Definition: DQMNet.h:52
virtual void setBinLabel(int bin, const std::string &label, int axis=1)
set bin label for x, y or z axis (axis=1, 2, 3 respectively)
virtual TProfile * getTProfile()
std::string objname
Definition: DQMNet.h:98
virtual int getNbinsY() const
get # of bins in Y-axis
virtual std::string getTitle() const
get MonitorElement title
MonitorElementData::Value const & value
virtual TObject const * getRootObject() const
void update()
Mark the object updated.
std::string getFullname() const
get full name of ME including Pathname
std::vector< MonitorElementData::QReport * > getQWarnings() const
get warnings from last set of quality tests
virtual void setYTitle(std::string const &title)
virtual void setBinEntries(int bin, double nentries)
set # of bin entries (to be used for profiles)
#define N
Definition: blowfish.cc:9
virtual void setBinContent(int binx, double content)
set content of bin (1-D)
static constexpr float a0
std::string qualityTagString(const DQMNet::QValue &qv) const
double b
Definition: hdecay.h:120
virtual DQM_DEPRECATED void setStatOverflows(bool value)
static void packQualityData(std::string &into, const QReports &qr)
Definition: DQMNet.cc:154
std::string tagString() const
virtual double getAxisMin(int axis=1) const
virtual const std::string & getStringValue() const
virtual double getMean(int axis=1) const
get mean value of histogram along x, y or z axis (axis=1, 2, 3 respectively)
void packQualityData(std::string &into) const
serialise quality report information into a string.
std::vector< QReport > qreports_
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:80
double a
Definition: hdecay.h:121
virtual double getAxisMax(int axis=1) const
int getStatus() const
get test status
float x
static const int STATUS_OK
virtual int getBin(int binx, int biny) const
get global bin number (for 2-D profiles)
virtual int getNbinsX() const
get # of bins in X-axis
virtual double getBinError(int binx) const
get uncertainty on content of bin (1-D) - See TH1::GetBinError for details
auto zw(V v) -> Vec2< typename std::remove_reference< decltype(v[0])>::type >
Definition: ExtVec.h:71
QValue & getValue()
access underlying value
virtual void setBinError(int binx, double error)
set uncertainty on content of bin (1-D)
static TH1 * checkRootObject(const std::string &name, TObject *tobj, const char *func, int reqdim)
static const uint32_t DQM_PROP_NEW
Definition: DQMNet.h:60
Log< level::Warning, false > LogWarning
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
std::string const & getObjectname() const
uint32_t streamId
Definition: DQMNet.h:95
static const uint32_t DQM_PROP_LUMI
Definition: DQMNet.h:62
void incompatible(const char *func) const
if(threadIdxLocalY==0 &&threadIdxLocalX==0)
virtual double getMeanError(int axis=1) const
def move(src, dest)
Definition: eostools.py:511
virtual void divide(const MonitorElement *, const MonitorElement *, double, double, const char *)
Replace entries with results of dividing num by denom.
static const int ERROR
virtual double getBinContent(int binx) const
get content of bin (1-D)
virtual void setAxisTitle(const std::string &title, int axis=1)
set x-, y- or z-axis title (axis=1, 2, 3 respectively)
virtual int64_t getIntValue() const