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 <iterator>
20 #include <cerrno>
21 #include <boost/algorithm/string.hpp>
22 #include <boost/range/iterator_range_core.hpp>
23 
24 #include <fstream>
25 #include <sstream>
26 #include <exception>
27 #include <utility>
28 
55 namespace {
56 
59  const std::string s_monitorDirName = "DQMData";
60  const std::string s_referenceDirName = "Reference";
61  const std::string s_collateDirName = "Collate";
62  const std::string s_safe = "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# ";
63 
64  const lat::Regexp s_rxmeval ("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$");
65  const lat::Regexp s_rxmeqr1 ("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$");
66  const lat::Regexp s_rxmeqr2 ("^st\\.(\\d+)\\.(.*)$");
67  const lat::Regexp s_rxtrace ("(.*)\\((.*)\\+0x.*\\).*");
68  const lat::Regexp s_rxself ("^[^()]*DQMStore::.*");
69  const lat::Regexp s_rxpbfile (".*\\.pb$");
70 
74  bool
75  isSubdirectory(const std::string &ofdir, const std::string &path)
76  {
77  return (ofdir.empty()
78  || (path.size() >= ofdir.size()
79  && path.compare(0, ofdir.size(), ofdir) == 0
80  && (path.size() == ofdir.size()
81  || path[ofdir.size()] == '/')));
82  }
83 
84  void
85  cleanTrailingSlashes(const std::string &path, std::string &clean, const std::string *&cleaned)
86  {
87  clean.clear();
88  cleaned = &path;
89 
90  size_t len = path.size();
91  for ( ; len > 0 && path[len-1] == '/'; --len)
92  ;
93 
94  if (len != path.size())
95  {
96  clean = path.substr(0, len);
97  cleaned = &clean;
98  }
99  }
100 
101  void
102  splitPath(std::string &dir, std::string &name, const std::string &path)
103  {
104  size_t slash = path.rfind('/');
105  if (slash != std::string::npos)
106  {
107  dir.append(path, 0, slash);
108  name.append(path, slash+1, std::string::npos);
109  }
110  else
111  name = path;
112  }
113 
114  void
115  mergePath(std::string &path, const std::string &dir, const std::string &name)
116  {
117  path.reserve(dir.size() + name.size() + 2);
118  path += dir;
119  if (! path.empty())
120  path += '/';
121  path += name;
122  }
123 
124  template <class T>
125  QCriterion *
126  makeQCriterion(const std::string &qtname)
127  { return new T(qtname); }
128 
129  template <class T>
130  void
131  initQCriterion(std::map<std::string, QCriterion *(*)(const std::string &)> &m)
132  { m[T::getAlgoName()] = &makeQCriterion<T>; }
133 
134 } // anonymous namespace
135 
138  fastString_ (std::move(_fastString)), matching_ (UseFull)
139 {
140  try
141  {
142  regexp_ = std::make_unique<lat::Regexp>(fastString_, 0, lat::Regexp::Wildcard);
143  regexp_->study();
144  }
145  catch (lat::Error &e)
146  {
147  raiseDQMError("DQMStore", "Invalid wildcard pattern '%s' in quality"
148  " test specification", fastString_.c_str());
149  }
150 
151  // count stars ( "*" )
152  size_t starCount = 0;
153  int pos = -1;
154  while (true)
155  {
156  pos = fastString_.find('*', pos + 1 );
157  if ((size_t)pos == std::string::npos)
158  break;
159  ++starCount;
160  }
161 
162  // investigate for heuristics
163  if ((fastString_.find('"') != std::string::npos) ||
164  (fastString_.find(']') != std::string::npos) ||
165  (fastString_.find('?') != std::string::npos) ||
166  (fastString_.find('\\') != std::string::npos) ||
167  (starCount > 2))
168  {
169  // no fast version can be used
170  return;
171  }
172 
173  // match for pattern "*MyString" and "MyString*"
174  if (starCount == 1)
175  {
176  if (boost::algorithm::starts_with(fastString_, "*"))
177  {
179  fastString_.erase(0,1);
180  return;
181  }
182 
183  if (boost::algorithm::ends_with(fastString_, "*"))
184  {
186  fastString_.erase(fastString_.length()-1,1);
187  return;
188  }
189  }
190 
191  // match for pattern "*MyString*"
192  if (starCount == 2)
193  {
194  if (boost::algorithm::starts_with(fastString_, "*") &&
195  boost::algorithm::ends_with(fastString_, "*"))
196  {
197  matching_ = TwoStar;
198  fastString_.erase(0,1);
199  fastString_.erase(fastString_.size() - 1, 1);
200  return;
201  }
202  }
203 }
204 
206  std::string const& input) const
207 {
208  if (input.size() < pattern.size())
209  return false;
210 
211  // compare the two strings character by character for equalness:
212  // this does not create uneeded copies of std::string. The
213  // boost::algorithm implementation does
214  auto rit_pattern = pattern.crbegin();
215  auto rit_input = input.crbegin();
216 
217  for (; rit_pattern < pattern.rend(); ++rit_pattern, ++rit_input)
218  {
219  if (*rit_pattern != *rit_input)
220  // found a difference, fail
221  return false;
222  }
223  return true;
224 }
225 
227  std::string const& input) const
228 {
229  if (input.size() < pattern.size())
230  return false;
231 
232  // compare the two strings character by character for equalness:
233  // this does not create uneeded copies of std::string. The
234  // boost::algorithm implementation does.
235  auto rit_pattern = pattern.cbegin();
236  auto rit_input = input.cbegin();
237 
238  for (; rit_pattern < pattern.end(); ++rit_pattern, ++rit_input)
239  {
240  if (*rit_pattern != *rit_input)
241  // found a difference, fail
242  return false;
243  }
244  return true;
245 }
246 
247 bool fastmatch::match(std::string const& s) const
248 {
249  switch (matching_)
250  {
251  case OneStarStart:
253 
254  case OneStarEnd:
255  return compare_strings(fastString_, s);
256 
257  case TwoStar:
258  return (s.find(fastString_) != std::string::npos);
259 
260  default:
261  return regexp_->match(s);
262  }
263 }
264 
265 //IBooker methods
267  owner_->cd();
268 }
269 
271  owner_->cd(dir);
272 }
273 
275  owner_->setCurrentFolder(fullpath);
276 }
277 
279  owner_->goUp();
280 }
281 
283  return owner_->pwd();
284 }
285 
286 void DQMStore::IBooker::tag(MonitorElement *me, unsigned int tag) {
287  owner_->tag(me, tag);
288 }
289 
290 void DQMStore::IBooker::tagContents(const std::string &path, unsigned int myTag) {
291  owner_->tagContents(path, myTag);
292 }
293 
294 //IGetter methods
295 std::vector<MonitorElement*>
297  uint32_t run /* = 0 */,
298  uint32_t lumi /* = 0 */) {
299  return owner_->getAllContents(path, run, lumi);
300 }
301 
303  return owner_->get(path);
304 }
305 
307  MonitorElement *ptr = this->get(path);
308  if (ptr == nullptr) {
309  std::stringstream msg;
310  msg << "DQM object not found";
311 
312  msg << ": " << path;
313 
314  // can't use cms::Exception inside DQMStore
315  throw std::out_of_range(msg.str());
316  }
317  return ptr;
318 }
319 
320 std::vector<std::string> DQMStore::IGetter::getSubdirs() {
321  return owner_->getSubdirs();
322 }
323 
324 std::vector<std::string> DQMStore::IGetter::getMEs() {
325  return owner_->getMEs();
326 }
327 
329  return owner_->containsAnyMonitorable(path);
330 }
331 
333  return owner_->dirExists(path);
334 }
335 
337  owner_->cd();
338 }
339 
341  owner_->cd(dir);
342 }
343 
345  owner_->setCurrentFolder(fullpath);
346 }
347 
350  : DQMStore{pset}
351 {
352  ar.preallocateSignal_.connect([this](edm::service::SystemBounds const& iBounds) {
353  if(iBounds.maxNumberOfStreams() > 1 ) {
354  enableMultiThread_ = true;
355  }
356  });
357  if(pset.getUntrackedParameter<bool>("forceResetOnBeginRun",false)) {
358  ar.watchPostSourceRun([this](edm::RunIndex){ forceReset(); });
359  }
360  if(pset.getUntrackedParameter<bool>("forceResetOnBeginLumi",false) && enableMultiThread_ == false) {
361  forceResetOnBeginLumi_ = true;
362  ar.watchPostSourceLumi([this](edm::LuminosityBlockIndex){ forceReset(); });
363  }
364  ar.watchPostGlobalBeginLumi(this, &DQMStore::postGlobalBeginLumi);
365 }
366 
368 {
369  initializeFrom(pset);
370 }
371 
373 {
374  for (auto & qtest : qtests_)
375  delete qtest.second;
376 
377  for (auto & qtestspec : qtestspecs_)
378  delete qtestspec.first;
379 }
380 
381 void
383  makeDirectory("");
384  reset();
385 
386  // set steerable parameters
387  verbose_ = pset.getUntrackedParameter<int>("verbose", 0);
388  if (verbose_ > 0)
389  std::cout << "DQMStore: verbosity set to " << verbose_ << std::endl;
390 
391  verboseQT_ = pset.getUntrackedParameter<int>("verboseQT", 0);
392  if (verbose_ > 0)
393  std::cout << "DQMStore: QTest verbosity set to " << verboseQT_ << std::endl;
394 
395  collateHistograms_ = pset.getUntrackedParameter<bool>("collateHistograms", false);
396  if (collateHistograms_)
397  std::cout << "DQMStore: histogram collation is enabled\n";
398 
399  enableMultiThread_ = pset.getUntrackedParameter<bool>("enableMultiThread", false);
400  if (enableMultiThread_)
401  std::cout << "DQMStore: MultiThread option is enabled\n";
402 
403  LSbasedMode_ = pset.getUntrackedParameter<bool>("LSbasedMode", false);
404  if (LSbasedMode_)
405  std::cout << "DQMStore: LSbasedMode option is enabled\n";
406 
407  std::string ref = pset.getUntrackedParameter<std::string>("referenceFileName", "");
408  if (! ref.empty())
409  {
410  std::cout << "DQMStore: using reference file '" << ref << "'\n";
411  readFile(ref, true, "", s_referenceDirName, StripRunDirs, false);
412  }
413 
414  initQCriterion<Comp2RefChi2>(qalgos_);
415  initQCriterion<Comp2Ref2DChi2>(qalgos_);
416  initQCriterion<Comp2RefKolmogorov>(qalgos_);
417  initQCriterion<ContentsXRange>(qalgos_);
418  initQCriterion<ContentsYRange>(qalgos_);
419  initQCriterion<MeanWithinExpected>(qalgos_);
420  initQCriterion<Comp2RefEqualH>(qalgos_);
421  initQCriterion<DeadChannel>(qalgos_);
422  initQCriterion<NoisyChannel>(qalgos_);
423  initQCriterion<ContentSigma>(qalgos_);
424  initQCriterion<ContentsWithinExpected>(qalgos_);
425  initQCriterion<CompareToMedian>(qalgos_);
426  initQCriterion<CompareLastFilledBin>(qalgos_);
427  initQCriterion<CheckVariance>(qalgos_);
428 
429  scaleFlag_ = pset.getUntrackedParameter<double>("ScalingFlag", 0.0);
430  if (verbose_ > 0)
431  std::cout << "DQMStore: Scaling Flag set to " << scaleFlag_ << std::endl;
432 }
433 
434 /* Generic method to do a backtrace and print it to stdout. It is
435  customised to properly get the routine that called the booking of the
436  histograms, which, following the usual stack, is at position 4. The
437  name of the calling function is properly demangled and the original
438  shared library including this function is also printed. For a more
439  detailed explanation of the routines involved, see here:
440  http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
441  http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html.*/
442 
443 void
445 {
446  // the access to the member stream_ is implicitely protected against
447  // concurrency problems because the print_trace method is always called behind
448  // a lock (see bookTransaction).
449  if (!stream_)
450  stream_ = std::make_unique<std::ofstream>("histogramBookingBT.log");
451 
452  void *array[10];
453  size_t size;
454  char **strings;
455  int r=0;
456  lat::RegexpMatch m;
457  m.reset();
458 
459  size = backtrace (array, 10);
460  strings = backtrace_symbols (array, size);
461 
462  size_t level = 1;
463  char * demangled = nullptr;
464  for (; level < size; ++level) {
465  if (!s_rxtrace.match(strings[level], 0, 0, &m)) continue;
466  demangled = abi::__cxa_demangle(m.matchString(strings[level], 2).c_str(), nullptr, nullptr, &r);
467  if (!demangled) continue;
468  if (!s_rxself.match(demangled, 0, 0)) break;
469  free(demangled);
470  demangled = nullptr;
471  }
472 
473  if (demangled != nullptr) {
474  *stream_ << "\"" << dir << "/"
475  << name << "\" "
476  << (r ? m.matchString(strings[level], 2) : demangled) << " "
477  << m.matchString(strings[level], 1) << "\n";
478  free(demangled);
479  } else {
480  *stream_ << "Skipping "<< dir << "/" << name
481  << " with stack size " << size << "\n";
482  }
483 
484  /* In this case print the full stack trace, up to main or to the
485  * maximum stack size, i.e. 10. */
486  if (verbose_ > 4 || demangled == nullptr)
487  {
488  size_t i;
489  m.reset();
490 
491  for (i = 0; i < size; ++i)
492  if (s_rxtrace.match(strings[i], 0, 0, &m))
493  {
494  char * demangled = abi::__cxa_demangle(m.matchString(strings[i], 2).c_str(), nullptr, nullptr, &r);
495  *stream_ << "\t\t" << i << "/" << size << " "
496  << (r ? m.matchString(strings[i], 2) : demangled) << " "
497  << m.matchString(strings[i], 1) << std::endl;
498  free (demangled);
499  }
500  }
501  free (strings);
502 }
503 
508 void
509 DQMStore::setVerbose(unsigned /* level */)
510 { return; }
511 
516 const std::string &
518 { return pwd_; }
519 
521 void
523 { setCurrentFolder(""); }
524 
526 void
527 DQMStore::cd(const std::string &subdir)
528 {
530  const std::string *cleaned = nullptr;
531  cleanTrailingSlashes(subdir, clean, cleaned);
532 
533  if (! dirExists(*cleaned))
534  raiseDQMError("DQMStore", "Cannot 'cd' into non-existent directory '%s'",
535  cleaned->c_str());
536 
537  setCurrentFolder(*cleaned);
538 }
539 
544 void
546 {
548  const std::string *cleaned = nullptr;
549  cleanTrailingSlashes(fullpath, clean, cleaned);
550  makeDirectory(*cleaned);
551  pwd_ = *cleaned;
552 }
553 
555 void
557 {
558  size_t pos = pwd_.rfind('/');
559  if (pos == std::string::npos)
560  setCurrentFolder("");
561  else
562  setCurrentFolder(pwd_.substr(0, pos));
563 }
564 
565 // -------------------------------------------------------------------
568 void
570 {
571  std::string prev;
572  std::string subdir;
574  prev.reserve(path.size());
575  subdir.reserve(path.size());
576  name.reserve(path.size());
577  size_t prevname = 0;
578  size_t slash = 0;
579 
580  while (true)
581  {
582  // Create this subdirectory component.
583  subdir.clear();
584  subdir.append(path, 0, slash);
585  name.clear();
586  name.append(subdir, prevname, std::string::npos);
587  if (! prev.empty() && findObject(prev, name))
588  raiseDQMError("DQMStore", "Attempt to create subdirectory '%s'"
589  " which already exists as a monitor element",
590  subdir.c_str());
591 
592  if (! dirs_.count(subdir))
593  dirs_.insert(subdir);
594 
595  // Stop if we've reached the end (including possibly a trailing slash).
596  if (slash+1 >= path.size())
597  break;
598 
599  // Find the next slash, making sure we progress. If reach the end,
600  // process the last path component; the next loop round will terminate.
601  prevname = slash ? slash+1 : slash;
602  prev = subdir;
603  if ((slash = path.find('/', ++slash)) == std::string::npos)
604  slash = path.size();
605  }
606 }
607 
609 bool
611 { return dirs_.count(path) > 0; }
612 
616 template <class HISTO, class COLLATE>
618 DQMStore::book_(const std::string &dir, const std::string &name,
619  const char *context, int kind,
620  HISTO *h, COLLATE collate)
621 {
622  assert(name.find('/') == std::string::npos);
623  if (verbose_ > 3)
624  print_trace(dir, name);
626  mergePath(path, dir, name);
627 
628  // Put us in charge of h.
629  h->SetDirectory(nullptr);
630 
631  // Check if the request monitor element already exists.
632  MonitorElement *me = findObject(dir, name, run_, 0, moduleId_);
633  if (me)
634  {
635  if (collateHistograms_)
636  {
637  collate(me, h, verbose_);
638  delete h;
639  return me;
640  }
641  else
642  {
643  if (verbose_ > 1)
644  std::cout << "DQMStore: "
645  << context << ": monitor element '"
646  << path << "' already exists, collating" << std::endl;
647  me->Reset();
648  collate(me, h, verbose_);
649  delete h;
650  return me;
651  }
652  }
653  else
654  {
655  // Create and initialise core object.
656  assert(dirs_.count(dir));
657  MonitorElement proto(&*dirs_.find(dir), name, run_, moduleId_);
658  me = const_cast<MonitorElement &>(*data_.insert(std::move(proto)).first)
660 
661  // Initialise quality test information.
662  for (auto const& q : qtestspecs_)
663  {
664  if (q.first->match(path))
665  me->addQReport(q.second);
666  }
667 
668  // If we just booked a (plain) MonitorElement, and there is a reference
669  // MonitorElement with the same name, link the two together.
670  // The other direction is handled by the extract method.
671  std::string refdir;
672  refdir.reserve(s_referenceDirName.size() + dir.size() + 1);
673  refdir += s_referenceDirName;
674  refdir += '/';
675  refdir += dir;
676  MonitorElement* referenceME = findObject(refdir, name);
677  if (referenceME) {
678  // We have booked a new MonitorElement with a specific dir and name.
679  // Then, if we can find the corresponding MonitorElement in the reference
680  // dir we assign the object_ of the reference MonitorElement to the
681  // reference_ property of our new MonitorElement.
682  me->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
683  me->reference_ = referenceME->object_;
684  }
685 
686  // Return the monitor element.
687  return me;
688  }
689 }
690 
693  const std::string &name,
694  const char *context)
695 {
696  assert(name.find('/') == std::string::npos);
697  if (verbose_ > 3)
698  print_trace(dir, name);
699 
700  // Check if the request monitor element already exists.
701  if (MonitorElement *me = findObject(dir, name, run_, 0, moduleId_))
702  {
703  if (verbose_ > 1)
704  {
706  mergePath(path, dir, name);
707 
708  std::cout << "DQMStore: "
709  << context << ": monitor element '"
710  << path << "' already exists, resetting" << std::endl;
711  }
712  me->Reset();
713  return me;
714  }
715  else
716  {
717  // Create it and return for initialisation.
718  assert(dirs_.count(dir));
719  MonitorElement proto(&*dirs_.find(dir), name, run_, moduleId_);
720  return &const_cast<MonitorElement &>(*data_.insert(std::move(proto)).first);
721  }
722 }
723 
724 // -------------------------------------------------------------------
728 {
729  if (collateHistograms_)
730  {
731  if (MonitorElement *me = findObject(dir, name, run_, 0, moduleId_))
732  {
733  me->Fill(0);
734  return me;
735  }
736  }
737 
738  return book_(dir, name, "bookInt")
740 }
741 
744 DQMStore::bookInt(const char *name)
745 { return bookInt_(pwd_, name); }
746 
750 {
751  return bookInt_(pwd_, name);
752 }
753 
754 // -------------------------------------------------------------------
758 {
759  if (collateHistograms_)
760  {
761  if (MonitorElement *me = findObject(dir, name, run_, 0, moduleId_))
762  {
763  me->Fill(0.);
764  return me;
765  }
766  }
767 
768  return book_(dir, name, "bookFloat")
770 }
771 
774 DQMStore::bookFloat(const char *name)
775 { return bookFloat_(pwd_, name); }
776 
780 {
781  return bookFloat_(pwd_, name);
782 }
783 
784 // -------------------------------------------------------------------
788  const std::string &name,
789  const std::string &value)
790 {
791  if (collateHistograms_)
792  {
793  if (MonitorElement *me = findObject(dir, name, run_, 0, moduleId_))
794  return me;
795  }
796 
797  return book_(dir, name, "bookString")
799 }
800 
803 DQMStore::bookString(const char *name, const char *value)
804 { return bookString_(pwd_, name, value); }
805 
809 {
810  return bookString_(pwd_, name, value);
811 }
812 
813 // -------------------------------------------------------------------
816 DQMStore::book1D_(const std::string &dir, const std::string &name, TH1F *h)
817 {
818  return book_(dir, name, "book1D", MonitorElement::DQM_KIND_TH1F, h, collate1D);
819 }
820 
823 DQMStore::book1S_(const std::string &dir, const std::string &name, TH1S *h)
824 {
825  return book_(dir, name, "book1S", MonitorElement::DQM_KIND_TH1S, h, collate1S);
826 }
827 
830 DQMStore::book1DD_(const std::string &dir, const std::string &name, TH1D *h)
831 {
832  return book_(dir, name, "book1DD", MonitorElement::DQM_KIND_TH1D, h, collate1DD);
833 }
834 
837 DQMStore::book1D(const char *name, const char *title,
838  int nchX, double lowX, double highX)
839 {
840  return book1D_(pwd_, name, new TH1F(name, title, nchX, lowX, highX));
841 }
842 
846  int nchX, double lowX, double highX)
847 {
848  return book1D_(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, lowX, highX));
849 }
850 
853 DQMStore::book1S(const char *name, const char *title,
854  int nchX, double lowX, double highX)
855 {
856  return book1S_(pwd_, name, new TH1S(name, title, nchX, lowX, highX));
857 }
858 
862  int nchX, double lowX, double highX)
863 {
864  return book1S_(pwd_, name, new TH1S(name.c_str(), title.c_str(), nchX, lowX, highX));
865 }
866 
869 DQMStore::book1DD(const char *name, const char *title,
870  int nchX, double lowX, double highX)
871 {
872  return book1DD_(pwd_, name, new TH1D(name, title, nchX, lowX, highX));
873 }
874 
878  int nchX, double lowX, double highX)
879 {
880  return book1DD_(pwd_, name, new TH1D(name.c_str(), title.c_str(), nchX, lowX, highX));
881 }
882 
885 DQMStore::book1D(const char *name, const char *title,
886  int nchX, const float *xbinsize)
887 {
888  return book1D_(pwd_, name, new TH1F(name, title, nchX, xbinsize));
889 }
890 
894  int nchX, const float *xbinsize)
895 {
896  return book1D_(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, xbinsize));
897 }
898 
901 DQMStore::book1D(const char *name, TH1F *source)
902 {
903  return book1D_(pwd_, name, static_cast<TH1F *>(source->Clone(name)));
904 }
905 
909 {
910  return book1D_(pwd_, name, static_cast<TH1F *>(source->Clone(name.c_str())));
911 }
912 
915 DQMStore::book1S(const char *name, TH1S *source)
916 {
917  return book1S_(pwd_, name, static_cast<TH1S *>(source->Clone(name)));
918 }
919 
923 {
924  return book1S_(pwd_, name, static_cast<TH1S *>(source->Clone(name.c_str())));
925 }
926 
929 DQMStore::book1DD(const char *name, TH1D *source)
930 {
931  return book1DD_(pwd_, name, static_cast<TH1D *>(source->Clone(name)));
932 }
933 
937 {
938  return book1DD_(pwd_, name, static_cast<TH1D *>(source->Clone(name.c_str())));
939 }
940 
941 // -------------------------------------------------------------------
944 DQMStore::book2D_(const std::string &dir, const std::string &name, TH2F *h)
945 {
946  return book_(dir, name, "book2D", MonitorElement::DQM_KIND_TH2F, h, collate2D);
947 }
948 
951 DQMStore::book2S_(const std::string &dir, const std::string &name, TH2S *h)
952 {
953  return book_(dir, name, "book2S", MonitorElement::DQM_KIND_TH2S, h, collate2S);
954 }
955 
958 DQMStore::book2DD_(const std::string &dir, const std::string &name, TH2D *h)
959 {
960  return book_(dir, name, "book2DD", MonitorElement::DQM_KIND_TH2D, h, collate2DD);
961 }
962 
965 DQMStore::book2D(const char *name, const char *title,
966  int nchX, double lowX, double highX,
967  int nchY, double lowY, double highY)
968 {
969  return book2D_(pwd_, name, new TH2F(name, title,
970  nchX, lowX, highX,
971  nchY, lowY, highY));
972 }
973 
977  int nchX, double lowX, double highX,
978  int nchY, double lowY, double highY)
979 {
980  return book2D_(pwd_, name, new TH2F(name.c_str(), title.c_str(),
981  nchX, lowX, highX,
982  nchY, lowY, highY));
983 }
984 
987 DQMStore::book2S(const char *name, const char *title,
988  int nchX, double lowX, double highX,
989  int nchY, double lowY, double highY)
990 {
991  return book2S_(pwd_, name, new TH2S(name, title,
992  nchX, lowX, highX,
993  nchY, lowY, highY));
994 }
995 
999  int nchX, double lowX, double highX,
1000  int nchY, double lowY, double highY)
1001 {
1002  return book2S_(pwd_, name, new TH2S(name.c_str(), title.c_str(),
1003  nchX, lowX, highX,
1004  nchY, lowY, highY));
1005 }
1006 
1009 DQMStore::book2DD(const char *name, const char *title,
1010  int nchX, double lowX, double highX,
1011  int nchY, double lowY, double highY)
1012 {
1013  return book2DD_(pwd_, name, new TH2D(name, title,
1014  nchX, lowX, highX,
1015  nchY, lowY, highY));
1016 }
1017 
1021  int nchX, double lowX, double highX,
1022  int nchY, double lowY, double highY)
1023 {
1024  return book2DD_(pwd_, name, new TH2D(name.c_str(), title.c_str(),
1025  nchX, lowX, highX,
1026  nchY, lowY, highY));
1027 }
1028 
1031 DQMStore::book2D(const char *name, const char *title,
1032  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1033 {
1034  return book2D_(pwd_, name, new TH2F(name, title,
1035  nchX, xbinsize, nchY, ybinsize));
1036 }
1037 
1041  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1042 {
1043  return book2D_(pwd_, name, new TH2F(name.c_str(), title.c_str(),
1044  nchX, xbinsize, nchY, ybinsize));
1045 }
1046 
1049 DQMStore::book2S(const char *name, const char *title,
1050  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1051 {
1052 
1053  return book2S_(pwd_, name, new TH2S(name, title,
1054  nchX, xbinsize, nchY, ybinsize));
1055 }
1056 
1060  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1061 {
1062  return book2S_(pwd_, name, new TH2S(name.c_str(), title.c_str(),
1063  nchX, xbinsize, nchY, ybinsize));
1064 }
1065 
1068 DQMStore::book2D(const char *name, TH2F *source)
1069 {
1070  return book2D_(pwd_, name, static_cast<TH2F *>(source->Clone(name)));
1071 }
1072 
1076 {
1077  return book2D_(pwd_, name, static_cast<TH2F *>(source->Clone(name.c_str())));
1078 }
1079 
1082 DQMStore::book2S(const char *name, TH2S *source)
1083 {
1084  return book2S_(pwd_, name, static_cast<TH2S *>(source->Clone(name)));
1085 }
1086 
1090 {
1091  return book2S_(pwd_, name, static_cast<TH2S *>(source->Clone(name.c_str())));
1092 }
1093 
1096 DQMStore::book2DD(const char *name, TH2D *source)
1097 {
1098  return book2DD_(pwd_, name, static_cast<TH2D *>(source->Clone(name)));
1099 }
1100 
1104 {
1105  return book2DD_(pwd_, name, static_cast<TH2D *>(source->Clone(name.c_str())));
1106 }
1107 
1108 // -------------------------------------------------------------------
1111 DQMStore::book3D_(const std::string &dir, const std::string &name, TH3F *h)
1112 {
1113  return book_(dir, name, "book3D", MonitorElement::DQM_KIND_TH3F, h, collate3D);
1114 }
1115 
1118 DQMStore::book3D(const char *name, const char *title,
1119  int nchX, double lowX, double highX,
1120  int nchY, double lowY, double highY,
1121  int nchZ, double lowZ, double highZ)
1122 {
1123  return book3D_(pwd_, name, new TH3F(name, title,
1124  nchX, lowX, highX,
1125  nchY, lowY, highY,
1126  nchZ, lowZ, highZ));
1127 }
1128 
1132  int nchX, double lowX, double highX,
1133  int nchY, double lowY, double highY,
1134  int nchZ, double lowZ, double highZ)
1135 {
1136  return book3D_(pwd_, name, new TH3F(name.c_str(), title.c_str(),
1137  nchX, lowX, highX,
1138  nchY, lowY, highY,
1139  nchZ, lowZ, highZ));
1140 }
1141 
1144 DQMStore::book3D(const char *name, TH3F *source)
1145 {
1146  return book3D_(pwd_, name, static_cast<TH3F *>(source->Clone(name)));
1147 }
1148 
1152 {
1153  return book3D_(pwd_, name, static_cast<TH3F *>(source->Clone(name.c_str())));
1154 }
1155 
1156 // -------------------------------------------------------------------
1159 DQMStore::bookProfile_(const std::string &dir, const std::string &name, TProfile *h)
1160 {
1161  return book_(dir, name, "bookProfile",
1163  h, collateProfile);
1164 }
1165 
1170 DQMStore::bookProfile(const char *name, const char *title,
1171  int nchX, double lowX, double highX,
1172  int /* nchY */, double lowY, double highY,
1173  const char *option /* = "s" */)
1174 {
1175  return bookProfile_(pwd_, name, new TProfile(name, title,
1176  nchX, lowX, highX,
1177  lowY, highY,
1178  option));
1179 }
1180 
1186  int nchX, double lowX, double highX,
1187  int /* nchY */, double lowY, double highY,
1188  const char *option /* = "s" */)
1189 {
1190  return bookProfile_(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1191  nchX, lowX, highX,
1192  lowY, highY,
1193  option));
1194 }
1195 
1200 DQMStore::bookProfile(const char *name, const char *title,
1201  int nchX, double lowX, double highX,
1202  double lowY, double highY,
1203  const char *option /* = "s" */)
1204 {
1205  return bookProfile_(pwd_, name, new TProfile(name, title,
1206  nchX, lowX, highX,
1207  lowY, highY,
1208  option));
1209 }
1210 
1216  int nchX, double lowX, double highX,
1217  double lowY, double highY,
1218  const char *option /* = "s" */)
1219 {
1220  return bookProfile_(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1221  nchX, lowX, highX,
1222  lowY, highY,
1223  option));
1224 }
1225 
1230 DQMStore::bookProfile(const char *name, const char *title,
1231  int nchX, const double *xbinsize,
1232  int /* nchY */, double lowY, double highY,
1233  const char *option /* = "s" */)
1234 {
1235  return bookProfile_(pwd_, name, new TProfile(name, title,
1236  nchX, xbinsize,
1237  lowY, highY,
1238  option));
1239 }
1240 
1246  int nchX, const double *xbinsize,
1247  int /* nchY */, double lowY, double highY,
1248  const char *option /* = "s" */)
1249 {
1250  return bookProfile_(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1251  nchX, xbinsize,
1252  lowY, highY,
1253  option));
1254 }
1255 
1260 DQMStore::bookProfile(const char *name, const char *title,
1261  int nchX, const double *xbinsize,
1262  double lowY, double highY,
1263  const char *option /* = "s" */)
1264 {
1265  return bookProfile_(pwd_, name, new TProfile(name, title,
1266  nchX, xbinsize,
1267  lowY, highY,
1268  option));
1269 }
1270 
1276  int nchX, const double *xbinsize,
1277  double lowY, double highY,
1278  const char *option /* = "s" */)
1279 {
1280  return bookProfile_(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1281  nchX, xbinsize,
1282  lowY, highY,
1283  option));
1284 }
1285 
1288 DQMStore::bookProfile(const char *name, TProfile *source)
1289 {
1290  return bookProfile_(pwd_, name, static_cast<TProfile *>(source->Clone(name)));
1291 }
1292 
1296 {
1297  return bookProfile_(pwd_, name, static_cast<TProfile *>(source->Clone(name.c_str())));
1298 }
1299 
1300 // -------------------------------------------------------------------
1303 DQMStore::bookProfile2D_(const std::string &dir, const std::string &name, TProfile2D *h)
1304 {
1305  return book_(dir, name, "bookProfile2D",
1307  h, collateProfile2D);
1308 }
1309 
1314 DQMStore::bookProfile2D(const char *name, const char *title,
1315  int nchX, double lowX, double highX,
1316  int nchY, double lowY, double highY,
1317  int /* nchZ */, double lowZ, double highZ,
1318  const char *option /* = "s" */)
1319 {
1320  return bookProfile2D_(pwd_, name, new TProfile2D(name, title,
1321  nchX, lowX, highX,
1322  nchY, lowY, highY,
1323  lowZ, highZ,
1324  option));
1325 }
1326 
1332  int nchX, double lowX, double highX,
1333  int nchY, double lowY, double highY,
1334  int /* nchZ */, double lowZ, double highZ,
1335  const char *option /* = "s" */)
1336 {
1337  return bookProfile2D_(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1338  nchX, lowX, highX,
1339  nchY, lowY, highY,
1340  lowZ, highZ,
1341  option));
1342 }
1343 
1348 DQMStore::bookProfile2D(const char *name, const char *title,
1349  int nchX, double lowX, double highX,
1350  int nchY, double lowY, double highY,
1351  double lowZ, double highZ,
1352  const char *option /* = "s" */)
1353 {
1354  return bookProfile2D_(pwd_, name, new TProfile2D(name, title,
1355  nchX, lowX, highX,
1356  nchY, lowY, highY,
1357  lowZ, highZ,
1358  option));
1359 }
1360 
1366  int nchX, double lowX, double highX,
1367  int nchY, double lowY, double highY,
1368  double lowZ, double highZ,
1369  const char *option /* = "s" */)
1370 {
1371  return bookProfile2D_(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1372  nchX, lowX, highX,
1373  nchY, lowY, highY,
1374  lowZ, highZ,
1375  option));
1376 }
1377 
1380 DQMStore::bookProfile2D(const char *name, TProfile2D *source)
1381 {
1382  return bookProfile2D_(pwd_, name, static_cast<TProfile2D *>(source->Clone(name)));
1383 }
1384 
1387 DQMStore::bookProfile2D(const std::string &name, TProfile2D *source)
1388 {
1389  return bookProfile2D_(pwd_, name, static_cast<TProfile2D *>(source->Clone(name.c_str())));
1390 }
1391 
1395 bool
1397 {
1398  if (me->getTH1()->GetNbinsX() != h->GetNbinsX()
1399  || me->getTH1()->GetNbinsY() != h->GetNbinsY()
1400  || me->getTH1()->GetNbinsZ() != h->GetNbinsZ()
1401  || me->getTH1()->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin()
1402  || me->getTH1()->GetYaxis()->GetXmin() != h->GetYaxis()->GetXmin()
1403  || me->getTH1()->GetZaxis()->GetXmin() != h->GetZaxis()->GetXmin()
1404  || me->getTH1()->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax()
1405  || me->getTH1()->GetYaxis()->GetXmax() != h->GetYaxis()->GetXmax()
1406  || me->getTH1()->GetZaxis()->GetXmax() != h->GetZaxis()->GetXmax()
1407  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetXaxis(),(TAxis*)h->GetXaxis())
1408  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetYaxis(),(TAxis*)h->GetYaxis())
1409  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetZaxis(),(TAxis*)h->GetZaxis()) )
1410  {
1411  if(verbose > 0)
1412  std::cout << "*** DQMStore: WARNING:"
1413  << "checkBinningMatches: different binning - cannot add object '"
1414  << h->GetName() << "' of type "
1415  << h->IsA()->GetName() << " to existing ME: '"
1416  << me->getFullname() << "'\n";
1417  return false;
1418  }
1419  return true;
1420 }
1421 
1422 void
1424 {
1425  if (checkBinningMatches(me,h,verbose))
1426  me->getTH1F()->Add(h);
1427 }
1428 
1429 void
1431 {
1432  if (checkBinningMatches(me,h,verbose))
1433  me->getTH1S()->Add(h);
1434 }
1435 
1436 void
1438 {
1439  if (checkBinningMatches(me,h,verbose))
1440  me->getTH1D()->Add(h);
1441 }
1442 
1443 void
1445 {
1446  if (checkBinningMatches(me,h,verbose))
1447  me->getTH2F()->Add(h);
1448 }
1449 
1450 void
1452 {
1453  if (checkBinningMatches(me,h,verbose))
1454  me->getTH2S()->Add(h);
1455 }
1456 
1457 void
1459 {
1460  if (checkBinningMatches(me,h,verbose))
1461  me->getTH2D()->Add(h);
1462 }
1463 
1464 void
1466 {
1467  if (checkBinningMatches(me,h,verbose))
1468  me->getTH3F()->Add(h);
1469 }
1470 
1471 void
1473 {
1474  if (checkBinningMatches(me,h,verbose))
1475  {
1476  TProfile *meh = me->getTProfile();
1477  me->addProfiles(h, meh, meh, 1, 1);
1478  }
1479 }
1480 
1481 void
1483 {
1484  if (checkBinningMatches(me,h,verbose))
1485  {
1486  TProfile2D *meh = me->getTProfile2D();
1487  me->addProfiles(h, meh, meh, 1, 1);
1488  }
1489 }
1490 
1495 void
1496 DQMStore::tag(MonitorElement *me, unsigned int myTag)
1497 {
1498  if (! myTag)
1499  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1500  " with a zero tag", me->getFullname().c_str());
1501  if ((me->data_.flags & DQMNet::DQM_PROP_TAGGED) && myTag != me->data_.tag)
1502  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1503  " twice with multiple tags", me->getFullname().c_str());
1504 
1505  me->data_.tag = myTag;
1507 }
1508 
1510 void
1511 DQMStore::tag(const std::string &path, unsigned int myTag)
1512 {
1513  std::string dir;
1514  std::string name;
1515  splitPath(dir, name, path);
1516 
1517  if (MonitorElement *me = findObject(dir, name))
1518  tag(me, myTag);
1519  else
1520  raiseDQMError("DQMStore", "Attempt to tag non-existent monitor element"
1521  " '%s' with tag %u", path.c_str(), myTag);
1522 
1523 }
1524 
1526 void
1527 DQMStore::tagContents(const std::string &path, unsigned int myTag)
1528 {
1529  MonitorElement proto(&path, std::string());
1530  auto e = data_.end();
1531  auto i = data_.lower_bound(proto);
1532  for ( ; i != e && path == *i->data_.dirname; ++i)
1533  tag(const_cast<MonitorElement *>(&*i), myTag);
1534 }
1535 
1538 void
1539 DQMStore::tagAllContents(const std::string &path, unsigned int myTag)
1540 {
1542  const std::string *cleaned = nullptr;
1543  cleanTrailingSlashes(path, clean, cleaned);
1544  MonitorElement proto(cleaned, std::string());
1545 
1546  // FIXME: WILDCARDS? Old one supported them, but nobody seemed to use them.
1547  auto e = data_.end();
1548  auto i = data_.lower_bound(proto);
1549  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
1550  {
1551  tag(const_cast<MonitorElement *>(&*i), myTag);
1552  ++i;
1553  }
1554 }
1555 
1560 std::vector<std::string>
1562 {
1563  std::vector<std::string> result;
1564  auto e = dirs_.end();
1565  auto i = dirs_.find(pwd_);
1566 
1567  // If we didn't find current directory, the tree is empty, so quit.
1568  if (i == e)
1569  return result;
1570 
1571  // Skip the current directory and then start looking for immediate
1572  // subdirectories in the dirs_ list. Stop when we are no longer in
1573  // (direct or indirect) subdirectories of pwd_. Note that we don't
1574  // "know" which order the set will sort A/B, A/B/C and A/D.
1575  while (++i != e && isSubdirectory(pwd_, *i))
1576  if (i->find('/', pwd_.size()+1) == std::string::npos)
1577  result.push_back(*i);
1578 
1579  return result;
1580 }
1581 
1583 std::vector<std::string>
1585 {
1586  MonitorElement proto(&pwd_, std::string());
1587  std::vector<std::string> result;
1588  auto e = data_.end();
1589  auto i = data_.lower_bound(proto);
1590  for ( ; i != e && isSubdirectory(pwd_, *i->data_.dirname); ++i)
1591  if (pwd_ == *i->data_.dirname)
1592  result.push_back(i->getName());
1593 
1594  return result;
1595 }
1596 
1599 bool
1601 {
1602  MonitorElement proto(&path, std::string());
1603  auto e = data_.end();
1604  auto i = data_.lower_bound(proto);
1605  return (i != e && isSubdirectory(path, *i->data_.dirname));
1606 }
1607 
1610 DQMStore::get(const std::string &path) const
1611 {
1612  std::string dir;
1613  std::string name;
1614  splitPath(dir, name, path);
1615  MonitorElement proto(&dir, name);
1616  auto mepos = data_.find(proto);
1617  return (mepos == data_.end() ? nullptr
1618  : const_cast<MonitorElement *>(&*mepos));
1619 }
1620 
1622 std::vector<MonitorElement *>
1623 DQMStore::get(unsigned int tag) const
1624 {
1625  // FIXME: Use reverse map [tag -> path] / [tag -> dir]?
1626  std::vector<MonitorElement *> result;
1627  for (auto const & me : data_)
1628  {
1629  if ((me.data_.flags & DQMNet::DQM_PROP_TAGGED) && me.data_.tag == tag)
1630  result.push_back(const_cast<MonitorElement *>(&me));
1631  }
1632  return result;
1633 }
1634 
1637 std::vector<MonitorElement *>
1639 {
1641  const std::string *cleaned = nullptr;
1642  cleanTrailingSlashes(path, clean, cleaned);
1643  MonitorElement proto(cleaned, std::string());
1644 
1645  std::vector<MonitorElement *> result;
1646  auto e = data_.end();
1647  auto i = data_.lower_bound(proto);
1648  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1649  if (*cleaned == *i->data_.dirname)
1650  result.push_back(const_cast<MonitorElement *>(&*i));
1651 
1652  return result;
1653 }
1654 
1656 std::vector<MonitorElement *>
1657 DQMStore::getContents(const std::string &path, unsigned int tag) const
1658 {
1660  const std::string *cleaned = nullptr;
1661  cleanTrailingSlashes(path, clean, cleaned);
1662  MonitorElement proto(cleaned, std::string());
1663 
1664  std::vector<MonitorElement *> result;
1665  auto e = data_.end();
1666  auto i = data_.lower_bound(proto);
1667  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1668  if (*cleaned == *i->data_.dirname
1669  && (i->data_.flags & DQMNet::DQM_PROP_TAGGED)
1670  && i->data_.tag == tag)
1671  result.push_back(const_cast<MonitorElement *>(&*i));
1672 
1673  return result;
1674 }
1675 
1680 void
1681 DQMStore::getContents(std::vector<std::string> &into, bool showContents /* = true */) const
1682 {
1683  into.clear();
1684  into.reserve(dirs_.size());
1685 
1686  auto me = data_.end();
1687  for (auto const& dir : dirs_)
1688  {
1689  MonitorElement proto(&dir, std::string());
1690  auto mi = data_.lower_bound(proto);
1691  auto m = mi;
1692  size_t sz = dir.size() + 2;
1693  size_t nfound = 0;
1694  for ( ; m != me && isSubdirectory(dir, *m->data_.dirname); ++m)
1695  if (dir == *m->data_.dirname)
1696  {
1697  sz += m->data_.objname.size() + 1;
1698  ++nfound;
1699  }
1700 
1701  if (! nfound)
1702  continue;
1703 
1704  auto istr
1705  = into.insert(into.end(), std::string());
1706 
1707  if (showContents)
1708  {
1709  istr->reserve(sz);
1710 
1711  *istr += dir;
1712  *istr += ':';
1713  for (sz = 0; mi != m; ++mi)
1714  {
1715  if (dir != *mi->data_.dirname)
1716  continue;
1717 
1718  if (sz > 0)
1719  *istr += ',';
1720 
1721  *istr += mi->data_.objname;
1722  ++sz;
1723  }
1724  }
1725  else
1726  {
1727  istr->reserve(dir.size() + 2);
1728  *istr += dir;
1729  *istr += ':';
1730  }
1731  }
1732 }
1733 
1738  const std::string &name,
1739  const uint32_t run /* = 0 */,
1740  const uint32_t lumi /* = 0 */,
1741  const uint32_t moduleId /* = 0 */) const
1742 {
1743  if (dir.find_first_not_of(s_safe) != std::string::npos)
1744  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1745  " unacceptable characters", dir.c_str());
1746  if (name.find_first_not_of(s_safe) != std::string::npos)
1747  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1748  " unacceptable characters", name.c_str());
1749 
1750  MonitorElement proto;
1751  proto.data_.dirname = &dir;
1752  proto.data_.objname = name;
1753  proto.data_.run = run;
1754  proto.data_.lumi = lumi;
1755  proto.data_.moduleId = moduleId;
1756 
1757  auto mepos = data_.find(proto);
1758  return (mepos == data_.end() ? nullptr
1759  : const_cast<MonitorElement *>(&*mepos));
1760 }
1761 
1764 std::vector<MonitorElement*>
1766  uint32_t run /* = 0 */,
1767  uint32_t lumi /* = 0 */) const
1768 {
1770  const std::string *cleaned = nullptr;
1771  cleanTrailingSlashes(path, clean, cleaned);
1772  MonitorElement proto(cleaned, std::string(), run, 0);
1773  proto.setLumi(lumi);
1774 
1775  std::vector<MonitorElement *> result;
1776  auto e = data_.end();
1777  auto i = data_.lower_bound(proto);
1778  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i) {
1779  if (run != 0) {
1780  if (i->data_.run > run // TODO[rovere]: pleonastic? first we encounter local ME of the same run ...
1781  || i->data_.moduleId != 0)
1782  break;
1783  }
1784  if (lumi != 0) {
1785  if (i->data_.lumi > lumi
1786  || i->data_.moduleId != 0)
1787  break;
1788  }
1789  if (run != 0 or lumi !=0) {
1790  assert(i->data_.moduleId == 0);
1791  }
1792  result.push_back(const_cast<MonitorElement *>(&*i));
1793  }
1794 
1795  if (enableMultiThread_)
1796  {
1797  //save legacy modules when running MT
1798  i = data_.begin();
1799  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i) {
1800  if (i->data_.run != 0 or i->data_.moduleId != 0)
1801  break;
1802  result.push_back(const_cast<MonitorElement *>(&*i));
1803  }
1804  }
1805 
1806  return result;
1807 }
1808 
1811 std::vector<MonitorElement*>
1812 DQMStore::getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType /* = Wildcard */) const
1813 {
1814  lat::Regexp rx;
1815  try
1816  {
1817  rx = lat::Regexp(pattern, 0, syntaxType);
1818  rx.study();
1819  }
1820  catch (lat::Error &e)
1821  {
1822  raiseDQMError("DQMStore", "Invalid regular expression '%s': %s",
1823  pattern.c_str(), e.explain().c_str());
1824  }
1825 
1826  std::string path;
1827  std::vector<MonitorElement *> result;
1828  for (auto const& me : data_)
1829  {
1830  path.clear();
1831  mergePath(path, *me.data_.dirname, me.data_.objname);
1832  if (rx.match(path))
1833  result.push_back(const_cast<MonitorElement *>(&me));
1834  }
1835 
1836  return result;
1837 }
1838 
1842 
1845 void
1847 {
1848  for (auto const& m : data_)
1849  {
1850  auto &me = const_cast<MonitorElement &>(m);
1851  if (me.wasUpdated())
1852  {
1853  if (me.resetMe())
1854  me.Reset();
1855  me.resetUpdate();
1856  }
1857  }
1858 
1859  reset_ = true;
1860 }
1861 
1865 
1867 void
1869 {
1870  for (auto const& m : data_)
1871  {
1872  if (forceResetOnBeginLumi_ && (m.getLumiFlag() == false))
1873  continue;
1874  auto &me = const_cast<MonitorElement &>(m);
1875  me.Reset();
1876  me.resetUpdate();
1877  }
1878 
1879  reset_ = true;
1880 }
1881 
1882 
1886 
1890 void
1892 {
1893  static const std::string null_str("");
1894 
1895  auto const& lumiblock = gc.luminosityBlockID();
1896  uint32_t run = lumiblock.run();
1897 
1898  // find the range of non-legacy global MEs for the current run:
1899  // run != 0, lumi == 0 (implicit), stream id == 0, module id == 0
1900  const MonitorElement begin(&null_str, null_str, run, 0);
1901  const MonitorElement end(&null_str, null_str, run, 1);
1902  auto i = data_.lower_bound(begin);
1903  const auto e = data_.lower_bound(end);
1904  while (i != e) {
1905  auto& me = const_cast<MonitorElement&>(*i++);
1906  // skip per-run MEs
1907  if (not LSbasedMode_ and not me.getLumiFlag())
1908  continue;
1909  me.Reset();
1910  me.resetUpdate();
1911  }
1912 }
1913 
1917 
1924 void
1925 DQMStore::cloneLumiHistograms(uint32_t run, uint32_t lumi, uint32_t moduleId)
1926 {
1927  if (verbose_ > 1) {
1928  std::cout << "DQMStore::cloneLumiHistograms - Preparing lumi histograms for run: "
1929  << run << ", lumi: " << lumi << ", module: " << moduleId << std::endl;
1930  }
1931 
1932  // acquire the global lock since this accesses the undelying data structure
1933  std::lock_guard<std::mutex> guard(book_mutex_);
1934 
1935  // MEs are sorted by (run, lumi, stream id, module id, directory, name)
1936  // lumi deafults to 0
1937  // stream id is always 0
1938  std::string null_str("");
1939  auto i = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId));
1940  auto e = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId + 1));
1941  for (; i != e; ++i) {
1942  // handle only lumisection-based histograms
1943  if (not LSbasedMode_ and not i->getLumiFlag())
1944  continue;
1945 
1946  // clone the lumisection-based histograms
1948  clone.globalize();
1949  clone.setLumi(lumi);
1950  clone.markToDelete();
1951  data_.insert(std::move(clone));
1952 
1953  // reset the ME for the next lumisection
1954  const_cast<MonitorElement*>(&*i)->Reset();
1955  }
1956 }
1957 
1961 void
1962 DQMStore::cloneRunHistograms(uint32_t run, uint32_t moduleId)
1963 {
1964  if (verbose_ > 1) {
1965  std::cout << "DQMStore::cloneRunHistograms - Preparing run histograms for run: "
1966  << run << ", module: " << moduleId << std::endl;
1967  }
1968 
1969  // acquire the global lock since this accesses the undelying data structure
1970  std::lock_guard<std::mutex> guard(book_mutex_);
1971 
1972  // MEs are sorted by (run, lumi, stream id, module id, directory, name)
1973  // lumi deafults to 0
1974  // stream id is always 0
1975  std::string null_str("");
1976  auto i = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId));
1977  auto e = data_.lower_bound(MonitorElement(&null_str, null_str, run, moduleId + 1));
1978  for (; i != e; ++i) {
1979  // handle only non lumisection-based histograms
1980  if (LSbasedMode_ or i->getLumiFlag())
1981  continue;
1982 
1983  // clone the lumisection-based histograms
1985  clone.globalize();
1986  clone.markToDelete();
1987  data_.insert(std::move(clone));
1988 
1989  // reset the ME for the next lumisection
1990  const_cast<MonitorElement*>(&*i)->Reset();
1991  }
1992 }
1993 
1994 
1999 void
2001 {
2002  if (!enableMultiThread_)
2003  return;
2004 
2005  std::lock_guard<std::mutex> guard(book_mutex_);
2006 
2007  std::string null_str("");
2008  MonitorElement proto(&null_str, null_str, run, 0);
2009  proto.setLumi(lumi);
2010 
2011  auto e = data_.end();
2012  auto i = data_.lower_bound(proto);
2013 
2014  while (i != e) {
2015  if (i->data_.moduleId != 0)
2016  break;
2017  if (i->data_.lumi != lumi)
2018  break;
2019  if (i->data_.run != run)
2020  break;
2021  if (not i->markedToDelete()) {
2022  ++i;
2023  continue;
2024  }
2025 
2026  if (verbose_ > 1) {
2027  std::cout << "DQMStore::deleteUnusedLumiHistograms: deleted monitor element '"
2028  << *i->data_.dirname << "/" << i->data_.objname << "'"
2029  << "flags " << i->data_.flags << "\n";
2030  }
2031 
2032  i = data_.erase(i);
2033  }
2034 }
2035 
2041 bool
2042 DQMStore::extract(TObject *obj, const std::string &dir,
2043  bool overwrite, bool collateHistograms)
2044 {
2045  // NB: Profile histograms inherit from TH*D, checking order matters.
2046  MonitorElement *refcheck = nullptr;
2047  if (auto *h = dynamic_cast<TProfile *>(obj))
2048  {
2049  MonitorElement *me = findObject(dir, h->GetName());
2050  if (! me)
2051  me = bookProfile_(dir, h->GetName(), (TProfile *) h->Clone());
2052  else if (overwrite)
2053  me->copyFrom(h);
2054  else if (isCollateME(me) || collateHistograms)
2055  collateProfile(me, h, verbose_);
2056  refcheck = me;
2057  }
2058  else if (auto *h = dynamic_cast<TProfile2D *>(obj))
2059  {
2060  MonitorElement *me = findObject(dir, h->GetName());
2061  if (! me)
2062  me = bookProfile2D_(dir, h->GetName(), (TProfile2D *) h->Clone());
2063  else if (overwrite)
2064  me->copyFrom(h);
2065  else if (isCollateME(me) || collateHistograms)
2066  collateProfile2D(me, h, verbose_);
2067  refcheck = me;
2068  }
2069  else if (auto *h = dynamic_cast<TH1F *>(obj))
2070  {
2071  MonitorElement *me = findObject(dir, h->GetName());
2072  if (! me)
2073  me = book1D_(dir, h->GetName(), (TH1F *) h->Clone());
2074  else if (overwrite)
2075  me->copyFrom(h);
2076  else if (isCollateME(me) || collateHistograms)
2077  collate1D(me, h, verbose_);
2078  refcheck = me;
2079  }
2080  else if (auto *h = dynamic_cast<TH1S *>(obj))
2081  {
2082  MonitorElement *me = findObject(dir, h->GetName());
2083  if (! me)
2084  me = book1S_(dir, h->GetName(), (TH1S *) h->Clone());
2085  else if (overwrite)
2086  me->copyFrom(h);
2087  else if (isCollateME(me) || collateHistograms)
2088  collate1S(me, h, verbose_);
2089  refcheck = me;
2090  }
2091  else if (auto *h = dynamic_cast<TH1D *>(obj))
2092  {
2093  MonitorElement *me = findObject(dir, h->GetName());
2094  if (! me)
2095  me = book1DD_(dir, h->GetName(), (TH1D *) h->Clone());
2096  else if (overwrite)
2097  me->copyFrom(h);
2098  else if (isCollateME(me) || collateHistograms)
2099  collate1DD(me, h, verbose_);
2100  refcheck = me;
2101  }
2102  else if (auto *h = dynamic_cast<TH2F *>(obj))
2103  {
2104  MonitorElement *me = findObject(dir, h->GetName());
2105  if (! me)
2106  me = book2D_(dir, h->GetName(), (TH2F *) h->Clone());
2107  else if (overwrite)
2108  me->copyFrom(h);
2109  else if (isCollateME(me) || collateHistograms)
2110  collate2D(me, h, verbose_);
2111  refcheck = me;
2112  }
2113  else if (auto *h = dynamic_cast<TH2S *>(obj))
2114  {
2115  MonitorElement *me = findObject(dir, h->GetName());
2116  if (! me)
2117  me = book2S_(dir, h->GetName(), (TH2S *) h->Clone());
2118  else if (overwrite)
2119  me->copyFrom(h);
2120  else if (isCollateME(me) || collateHistograms)
2121  collate2S(me, h, verbose_);
2122  refcheck = me;
2123  }
2124  else if (auto *h = dynamic_cast<TH2D *>(obj))
2125  {
2126  MonitorElement *me = findObject(dir, h->GetName());
2127  if (! me)
2128  me = book2DD_(dir, h->GetName(), (TH2D *) h->Clone());
2129  else if (overwrite)
2130  me->copyFrom(h);
2131  else if (isCollateME(me) || collateHistograms)
2132  collate2DD(me, h, verbose_);
2133  refcheck = me;
2134  }
2135  else if (auto *h = dynamic_cast<TH3F *>(obj))
2136  {
2137  MonitorElement *me = findObject(dir, h->GetName());
2138  if (! me)
2139  me = book3D_(dir, h->GetName(), (TH3F *) h->Clone());
2140  else if (overwrite)
2141  me->copyFrom(h);
2142  else if (isCollateME(me) || collateHistograms)
2143  collate3D(me, h, verbose_);
2144  refcheck = me;
2145  }
2146  else if (dynamic_cast<TObjString *>(obj))
2147  {
2148  lat::RegexpMatch m;
2149  if (! s_rxmeval.match(obj->GetName(), 0, 0, &m))
2150  {
2151  if (strstr(obj->GetName(), "CMSSW"))
2152  {
2153  if (verbose_)
2154  std::cout << "Input file version: " << obj->GetName() << std::endl;
2155  return true;
2156  }
2157  else if (strstr(obj->GetName(), "DQMPATCH"))
2158  {
2159  if (verbose_)
2160  std::cout << "DQM patch version: " << obj->GetName() << std::endl;
2161  return true;
2162  }
2163  else
2164  {
2165  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2166  << obj->GetName() << "' of type '"
2167  << obj->IsA()->GetName() << "'\n";
2168  return false;
2169  }
2170  }
2171 
2172  std::string label = m.matchString(obj->GetName(), 1);
2173  std::string kind = m.matchString(obj->GetName(), 2);
2174  std::string value = m.matchString(obj->GetName(), 3);
2175 
2176  if (kind == "i")
2177  {
2178  MonitorElement *me = findObject(dir, label);
2179  if (! me || overwrite)
2180  {
2181  if (! me) me = bookInt_(dir, label);
2182  me->Fill(atoll(value.c_str()));
2183  }
2184  }
2185  else if (kind == "f")
2186  {
2187  MonitorElement *me = findObject(dir, label);
2188  if (! me || overwrite)
2189  {
2190  if (! me) me = bookFloat_(dir, label);
2191  me->Fill(atof(value.c_str()));
2192  }
2193  }
2194  else if (kind == "s")
2195  {
2196  MonitorElement *me = findObject(dir, label);
2197  if (! me)
2198  me = bookString_(dir, label, value);
2199  else if (overwrite)
2200  me->Fill(value);
2201  }
2202  else if (kind == "e")
2203  {
2204  MonitorElement *me = findObject(dir, label);
2205  if (! me)
2206  {
2207  std::cout << "*** DQMStore: WARNING: no monitor element '"
2208  << label << "' in directory '"
2209  << dir << "' to be marked as efficiency plot.\n";
2210  return false;
2211  }
2212  me->setEfficiencyFlag();
2213  }
2214  else if (kind == "t")
2215  {
2216  MonitorElement *me = findObject(dir, label);
2217  if (! me)
2218  {
2219  std::cout << "*** DQMStore: WARNING: no monitor element '"
2220  << label << "' in directory '"
2221  << dir << "' for a tag\n";
2222  return false;
2223  }
2224  errno = 0;
2225  char *endp = nullptr;
2226  unsigned long val = strtoul(value.c_str(), &endp, 10);
2227  if ((val == 0 && errno) || *endp || val > ~uint32_t(0))
2228  {
2229  std::cout << "*** DQMStore: WARNING: cannot restore tag '"
2230  << value << "' for monitor element '"
2231  << label << "' in directory '"
2232  << dir << "' - invalid value\n";
2233  return false;
2234  }
2235  tag(me, val);
2236  }
2237  else if (kind == "qr")
2238  {
2239  // Handle qreports, but skip them while reading in references.
2240  if (! isSubdirectory(s_referenceDirName, dir))
2241  {
2242  size_t dot = label.find('.');
2243  if (dot == std::string::npos)
2244  {
2245  std::cout << "*** DQMStore: WARNING: quality report label in '" << label
2246  << "' is missing a '.' and cannot be extracted\n";
2247  return false;
2248  }
2249 
2250  std::string mename (label, 0, dot);
2251  std::string qrname (label, dot+1, std::string::npos);
2252 
2253  m.reset();
2254  DQMNet::QValue qv;
2255  if (s_rxmeqr1.match(value, 0, 0, &m))
2256  {
2257  qv.code = atoi(m.matchString(value, 1).c_str());
2258  qv.qtresult = strtod(m.matchString(value, 2).c_str(), nullptr);
2259  qv.message = m.matchString(value, 4);
2260  qv.qtname = qrname;
2261  qv.algorithm = m.matchString(value, 3);
2262  }
2263  else if (s_rxmeqr2.match(value, 0, 0, &m))
2264  {
2265  qv.code = atoi(m.matchString(value, 1).c_str());
2266  qv.qtresult = 0; // unavailable in old format
2267  qv.message = m.matchString(value, 2);
2268  qv.qtname = qrname;
2269  // qv.algorithm unavailable in old format
2270  }
2271  else
2272  {
2273  std::cout << "*** DQMStore: WARNING: quality test value '"
2274  << value << "' is incorrectly formatted\n";
2275  return false;
2276  }
2277 
2278  MonitorElement *me = findObject(dir, mename);
2279  if (! me)
2280  {
2281  std::cout << "*** DQMStore: WARNING: no monitor element '"
2282  << mename << "' in directory '"
2283  << dir << "' for quality test '"
2284  << label << "'\n";
2285  return false;
2286  }
2287 
2288  me->addQReport(qv, /* FIXME: getQTest(qv.qtname)? */ nullptr);
2289  }
2290  }
2291  else
2292  {
2293  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2294  << obj->GetName() << "' of type '"
2295  << obj->IsA()->GetName() << "'\n";
2296  return false;
2297  }
2298  }
2299  else if (auto *n = dynamic_cast<TNamed *>(obj))
2300  {
2301  // For old DQM data.
2302  std::string s;
2303  s.reserve(6 + strlen(n->GetTitle()) + 2*strlen(n->GetName()));
2304  s += '<'; s += n->GetName(); s += '>';
2305  s += n->GetTitle();
2306  s += '<'; s += '/'; s += n->GetName(); s += '>';
2307  TObjString os(s.c_str());
2308  return extract(&os, dir, overwrite, collateHistograms_);
2309  }
2310  else
2311  {
2312  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2313  << obj->GetName() << "' of type '" << obj->IsA()->GetName()
2314  << "' and with title '" << obj->GetTitle() << "'\n";
2315  return false;
2316  }
2317 
2318  // If we just read in a reference MonitorElement, and there is a
2319  // MonitorElement with the same name, link the two together.
2320  // The other direction is handled by the book() method.
2321  if (refcheck && isSubdirectory(s_referenceDirName, dir))
2322  {
2323  std::string mdir(dir, s_referenceDirName.size()+1, std::string::npos);
2324  if (MonitorElement *master = findObject(mdir, obj->GetName()))
2325  {
2326  // We have extracted a MonitorElement, and it's located in the reference
2327  // dir. Then we find the corresponding MonitorElement in the
2328  // non-reference dir and assign the object_ of the reference
2329  // MonitorElement to the reference_ property of the corresponding
2330  // non-reference MonitorElement.
2331  master->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
2332  master->reference_ = refcheck->object_;
2333  }
2334  }
2335 
2336  return true;
2337 }
2338 
2342 bool
2343 DQMStore::cdInto(const std::string &path) const
2344 {
2345  assert(! path.empty());
2346 
2347  // Find the first path component.
2348  size_t start = 0;
2349  size_t end = path.find('/', start);
2350  if (end == std::string::npos)
2351  end = path.size();
2352 
2353  while (true)
2354  {
2355  // Check if this subdirectory component exists. If yes, make sure
2356  // it is actually a subdirectory. Otherwise create or cd into it.
2357  std::string part(path, start, end-start);
2358  TObject *o = gDirectory->Get(part.c_str());
2359  if (o && ! dynamic_cast<TDirectory *>(o))
2360  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2361  " fails because the part '%s' already exists and is not"
2362  " directory", path.c_str(), part.c_str());
2363  else if (! o)
2364  gDirectory->mkdir(part.c_str());
2365 
2366  if (! gDirectory->cd(part.c_str()))
2367  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2368  " fails because could not cd into subdirectory '%s'",
2369  path.c_str(), part.c_str());
2370 
2371  // Stop if we reached the end, ignoring any trailing '/'.
2372  if (end+1 >= path.size())
2373  break;
2374 
2375  // Find the next path component.
2376  start = end+1;
2377  end = path.find('/', start);
2378  if (end == std::string::npos)
2379  end = path.size();
2380  }
2381 
2382  return true;
2383 }
2384 
2385 void
2387  MonitorElement const& me,
2388  TFile & file)
2389 {
2390  // Save the object.
2391  if (me.kind() < MonitorElement::DQM_KIND_TH1F) {
2392  TObjString(me.tagString().c_str()).Write();
2393  } else {
2394  me.object_->Write();
2395  }
2396 
2397  // Save quality reports if this is not in reference section.
2398  if (not isSubdirectory(s_referenceDirName, *me.data_.dirname))
2399  {
2400  for (auto const& report: me.data_.qreports) {
2401  TObjString(me.qualityTagString(report).c_str()).Write();
2402  }
2403  }
2404 
2405  // Save efficiency tag, if any.
2407  TObjString(me.effLabelString().c_str()).Write();
2408  }
2409 
2410  // Save tag if any.
2411  if (me.data_.flags & DQMNet::DQM_PROP_TAGGED) {
2412  TObjString(me.tagLabelString().c_str()).Write();
2413  }
2414 }
2415 
2416 void
2418  std::string const& dir,
2419  std::string const& refpath,
2420  SaveReferenceTag ref,
2421  int minStatus,
2422  unsigned int run,
2423  MEMap::const_iterator begin,
2424  MEMap::const_iterator end,
2425  TFile & file,
2426  unsigned int & counter)
2427 {
2428  for (auto const& me: boost::make_iterator_range(begin, end))
2429  {
2430  if (not isSubdirectory(dir, *me.data_.dirname))
2431  break;
2432 
2433  if (verbose_ > 1)
2434  std::cout << "DQMStore::save:"
2435  << " run: " << me.run()
2436  << " lumi: " << me.lumi()
2437  << " lumiFlag: " << me.getLumiFlag()
2438  << " moduleId: " << me.moduleId()
2439  << " fullpathname: " << me.getFullname()
2440  << " flags: " << std::hex << me.data_.flags
2441  << std::endl;
2442 
2443  // Skip MonitorElements in a subdirectory of the current one.
2444  if (dir != *me.data_.dirname) {
2445  if (verbose_ > 1) {
2446  std::cout << "DQMStore::save: skipping monitor element in a subfolder of " << dir << "/" << std::endl;
2447  }
2448  continue;
2449  }
2450 
2451  // Handle reference histograms, with three distinct cases:
2452  // 1) Skip all references entirely on saving.
2453  // 2) Blanket saving of all references.
2454  // 3) Save only references for monitor elements with qtests.
2455  // The latter two are affected by "path" sub-tree selection,
2456  // i.e. references are saved only in the selected tree part.
2457  if (isSubdirectory(refpath, *me.data_.dirname))
2458  {
2459  if (ref == SaveWithoutReference)
2460  // Skip the reference entirely.
2461  continue;
2462  else if (ref == SaveWithReference)
2463  // Save all references regardless of qtests.
2464  ;
2465  else if (ref == SaveWithReferenceForQTest)
2466  {
2467  // Save only references for monitor elements with qtests
2468  // with an optional cut on minimum quality test result.
2469  int status = -1;
2470  std::string mname(me.getFullname(), s_referenceDirName.size()+1, std::string::npos);
2471  MonitorElement *master = get(mname);
2472  if (master)
2473  for (auto const& qreport : master->data_.qreports)
2474  status = std::max(status, qreport.code);
2475 
2476  if (not master or status < minStatus)
2477  {
2478  if (verbose_ > 1)
2479  std::cout << "DQMStore::save: skipping monitor element '"
2480  << me.data_.objname << "' while saving, status is "
2481  << status << ", required minimum status is "
2482  << minStatus << std::endl;
2483  continue;
2484  }
2485  }
2486  }
2487 
2488  if (verbose_ > 1) {
2489  std::cout << "DQMStore::save: saving monitor element" << std::endl;
2490  }
2491 
2492  saveMonitorElementToROOT(me, file);
2493 
2494  // Count saved histograms
2495  ++counter;
2496  }
2497 }
2498 
2501 void
2503  const std::string &path /* = "" */,
2504  const std::string &pattern /* = "" */,
2505  const std::string &rewrite /* = "" */,
2506  const uint32_t run /* = 0 */,
2507  const uint32_t lumi /* = 0 */,
2508  SaveReferenceTag ref /* = SaveWithReference */,
2509  int minStatus /* = dqm::qstatus::STATUS_OK */,
2510  const std::string &fileupdate /* = RECREATE */)
2511 {
2512  // TFile flushes to disk with fsync() on every TDirectory written to
2513  // the file. This makes DQM file saving painfully slow, and
2514  // ironically makes it _more_ likely the file saving gets
2515  // interrupted and corrupts the file. The utility class below
2516  // simply ignores the flush synchronisation.
2517  class TFileNoSync : public TFile
2518  {
2519  public:
2520  TFileNoSync(const char *file, const char *opt) : TFile(file, opt) {}
2521  Int_t SysSync(Int_t) override { return 0; }
2522  };
2523 
2524  std::lock_guard<std::mutex> guard(book_mutex_);
2525 
2526  unsigned int nme = 0;
2527 
2528  // open output file, on 1st save recreate, later update
2529  if (verbose_) {
2530  std::cout << "DQMStore::save: Opening TFile '" << filename
2531  << "' with option '" << fileupdate << "'"
2532  << std::endl;
2533  }
2534 
2535  TFileNoSync f(filename.c_str(), fileupdate.c_str()); // open file
2536  if(f.IsZombie())
2537  raiseDQMError("DQMStore", "Failed to create/update file '%s'", filename.c_str());
2538  f.cd();
2539 
2540  // Construct a regular expression from the pattern string.
2541  std::unique_ptr<lat::Regexp> rxpat;
2542  if (not pattern.empty())
2543  rxpat = std::make_unique<lat::Regexp>(pattern);
2544 
2545  // Prepare a path for the reference object selection.
2546  std::string refpath;
2547  refpath.reserve(s_referenceDirName.size() + path.size() + 2);
2548  refpath += s_referenceDirName;
2549  if (not path.empty())
2550  {
2551  refpath += '/';
2552  refpath += path;
2553  }
2554 
2555  // Loop over the directory structure.
2556  for (auto const& dir: dirs_)
2557  {
2558  // Check if we should process this directory. We process the
2559  // requested part of the object tree, including references.
2560  if (not path.empty()
2561  and not isSubdirectory(refpath, dir)
2562  and not isSubdirectory(path, dir))
2563  continue;
2564 
2565  if (verbose_ > 1) {
2566  std::cout << "DQMStore::save: DQM folder " << dir << "/" << std::endl;
2567  }
2568 
2569  // Create the directory.
2570  gDirectory->cd("/");
2571  if (dir.empty())
2572  cdInto(s_monitorDirName);
2573  else if (rxpat.get())
2574  cdInto(s_monitorDirName + '/' + lat::StringOps::replace(dir, *rxpat, rewrite));
2575  else
2576  cdInto(s_monitorDirName + '/' + dir);
2577 
2578  // Loop over monitor elements in this directory.
2579  if (not enableMultiThread_) {
2580  MonitorElement proto(&dir, std::string(), run, 0);
2581  auto begin = data_.lower_bound(proto);
2582  auto end = data_.end();
2583  saveMonitorElementRangeToROOT(dir, refpath, ref, minStatus, run, begin, end, f, nme);
2584  } else {
2585  // Restrict the loop to the monitor elements for the current lumisection
2586  MonitorElement proto(&dir, std::string(), run, 0);
2587  proto.setLumi(lumi);
2588  auto begin = data_.lower_bound(proto);
2589  proto.setLumi(lumi+1);
2590  auto end = data_.lower_bound(proto);
2591  saveMonitorElementRangeToROOT(dir, refpath, ref, minStatus, run, begin, end, f, nme);
2592  }
2593 
2594  // In LSbasedMode, loop also over the (run, 0) global histograms;
2595  // these could be the merged global histrograms of their per-stream
2596  // counterparts after the streamEndRun transition - but they are not
2597  // produced in LSbasedMode.
2598  if (enableMultiThread_ and LSbasedMode_ and lumi != 0) {
2599  auto begin = data_.lower_bound(MonitorElement(&dir, std::string(), run, 0));
2600  auto end = data_.lower_bound(MonitorElement(&dir, std::string(), run, 1));
2601  saveMonitorElementRangeToROOT(dir, refpath, ref, minStatus, run, begin, end, f, nme);
2602  }
2603  }
2604 
2605  f.Close();
2606 
2607  // Maybe make some noise.
2608  if (verbose_) {
2609  std::cout << "DQMStore::save: successfully wrote " << nme
2610  << " objects from path '" << path << "/"
2611  << "' into DQM file '" << filename << "'\n";
2612  }
2613 }
2614 
2615 void
2617  MonitorElement const& me,
2619 {
2620  // Save the object.
2621  TBufferFile buffer(TBufferFile::kWrite);
2622  if (me.kind() < MonitorElement::DQM_KIND_TH1F) {
2623  TObjString object(me.tagString().c_str());
2624  buffer.WriteObject(&object);
2625  } else {
2626  buffer.WriteObject(me.object_);
2627  }
2629  histo.set_full_pathname(*me.data_.dirname + '/' + me.data_.objname);
2630  histo.set_flags(me.data_.flags);
2631  histo.set_size(buffer.Length());
2632  histo.set_streamed_histo((const void*)buffer.Buffer(), buffer.Length());
2633 
2634  // Save quality reports if this is not in reference section.
2635  // XXX not supported by protobuf files.
2636 
2637  // Save efficiency tag, if any.
2638  // XXX not supported by protobuf files.
2639 
2640  // Save tag if any.
2641  // XXX not supported by protobuf files.
2642 }
2643 
2644 void
2646  std::string const& dir,
2647  unsigned int run,
2648  MEMap::const_iterator begin,
2649  MEMap::const_iterator end,
2651  unsigned int & counter)
2652 {
2653  for (auto const& me: boost::make_iterator_range(begin, end))
2654  {
2655  if (not isSubdirectory(dir, *me.data_.dirname))
2656  break;
2657 
2658  if (verbose_ > 1)
2659  std::cout << "DQMStore::savePB:"
2660  << " run: " << me.run()
2661  << " lumi: " << me.lumi()
2662  << " lumiFlag: " << me.getLumiFlag()
2663  << " moduleId: " << me.moduleId()
2664  << " fullpathname: " << me.getFullname()
2665  << " flags: " << std::hex << me.data_.flags
2666  << std::endl;
2667 
2668  // Skip MonitorElements in a subdirectory of the current one.
2669  if (dir != *me.data_.dirname) {
2670  if (verbose_ > 1) {
2671  std::cout << "DQMStore::savePB: skipping monitor element in a subfolder of " << dir << "/" << std::endl;
2672  }
2673  continue;
2674  }
2675 
2676  // Handle reference histograms, with three distinct cases:
2677  // XXX not supported by protobuf files.
2678 
2679  if (verbose_ > 1) {
2680  std::cout << "DQMStore::savePB: saving monitor element" << std::endl;
2681  }
2682 
2683  saveMonitorElementToPB(me, file);
2684 
2685  // Count saved histograms
2686  ++counter;
2687  }
2688 }
2689 
2692 void
2694  const std::string &path /* = "" */,
2695  const uint32_t run /* = 0 */,
2696  const uint32_t lumi /* = 0 */)
2697 {
2698  using google::protobuf::io::FileOutputStream;
2699  using google::protobuf::io::GzipOutputStream;
2700  using google::protobuf::io::StringOutputStream;
2701 
2702  std::lock_guard<std::mutex> guard(book_mutex_);
2703 
2704  unsigned int nme = 0;
2705 
2706  if (verbose_) {
2707  std::cout << "DQMStore::savePB: Opening PBFile '" << filename << "'"
2708  << std::endl;
2709  }
2710  dqmstorepb::ROOTFilePB dqmstore_message;
2711 
2712  // Loop over the directory structure.
2713  for (auto const& dir: dirs_)
2714  {
2715  // Check if we should process this directory. We process the
2716  // requested part of the object tree, including references.
2717  if (not path.empty()
2718  and not isSubdirectory(path, dir))
2719  continue;
2720 
2721  if (verbose_ > 1) {
2722  std::cout << "DQMStore::savePB: DQM folder " << dir << "/" << std::endl;
2723  }
2724 
2725  // Loop over monitor elements in this directory.
2726  if (not enableMultiThread_) {
2727  MonitorElement proto(&dir, std::string(), run, 0);
2728  auto begin = data_.lower_bound(proto);
2729  auto end = data_.end();
2730  saveMonitorElementRangeToPB(dir, run, begin, end, dqmstore_message, nme);
2731  } else {
2732  // Restrict the loop to the monitor elements for the current lumisection
2733  MonitorElement proto(&dir, std::string(), run, 0);
2734  proto.setLumi(lumi);
2735  auto begin = data_.lower_bound(proto);
2736  proto.setLumi(lumi+1);
2737  auto end = data_.lower_bound(proto);
2738  saveMonitorElementRangeToPB(dir, run, begin, end, dqmstore_message, nme);
2739  }
2740 
2741  // In LSbasedMode, loop also over the (run, 0) global histograms;
2742  // these could be the merged global histrograms of their per-stream
2743  // counterparts after the streamEndRun transition - but they are not
2744  // produced in LSbasedMode.
2745  if (enableMultiThread_ and LSbasedMode_ and lumi != 0) {
2746  auto begin = data_.lower_bound(MonitorElement(&dir, std::string(), run, 0));
2747  auto end = data_.lower_bound(MonitorElement(&dir, std::string(), run, 1));
2748  saveMonitorElementRangeToPB(dir, run, begin, end, dqmstore_message, nme);
2749  }
2750  }
2751 
2752  int filedescriptor = ::open(filename.c_str(),
2753  O_WRONLY | O_CREAT | O_TRUNC,
2754  S_IRUSR | S_IWUSR |
2755  S_IRGRP | S_IWGRP |
2756  S_IROTH);
2757  FileOutputStream file_stream(filedescriptor);
2759  options.format = GzipOutputStream::GZIP;
2760  options.compression_level = 1;
2761  GzipOutputStream gzip_stream(&file_stream, options);
2762  dqmstore_message.SerializeToZeroCopyStream(&gzip_stream);
2763 
2764  // Flush the internal streams before closing the fd.
2765  gzip_stream.Close();
2766  file_stream.Close();
2767  ::close(filedescriptor);
2768 
2769  // Maybe make some noise.
2770  if (verbose_) {
2771  std::cout << "DQMStore::savePB: successfully wrote " << nme
2772  << " objects from path '" << path << "/"
2773  << "' into DQM file '" << filename << "'\n";
2774  }
2775 }
2776 
2777 
2780 unsigned int
2782  bool overwrite,
2783  const std::string &onlypath,
2784  const std::string &prepend,
2785  const std::string &curdir,
2786  OpenRunDirs stripdirs)
2787 {
2788  unsigned int ntot = 0;
2789  unsigned int count = 0;
2790 
2791  if (! file->cd(curdir.c_str()))
2792  raiseDQMError("DQMStore", "Failed to process directory '%s' while"
2793  " reading file '%s'", curdir.c_str(), file->GetName());
2794 
2795  // Figure out current directory name, but strip out the top
2796  // directory into which we dump everything.
2797  std::string dirpart = curdir;
2798  if (dirpart.compare(0, s_monitorDirName.size(), s_monitorDirName) == 0)
2799  {
2800  if (dirpart.size() == s_monitorDirName.size())
2801  dirpart.clear();
2802  else if (dirpart[s_monitorDirName.size()] == '/')
2803  dirpart.erase(0, s_monitorDirName.size()+1);
2804  }
2805 
2806  // See if we are going to skip this directory.
2807  bool skip = (! onlypath.empty() && ! isSubdirectory(onlypath, dirpart));
2808 
2809  if (prepend == s_collateDirName ||
2810  prepend == s_referenceDirName ||
2811  stripdirs == StripRunDirs )
2812  {
2813  // Remove Run # and RunSummary dirs
2814  // first look for Run summary,
2815  // if that is found and erased, also erase Run dir
2816  size_t slash = dirpart.find('/');
2817  size_t pos = dirpart.find("/Run summary");
2818  if (slash != std::string::npos && pos !=std::string::npos)
2819  {
2820  dirpart.erase(pos,12);
2821 
2822  pos = dirpart.find("Run ");
2823  size_t length = dirpart.find('/',pos+1)-pos+1;
2824  if (pos !=std::string::npos)
2825  dirpart.erase(pos,length);
2826  }
2827  }
2828 
2829  // If we are prepending, add it to the directory name,
2830  // and suppress reading of already existing reference histograms
2831  if (prepend == s_collateDirName ||
2832  prepend == s_referenceDirName)
2833  {
2834  size_t slash = dirpart.find('/');
2835  // If we are reading reference, skip previous reference.
2836  if (slash == std::string::npos // skip if Reference is toplevel folder, i.e. no slash
2837  && slash+1+s_referenceDirName.size() == dirpart.size()
2838  && dirpart.compare(slash+1, s_referenceDirName.size(), s_referenceDirName) == 0)
2839  return 0;
2840 
2841  slash = dirpart.find('/');
2842  // Skip reading of EventInfo subdirectory.
2843  if (slash != std::string::npos
2844  && slash + 10 == dirpart.size()
2845  && dirpart.compare( slash+1 , 9 , "EventInfo") == 0) {
2846  if (verbose_)
2847  std::cout << "DQMStore::readDirectory: skipping '" << dirpart << "'\n";
2848  return 0;
2849  }
2850 
2851  // Add prefix.
2852  if (dirpart.empty())
2853  dirpart = prepend;
2854  else
2855  dirpart = prepend + '/' + dirpart;
2856  }
2857  else if (! prepend.empty())
2858  {
2859  if (dirpart.empty())
2860  dirpart = prepend;
2861  else
2862  dirpart = prepend + '/' + dirpart;
2863  }
2864 
2865  // Loop over the contents of this directory in the file.
2866  // Post-pone string object handling to happen after other
2867  // objects have been read in so we are guaranteed to have
2868  // histograms by the time we read in quality tests and tags.
2869  TKey *key;
2870  TIter next (gDirectory->GetListOfKeys());
2871  std::list<TObject *> delayed;
2872  while ((key = (TKey *) next()))
2873  {
2874  std::unique_ptr<TObject> obj(key->ReadObj());
2875  if (dynamic_cast<TDirectory *>(obj.get()))
2876  {
2877  std::string subdir;
2878  subdir.reserve(curdir.size() + strlen(obj->GetName()) + 2);
2879  subdir += curdir;
2880  if (! curdir.empty())
2881  subdir += '/';
2882  subdir += obj->GetName();
2883 
2884  ntot += readDirectory(file, overwrite, onlypath, prepend, subdir, stripdirs);
2885  }
2886  else if (skip)
2887  ;
2888  else if (dynamic_cast<TObjString *>(obj.get()))
2889  {
2890  delayed.push_back(obj.release());
2891  }
2892  else
2893  {
2894  if (verbose_ > 2)
2895  std::cout << "DQMStore: reading object '" << obj->GetName()
2896  << "' of type '" << obj->IsA()->GetName()
2897  << "' from '" << file->GetName()
2898  << "' into '" << dirpart << "'\n";
2899 
2900  makeDirectory(dirpart);
2901  if (extract(obj.get(), dirpart, overwrite, collateHistograms_))
2902  ++count;
2903  }
2904  }
2905 
2906  while (! delayed.empty())
2907  {
2908  if (verbose_ > 2)
2909  std::cout << "DQMStore: reading object '" << delayed.front()->GetName()
2910  << "' of type '" << delayed.front()->IsA()->GetName()
2911  << "' from '" << file->GetName()
2912  << "' into '" << dirpart << "'\n";
2913 
2914  makeDirectory(dirpart);
2915  if (extract(delayed.front(), dirpart, overwrite, collateHistograms_))
2916  ++count;
2917 
2918  delete delayed.front();
2919  delayed.pop_front();
2920  }
2921 
2922  if (verbose_ > 1)
2923  std::cout << "DQMStore: read " << count << '/' << ntot
2924  << " objects from directory '" << dirpart << "'\n";
2925 
2926  return ntot + count;
2927 }
2928 
2935 bool
2937  bool overwrite /* = false */,
2938  const std::string &onlypath /* ="" */,
2939  const std::string &prepend /* ="" */,
2940  OpenRunDirs stripdirs /* =KeepRunDirs */,
2941  bool fileMustExist /* =true */)
2942 {
2943  return readFile(filename,overwrite,onlypath,prepend,stripdirs,fileMustExist);
2944 }
2945 
2950 bool
2952  OpenRunDirs stripdirs /* =StripRunDirs */,
2953  bool fileMustExist /* =true */)
2954 {
2955  bool overwrite = true;
2956  if (collateHistograms_) overwrite = false;
2957  if (verbose_)
2958  {
2959  std::cout << "DQMStore::load: reading from file '" << filename << "'\n";
2960  if (collateHistograms_)
2961  std::cout << "DQMStore::load: in collate mode " << "\n";
2962  else
2963  std::cout << "DQMStore::load: in overwrite mode " << "\n";
2964  }
2965 
2966  if (!s_rxpbfile.match(filename, 0, 0))
2967  return readFile(filename, overwrite, "", "", stripdirs, fileMustExist);
2968  else
2969  return readFilePB(filename, overwrite, "", "", stripdirs, fileMustExist);
2970 }
2971 
2977 bool
2979  bool overwrite /* = false */,
2980  const std::string &onlypath /* ="" */,
2981  const std::string &prepend /* ="" */,
2982  OpenRunDirs stripdirs /* =StripRunDirs */,
2983  bool fileMustExist /* =true */)
2984 {
2985 
2986  if (verbose_)
2987  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
2988 
2989  std::unique_ptr<TFile> f;
2990 
2991  try
2992  {
2993  f.reset(TFile::Open(filename.c_str()));
2994  if (! f.get() || f->IsZombie())
2995  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
2996  }
2997  catch (std::exception &)
2998  {
2999  if (fileMustExist)
3000  throw;
3001  else
3002  {
3003  if (verbose_)
3004  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
3005  return false;
3006  }
3007  }
3008 
3009  unsigned n = readDirectory(f.get(), overwrite, onlypath, prepend, "", stripdirs);
3010  f->Close();
3011 
3012  for (auto const& me : data_)
3013  const_cast<MonitorElement &>(me).updateQReportStats();
3014 
3015  if (verbose_)
3016  {
3017  std::cout << "DQMStore::open: successfully read " << n
3018  << " objects from file '" << filename << "'";
3019  if (! onlypath.empty())
3020  std::cout << " from directory '" << onlypath << "'";
3021  if (! prepend.empty())
3022  std::cout << " into directory '" << prepend << "'";
3023  std::cout << std::endl;
3024  }
3025  return true;
3026 }
3027 
3031 inline TObject * DQMStore::extractNextObject(TBufferFile &buf) const {
3032  if (buf.Length() == buf.BufferSize())
3033  return nullptr;
3034  buf.InitMap();
3035  void *ptr = buf.ReadObjectAny(nullptr);
3036  return reinterpret_cast<TObject *>(ptr);
3037 }
3038 
3041  std::string &objname,
3042  TObject ** obj) {
3043 
3044  size_t slash = h.full_pathname().rfind('/');
3045  size_t dirpos = (slash == std::string::npos ? 0 : slash);
3046  size_t namepos = (slash == std::string::npos ? 0 : slash+1);
3047  dirname.assign(h.full_pathname(), 0, dirpos);
3048  objname.assign(h.full_pathname(), namepos, std::string::npos);
3049  TBufferFile buf(TBufferFile::kRead, h.size(),
3050  (void*)h.streamed_histo().data(),
3051  kFALSE);
3052  buf.Reset();
3053  *obj = extractNextObject(buf);
3054  if (!*obj) {
3055  raiseDQMError("DQMStore", "Error reading element:'%s'" , h.full_pathname().c_str());
3056  }
3057 }
3058 
3059 bool
3061  bool overwrite /* = false */,
3062  const std::string &onlypath /* ="" */,
3063  const std::string &prepend /* ="" */,
3064  OpenRunDirs stripdirs /* =StripRunDirs */,
3065  bool fileMustExist /* =true */)
3066 {
3067  using google::protobuf::io::FileInputStream;
3068  using google::protobuf::io::FileOutputStream;
3069  using google::protobuf::io::GzipInputStream;
3070  using google::protobuf::io::GzipOutputStream;
3071  using google::protobuf::io::CodedInputStream;
3072  using google::protobuf::io::ArrayInputStream;
3073 
3074  if (verbose_)
3075  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
3076 
3077  int filedescriptor;
3078  if ((filedescriptor = ::open(filename.c_str(), O_RDONLY)) == -1) {
3079  if (fileMustExist)
3080  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
3081  else
3082  if (verbose_)
3083  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
3084  return false;
3085  }
3086 
3087  dqmstorepb::ROOTFilePB dqmstore_message;
3088  FileInputStream fin(filedescriptor);
3089  GzipInputStream input(&fin);
3090  CodedInputStream input_coded(&input);
3091  input_coded.SetTotalBytesLimit(1024*1024*1024, -1);
3092  if (!dqmstore_message.ParseFromCodedStream(&input_coded)) {
3093  raiseDQMError("DQMStore", "Fatal parsing file '%s'", filename.c_str());
3094  return false;
3095  }
3096  ::close(filedescriptor);
3097 
3098  for (int i = 0; i < dqmstore_message.histo_size(); ++i) {
3099  std::string path;
3100  std::string objname;
3101 
3102  TObject *obj = nullptr;
3103  const dqmstorepb::ROOTFilePB::Histo &h = dqmstore_message.histo(i);
3104  get_info(h, path, objname, &obj);
3105 
3106  setCurrentFolder(path);
3107  if (obj)
3108  {
3109  /* Before calling the extract() check if histogram exists:
3110  * if it does - flags for the given monitor are already set (and merged)
3111  * else - set the flags after the histogram is created.
3112  */
3113  MonitorElement *me = findObject(path, objname);
3114 
3115  /* Run histograms should be collated and not overwritten,
3116  * Lumi histograms should be overwritten (and collate flag is not checked)
3117  */
3118  bool overwrite = h.flags() & DQMNet::DQM_PROP_LUMI;
3119  bool collate = !(h.flags() & DQMNet::DQM_PROP_LUMI);
3120  extract(static_cast<TObject *>(obj), path, overwrite, collate);
3121 
3122  if (me == nullptr) {
3123  me = findObject(path, objname);
3124  me->data_.flags = h.flags();
3125  }
3126 
3127  delete obj;
3128  }
3129  }
3130 
3131  cd();
3132  return true;
3133 }
3134 
3140 void
3142 {
3144  const std::string *cleaned = nullptr;
3145  cleanTrailingSlashes(path, clean, cleaned);
3146  MonitorElement proto(cleaned, std::string());
3147 
3148  auto e = data_.end();
3149  auto i = data_.lower_bound(proto);
3150  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
3151  data_.erase(i++);
3152 
3153  auto de = dirs_.end();
3154  auto di = dirs_.lower_bound(*cleaned);
3155  while (di != de && isSubdirectory(*cleaned, *di))
3156  dirs_.erase(di++);
3157 }
3158 
3160 void
3162 {
3163  MonitorElement proto(&dir, std::string());
3164  auto e = data_.end();
3165  auto i = data_.lower_bound(proto);
3166  while (i != e && isSubdirectory(dir, *i->data_.dirname))
3167  if (dir == *i->data_.dirname)
3168  data_.erase(i++);
3169  else
3170  ++i;
3171 }
3172 
3174 void
3176 {
3178 }
3179 
3182 void
3184 {
3185  removeElement(pwd_, name);
3186 }
3187 
3190 void
3191 DQMStore::removeElement(const std::string &dir, const std::string &name, bool warning /* = true */)
3192 {
3193  MonitorElement proto(&dir, name);
3194  auto pos = data_.find(proto);
3195  if (pos != data_.end())
3196  data_.erase(pos);
3197  else if (warning) {
3198  std::cout << "DQMStore: WARNING: attempt to remove non-existent"
3199  << " monitor element '" << name << "' in '" << dir << "'\n";
3200  }
3201 }
3202 
3208 QCriterion *
3210 {
3211  auto i = qtests_.find(qtname);
3212  auto e = qtests_.end();
3213  return (i == e ? nullptr : i->second);
3214 }
3215 
3219 QCriterion *
3221 {
3222  if (qtests_.count(qtname))
3223  raiseDQMError("DQMStore", "Attempt to create duplicate quality test '%s'",
3224  qtname.c_str());
3225 
3226  auto i = qalgos_.find(algoname);
3227  if (i == qalgos_.end())
3228  raiseDQMError("DQMStore", "Cannot create a quality test using unknown"
3229  " algorithm '%s'", algoname.c_str());
3230 
3231  QCriterion *qc = i->second(qtname);
3232  qc->setVerbose(verboseQT_);
3233 
3234  qtests_[qtname] = qc;
3235  return qc;
3236 }
3237 
3240 void
3241 DQMStore::useQTest(const std::string &dir, const std::string &qtname)
3242 {
3243  // Clean the path
3245  const std::string *cleaned = nullptr;
3246  cleanTrailingSlashes(dir, clean, cleaned);
3247 
3248  // Validate the path.
3249  if (cleaned->find_first_not_of(s_safe) != std::string::npos)
3250  raiseDQMError("DQMStore", "Monitor element path name '%s'"
3251  " uses unacceptable characters", cleaned->c_str());
3252 
3253  // Redirect to the pattern match version.
3254  useQTestByMatch(*cleaned + "/*", qtname);
3255 }
3256 
3258 int
3260 {
3261  QCriterion *qc = getQCriterion(qtname);
3262  if (! qc)
3263  raiseDQMError("DQMStore", "Cannot apply non-existent quality test '%s'",
3264  qtname.c_str());
3265 
3266  auto * fm = new fastmatch( pattern );
3267 
3268  // Record the test for future reference.
3269  QTestSpec qts(fm, qc);
3270  qtestspecs_.push_back(qts);
3271 
3272  // Apply the quality test.
3273  std::string path;
3274  int cases = 0;
3275  for (auto const& me : data_)
3276  {
3277  path.clear();
3278  mergePath(path, *me.data_.dirname, me.data_.objname);
3279  if (fm->match(path))
3280  {
3281  ++cases;
3282  const_cast<MonitorElement &>(me).addQReport(qts.second);
3283  }
3284  }
3285 
3286  //return the number of matched cases
3287  return cases;
3288 }
3291 void
3293 {
3294 
3295  if (verbose_ > 0)
3296  std::cout << "DQMStore: running runQTests() with reset = "
3297  << ( reset_ ? "true" : "false" ) << std::endl;
3298 
3299  // Apply quality tests to each monitor element, skipping references.
3300  for (auto const& me : data_)
3301  if (! isSubdirectory(s_referenceDirName, *me.data_.dirname))
3302  const_cast<MonitorElement &>(me).runQTests();
3303 
3304  reset_ = false;
3305 }
3306 
3310 int
3311 DQMStore::getStatus(const std::string &path /* = "" */) const
3312 {
3314  const std::string *cleaned = nullptr;
3315  cleanTrailingSlashes(path, clean, cleaned);
3316 
3318  for (auto const& me : data_)
3319  {
3320  if (! cleaned->empty() && ! isSubdirectory(*cleaned, *me.data_.dirname))
3321  continue;
3322 
3323  if (me.hasError())
3324  return dqm::qstatus::ERROR;
3325  else if (me.hasWarning())
3326  status = dqm::qstatus::WARNING;
3327  else if (status < dqm::qstatus::WARNING
3328  && me.hasOtherReport())
3329  status = dqm::qstatus::OTHER;
3330  }
3331  return status;
3332 }
3333 
3339 void
3341 {
3342  if (me)
3343  me->softReset();
3344 }
3345 
3346 // reverts action of softReset
3347 void
3349 {
3350  if (me)
3351  me->disableSoftReset();
3352 }
3353 
3356 void
3358 {
3359  if (me)
3360  me->setAccumulate(flag);
3361 }
3362 
3366 void
3368 {
3369  std::vector<std::string> contents;
3370  getContents(contents);
3371 
3372  std::cout << " ------------------------------------------------------------\n"
3373  << " Directory structure: \n"
3374  << " ------------------------------------------------------------\n";
3375 
3376  std::copy(contents.begin(), contents.end(),
3377  std::ostream_iterator<std::string>(std::cout, "\n"));
3378 
3379  std::cout << " ------------------------------------------------------------\n";
3380 }
3381 
3385 // check if the collate option is active on the DQMStore
3386 bool
3388 {
3389  return collateHistograms_;
3390 }
3394 // check if the monitor element is in auto-collation folder
3395 bool
3397 { return me && isSubdirectory(s_collateDirName, *me->data_.dirname); }
3401 
3403 void
3405 {
3406  if (scaleFlag_ == 0.0) return;
3407  if (verbose_ > 0)
3408  std::cout << " =========== " << " ScaleFlag " << scaleFlag_ << std::endl;
3409  double factor = scaleFlag_;
3410  int events = 1;
3411  if (dirExists("Info/EventInfo")) {
3412  if ( scaleFlag_ == -1.0) {
3413  MonitorElement * scale_me = get("Info/EventInfo/ScaleFactor");
3414  if (scale_me && scale_me->kind()==MonitorElement::DQM_KIND_REAL) factor = scale_me->getFloatValue();
3415  }
3416  MonitorElement * event_me = get("Info/EventInfo/processedEvents");
3417  if (event_me && event_me->kind()==MonitorElement::DQM_KIND_INT) events = event_me->getIntValue();
3418  }
3419  factor = factor/(events*1.0);
3420 
3421  for (auto const& m : data_)
3422  {
3423  auto &me = const_cast<MonitorElement &>(m);
3424  switch (me.kind())
3425  {
3427  {
3428  me.getTH1F()->Scale(factor);
3429  break;
3430  }
3432  {
3433  me.getTH1S()->Scale(factor);
3434  break;
3435  }
3437  {
3438  me.getTH1D()->Scale(factor);
3439  break;
3440  }
3442  {
3443  me.getTH2F()->Scale(factor);
3444  break;
3445  }
3447  {
3448  me.getTH2S()->Scale(factor);
3449  break;
3450  }
3452  {
3453  me.getTH2D()->Scale(factor);
3454  break;
3455  }
3457  {
3458  me.getTH3F()->Scale(factor);
3459  break;
3460  }
3462  {
3463  me.getTProfile()->Scale(factor);
3464  break;
3465  }
3467  {
3468  me.getTProfile2D()->Scale(factor);
3469  break;
3470  }
3471  default:
3472  if (verbose_ > 0)
3473  std::cout << " The DQM object '" << me.getFullname() << "' is not scalable object " << std::endl;
3474  continue;
3475  }
3476  }
3477 }
QCriterion * getQCriterion(const std::string &qtname) const
Definition: DQMStore.cc:3209
size
Write out results.
~DQMStore()
Definition: DQMStore.cc:372
MonitorElement * getElement(const std::string &path)
Definition: DQMStore.cc:306
bool compare_strings_reverse(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:205
Definition: start.py:1
TProfile * getTProfile() const
MonitorElement * book2DD_(const std::string &dir, const std::string &name, TH2D *h)
Book 2D histogram based on TH2D.
Definition: DQMStore.cc:958
edm::ErrorSummaryEntry Error
Master< F > master(const F &f)
Definition: FunctClone.h:68
T getUntrackedParameter(std::string const &, T const &) const
DQMStore(const edm::ParameterSet &pset, edm::ActivityRegistry &)
Definition: DQMStore.cc:349
MonitorElement * book2S(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2S histogram.
Definition: DQMStore.cc:987
bool containsAnyMonitorable(const std::string &path) const
Definition: DQMStore.cc:1600
uint32_t moduleId
Definition: DQMNet.h:105
::google::protobuf::uint32 size() const
int64_t getIntValue() const
bool isCollateME(MonitorElement *me) const
Definition: DQMStore.cc:3396
bool cdInto(const std::string &path) const
Definition: DQMStore.cc:2343
QReports qreports
Definition: DQMNet.h:108
const ::std::string & full_pathname() const
int getStatus(const std::string &path="") const
Definition: DQMStore.cc:3311
void copyFrom(TH1 *from)
const std::string & pwd() const
Definition: DQMStore.cc:517
MonitorElement * initialise(Kind kind)
MonitorElement * bookProfile2D_(const std::string &dir, const std::string &name, TProfile2D *h)
Book 2D profile histogram based on TProfile2D.
Definition: DQMStore.cc:1303
static const int OTHER
TProfile2D * getTProfile2D() const
std::string algorithm
Definition: DQMNet.h:94
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
MonitorElement * book1D(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1D histogram.
Definition: DQMStore.cc:837
def copy(args, dbName)
void rmdir(const std::string &fullpath)
Definition: DQMStore.cc:3141
static void collate3D(MonitorElement *me, TH3F *h, unsigned verbose)
Definition: DQMStore.cc:1465
bool match(std::string const &s) const
Definition: DQMStore.cc:247
bool readFile(const std::string &filename, bool overwrite=false, const std::string &path="", const std::string &prepend="", OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2978
static void collateProfile(MonitorElement *me, TProfile *h, unsigned verbose)
Definition: DQMStore.cc:1472
TH1F * getTH1F() const
MonitorElement * book3D(const char *name, const char *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:1118
TH2S * getTH2S() const
void scaleElements()
Definition: DQMStore.cc:3404
double getFloatValue() const
void setLumi(uint32_t ls)
MonitorElement * get(const std::string &path)
Definition: DQMStore.cc:302
void postGlobalBeginLumi(const edm::GlobalContext &)
Definition: DQMStore.cc:1891
MonitorElement * book2DD(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2D double histogram.
Definition: DQMStore.cc:1009
std::pair< fastmatch *, QCriterion * > QTestSpec
Definition: DQMStore.h:802
std::string qualityTagString(const DQMNet::QValue &qv) const
uint32_t flags
Definition: DQMNet.h:99
LuminosityBlockID const & luminosityBlockID() const
Definition: GlobalContext.h:57
TH1 * getTH1() const
static void collate2DD(MonitorElement *me, TH2D *h, unsigned verbose)
Definition: DQMStore.cc:1458
std::vector< MonitorElement * > getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType=lat::Regexp::Wildcard) const
Definition: DQMStore.cc:1812
static const int WARNING
def replace(string, replacements)
static const uint32_t DQM_PROP_TAGGED
Definition: DQMNet.h:55
MatchingHeuristicEnum matching_
Definition: DQMStore.h:75
static const uint32_t DQM_PROP_EFFICIENCY_PLOT
Definition: DQMNet.h:64
uint32_t tag
Definition: DQMNet.h:100
bool reset_
Definition: DQMStore.h:836
const std::string * dirname
Definition: DQMNet.h:106
MonitorElement * book1DD(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:869
void initializeFrom(const edm::ParameterSet &)
Definition: DQMStore.cc:382
OpenRunDirs
Definition: DQMStore.h:87
void set_flags(::google::protobuf::uint32 value)
void disableSoftReset()
reverts action of softReset
uint32_t run
Definition: DQMNet.h:102
uint32_t moduleId_
Definition: DQMStore.h:844
const ::std::string & streamed_histo() const
QCMap qtests_
Definition: DQMStore.h:851
void forceReset()
Definition: DQMStore.cc:1868
std::mutex book_mutex_
Definition: DQMStore.h:855
MonitorElement * bookFloat(const char *name)
Book float.
Definition: DQMStore.cc:774
static std::string const input
Definition: EdmProvDump.cc:44
SaveReferenceTag
Definition: DQMStore.h:81
void Fill(long long x)
void tag(MonitorElement *me, unsigned int myTag)
Definition: DQMStore.cc:1496
MonitorElement * book2D_(const std::string &dir, const std::string &name, TH2F *h)
Book 2D histogram based on TH2F.
Definition: DQMStore.cc:944
void disableSoftReset(MonitorElement *me)
Definition: DQMStore.cc:3348
unsigned int maxNumberOfStreams() const
Definition: SystemBounds.h:43
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:2417
void saveMonitorElementToROOT(MonitorElement const &me, TFile &file)
Definition: DQMStore.cc:2386
std::vector< MonitorElement * > getAllContents(const std::string &path, uint32_t runNumber=0, uint32_t lumi=0) const
Definition: DQMStore.cc:1765
unsigned verboseQT_
Definition: DQMStore.h:835
void setEfficiencyFlag()
static const uint32_t DQM_PROP_HAS_REFERENCE
Definition: DQMNet.h:54
QTestSpecs qtestspecs_
Definition: DQMStore.h:853
double scaleFlag_
Definition: DQMStore.h:837
void deleteUnusedLumiHistograms(uint32_t run, uint32_t lumi)
Definition: DQMStore.cc:2000
fastmatch(std::string _fastString)
Definition: DQMStore.cc:137
void get_info(const dqmstorepb::ROOTFilePB_Histo &, std::string &dirname, std::string &objname, TObject **obj)
Definition: DQMStore.cc:3039
MonitorElement * bookString(const char *name, const char *value)
Book string.
Definition: DQMStore.cc:803
bool isCollate() const
Definition: DQMStore.cc:3387
void setAccumulate(bool)
uint32_t lumi
Definition: DQMNet.h:103
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
MonitorElement * bookString_(const std::string &dir, const std::string &name, const std::string &value)
Book string.
Definition: DQMStore.cc:787
void removeElement(const std::string &name)
Definition: DQMStore.cc:3183
void addProfiles(TProfile *h1, TProfile *h2, TProfile *sum, float c1, float c2)
MonitorElement * book3D_(const std::string &dir, const std::string &name, TH3F *h)
Book 3D histogram based on TH3F.
Definition: DQMStore.cc:1111
static void collateProfile2D(MonitorElement *me, TProfile2D *h, unsigned verbose)
Definition: DQMStore.cc:1482
std::string tagString() const
TH2D * getTH2D() const
void tag(MonitorElement *, unsigned int)
Definition: DQMStore.cc:286
void save(const std::string &filename, const std::string &path="", const std::string &pattern="", const std::string &rewrite="", const uint32_t run=0, const uint32_t lumi=0, SaveReferenceTag ref=SaveWithReference, int minStatus=dqm::qstatus::STATUS_OK, const std::string &fileupdate="RECREATE")
Definition: DQMStore.cc:2502
std::vector< std::shared_ptr< fireworks::OptionNode > > Options
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:2645
MonitorElement * bookInt_(const std::string &dir, const std::string &name)
Book int.
Definition: DQMStore.cc:727
MonitorElement * bookProfile_(const std::string &dir, const std::string &name, TProfile *h)
Book profile histogram based on TProfile.
Definition: DQMStore.cc:1159
double f[11][100]
uint32_t run_
Definition: DQMStore.h:843
MonitorElement * bookProfile(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, const char *option="s")
Definition: DQMStore.cc:1170
#define end
Definition: vmac.h:39
void setVerbose(unsigned level)
Definition: DQMStore.cc:509
Definition: value.py:1
void softReset(MonitorElement *me)
Definition: DQMStore.cc:3340
std::string pwd_
Definition: DQMStore.h:847
TObject * extractNextObject(TBufferFile &) const
Definition: DQMStore.cc:3031
MonitorElement * get(const std::string &path) const
get ME from full pathname (e.g. "my/long/dir/my_histo")
Definition: DQMStore.cc:1610
void Reset()
reset ME (ie. contents, errors, etc)
QAMap qalgos_
Definition: DQMStore.h:852
std::vector< MonitorElement * > getContents(const std::string &path) const
Definition: DQMStore.cc:1638
std::vector< std::string > getSubdirs() const
Definition: DQMStore.cc:1561
std::string objname
Definition: DQMNet.h:107
std::string fastString_
Definition: DQMStore.h:74
TH2F * getTH2F() const
std::vector< T * > clean
Definition: MVATrainer.cc:156
std::string qtname
Definition: DQMNet.h:93
DQMNet::CoreObject data_
const std::string getFullname() const
get full name of ME including Pathname
bool dirExists(const std::string &path) const
true if directory exists
Definition: DQMStore.cc:610
MonitorElement * findObject(const std::string &dir, const std::string &name, const uint32_t run=0, const uint32_t lumi=0, const uint32_t moduleId=0) const
Definition: DQMStore.cc:1737
bool dirExists(const std::string &path)
Definition: DQMStore.cc:332
bool load(const std::string &filename, OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2951
void saveMonitorElementToPB(MonitorElement const &me, dqmstorepb::ROOTFilePB &file)
Definition: DQMStore.cc:2616
static void collate1DD(MonitorElement *me, TH1D *h, unsigned verbose)
Definition: DQMStore.cc:1437
void tagAllContents(const std::string &path, unsigned int myTag)
Definition: DQMStore.cc:1539
demangled
Definition: symbols.py:61
void showDirStructure() const
Definition: DQMStore.cc:3367
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:274
MonitorElement * initialise(MonitorElement *me, const std::string &path)
void cd()
go to top directory (ie. root)
Definition: DQMStore.cc:522
bool containsAnyMonitorable(const std::string &path)
Definition: DQMStore.cc:328
void tagContents(const std::string &, unsigned int)
Definition: DQMStore.cc:290
std::string effLabelString() const
return label string for the monitor element tag (eg. <name>t=12345</name>)
const ::dqmstorepb::ROOTFilePB_Histo & histo(int index) const
unsigned verbose_
Definition: DQMStore.h:834
void set_size(::google::protobuf::uint32 value)
MonitorElement * book_(const std::string &dir, const std::string &name, const char *context)
Definition: DQMStore.cc:692
MonitorElement * book2S_(const std::string &dir, const std::string &name, TH2S *h)
Book 2D histogram based on TH2S.
Definition: DQMStore.cc:951
TH3F * getTH3F() const
MEMap data_
Definition: DQMStore.h:848
part
Definition: HCALResponse.h:20
void print_trace(const std::string &dir, const std::string &name)
Definition: DQMStore.cc:444
MonitorElement * book1D_(const std::string &dir, const std::string &name, TH1F *h)
Book 1D histogram based on TH1F.
Definition: DQMStore.cc:816
const std::string & pwd()
Definition: DQMStore.cc:282
int useQTestByMatch(const std::string &pattern, const std::string &qtname)
attach quality test <qc> to monitor elements matching <pattern>.
Definition: DQMStore.cc:3259
std::vector< MonitorElement * > getAllContents(const std::string &path, uint32_t runNumber=0, uint32_t lumi=0)
Definition: DQMStore.cc:296
std::string tagLabelString() const
return label string for the monitor element tag (eg. <name>t=12345</name>)
static void collate1D(MonitorElement *me, TH1F *h, unsigned verbose)
Definition: DQMStore.cc:1423
std::vector< std::string > getMEs() const
get list of (non-dir) MEs of current directory
Definition: DQMStore.cc:1584
tuple msg
Definition: mps_check.py:277
TEveGeoShape * clone(const TEveElement *element, TEveElement *parent)
Definition: eve_macros.cc:135
MonitorElement * book1DD_(const std::string &dir, const std::string &name, TH1D *h)
Book 1D histogram based on TH1D.
Definition: DQMStore.cc:830
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:344
static const Regexp s_rxmeval("<(.*)>(i|f|s|qr)=(.*)</\\1>")
void set_full_pathname(const ::std::string &value)
unsigned int readDirectory(TFile *file, bool overwrite, const std::string &path, const std::string &prepend, const std::string &curdir, OpenRunDirs stripdirs)
Definition: DQMStore.cc:2781
void setVerbose(int verbose)
probability limits for warnings, errors
Definition: QTest.h:119
void removeContents()
erase all monitoring elements in current directory (not including subfolders);
Definition: DQMStore.cc:3175
bool extract(TObject *obj, const std::string &dir, bool overwrite, bool collateHistograms)
Definition: DQMStore.cc:2042
bool forceResetOnBeginLumi_
Definition: DQMStore.h:841
#define begin
Definition: vmac.h:32
T dot(const Basic3DVector &v) const
Scalar product, or "dot" product, with a vector of same type.
void tagContents(const std::string &path, unsigned int myTag)
tag all children of folder (does NOT include subfolders)
Definition: DQMStore.cc:1527
::dqmstorepb::ROOTFilePB_Histo * add_histo()
void cloneRunHistograms(uint32_t run, uint32_t moduleId)
Definition: DQMStore.cc:1962
static std::atomic< unsigned int > counter
bool readFilePB(const std::string &filename, bool overwrite=false, const std::string &path="", const std::string &prepend="", OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:3060
void cloneLumiHistograms(uint32_t run, uint32_t lumi, uint32_t moduleId)
Definition: DQMStore.cc:1925
void useQTest(const std::string &dir, const std::string &qtname)
Definition: DQMStore.cc:3241
std::vector< std::string > getSubdirs()
Definition: DQMStore.cc:320
std::unique_ptr< std::ostream > stream_
Definition: DQMStore.h:845
std::string message
Definition: DQMNet.h:92
TH1D * getTH1D() const
bool open(const std::string &filename, bool overwrite=false, const std::string &path="", const std::string &prepend="", OpenRunDirs stripdirs=KeepRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2936
::google::protobuf::uint32 flags() const
static const int STATUS_OK
TH1S * getTH1S() const
void setAccumulate(MonitorElement *me, bool flag)
Definition: DQMStore.cc:3357
static void collate1S(MonitorElement *me, TH1S *h, unsigned verbose)
Definition: DQMStore.cc:1430
void Reset(std::vector< TH2F > &depth)
QCriterion * createQTest(const std::string &algoname, const std::string &qtname)
Definition: DQMStore.cc:3220
static bool checkBinningMatches(MonitorElement *me, TH1 *h, unsigned verbose)
Definition: DQMStore.cc:1396
dbl *** dir
Definition: mlp_gen.cc:35
void goUp()
equivalent to "cd .."
Definition: DQMStore.cc:556
void savePB(const std::string &filename, const std::string &path="", const uint32_t run=0, const uint32_t lumi=0)
Definition: DQMStore.cc:2693
MonitorElement * bookFloat_(const std::string &dir, const std::string &name)
Book float.
Definition: DQMStore.cc:757
static void collate2D(MonitorElement *me, TH2F *h, unsigned verbose)
Definition: DQMStore.cc:1444
MonitorElement * bookInt(const char *name)
Book int.
Definition: DQMStore.cc:744
MonitorElement * book2D(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2D histogram.
Definition: DQMStore.cc:965
std::vector< std::string > getMEs()
Definition: DQMStore.cc:324
long double T
float qtresult
Definition: DQMNet.h:91
std::set< std::string > dirs_
Definition: DQMStore.h:849
bool collateHistograms_
Definition: DQMStore.h:838
static const uint32_t DQM_PROP_LUMI
Definition: DQMNet.h:61
static std::string const source
Definition: EdmProvDump.cc:43
bool LSbasedMode_
Definition: DQMStore.h:840
MonitorElement * book1S(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:853
void addQReport(const DQMNet::QValue &desc, QCriterion *qc)
Add quality report, from DQMStore.
void runQTests()
Definition: DQMStore.cc:3292
void makeDirectory(const std::string &path)
Definition: DQMStore.cc:569
Kind kind() const
Get the type of the monitor element.
void reset()
Definition: DQMStore.cc:1846
def move(src, dest)
Definition: eostools.py:510
bool compare_strings(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:226
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:545
static void collate2S(MonitorElement *me, TH2S *h, unsigned verbose)
Definition: DQMStore.cc:1451
MonitorElement * book1S_(const std::string &dir, const std::string &name, TH1S *h)
Book 1D histogram based on TH1S.
Definition: DQMStore.cc:823
std::unique_ptr< lat::Regexp > regexp_
Definition: DQMStore.h:73
static const int ERROR
bool enableMultiThread_
Definition: DQMStore.h:839
void set_streamed_histo(const ::std::string &value)
static bool CheckBinLabels(const TAxis *a1, const TAxis *a2)
Check the consistency of the axis labels.
MonitorElement * bookProfile2D(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, int nchZ, double lowZ, double highZ, const char *option="s")
Definition: DQMStore.cc:1314
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:11