CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DQMStore.cc
Go to the documentation of this file.
8 #include "classlib/utils/RegexpMatch.h"
9 #include "classlib/utils/Regexp.h"
10 #include "classlib/utils/StringOps.h"
11 #include <google/protobuf/io/coded_stream.h>
12 #include <google/protobuf/io/gzip_stream.h>
13 #include <google/protobuf/io/zero_copy_stream_impl.h>
14 #include "TFile.h"
15 #include "TROOT.h"
16 #include "TKey.h"
17 #include "TClass.h"
18 #include "TSystem.h"
19 #include "TBufferFile.h"
20 #include <iterator>
21 #include <cerrno>
22 #include <boost/algorithm/string.hpp>
23 #include <fstream>
24 
51 static const std::string s_monitorDirName = "DQMData";
54 static const std::string s_referenceDirName = "Reference";
55 static const std::string s_collateDirName = "Collate";
56 static const std::string s_safe = "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# ";
57 
58 static const lat::Regexp s_rxmeval ("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$");
59 static const lat::Regexp s_rxmeqr1 ("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$");
60 static const lat::Regexp s_rxmeqr2 ("^st\\.(\\d+)\\.(.*)$");
61 static const lat::Regexp s_rxtrace ("(.*)\\((.*)\\+0x.*\\).*");
62 static const lat::Regexp s_rxpbfile (".*\\.pb$");
63 
67 static bool
69 {
70  return (ofdir.empty()
71  || (path.size() >= ofdir.size()
72  && path.compare(0, ofdir.size(), ofdir) == 0
73  && (path.size() == ofdir.size()
74  || path[ofdir.size()] == '/')));
75 }
76 
77 static void
79 {
80  clean.clear();
81  cleaned = &path;
82 
83  size_t len = path.size();
84  for ( ; len > 0 && path[len-1] == '/'; --len)
85  ;
86 
87  if (len != path.size())
88  {
89  clean = path.substr(0, len);
90  cleaned = &clean;
91  }
92 }
93 
94 static void
96 {
97  size_t slash = path.rfind('/');
98  if (slash != std::string::npos)
99  {
100  dir.append(path, 0, slash);
101  name.append(path, slash+1, std::string::npos);
102  }
103  else
104  name = path;
105 }
106 
107 static void
109 {
110  path.reserve(dir.size() + name.size() + 2);
111  path += dir;
112  if (! path.empty())
113  path += '/';
114  path += name;
115 }
116 
117 template <class T>
118 QCriterion *
120 { return new T(qtname); }
121 
122 template <class T>
123 void
125 { m[T::getAlgoName()] = &makeQCriterion<T>; }
126 
127 
129 fastmatch::fastmatch (std::string const& _fastString) :
130  fastString_ (_fastString), matching_ (UseFull)
131 {
132  try
133  {
134  regexp_ = NULL;
135  regexp_ = new lat::Regexp(fastString_, 0, lat::Regexp::Wildcard);
136  regexp_->study();
137  }
138  catch (lat::Error &e)
139  {
140  delete regexp_;
141  raiseDQMError("DQMStore", "Invalid wildcard pattern '%s' in quality"
142  " test specification", fastString_.c_str());
143  }
144 
145  // count stars ( "*" )
146  size_t starCount = 0;
147  int pos = -1;
148  while (true)
149  {
150  pos = fastString_.find("*", pos + 1 );
151  if ((size_t)pos == std::string::npos)
152  break;
153  starCount ++;
154  }
155 
156  // investigate for heuristics
157  if ((fastString_.find('"') != std::string::npos) ||
158  (fastString_.find(']') != std::string::npos) ||
159  (fastString_.find('?') != std::string::npos) ||
160  (fastString_.find('\\') != std::string::npos) ||
161  (starCount > 2))
162  {
163  // no fast version can be used
164  return;
165  }
166 
167  // match for pattern "*MyString" and "MyString*"
168  if (starCount == 1)
169  {
170  if (boost::algorithm::starts_with(fastString_, "*"))
171  {
173  fastString_.erase(0,1);
174  return;
175  }
176 
177  if (boost::algorithm::ends_with(fastString_, "*"))
178  {
180  fastString_.erase(fastString_.length()-1,1);
181  return;
182  }
183  }
184 
185  // match for pattern "*MyString*"
186  if (starCount == 2)
187  {
188  if (boost::algorithm::starts_with(fastString_, "*") &&
189  boost::algorithm::ends_with(fastString_, "*"))
190  {
191  matching_ = TwoStar;
192  fastString_.erase(0,1);
193  fastString_.erase(fastString_.size() - 1, 1);
194  return;
195  }
196  }
197 }
198 
200 {
201  if (regexp_ != NULL)
202  delete regexp_;
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  std::string::const_reverse_iterator rit_pattern = pattern.rbegin();
215  std::string::const_reverse_iterator rit_input = input.rbegin();
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  std::string::const_iterator rit_pattern = pattern.begin();
236  std::string::const_iterator rit_input = input.begin();
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 runNumber /* = 0 */,
298  uint32_t lumi /* = 0 */) {
299  return owner_->getAllContents(path, runNumber, lumi);
300 }
301 
303  return owner_->get(path);
304 }
305 
306 std::vector<std::string> DQMStore::IGetter::getSubdirs(void) {
307  return owner_->getSubdirs();
308 }
309 
310 std::vector<std::string> DQMStore::IGetter::getMEs(void) {
311  return owner_->getMEs();
312 }
313 
315  return owner_->containsAnyMonitorable(path);
316 }
317 
319  return owner_->dirExists(path);
320 }
321 
323  owner_->cd();
324 }
325 
327  owner_->cd(dir);
328 }
329 
331  owner_->setCurrentFolder(fullpath);
332 }
333 
344  uint32_t streamId,
345  uint32_t moduleId) {
346  if (verbose_ > 1)
347  std::cout << "DQMStore::mergeAndResetMEsRunSummaryCache - Merging objects from run: "
348  << run
349  << ", stream: " << streamId
350  << " module: " << moduleId << std::endl;
351 
352  if (LSbasedMode_) {
353  return;
354  }
355 
356  std::string null_str("");
357  MonitorElement proto(&null_str, null_str, run, streamId, moduleId);
358  std::set<MonitorElement>::const_iterator e = data_.end();
359  std::set<MonitorElement>::const_iterator i = data_.lower_bound(proto);
360  while (i != e) {
361  if (i->data_.run != run
362  || i->data_.streamId != streamId
363  || i->data_.moduleId != moduleId)
364  break;
365 
366  // Handle Run-based histograms only.
367  if (i->getLumiFlag() || LSbasedMode_) {
368  ++i;
369  continue;
370  }
371 
372  MonitorElement global_me(*i);
373  global_me.globalize();
374  // Since this accesses the data, the operation must be
375  // be locked.
376  std::lock_guard<std::mutex> guard(book_mutex_);
377  std::set<MonitorElement>::const_iterator me = data_.find(global_me);
378  if (me != data_.end()) {
379  if (verbose_ > 1)
380  std::cout << "Found global Object, using it --> " << me->getFullname() << std::endl;
381 
382  //don't take any action if the ME is an INT || FLOAT || STRING
383  if(me->kind() >= MonitorElement::DQM_KIND_TH1F)
384  me->getTH1()->Add(i->getTH1());
385 
386  } else {
387  if (verbose_ > 1)
388  std::cout << "No global Object found. " << std::endl;
389  std::pair<std::set<MonitorElement>::const_iterator, bool> gme;
390  gme = data_.insert(global_me);
391  assert(gme.second);
392  }
393  // TODO(rovere): eventually reset the local object and mark it as reusable??
394  ++i;
395  }
396 }
397 
399  uint32_t lumi,
400  uint32_t streamId,
401  uint32_t moduleId) {
402  if (verbose_ > 1)
403  std::cout << "DQMStore::mergeAndResetMEsLuminositySummaryCache - Merging objects from run: "
404  << run << " lumi: " << lumi
405  << ", stream: " << streamId
406  << " module: " << moduleId << std::endl;
407  std::string null_str("");
408  MonitorElement proto(&null_str, null_str, run, streamId, moduleId);
409  std::set<MonitorElement>::const_iterator e = data_.end();
410  std::set<MonitorElement>::const_iterator i = data_.lower_bound(proto);
411 
412  while (i != e) {
413  if (i->data_.run != run
414  || i->data_.streamId != streamId
415  || i->data_.moduleId != moduleId)
416  break;
417 
418  // Handle LS-based histograms only.
419  if (not (i->getLumiFlag() || LSbasedMode_)) {
420  ++i;
421  continue;
422  }
423 
424  MonitorElement global_me(*i);
425  global_me.globalize();
426  global_me.setLumi(lumi);
427  // Since this accesses the data, the operation must be
428  // be locked.
429  std::lock_guard<std::mutex> guard(book_mutex_);
430  std::set<MonitorElement>::const_iterator me = data_.find(global_me);
431  if (me != data_.end()) {
432  if (verbose_ > 1)
433  std::cout << "Found global Object, using it --> " << me->getFullname() << std::endl;
434 
435  //don't take any action if the ME is an INT || FLOAT || STRING
436  if (me->kind() >= MonitorElement::DQM_KIND_TH1F)
437  me->getTH1()->Add(i->getTH1());
438  } else {
439  if (verbose_ > 1)
440  std::cout << "No global Object found. " << std::endl;
441  std::pair<std::set<MonitorElement>::const_iterator, bool> gme;
442  gme = data_.insert(global_me);
443  assert(gme.second);
444  }
445  // make the ME reusable for the next LS
446  const_cast<MonitorElement*>(&*i)->Reset();
447  ++i;
448 
449  // check and remove the global lumi based histo belonging to the previous LSs
450  // if properly flagged as DQMNet::DQM_PROP_MARKTODELETE
451  global_me.setLumi(1);
452  std::set<MonitorElement>::const_iterator i_lumi = data_.lower_bound(global_me);
453  while (i_lumi->data_.lumi != lumi) {
454  auto temp = i_lumi++;
455  if (i_lumi->getFullname() == i->getFullname() && i_lumi->markedToDelete())
456  {
457  data_.erase(temp);
458  }
459  }
460  }
461 }
462 
465  : verbose_ (1),
466  verboseQT_ (1),
467  reset_ (false),
472  run_(0),
473  streamId_(0),
474  moduleId_(0),
475  stream_(nullptr),
476  pwd_ (""),
477  ibooker_(0),
478  igetter_(0)
479 {
480  if (!ibooker_)
481  ibooker_ = new DQMStore::IBooker(this);
482  if (!igetter_)
483  igetter_ = new DQMStore::IGetter(this);
484  initializeFrom(pset);
485 
486  if(pset.getUntrackedParameter<bool>("forceResetOnBeginRun",false)) {
488  }
489  ar.preallocateSignal_.connect([this](edm::service::SystemBounds const& iBounds) {
490  if(iBounds.maxNumberOfStreams() > 1 ) {
491  enableMultiThread_ = true;
492  }
493  });
494  if(pset.getUntrackedParameter<bool>("forceResetOnBeginLumi",false) && enableMultiThread_ == false) {
495  forceResetOnBeginLumi_ = true;
497  }
498 }
499 
501  : verbose_ (1),
502  verboseQT_ (1),
503  reset_ (false),
504  collateHistograms_ (false),
505  enableMultiThread_(false),
506  readSelectedDirectory_ (""),
507  run_(0),
508  streamId_(0),
509  moduleId_(0),
510  stream_(nullptr),
511  pwd_ (""),
512  ibooker_(0),
513  igetter_(0)
514 {
515  if (!ibooker_)
516  ibooker_ = new DQMStore::IBooker(this);
517  if (!igetter_)
518  igetter_ = new DQMStore::IGetter(this);
519  initializeFrom(pset);
520 }
521 
523 {
524  for (QCMap::iterator i = qtests_.begin(), e = qtests_.end(); i != e; ++i)
525  delete i->second;
526 
527  for (QTestSpecs::iterator i = qtestspecs_.begin(), e = qtestspecs_.end(); i != e; ++i)
528  delete i->first;
529 
530  if (stream_)
531  stream_->close();
532  delete stream_;
533 }
534 
535 void
537  makeDirectory("");
538  reset();
539 
540  // set steerable parameters
541  verbose_ = pset.getUntrackedParameter<int>("verbose", 0);
542  if (verbose_ > 0)
543  std::cout << "DQMStore: verbosity set to " << verbose_ << std::endl;
544 
545  verboseQT_ = pset.getUntrackedParameter<int>("verboseQT", 0);
546  if (verbose_ > 0)
547  std::cout << "DQMStore: QTest verbosity set to " << verboseQT_ << std::endl;
548 
549  collateHistograms_ = pset.getUntrackedParameter<bool>("collateHistograms", false);
550  if (collateHistograms_)
551  std::cout << "DQMStore: histogram collation is enabled\n";
552 
553  enableMultiThread_ = pset.getUntrackedParameter<bool>("enableMultiThread", false);
554  if (enableMultiThread_)
555  std::cout << "DQMStore: MultiThread option is enabled\n";
556 
557  LSbasedMode_ = pset.getUntrackedParameter<bool>("LSbasedMode", false);
558  if (LSbasedMode_)
559  std::cout << "DQMStore: LSbasedMode option is enabled\n";
560 
561  std::string ref = pset.getUntrackedParameter<std::string>("referenceFileName", "");
562  if (! ref.empty())
563  {
564  std::cout << "DQMStore: using reference file '" << ref << "'\n";
565  readFile(ref, true, "", s_referenceDirName, StripRunDirs, false);
566  }
567 
568  initQCriterion<Comp2RefChi2>(qalgos_);
569  initQCriterion<Comp2RefKolmogorov>(qalgos_);
570  initQCriterion<ContentsXRange>(qalgos_);
571  initQCriterion<ContentsYRange>(qalgos_);
572  initQCriterion<MeanWithinExpected>(qalgos_);
573  initQCriterion<Comp2RefEqualH>(qalgos_);
574  initQCriterion<DeadChannel>(qalgos_);
575  initQCriterion<NoisyChannel>(qalgos_);
576  initQCriterion<ContentsWithinExpected>(qalgos_);
577  initQCriterion<CompareToMedian>(qalgos_);
578  initQCriterion<CompareLastFilledBin>(qalgos_);
579  initQCriterion<CheckVariance>(qalgos_);
580 
581  scaleFlag_ = pset.getUntrackedParameter<double>("ScalingFlag", 0.0);
582  if (verbose_ > 0)
583  std::cout << "DQMStore: Scaling Flag set to " << scaleFlag_ << std::endl;
584 }
585 
586 /* Generic method to do a backtrace and print it to stdout. It is
587  customised to properly get the routine that called the booking of the
588  histograms, which, following the usual stack, is at position 4. The
589  name of the calling function is properly demangled and the original
590  shared library including this function is also printed. For a more
591  detailed explanation of the routines involved, see here:
592  http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
593  http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html.*/
594 
595 void
597 {
598  // the access to the member stream_ is implicitely protected against
599  // concurrency problems because the print_trace method is always called behind
600  // a lock (see bookTransaction).
601  if (!stream_)
602  stream_ = new std::ofstream("histogramBookingBT.log");
603 
604  void *array[10];
605  size_t size;
606  char **strings;
607  int r=0;
608  lat::RegexpMatch m;
609  m.reset();
610 
611  size = backtrace (array, 10);
612  strings = backtrace_symbols (array, size);
613 
614  if ((size > 4)
615  &&s_rxtrace.match(strings[4], 0, 0, &m))
616  {
617  char * demangled = abi::__cxa_demangle(m.matchString(strings[4], 2).c_str(), 0, 0, &r);
618  *stream_ << "\"" << dir << "/"
619  << name << "\" "
620  << (r ? m.matchString(strings[4], 2) : demangled) << " "
621  << m.matchString(strings[4], 1) << "\n";
622  free(demangled);
623  }
624  else
625  *stream_ << "Skipping "<< dir << "/" << name
626  << " with stack size " << size << "\n";
627  /* In this case print the full stack trace, up to main or to the
628  * maximum stack size, i.e. 10. */
629  if (verbose_ > 4)
630  {
631  size_t i;
632  m.reset();
633 
634  for (i = 0; i < size; i++)
635  if (s_rxtrace.match(strings[i], 0, 0, &m))
636  {
637  char * demangled = abi::__cxa_demangle(m.matchString(strings[i], 2).c_str(), 0, 0, &r);
638  *stream_ << "\t\t" << i << "/" << size << " "
639  << (r ? m.matchString(strings[i], 2) : demangled) << " "
640  << m.matchString(strings[i], 1) << std::endl;
641  free (demangled);
642  }
643  }
644  free (strings);
645 }
646 
651 void
652 DQMStore::setVerbose(unsigned /* level */)
653 { return; }
654 
659 const std::string &
660 DQMStore::pwd(void) const
661 { return pwd_; }
662 
664 void
666 { setCurrentFolder(""); }
667 
669 void
670 DQMStore::cd(const std::string &subdir)
671 {
673  const std::string *cleaned = 0;
674  cleanTrailingSlashes(subdir, clean, cleaned);
675 
676  if (! dirExists(*cleaned))
677  raiseDQMError("DQMStore", "Cannot 'cd' into non-existent directory '%s'",
678  cleaned->c_str());
679 
680  setCurrentFolder(*cleaned);
681 }
682 
687 void
689 {
691  const std::string *cleaned = 0;
692  cleanTrailingSlashes(fullpath, clean, cleaned);
693  makeDirectory(*cleaned);
694  pwd_ = *cleaned;
695 }
696 
698 void
700 {
701  size_t pos = pwd_.rfind('/');
702  if (pos == std::string::npos)
703  setCurrentFolder("");
704  else
705  setCurrentFolder(pwd_.substr(0, pos));
706 }
707 
708 // -------------------------------------------------------------------
711 void
713 {
714  std::string prev;
715  std::string subdir;
717  prev.reserve(path.size());
718  subdir.reserve(path.size());
719  name.reserve(path.size());
720  size_t prevname = 0;
721  size_t slash = 0;
722 
723  while (true)
724  {
725  // Create this subdirectory component.
726  subdir.clear();
727  subdir.append(path, 0, slash);
728  name.clear();
729  name.append(subdir, prevname, std::string::npos);
730  if (! prev.empty() && findObject(prev, name))
731  raiseDQMError("DQMStore", "Attempt to create subdirectory '%s'"
732  " which already exists as a monitor element",
733  subdir.c_str());
734 
735  if (! dirs_.count(subdir))
736  dirs_.insert(subdir);
737 
738  // Stop if we've reached the end (including possibly a trailing slash).
739  if (slash+1 >= path.size())
740  break;
741 
742  // Find the next slash, making sure we progress. If reach the end,
743  // process the last path component; the next loop round will terminate.
744  prevname = slash ? slash+1 : slash;
745  prev = subdir;
746  if ((slash = path.find('/', ++slash)) == std::string::npos)
747  slash = path.size();
748  }
749 }
750 
752 bool
754 { return dirs_.count(path) > 0; }
755 
759 template <class HISTO, class COLLATE>
762  const char *context, int kind,
763  HISTO *h, COLLATE collate)
764 {
765  assert(name.find('/') == std::string::npos);
766  if (verbose_ > 3)
767  print_trace(dir, name);
769  mergePath(path, dir, name);
770 
771  // Put us in charge of h.
772  h->SetDirectory(0);
773 
774  // Check if the request monitor element already exists.
775  MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_);
776  if (me)
777  {
778  if (collateHistograms_)
779  {
780  collate(me, h, verbose_);
781  delete h;
782  return me;
783  }
784  else
785  {
786  if (verbose_ > 1)
787  std::cout << "DQMStore: "
788  << context << ": monitor element '"
789  << path << "' already exists, collating" << std::endl;
790  me->Reset();
791  collate(me, h, verbose_);
792  delete h;
793  return me;
794  }
795  }
796  else
797  {
798  // Create and initialise core object.
799  assert(dirs_.count(dir));
800  MonitorElement proto(&*dirs_.find(dir), name, run_, streamId_, moduleId_);
801  me = const_cast<MonitorElement &>(*data_.insert(proto).first)
803 
804  // Initialise quality test information.
805  QTestSpecs::iterator qi = qtestspecs_.begin();
806  QTestSpecs::iterator qe = qtestspecs_.end();
807  for ( ; qi != qe; ++qi)
808  {
809  if ( qi->first->match(path) )
810  me->addQReport(qi->second);
811  }
812 
813  // Assign reference if we have one.
814  std::string refdir;
815  refdir.reserve(s_referenceDirName.size() + dir.size() + 2);
816  refdir += s_referenceDirName;
817  refdir += '/';
818  refdir += dir;
819 
820  if (findObject(refdir, name))
821  {
822  me->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
823  }
824  // Return the monitor element.
825  return me;
826  }
827 }
828 
831  const std::string &name,
832  const char *context)
833 {
834  assert(name.find('/') == std::string::npos);
835  if (verbose_ > 3)
836  print_trace(dir, name);
837 
838  // Check if the request monitor element already exists.
839  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
840  {
841  if (verbose_ > 1)
842  {
844  mergePath(path, dir, name);
845 
846  std::cout << "DQMStore: "
847  << context << ": monitor element '"
848  << path << "' already exists, resetting" << std::endl;
849  }
850  me->Reset();
851  return me;
852  }
853  else
854  {
855  // Create it and return for initialisation.
856  assert(dirs_.count(dir));
857  MonitorElement proto(&*dirs_.find(dir), name, run_, streamId_, moduleId_);
858  return &const_cast<MonitorElement &>(*data_.insert(proto).first);
859  }
860 }
861 
862 // -------------------------------------------------------------------
866 {
867  if (collateHistograms_)
868  {
869  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
870  {
871  me->Fill(0);
872  return me;
873  }
874  }
875 
876  return book(dir, name, "bookInt")
878 }
879 
883 { return bookInt(pwd_, name); }
884 
888 {
889  return bookInt(pwd_, name);
890 }
891 
892 // -------------------------------------------------------------------
896 {
897  if (collateHistograms_)
898  {
899  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
900  {
901  me->Fill(0.);
902  return me;
903  }
904  }
905 
906  return book(dir, name, "bookFloat")
908 }
909 
913 { return bookFloat(pwd_, name); }
914 
918 {
919  return bookFloat(pwd_, name);
920 }
921 
922 // -------------------------------------------------------------------
926  const std::string &name,
927  const std::string &value)
928 {
929  if (collateHistograms_)
930  {
931  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
932  return me;
933  }
934 
935  return book(dir, name, "bookString")
937 }
938 
941 DQMStore::bookString(const char *name, const char *value)
942 { return bookString(pwd_, name, value); }
943 
947 {
948  return bookString(pwd_, name, value);
949 }
950 
951 // -------------------------------------------------------------------
955 {
956  return book(dir, name, "book1D", MonitorElement::DQM_KIND_TH1F, h, collate1D);
957 }
958 
962 {
963  return book(dir, name, "book1S", MonitorElement::DQM_KIND_TH1S, h, collate1S);
964 }
965 
969 {
970  return book(dir, name, "book1DD", MonitorElement::DQM_KIND_TH1D, h, collate1DD);
971 }
972 
975 DQMStore::book1D(const char *name, const char *title,
976  int nchX, double lowX, double highX)
977 {
978  return book1D(pwd_, name, new TH1F(name, title, nchX, lowX, highX));
979 }
980 
984  int nchX, double lowX, double highX)
985 {
986  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, lowX, highX));
987 }
988 
991 DQMStore::book1S(const char *name, const char *title,
992  int nchX, double lowX, double highX)
993 {
994  return book1S(pwd_, name, new TH1S(name, title, nchX, lowX, highX));
995 }
996 
1000  int nchX, double lowX, double highX)
1001 {
1002  return book1S(pwd_, name, new TH1S(name.c_str(), title.c_str(), nchX, lowX, highX));
1003 }
1004 
1007 DQMStore::book1DD(const char *name, const char *title,
1008  int nchX, double lowX, double highX)
1009 {
1010  return book1DD(pwd_, name, new TH1D(name, title, nchX, lowX, highX));
1011 }
1012 
1016  int nchX, double lowX, double highX)
1017 {
1018  return book1DD(pwd_, name, new TH1D(name.c_str(), title.c_str(), nchX, lowX, highX));
1019 }
1020 
1023 DQMStore::book1D(const char *name, const char *title,
1024  int nchX, const float *xbinsize)
1025 {
1026  return book1D(pwd_, name, new TH1F(name, title, nchX, xbinsize));
1027 }
1028 
1032  int nchX, const float *xbinsize)
1033 {
1034  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, xbinsize));
1035 }
1036 
1039 DQMStore::book1D(const char *name, TH1F *source)
1040 {
1041  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name)));
1042 }
1043 
1047 {
1048  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name.c_str())));
1049 }
1050 
1053 DQMStore::book1S(const char *name, TH1S *source)
1054 {
1055  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name)));
1056 }
1057 
1061 {
1062  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name.c_str())));
1063 }
1064 
1067 DQMStore::book1DD(const char *name, TH1D *source)
1068 {
1069  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name)));
1070 }
1071 
1075 {
1076  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name.c_str())));
1077 }
1078 
1079 // -------------------------------------------------------------------
1083 {
1084  return book(dir, name, "book2D", MonitorElement::DQM_KIND_TH2F, h, collate2D);
1085 }
1086 
1090 {
1091  return book(dir, name, "book2S", MonitorElement::DQM_KIND_TH2S, h, collate2S);
1092 }
1093 
1097 {
1098  return book(dir, name, "book2DD", MonitorElement::DQM_KIND_TH2D, h, collate2DD);
1099 }
1100 
1103 DQMStore::book2D(const char *name, const char *title,
1104  int nchX, double lowX, double highX,
1105  int nchY, double lowY, double highY)
1106 {
1107  return book2D(pwd_, name, new TH2F(name, title,
1108  nchX, lowX, highX,
1109  nchY, lowY, highY));
1110 }
1111 
1115  int nchX, double lowX, double highX,
1116  int nchY, double lowY, double highY)
1117 {
1118  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
1119  nchX, lowX, highX,
1120  nchY, lowY, highY));
1121 }
1122 
1125 DQMStore::book2S(const char *name, const char *title,
1126  int nchX, double lowX, double highX,
1127  int nchY, double lowY, double highY)
1128 {
1129  return book2S(pwd_, name, new TH2S(name, title,
1130  nchX, lowX, highX,
1131  nchY, lowY, highY));
1132 }
1133 
1137  int nchX, double lowX, double highX,
1138  int nchY, double lowY, double highY)
1139 {
1140  return book2S(pwd_, name, new TH2S(name.c_str(), title.c_str(),
1141  nchX, lowX, highX,
1142  nchY, lowY, highY));
1143 }
1144 
1147 DQMStore::book2DD(const char *name, const char *title,
1148  int nchX, double lowX, double highX,
1149  int nchY, double lowY, double highY)
1150 {
1151  return book2DD(pwd_, name, new TH2D(name, title,
1152  nchX, lowX, highX,
1153  nchY, lowY, highY));
1154 }
1155 
1159  int nchX, double lowX, double highX,
1160  int nchY, double lowY, double highY)
1161 {
1162  return book2DD(pwd_, name, new TH2D(name.c_str(), title.c_str(),
1163  nchX, lowX, highX,
1164  nchY, lowY, highY));
1165 }
1166 
1169 DQMStore::book2D(const char *name, const char *title,
1170  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1171 {
1172  return book2D(pwd_, name, new TH2F(name, title,
1173  nchX, xbinsize, nchY, ybinsize));
1174 }
1175 
1179  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1180 {
1181  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
1182  nchX, xbinsize, nchY, ybinsize));
1183 }
1184 
1187 DQMStore::book2D(const char *name, TH2F *source)
1188 {
1189  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name)));
1190 }
1191 
1195 {
1196  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name.c_str())));
1197 }
1198 
1201 DQMStore::book2S(const char *name, TH2S *source)
1202 {
1203  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name)));
1204 }
1205 
1209 {
1210  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name.c_str())));
1211 }
1212 
1215 DQMStore::book2DD(const char *name, TH2D *source)
1216 {
1217  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name)));
1218 }
1219 
1223 {
1224  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name.c_str())));
1225 }
1226 
1227 // -------------------------------------------------------------------
1231 {
1232  return book(dir, name, "book3D", MonitorElement::DQM_KIND_TH3F, h, collate3D);
1233 }
1234 
1237 DQMStore::book3D(const char *name, const char *title,
1238  int nchX, double lowX, double highX,
1239  int nchY, double lowY, double highY,
1240  int nchZ, double lowZ, double highZ)
1241 {
1242  return book3D(pwd_, name, new TH3F(name, title,
1243  nchX, lowX, highX,
1244  nchY, lowY, highY,
1245  nchZ, lowZ, highZ));
1246 }
1247 
1251  int nchX, double lowX, double highX,
1252  int nchY, double lowY, double highY,
1253  int nchZ, double lowZ, double highZ)
1254 {
1255  return book3D(pwd_, name, new TH3F(name.c_str(), title.c_str(),
1256  nchX, lowX, highX,
1257  nchY, lowY, highY,
1258  nchZ, lowZ, highZ));
1259 }
1260 
1263 DQMStore::book3D(const char *name, TH3F *source)
1264 {
1265  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name)));
1266 }
1267 
1271 {
1272  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name.c_str())));
1273 }
1274 
1275 // -------------------------------------------------------------------
1279 {
1280  return book(dir, name, "bookProfile",
1282  h, collateProfile);
1283 }
1284 
1289 DQMStore::bookProfile(const char *name, const char *title,
1290  int nchX, double lowX, double highX,
1291  int /* nchY */, double lowY, double highY,
1292  const char *option /* = "s" */)
1293 {
1294  return bookProfile(pwd_, name, new TProfile(name, title,
1295  nchX, lowX, highX,
1296  lowY, highY,
1297  option));
1298 }
1299 
1305  int nchX, double lowX, double highX,
1306  int /* nchY */, double lowY, double highY,
1307  const char *option /* = "s" */)
1308 {
1309  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1310  nchX, lowX, highX,
1311  lowY, highY,
1312  option));
1313 }
1314 
1319 DQMStore::bookProfile(const char *name, const char *title,
1320  int nchX, double lowX, double highX,
1321  double lowY, double highY,
1322  const char *option /* = "s" */)
1323 {
1324  return bookProfile(pwd_, name, new TProfile(name, title,
1325  nchX, lowX, highX,
1326  lowY, highY,
1327  option));
1328 }
1329 
1335  int nchX, double lowX, double highX,
1336  double lowY, double highY,
1337  const char *option /* = "s" */)
1338 {
1339  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1340  nchX, lowX, highX,
1341  lowY, highY,
1342  option));
1343 }
1344 
1349 DQMStore::bookProfile(const char *name, const char *title,
1350  int nchX, const double *xbinsize,
1351  int /* nchY */, double lowY, double highY,
1352  const char *option /* = "s" */)
1353 {
1354  return bookProfile(pwd_, name, new TProfile(name, title,
1355  nchX, xbinsize,
1356  lowY, highY,
1357  option));
1358 }
1359 
1365  int nchX, const double *xbinsize,
1366  int /* nchY */, double lowY, double highY,
1367  const char *option /* = "s" */)
1368 {
1369  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1370  nchX, xbinsize,
1371  lowY, highY,
1372  option));
1373 }
1374 
1379 DQMStore::bookProfile(const char *name, const char *title,
1380  int nchX, const double *xbinsize,
1381  double lowY, double highY,
1382  const char *option /* = "s" */)
1383 {
1384  return bookProfile(pwd_, name, new TProfile(name, title,
1385  nchX, xbinsize,
1386  lowY, highY,
1387  option));
1388 }
1389 
1395  int nchX, const double *xbinsize,
1396  double lowY, double highY,
1397  const char *option /* = "s" */)
1398 {
1399  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1400  nchX, xbinsize,
1401  lowY, highY,
1402  option));
1403 }
1404 
1407 DQMStore::bookProfile(const char *name, TProfile *source)
1408 {
1409  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name)));
1410 }
1411 
1415 {
1416  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name.c_str())));
1417 }
1418 
1419 // -------------------------------------------------------------------
1423 {
1424  return book(dir, name, "bookProfile2D",
1426  h, collateProfile2D);
1427 }
1428 
1433 DQMStore::bookProfile2D(const char *name, const char *title,
1434  int nchX, double lowX, double highX,
1435  int nchY, double lowY, double highY,
1436  int /* nchZ */, double lowZ, double highZ,
1437  const char *option /* = "s" */)
1438 {
1439  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1440  nchX, lowX, highX,
1441  nchY, lowY, highY,
1442  lowZ, highZ,
1443  option));
1444 }
1445 
1451  int nchX, double lowX, double highX,
1452  int nchY, double lowY, double highY,
1453  int /* nchZ */, double lowZ, double highZ,
1454  const char *option /* = "s" */)
1455 {
1456  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1457  nchX, lowX, highX,
1458  nchY, lowY, highY,
1459  lowZ, highZ,
1460  option));
1461 }
1462 
1467 DQMStore::bookProfile2D(const char *name, const char *title,
1468  int nchX, double lowX, double highX,
1469  int nchY, double lowY, double highY,
1470  double lowZ, double highZ,
1471  const char *option /* = "s" */)
1472 {
1473  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1474  nchX, lowX, highX,
1475  nchY, lowY, highY,
1476  lowZ, highZ,
1477  option));
1478 }
1479 
1485  int nchX, double lowX, double highX,
1486  int nchY, double lowY, double highY,
1487  double lowZ, double highZ,
1488  const char *option /* = "s" */)
1489 {
1490  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1491  nchX, lowX, highX,
1492  nchY, lowY, highY,
1493  lowZ, highZ,
1494  option));
1495 }
1496 
1499 DQMStore::bookProfile2D(const char *name, TProfile2D *source)
1500 {
1501  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name)));
1502 }
1503 
1507 {
1508  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name.c_str())));
1509 }
1510 
1514 bool
1516 {
1517  if (me->getTH1()->GetNbinsX() != h->GetNbinsX()
1518  || me->getTH1()->GetNbinsY() != h->GetNbinsY()
1519  || me->getTH1()->GetNbinsZ() != h->GetNbinsZ()
1520  || me->getTH1()->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin()
1521  || me->getTH1()->GetYaxis()->GetXmin() != h->GetYaxis()->GetXmin()
1522  || me->getTH1()->GetZaxis()->GetXmin() != h->GetZaxis()->GetXmin()
1523  || me->getTH1()->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax()
1524  || me->getTH1()->GetYaxis()->GetXmax() != h->GetYaxis()->GetXmax()
1525  || me->getTH1()->GetZaxis()->GetXmax() != h->GetZaxis()->GetXmax()
1526  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetXaxis(),(TAxis*)h->GetXaxis())
1527  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetYaxis(),(TAxis*)h->GetYaxis())
1528  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetZaxis(),(TAxis*)h->GetZaxis()) )
1529  {
1530  if(verbose > 0)
1531  std::cout << "*** DQMStore: WARNING:"
1532  << "checkBinningMatches: different binning - cannot add object '"
1533  << h->GetName() << "' of type "
1534  << h->IsA()->GetName() << " to existing ME: '"
1535  << me->getFullname() << "'\n";
1536  return false;
1537  }
1538  return true;
1539 }
1540 
1541 void
1543 {
1544  if (checkBinningMatches(me,h,verbose))
1545  me->getTH1F()->Add(h);
1546 }
1547 
1548 void
1550 {
1551  if (checkBinningMatches(me,h,verbose))
1552  me->getTH1S()->Add(h);
1553 }
1554 
1555 void
1557 {
1558  if (checkBinningMatches(me,h,verbose))
1559  me->getTH1D()->Add(h);
1560 }
1561 
1562 void
1564 {
1565  if (checkBinningMatches(me,h,verbose))
1566  me->getTH2F()->Add(h);
1567 }
1568 
1569 void
1571 {
1572  if (checkBinningMatches(me,h,verbose))
1573  me->getTH2S()->Add(h);
1574 }
1575 
1576 void
1578 {
1579  if (checkBinningMatches(me,h,verbose))
1580  me->getTH2D()->Add(h);
1581 }
1582 
1583 void
1585 {
1586  if (checkBinningMatches(me,h,verbose))
1587  me->getTH3F()->Add(h);
1588 }
1589 
1590 void
1592 {
1593  if (checkBinningMatches(me,h,verbose))
1594  {
1595  TProfile *meh = me->getTProfile();
1596  me->addProfiles(h, meh, meh, 1, 1);
1597  }
1598 }
1599 
1600 void
1602 {
1603  if (checkBinningMatches(me,h,verbose))
1604  {
1605  TProfile2D *meh = me->getTProfile2D();
1606  me->addProfiles(h, meh, meh, 1, 1);
1607  }
1608 }
1609 
1614 void
1615 DQMStore::tag(MonitorElement *me, unsigned int myTag)
1616 {
1617  if (! myTag)
1618  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1619  " with a zero tag", me->getFullname().c_str());
1620  if ((me->data_.flags & DQMNet::DQM_PROP_TAGGED) && myTag != me->data_.tag)
1621  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1622  " twice with multiple tags", me->getFullname().c_str());
1623 
1624  me->data_.tag = myTag;
1626 }
1627 
1629 void
1630 DQMStore::tag(const std::string &path, unsigned int myTag)
1631 {
1632  std::string dir;
1633  std::string name;
1634  splitPath(dir, name, path);
1635 
1636  if (MonitorElement *me = findObject(dir, name))
1637  tag(me, myTag);
1638  else
1639  raiseDQMError("DQMStore", "Attempt to tag non-existent monitor element"
1640  " '%s' with tag %u", path.c_str(), myTag);
1641 
1642 }
1643 
1645 void
1646 DQMStore::tagContents(const std::string &path, unsigned int myTag)
1647 {
1648  MonitorElement proto(&path, std::string());
1649  MEMap::iterator e = data_.end();
1650  MEMap::iterator i = data_.lower_bound(proto);
1651  for ( ; i != e && path == *i->data_.dirname; ++i)
1652  tag(const_cast<MonitorElement *>(&*i), myTag);
1653 }
1654 
1657 void
1658 DQMStore::tagAllContents(const std::string &path, unsigned int myTag)
1659 {
1661  const std::string *cleaned = 0;
1662  cleanTrailingSlashes(path, clean, cleaned);
1663  MonitorElement proto(cleaned, std::string());
1664 
1665  // FIXME: WILDCARDS? Old one supported them, but nobody seemed to use them.
1666  MEMap::iterator e = data_.end();
1667  MEMap::iterator i = data_.lower_bound(proto);
1668  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
1669  {
1670  tag(const_cast<MonitorElement *>(&*i), myTag);
1671  ++i;
1672  }
1673 }
1674 
1679 std::vector<std::string>
1681 {
1682  std::vector<std::string> result;
1683  std::set<std::string>::const_iterator e = dirs_.end();
1684  std::set<std::string>::const_iterator i = dirs_.find(pwd_);
1685 
1686  // If we didn't find current directory, the tree is empty, so quit.
1687  if (i == e)
1688  return result;
1689 
1690  // Skip the current directory and then start looking for immediate
1691  // subdirectories in the dirs_ list. Stop when we are no longer in
1692  // (direct or indirect) subdirectories of pwd_. Note that we don't
1693  // "know" which order the set will sort A/B, A/B/C and A/D.
1694  while (++i != e && isSubdirectory(pwd_, *i))
1695  if (i->find('/', pwd_.size()+1) == std::string::npos)
1696  result.push_back(*i);
1697 
1698  return result;
1699 }
1700 
1702 std::vector<std::string>
1703 DQMStore::getMEs(void) const
1704 {
1705  MonitorElement proto(&pwd_, std::string());
1706  std::vector<std::string> result;
1707  MEMap::const_iterator e = data_.end();
1708  MEMap::const_iterator i = data_.lower_bound(proto);
1709  for ( ; i != e && isSubdirectory(pwd_, *i->data_.dirname); ++i)
1710  if (pwd_ == *i->data_.dirname)
1711  result.push_back(i->getName());
1712 
1713  return result;
1714 }
1715 
1718 bool
1720 {
1721  MonitorElement proto(&path, std::string());
1722  MEMap::const_iterator e = data_.end();
1723  MEMap::const_iterator i = data_.lower_bound(proto);
1724  return (i != e && isSubdirectory(path, *i->data_.dirname));
1725 }
1726 
1730 {
1731  std::string dir;
1732  std::string name;
1733  splitPath(dir, name, path);
1734  MonitorElement proto(&dir, name);
1735  MEMap::const_iterator mepos = data_.find(proto);
1736  return (mepos == data_.end() ? 0
1737  : const_cast<MonitorElement *>(&*mepos));
1738 }
1739 
1741 std::vector<MonitorElement *>
1742 DQMStore::get(unsigned int tag) const
1743 {
1744  // FIXME: Use reverse map [tag -> path] / [tag -> dir]?
1745  std::vector<MonitorElement *> result;
1746  for (MEMap::const_iterator i = data_.begin(), e = data_.end(); i != e; ++i)
1747  {
1748  const MonitorElement &me = *i;
1749  if ((me.data_.flags & DQMNet::DQM_PROP_TAGGED) && me.data_.tag == tag)
1750  result.push_back(const_cast<MonitorElement *>(&me));
1751  }
1752  return result;
1753 }
1754 
1757 std::vector<MonitorElement *>
1759 {
1761  const std::string *cleaned = 0;
1762  cleanTrailingSlashes(path, clean, cleaned);
1763  MonitorElement proto(cleaned, std::string());
1764 
1765  std::vector<MonitorElement *> result;
1766  MEMap::const_iterator e = data_.end();
1767  MEMap::const_iterator i = data_.lower_bound(proto);
1768  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1769  if (*cleaned == *i->data_.dirname)
1770  result.push_back(const_cast<MonitorElement *>(&*i));
1771 
1772  return result;
1773 }
1774 
1776 std::vector<MonitorElement *>
1777 DQMStore::getContents(const std::string &path, unsigned int tag) const
1778 {
1780  const std::string *cleaned = 0;
1781  cleanTrailingSlashes(path, clean, cleaned);
1782  MonitorElement proto(cleaned, std::string());
1783 
1784  std::vector<MonitorElement *> result;
1785  MEMap::const_iterator e = data_.end();
1786  MEMap::const_iterator i = data_.lower_bound(proto);
1787  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1788  if (*cleaned == *i->data_.dirname
1789  && (i->data_.flags & DQMNet::DQM_PROP_TAGGED)
1790  && i->data_.tag == tag)
1791  result.push_back(const_cast<MonitorElement *>(&*i));
1792 
1793  return result;
1794 }
1795 
1800 void
1801 DQMStore::getContents(std::vector<std::string> &into, bool showContents /* = true */) const
1802 {
1803  into.clear();
1804  into.reserve(dirs_.size());
1805 
1806  MEMap::const_iterator me = data_.end();
1807  std::set<std::string>::const_iterator di = dirs_.begin();
1808  std::set<std::string>::const_iterator de = dirs_.end();
1809  for ( ; di != de; ++di)
1810  {
1811  MonitorElement proto(&*di, std::string());
1812  MEMap::const_iterator mi = data_.lower_bound(proto);
1813  MEMap::const_iterator m = mi;
1814  size_t sz = di->size() + 2;
1815  size_t nfound = 0;
1816  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1817  if (*di == *m->data_.dirname)
1818  {
1819  sz += m->data_.objname.size() + 1;
1820  ++nfound;
1821  }
1822 
1823  if (! nfound)
1824  continue;
1825 
1826  std::vector<std::string>::iterator istr
1827  = into.insert(into.end(), std::string());
1828 
1829  if (showContents)
1830  {
1831  istr->reserve(sz);
1832 
1833  *istr += *di;
1834  *istr += ':';
1835  for (sz = 0; mi != m; ++mi)
1836  {
1837  if (*di != *mi->data_.dirname)
1838  continue;
1839 
1840  if (sz > 0)
1841  *istr += ',';
1842 
1843  *istr += mi->data_.objname;
1844  ++sz;
1845  }
1846  }
1847  else
1848  {
1849  istr->reserve(di->size() + 2);
1850  *istr += *di;
1851  *istr += ':';
1852  }
1853  }
1854 }
1855 
1860  const std::string &name,
1861  const uint32_t run /* = 0 */,
1862  const uint32_t lumi /* = 0 */,
1863  const uint32_t streamId /* = 0 */,
1864  const uint32_t moduleId /* = 0 */) const
1865 {
1866  if (dir.find_first_not_of(s_safe) != std::string::npos)
1867  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1868  " unacceptable characters", dir.c_str());
1869  if (name.find_first_not_of(s_safe) != std::string::npos)
1870  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1871  " unacceptable characters", name.c_str());
1872 
1873  MonitorElement proto;
1874  proto.data_.dirname = &dir;
1875  proto.data_.objname = name;
1876  proto.data_.run = run;
1877  proto.data_.lumi = lumi;
1878  proto.data_.streamId = streamId;
1879  proto.data_.moduleId = moduleId;
1880 
1881  MEMap::const_iterator mepos = data_.find(proto);
1882  return (mepos == data_.end() ? 0
1883  : const_cast<MonitorElement *>(&*mepos));
1884 }
1885 
1888 void
1889 DQMStore::getAllTags(std::vector<std::string> &into) const
1890 {
1891  into.clear();
1892  into.reserve(dirs_.size());
1893 
1894  MEMap::const_iterator me = data_.end();
1895  std::set<std::string>::const_iterator di = dirs_.begin();
1896  std::set<std::string>::const_iterator de = dirs_.end();
1897  char tagbuf[32]; // more than enough for '/' and up to 10 digits
1898 
1899  for ( ; di != de; ++di)
1900  {
1901  MonitorElement proto(&*di, std::string());
1902  MEMap::const_iterator mi = data_.lower_bound(proto);
1903  MEMap::const_iterator m = mi;
1904  size_t sz = di->size() + 2;
1905  size_t nfound = 0;
1906  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1907  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1908  {
1909  // the tags count for '/' + up to 10 digits, otherwise ',' + ME name
1910  sz += 1 + m->data_.objname.size() + 11;
1911  ++nfound;
1912  }
1913 
1914  if (! nfound)
1915  continue;
1916 
1917  std::vector<std::string>::iterator istr
1918  = into.insert(into.end(), std::string());
1919 
1920  istr->reserve(sz);
1921 
1922  *istr += *di;
1923  *istr += ':';
1924  for (sz = 0; mi != m; ++mi)
1925  {
1926  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1927  {
1928  sprintf(tagbuf, "/%u", mi->data_.tag);
1929  if (sz > 0)
1930  *istr += ',';
1931  *istr += m->data_.objname;
1932  *istr += tagbuf;
1933  ++sz;
1934  }
1935  }
1936  }
1937 }
1938 
1941 std::vector<MonitorElement*>
1943  uint32_t runNumber /* = 0 */,
1944  uint32_t lumi /* = 0 */) const
1945 {
1947  const std::string *cleaned = 0;
1948  cleanTrailingSlashes(path, clean, cleaned);
1949  MonitorElement proto(cleaned, std::string(), runNumber);
1950  proto.setLumi(lumi);
1951 
1952  std::vector<MonitorElement *> result;
1953  MEMap::const_iterator e = data_.end();
1954  MEMap::const_iterator i = data_.lower_bound(proto);
1955  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i) {
1956  if (runNumber != 0) {
1957  if (i->data_.run > runNumber // TODO[rovere]: pleonastic? first we encounter local ME of the same run ...
1958  || i->data_.streamId != 0
1959  || i->data_.moduleId != 0)
1960  break;
1961  }
1962  if (lumi != 0) {
1963  if (i->data_.lumi > lumi
1964  || i->data_.streamId != 0
1965  || i->data_.moduleId != 0)
1966  break;
1967  }
1968  if (runNumber != 0 or lumi !=0) {
1969  assert(i->data_.streamId == 0);
1970  assert(i->data_.moduleId == 0);
1971  }
1972  result.push_back(const_cast<MonitorElement *>(&*i));
1973  }
1974  return result;
1975 }
1976 
1979 std::vector<MonitorElement*>
1980 DQMStore::getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType /* = Wildcard */) const
1981 {
1982  lat::Regexp rx;
1983  try
1984  {
1985  rx = lat::Regexp(pattern, 0, syntaxType);
1986  rx.study();
1987  }
1988  catch (lat::Error &e)
1989  {
1990  raiseDQMError("DQMStore", "Invalid regular expression '%s': %s",
1991  pattern.c_str(), e.explain().c_str());
1992  }
1993 
1994  std::string path;
1995  std::vector<MonitorElement *> result;
1996  MEMap::const_iterator i = data_.begin();
1997  MEMap::const_iterator e = data_.end();
1998  for ( ; i != e; ++i)
1999  {
2000  path.clear();
2001  mergePath(path, *i->data_.dirname, i->data_.objname);
2002  if (rx.match(path))
2003  result.push_back(const_cast<MonitorElement *>(&*i));
2004  }
2005 
2006  return result;
2007 }
2008 
2012 
2015 void
2017 {
2018  MEMap::iterator mi = data_.begin();
2019  MEMap::iterator me = data_.end();
2020  for ( ; mi != me; ++mi)
2021  {
2022  MonitorElement &me = const_cast<MonitorElement &>(*mi);
2023  if (mi->wasUpdated())
2024  {
2025  if (me.resetMe())
2026  me.Reset();
2027  me.resetUpdate();
2028  }
2029  }
2030 
2031  reset_ = true;
2032 }
2033 
2037 
2039 void
2041 {
2042  MEMap::iterator mi = data_.begin();
2043  MEMap::iterator me = data_.end();
2044  for ( ; mi != me; ++mi)
2045  {
2046  if (forceResetOnBeginLumi_ && ((*mi).getLumiFlag() == false))
2047  continue;
2048  MonitorElement &me = const_cast<MonitorElement &>(*mi);
2049  me.Reset();
2050  me.resetUpdate();
2051  }
2052 
2053  reset_ = true;
2054 }
2055 
2059 
2060 void
2062  uint32_t lumi)
2063 {
2064 
2065  std::string null_str("");
2066  MonitorElement proto(&null_str, null_str, run, 0, 0);
2067  if (enableMultiThread_)
2068  proto.setLumi(lumi);
2069 
2070  std::set<MonitorElement>::const_iterator e = data_.end();
2071  std::set<MonitorElement>::const_iterator i = data_.lower_bound(proto);
2072 
2073  while (i != e) {
2074  if (i->data_.streamId != 0 ||
2075  i->data_.moduleId != 0)
2076  break;
2077  if ((i->data_.lumi != lumi) && enableMultiThread_)
2078  break;
2079  if (i->data_.run != run)
2080  break;
2081 
2082  const_cast<MonitorElement*>(&*i)->markToDelete();
2083 
2084  if (verbose_ > 1)
2085  std::cout << "DQMStore::markForDeletion: marked monitor element '"
2086  << *i->data_.dirname << "/" << i->data_.objname << "'"
2087  << "flags " << i->data_.flags << "\n";
2088 
2089  ++i;
2090  }
2091 }
2092 
2093 
2099 bool
2101  bool overwrite, bool collateHistograms)
2102 {
2103  // NB: Profile histograms inherit from TH*D, checking order matters.
2104  MonitorElement *refcheck = 0;
2105  if (TProfile *h = dynamic_cast<TProfile *>(obj))
2106  {
2107  MonitorElement *me = findObject(dir, h->GetName());
2108  if (! me)
2109  me = bookProfile(dir, h->GetName(), (TProfile *) h->Clone());
2110  else if (overwrite)
2111  me->copyFrom(h);
2112  else if (isCollateME(me) || collateHistograms)
2113  collateProfile(me, h, verbose_);
2114  refcheck = me;
2115  }
2116  else if (TProfile2D *h = dynamic_cast<TProfile2D *>(obj))
2117  {
2118  MonitorElement *me = findObject(dir, h->GetName());
2119  if (! me)
2120  me = bookProfile2D(dir, h->GetName(), (TProfile2D *) h->Clone());
2121  else if (overwrite)
2122  me->copyFrom(h);
2123  else if (isCollateME(me) || collateHistograms)
2124  collateProfile2D(me, h, verbose_);
2125  refcheck = me;
2126  }
2127  else if (TH1F *h = dynamic_cast<TH1F *>(obj))
2128  {
2129  MonitorElement *me = findObject(dir, h->GetName());
2130  if (! me)
2131  me = book1D(dir, h->GetName(), (TH1F *) h->Clone());
2132  else if (overwrite)
2133  me->copyFrom(h);
2134  else if (isCollateME(me) || collateHistograms)
2135  collate1D(me, h, verbose_);
2136  refcheck = me;
2137  }
2138  else if (TH1S *h = dynamic_cast<TH1S *>(obj))
2139  {
2140  MonitorElement *me = findObject(dir, h->GetName());
2141  if (! me)
2142  me = book1S(dir, h->GetName(), (TH1S *) h->Clone());
2143  else if (overwrite)
2144  me->copyFrom(h);
2145  else if (isCollateME(me) || collateHistograms)
2146  collate1S(me, h, verbose_);
2147  refcheck = me;
2148  }
2149  else if (TH1D *h = dynamic_cast<TH1D *>(obj))
2150  {
2151  MonitorElement *me = findObject(dir, h->GetName());
2152  if (! me)
2153  me = book1DD(dir, h->GetName(), (TH1D *) h->Clone());
2154  else if (overwrite)
2155  me->copyFrom(h);
2156  else if (isCollateME(me) || collateHistograms)
2157  collate1DD(me, h, verbose_);
2158  refcheck = me;
2159  }
2160  else if (TH2F *h = dynamic_cast<TH2F *>(obj))
2161  {
2162  MonitorElement *me = findObject(dir, h->GetName());
2163  if (! me)
2164  me = book2D(dir, h->GetName(), (TH2F *) h->Clone());
2165  else if (overwrite)
2166  me->copyFrom(h);
2167  else if (isCollateME(me) || collateHistograms)
2168  collate2D(me, h, verbose_);
2169  refcheck = me;
2170  }
2171  else if (TH2S *h = dynamic_cast<TH2S *>(obj))
2172  {
2173  MonitorElement *me = findObject(dir, h->GetName());
2174  if (! me)
2175  me = book2S(dir, h->GetName(), (TH2S *) h->Clone());
2176  else if (overwrite)
2177  me->copyFrom(h);
2178  else if (isCollateME(me) || collateHistograms)
2179  collate2S(me, h, verbose_);
2180  refcheck = me;
2181  }
2182  else if (TH2D *h = dynamic_cast<TH2D *>(obj))
2183  {
2184  MonitorElement *me = findObject(dir, h->GetName());
2185  if (! me)
2186  me = book2DD(dir, h->GetName(), (TH2D *) h->Clone());
2187  else if (overwrite)
2188  me->copyFrom(h);
2189  else if (isCollateME(me) || collateHistograms)
2190  collate2DD(me, h, verbose_);
2191  refcheck = me;
2192  }
2193  else if (TH3F *h = dynamic_cast<TH3F *>(obj))
2194  {
2195  MonitorElement *me = findObject(dir, h->GetName());
2196  if (! me)
2197  me = book3D(dir, h->GetName(), (TH3F *) h->Clone());
2198  else if (overwrite)
2199  me->copyFrom(h);
2200  else if (isCollateME(me) || collateHistograms)
2201  collate3D(me, h, verbose_);
2202  refcheck = me;
2203  }
2204  else if (dynamic_cast<TObjString *>(obj))
2205  {
2206  lat::RegexpMatch m;
2207  if (! s_rxmeval.match(obj->GetName(), 0, 0, &m))
2208  {
2209  if (strstr(obj->GetName(), "CMSSW"))
2210  {
2211  if (verbose_)
2212  std::cout << "Input file version: " << obj->GetName() << std::endl;
2213  return true;
2214  }
2215  else if (strstr(obj->GetName(), "DQMPATCH"))
2216  {
2217  if (verbose_)
2218  std::cout << "DQM patch version: " << obj->GetName() << std::endl;
2219  return true;
2220  }
2221  else
2222  {
2223  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2224  << obj->GetName() << "' of type '"
2225  << obj->IsA()->GetName() << "'\n";
2226  return false;
2227  }
2228  }
2229 
2230  std::string label = m.matchString(obj->GetName(), 1);
2231  std::string kind = m.matchString(obj->GetName(), 2);
2232  std::string value = m.matchString(obj->GetName(), 3);
2233 
2234  if (kind == "i")
2235  {
2236  MonitorElement *me = findObject(dir, label);
2237  if (! me || overwrite)
2238  {
2239  if (! me) me = bookInt(dir, label);
2240  me->Fill(atoll(value.c_str()));
2241  }
2242  }
2243  else if (kind == "f")
2244  {
2245  MonitorElement *me = findObject(dir, label);
2246  if (! me || overwrite)
2247  {
2248  if (! me) me = bookFloat(dir, label);
2249  me->Fill(atof(value.c_str()));
2250  }
2251  }
2252  else if (kind == "s")
2253  {
2254  MonitorElement *me = findObject(dir, label);
2255  if (! me)
2256  me = bookString(dir, label, value);
2257  else if (overwrite)
2258  me->Fill(value);
2259  }
2260  else if (kind == "e")
2261  {
2262  MonitorElement *me = findObject(dir, label);
2263  if (! me)
2264  {
2265  std::cout << "*** DQMStore: WARNING: no monitor element '"
2266  << label << "' in directory '"
2267  << dir << "' to be marked as efficiency plot.\n";
2268  return false;
2269  }
2270  me->setEfficiencyFlag();
2271  }
2272  else if (kind == "t")
2273  {
2274  MonitorElement *me = findObject(dir, label);
2275  if (! me)
2276  {
2277  std::cout << "*** DQMStore: WARNING: no monitor element '"
2278  << label << "' in directory '"
2279  << dir << "' for a tag\n";
2280  return false;
2281  }
2282  errno = 0;
2283  char *endp = 0;
2284  unsigned long val = strtoul(value.c_str(), &endp, 10);
2285  if ((val == 0 && errno) || *endp || val > ~uint32_t(0))
2286  {
2287  std::cout << "*** DQMStore: WARNING: cannot restore tag '"
2288  << value << "' for monitor element '"
2289  << label << "' in directory '"
2290  << dir << "' - invalid value\n";
2291  return false;
2292  }
2293  tag(me, val);
2294  }
2295  else if (kind == "qr")
2296  {
2297  // Handle qreports, but skip them while reading in references.
2298  if (! isSubdirectory(s_referenceDirName, dir))
2299  {
2300  size_t dot = label.find('.');
2301  if (dot == std::string::npos)
2302  {
2303  std::cout << "*** DQMStore: WARNING: quality report label in '" << label
2304  << "' is missing a '.' and cannot be extracted\n";
2305  return false;
2306  }
2307 
2308  std::string mename (label, 0, dot);
2309  std::string qrname (label, dot+1, std::string::npos);
2310 
2311  m.reset();
2312  DQMNet::QValue qv;
2313  if (s_rxmeqr1.match(value, 0, 0, &m))
2314  {
2315  qv.code = atoi(m.matchString(value, 1).c_str());
2316  qv.qtresult = strtod(m.matchString(value, 2).c_str(), 0);
2317  qv.message = m.matchString(value, 4);
2318  qv.qtname = qrname;
2319  qv.algorithm = m.matchString(value, 3);
2320  }
2321  else if (s_rxmeqr2.match(value, 0, 0, &m))
2322  {
2323  qv.code = atoi(m.matchString(value, 1).c_str());
2324  qv.qtresult = 0; // unavailable in old format
2325  qv.message = m.matchString(value, 2);
2326  qv.qtname = qrname;
2327  // qv.algorithm unavailable in old format
2328  }
2329  else
2330  {
2331  std::cout << "*** DQMStore: WARNING: quality test value '"
2332  << value << "' is incorrectly formatted\n";
2333  return false;
2334  }
2335 
2336  MonitorElement *me = findObject(dir, mename);
2337  if (! me)
2338  {
2339  std::cout << "*** DQMStore: WARNING: no monitor element '"
2340  << mename << "' in directory '"
2341  << dir << "' for quality test '"
2342  << label << "'\n";
2343  return false;
2344  }
2345 
2346  me->addQReport(qv, /* FIXME: getQTest(qv.qtname)? */ 0);
2347  }
2348  }
2349  else
2350  {
2351  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2352  << obj->GetName() << "' of type '"
2353  << obj->IsA()->GetName() << "'\n";
2354  return false;
2355  }
2356  }
2357  else if (TNamed *n = dynamic_cast<TNamed *>(obj))
2358  {
2359  // For old DQM data.
2360  std::string s;
2361  s.reserve(6 + strlen(n->GetTitle()) + 2*strlen(n->GetName()));
2362  s += '<'; s += n->GetName(); s += '>';
2363  s += n->GetTitle();
2364  s += '<'; s += '/'; s += n->GetName(); s += '>';
2365  TObjString os(s.c_str());
2366  return extract(&os, dir, overwrite, collateHistograms_);
2367  }
2368  else
2369  {
2370  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2371  << obj->GetName() << "' of type '" << obj->IsA()->GetName()
2372  << "' and with title '" << obj->GetTitle() << "'\n";
2373  return false;
2374  }
2375 
2376  // If we just read in a reference monitor element, and there is a
2377  // monitor element with the same name, link the two together. The
2378  // other direction is handled by the initialise() method.
2379  if (refcheck && isSubdirectory(s_referenceDirName, dir))
2380  {
2381  std::string mdir(dir, s_referenceDirName.size()+1, std::string::npos);
2382  if (MonitorElement *master = findObject(mdir, obj->GetName()))
2383  {
2384  master->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
2385  master->reference_ = refcheck->object_;
2386  }
2387  }
2388 
2389  return true;
2390 }
2391 
2395 bool
2397 {
2398  assert(! path.empty());
2399 
2400  // Find the first path component.
2401  size_t start = 0;
2402  size_t end = path.find('/', start);
2403  if (end == std::string::npos)
2404  end = path.size();
2405 
2406  while (true)
2407  {
2408  // Check if this subdirectory component exists. If yes, make sure
2409  // it is actually a subdirectory. Otherwise create or cd into it.
2410  std::string part(path, start, end-start);
2411  TObject *o = gDirectory->Get(part.c_str());
2412  if (o && ! dynamic_cast<TDirectory *>(o))
2413  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2414  " fails because the part '%s' already exists and is not"
2415  " directory", path.c_str(), part.c_str());
2416  else if (! o)
2417  gDirectory->mkdir(part.c_str());
2418 
2419  if (! gDirectory->cd(part.c_str()))
2420  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2421  " fails because could not cd into subdirectory '%s'",
2422  path.c_str(), part.c_str());
2423 
2424  // Stop if we reached the end, ignoring any trailing '/'.
2425  if (end+1 >= path.size())
2426  break;
2427 
2428  // Find the next path component.
2429  start = end+1;
2430  end = path.find('/', start);
2431  if (end == std::string::npos)
2432  end = path.size();
2433  }
2434 
2435  return true;
2436 }
2437 
2439  const std::string &path /* = "" */,
2440  const uint32_t run /* = 0 */,
2441  const uint32_t lumi /* = 0 */,
2442  const bool resetMEsAfterWriting /* = false */)
2443 {
2444  using google::protobuf::io::FileOutputStream;
2445  using google::protobuf::io::GzipOutputStream;
2446  using google::protobuf::io::StringOutputStream;
2447 
2448  std::set<std::string>::iterator di, de;
2449  MEMap::iterator mi, me = data_.end();
2450  dqmstorepb::ROOTFilePB dqmstore_message;
2451  int nme = 0;
2452 
2453  if (verbose_)
2454  std::cout << "\n DQMStore: Opening PBFile '"
2455  << filename << "'"<< std::endl;
2456 
2457  // Loop over the directory structure.
2458  for (di = dirs_.begin(), de = dirs_.end(); di != de; ++di)
2459  {
2460  // Check if we should process this directory. We process the
2461  // requested part of the object tree, including references.
2462  if (! path.empty()
2463  && ! isSubdirectory(path, *di))
2464  continue;
2465 
2466  // Loop over monitor elements in this directory.
2467  MonitorElement proto(&*di, std::string(), run, 0, 0);
2468  if (enableMultiThread_)
2469  proto.setLumi(lumi);
2470 
2471  mi = data_.lower_bound(proto);
2472  for ( ; mi != me && isSubdirectory(*di, *mi->data_.dirname); ++mi)
2473  {
2474  if (verbose_ > 1)
2475  std::cout << "Run: " << (*mi).run()
2476  << " Lumi: " << (*mi).lumi()
2477  << " LumiFlag: " << (*mi).getLumiFlag()
2478  << " streamId: " << (*mi).streamId()
2479  << " moduleId: " << (*mi).moduleId()
2480  << " fullpathname: " << (*mi).getFullname() << std::endl;
2481 
2482  // Upper bound in the loop over the MEs
2483  if (enableMultiThread_ && ((*mi).lumi() != lumi))
2484  break;
2485 
2486  // Skip if it isn't a direct child.
2487  if (*di != *mi->data_.dirname)
2488  continue;
2489 
2490  // Keep backward compatibility with the old way of
2491  // booking/handlind MonitorElements into the DQMStore. If run is
2492  // 0 it means that a booking happened w/ the old non-threadsafe
2493  // style, and we have to ignore the streamId and moduleId as a
2494  // consequence.
2495 
2496  if (run != 0 && (mi->data_.streamId !=0 || mi->data_.moduleId !=0))
2497  continue;
2498 
2499  if (verbose_ > 1)
2500  std::cout << "DQMStore::savePB: saving monitor element '"
2501  << *mi->data_.dirname << "/" << mi->data_.objname << "'"
2502  << "flags " << mi->data_.flags << "\n";
2503 
2504  nme++;
2505  dqmstorepb::ROOTFilePB::Histo* me = dqmstore_message.add_histo();
2506  me->set_full_pathname((*mi->data_.dirname) + '/' + mi->data_.objname);
2507  me->set_flags(mi->data_.flags);
2508 
2509  TObject *toWrite = nullptr;
2510  bool deleteObject = false;
2511 
2512  if (mi->kind() < MonitorElement::DQM_KIND_TH1F) {
2513  toWrite = new TObjString(mi->tagString().c_str());
2514  deleteObject = true;
2515  } else {
2516  toWrite = mi->object_;
2517  }
2518 
2519  TBufferFile buffer(TBufferFile::kWrite);
2520  buffer.WriteObject(toWrite);
2521  me->set_size(buffer.Length());
2522  me->set_streamed_histo((const void*)buffer.Buffer(),
2523  buffer.Length());
2524 
2525  if (deleteObject) {
2526  delete toWrite;
2527  }
2528 
2529  //reset the ME just written to make it available for the next LS (online)
2530  if (resetMEsAfterWriting)
2531  const_cast<MonitorElement*>(&*mi)->Reset();
2532  }
2533  }
2534 
2535  int filedescriptor = ::open(filename.c_str(),
2536  O_WRONLY | O_CREAT | O_TRUNC,
2537  S_IRUSR | S_IWUSR |
2538  S_IRGRP | S_IWGRP |
2539  S_IROTH);
2540  FileOutputStream file_stream(filedescriptor);
2542  options.format = GzipOutputStream::GZIP;
2543  options.compression_level = 6;
2544  GzipOutputStream gzip_stream(&file_stream,
2545  options);
2546  dqmstore_message.SerializeToZeroCopyStream(&gzip_stream);
2547 
2548  // we need to flush it before we close the fd
2549  gzip_stream.Close();
2550  file_stream.Close();
2551  ::close(filedescriptor);
2552 
2553  // Maybe make some noise.
2554  if (verbose_)
2555  std::cout << "DQMStore::savePB: successfully wrote " << nme
2556  << " objects from path '" << path
2557  << "' into DQM file '" << filename << "'\n";
2558 }
2559 
2560 
2565 void
2567  const std::string &path /* = "" */,
2568  const std::string &pattern /* = "" */,
2569  const std::string &rewrite /* = "" */,
2570  const uint32_t run /* = 0 */,
2571  const uint32_t lumi /* = 0 */,
2572  SaveReferenceTag ref /* = SaveWithReference */,
2573  int minStatus /* = dqm::qstatus::STATUS_OK */,
2574  const std::string &fileupdate /* = RECREATE */,
2575  const bool resetMEsAfterWriting /* = false */)
2576 {
2577  std::set<std::string>::iterator di, de;
2578  MEMap::iterator mi, me = data_.end();
2579  DQMNet::QReports::const_iterator qi, qe;
2580  int nme=0;
2581 
2582  // TFile flushes to disk with fsync() on every TDirectory written to
2583  // the file. This makes DQM file saving painfully slow, and
2584  // ironically makes it _more_ likely the file saving gets
2585  // interrupted and corrupts the file. The utility class below
2586  // simply ignores the flush synchronisation.
2587  class TFileNoSync : public TFile
2588  {
2589  public:
2590  TFileNoSync(const char *file, const char *opt) : TFile(file, opt) {}
2591  virtual Int_t SysSync(Int_t) override { return 0; }
2592  };
2593 
2594  // open output file, on 1st save recreate, later update
2595  if (verbose_)
2596  std::cout << "\n DQMStore: Opening TFile '" << filename
2597  << "' with option '" << fileupdate <<"'\n";
2598 
2599  TFileNoSync f(filename.c_str(), fileupdate.c_str()); // open file
2600  if(f.IsZombie())
2601  raiseDQMError("DQMStore", "Failed to create/update file '%s'", filename.c_str());
2602  f.cd();
2603 
2604  // Construct a regular expression from the pattern string.
2605  std::auto_ptr<lat::Regexp> rxpat;
2606  if (! pattern.empty())
2607  rxpat.reset(new lat::Regexp(pattern.c_str()));
2608 
2609  // Prepare a path for the reference object selection.
2610  std::string refpath;
2611  refpath.reserve(s_referenceDirName.size() + path.size() + 2);
2612  refpath += s_referenceDirName;
2613  if (! path.empty())
2614  {
2615  refpath += '/';
2616  refpath += path;
2617  }
2618 
2619  // Loop over the directory structure.
2620  for (di = dirs_.begin(), de = dirs_.end(); di != de; ++di)
2621  {
2622  // Check if we should process this directory. We process the
2623  // requested part of the object tree, including references.
2624  if (! path.empty()
2625  && ! isSubdirectory(path, *di)
2626  && ! isSubdirectory(refpath, *di))
2627  continue;
2628 
2629  // Loop over monitor elements in this directory.
2630  MonitorElement proto(&*di, std::string(), run, 0, 0);
2631  if (enableMultiThread_)
2632  proto.setLumi(lumi);
2633 
2634  mi = data_.lower_bound(proto);
2635  for ( ; mi != me && isSubdirectory(*di, *mi->data_.dirname); ++mi)
2636  {
2637  if (verbose_ > 1)
2638  std::cout << "DQMStore::save: Run: " << (*mi).run()
2639  << " Lumi: " << (*mi).lumi()
2640  << " LumiFlag: " << (*mi).getLumiFlag()
2641  << " streamId: " << (*mi).streamId()
2642  << " moduleId: " << (*mi).moduleId()
2643  << " fullpathname: " << (*mi).getFullname() << std::endl;
2644 
2645  // Upper bound in the loop over the MEs
2646  if (enableMultiThread_ && ((*mi).lumi() != lumi))
2647  break;
2648 
2649  // Skip if it isn't a direct child.
2650  if (*di != *mi->data_.dirname) {
2651  if (verbose_ > 1)
2652  std::cout << "DQMStore::save: isn't a direct child. Skipping" << std::endl;
2653  continue;
2654  }
2655 
2656  // Keep backward compatibility with the old way of
2657  // booking/handlind MonitorElements into the DQMStore. If run is
2658  // 0 it means that a booking happened w/ the old non-threadsafe
2659  // style, and we have to ignore the streamId and moduleId as a
2660  // consequence.
2661 
2662  if (run != 0 && (mi->data_.streamId !=0 || mi->data_.moduleId !=0)) {
2663  continue;
2664  }
2665 
2666  // Handle reference histograms, with three distinct cases:
2667  // 1) Skip all references entirely on saving.
2668  // 2) Blanket saving of all references.
2669  // 3) Save only references for monitor elements with qtests.
2670  // The latter two are affected by "path" sub-tree selection,
2671  // i.e. references are saved only in the selected tree part.
2672  if (isSubdirectory(refpath, *mi->data_.dirname))
2673  {
2674  if (ref == SaveWithoutReference)
2675  // Skip the reference entirely.
2676  continue;
2677  else if (ref == SaveWithReference)
2678  // Save all references regardless of qtests.
2679  ;
2680  else if (ref == SaveWithReferenceForQTest)
2681  {
2682  // Save only references for monitor elements with qtests
2683  // with an optional cut on minimum quality test result.
2684  int status = -1;
2685  std::string mname(mi->getFullname(), s_referenceDirName.size()+1, std::string::npos);
2686  MonitorElement *master = get(mname);
2687  if (master)
2688  for (size_t i = 0, e = master->data_.qreports.size(); i != e; ++i)
2689  status = std::max(status, master->data_.qreports[i].code);
2690 
2691  if (! master || status < minStatus)
2692  {
2693  if (verbose_ > 1)
2694  std::cout << "DQMStore::save: skipping monitor element '"
2695  << mi->data_.objname << "' while saving, status is "
2696  << status << ", required minimum status is "
2697  << minStatus << std::endl;
2698  continue;
2699  }
2700  }
2701  }
2702 
2703  if (verbose_ > 1)
2704  std::cout << "DQMStore::save: saving monitor element '"
2705  << mi->data_.objname << "'\n";
2706  nme++; // count saved histograms
2707 
2708  // Create the directory.
2709  gDirectory->cd("/");
2710  if (di->empty())
2712  else if (rxpat.get())
2713  cdInto(s_monitorDirName + '/' + lat::StringOps::replace(*di, *rxpat, rewrite));
2714  else
2715  cdInto(s_monitorDirName + '/' + *di);
2716 
2717  // Save the object.
2718  switch (mi->kind())
2719  {
2723  TObjString(mi->tagString().c_str()).Write();
2724  break;
2725 
2726  default:
2727  mi->object_->Write();
2728  break;
2729  }
2730 
2731  // Save quality reports if this is not in reference section.
2732  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
2733  {
2734  qi = mi->data_.qreports.begin();
2735  qe = mi->data_.qreports.end();
2736  for ( ; qi != qe; ++qi)
2737  TObjString(mi->qualityTagString(*qi).c_str()).Write();
2738  }
2739 
2740  // Save efficiency tag, if any
2741  if (mi->data_.flags & DQMNet::DQM_PROP_EFFICIENCY_PLOT)
2742  TObjString(mi->effLabelString().c_str()).Write();
2743 
2744  // Save tag if any
2745  if (mi->data_.flags & DQMNet::DQM_PROP_TAGGED)
2746  TObjString(mi->tagLabelString().c_str()).Write();
2747 
2748  //reset the ME just written to make it available for the next LS (online)
2749  if (resetMEsAfterWriting)
2750  const_cast<MonitorElement*>(&*mi)->Reset();
2751  }
2752  }
2753 
2754  f.Close();
2755 
2756  // Maybe make some noise.
2757  if (verbose_)
2758  std::cout << "DQMStore::save: successfully wrote " << nme
2759  << " objects from path '" << path
2760  << "' into DQM file '" << filename << "'\n";
2761 }
2762 
2765 unsigned int
2767  bool overwrite,
2768  const std::string &onlypath,
2769  const std::string &prepend,
2770  const std::string &curdir,
2771  OpenRunDirs stripdirs)
2772 {
2773  unsigned int ntot = 0;
2774  unsigned int count = 0;
2775 
2776  if (! file->cd(curdir.c_str()))
2777  raiseDQMError("DQMStore", "Failed to process directory '%s' while"
2778  " reading file '%s'", curdir.c_str(), file->GetName());
2779 
2780  // Figure out current directory name, but strip out the top
2781  // directory into which we dump everything.
2782  std::string dirpart = curdir;
2783  if (dirpart.compare(0, s_monitorDirName.size(), s_monitorDirName) == 0)
2784  {
2785  if (dirpart.size() == s_monitorDirName.size())
2786  dirpart.clear();
2787  else if (dirpart[s_monitorDirName.size()] == '/')
2788  dirpart.erase(0, s_monitorDirName.size()+1);
2789  }
2790 
2791  // See if we are going to skip this directory.
2792  bool skip = (! onlypath.empty() && ! isSubdirectory(onlypath, dirpart));
2793 
2794  if (prepend == s_collateDirName ||
2795  prepend == s_referenceDirName ||
2796  stripdirs == StripRunDirs )
2797  {
2798  // Remove Run # and RunSummary dirs
2799  // first look for Run summary,
2800  // if that is found and erased, also erase Run dir
2801  size_t slash = dirpart.find('/');
2802  size_t pos = dirpart.find("/Run summary");
2803  if (slash != std::string::npos && pos !=std::string::npos)
2804  {
2805  dirpart.erase(pos,12);
2806 
2807  pos = dirpart.find("Run ");
2808  size_t length = dirpart.find('/',pos+1)-pos+1;
2809  if (pos !=std::string::npos)
2810  dirpart.erase(pos,length);
2811  }
2812  }
2813 
2814  // If we are prepending, add it to the directory name,
2815  // and suppress reading of already existing reference histograms
2816  if (prepend == s_collateDirName ||
2817  prepend == s_referenceDirName)
2818  {
2819  size_t slash = dirpart.find('/');
2820  // If we are reading reference, skip previous reference.
2821  if (slash == std::string::npos // skip if Reference is toplevel folder, i.e. no slash
2822  && slash+1+s_referenceDirName.size() == dirpart.size()
2823  && dirpart.compare(slash+1, s_referenceDirName.size(), s_referenceDirName) == 0)
2824  return 0;
2825 
2826  slash = dirpart.find('/');
2827  // Skip reading of EventInfo subdirectory.
2828  if (slash != std::string::npos
2829  && slash + 10 == dirpart.size()
2830  && dirpart.compare( slash+1 , 9 , "EventInfo") == 0) {
2831  if (verbose_)
2832  std::cout << "DQMStore::readDirectory: skipping '" << dirpart << "'\n";
2833  return 0;
2834  }
2835 
2836  // Add prefix.
2837  if (dirpart.empty())
2838  dirpart = prepend;
2839  else
2840  dirpart = prepend + '/' + dirpart;
2841  }
2842  else if (! prepend.empty())
2843  {
2844  if (dirpart.empty())
2845  dirpart = prepend;
2846  else
2847  dirpart = prepend + '/' + dirpart;
2848  }
2849 
2850  // Loop over the contents of this directory in the file.
2851  // Post-pone string object handling to happen after other
2852  // objects have been read in so we are guaranteed to have
2853  // histograms by the time we read in quality tests and tags.
2854  TKey *key;
2855  TIter next (gDirectory->GetListOfKeys());
2856  std::list<TObject *> delayed;
2857  while ((key = (TKey *) next()))
2858  {
2859  std::auto_ptr<TObject> obj(key->ReadObj());
2860  if (dynamic_cast<TDirectory *>(obj.get()))
2861  {
2862  std::string subdir;
2863  subdir.reserve(curdir.size() + strlen(obj->GetName()) + 2);
2864  subdir += curdir;
2865  if (! curdir.empty())
2866  subdir += '/';
2867  subdir += obj->GetName();
2868 
2869  ntot += readDirectory(file, overwrite, onlypath, prepend, subdir, stripdirs);
2870  }
2871  else if (skip)
2872  ;
2873  else if (dynamic_cast<TObjString *>(obj.get()))
2874  {
2875  delayed.push_back(obj.release());
2876  }
2877  else
2878  {
2879  if (verbose_ > 2)
2880  std::cout << "DQMStore: reading object '" << obj->GetName()
2881  << "' of type '" << obj->IsA()->GetName()
2882  << "' from '" << file->GetName()
2883  << "' into '" << dirpart << "'\n";
2884 
2885  makeDirectory(dirpart);
2886  if (extract(obj.get(), dirpart, overwrite, collateHistograms_))
2887  ++count;
2888  }
2889  }
2890 
2891  while (! delayed.empty())
2892  {
2893  if (verbose_ > 2)
2894  std::cout << "DQMStore: reading object '" << delayed.front()->GetName()
2895  << "' of type '" << delayed.front()->IsA()->GetName()
2896  << "' from '" << file->GetName()
2897  << "' into '" << dirpart << "'\n";
2898 
2899  makeDirectory(dirpart);
2900  if (extract(delayed.front(), dirpart, overwrite, collateHistograms_))
2901  ++count;
2902 
2903  delete delayed.front();
2904  delayed.pop_front();
2905  }
2906 
2907  if (verbose_ > 1)
2908  std::cout << "DQMStore: read " << count << '/' << ntot
2909  << " objects from directory '" << dirpart << "'\n";
2910 
2911  return ntot + count;
2912 }
2913 
2920 bool
2922  bool overwrite /* = false */,
2923  const std::string &onlypath /* ="" */,
2924  const std::string &prepend /* ="" */,
2925  OpenRunDirs stripdirs /* =KeepRunDirs */,
2926  bool fileMustExist /* =true */)
2927 {
2928  return readFile(filename,overwrite,onlypath,prepend,stripdirs,fileMustExist);
2929 }
2930 
2935 bool
2937  OpenRunDirs stripdirs /* =StripRunDirs */,
2938  bool fileMustExist /* =true */)
2939 {
2940  bool overwrite = true;
2941  if (collateHistograms_) overwrite = false;
2942  if (verbose_)
2943  {
2944  std::cout << "DQMStore::load: reading from file '" << filename << "'\n";
2945  if (collateHistograms_)
2946  std::cout << "DQMStore::load: in collate mode " << "\n";
2947  else
2948  std::cout << "DQMStore::load: in overwrite mode " << "\n";
2949  }
2950 
2951  if (!s_rxpbfile.match(filename, 0, 0))
2952  return readFile(filename, overwrite, "", "", stripdirs, fileMustExist);
2953  else
2954  return readFilePB(filename, overwrite, "", "", stripdirs, fileMustExist);
2955 }
2956 
2962 bool
2964  bool overwrite /* = false */,
2965  const std::string &onlypath /* ="" */,
2966  const std::string &prepend /* ="" */,
2967  OpenRunDirs stripdirs /* =StripRunDirs */,
2968  bool fileMustExist /* =true */)
2969 {
2970 
2971  if (verbose_)
2972  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
2973 
2974  std::auto_ptr<TFile> f;
2975 
2976  try
2977  {
2978  f.reset(TFile::Open(filename.c_str()));
2979  if (! f.get() || f->IsZombie())
2980  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
2981  }
2982  catch (std::exception &)
2983  {
2984  if (fileMustExist)
2985  throw;
2986  else
2987  {
2988  if (verbose_)
2989  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
2990  return false;
2991  }
2992  }
2993 
2994  unsigned n = readDirectory(f.get(), overwrite, onlypath, prepend, "", stripdirs);
2995  f->Close();
2996 
2997  MEMap::iterator mi = data_.begin();
2998  MEMap::iterator me = data_.end();
2999  for ( ; mi != me; ++mi)
3000  const_cast<MonitorElement &>(*mi).updateQReportStats();
3001 
3002  if (verbose_)
3003  {
3004  std::cout << "DQMStore::open: successfully read " << n
3005  << " objects from file '" << filename << "'";
3006  if (! onlypath.empty())
3007  std::cout << " from directory '" << onlypath << "'";
3008  if (! prepend.empty())
3009  std::cout << " into directory '" << prepend << "'";
3010  std::cout << std::endl;
3011  }
3012  return true;
3013 }
3014 
3018 inline TObject * DQMStore::extractNextObject(TBufferFile &buf) const {
3019  if (buf.Length() == buf.BufferSize())
3020  return 0;
3021  buf.InitMap();
3022  void *ptr = buf.ReadObjectAny(0);
3023  return reinterpret_cast<TObject *>(ptr);
3024 }
3025 
3027  std::string &dirname,
3028  std::string &objname,
3029  TObject ** obj) {
3030 
3031  size_t slash = h.full_pathname().rfind('/');
3032  size_t dirpos = (slash == std::string::npos ? 0 : slash);
3033  size_t namepos = (slash == std::string::npos ? 0 : slash+1);
3034  dirname.assign(h.full_pathname(), 0, dirpos);
3035  objname.assign(h.full_pathname(), namepos, std::string::npos);
3036  TBufferFile buf(TBufferFile::kRead, h.size(),
3037  (void*)h.streamed_histo().data(),
3038  kFALSE);
3039  buf.Reset();
3040  *obj = extractNextObject(buf);
3041  if (!*obj) {
3042  raiseDQMError("DQMStore", "Error reading element:'%s'" , h.full_pathname().c_str());
3043  }
3044 }
3045 
3046 bool
3048  bool overwrite /* = false */,
3049  const std::string &onlypath /* ="" */,
3050  const std::string &prepend /* ="" */,
3051  OpenRunDirs stripdirs /* =StripRunDirs */,
3052  bool fileMustExist /* =true */)
3053 {
3054  using google::protobuf::io::FileInputStream;
3055  using google::protobuf::io::FileOutputStream;
3056  using google::protobuf::io::GzipInputStream;
3057  using google::protobuf::io::GzipOutputStream;
3058  using google::protobuf::io::CodedInputStream;
3059  using google::protobuf::io::ArrayInputStream;
3060 
3061  if (verbose_)
3062  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
3063 
3064  int filedescriptor;
3065  if ((filedescriptor = ::open(filename.c_str(), O_RDONLY)) == -1) {
3066  if (fileMustExist)
3067  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
3068  else
3069  if (verbose_)
3070  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
3071  return false;
3072  }
3073 
3074  dqmstorepb::ROOTFilePB dqmstore_message;
3075  FileInputStream fin(filedescriptor);
3076  GzipInputStream input(&fin);
3077  CodedInputStream input_coded(&input);
3078  input_coded.SetTotalBytesLimit(1024*1024*1024, -1);
3079  if (!dqmstore_message.ParseFromCodedStream(&input_coded)) {
3080  raiseDQMError("DQMStore", "Fatal parsing file '%s'", filename.c_str());
3081  return false;
3082  }
3083  ::close(filedescriptor);
3084 
3085  for (int i = 0; i < dqmstore_message.histo_size(); i++) {
3086  std::string path;
3087  std::string objname;
3088 
3089  TObject *obj = NULL;
3090  const dqmstorepb::ROOTFilePB::Histo &h = dqmstore_message.histo(i);
3091  get_info(h, path, objname, &obj);
3092 
3093  setCurrentFolder(path);
3094  if (obj)
3095  {
3096  /* Before calling the extract() check if histogram exists:
3097  * if it does - flags for the given monitor are already set (and merged)
3098  * else - set the flags after the histogram is created.
3099  */
3100  MonitorElement *me = findObject(path, objname);
3101 
3102  /* Run histograms should be collated and not overwritten,
3103  * Lumi histograms should be overwritten (and collate flag is not checked)
3104  */
3105  bool overwrite = h.flags() & DQMNet::DQM_PROP_LUMI;
3106  bool collate = !(h.flags() & DQMNet::DQM_PROP_LUMI);
3107  extract(static_cast<TObject *>(obj), path, overwrite, collate);
3108 
3109  if (me == nullptr) {
3110  me = findObject(path, objname);
3111  me->data_.flags = h.flags();
3112  }
3113 
3114  delete obj;
3115  }
3116  }
3117 
3118  cd();
3119  return true;
3120 }
3121 
3127 void
3129 {
3131  const std::string *cleaned = 0;
3132  cleanTrailingSlashes(path, clean, cleaned);
3133  MonitorElement proto(cleaned, std::string());
3134 
3135  MEMap::iterator e = data_.end();
3136  MEMap::iterator i = data_.lower_bound(proto);
3137  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
3138  data_.erase(i++);
3139 
3140  std::set<std::string>::iterator de = dirs_.end();
3141  std::set<std::string>::iterator di = dirs_.lower_bound(*cleaned);
3142  while (di != de && isSubdirectory(*cleaned, *di))
3143  dirs_.erase(di++);
3144 }
3145 
3147 void
3149 {
3150  MonitorElement proto(&dir, std::string());
3151  MEMap::iterator e = data_.end();
3152  MEMap::iterator i = data_.lower_bound(proto);
3153  while (i != e && isSubdirectory(dir, *i->data_.dirname))
3154  if (dir == *i->data_.dirname)
3155  data_.erase(i++);
3156  else
3157  ++i;
3158 }
3159 
3161 void
3163 {
3165 }
3166 
3169 void
3171 {
3172  removeElement(pwd_, name);
3173 }
3174 
3177 void
3178 DQMStore::removeElement(const std::string &dir, const std::string &name, bool warning /* = true */)
3179 {
3180  MonitorElement proto(&dir, name);
3181  MEMap::iterator pos = data_.find(proto);
3182  if (pos == data_.end() && warning)
3183  std::cout << "DQMStore: WARNING: attempt to remove non-existent"
3184  << " monitor element '" << name << "' in '" << dir << "'\n";
3185  else
3186  data_.erase(pos);
3187 }
3188 
3194 QCriterion *
3196 {
3197  QCMap::const_iterator i = qtests_.find(qtname);
3198  QCMap::const_iterator e = qtests_.end();
3199  return (i == e ? 0 : i->second);
3200 }
3201 
3205 QCriterion *
3206 DQMStore::createQTest(const std::string &algoname, const std::string &qtname)
3207 {
3208  if (qtests_.count(qtname))
3209  raiseDQMError("DQMStore", "Attempt to create duplicate quality test '%s'",
3210  qtname.c_str());
3211 
3212  QAMap::iterator i = qalgos_.find(algoname);
3213  if (i == qalgos_.end())
3214  raiseDQMError("DQMStore", "Cannot create a quality test using unknown"
3215  " algorithm '%s'", algoname.c_str());
3216 
3217  QCriterion *qc = i->second(qtname);
3218  qc->setVerbose(verboseQT_);
3219 
3220  qtests_[qtname] = qc;
3221  return qc;
3222 }
3223 
3226 void
3228 {
3229  // Clean the path
3231  const std::string *cleaned = 0;
3232  cleanTrailingSlashes(dir, clean, cleaned);
3233 
3234  // Validate the path.
3235  if (cleaned->find_first_not_of(s_safe) != std::string::npos)
3236  raiseDQMError("DQMStore", "Monitor element path name '%s'"
3237  " uses unacceptable characters", cleaned->c_str());
3238 
3239  // Redirect to the pattern match version.
3240  useQTestByMatch(*cleaned + "/*", qtname);
3241 }
3242 
3244 int
3246 {
3247  QCriterion *qc = getQCriterion(qtname);
3248  if (! qc)
3249  raiseDQMError("DQMStore", "Cannot apply non-existent quality test '%s'",
3250  qtname.c_str());
3251 
3252  fastmatch * fm = new fastmatch( pattern );
3253 
3254  // Record the test for future reference.
3255  QTestSpec qts(fm, qc);
3256  qtestspecs_.push_back(qts);
3257 
3258  // Apply the quality test.
3259  MEMap::iterator mi = data_.begin();
3260  MEMap::iterator me = data_.end();
3261  std::string path;
3262  int cases = 0;
3263  for ( ; mi != me; ++mi)
3264  {
3265  path.clear();
3266  mergePath(path, *mi->data_.dirname, mi->data_.objname);
3267  if (fm->match(path))
3268  {
3269  ++cases;
3270  const_cast<MonitorElement &>(*mi).addQReport(qts.second);
3271  }
3272  }
3273 
3274  //return the number of matched cases
3275  return cases;
3276 }
3279 void
3281 {
3282 
3283  if (verbose_ > 0)
3284  std::cout << "DQMStore: running runQTests() with reset = "
3285  << ( reset_ ? "true" : "false" ) << std::endl;
3286 
3287  // Apply quality tests to each monitor element, skipping references.
3288  MEMap::iterator mi = data_.begin();
3289  MEMap::iterator me = data_.end();
3290  for ( ; mi != me; ++mi)
3291  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
3292  const_cast<MonitorElement &>(*mi).runQTests();
3293 
3294  reset_ = false;
3295 }
3296 
3300 int
3301 DQMStore::getStatus(const std::string &path /* = "" */) const
3302 {
3304  const std::string *cleaned = 0;
3305  cleanTrailingSlashes(path, clean, cleaned);
3306 
3308  MEMap::const_iterator mi = data_.begin();
3309  MEMap::const_iterator me = data_.end();
3310  for ( ; mi != me; ++mi)
3311  {
3312  if (! cleaned->empty() && ! isSubdirectory(*cleaned, *mi->data_.dirname))
3313  continue;
3314 
3315  if (mi->hasError())
3316  return dqm::qstatus::ERROR;
3317  else if (mi->hasWarning())
3318  status = dqm::qstatus::WARNING;
3319  else if (status < dqm::qstatus::WARNING
3320  && mi->hasOtherReport())
3321  status = dqm::qstatus::OTHER;
3322  }
3323  return status;
3324 }
3325 
3331 void
3333 {
3334  if (me)
3335  me->softReset();
3336 }
3337 
3338 // reverts action of softReset
3339 void
3341 {
3342  if (me)
3343  me->disableSoftReset();
3344 }
3345 
3348 void
3350 {
3351  if (me)
3352  me->setAccumulate(flag);
3353 }
3354 
3358 void
3360 {
3361  std::vector<std::string> contents;
3362  getContents(contents);
3363 
3364  std::cout << " ------------------------------------------------------------\n"
3365  << " Directory structure: \n"
3366  << " ------------------------------------------------------------\n";
3367 
3368  std::copy(contents.begin(), contents.end(),
3369  std::ostream_iterator<std::string>(std::cout, "\n"));
3370 
3371  std::cout << " ------------------------------------------------------------\n";
3372 }
3373 
3377 // check if the collate option is active on the DQMStore
3378 bool
3380 {
3381  return collateHistograms_;
3382 }
3386 // check if the monitor element is in auto-collation folder
3387 bool
3389 { return me && isSubdirectory(s_collateDirName, *me->data_.dirname); }
3393 
3395 void
3397 {
3398  if (scaleFlag_ == 0.0) return;
3399  if (verbose_ > 0)
3400  std::cout << " =========== " << " ScaleFlag " << scaleFlag_ << std::endl;
3401  double factor = scaleFlag_;
3402  int events = 1;
3403  if (dirExists("Info/EventInfo")) {
3404  if ( scaleFlag_ == -1.0) {
3405  MonitorElement * scale_me = get("Info/EventInfo/ScaleFactor");
3406  if (scale_me && scale_me->kind()==MonitorElement::DQM_KIND_REAL) factor = scale_me->getFloatValue();
3407  }
3408  MonitorElement * event_me = get("Info/EventInfo/processedEvents");
3409  if (event_me && event_me->kind()==MonitorElement::DQM_KIND_INT) events = event_me->getIntValue();
3410  }
3411  factor = factor/(events*1.0);
3412 
3413  MEMap::iterator mi = data_.begin();
3414  MEMap::iterator me = data_.end();
3415  for ( ; mi != me; ++mi)
3416  {
3417  MonitorElement &me = const_cast<MonitorElement &>(*mi);
3418  switch (me.kind())
3419  {
3421  {
3422  me.getTH1F()->Scale(factor);
3423  break;
3424  }
3426  {
3427  me.getTH1S()->Scale(factor);
3428  break;
3429  }
3431  {
3432  me.getTH1D()->Scale(factor);
3433  break;
3434  }
3436  {
3437  me.getTH2F()->Scale(factor);
3438  break;
3439  }
3441  {
3442  me.getTH2S()->Scale(factor);
3443  break;
3444  }
3446  {
3447  me.getTH2D()->Scale(factor);
3448  break;
3449  }
3451  {
3452  me.getTH3F()->Scale(factor);
3453  break;
3454  }
3456  {
3457  me.getTProfile()->Scale(factor);
3458  break;
3459  }
3461  {
3462  me.getTProfile2D()->Scale(factor);
3463  break;
3464  }
3465  default:
3466  if (verbose_ > 0)
3467  std::cout << " The DQM object '" << me.getFullname() << "' is not scalable object " << std::endl;
3468  continue;
3469  }
3470  }
3471 }
QCriterion * getQCriterion(const std::string &qtname) const
Definition: DQMStore.cc:3195
IGetter * igetter_
Definition: DQMStore.h:718
bool compare_strings_reverse(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:205
std::pair< fastmatch *, QCriterion * > QTestSpec
Definition: DQMStore.h:688
TH2S * getTH2S(void) const
TH1S * getTH1S(void) const
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
DQMStore(const edm::ParameterSet &pset, edm::ActivityRegistry &)
Definition: DQMStore.cc:464
static const lat::Regexp s_rxmeqr2("^st\\.(\\d+)\\.(.*)$")
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:1125
bool containsAnyMonitorable(const std::string &path) const
Definition: DQMStore.cc:1719
uint32_t moduleId
Definition: DQMNet.h:104
inline::google::protobuf::uint32 size() const
bool isCollateME(MonitorElement *me) const
Definition: DQMStore.cc:3388
void resetUpdate(void)
reset &quot;was updated&quot; flag
tuple start
Check for commandline option errors.
Definition: dqm_diff.py:58
bool cdInto(const std::string &path) const
Definition: DQMStore.cc:2396
const ::std::string & full_pathname() const
void cd(void)
Definition: DQMStore.cc:322
int getStatus(const std::string &path="") const
Definition: DQMStore.cc:3301
void copyFrom(TH1 *from)
MonitorElement * initialise(Kind kind)
static const int OTHER
static void mergePath(std::string &path, const std::string &dir, const std::string &name)
Definition: DQMStore.cc:108
std::string algorithm
Definition: DQMNet.h:93
std::vector< std::string > getSubdirs(void) const
Definition: DQMStore.cc:1680
TProfile2D * getTProfile2D(void) const
MonitorElement * book1D(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1D histogram.
Definition: DQMStore.cc:975
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::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
void rmdir(const std::string &fullpath)
Definition: DQMStore.cc:3128
static void collate3D(MonitorElement *me, TH3F *h, unsigned verbose)
Definition: DQMStore.cc:1584
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:2963
MonitorElement * findObject(const std::string &dir, const std::string &name, const uint32_t run=0, const uint32_t lumi=0, const uint32_t streamId=0, const uint32_t moduleId=0) const
Definition: DQMStore.cc:1859
static void collateProfile(MonitorElement *me, TProfile *h, unsigned verbose)
Definition: DQMStore.cc:1591
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:1237
void setLumi(uint32_t ls)
void cd(void)
Definition: DQMStore.cc:266
void cd(void)
go to top directory (ie. root)
Definition: DQMStore.cc:665
MonitorElement * get(const std::string &path)
Definition: DQMStore.cc:302
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:1147
uint32_t streamId_
Definition: DQMStore.h:704
tuple lumi
Definition: fjr2json.py:35
void markForDeletion(uint32_t run, uint32_t lumi)
Definition: DQMStore.cc:2061
static const std::string s_safe
Definition: DQMStore.cc:56
static void splitPath(std::string &dir, std::string &name, const std::string &path)
Definition: DQMStore.cc:95
uint32_t flags
Definition: DQMNet.h:98
const std::string & pwd(void)
Definition: DQMStore.cc:282
assert(m_qm.get())
void disableSoftReset(void)
reverts action of softReset
static void collate2DD(MonitorElement *me, TH2D *h, unsigned verbose)
Definition: DQMStore.cc:1577
std::vector< MonitorElement * > getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType=lat::Regexp::Wildcard) const
Definition: DQMStore.cc:1980
static const int WARNING
TH3F * getTH3F(void) const
static const uint32_t DQM_PROP_TAGGED
Definition: DQMNet.h:54
TH1D * getTH1D(void) const
MatchingHeuristicEnum matching_
Definition: DQMStore.h:72
void runQTests(void)
run all quality tests
#define NULL
Definition: scimark2.h:8
static const uint32_t DQM_PROP_EFFICIENCY_PLOT
Definition: DQMNet.h:63
list pattern
Definition: chain.py:104
void softReset(void)
TH2D * getTH2D(void) const
uint32_t tag
Definition: DQMNet.h:99
bool reset_
Definition: DQMStore.h:696
const std::string * dirname
Definition: DQMNet.h:105
MonitorElement * book1DD(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:1007
void initializeFrom(const edm::ParameterSet &)
Definition: DQMStore.cc:536
#define nullptr
OpenRunDirs
Definition: DQMStore.h:84
void set_flags(::google::protobuf::uint32 value)
uint32_t run
Definition: DQMNet.h:101
uint32_t moduleId_
Definition: DQMStore.h:705
const ::std::string & streamed_histo() const
void initQCriterion(std::map< std::string, QCriterion *(*)(const std::string &)> &m)
Definition: DQMStore.cc:124
QCMap qtests_
Definition: DQMStore.h:712
static const std::string s_collateDirName
Definition: DQMStore.cc:55
MonitorElement * book(const std::string &dir, const std::string &name, const char *context)
Definition: DQMStore.cc:830
static const std::string s_monitorDirName
name of global monitoring folder (containing all sources subdirectories)
Definition: DQMStore.cc:53
std::mutex book_mutex_
Definition: DQMStore.h:716
MonitorElement * bookFloat(const char *name)
Book float.
Definition: DQMStore.cc:912
static std::string const input
Definition: EdmProvDump.cc:43
SaveReferenceTag
Definition: DQMStore.h:78
static const lat::Regexp s_rxtrace("(.*)\\((.*)\\+0x.*\\).*")
void Fill(long long x)
static void cleanTrailingSlashes(const std::string &path, std::string &clean, const std::string *&cleaned)
Definition: DQMStore.cc:78
Preallocate preallocateSignal_
signal is emitted before beginJob
void tag(MonitorElement *me, unsigned int myTag)
Definition: DQMStore.cc:1615
~DQMStore(void)
Definition: DQMStore.cc:522
void disableSoftReset(MonitorElement *me)
Definition: DQMStore.cc:3340
unsigned int maxNumberOfStreams() const
Definition: SystemBounds.h:43
static const lat::Regexp s_rxmeval("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$")
void forceReset(void)
Definition: DQMStore.cc:2040
static bool isSubdirectory(const std::string &ofdir, const std::string &path)
Definition: DQMStore.cc:68
std::vector< MonitorElement * > getAllContents(const std::string &path, uint32_t runNumber=0, uint32_t lumi=0) const
Definition: DQMStore.cc:1942
fastmatch(std::string const &_fastString)
Definition: DQMStore.cc:129
unsigned verboseQT_
Definition: DQMStore.h:695
static const uint32_t DQM_PROP_HAS_REFERENCE
Definition: DQMNet.h:53
void removeContents(void)
erase all monitoring elements in current directory (not including subfolders);
Definition: DQMStore.cc:3162
QTestSpecs qtestspecs_
Definition: DQMStore.h:714
tuple path
else: Piece not in the list, fine.
double scaleFlag_
Definition: DQMStore.h:697
void get_info(const dqmstorepb::ROOTFilePB_Histo &, std::string &dirname, std::string &objname, TObject **obj)
Definition: DQMStore.cc:3026
void watchPostSourceRun(PostSourceRun::slot_type const &iSlot)
MonitorElement * bookString(const char *name, const char *value)
Book string.
Definition: DQMStore.cc:941
void setAccumulate(bool)
uint32_t lumi
Definition: DQMNet.h:102
bool isCollate(void) const
Definition: DQMStore.cc:3379
tuple result
Definition: query.py:137
void removeElement(const std::string &name)
Definition: DQMStore.cc:3170
void addProfiles(TProfile *h1, TProfile *h2, TProfile *sum, float c1, float c2)
static void collateProfile2D(MonitorElement *me, TProfile2D *h, unsigned verbose)
Definition: DQMStore.cc:1601
double getFloatValue(void) const
void tag(MonitorElement *, unsigned int)
Definition: DQMStore.cc:286
TH1 * getTH1(void) const
double f[11][100]
uint32_t run_
Definition: DQMStore.h:703
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
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:1289
QCriterion * makeQCriterion(const std::string &qtname)
Definition: DQMStore.cc:119
#define end
Definition: vmac.h:37
void setVerbose(unsigned level)
Definition: DQMStore.cc:652
void softReset(MonitorElement *me)
Definition: DQMStore.cc:3332
std::string pwd_
Definition: DQMStore.h:708
Kind kind(void) const
Get the type of the monitor element.
void runQTests(void)
Definition: DQMStore.cc:3280
TObject * extractNextObject(TBufferFile &) const
Definition: DQMStore.cc:3018
lat::Regexp * regexp_
Definition: DQMStore.h:70
IBooker * ibooker_
Definition: DQMStore.h:717
MonitorElement * get(const std::string &path) const
get ME from full pathname (e.g. &quot;my/long/dir/my_histo&quot;)
Definition: DQMStore.cc:1729
QAMap qalgos_
Definition: DQMStore.h:713
const std::string getFullname(void) const
get full name of ME including Pathname
std::vector< MonitorElement * > getContents(const std::string &path) const
Definition: DQMStore.cc:1758
std::string readSelectedDirectory_
Definition: DQMStore.h:702
std::vector< std::string > getMEs(void)
Definition: DQMStore.cc:310
std::string objname
Definition: DQMNet.h:106
void mergeAndResetMEsRunSummaryCache(uint32_t run, uint32_t streamId, uint32_t moduleId)
Definition: DQMStore.cc:343
std::string fastString_
Definition: DQMStore.h:71
std::vector< T * > clean
Definition: MVATrainer.cc:156
std::string qtname
Definition: DQMNet.h:92
DQMNet::CoreObject data_
bool dirExists(const std::string &path) const
true if directory exists
Definition: DQMStore.cc:753
void savePB(const std::string &filename, const std::string &path="", const uint32_t run=0, const uint32_t lumi=0, const bool resetMEsAfterWriting=false)
Definition: DQMStore.cc:2438
void getAllTags(std::vector< std::string > &into) const
Definition: DQMStore.cc:1889
bool dirExists(const std::string &path)
Definition: DQMStore.cc:318
bool load(const std::string &filename, OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2936
void scaleElements(void)
Definition: DQMStore.cc:3396
~fastmatch()
Definition: DQMStore.cc:199
static void collate1DD(MonitorElement *me, TH1D *h, unsigned verbose)
Definition: DQMStore.cc:1556
void tagAllContents(const std::string &path, unsigned int myTag)
Definition: DQMStore.cc:1658
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:274
MonitorElement * initialise(MonitorElement *me, const std::string &path)
void watchPostSourceLumi(PostSourceLumi::slot_type const &iSlot)
void goUp(void)
Definition: DQMStore.cc:278
bool containsAnyMonitorable(const std::string &path)
Definition: DQMStore.cc:314
void tagContents(const std::string &, unsigned int)
Definition: DQMStore.cc:290
const ::dqmstorepb::ROOTFilePB_Histo & histo(int index) const
unsigned verbose_
Definition: DQMStore.h:694
void set_size(::google::protobuf::uint32 value)
MEMap data_
Definition: DQMStore.h:709
part
Definition: HCALResponse.h:20
int64_t getIntValue(void) const
static const std::string s_referenceDirName
Definition: DQMStore.cc:54
void print_trace(const std::string &dir, const std::string &name)
Definition: DQMStore.cc:596
int useQTestByMatch(const std::string &pattern, const std::string &qtname)
attach quality test &lt;qc&gt; to monitor elements matching &lt;pattern&gt;.
Definition: DQMStore.cc:3245
std::vector< MonitorElement * > getAllContents(const std::string &path, uint32_t runNumber=0, uint32_t lumi=0)
Definition: DQMStore.cc:296
TH1F * getTH1F(void) const
static void collate1D(MonitorElement *me, TH1F *h, unsigned verbose)
Definition: DQMStore.cc:1542
static const lat::Regexp s_rxpbfile(".*\\.pb$")
std::vector< std::string > getMEs(void) const
get list of (non-dir) MEs of current directory
Definition: DQMStore.cc:1703
std::vector< std::string > getSubdirs(void)
Definition: DQMStore.cc:306
DQMStore * owner_
Definition: DQMStore.h:187
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:330
bool resetMe(void) const
true if ME should be reset at end of monitoring cycle
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:2766
void setVerbose(int verbose)
probability limits for warnings, errors
Definition: QTest.h:116
bool extract(TObject *obj, const std::string &dir, bool overwrite, bool collateHistograms)
Definition: DQMStore.cc:2100
bool forceResetOnBeginLumi_
Definition: DQMStore.h:701
T dot(const Basic3DVector &v) const
Scalar product, or &quot;dot&quot; product, with a vector of same type.
std::vector< boost::shared_ptr< fireworks::OptionNode > > Options
void tagContents(const std::string &path, unsigned int myTag)
tag all children of folder (does NOT include subfolders)
Definition: DQMStore.cc:1646
tuple events
Definition: patZpeak.py:19
inline::dqmstorepb::ROOTFilePB_Histo * add_histo()
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", const bool resetMEsAfterWriting=false)
Definition: DQMStore.cc:2566
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:3047
TProfile * getTProfile(void) const
void useQTest(const std::string &dir, const std::string &qtname)
Definition: DQMStore.cc:3227
tuple filename
Definition: lut2db_cfg.py:20
std::string message
Definition: DQMNet.h:91
void goUp(void)
equivalent to &quot;cd ..&quot;
Definition: DQMStore.cc:699
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:2921
inline::google::protobuf::uint32 flags() const
static const int STATUS_OK
void setAccumulate(MonitorElement *me, bool flag)
Definition: DQMStore.cc:3349
tuple cout
Definition: gather_cfg.py:121
void setEfficiencyFlag(void)
static void collate1S(MonitorElement *me, TH1S *h, unsigned verbose)
Definition: DQMStore.cc:1549
void Reset(std::vector< TH2F > &depth)
std::ofstream * stream_
Definition: DQMStore.h:706
QCriterion * createQTest(const std::string &algoname, const std::string &qtname)
Definition: DQMStore.cc:3206
static bool checkBinningMatches(MonitorElement *me, TH1 *h, unsigned verbose)
Definition: DQMStore.cc:1515
dbl *** dir
Definition: mlp_gen.cc:35
volatile std::atomic< bool > shutdown_flag false
void showDirStructure(void) const
Definition: DQMStore.cc:3359
void reset(void)
Definition: DQMStore.cc:2016
bool deleteObject(T *fObject, const std::string &fInput, const std::string &fInputTag, HcalDbTool::IOVRun fInputRun, bool fVerbose)
tuple status
Definition: ntuplemaker.py:245
TH2F * getTH2F(void) const
if(conf.exists("allCellsPositionCalc"))
static void collate2D(MonitorElement *me, TH2F *h, unsigned verbose)
Definition: DQMStore.cc:1563
MonitorElement * bookInt(const char *name)
Book int.
Definition: DQMStore.cc:882
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:1103
tuple collateHistograms
for(const auto &isodef:isoDefs)
long double T
uint32_t streamId
Definition: DQMNet.h:103
void mergeAndResetMEsLuminositySummaryCache(uint32_t run, uint32_t lumi, uint32_t streamId, uint32_t moduleId)
Definition: DQMStore.cc:398
float qtresult
Definition: DQMNet.h:90
std::set< std::string > dirs_
Definition: DQMStore.h:710
bool collateHistograms_
Definition: DQMStore.h:698
void Reset(void)
reset ME (ie. contents, errors, etc)
static const uint32_t DQM_PROP_LUMI
Definition: DQMNet.h:60
static std::string const source
Definition: EdmProvDump.cc:42
bool LSbasedMode_
Definition: DQMStore.h:700
void addQReport(const DQMNet::QValue &desc, QCriterion *qc)
Add quality report, from DQMStore.
MonitorElement * book1S(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:991
tuple size
Write out results.
static const lat::Regexp s_rxmeqr1("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$")
void makeDirectory(const std::string &path)
Definition: DQMStore.cc:712
void connect(U iFunc)
Definition: Signal.h:63
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:688
static void collate2S(MonitorElement *me, TH2S *h, unsigned verbose)
Definition: DQMStore.cc:1570
static const int ERROR
const std::string & pwd(void) const
Definition: DQMStore.cc:660
bool enableMultiThread_
Definition: DQMStore.h:699
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:1433
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:11