CMS 3D CMS Logo

DQMStore.cc
Go to the documentation of this file.
7 #include "classlib/utils/RegexpMatch.h"
8 #include "classlib/utils/Regexp.h"
9 #include "classlib/utils/StringOps.h"
10 #include <google/protobuf/io/coded_stream.h>
11 #include <google/protobuf/io/gzip_stream.h>
12 #include <google/protobuf/io/zero_copy_stream_impl.h>
13 #include "TFile.h"
14 #include "TROOT.h"
15 #include "TKey.h"
16 #include "TClass.h"
17 #include "TSystem.h"
18 #include "TBufferFile.h"
19 #include <boost/algorithm/string.hpp>
20 #include <boost/range/iterator_range_core.hpp>
21 
22 #include <iterator>
23 #include <cerrno>
24 #include <exception>
25 #include <fstream>
26 #include <sstream>
27 #include <utility>
28 
55 namespace dqm::dqmstoreimpl {
56 
59  std::string const s_monitorDirName{"DQMData"};
60  std::string const s_referenceDirName{"Reference"};
61  std::string const s_collateDirName{"Collate"};
62  std::string const s_safe{"/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# "};
63 
64  lat::Regexp const s_rxmeval{"^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$"};
65  lat::Regexp const s_rxmeqr1{"^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$"};
66  lat::Regexp const s_rxmeqr2{"^st\\.(\\d+)\\.(.*)$"};
67  lat::Regexp const s_rxtrace{"(.*)\\((.*)\\+0x.*\\).*"};
68  lat::Regexp const s_rxself{"^[^()]*DQMStore::.*"};
69  lat::Regexp const s_rxpbfile{".*\\.pb$"};
70 
72 
76  bool isSubdirectory(std::string const& ofdir, std::string const& path) {
77  return (ofdir.empty() || (path.size() >= ofdir.size() && path.compare(0, ofdir.size(), ofdir) == 0 &&
78  (path.size() == ofdir.size() || path[ofdir.size()] == '/')));
79  }
80 
82  clean.clear();
83  cleaned = &path;
84 
85  size_t len = path.size();
86  for (; len > 0 && path[len - 1] == '/'; --len)
87  ;
88 
89  if (len != path.size()) {
90  clean = path.substr(0, len);
91  cleaned = &clean;
92  }
93  }
94 
96  size_t slash = path.rfind('/');
97  if (slash != std::string::npos) {
98  dir.append(path, 0, slash);
99  name.append(path, slash + 1, std::string::npos);
100  } else
101  name = path;
102  }
103 
105  path.reserve(dir.size() + name.size() + 2);
106  path += dir;
107  if (!path.empty())
108  path += '/';
109  path += name;
110  }
111 
112  template <class T>
114  return new T{qtname};
115  }
116 
117  template <class T>
119  m[T::getAlgoName()] = &makeQCriterion<T>;
120  }
121 
123  fastmatch::fastmatch(std::string fastString) : fastString_{move(fastString)}, matching_{UseFull} {
124  try {
125  regexp_ = std::make_unique<lat::Regexp>(fastString_, 0, lat::Regexp::Wildcard);
126  regexp_->study();
127  } catch (lat::Error& e) {
128  raiseDQMError("DQMStore",
129  "Invalid wildcard pattern '%s' in quality"
130  " test specification",
131  fastString_.c_str());
132  }
133 
134  // count stars ( "*" )
135  size_t starCount = 0;
136  int pos = -1;
137  while (true) {
138  pos = fastString_.find('*', pos + 1);
139  if ((size_t)pos == std::string::npos)
140  break;
141  ++starCount;
142  }
143 
144  // investigate for heuristics
145  if ((fastString_.find('"') != std::string::npos) || (fastString_.find(']') != std::string::npos) ||
146  (fastString_.find('?') != std::string::npos) || (fastString_.find('\\') != std::string::npos) ||
147  (starCount > 2)) {
148  // no fast version can be used
149  return;
150  }
151 
152  // match for pattern "*MyString" and "MyString*"
153  if (starCount == 1) {
154  if (boost::algorithm::starts_with(fastString_, "*")) {
156  fastString_.erase(0, 1);
157  return;
158  }
159 
160  if (boost::algorithm::ends_with(fastString_, "*")) {
162  fastString_.erase(fastString_.length() - 1, 1);
163  return;
164  }
165  }
166 
167  // match for pattern "*MyString*"
168  if (starCount == 2) {
169  if (boost::algorithm::starts_with(fastString_, "*") && boost::algorithm::ends_with(fastString_, "*")) {
170  matching_ = TwoStar;
171  fastString_.erase(0, 1);
172  fastString_.erase(fastString_.size() - 1, 1);
173  return;
174  }
175  }
176  }
177 
179  if (input.size() < pattern.size())
180  return false;
181 
182  // compare the two strings character by character for equalness:
183  // this does not create uneeded copies of std::string. The
184  // boost::algorithm implementation does
185  auto rit_pattern = pattern.crbegin();
186  auto rit_input = input.crbegin();
187 
188  for (; rit_pattern < pattern.rend(); ++rit_pattern, ++rit_input) {
189  if (*rit_pattern != *rit_input)
190  // found a difference, fail
191  return false;
192  }
193  return true;
194  }
195 
197  if (input.size() < pattern.size())
198  return false;
199 
200  // compare the two strings character by character for equalness:
201  // this does not create uneeded copies of std::string. The
202  // boost::algorithm implementation does.
203  auto rit_pattern = pattern.cbegin();
204  auto rit_input = input.cbegin();
205 
206  for (; rit_pattern < pattern.end(); ++rit_pattern, ++rit_input) {
207  if (*rit_pattern != *rit_input)
208  // found a difference, fail
209  return false;
210  }
211  return true;
212  }
213 
214  bool fastmatch::match(std::string const& s) const {
215  switch (matching_) {
216  case OneStarStart:
218 
219  case OneStarEnd:
220  return compare_strings(fastString_, s);
221 
222  case TwoStar:
223  return (s.find(fastString_) != std::string::npos);
224 
225  default:
226  return regexp_->match(s);
227  }
228  }
229 
230  //IBooker methods
231  MonitorElement* DQMStore::IBooker::bookInt(TString const& name) { return owner_->bookInt(name); }
232 
233  MonitorElement* DQMStore::IBooker::bookFloat(TString const& name) { return owner_->bookFloat(name); }
234 
235  MonitorElement* DQMStore::IBooker::bookString(TString const& name, TString const& value) {
236  return owner_->bookString(name, value);
237  }
238 
240  TString const& name, TString const& title, int const nchX, double const lowX, double const highX) {
241  return owner_->book1D(name, title, nchX, lowX, highX);
242  }
243 
244  MonitorElement* DQMStore::IBooker::book1D(TString const& name, TString const& title, int nchX, float const* xbinsize) {
245  return owner_->book1D(name, title, nchX, xbinsize);
246  };
247 
248  MonitorElement* DQMStore::IBooker::book1D(TString const& name, TH1F* object) { return owner_->book1D(name, object); }
249 
251  TString const& name, TString const& title, int nchX, double lowX, double highX) {
252  return owner_->book1S(name, title, nchX, lowX, highX);
253  }
254 
255  MonitorElement* DQMStore::IBooker::book1S(TString const& name, TH1S* object) { return owner_->book1S(name, object); }
256 
258  TString const& name, TString const& title, int nchX, double lowX, double highX) {
259  return owner_->book1DD(name, title, nchX, lowX, highX);
260  }
261 
262  MonitorElement* DQMStore::IBooker::book1DD(TString const& name, TH1D* object) {
263  return owner_->book1DD(name, object);
264  }
265 
267  TString const& title,
268  int nchX,
269  double lowX,
270  double highX,
271  int nchY,
272  double lowY,
273  double highY) {
274  return owner_->book2D(name, title, nchX, lowX, highX, nchY, lowY, highY);
275  }
276 
278  TString const& name, TString const& title, int nchX, float const* xbinsize, int nchY, float const* ybinsize) {
279  return owner_->book2D(name, title, nchX, xbinsize, nchY, ybinsize);
280  }
281 
282  MonitorElement* DQMStore::IBooker::book2D(TString const& name, TH2F* object) { return owner_->book2D(name, object); }
283 
285  TString const& title,
286  int nchX,
287  double lowX,
288  double highX,
289  int nchY,
290  double lowY,
291  double highY) {
292  return owner_->book2S(name, title, nchX, lowX, highX, nchY, lowY, highY);
293  }
294 
296  TString const& name, TString const& title, int nchX, float const* xbinsize, int nchY, float const* ybinsize) {
297  return owner_->book2S(name, title, nchX, xbinsize, nchY, ybinsize);
298  }
299 
300  MonitorElement* DQMStore::IBooker::book2S(TString const& name, TH2S* object) { return owner_->book2S(name, object); }
301 
303  TString const& title,
304  int nchX,
305  double lowX,
306  double highX,
307  int nchY,
308  double lowY,
309  double highY) {
310  return owner_->book2DD(name, title, nchX, lowX, highX, nchY, lowY, highY);
311  }
312 
313  MonitorElement* DQMStore::IBooker::book2DD(TString const& name, TH2D* object) {
314  return owner_->book2DD(name, object);
315  }
316 
318  TString const& title,
319  int nchX,
320  double lowX,
321  double highX,
322  int nchY,
323  double lowY,
324  double highY,
325  int nchZ,
326  double lowZ,
327  double highZ) {
328  return owner_->book3D(name, title, nchX, lowX, highX, nchY, lowY, highY, nchZ, lowZ, highZ);
329  }
330 
331  MonitorElement* DQMStore::IBooker::book3D(TString const& name, TH3F* object) { return owner_->book3D(name, object); }
332 
334  TString const& title,
335  int nchX,
336  double lowX,
337  double highX,
338  int nchY,
339  double lowY,
340  double highY,
341  char const* option) {
342  return owner_->bookProfile(name, title, nchX, lowX, highX, nchY, lowY, highY, option);
343  }
344 
346  TString const& title,
347  int nchX,
348  double lowX,
349  double highX,
350  double lowY,
351  double highY,
352  char const* option) {
353  return owner_->bookProfile(name, title, nchX, lowX, highX, lowY, highY, option);
354  }
355 
357  TString const& title,
358  int nchX,
359  double const* xbinsize,
360  int nchY,
361  double lowY,
362  double highY,
363  char const* option) {
364  return owner_->bookProfile(name, title, nchX, xbinsize, nchY, lowY, highY, option);
365  }
366 
368  TString const& title,
369  int nchX,
370  double const* xbinsize,
371  double lowY,
372  double highY,
373  char const* option) {
374  return owner_->bookProfile(name, title, nchX, xbinsize, lowY, highY, option);
375  }
376 
377  MonitorElement* DQMStore::IBooker::bookProfile(TString const& name, TProfile* object) {
378  return owner_->bookProfile(name, object);
379  }
380 
382  TString const& title,
383  int nchX,
384  double lowX,
385  double highX,
386  int nchY,
387  double lowY,
388  double highY,
389  double lowZ,
390  double highZ,
391  char const* option) {
392  return owner_->bookProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, lowZ, highZ, option);
393  }
394 
396  TString const& title,
397  int nchX,
398  double lowX,
399  double highX,
400  int nchY,
401  double lowY,
402  double highY,
403  int nchZ,
404  double lowZ,
405  double highZ,
406  char const* option) {
407  return owner_->bookProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, nchZ, lowZ, highZ, option);
408  }
409 
410  MonitorElement* DQMStore::IBooker::bookProfile2D(TString const& name, TProfile2D* object) {
411  return owner_->bookProfile2D(name, object);
412  }
413 
414  void DQMStore::IBooker::cd() { owner_->cd(); }
415 
416  void DQMStore::IBooker::cd(std::string const& dir) { owner_->cd(dir); }
417 
418  void DQMStore::IBooker::setCurrentFolder(std::string const& fullpath) { owner_->setCurrentFolder(fullpath); }
419 
420  void DQMStore::IGetter::cd() { owner_->cd(); }
421 
422  void DQMStore::IGetter::cd(std::string const& dir) { owner_->cd(dir); }
423 
424  void DQMStore::IGetter::setCurrentFolder(std::string const& fullpath) { owner_->setCurrentFolder(fullpath); }
425 
426  void DQMStore::IBooker::goUp() { owner_->goUp(); }
427 
428  std::string const& DQMStore::IBooker::pwd() { return owner_->pwd(); }
429 
430  //IGetter methods
431  std::vector<MonitorElement*> DQMStore::IGetter::getAllContents(std::string const& path,
432  uint32_t const run /* = 0 */,
433  uint32_t const lumi /* = 0 */) {
434  return owner_->getAllContents(path, run, lumi);
435  }
436 
437  MonitorElement* DQMStore::IGetter::get(std::string const& path) { return owner_->get(path); }
438 
440  MonitorElement* ptr = this->get(path);
441  if (ptr == nullptr) {
442  std::stringstream msg;
443  msg << "DQM object not found";
444 
445  msg << ": " << path;
446 
447  // can't use cms::Exception inside DQMStore
448  throw std::out_of_range(msg.str());
449  }
450  return ptr;
451  }
452 
453  std::vector<std::string> DQMStore::IGetter::getSubdirs() { return owner_->getSubdirs(); }
454 
455  std::vector<std::string> DQMStore::IGetter::getMEs() { return owner_->getMEs(); }
456 
458  return owner_->containsAnyMonitorable(path);
459  }
460 
461  bool DQMStore::IGetter::dirExists(std::string const& path) { return owner_->dirExists(path); }
462 
465  ar.preallocateSignal_.connect([this](edm::service::SystemBounds const& iBounds) {
466  if (iBounds.maxNumberOfStreams() > 1) {
467  enableMultiThread_ = true;
468  }
469  });
470  if (pset.getUntrackedParameter<bool>("forceResetOnBeginRun", false)) {
471  ar.watchPostSourceRun([this](edm::RunIndex) { forceReset(); });
472  }
473  if (pset.getUntrackedParameter<bool>("forceResetOnBeginLumi", false) && enableMultiThread_ == false) {
474 #if !WITHOUT_CMS_FRAMEWORK
475  forceResetOnBeginLumi_ = true;
476  ar.watchPreSourceLumi([this](edm::LuminosityBlockIndex) { forceReset(); });
477 #endif
478  }
479  ar.watchPostGlobalBeginLumi(this, &DQMStore::postGlobalBeginLumi);
480  }
481 
483 
485  for (auto& qtest : qtests_)
486  delete qtest.second;
487 
488  for (auto& qtestspec : qtestspecs_)
489  delete qtestspec.first;
490  }
491 
493  makeDirectory("");
494  reset();
495 
496  // set steerable parameters
497  verbose_ = pset.getUntrackedParameter<int>("verbose", 0);
498  if (verbose_ > 0)
499  std::cout << "DQMStore: verbosity set to " << verbose_ << std::endl;
500 
501  verboseQT_ = pset.getUntrackedParameter<int>("verboseQT", 0);
502  if (verbose_ > 0)
503  std::cout << "DQMStore: QTest verbosity set to " << verboseQT_ << std::endl;
504 
505  collateHistograms_ = pset.getUntrackedParameter<bool>("collateHistograms", false);
506  if (collateHistograms_)
507  std::cout << "DQMStore: histogram collation is enabled\n";
508 
509  enableMultiThread_ = pset.getUntrackedParameter<bool>("enableMultiThread", false);
510  if (enableMultiThread_)
511  std::cout << "DQMStore: MultiThread option is enabled\n";
512 
513  LSbasedMode_ = pset.getUntrackedParameter<bool>("LSbasedMode", false);
514  if (LSbasedMode_)
515  std::cout << "DQMStore: LSbasedMode option is enabled\n";
516 
517  doSaveByLumi_ = pset.getUntrackedParameter<bool>("saveByLumi", false);
518  if (doSaveByLumi_)
519  std::cout << "DQMStore: saveByLumi option is enabled\n";
520 
521  std::string ref = pset.getUntrackedParameter<std::string>("referenceFileName", "");
522  if (!ref.empty()) {
523  std::cout << "DQMStore: using reference file '" << ref << "'\n";
524  readFile(ref, true, "", s_referenceDirName, StripRunDirs, false);
525  }
526 
527  initQCriterion<ContentsXRange>(qalgos_);
528  initQCriterion<ContentsYRange>(qalgos_);
529  initQCriterion<MeanWithinExpected>(qalgos_);
530  initQCriterion<DeadChannel>(qalgos_);
531  initQCriterion<NoisyChannel>(qalgos_);
532  initQCriterion<ContentSigma>(qalgos_);
533  initQCriterion<ContentsWithinExpected>(qalgos_);
534  initQCriterion<CompareToMedian>(qalgos_);
535  initQCriterion<CompareLastFilledBin>(qalgos_);
536  initQCriterion<CheckVariance>(qalgos_);
537 
538  scaleFlag_ = pset.getUntrackedParameter<double>("ScalingFlag", 0.0);
539  if (verbose_ > 0)
540  std::cout << "DQMStore: Scaling Flag set to " << scaleFlag_ << std::endl;
541  }
542 
543  /* Generic method to do a backtrace and print it to stdout. It is
544  customised to properly get the routine that called the booking of the
545  histograms, which, following the usual stack, is at position 4. The
546  name of the calling function is properly demangled and the original
547  shared library including this function is also printed. For a more
548  detailed explanation of the routines involved, see here:
549  http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
550  http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html.*/
551 
553  // the access to the member stream_ is implicitely protected against
554  // concurrency problems because the print_trace method is always called behind
555  // a lock (see bookTransaction).
556  if (!stream_)
557  stream_ = std::make_unique<std::ofstream>("histogramBookingBT.log");
558 
559  void* array[10];
560  size_t size;
561  char** strings;
562  int r = 0;
563  lat::RegexpMatch m;
564  m.reset();
565 
566  size = backtrace(array, 10);
567  strings = backtrace_symbols(array, size);
568 
569  size_t level = 1;
570  char* demangled = nullptr;
571  for (; level < size; ++level) {
572  if (!s_rxtrace.match(strings[level], 0, 0, &m))
573  continue;
574  demangled = abi::__cxa_demangle(m.matchString(strings[level], 2).c_str(), nullptr, nullptr, &r);
575  if (!demangled)
576  continue;
577  if (!s_rxself.match(demangled, 0, 0))
578  break;
579  free(demangled);
580  demangled = nullptr;
581  }
582 
583  if (demangled != nullptr) {
584  *stream_ << "\"" << dir << "/" << name << "\" " << (r ? m.matchString(strings[level], 2) : demangled) << " "
585  << m.matchString(strings[level], 1) << "\n";
586  free(demangled);
587  } else {
588  *stream_ << "Skipping " << dir << "/" << name << " with stack size " << size << "\n";
589  }
590 
591  /* In this case print the full stack trace, up to main or to the
592  * maximum stack size, i.e. 10. */
593  if (verbose_ > 4 || demangled == nullptr) {
594  size_t i;
595  m.reset();
596 
597  for (i = 0; i < size; ++i)
598  if (s_rxtrace.match(strings[i], 0, 0, &m)) {
599  char* demangled = abi::__cxa_demangle(m.matchString(strings[i], 2).c_str(), nullptr, nullptr, &r);
600  *stream_ << "\t\t" << i << "/" << size << " " << (r ? m.matchString(strings[i], 2) : demangled) << " "
601  << m.matchString(strings[i], 1) << std::endl;
602  free(demangled);
603  }
604  }
605  free(strings);
606  }
607 
612  void DQMStore::setVerbose(unsigned /* level */) {}
613 
618  std::string const& DQMStore::pwd() const { return pwd_; }
619 
622 
624  void DQMStore::cd(std::string const& subdir) {
626  std::string const* cleaned = nullptr;
627  cleanTrailingSlashes(subdir, clean, cleaned);
628 
629  if (!dirExists(*cleaned))
630  raiseDQMError("DQMStore", "Cannot 'cd' into non-existent directory '%s'", cleaned->c_str());
631 
632  setCurrentFolder(*cleaned);
633  }
634 
641  std::string const* cleaned = nullptr;
642  cleanTrailingSlashes(fullpath, clean, cleaned);
643  makeDirectory(*cleaned);
644  pwd_ = *cleaned;
645  }
646 
648  void DQMStore::goUp() {
649  size_t pos = pwd_.rfind('/');
650  if (pos == std::string::npos)
651  setCurrentFolder("");
652  else
653  setCurrentFolder(pwd_.substr(0, pos));
654  }
655 
656  // -------------------------------------------------------------------
660  std::string prev;
661  std::string subdir;
663  prev.reserve(path.size());
664  subdir.reserve(path.size());
665  name.reserve(path.size());
666  size_t prevname = 0;
667  size_t slash = 0;
668 
669  while (true) {
670  // Create this subdirectory component.
671  subdir.clear();
672  subdir.append(path, 0, slash);
673  name.clear();
674  name.append(subdir, prevname, std::string::npos);
675  if (!prev.empty() && findObject(0, 0, 0, prev, name))
676  raiseDQMError("DQMStore",
677  "Attempt to create subdirectory '%s'"
678  " which already exists as a monitor element",
679  subdir.c_str());
680 
681  if (!dirs_.count(subdir))
682  dirs_.insert(subdir);
683 
684  // Stop if we've reached the end (including possibly a trailing slash).
685  if (slash + 1 >= path.size())
686  break;
687 
688  // Find the next slash, making sure we progress. If reach the end,
689  // process the last path component; the next loop round will terminate.
690  prevname = slash ? slash + 1 : slash;
691  prev = subdir;
692  if ((slash = path.find('/', ++slash)) == std::string::npos)
693  slash = path.size();
694  }
695  }
696 
698  bool DQMStore::dirExists(std::string const& path) const { return dirs_.count(path) > 0; }
699 
700  // //====================================================
701  // // Global-histogram booking
702  // MonitorElement*
703  // DQMStore::bookInt(char_string const& name)
704  // {
705  // return bookInt(0, 0, pwd_, name);
706  // }
707 
708  // MonitorElement*
709  // DQMStore::bookFloat(char_string const& name)
710  // {
711  // return bookFloat(0, 0, pwd_, name);
712  // }
713 
714  // MonitorElement*
715  // DQMStore::bookString(char_string const& name,
716  // char_string const& value)
717  // {
718  // return bookString(0, 0, pwd_, name, value);
719  // }
720 
721  // MonitorElement*
722  // DQMStore::book1D(char_string const& name,
723  // char_string const& title,
724  // int const nchX, double const lowX, double const highX)
725  // {
726  // return book1D(0, 0, pwd_, name, title, nchX, lowX, highX);
727  // }
728 
729  // MonitorElement*
730  // DQMStore::book1D(char_string const& name,
731  // char_string const& title,
732  // int const nchX, float const* xbinsize)
733  // {
734  // return book1D(0, 0, pwd_, name, title, nchX, xbinsize);
735  // }
736 
737  // MonitorElement*
738  // DQMStore::book1D(char_string const& name, TH1F* h)
739  // {
740  // return book1D(0, 0, pwd_, name, h);
741  // }
742 
743  // MonitorElement*
744  // DQMStore::book1S(char_string const& name,
745  // char_string const& title,
746  // int const nchX, double const lowX, double const highX)
747  // {
748  // return book1S(0, 0, pwd_, name, title, nchX, lowX, highX);
749  // }
750 
751  // MonitorElement*
752  // DQMStore::book1S(char_string const& name,
753  // char_string const& title,
754  // int const nchX, float const* xbinsize)
755  // {
756  // return book1S(0, 0, pwd_, name, title, nchX, xbinsize);
757  // }
758 
759  // MonitorElement*
760  // DQMStore::book1S(char_string const& name, TH1S* h)
761  // {
762  // return book1S(0, 0, pwd_, name, h);
763  // }
764 
765  // MonitorElement*
766  // DQMStore::book1DD(char_string const& name,
767  // char_string const& title,
768  // int const nchX, double const lowX, double const highX)
769  // {
770  // return book1DD(0, 0, pwd_, name, title, nchX, lowX, highX);
771  // }
772 
773  // MonitorElement*
774  // DQMStore::book1DD(char_string const& name,
775  // char_string const& title,
776  // int const nchX, float const* xbinsize)
777  // {
778  // return book1DD(0, 0, pwd_, name, title, nchX, xbinsize);
779  // }
780 
781  // MonitorElement*
782  // DQMStore::book1DD(char_string const& name, TH1D* h)
783  // {
784  // return book1DD(0, 0, pwd_, name, h);
785  // }
786 
787  // MonitorElement*
788  // DQMStore::book2D(char_string const& name,
789  // char_string const& title,
790  // int const nchX, double const lowX, double const highX,
791  // int const nchY, double const lowY, double const highY)
792  // {
793  // return book2D(0, 0, pwd_, name, title, nchX, lowX, highX, nchY, lowY, highY);
794  // }
795 
796  // MonitorElement*
797  // DQMStore::book2D(char_string const& name,
798  // char_string const& title,
799  // int const nchX, float const* xbinsize,
800  // int const nchY, float const* ybinsize)
801  // {
802  // return book2D(0, 0, pwd_, name, title, nchX, xbinsize, nchY, ybinsize);
803  // }
804 
805  // MonitorElement*
806  // DQMStore::book2D(char_string const& name, TH2F* h)
807  // {
808  // return book2D(0, 0, pwd_, name, h);
809  // }
810 
811  // MonitorElement*
812  // DQMStore::book2S(char_string const& name,
813  // char_string const& title,
814  // int const nchX, double const lowX, double const highX,
815  // int const nchY, double const lowY, double const highY)
816  // {
817  // return book2S(0, 0, pwd_, name, title, nchX, lowX, highX, nchY, lowY, highY);
818  // }
819 
820  // MonitorElement*
821  // DQMStore::book2S(char_string const& name,
822  // char_string const& title,
823  // int const nchX, float const* xbinsize,
824  // int const nchY, float const* ybinsize)
825  // {
826  // return book2S(0, 0, pwd_, name, title, nchX, xbinsize, nchY, ybinsize);
827  // }
828 
829  // MonitorElement*
830  // DQMStore::book2S(char_string const& name, TH2S* h)
831  // {
832  // return book2S(0, 0, pwd_, name, h);
833  // }
834 
835  // MonitorElement*
836  // DQMStore::book2DD(char_string const& name,
837  // char_string const& title,
838  // int const nchX, double const lowX, double const highX,
839  // int const nchY, double const lowY, double const highY)
840  // {
841  // return book2DD(0, 0, pwd_, name, title, nchX, lowX, highX, nchY, lowY, highY);
842  // }
843 
844  // MonitorElement*
845  // DQMStore::book2DD(char_string const& name,
846  // char_string const& title,
847  // int const nchX, float const* xbinsize,
848  // int const nchY, float const* ybinsize)
849  // {
850  // return book2DD(0, 0, pwd_, name, title, nchX, xbinsize, nchY, ybinsize);
851  // }
852 
853  // MonitorElement*
854  // DQMStore::book2DD(char_string const& name, TH2D* h)
855  // {
856  // return book2DD(0, 0, pwd_, name, h);
857  // }
858 
859  // MonitorElement*
860  // DQMStore::book3D(char_string const& name,
861  // char_string const& title,
862  // int const nchX, double const lowX, double const highX,
863  // int const nchY, double const lowY, double const highY,
864  // int const nchZ, double const lowZ, double const highZ)
865  // {
866  // return book3D(0, 0, pwd_, name, title,
867  // nchX, lowX, highX,
868  // nchY, lowY, highY,
869  // nchZ, lowZ, highZ);
870  // }
871 
872  // MonitorElement*
873  // DQMStore::book3D(char_string const& name, TH3F* h)
874  // {
875  // return book3D(0, 0, pwd_, name, h);
876  // }
877 
878  // MonitorElement*
879  // DQMStore::bookProfile(char_string const& name,
880  // char_string const& title,
881  // int const nchX, double const lowX, double const highX,
882  // int const nchY, double const lowY, double const highY,
883  // char const* option)
884  // {
885  // return bookProfile(0, 0, pwd_, name, title, nchX, lowX, highX, nchY, lowY, highY, option);
886  // }
887 
888  // MonitorElement*
889  // DQMStore::bookProfile(char_string const& name,
890  // char_string const& title,
891  // int const nchX, double const lowX, double const highX,
892  // double const lowY, double const highY,
893  // char const* option)
894  // {
895  // return bookProfile(0, 0, pwd_, name, title, nchX, lowX, highX, lowY, highY, option);
896  // }
897 
898  // MonitorElement*
899  // DQMStore::bookProfile(char_string const& name,
900  // char_string const& title,
901  // int const nchX, double const* xbinsize,
902  // int const nchY, double const lowY, double const highY,
903  // char const* option)
904  // {
905  // return bookProfile(0, 0, pwd_, name, title, nchX, xbinsize, nchY, lowY, highY, option);
906  // }
907 
908  // MonitorElement*
909  // DQMStore::bookProfile(char_string const& name,
910  // char_string const& title,
911  // int const nchX, double const* xbinsize,
912  // double const lowY, double const highY,
913  // char const* option)
914  // {
915  // return bookProfile(0, 0, pwd_, name, title, nchX, xbinsize, lowY, highY, option);
916  // }
917 
918  // MonitorElement*
919  // DQMStore::bookProfile(char_string const& name, TProfile* h)
920  // {
921  // return bookProfile(0, 0, pwd_, name, h);
922  // }
923 
924  // MonitorElement*
925  // DQMStore::bookProfile2D(char_string const& name,
926  // char_string const& title,
927  // int const nchX, double const lowX, double const highX,
928  // int const nchY, double const lowY, double const highY,
929  // int const nchZ, double const lowZ, double const highZ,
930  // char const* option)
931  // {
932  // return bookProfile2D(0, 0, pwd_, name, title,
933  // nchX, lowX, highX,
934  // nchY, lowY, highY,
935  // nchZ, lowZ, highZ, option);
936  // }
937 
938  // MonitorElement*
939  // DQMStore::bookProfile2D(char_string const& name,
940  // char_string const& title,
941  // int const nchX, double const lowX, double const highX,
942  // int const nchY, double const lowY, double const highY,
943  // double const lowZ, double const highZ,
944  // char const* option)
945  // {
946  // return bookProfile2D(0, 0, pwd_, name, title,
947  // nchX, lowX, highX,
948  // nchY, lowY, highY,
949  // lowZ, highZ, option);
950  // }
951 
952  // MonitorElement*
953  // DQMStore::bookProfile2D(char_string const& name, TProfile2D* h)
954  // {
955  // return bookProfile2D(0, 0, pwd_, name, h);
956  // }
957 
961  template <class HISTO, class COLLATE>
963  std::string const& name,
964  char const* context,
966  HISTO* h,
967  COLLATE collate) {
968  assert(name.find('/') == std::string::npos);
969  if (verbose_ > 3)
970  print_trace(dir, name);
972  mergePath(path, dir, name);
973 
974  // Put us in charge of h.
975  h->SetDirectory(nullptr);
976 
977  // Check if the request monitor element already exists.
978  MonitorElement* me = findObject(run_, 0, moduleId_, dir, name);
979  if (me) {
980  if (collateHistograms_) {
981  collate(me, h, verbose_);
982  delete h;
983  return me;
984  } else {
985  if (verbose_ > 1)
986  std::cout << "DQMStore: " << context << ": monitor element '" << path << "' already exists, collating"
987  << std::endl;
988  me->Reset();
989  collate(me, h, verbose_);
990  delete h;
991  return me;
992  }
993  } else {
994  // Create and initialise core object.
995  assert(dirs_.count(dir));
996  MonitorElement proto(&*dirs_.find(dir), name, run_, moduleId_);
997  if (doSaveByLumi_ && canSaveByLumi_) {
998  // for legacy (not DQMEDAnalyzer) this is not save.
999  proto.setLumiFlag(); // default to per-lumi mode for all non-legacy MEs.
1000  }
1001  me = (MonitorElement*)const_cast<MonitorElement&>(*data_.insert(std::move(proto)).first)
1003 
1004  // Initialise quality test information.
1005  for (auto const& q : qtestspecs_) {
1006  if (q.first->match(path))
1007  me->addQReport(q.second);
1008  }
1009 
1010  // If we just booked a (plain) MonitorElement, and there is a reference
1011  // MonitorElement with the same name, link the two together.
1012  // The other direction is handled by the extract method.
1013  std::string refdir;
1014  refdir.reserve(s_referenceDirName.size() + dir.size() + 1);
1015  refdir += s_referenceDirName;
1016  refdir += '/';
1017  refdir += dir;
1018  MonitorElement* referenceME = findObject(0, 0, 0, refdir, name);
1019  if (referenceME) {
1020  // We have booked a new MonitorElement with a specific dir and name.
1021  // Then, if we can find the corresponding MonitorElement in the reference
1022  // dir we assign the object_ of the reference MonitorElement to the
1023  // reference_ property of our new MonitorElement.
1025  me->reference_ = referenceME->getTH1();
1026  }
1027 
1028  // Return the monitor element.
1029  return me;
1030  }
1031  }
1032 
1033  MonitorElement* DQMStore::book_(std::string const& dir, std::string const& name, char const* context) {
1034  assert(name.find('/') == std::string::npos);
1035  if (verbose_ > 3)
1036  print_trace(dir, name);
1037 
1038  // Check if the request monitor element already exists.
1039  if (MonitorElement* me = findObject(run_, 0, moduleId_, dir, name)) {
1040  if (verbose_ > 1) {
1041  std::string path;
1042  mergePath(path, dir, name);
1043 
1044  std::cout << "DQMStore: " << context << ": monitor element '" << path << "' already exists, resetting"
1045  << std::endl;
1046  }
1047  me->Reset();
1048  return me;
1049  } else {
1050  // Create it and return for initialisation.
1051  assert(dirs_.count(dir));
1052  MonitorElement proto(&*dirs_.find(dir), name, run_, moduleId_);
1053  // this is used only for Int/String/Float. We don't save these by lumi by
1054  // default, since we can't merge them properly.
1055  return &const_cast<MonitorElement&>(*data_.insert(std::move(proto)).first);
1056  }
1057  }
1058 
1059  // -------------------------------------------------------------------
1062  if (collateHistograms_) {
1063  if (MonitorElement* me = findObject(run_, 0, moduleId_, dir, name)) {
1064  me->Fill(0);
1065  return me;
1066  }
1067  }
1068  return (MonitorElement*)book_(dir, name, "bookInt")->initialise(MonitorElement::Kind::INT);
1069  }
1070 
1073 
1074  // -------------------------------------------------------------------
1077  if (collateHistograms_) {
1078  if (MonitorElement* me = findObject(run_, 0, moduleId_, dir, name)) {
1079  me->Fill(0.);
1080  return me;
1081  }
1082  }
1083  return (MonitorElement*)book_(dir, name, "bookFloat")->initialise(MonitorElement::Kind::REAL);
1084  }
1085 
1088 
1089  // -------------------------------------------------------------------
1092  if (collateHistograms_) {
1093  if (MonitorElement* me = findObject(run_, 0, moduleId_, dir, name))
1094  return me;
1095  }
1096  return (MonitorElement*)book_(dir, name, "bookString")->initialise(MonitorElement::Kind::STRING, value);
1097  }
1098 
1101  return bookString_(pwd_, name, value);
1102  }
1103 
1104  // -------------------------------------------------------------------
1107  return book_(dir, name, "book1D", MonitorElement::Kind::TH1F, h, collate1D);
1108  }
1109 
1112  return book_(dir, name, "book1S", MonitorElement::Kind::TH1S, h, collate1S);
1113  }
1114 
1117  return book_(dir, name, "book1DD", MonitorElement::Kind::TH1D, h, collate1DD);
1118  }
1119 
1122  char_string const& name, char_string const& title, int const nchX, double const lowX, double const highX) {
1123  return book1D_(pwd_, name, new TH1F(name, title, nchX, lowX, highX));
1124  }
1125 
1128  char_string const& name, char_string const& title, int const nchX, double const lowX, double const highX) {
1129  return book1S_(pwd_, name, new TH1S(name, title, nchX, lowX, highX));
1130  }
1131 
1134  char_string const& name, char_string const& title, int const nchX, double const lowX, double const highX) {
1135  return book1DD_(pwd_, name, new TH1D(name, title, nchX, lowX, highX));
1136  }
1137 
1140  char_string const& title,
1141  int const nchX,
1142  const float* xbinsize) {
1143  return book1D_(pwd_, name, new TH1F(name, title, nchX, xbinsize));
1144  }
1145 
1148  return book1D_(pwd_, name, static_cast<TH1F*>(source->Clone(name)));
1149  }
1150 
1153  return book1S_(pwd_, name, static_cast<TH1S*>(source->Clone(name)));
1154  }
1155 
1158  return book1DD_(pwd_, name, static_cast<TH1D*>(source->Clone(name)));
1159  }
1160 
1161  // -------------------------------------------------------------------
1164  return book_(dir, name, "book2D", MonitorElement::Kind::TH2F, h, collate2D);
1165  }
1166 
1169  return book_(dir, name, "book2S", MonitorElement::Kind::TH2S, h, collate2S);
1170  }
1171 
1174  return book_(dir, name, "book2DD", MonitorElement::Kind::TH2D, h, collate2DD);
1175  }
1176 
1179  char_string const& title,
1180  int const nchX,
1181  double const lowX,
1182  double const highX,
1183  int const nchY,
1184  double const lowY,
1185  double const highY) {
1186  return book2D_(pwd_, name, new TH2F(name, title, nchX, lowX, highX, nchY, lowY, highY));
1187  }
1188 
1191  char_string const& title,
1192  int const nchX,
1193  double const lowX,
1194  double const highX,
1195  int const nchY,
1196  double const lowY,
1197  double const highY) {
1198  return book2S_(pwd_, name, new TH2S(name, title, nchX, lowX, highX, nchY, lowY, highY));
1199  }
1200 
1203  char_string const& title,
1204  int const nchX,
1205  double const lowX,
1206  double const highX,
1207  int const nchY,
1208  double const lowY,
1209  double const highY) {
1210  return book2DD_(pwd_, name, new TH2D(name, title, nchX, lowX, highX, nchY, lowY, highY));
1211  }
1212 
1215  char_string const& title,
1216  int const nchX,
1217  const float* xbinsize,
1218  int const nchY,
1219  const float* ybinsize) {
1220  return book2D_(pwd_, name, new TH2F(name, title, nchX, xbinsize, nchY, ybinsize));
1221  }
1222 
1225  char_string const& title,
1226  int const nchX,
1227  const float* xbinsize,
1228  int const nchY,
1229  const float* ybinsize) {
1230  return book2S_(pwd_, name, new TH2S(name, title, nchX, xbinsize, nchY, ybinsize));
1231  }
1232 
1235  return book2D_(pwd_, name, static_cast<TH2F*>(source->Clone(name)));
1236  }
1237 
1240  return book2S_(pwd_, name, static_cast<TH2S*>(source->Clone(name)));
1241  }
1242 
1245  return book2DD_(pwd_, name, static_cast<TH2D*>(source->Clone(name)));
1246  }
1247 
1248  // -------------------------------------------------------------------
1251  return book_(dir, name, "book3D", MonitorElement::Kind::TH3F, h, collate3D);
1252  }
1253 
1256  char_string const& title,
1257  int const nchX,
1258  double const lowX,
1259  double const highX,
1260  int const nchY,
1261  double const lowY,
1262  double const highY,
1263  int const nchZ,
1264  double const lowZ,
1265  double const highZ) {
1266  return book3D_(pwd_, name, new TH3F(name, title, nchX, lowX, highX, nchY, lowY, highY, nchZ, lowZ, highZ));
1267  }
1268 
1271  return book3D_(pwd_, name, static_cast<TH3F*>(source->Clone(name)));
1272  }
1273 
1274  // -------------------------------------------------------------------
1277  return book_(dir, name, "bookProfile", MonitorElement::Kind::TPROFILE, h, collateProfile);
1278  }
1279 
1284  char_string const& title,
1285  int const nchX,
1286  double const lowX,
1287  double const highX,
1288  int /* nchY */,
1289  double const lowY,
1290  double const highY,
1291  char const* option /* = "s" */) {
1292  return bookProfile_(pwd_, name, new TProfile(name, title, nchX, lowX, highX, lowY, highY, option));
1293  }
1294 
1299  char_string const& title,
1300  int const nchX,
1301  double const lowX,
1302  double const highX,
1303  double const lowY,
1304  double const highY,
1305  char const* option /* = "s" */) {
1306  return bookProfile_(pwd_, name, new TProfile(name, title, nchX, lowX, highX, lowY, highY, option));
1307  }
1308 
1313  char_string const& title,
1314  int const nchX,
1315  double const* xbinsize,
1316  int /* nchY */,
1317  double const lowY,
1318  double const highY,
1319  char const* option /* = "s" */) {
1320  return bookProfile_(pwd_, name, new TProfile(name, title, nchX, xbinsize, lowY, highY, option));
1321  }
1322 
1327  char_string const& title,
1328  int const nchX,
1329  double const* xbinsize,
1330  double const lowY,
1331  double const highY,
1332  char const* option /* = "s" */) {
1333  return bookProfile_(pwd_, name, new TProfile(name, title, nchX, xbinsize, lowY, highY, option));
1334  }
1335 
1338  return bookProfile_(pwd_, name, static_cast<TProfile*>(source->Clone(name)));
1339  }
1340 
1341  // -------------------------------------------------------------------
1344  return book_(dir, name, "bookProfile2D", MonitorElement::Kind::TPROFILE2D, h, collateProfile2D);
1345  }
1346 
1351  char_string const& title,
1352  int const nchX,
1353  double const lowX,
1354  double const highX,
1355  int const nchY,
1356  double const lowY,
1357  double const highY,
1358  int /* nchZ */,
1359  double const lowZ,
1360  double const highZ,
1361  char const* option /* = "s" */) {
1362  return bookProfile2D_(
1363  pwd_, name, new TProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, lowZ, highZ, option));
1364  }
1365 
1370  char_string const& title,
1371  int const nchX,
1372  double const lowX,
1373  double const highX,
1374  int const nchY,
1375  double const lowY,
1376  double const highY,
1377  double const lowZ,
1378  double const highZ,
1379  char const* option /* = "s" */) {
1380  return bookProfile2D_(
1381  pwd_, name, new TProfile2D(name, title, nchX, lowX, highX, nchY, lowY, highY, lowZ, highZ, option));
1382  }
1383 
1386  return bookProfile2D_(pwd_, name, static_cast<TProfile2D*>(source->Clone(name)));
1387  }
1388 
1393  if (me->getTH1()->GetNbinsX() != h->GetNbinsX() || me->getTH1()->GetNbinsY() != h->GetNbinsY() ||
1394  me->getTH1()->GetNbinsZ() != h->GetNbinsZ() ||
1395  me->getTH1()->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin() ||
1396  me->getTH1()->GetYaxis()->GetXmin() != h->GetYaxis()->GetXmin() ||
1397  me->getTH1()->GetZaxis()->GetXmin() != h->GetZaxis()->GetXmin() ||
1398  me->getTH1()->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax() ||
1399  me->getTH1()->GetYaxis()->GetXmax() != h->GetYaxis()->GetXmax() ||
1400  me->getTH1()->GetZaxis()->GetXmax() != h->GetZaxis()->GetXmax() ||
1401  !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetXaxis(), (TAxis*)h->GetXaxis()) ||
1402  !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetYaxis(), (TAxis*)h->GetYaxis()) ||
1403  !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetZaxis(), (TAxis*)h->GetZaxis())) {
1404  if (verbose > 0)
1405  std::cout << "*** DQMStore: WARNING:"
1406  << "checkBinningMatches: different binning - cannot add object '" << h->GetName() << "' of type "
1407  << h->IsA()->GetName() << " to existing ME: '" << me->getFullname() << "'\n";
1408  return false;
1409  }
1410  return true;
1411  }
1412 
1413  void DQMStore::collate1D(MonitorElement* me, TH1F* h, unsigned const verbose) {
1414  if (checkBinningMatches(me, h, verbose))
1415  me->getTH1F()->Add(h);
1416  }
1417 
1418  void DQMStore::collate1S(MonitorElement* me, TH1S* h, unsigned const verbose) {
1419  if (checkBinningMatches(me, h, verbose))
1420  me->getTH1S()->Add(h);
1421  }
1422 
1423  void DQMStore::collate1DD(MonitorElement* me, TH1D* h, unsigned const verbose) {
1424  if (checkBinningMatches(me, h, verbose))
1425  me->getTH1D()->Add(h);
1426  }
1427 
1428  void DQMStore::collate2D(MonitorElement* me, TH2F* h, unsigned const verbose) {
1429  if (checkBinningMatches(me, h, verbose))
1430  me->getTH2F()->Add(h);
1431  }
1432 
1433  void DQMStore::collate2S(MonitorElement* me, TH2S* h, unsigned const verbose) {
1434  if (checkBinningMatches(me, h, verbose))
1435  me->getTH2S()->Add(h);
1436  }
1437 
1438  void DQMStore::collate2DD(MonitorElement* me, TH2D* h, unsigned const verbose) {
1439  if (checkBinningMatches(me, h, verbose))
1440  me->getTH2D()->Add(h);
1441  }
1442 
1443  void DQMStore::collate3D(MonitorElement* me, TH3F* h, unsigned const verbose) {
1444  if (checkBinningMatches(me, h, verbose))
1445  me->getTH3F()->Add(h);
1446  }
1447 
1448  void DQMStore::collateProfile(MonitorElement* me, TProfile* h, unsigned const verbose) {
1449  if (checkBinningMatches(me, h, verbose)) {
1450  TProfile* meh = me->getTProfile();
1451  me->addProfiles(h, meh, meh, 1, 1);
1452  }
1453  }
1454 
1455  void DQMStore::collateProfile2D(MonitorElement* me, TProfile2D* h, unsigned const verbose) {
1456  if (checkBinningMatches(me, h, verbose)) {
1457  TProfile2D* meh = me->getTProfile2D();
1458  me->addProfiles(h, meh, meh, 1, 1);
1459  }
1460  }
1461 
1466  std::vector<std::string> DQMStore::getSubdirs() const {
1467  std::vector<std::string> result;
1468  auto e = dirs_.end();
1469  auto i = dirs_.find(pwd_);
1470 
1471  // If we didn't find current directory, the tree is empty, so quit.
1472  if (i == e)
1473  return result;
1474 
1475  // Skip the current directory and then start looking for immediate
1476  // subdirectories in the dirs_ list. Stop when we are no longer in
1477  // (direct or indirect) subdirectories of pwd_. Note that we don't
1478  // "know" which order the set will sort A/B, A/B/C and A/D.
1479  while (++i != e && isSubdirectory(pwd_, *i))
1480  if (i->find('/', pwd_.size() + 1) == std::string::npos)
1481  result.push_back(*i);
1482 
1483  return result;
1484  }
1485 
1487  std::vector<std::string> DQMStore::getMEs() const {
1488  MonitorElement proto(&pwd_, std::string());
1489  std::vector<std::string> result;
1490  auto e = data_.end();
1491  auto i = data_.lower_bound(proto);
1492  for (; i != e && isSubdirectory(pwd_, *i->data_.dirname); ++i)
1493  if (pwd_ == *i->data_.dirname)
1494  result.push_back(i->getName());
1495 
1496  return result;
1497  }
1498 
1502  MonitorElement proto(&path, std::string());
1503  auto e = data_.end();
1504  auto i = data_.lower_bound(proto);
1505  return (i != e && isSubdirectory(path, *i->data_.dirname));
1506  }
1507 
1510  std::string dir;
1511  std::string name;
1512  splitPath(dir, name, path);
1513  MonitorElement proto(&dir, name);
1514  auto mepos = data_.find(proto);
1515  return (mepos == data_.end() ? nullptr : const_cast<MonitorElement*>(&*mepos));
1516  }
1517 
1520  std::vector<MonitorElement*> DQMStore::getContents(std::string const& path) const {
1522  std::string const* cleaned = nullptr;
1523  cleanTrailingSlashes(path, clean, cleaned);
1524  MonitorElement proto(cleaned, std::string());
1525 
1526  std::vector<MonitorElement*> result;
1527  auto e = data_.end();
1528  auto i = data_.lower_bound(proto);
1529  for (; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1530  if (*cleaned == *i->data_.dirname)
1531  result.push_back(const_cast<MonitorElement*>(&*i));
1532 
1533  return result;
1534  }
1535 
1540  void DQMStore::getContents(std::vector<std::string>& into, bool const showContents /* = true */) const {
1541  into.clear();
1542  into.reserve(dirs_.size());
1543 
1544  auto me = data_.end();
1545  for (auto const& dir : dirs_) {
1546  MonitorElement proto(&dir, std::string());
1547  auto mi = data_.lower_bound(proto);
1548  auto m = mi;
1549  size_t sz = dir.size() + 2;
1550  size_t nfound = 0;
1551  for (; m != me && isSubdirectory(dir, *m->data_.dirname); ++m)
1552  if (dir == *m->data_.dirname) {
1553  sz += m->data_.objname.size() + 1;
1554  ++nfound;
1555  }
1556 
1557  if (!nfound)
1558  continue;
1559 
1560  auto istr = into.insert(into.end(), std::string());
1561 
1562  if (showContents) {
1563  istr->reserve(sz);
1564 
1565  *istr += dir;
1566  *istr += ':';
1567  for (sz = 0; mi != m; ++mi) {
1568  if (dir != *mi->data_.dirname)
1569  continue;
1570 
1571  if (sz > 0)
1572  *istr += ',';
1573 
1574  *istr += mi->data_.objname;
1575  ++sz;
1576  }
1577  } else {
1578  istr->reserve(dir.size() + 2);
1579  *istr += dir;
1580  *istr += ':';
1581  }
1582  }
1583  }
1584 
1588  uint32_t const lumi,
1589  uint32_t const moduleId,
1590  std::string const& dir,
1591  std::string const& name) const {
1592  if (dir.find_first_not_of(s_safe) != std::string::npos)
1593  raiseDQMError("DQMStore",
1594  "Monitor element path name '%s' uses"
1595  " unacceptable characters",
1596  dir.c_str());
1597  if (name.find_first_not_of(s_safe) != std::string::npos)
1598  raiseDQMError("DQMStore",
1599  "Monitor element path name '%s' uses"
1600  " unacceptable characters",
1601  name.c_str());
1602 
1603  MonitorElement proto;
1604  proto.data_.dirname = &dir;
1605  proto.data_.objname = name;
1606  proto.data_.run = run;
1607  proto.data_.lumi = lumi;
1608  proto.data_.moduleId = moduleId;
1609 
1610  auto mepos = data_.find(proto);
1611  return (mepos == data_.end() ? nullptr : const_cast<MonitorElement*>(&*mepos));
1612  }
1613 
1616  std::vector<MonitorElement*> DQMStore::getAllContents(std::string const& path,
1617  uint32_t const run /* = 0 */,
1618  uint32_t const lumi /* = 0 */) const {
1620  std::string const* cleaned = nullptr;
1621  cleanTrailingSlashes(path, clean, cleaned);
1622  MonitorElement proto(cleaned, std::string(), run, 0);
1623  proto.setLumi(lumi);
1624 
1625  std::vector<MonitorElement*> result;
1626  auto e = data_.end();
1627  auto i = data_.lower_bound(proto);
1628  for (; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i) {
1629  if (run != 0) {
1630  if (i->data_.run > run // TODO[rovere]: pleonastic? first we encounter local ME of the same run ...
1631  || i->data_.moduleId != 0)
1632  break;
1633  }
1634  if (lumi != 0) {
1635  if (i->data_.lumi > lumi || i->data_.moduleId != 0)
1636  break;
1637  }
1638  if (run != 0 or lumi != 0) {
1639  assert(i->data_.moduleId == 0);
1640  }
1641  result.push_back(const_cast<MonitorElement*>(&*i));
1642  }
1643 
1644  if (enableMultiThread_) {
1645  //save legacy modules when running MT
1646  i = data_.begin();
1647  for (; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i) {
1648  if (i->data_.run != 0 or i->data_.moduleId != 0)
1649  break;
1650  result.push_back(const_cast<MonitorElement*>(&*i));
1651  }
1652  }
1653 
1654  return result;
1655  }
1656 
1659  std::vector<MonitorElement*> DQMStore::getMatchingContents(
1660  std::string const& pattern, lat::Regexp::Syntax const syntaxType /* = Wildcard */) const {
1661  lat::Regexp rx;
1662  try {
1663  rx = lat::Regexp(pattern, 0, syntaxType);
1664  rx.study();
1665  } catch (lat::Error& e) {
1666  raiseDQMError("DQMStore", "Invalid regular expression '%s': %s", pattern.c_str(), e.explain().c_str());
1667  }
1668 
1669  std::string path;
1670  std::vector<MonitorElement*> result;
1671  for (auto const& me : data_) {
1672  path.clear();
1673  mergePath(path, *me.data_.dirname, me.data_.objname);
1674  if (rx.match(path))
1675  result.push_back(const_cast<MonitorElement*>(&me));
1676  }
1677 
1678  return result;
1679  }
1680 
1684 
1688  for (auto const& m : data_) {
1689  auto& me = const_cast<MonitorElement&>(m);
1690  if (me.wasUpdated()) {
1691  if (me.resetMe())
1692  me.Reset();
1693  me.resetUpdate();
1694  }
1695  }
1696 
1697  reset_ = true;
1698  }
1699 
1703 
1706  for (auto const& m : data_) {
1707  if (forceResetOnBeginLumi_ && (m.getLumiFlag() == false))
1708  continue;
1709  auto& me = const_cast<MonitorElement&>(m);
1710  me.Reset();
1711  me.resetUpdate();
1712  }
1713 
1714  reset_ = true;
1715  }
1716 
1720 
1725  static const std::string null_str("");
1726 
1727  auto const& lumiblock = gc.luminosityBlockID();
1728  uint32_t run = lumiblock.run();
1729 
1730  // find the range of non-legacy global MEs for the current run:
1731  // run != 0, lumi == 0 (implicit), stream id == 0, module id == 0
1732  const MonitorElement begin(&null_str, null_str, run, 0);
1733  const MonitorElement end(&null_str, null_str, run, 1);
1734  auto i = data_.lower_bound(begin);
1735  const auto e = data_.lower_bound(end);
1736  while (i != e) {
1737  auto& me = const_cast<MonitorElement&>(*i++);
1738  // skip per-run MEs
1739  if (not LSbasedMode_ and not me.getLumiFlag())
1740  continue;
1741  me.Reset();
1742  me.resetUpdate();
1743  }
1744  }
1745 
1749 
1756  void DQMStore::cloneLumiHistograms(uint32_t const run, uint32_t const lumi, uint32_t const moduleId) {
1757  if (verbose_ > 1) {
1758  std::cout << "DQMStore::cloneLumiHistograms - Preparing lumi histograms for run: " << run << ", lumi: " << lumi
1759  << ", module: " << moduleId << std::endl;
1760  }
1761 
1762  // acquire the global lock since this accesses the undelying data structure
1763  std::lock_guard<std::mutex> guard(book_mutex_);
1764 
1765  // MEs are sorted by (run, lumi, stream id, module id, directory, name)
1766  // lumi deafults to 0
1767  // stream id is always 0
1768  std::string null_str("");
1769  auto i = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId));
1770  auto e = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId + 1));
1771  // we will later modify data_, so better do two passes.
1772  auto tobehandled = std::vector<MonitorElement const*>();
1773  for (; i != e; ++i) {
1774  tobehandled.push_back(&*i);
1775  }
1776  for (auto i : tobehandled) {
1777  // handle only lumisection-based histograms
1778  if (not LSbasedMode_ and not i->getLumiFlag())
1779  continue;
1780 
1781  // clone the lumisection-based histograms
1783  clone.globalize();
1784  clone.setLumi(lumi);
1785  clone.markToDelete();
1786  data_.insert(std::move(clone));
1787 
1788  // reset the ME for the next lumisection
1789  const_cast<MonitorElement*>(&*i)->Reset();
1790  }
1791  }
1792 
1796  void DQMStore::cloneRunHistograms(uint32_t const run, uint32_t const moduleId) {
1797  if (verbose_ > 1) {
1798  std::cout << "DQMStore::cloneRunHistograms - Preparing run histograms for run: " << run
1799  << ", module: " << moduleId << std::endl;
1800  }
1801 
1802  // acquire the global lock since this accesses the undelying data structure
1803  std::lock_guard<std::mutex> guard(book_mutex_);
1804 
1805  // MEs are sorted by (run, lumi, stream id, module id, directory, name)
1806  // lumi deafults to 0
1807  // stream id is always 0
1808  std::string null_str("");
1809  auto i = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId));
1810  auto e = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId + 1));
1811  // we will later modify data_, so better do two passes.
1812  auto tobehandled = std::vector<MonitorElement const*>();
1813  for (; i != e; ++i) {
1814  tobehandled.push_back(&*i);
1815  }
1816  for (auto i : tobehandled) {
1817  // handle only non lumisection-based histograms
1818  if (LSbasedMode_ or i->getLumiFlag())
1819  continue;
1820 
1821  // clone the lumisection-based histograms
1823  clone.globalize();
1824  clone.markToDelete();
1825  data_.insert(std::move(clone));
1826 
1827  // reset the ME for the next lumisection
1828  const_cast<MonitorElement*>(&*i)->Reset();
1829  }
1830  }
1831 
1836  void DQMStore::deleteUnusedLumiHistograms(uint32_t const run, uint32_t const lumi) {
1837  if (!enableMultiThread_)
1838  return;
1839 
1840  std::lock_guard<std::mutex> guard(book_mutex_);
1841 
1842  std::string null_str("");
1843  MonitorElement proto(&null_str, null_str, run, 0);
1844  proto.setLumi(lumi);
1845 
1846  auto e = data_.end();
1847  auto i = data_.lower_bound(proto);
1848 
1849  while (i != e) {
1850  if (i->data_.moduleId != 0)
1851  break;
1852  if (i->data_.lumi != lumi)
1853  break;
1854  if (i->data_.run != run)
1855  break;
1856  if (not i->markedToDelete()) {
1857  ++i;
1858  continue;
1859  }
1860 
1861  if (verbose_ > 1) {
1862  std::cout << "DQMStore::deleteUnusedLumiHistograms: deleted monitor element '" << *i->data_.dirname << "/"
1863  << i->data_.objname << "'"
1864  << "flags " << i->data_.flags << "\n";
1865  }
1866 
1867  i = data_.erase(i);
1868  }
1869  }
1870 
1876  bool DQMStore::extract(TObject* obj, std::string const& dir, bool const overwrite, bool const collateHistograms) {
1877  // NB: Profile histograms inherit from TH*D, checking order matters.
1878  MonitorElement* refcheck = nullptr;
1879  if (auto* h = dynamic_cast<TProfile*>(obj)) {
1880  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1881  if (!me)
1882  me = bookProfile_(dir, h->GetName(), (TProfile*)h->Clone());
1883  else if (overwrite)
1884  me->copyFrom(h);
1885  else if (isCollateME(me) || collateHistograms)
1886  collateProfile(me, h, verbose_);
1887  refcheck = me;
1888  } else if (auto* h = dynamic_cast<TProfile2D*>(obj)) {
1889  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1890  if (!me)
1891  me = bookProfile2D_(dir, h->GetName(), (TProfile2D*)h->Clone());
1892  else if (overwrite)
1893  me->copyFrom(h);
1894  else if (isCollateME(me) || collateHistograms)
1895  collateProfile2D(me, h, verbose_);
1896  refcheck = me;
1897  } else if (auto* h = dynamic_cast<TH1F*>(obj)) {
1898  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1899  if (!me)
1900  me = book1D_(dir, h->GetName(), (TH1F*)h->Clone());
1901  else if (overwrite)
1902  me->copyFrom(h);
1903  else if (isCollateME(me) || collateHistograms)
1904  collate1D(me, h, verbose_);
1905  refcheck = me;
1906  } else if (auto* h = dynamic_cast<TH1S*>(obj)) {
1907  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1908  if (!me)
1909  me = book1S_(dir, h->GetName(), (TH1S*)h->Clone());
1910  else if (overwrite)
1911  me->copyFrom(h);
1912  else if (isCollateME(me) || collateHistograms)
1913  collate1S(me, h, verbose_);
1914  refcheck = me;
1915  } else if (auto* h = dynamic_cast<TH1D*>(obj)) {
1916  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1917  if (!me)
1918  me = book1DD_(dir, h->GetName(), (TH1D*)h->Clone());
1919  else if (overwrite)
1920  me->copyFrom(h);
1921  else if (isCollateME(me) || collateHistograms)
1922  collate1DD(me, h, verbose_);
1923  refcheck = me;
1924  } else if (auto* h = dynamic_cast<TH2F*>(obj)) {
1925  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1926  if (!me)
1927  me = book2D_(dir, h->GetName(), (TH2F*)h->Clone());
1928  else if (overwrite)
1929  me->copyFrom(h);
1930  else if (isCollateME(me) || collateHistograms)
1931  collate2D(me, h, verbose_);
1932  refcheck = me;
1933  } else if (auto* h = dynamic_cast<TH2S*>(obj)) {
1934  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1935  if (!me)
1936  me = book2S_(dir, h->GetName(), (TH2S*)h->Clone());
1937  else if (overwrite)
1938  me->copyFrom(h);
1939  else if (isCollateME(me) || collateHistograms)
1940  collate2S(me, h, verbose_);
1941  refcheck = me;
1942  } else if (auto* h = dynamic_cast<TH2D*>(obj)) {
1943  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1944  if (!me)
1945  me = book2DD_(dir, h->GetName(), (TH2D*)h->Clone());
1946  else if (overwrite)
1947  me->copyFrom(h);
1948  else if (isCollateME(me) || collateHistograms)
1949  collate2DD(me, h, verbose_);
1950  refcheck = me;
1951  } else if (auto* h = dynamic_cast<TH3F*>(obj)) {
1952  MonitorElement* me = findObject(0, 0, 0, dir, h->GetName());
1953  if (!me)
1954  me = book3D_(dir, h->GetName(), (TH3F*)h->Clone());
1955  else if (overwrite)
1956  me->copyFrom(h);
1957  else if (isCollateME(me) || collateHistograms)
1958  collate3D(me, h, verbose_);
1959  refcheck = me;
1960  } else if (dynamic_cast<TObjString*>(obj)) {
1961  lat::RegexpMatch m;
1962  if (!s_rxmeval.match(obj->GetName(), 0, 0, &m)) {
1963  if (strstr(obj->GetName(), "CMSSW")) {
1964  if (verbose_)
1965  std::cout << "Input file version: " << obj->GetName() << std::endl;
1966  return true;
1967  } else if (strstr(obj->GetName(), "DQMPATCH")) {
1968  if (verbose_)
1969  std::cout << "DQM patch version: " << obj->GetName() << std::endl;
1970  return true;
1971  } else {
1972  std::cout << "*** DQMStore: WARNING: cannot extract object '" << obj->GetName() << "' of type '"
1973  << obj->IsA()->GetName() << "'\n";
1974  return false;
1975  }
1976  }
1977 
1978  std::string label = m.matchString(obj->GetName(), 1);
1979  std::string kind = m.matchString(obj->GetName(), 2);
1980  std::string value = m.matchString(obj->GetName(), 3);
1981 
1982  if (kind == "i") {
1983  MonitorElement* me = findObject(0, 0, 0, dir, label);
1984  if (!me || overwrite) {
1985  if (!me)
1986  me = bookInt_(dir, label);
1987  me->Fill(atoll(value.c_str()));
1988  }
1989  } else if (kind == "f") {
1990  MonitorElement* me = findObject(0, 0, 0, dir, label);
1991  if (!me || overwrite) {
1992  if (!me)
1993  me = bookFloat_(dir, label);
1994  me->Fill(atof(value.c_str()));
1995  }
1996  } else if (kind == "s") {
1997  MonitorElement* me = findObject(0, 0, 0, dir, label);
1998  if (!me)
1999  me = bookString_(dir, label, value);
2000  else if (overwrite)
2001  me->Fill(value);
2002  } else if (kind == "e") {
2003  MonitorElement* me = findObject(0, 0, 0, dir, label);
2004  if (!me) {
2005  std::cout << "*** DQMStore: WARNING: no monitor element '" << label << "' in directory '" << dir
2006  << "' to be marked as efficiency plot.\n";
2007  return false;
2008  }
2009  me->setEfficiencyFlag();
2010  } else if (kind == "t") {
2011  // ignore tags.
2012  } else if (kind == "qr") {
2013  // Handle qreports, but skip them while reading in references.
2014  if (!isSubdirectory(s_referenceDirName, dir)) {
2015  size_t dot = label.find('.');
2016  if (dot == std::string::npos) {
2017  std::cout << "*** DQMStore: WARNING: quality report label in '" << label
2018  << "' is missing a '.' and cannot be extracted\n";
2019  return false;
2020  }
2021 
2022  std::string mename(label, 0, dot);
2023  std::string qrname(label, dot + 1, std::string::npos);
2024 
2025  m.reset();
2026  DQMNet::QValue qv;
2027  if (s_rxmeqr1.match(value, 0, 0, &m)) {
2028  qv.code = atoi(m.matchString(value, 1).c_str());
2029  qv.qtresult = strtod(m.matchString(value, 2).c_str(), nullptr);
2030  qv.message = m.matchString(value, 4);
2031  qv.qtname = qrname;
2032  qv.algorithm = m.matchString(value, 3);
2033  } else if (s_rxmeqr2.match(value, 0, 0, &m)) {
2034  qv.code = atoi(m.matchString(value, 1).c_str());
2035  qv.qtresult = 0; // unavailable in old format
2036  qv.message = m.matchString(value, 2);
2037  qv.qtname = qrname;
2038  // qv.algorithm unavailable in old format
2039  } else {
2040  std::cout << "*** DQMStore: WARNING: quality test value '" << value << "' is incorrectly formatted\n";
2041  return false;
2042  }
2043 
2044  MonitorElement* me = findObject(0, 0, 0, dir, mename);
2045  if (!me) {
2046  std::cout << "*** DQMStore: WARNING: no monitor element '" << mename << "' in directory '" << dir
2047  << "' for quality test '" << label << "'\n";
2048  return false;
2049  }
2050 
2051  me->addQReport(qv, /* FIXME: getQTest(qv.qtname)? */ nullptr);
2052  }
2053  } else {
2054  std::cout << "*** DQMStore: WARNING: cannot extract object '" << obj->GetName() << "' of type '"
2055  << obj->IsA()->GetName() << "'\n";
2056  return false;
2057  }
2058  } else if (auto* n = dynamic_cast<TNamed*>(obj)) {
2059  // For old DQM data.
2060  std::string s;
2061  s.reserve(6 + strlen(n->GetTitle()) + 2 * strlen(n->GetName()));
2062  s += '<';
2063  s += n->GetName();
2064  s += '>';
2065  s += n->GetTitle();
2066  s += '<';
2067  s += '/';
2068  s += n->GetName();
2069  s += '>';
2070  TObjString os(s.c_str());
2071  return extract(&os, dir, overwrite, collateHistograms_);
2072  } else {
2073  std::cout << "*** DQMStore: WARNING: cannot extract object '" << obj->GetName() << "' of type '"
2074  << obj->IsA()->GetName() << "' and with title '" << obj->GetTitle() << "'\n";
2075  return false;
2076  }
2077 
2078  // If we just read in a reference MonitorElement, and there is a
2079  // MonitorElement with the same name, link the two together.
2080  // The other direction is handled by the book() method.
2081  if (refcheck && isSubdirectory(s_referenceDirName, dir)) {
2082  std::string mdir(dir, s_referenceDirName.size() + 1, std::string::npos);
2083  if (MonitorElement* master = findObject(0, 0, 0, mdir, obj->GetName())) {
2084  // We have extracted a MonitorElement, and it's located in the reference
2085  // dir. Then we find the corresponding MonitorElement in the
2086  // non-reference dir and assign the object_ of the reference
2087  // MonitorElement to the reference_ property of the corresponding
2088  // non-reference MonitorElement.
2089  master->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
2090  master->reference_ = refcheck->getTH1();
2091  }
2092  }
2093 
2094  return true;
2095  }
2096 
2100  bool DQMStore::cdInto(std::string const& path) const {
2101  assert(!path.empty());
2102 
2103  // Find the first path component.
2104  size_t start = 0;
2105  size_t end = path.find('/', start);
2106  if (end == std::string::npos)
2107  end = path.size();
2108 
2109  while (true) {
2110  // Check if this subdirectory component exists. If yes, make sure
2111  // it is actually a subdirectory. Otherwise create or cd into it.
2112  std::string part(path, start, end - start);
2113  TObject* o = gDirectory->Get(part.c_str());
2114  if (o && !dynamic_cast<TDirectory*>(o))
2115  raiseDQMError("DQMStore",
2116  "Attempt to create directory '%s' in a file"
2117  " fails because the part '%s' already exists and is not"
2118  " directory",
2119  path.c_str(),
2120  part.c_str());
2121  else if (!o)
2122  gDirectory->mkdir(part.c_str());
2123 
2124  if (!gDirectory->cd(part.c_str()))
2125  raiseDQMError("DQMStore",
2126  "Attempt to create directory '%s' in a file"
2127  " fails because could not cd into subdirectory '%s'",
2128  path.c_str(),
2129  part.c_str());
2130 
2131  // Stop if we reached the end, ignoring any trailing '/'.
2132  if (end + 1 >= path.size())
2133  break;
2134 
2135  // Find the next path component.
2136  start = end + 1;
2137  end = path.find('/', start);
2138  if (end == std::string::npos)
2139  end = path.size();
2140  }
2141 
2142  return true;
2143  }
2144 
2146  // Save the object.
2147  if (me.kind() < MonitorElement::Kind::TH1F) {
2148  TObjString(me.tagString().c_str()).Write();
2149  } else {
2150  me.getRootObject()->Write();
2151  }
2152 
2153  // Save quality reports if this is not in reference section.
2155  for (auto const& report : me.data_.qreports) {
2156  TObjString(me.qualityTagString(report).c_str()).Write();
2157  }
2158  }
2159 
2160  // Save efficiency tag, if any.
2162  TObjString(me.effLabelString().c_str()).Write();
2163  }
2164 
2165  // Save tag if any.
2166  if (me.data_.flags & DQMNet::DQM_PROP_TAGGED) {
2167  TObjString(me.tagLabelString().c_str()).Write();
2168  }
2169  }
2170 
2172  std::string const& refpath,
2173  SaveReferenceTag const ref,
2174  int const minStatus,
2175  unsigned int const run,
2176  MEMap::const_iterator const begin,
2177  MEMap::const_iterator const end,
2178  TFile& file,
2179  unsigned int& counter) {
2180  for (auto const& me : boost::make_iterator_range(begin, end)) {
2181  if (not isSubdirectory(dir, *me.data_.dirname))
2182  break;
2183 
2184  if (verbose_ > 1)
2185  std::cout << "DQMStore::save:"
2186  << " run: " << me.run() << " lumi: " << me.lumi() << " lumiFlag: " << me.getLumiFlag()
2187  << " moduleId: " << me.moduleId() << " fullpathname: " << me.getFullname() << " flags: " << std::hex
2188  << me.data_.flags << std::endl;
2189 
2190  // Skip MonitorElements in a subdirectory of the current one.
2191  if (dir != *me.data_.dirname) {
2192  if (verbose_ > 1) {
2193  std::cout << "DQMStore::save: skipping monitor element in a subfolder of " << dir << "/" << std::endl;
2194  }
2195  continue;
2196  }
2197 
2198  // Handle reference histograms, with three distinct cases:
2199  // 1) Skip all references entirely on saving.
2200  // 2) Blanket saving of all references.
2201  // 3) Save only references for monitor elements with qtests.
2202  // The latter two are affected by "path" sub-tree selection,
2203  // i.e. references are saved only in the selected tree part.
2204  if (isSubdirectory(refpath, *me.data_.dirname)) {
2205  if (ref == SaveWithoutReference)
2206  // Skip the reference entirely.
2207  continue;
2208  else if (ref == SaveWithReference)
2209  // Save all references regardless of qtests.
2210  ;
2211  else if (ref == SaveWithReferenceForQTest) {
2212  // Save only references for monitor elements with qtests
2213  // with an optional cut on minimum quality test result.
2214  int status = -1;
2215  std::string mname(me.getFullname(), s_referenceDirName.size() + 1, std::string::npos);
2216  MonitorElement* master = get(mname);
2217  if (master)
2218  for (auto const& qreport : master->data_.qreports)
2219  status = std::max(status, qreport.code);
2220 
2221  if (not master or status < minStatus) {
2222  if (verbose_ > 1)
2223  std::cout << "DQMStore::save: skipping monitor element '" << me.data_.objname
2224  << "' while saving, status is " << status << ", required minimum status is " << minStatus
2225  << std::endl;
2226  continue;
2227  }
2228  }
2229  }
2230 
2231  if (verbose_ > 1) {
2232  std::cout << "DQMStore::save: saving monitor element" << std::endl;
2233  }
2234 
2236 
2237  // Count saved histograms
2238  ++counter;
2239  }
2240  }
2241 
2245  std::string const& path /* = "" */,
2246  std::string const& pattern /* = "" */,
2247  std::string const& rewrite /* = "" */,
2248  uint32_t const run /* = 0 */,
2249  uint32_t const lumi /* = 0 */,
2250  SaveReferenceTag const ref /* = SaveWithReference */,
2251  int const minStatus /* = dqm::qstatus::STATUS_OK */,
2252  std::string const& fileupdate /* = RECREATE */) {
2253  // TFile flushes to disk with fsync() on every TDirectory written to
2254  // the file. This makes DQM file saving painfully slow, and
2255  // ironically makes it _more_ likely the file saving gets
2256  // interrupted and corrupts the file. The utility class below
2257  // simply ignores the flush synchronisation.
2258  class TFileNoSync : public TFile {
2259  public:
2260  TFileNoSync(char const* file, char const* opt) : TFile{file, opt} {}
2261  Int_t SysSync(Int_t) override { return 0; }
2262  };
2263 
2264  std::lock_guard<std::mutex> guard(book_mutex_);
2265 
2266  unsigned int nme = 0;
2267 
2268  // open output file, on 1st save recreate, later update
2269  if (verbose_) {
2270  std::cout << "DQMStore::save: Opening TFile '" << filename << "' with option '" << fileupdate << "'" << std::endl;
2271  }
2272 
2273  TFileNoSync f(filename.c_str(), fileupdate.c_str()); // open file
2274  if (f.IsZombie())
2275  raiseDQMError("DQMStore", "Failed to create/update file '%s'", filename.c_str());
2276  f.cd();
2277 
2278  // Construct a regular expression from the pattern string.
2279  std::unique_ptr<lat::Regexp> rxpat;
2280  if (not pattern.empty())
2281  rxpat = std::make_unique<lat::Regexp>(pattern);
2282 
2283  // Prepare a path for the reference object selection.
2284  std::string refpath;
2285  refpath.reserve(s_referenceDirName.size() + path.size() + 2);
2286  refpath += s_referenceDirName;
2287  if (not path.empty()) {
2288  refpath += '/';
2289  refpath += path;
2290  }
2291 
2292  // Loop over the directory structure.
2293  for (auto const& dir : dirs_) {
2294  // Check if we should process this directory. We process the
2295  // requested part of the object tree, including references.
2296  if (not path.empty() and not isSubdirectory(refpath, dir) and not isSubdirectory(path, dir))
2297  continue;
2298 
2299  if (verbose_ > 1) {
2300  std::cout << "DQMStore::save: DQM folder " << dir << "/" << std::endl;
2301  }
2302 
2303  // Create the directory.
2304  gDirectory->cd("/");
2305  if (dir.empty())
2307  else if (rxpat.get())
2308  cdInto(s_monitorDirName + '/' + lat::StringOps::replace(dir, *rxpat, rewrite));
2309  else
2310  cdInto(s_monitorDirName + '/' + dir);
2311 
2312  // Loop over monitor elements in this directory.
2313  if (not enableMultiThread_) {
2314  MonitorElement proto(&dir, std::string(), run, 0);
2315  auto begin = data_.lower_bound(proto);
2316  auto end = data_.end();
2317  saveMonitorElementRangeToROOT(dir, refpath, ref, minStatus, run, begin, end, f, nme);
2318  } else {
2319  // Restrict the loop to the monitor elements for the current lumisection
2320  MonitorElement proto(&dir, std::string(), run, 0);
2321  proto.setLumi(lumi);
2322  auto begin = data_.lower_bound(proto);
2323  proto.setLumi(lumi + 1);
2324  auto end = data_.lower_bound(proto);
2325  saveMonitorElementRangeToROOT(dir, refpath, ref, minStatus, run, begin, end, f, nme);
2326  }
2327 
2328  // In LSbasedMode, loop also over the (run, 0) global histograms;
2329  // these could be the merged global histrograms of their per-stream
2330  // counterparts after the streamEndRun transition - but they are not
2331  // produced in LSbasedMode.
2332  if (enableMultiThread_ and LSbasedMode_ and lumi != 0) {
2333  auto begin = data_.lower_bound(MonitorElement(&dir, std::string(), run, 0));
2334  auto end = data_.lower_bound(MonitorElement(&dir, std::string(), run, 1));
2335  saveMonitorElementRangeToROOT(dir, refpath, ref, minStatus, run, begin, end, f, nme);
2336  }
2337  }
2338 
2339  f.Close();
2340 
2341  // Maybe make some noise.
2342  if (verbose_) {
2343  std::cout << "DQMStore::save: successfully wrote " << nme << " objects from path '" << path << "/"
2344  << "' into DQM file '" << filename << "'\n";
2345  }
2346  }
2347 
2349  // Save the object.
2350  TBufferFile buffer(TBufferFile::kWrite);
2351  if (me.kind() < MonitorElement::Kind::TH1F) {
2352  TObjString object(me.tagString().c_str());
2353  buffer.WriteObject(&object);
2354  } else {
2355  buffer.WriteObject(me.getRootObject());
2356  }
2358  histo.set_full_pathname(*me.data_.dirname + '/' + me.data_.objname);
2359  histo.set_flags(me.data_.flags);
2360  histo.set_size(buffer.Length());
2361  histo.set_streamed_histo((void const*)buffer.Buffer(), buffer.Length());
2362 
2363  // Save quality reports if this is not in reference section.
2364  // XXX not supported by protobuf files.
2365 
2366  // Save efficiency tag, if any.
2367  // XXX not supported by protobuf files.
2368 
2369  // Save tag if any.
2370  // XXX not supported by protobuf files.
2371  }
2372 
2374  unsigned int const run,
2375  MEMap::const_iterator const begin,
2376  MEMap::const_iterator const end,
2378  unsigned int& counter) {
2379  for (auto const& me : boost::make_iterator_range(begin, end)) {
2380  if (not isSubdirectory(dir, *me.data_.dirname))
2381  break;
2382 
2383  if (verbose_ > 1)
2384  std::cout << "DQMStore::savePB:"
2385  << " run: " << me.run() << " lumi: " << me.lumi() << " lumiFlag: " << me.getLumiFlag()
2386  << " moduleId: " << me.moduleId() << " fullpathname: " << me.getFullname() << " flags: " << std::hex
2387  << me.data_.flags << std::endl;
2388 
2389  // Skip MonitorElements in a subdirectory of the current one.
2390  if (dir != *me.data_.dirname) {
2391  if (verbose_ > 1) {
2392  std::cout << "DQMStore::savePB: skipping monitor element in a subfolder of " << dir << "/" << std::endl;
2393  }
2394  continue;
2395  }
2396 
2397  // Handle reference histograms, with three distinct cases:
2398  // XXX not supported by protobuf files.
2399 
2400  if (verbose_ > 1) {
2401  std::cout << "DQMStore::savePB: saving monitor element" << std::endl;
2402  }
2403 
2404  saveMonitorElementToPB(me, file);
2405 
2406  // Count saved histograms
2407  ++counter;
2408  }
2409  }
2410 
2414  std::string const& path /* = "" */,
2415  uint32_t const run /* = 0 */,
2416  uint32_t const lumi /* = 0 */) {
2417  using google::protobuf::io::FileOutputStream;
2418  using google::protobuf::io::GzipOutputStream;
2419  using google::protobuf::io::StringOutputStream;
2420 
2421  std::lock_guard<std::mutex> guard(book_mutex_);
2422 
2423  unsigned int nme = 0;
2424 
2425  if (verbose_) {
2426  std::cout << "DQMStore::savePB: Opening PBFile '" << filename << "'" << std::endl;
2427  }
2428  dqmstorepb::ROOTFilePB dqmstore_message;
2429 
2430  // Loop over the directory structure.
2431  for (auto const& dir : dirs_) {
2432  // Check if we should process this directory. We process the
2433  // requested part of the object tree, including references.
2434  if (not path.empty() and not isSubdirectory(path, dir))
2435  continue;
2436 
2437  if (verbose_ > 1) {
2438  std::cout << "DQMStore::savePB: DQM folder " << dir << "/" << std::endl;
2439  }
2440 
2441  // Loop over monitor elements in this directory.
2442  if (not enableMultiThread_) {
2443  MonitorElement proto(&dir, std::string(), run, 0);
2444  auto begin = data_.lower_bound(proto);
2445  auto end = data_.end();
2446  saveMonitorElementRangeToPB(dir, run, begin, end, dqmstore_message, nme);
2447  } else {
2448  // Restrict the loop to the monitor elements for the current lumisection
2449  MonitorElement proto(&dir, std::string(), run, 0);
2450  proto.setLumi(lumi);
2451  auto begin = data_.lower_bound(proto);
2452  proto.setLumi(lumi + 1);
2453  auto end = data_.lower_bound(proto);
2454  saveMonitorElementRangeToPB(dir, run, begin, end, dqmstore_message, nme);
2455  }
2456 
2457  // In LSbasedMode, loop also over the (run, 0) global histograms;
2458  // these could be the merged global histrograms of their per-stream
2459  // counterparts after the streamEndRun transition - but they are not
2460  // produced in LSbasedMode.
2461  if (enableMultiThread_ and LSbasedMode_ and lumi != 0) {
2462  auto begin = data_.lower_bound(MonitorElement(&dir, std::string(), run, 0));
2463  auto end = data_.lower_bound(MonitorElement(&dir, std::string(), run, 1));
2464  saveMonitorElementRangeToPB(dir, run, begin, end, dqmstore_message, nme);
2465  }
2466  }
2467 
2468  int filedescriptor =
2469  ::open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
2470  FileOutputStream file_stream(filedescriptor);
2472  options.format = GzipOutputStream::GZIP;
2473  options.compression_level = 1;
2474  GzipOutputStream gzip_stream(&file_stream, options);
2475  dqmstore_message.SerializeToZeroCopyStream(&gzip_stream);
2476 
2477  // Flush the internal streams before closing the fd.
2478  gzip_stream.Close();
2479  file_stream.Close();
2480  ::close(filedescriptor);
2481 
2482  // Maybe make some noise.
2483  if (verbose_) {
2484  std::cout << "DQMStore::savePB: successfully wrote " << nme << " objects from path '" << path << "/"
2485  << "' into DQM file '" << filename << "'\n";
2486  }
2487  }
2488 
2491  unsigned int DQMStore::readDirectory(TFile* file,
2492  bool const overwrite,
2493  std::string const& onlypath,
2494  std::string const& prepend,
2495  std::string const& curdir,
2496  OpenRunDirs const stripdirs) {
2497  unsigned int ntot = 0;
2498  unsigned int count = 0;
2499 
2500  if (!file->cd(curdir.c_str()))
2501  raiseDQMError("DQMStore",
2502  "Failed to process directory '%s' while"
2503  " reading file '%s'",
2504  curdir.c_str(),
2505  file->GetName());
2506 
2507  // Figure out current directory name, but strip out the top
2508  // directory into which we dump everything.
2509  std::string dirpart = curdir;
2510  if (dirpart.compare(0, s_monitorDirName.size(), s_monitorDirName) == 0) {
2511  if (dirpart.size() == s_monitorDirName.size())
2512  dirpart.clear();
2513  else if (dirpart[s_monitorDirName.size()] == '/')
2514  dirpart.erase(0, s_monitorDirName.size() + 1);
2515  }
2516 
2517  // See if we are going to skip this directory.
2518  bool skip = (!onlypath.empty() && !isSubdirectory(onlypath, dirpart));
2519 
2520  if (prepend == s_collateDirName || prepend == s_referenceDirName || stripdirs == StripRunDirs) {
2521  // Remove Run # and RunSummary dirs
2522  // first look for Run summary,
2523  // if that is found and erased, also erase Run dir
2524  size_t slash = dirpart.find('/');
2525  size_t pos = dirpart.find("/Run summary");
2526  if (slash != std::string::npos && pos != std::string::npos) {
2527  dirpart.erase(pos, 12);
2528 
2529  pos = dirpart.find("Run ");
2530  size_t length = dirpart.find('/', pos + 1) - pos + 1;
2531  if (pos != std::string::npos)
2532  dirpart.erase(pos, length);
2533  }
2534  }
2535 
2536  // If we are prepending, add it to the directory name,
2537  // and suppress reading of already existing reference histograms
2538  if (prepend == s_collateDirName || prepend == s_referenceDirName) {
2539  size_t slash = dirpart.find('/');
2540  // If we are reading reference, skip previous reference.
2541  if (slash == std::string::npos // skip if Reference is toplevel folder, i.e. no slash
2542  && slash + 1 + s_referenceDirName.size() == dirpart.size() &&
2543  dirpart.compare(slash + 1, s_referenceDirName.size(), s_referenceDirName) == 0)
2544  return 0;
2545 
2546  slash = dirpart.find('/');
2547  // Skip reading of EventInfo subdirectory.
2548  if (slash != std::string::npos && slash + 10 == dirpart.size() &&
2549  dirpart.compare(slash + 1, 9, "EventInfo") == 0) {
2550  if (verbose_)
2551  std::cout << "DQMStore::readDirectory: skipping '" << dirpart << "'\n";
2552  return 0;
2553  }
2554 
2555  // Add prefix.
2556  if (dirpart.empty())
2557  dirpart = prepend;
2558  else
2559  dirpart = prepend + '/' + dirpart;
2560  } else if (!prepend.empty()) {
2561  if (dirpart.empty())
2562  dirpart = prepend;
2563  else
2564  dirpart = prepend + '/' + dirpart;
2565  }
2566 
2567  // Loop over the contents of this directory in the file.
2568  // Post-pone string object handling to happen after other
2569  // objects have been read in so we are guaranteed to have
2570  // histograms by the time we read in quality tests and tags.
2571  TKey* key;
2572  TIter next(gDirectory->GetListOfKeys());
2573  std::list<TObject*> delayed;
2574  while ((key = (TKey*)next())) {
2575  std::unique_ptr<TObject> obj(key->ReadObj());
2576  if (dynamic_cast<TDirectory*>(obj.get())) {
2577  std::string subdir;
2578  subdir.reserve(curdir.size() + strlen(obj->GetName()) + 2);
2579  subdir += curdir;
2580  if (!curdir.empty())
2581  subdir += '/';
2582  subdir += obj->GetName();
2583 
2584  ntot += readDirectory(file, overwrite, onlypath, prepend, subdir, stripdirs);
2585  } else if (skip)
2586  ;
2587  else if (dynamic_cast<TObjString*>(obj.get())) {
2588  delayed.push_back(obj.release());
2589  } else {
2590  if (verbose_ > 2)
2591  std::cout << "DQMStore: reading object '" << obj->GetName() << "' of type '" << obj->IsA()->GetName()
2592  << "' from '" << file->GetName() << "' into '" << dirpart << "'\n";
2593 
2594  makeDirectory(dirpart);
2595  if (extract(obj.get(), dirpart, overwrite, collateHistograms_))
2596  ++count;
2597  }
2598  }
2599 
2600  while (!delayed.empty()) {
2601  if (verbose_ > 2)
2602  std::cout << "DQMStore: reading object '" << delayed.front()->GetName() << "' of type '"
2603  << delayed.front()->IsA()->GetName() << "' from '" << file->GetName() << "' into '" << dirpart
2604  << "'\n";
2605 
2606  makeDirectory(dirpart);
2607  if (extract(delayed.front(), dirpart, overwrite, collateHistograms_))
2608  ++count;
2609 
2610  delete delayed.front();
2611  delayed.pop_front();
2612  }
2613 
2614  if (verbose_ > 1)
2615  std::cout << "DQMStore: read " << count << '/' << ntot << " objects from directory '" << dirpart << "'\n";
2616 
2617  return ntot + count;
2618  }
2619 
2627  bool const overwrite /* = false */,
2628  std::string const& onlypath /* ="" */,
2629  std::string const& prepend /* ="" */,
2630  OpenRunDirs const stripdirs /* =KeepRunDirs */,
2631  bool const fileMustExist /* =true */) {
2632  return readFile(filename, overwrite, onlypath, prepend, stripdirs, fileMustExist);
2633  }
2634 
2640  OpenRunDirs const stripdirs /* =StripRunDirs */,
2641  bool const fileMustExist /* =true */) {
2642  bool overwrite = true;
2643  if (collateHistograms_)
2644  overwrite = false;
2645  if (verbose_) {
2646  std::cout << "DQMStore::load: reading from file '" << filename << "'\n";
2647  if (collateHistograms_)
2648  std::cout << "DQMStore::load: in collate mode "
2649  << "\n";
2650  else
2651  std::cout << "DQMStore::load: in overwrite mode "
2652  << "\n";
2653  }
2654 
2655  if (!s_rxpbfile.match(filename, 0, 0))
2656  return readFile(filename, overwrite, "", "", stripdirs, fileMustExist);
2657  else
2658  return readFilePB(filename, overwrite, "", "", stripdirs, fileMustExist);
2659  }
2660 
2667  bool const overwrite /* = false */,
2668  std::string const& onlypath /* ="" */,
2669  std::string const& prepend /* ="" */,
2670  OpenRunDirs const stripdirs /* =StripRunDirs */,
2671  bool const fileMustExist /* =true */) {
2672  if (verbose_)
2673  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
2674 
2675  std::unique_ptr<TFile> f;
2676 
2677  try {
2678  f.reset(TFile::Open(filename.c_str()));
2679  if (!f.get() || f->IsZombie())
2680  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
2681  } catch (std::exception&) {
2682  if (fileMustExist)
2683  throw;
2684  else {
2685  if (verbose_)
2686  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
2687  return false;
2688  }
2689  }
2690 
2691  unsigned n = readDirectory(f.get(), overwrite, onlypath, prepend, "", stripdirs);
2692  f->Close();
2693 
2694  for (auto const& me : data_)
2695  const_cast<MonitorElement&>(me).updateQReportStats();
2696 
2697  if (verbose_) {
2698  std::cout << "DQMStore::open: successfully read " << n << " objects from file '" << filename << "'";
2699  if (!onlypath.empty())
2700  std::cout << " from directory '" << onlypath << "'";
2701  if (!prepend.empty())
2702  std::cout << " into directory '" << prepend << "'";
2703  std::cout << std::endl;
2704  }
2705  return true;
2706  }
2707 
2711  inline TObject* DQMStore::extractNextObject(TBufferFile& buf) const {
2712  if (buf.Length() == buf.BufferSize())
2713  return nullptr;
2714  buf.InitMap();
2715  void* ptr = buf.ReadObjectAny(nullptr);
2716  return reinterpret_cast<TObject*>(ptr);
2717  }
2718 
2721  std::string& objname,
2722  TObject** obj) {
2723  size_t slash = h.full_pathname().rfind('/');
2724  size_t dirpos = (slash == std::string::npos ? 0 : slash);
2725  size_t namepos = (slash == std::string::npos ? 0 : slash + 1);
2726  dirname.assign(h.full_pathname(), 0, dirpos);
2727  objname.assign(h.full_pathname(), namepos, std::string::npos);
2728  TBufferFile buf(TBufferFile::kRead, h.size(), (void*)h.streamed_histo().data(), kFALSE);
2729  buf.Reset();
2730  *obj = extractNextObject(buf);
2731  if (!*obj) {
2732  raiseDQMError("DQMStore", "Error reading element:'%s'", h.full_pathname().c_str());
2733  }
2734  }
2735 
2737  bool const overwrite /* = false */,
2738  std::string const& onlypath /* ="" */,
2739  std::string const& prepend /* ="" */,
2740  OpenRunDirs const stripdirs /* =StripRunDirs */,
2741  bool const fileMustExist /* =true */) {
2742  using google::protobuf::io::ArrayInputStream;
2743  using google::protobuf::io::CodedInputStream;
2744  using google::protobuf::io::FileInputStream;
2745  using google::protobuf::io::FileOutputStream;
2746  using google::protobuf::io::GzipInputStream;
2747  using google::protobuf::io::GzipOutputStream;
2748 
2749  if (verbose_)
2750  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
2751 
2752  int filedescriptor;
2753  if ((filedescriptor = ::open(filename.c_str(), O_RDONLY)) == -1) {
2754  if (fileMustExist)
2755  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
2756  else if (verbose_)
2757  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
2758  return false;
2759  }
2760 
2761  dqmstorepb::ROOTFilePB dqmstore_message;
2762  FileInputStream fin(filedescriptor);
2763  GzipInputStream input(&fin);
2764  CodedInputStream input_coded(&input);
2765  input_coded.SetTotalBytesLimit(1024 * 1024 * 1024, -1);
2766  if (!dqmstore_message.ParseFromCodedStream(&input_coded)) {
2767  raiseDQMError("DQMStore", "Fatal parsing file '%s'", filename.c_str());
2768  return false;
2769  }
2770  ::close(filedescriptor);
2771 
2772  for (int i = 0; i < dqmstore_message.histo_size(); ++i) {
2773  std::string path;
2774  std::string objname;
2775 
2776  TObject* obj = nullptr;
2777  dqmstorepb::ROOTFilePB::Histo const& h = dqmstore_message.histo(i);
2778  get_info(h, path, objname, &obj);
2779 
2780  setCurrentFolder(path);
2781  if (obj) {
2782  /* Before calling the extract() check if histogram exists:
2783  * if it does - flags for the given monitor are already set (and merged)
2784  * else - set the flags after the histogram is created.
2785  */
2786  MonitorElement* me = findObject(0, 0, 0, path, objname);
2787 
2788  /* Run histograms should be collated and not overwritten,
2789  * Lumi histograms should be overwritten (and collate flag is not checked)
2790  */
2791  bool overwrite = h.flags() & DQMNet::DQM_PROP_LUMI;
2792  bool collate = !(h.flags() & DQMNet::DQM_PROP_LUMI);
2793  extract(static_cast<TObject*>(obj), path, overwrite, collate);
2794 
2795  if (me == nullptr) {
2796  me = findObject(0, 0, 0, path, objname);
2797  me->data_.flags = h.flags();
2798  }
2799 
2800  delete obj;
2801  }
2802  }
2803 
2804  cd();
2805  return true;
2806  }
2807 
2814  auto i = qtests_.find(qtname);
2815  auto e = qtests_.end();
2816  return (i == e ? nullptr : i->second);
2817  }
2818 
2822  QCriterion* DQMStore::createQTest(std::string const& algoname, std::string const& qtname) {
2823  if (qtests_.count(qtname))
2824  raiseDQMError("DQMStore", "Attempt to create duplicate quality test '%s'", qtname.c_str());
2825 
2826  auto i = qalgos_.find(algoname);
2827  if (i == qalgos_.end())
2828  raiseDQMError("DQMStore",
2829  "Cannot create a quality test using unknown"
2830  " algorithm '%s'",
2831  algoname.c_str());
2832 
2833  QCriterion* qc = i->second(qtname);
2834  qc->setVerbose(verboseQT_);
2835 
2836  qtests_[qtname] = qc;
2837  return qc;
2838  }
2839 
2842  void DQMStore::useQTest(std::string const& dir, std::string const& qtname) {
2843  // Clean the path
2845  std::string const* cleaned = nullptr;
2846  cleanTrailingSlashes(dir, clean, cleaned);
2847 
2848  // Validate the path.
2849  if (cleaned->find_first_not_of(s_safe) != std::string::npos)
2850  raiseDQMError("DQMStore",
2851  "Monitor element path name '%s'"
2852  " uses unacceptable characters",
2853  cleaned->c_str());
2854 
2855  // Redirect to the pattern match version.
2856  useQTestByMatch(*cleaned + "/*", qtname);
2857  }
2858 
2861  QCriterion* qc = getQCriterion(qtname);
2862  if (!qc)
2863  raiseDQMError("DQMStore", "Cannot apply non-existent quality test '%s'", qtname.c_str());
2864 
2865  auto* fm = new fastmatch(pattern);
2866 
2867  // Record the test for future reference.
2868  QTestSpec qts(fm, qc);
2869  qtestspecs_.push_back(qts);
2870 
2871  // Apply the quality test.
2872  std::string path;
2873  int cases = 0;
2874  for (auto const& me : data_) {
2875  path.clear();
2876  mergePath(path, *me.data_.dirname, me.data_.objname);
2877  if (fm->match(path)) {
2878  ++cases;
2879  const_cast<MonitorElement&>(me).addQReport(qts.second);
2880  }
2881  }
2882 
2883  //return the number of matched cases
2884  return cases;
2885  }
2889  if (verbose_ > 0)
2890  std::cout << "DQMStore: running runQTests() with reset = " << (reset_ ? "true" : "false") << std::endl;
2891 
2892  // Apply quality tests to each monitor element, skipping references.
2893  for (auto const& me : data_)
2894  if (!isSubdirectory(s_referenceDirName, *me.data_.dirname))
2895  const_cast<MonitorElement&>(me).runQTests();
2896 
2897  reset_ = false;
2898  }
2899 
2903  int DQMStore::getStatus(std::string const& path /* = "" */) const {
2905  std::string const* cleaned = nullptr;
2906  cleanTrailingSlashes(path, clean, cleaned);
2907 
2909  for (auto const& me : data_) {
2910  if (!cleaned->empty() && !isSubdirectory(*cleaned, *me.data_.dirname))
2911  continue;
2912 
2913  if (me.hasError())
2914  return dqm::qstatus::ERROR;
2915  else if (me.hasWarning())
2916  status = dqm::qstatus::WARNING;
2917  else if (status < dqm::qstatus::WARNING && me.hasOtherReport())
2918  status = dqm::qstatus::OTHER;
2919  }
2920  return status;
2921  }
2922 
2927  std::vector<std::string> contents;
2928  getContents(contents);
2929 
2930  std::cout << " ------------------------------------------------------------\n"
2931  << " Directory structure: \n"
2932  << " ------------------------------------------------------------\n";
2933 
2934  std::copy(contents.begin(), contents.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
2935 
2936  std::cout << " ------------------------------------------------------------\n";
2937  }
2938 
2942  // check if the collate option is active on the DQMStore
2943  bool DQMStore::isCollate() const { return collateHistograms_; }
2947  // check if the monitor element is in auto-collation folder
2949  return me && isSubdirectory(s_collateDirName, *me->data_.dirname);
2950  }
2951 
2952 } // namespace dqm::dqmstoreimpl
MonitorElement * bookString(char_string const &name, char_string const &value)
Book string.
Definition: DQMStore.cc:1100
size
Write out results.
TObject * extractNextObject(TBufferFile &) const
Definition: DQMStore.cc:2711
Definition: start.py:1
edm::ErrorSummaryEntry Error
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX)
Definition: DQMStore.cc:239
virtual TH2D * getTH2D() const
T getUntrackedParameter(std::string const &, T const &) const
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
bool compare_strings(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:196
uint32_t moduleId
Definition: DQMNet.h:100
::google::protobuf::uint32 size() const
virtual TH2F * getTH2F() const
MonitorElement * getElement(std::string const &path)
Definition: DQMStore.cc:439
MonitorElement * book2D(char_string const &name, char_string const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2D histogram.
Definition: DQMStore.cc:1178
QReports qreports
Definition: DQMNet.h:103
const ::std::string & full_pathname() const
void goUp()
equivalent to "cd .."
Definition: DQMStore.cc:648
void cloneRunHistograms(uint32_t run, uint32_t moduleId)
Definition: DQMStore.cc:1796
MonitorElement * book2DD(char_string const &name, char_string const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2D histogram.
Definition: DQMStore.cc:1202
DQMStore(edm::ParameterSet const &pset, edm::ActivityRegistry &)
Definition: DQMStore.cc:464
static const int OTHER
static void collateProfile2D(MonitorElement *me, TProfile2D *h, unsigned verbose)
Definition: DQMStore.cc:1455
void savePB(std::string const &filename, std::string const &path="", uint32_t run=0, uint32_t lumi=0)
Definition: DQMStore.cc:2413
std::string algorithm
Definition: DQMNet.h:90
MonitorElement * book1S(char_string const &name, char_string const &title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:1127
void makeDirectory(std::string const &path)
Definition: DQMStore.cc:659
MonitorElement * bookFloat(TString const &name)
Definition: DQMStore.cc:233
DQMNet::CoreObject data_
std::vector< std::string > getMEs() const
get list of (non-dir) MEs of current directory
Definition: DQMStore.cc:1487
MonitorElement * book2S(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Definition: DQMStore.cc:284
dqm::legacy::MonitorElement MonitorElement
Definition: DQMStore.h:73
unsigned int readDirectory(TFile *file, bool overwrite, std::string const &path, std::string const &prepend, std::string const &curdir, OpenRunDirs stripdirs)
Definition: DQMStore.cc:2491
MonitorElement * book_(std::string const &dir, std::string const &name, char const *context)
Definition: DQMStore.cc:1033
void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:418
void saveMonitorElementRangeToPB(std::string const &dir, unsigned int run, MEMap::const_iterator begin, MEMap::const_iterator end, dqmstorepb::ROOTFilePB &file, unsigned int &counter)
Definition: DQMStore.cc:2373
std::string const empty_str
Definition: DQMStore.cc:71
virtual TH1F * getTH1F() const
MonitorElement * book1DD_(std::string const &dir, std::string const &name, TH1D *h)
Book 1D histogram based on TH1D.
Definition: DQMStore.cc:1116
MonitorElement * book1DD(TString const &name, TString const &title, int nchX, double lowX, double highX)
Definition: DQMStore.cc:257
uint32_t flags
Definition: DQMNet.h:94
LuminosityBlockID const & luminosityBlockID() const
Definition: GlobalContext.h:55
static bool CheckBinLabels(const TAxis *a1, const TAxis *a2)
Check the consistency of the axis labels.
MonitorElement * book2S_(std::string const &dir, std::string const &name, TH2S *h)
Book 2D histogram based on TH2S.
Definition: DQMStore.cc:1168
std::vector< MonitorElement * > getContents(std::string const &path) const
Definition: DQMStore.cc:1520
void setLumiFlag()
this ME is meant to be stored for each luminosity section
void saveMonitorElementToROOT(MonitorElement const &me, TFile &file)
Definition: DQMStore.cc:2145
static const int WARNING
def replace(string, replacements)
Kind kind() const
Get the type of the monitor element.
static const uint32_t DQM_PROP_TAGGED
Definition: DQMNet.h:52
MonitorElement * book3D(char_string const &name, char_string const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, int nchZ, double lowZ, double highZ)
Book 3D histogram.
Definition: DQMStore.cc:1255
std::string const & pwd() const
Definition: DQMStore.cc:618
static const uint32_t DQM_PROP_EFFICIENCY_PLOT
Definition: DQMNet.h:61
static void collate2D(MonitorElement *me, TH2F *h, unsigned verbose)
Definition: DQMStore.cc:1428
bool load(std::string const &filename, OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2639
std::unique_ptr< std::ostream > stream_
Definition: DQMStore.h:680
MonitorElement * bookProfile_(std::string const &dir, std::string const &name, TProfile *h)
Book profile histogram based on TProfile.
Definition: DQMStore.cc:1276
static void collate2S(MonitorElement *me, TH2S *h, unsigned verbose)
Definition: DQMStore.cc:1433
MonitorElement * bookProfile2D(char_string const &name, char_string const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, double lowZ, double highZ, char const *option="s")
Definition: DQMStore.cc:1369
MonitorElement * bookInt(char_string const &name)
Book int.
Definition: DQMStore.cc:1072
const std::string * dirname
Definition: DQMNet.h:101
static void collate1DD(MonitorElement *me, TH1D *h, unsigned verbose)
Definition: DQMStore.cc:1423
MonitorElement * book2DD_(std::string const &dir, std::string const &name, TH2D *h)
Book 2D histogram based on TH2D.
Definition: DQMStore.cc:1173
static void collateProfile(MonitorElement *me, TProfile *h, unsigned verbose)
Definition: DQMStore.cc:1448
bool isCollateME(MonitorElement *me) const
Definition: DQMStore.cc:2948
QCriterion * createQTest(std::string const &algoname, std::string const &qtname)
Definition: DQMStore.cc:2822
void cd()
go to top directory (ie. root)
Definition: DQMStore.cc:621
static bool checkBinningMatches(MonitorElement *me, TH1 *h, unsigned verbose)
Definition: DQMStore.cc:1392
void set_flags(::google::protobuf::uint32 value)
MonitorElement * book1S_(std::string const &dir, std::string const &name, TH1S *h)
Book 1D histogram based on TH1S.
Definition: DQMStore.cc:1111
uint32_t run
Definition: DQMNet.h:97
void saveMonitorElementToPB(MonitorElement const &me, dqmstorepb::ROOTFilePB &file)
Definition: DQMStore.cc:2348
MonitorElement * bookProfile(char_string const &name, char_string const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, char const *option="s")
Definition: DQMStore.cc:1283
const ::std::string & streamed_histo() const
virtual TH1S * getTH1S() const
void get_info(dqmstorepb::ROOTFilePB_Histo const &, std::string &dirname, std::string &objname, TObject **obj)
Definition: DQMStore.cc:2719
bool extract(TObject *obj, std::string const &dir, bool overwrite, bool collateHistograms)
Definition: DQMStore.cc:1876
const std::string getFullname() const
get full name of ME including Pathname
static std::string const input
Definition: EdmProvDump.cc:48
MatchingHeuristicEnum matching_
Definition: DQMStore.h:95
void setVerbose(unsigned level)
Definition: DQMStore.cc:612
void setLumi(uint32_t ls)
void deleteUnusedLumiHistograms(uint32_t run, uint32_t lumi)
Definition: DQMStore.cc:1836
int getStatus(std::string const &path="") const
Definition: DQMStore.cc:2903
static void clean(char *s)
std::string const s_referenceDirName
Definition: DQMStore.cc:60
void Fill(long long x)
static void collate1S(MonitorElement *me, TH1S *h, unsigned verbose)
Definition: DQMStore.cc:1418
unsigned int maxNumberOfStreams() const
Definition: SystemBounds.h:35
virtual void Reset()
reset ME (ie. contents, errors, etc)
void mergePath(std::string &path, std::string const &dir, std::string const &name)
Definition: DQMStore.cc:104
char const * label
lat::Regexp const s_rxmeval
Definition: DQMStore.cc:64
MonitorElement * get(std::string const &path) const
get ME from full pathname (e.g. "my/long/dir/my_histo")
Definition: DQMStore.cc:1509
lat::Regexp const s_rxpbfile
Definition: DQMStore.cc:69
bool dirExists(std::string const &path)
Definition: DQMStore.cc:461
MonitorElement * book2D_(std::string const &dir, std::string const &name, TH2F *h)
Book 2D histogram based on TH2F.
Definition: DQMStore.cc:1163
lat::Regexp const s_rxmeqr2
Definition: DQMStore.cc:66
static const uint32_t DQM_PROP_HAS_REFERENCE
Definition: DQMNet.h:51
std::string tagString() const
uint32_t lumi
Definition: DQMNet.h:98
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
bool readFilePB(std::string const &filename, bool overwrite=false, std::string const &path="", std::string const &prepend="", OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2736
void print_trace(std::string const &dir, std::string const &name)
Definition: DQMStore.cc:552
std::vector< std::string > getMEs()
Definition: DQMStore.cc:455
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, char const *option="s")
Definition: DQMStore.cc:333
void addQReport(const DQMNet::QValue &desc, QCriterion *qc)
Add quality report, from DQMStore.
bool match(std::string const &s) const
Definition: DQMStore.cc:214
bool containsAnyMonitorable(std::string const &path)
Definition: DQMStore.cc:457
MonitorElement * book3D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, int nchZ, double lowZ, double highZ)
Definition: DQMStore.cc:317
std::vector< std::shared_ptr< fireworks::OptionNode > > Options
MonitorElement * bookFloat_(std::string const &dir, std::string const &name)
Book float.
Definition: DQMStore.cc:1076
double f[11][100]
int useQTestByMatch(std::string const &pattern, std::string const &qtname)
attach quality test <qc> to monitor elements matching <pattern>.
Definition: DQMStore.cc:2860
#define end
Definition: vmac.h:39
MonitorElement * bookProfile2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, double lowZ, double highZ, char const *option="s")
Definition: DQMStore.cc:381
lat::Regexp const s_rxself
Definition: DQMStore.cc:68
Definition: value.py:1
void addProfiles(TProfile *h1, TProfile *h2, TProfile *sum, float c1, float c2)
lat::Regexp const s_rxtrace
Definition: DQMStore.cc:67
virtual TProfile2D * getTProfile2D() const
bool compare_strings_reverse(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:178
MonitorElement * book1D_(std::string const &dir, std::string const &name, TH1F *h)
Book 1D histogram based on TH1F.
Definition: DQMStore.cc:1106
std::pair< fastmatch *, QCriterion * > QTestSpec
Definition: DQMStore.h:640
std::vector< MonitorElement * > getAllContents(std::string const &path, uint32_t runNumber=0, uint32_t lumi=0) const
Definition: DQMStore.cc:1616
std::string objname
Definition: DQMNet.h:102
virtual TH2S * getTH2S() const
std::string qtname
Definition: DQMNet.h:89
void useQTest(std::string const &dir, std::string const &qtname)
Definition: DQMStore.cc:2842
void postGlobalBeginLumi(const edm::GlobalContext &)
Definition: DQMStore.cc:1724
MonitorElement * findObject(uint32_t run, uint32_t lumi, uint32_t moduleId, std::string const &dir, std::string const &name) const
Definition: DQMStore.cc:1587
fastmatch(std::string fastString)
Definition: DQMStore.cc:123
demangled
Definition: symbols.py:62
void splitPath(std::string &dir, std::string &name, std::string const &path)
Definition: DQMStore.cc:95
MonitorElement * book2S(char_string const &name, char_string const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2S histogram.
Definition: DQMStore.cc:1190
const ::dqmstorepb::ROOTFilePB_Histo & histo(int index) const
void set_size(::google::protobuf::uint32 value)
QCriterion * getQCriterion(std::string const &qtname) const
Definition: DQMStore.cc:2813
virtual TProfile * getTProfile() const
virtual TH1D * getTH1D() const
part
Definition: HCALResponse.h:20
tuple msg
Definition: mps_check.py:285
TEveGeoShape * clone(const TEveElement *element, TEveElement *parent)
Definition: eve_macros.cc:135
void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:639
std::set< std::string > dirs_
Definition: DQMStore.h:684
std::vector< std::string > getSubdirs() const
Definition: DQMStore.cc:1466
lat::Regexp const s_rxmeqr1
Definition: DQMStore.cc:65
MonitorElement * bookProfile2D_(std::string const &dir, std::string const &name, TProfile2D *h)
Book 2D profile histogram based on TProfile2D.
Definition: DQMStore.cc:1343
MonitorElement * bookInt_(std::string const &dir, std::string const &name)
Book int.
Definition: DQMStore.cc:1061
void set_full_pathname(const ::std::string &value)
void setVerbose(int verbose)
probability limits for warnings, errors
Definition: QTest.h:137
#define begin
Definition: vmac.h:32
static void collate2DD(MonitorElement *me, TH2D *h, unsigned verbose)
Definition: DQMStore.cc:1438
MonitorElement * book2DD(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Definition: DQMStore.cc:302
T dot(const Basic3DVector &v) const
Scalar product, or "dot" product, with a vector of same type.
::dqmstorepb::ROOTFilePB_Histo * add_histo()
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Definition: DQMStore.cc:266
std::unique_ptr< lat::Regexp > regexp_
Definition: DQMStore.h:93
static std::atomic< unsigned int > counter
MonitorElement * book3D_(std::string const &dir, std::string const &name, TH3F *h)
Book 3D histogram based on TH3F.
Definition: DQMStore.cc:1250
std::string tagLabelString() const
return label string for the monitor element tag (eg. <name>t=12345</name>)
MonitorElement * bookFloat(char_string const &name)
Book float.
Definition: DQMStore.cc:1087
bool readFile(std::string const &filename, bool overwrite=false, std::string const &path="", std::string const &prepend="", OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2666
std::string const s_collateDirName
Definition: DQMStore.cc:61
std::vector< MonitorElement * > getMatchingContents(std::string const &pattern, lat::Regexp::Syntax syntaxType=lat::Regexp::Wildcard) const
Definition: DQMStore.cc:1659
std::string message
Definition: DQMNet.h:88
MonitorElement * bookString(TString const &name, TString const &value)
Definition: DQMStore.cc:235
::google::protobuf::uint32 flags() const
std::string const s_safe
Definition: DQMStore.cc:62
static const int STATUS_OK
bool open(std::string const &filename, bool overwrite=false, std::string const &path="", std::string const &prepend="", OpenRunDirs stripdirs=KeepRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2626
void showDirStructure() const
Definition: DQMStore.cc:2926
MonitorElement * initialise(MonitorElement *me, std::string const &path)
QCriterion * makeQCriterion(std::string const &qtname)
Definition: DQMStore.cc:113
MonitorElement * book1D(char_string const &name, char_string const &title, int const nchX, double const lowX, double const highX)
Book 1D histogram.
Definition: DQMStore.cc:1121
MonitorElement * initialise(Kind kind)
TObject * getRootObject() const override
void cloneLumiHistograms(uint32_t run, uint32_t lumi, uint32_t moduleId)
Definition: DQMStore.cc:1756
void saveMonitorElementRangeToROOT(std::string const &dir, std::string const &refpath, SaveReferenceTag ref, int minStatus, unsigned int run, MEMap::const_iterator begin, MEMap::const_iterator end, TFile &file, unsigned int &counter)
Definition: DQMStore.cc:2171
bool cdInto(std::string const &path) const
Definition: DQMStore.cc:2100
void Reset(std::vector< TH2F > &depth)
static void collate1D(MonitorElement *me, TH1F *h, unsigned verbose)
Definition: DQMStore.cc:1413
bool containsAnyMonitorable(std::string const &path) const
Definition: DQMStore.cc:1501
MonitorElement * get(std::string const &path)
Definition: DQMStore.cc:437
long double T
void initializeFrom(const edm::ParameterSet &)
Definition: DQMStore.cc:492
bool isSubdirectory(std::string const &ofdir, std::string const &path)
Definition: DQMStore.cc:76
float qtresult
Definition: DQMNet.h:87
std::string effLabelString() const
return label string for the monitor element tag (eg. <name>t=12345</name>)
static const uint32_t DQM_PROP_LUMI
Definition: DQMNet.h:58
static std::string const source
Definition: EdmProvDump.cc:47
void cleanTrailingSlashes(std::string const &path, std::string &clean, std::string const *&cleaned)
Definition: DQMStore.cc:81
MonitorElement * bookString_(std::string const &dir, std::string const &name, std::string const &value)
Book string.
Definition: DQMStore.cc:1091
MonitorElement * book1DD(char_string const &name, char_string const &title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:1133
virtual TH1 * getTH1() const
void initQCriterion(std::map< std::string, QCriterion *(*)(std::string const &)> &m)
Definition: DQMStore.cc:118
MonitorElement * bookInt(TString const &name)
Definition: DQMStore.cc:231
virtual TH3F * getTH3F() const
MonitorElement * book1S(TString const &name, TString const &title, int nchX, double lowX, double highX)
Definition: DQMStore.cc:250
void save(std::string const &filename, std::string const &path="", std::string const &pattern="", std::string const &rewrite="", uint32_t run=0, uint32_t lumi=0, SaveReferenceTag ref=SaveWithReference, int minStatus=dqm::qstatus::STATUS_OK, std::string const &fileupdate="RECREATE")
Definition: DQMStore.cc:2244
def move(src, dest)
Definition: eostools.py:511
static void collate3D(MonitorElement *me, TH3F *h, unsigned verbose)
Definition: DQMStore.cc:1443
std::vector< MonitorElement * > getAllContents(std::string const &path, uint32_t runNumber=0, uint32_t lumi=0)
Definition: DQMStore.cc:431
std::string qualityTagString(const DQMNet::QValue &qv) const
static const int ERROR
std::string const s_monitorDirName
name of global monitoring folder (containing all sources subdirectories)
Definition: DQMStore.cc:59
bool dirExists(std::string const &path) const
true if directory exists
Definition: DQMStore.cc:698
void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:424
std::vector< std::string > getSubdirs()
Definition: DQMStore.cc:453
void set_streamed_histo(const ::std::string &value)
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:10