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.
6 #include "classlib/utils/RegexpMatch.h"
7 #include "classlib/utils/Regexp.h"
8 #include "classlib/utils/StringOps.h"
9 #include "TFile.h"
10 #include "TROOT.h"
11 #include "TKey.h"
12 #include "TClass.h"
13 #include "TSystem.h"
14 #include <iterator>
15 #include <cerrno>
16 #include <boost/algorithm/string.hpp>
17 #include <fstream>
18 
45 static std::string s_monitorDirName = "DQMData";
48 static std::string s_referenceDirName = "Reference";
49 static std::string s_collateDirName = "Collate";
50 static std::string s_safe = "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# ";
51 
52 static const lat::Regexp s_rxmeval ("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$");
53 static const lat::Regexp s_rxmeqr1 ("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$");
54 static const lat::Regexp s_rxmeqr2 ("^st\\.(\\d+)\\.(.*)$");
55 static const lat::Regexp s_rxtrace ("(.*)\\((.*)\\+0x.*\\).*");
56 
60 static bool
62 {
63  return (ofdir.empty()
64  || (path.size() >= ofdir.size()
65  && path.compare(0, ofdir.size(), ofdir) == 0
66  && (path.size() == ofdir.size()
67  || path[ofdir.size()] == '/')));
68 }
69 
70 static void
72 {
73  clean.clear();
74  cleaned = &path;
75 
76  size_t len = path.size();
77  for ( ; len > 0 && path[len-1] == '/'; --len)
78  ;
79 
80  if (len != path.size())
81  {
82  clean = path.substr(0, len);
83  cleaned = &clean;
84  }
85 }
86 
87 static void
89 {
90  size_t slash = path.rfind('/');
91  if (slash != std::string::npos)
92  {
93  dir.append(path, 0, slash);
94  name.append(path, slash+1, std::string::npos);
95  }
96  else
97  name = path;
98 }
99 
100 static void
102 {
103  path.reserve(dir.size() + name.size() + 2);
104  path += dir;
105  if (! path.empty())
106  path += '/';
107  path += name;
108 }
109 
110 template <class T>
111 QCriterion *
113 { return new T(qtname); }
114 
115 template <class T>
116 void
118 { m[T::getAlgoName()] = &makeQCriterion<T>; }
119 
120 
122 fastmatch::fastmatch (std::string const& _fastString) :
123  fastString_ (_fastString), matching_ (UseFull)
124 {
125  try
126  {
127  regexp_ = NULL;
128  regexp_ = new lat::Regexp(fastString_, 0, lat::Regexp::Wildcard);
129  regexp_->study();
130  }
131  catch (lat::Error &e)
132  {
133  delete regexp_;
134  raiseDQMError("DQMStore", "Invalid wildcard pattern '%s' in quality"
135  " test specification", fastString_.c_str());
136  }
137 
138  // count stars ( "*" )
139  size_t starCount = 0;
140  int pos = -1;
141  while (true)
142  {
143  pos = fastString_.find("*", pos + 1 );
144  if ((size_t)pos == std::string::npos)
145  break;
146  starCount ++;
147  }
148 
149  // investigate for heuristics
150  if ((fastString_.find('"') != std::string::npos) ||
151  (fastString_.find(']') != std::string::npos) ||
152  (fastString_.find('?') != std::string::npos) ||
153  (fastString_.find('\\') != std::string::npos) ||
154  (starCount > 2))
155  {
156  // no fast version can be used
157  return;
158  }
159 
160  // match for pattern "*MyString" and "MyString*"
161  if (starCount == 1)
162  {
163  if (boost::algorithm::starts_with(fastString_, "*"))
164  {
166  fastString_.erase(0,1);
167  return;
168  }
169 
170  if (boost::algorithm::ends_with(fastString_, "*"))
171  {
173  fastString_.erase(fastString_.length()-1,1);
174  return;
175  }
176  }
177 
178  // match for pattern "*MyString*"
179  if (starCount == 2)
180  {
181  if (boost::algorithm::starts_with(fastString_, "*") &&
182  boost::algorithm::ends_with(fastString_, "*"))
183  {
184  matching_ = TwoStar;
185  fastString_.erase(0,1);
186  fastString_.erase(fastString_.size() - 1, 1);
187  return;
188  }
189  }
190 }
191 
193 {
194  if (regexp_ != NULL)
195  delete regexp_;
196 }
197 
199  std::string const& input) const
200 {
201  if (input.size() < pattern.size())
202  return false;
203 
204  // compare the two strings character by character for equalness:
205  // this does not create uneeded copies of std::string. The
206  // boost::algorithm implementation does
207  std::string::const_reverse_iterator rit_pattern = pattern.rbegin();
208  std::string::const_reverse_iterator rit_input = input.rbegin();
209 
210  for (; rit_pattern < pattern.rend(); rit_pattern++, rit_input++)
211  {
212  if (*rit_pattern != *rit_input)
213  // found a difference, fail
214  return false;
215  }
216  return true;
217 }
218 
220  std::string const& input) const
221 {
222  if (input.size() < pattern.size())
223  return false;
224 
225  // compare the two strings character by character for equalness:
226  // this does not create uneeded copies of std::string. The
227  // boost::algorithm implementation does.
228  std::string::const_iterator rit_pattern = pattern.begin();
229  std::string::const_iterator rit_input = input.begin();
230 
231  for (; rit_pattern < pattern.end(); rit_pattern++, rit_input++)
232  {
233  if (*rit_pattern != *rit_input)
234  // found a difference, fail
235  return false;
236  }
237  return true;
238 }
239 
240 bool fastmatch::match(std::string const& s) const
241 {
242  switch (matching_)
243  {
244  case OneStarStart:
246 
247  case OneStarEnd:
248  return compare_strings(fastString_, s);
249 
250  case TwoStar:
251  return (s.find(fastString_) != std::string::npos);
252 
253  default:
254  return regexp_->match(s);
255  }
256 }
257 
260  : verbose_ (1),
261  verboseQT_ (1),
262  reset_ (false),
263  collateHistograms_ (false),
264  readSelectedDirectory_ (""),
265  pwd_ ("")
266 {
267  initializeFrom(pset);
268  if(pset.getUntrackedParameter<bool>("forceResetOnBeginRun",false)) {
270  }
271  std::cout << __LINE__ << " DQMStore::DQMStore " << std::endl;
272 }
273 
275  : verbose_ (1),
276  verboseQT_ (1),
277  reset_ (false),
278  collateHistograms_ (false),
279  readSelectedDirectory_ (""),
280  pwd_ ("")
281 {
282  initializeFrom(pset);
283 }
284 
286 {
287  for (QCMap::iterator i = qtests_.begin(), e = qtests_.end(); i != e; ++i)
288  delete i->second;
289 
290  for (QTestSpecs::iterator i = qtestspecs_.begin(), e = qtestspecs_.end(); i != e; ++i)
291  delete i->first;
292 
293 }
294 
295 void
297  makeDirectory("");
298  reset();
299 
300  // set steerable parameters
301  verbose_ = pset.getUntrackedParameter<int>("verbose", 0);
302  if (verbose_ > 0)
303  std::cout << "DQMStore: verbosity set to " << verbose_ << std::endl;
304 
305  verboseQT_ = pset.getUntrackedParameter<int>("verboseQT", 0);
306  if (verbose_ > 0)
307  std::cout << "DQMStore: QTest verbosity set to " << verboseQT_ << std::endl;
308 
309  collateHistograms_ = pset.getUntrackedParameter<bool>("collateHistograms", false);
310  if (collateHistograms_)
311  std::cout << "DQMStore: histogram collation is enabled\n";
312 
313  std::string ref = pset.getUntrackedParameter<std::string>("referenceFileName", "");
314  if (! ref.empty())
315  {
316  std::cout << "DQMStore: using reference file '" << ref << "'\n";
317  readFile(ref, true, "", s_referenceDirName, StripRunDirs, false);
318  }
319 
320  initQCriterion<Comp2RefChi2>(qalgos_);
321  initQCriterion<Comp2RefKolmogorov>(qalgos_);
322  initQCriterion<ContentsXRange>(qalgos_);
323  initQCriterion<ContentsYRange>(qalgos_);
324  initQCriterion<MeanWithinExpected>(qalgos_);
325  initQCriterion<Comp2RefEqualH>(qalgos_);
326  initQCriterion<DeadChannel>(qalgos_);
327  initQCriterion<NoisyChannel>(qalgos_);
328  initQCriterion<ContentsWithinExpected>(qalgos_);
329  initQCriterion<CompareToMedian>(qalgos_);
330  initQCriterion<CompareLastFilledBin>(qalgos_);
331 
332  scaleFlag_ = pset.getUntrackedParameter<double>("ScalingFlag", 0.0);
333  if (verbose_ > 0)
334  std::cout << "DQMStore: Scaling Flag set to " << scaleFlag_ << std::endl;
335 }
336 
337 /* Generic method to do a backtrace and print it to stdout. It is
338  customised to properly get the routine that called the booking of the
339  histograms, which, following the usual stack, is at position 4. The
340  name of the calling function is properly demangled and the original
341  shared library including this function is also printed. For a more
342  detailed explanation of the routines involved, see here:
343  http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
344  http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html.*/
345 
346 void
348 {
349  static std::ofstream stream("histogramBookingBT.log");
350  void *array[10];
351  size_t size;
352  char **strings;
353  int r=0;
354  lat::RegexpMatch m;
355  m.reset();
356 
357  size = backtrace (array, 10);
358  strings = backtrace_symbols (array, size);
359 
360  if ((size > 4)
361  &&s_rxtrace.match(strings[4], 0, 0, &m))
362  {
363  char * demangled = abi::__cxa_demangle(m.matchString(strings[4], 2).c_str(), 0, 0, &r);
364  stream << "\"" << dir << "/"
365  << name << "\" "
366  << (r ? m.matchString(strings[4], 2) : demangled) << " "
367  << m.matchString(strings[4], 1) << "\n";
368  free(demangled);
369  }
370  else
371  stream << "Skipping "<< dir << "/" << name
372  << " with stack size " << size << "\n";
373  /* In this case print the full stack trace, up to main or to the
374  * maximum stack size, i.e. 10. */
375  if (verbose_ > 4)
376  {
377  size_t i;
378  m.reset();
379 
380  for (i = 0; i < size; i++)
381  if (s_rxtrace.match(strings[i], 0, 0, &m))
382  {
383  char * demangled = abi::__cxa_demangle(m.matchString(strings[i], 2).c_str(), 0, 0, &r);
384  stream << "\t\t" << i << "/" << size << " "
385  << (r ? m.matchString(strings[i], 2) : demangled) << " "
386  << m.matchString(strings[i], 1) << std::endl;
387  free (demangled);
388  }
389  }
390  free (strings);
391 }
392 
397 void
398 DQMStore::setVerbose(unsigned /* level */)
399 { return; }
400 
405 const std::string &
406 DQMStore::pwd(void) const
407 { return pwd_; }
408 
410 void
412 { setCurrentFolder(""); }
413 
415 void
416 DQMStore::cd(const std::string &subdir)
417 {
419  const std::string *cleaned = 0;
420  cleanTrailingSlashes(subdir, clean, cleaned);
421 
422  if (! dirExists(*cleaned))
423  raiseDQMError("DQMStore", "Cannot 'cd' into non-existent directory '%s'",
424  cleaned->c_str());
425 
426  setCurrentFolder(*cleaned);
427 }
428 
433 void
435 {
437  const std::string *cleaned = 0;
438  cleanTrailingSlashes(fullpath, clean, cleaned);
439  makeDirectory(*cleaned);
440  pwd_ = *cleaned;
441 }
442 
444 void
446 {
447  size_t pos = pwd_.rfind('/');
448  if (pos == std::string::npos)
449  setCurrentFolder("");
450  else
451  setCurrentFolder(pwd_.substr(0, pos));
452 }
453 
454 // -------------------------------------------------------------------
456 void
458 {
459  std::string prev;
460  std::string subdir;
462  prev.reserve(path.size());
463  subdir.reserve(path.size());
464  name.reserve(path.size());
465  size_t prevname = 0;
466  size_t slash = 0;
467 
468  while (true)
469  {
470  // Create this subdirectory component.
471  subdir.clear();
472  subdir.append(path, 0, slash);
473  name.clear();
474  name.append(subdir, prevname, std::string::npos);
475  if (! prev.empty() && findObject(prev, name))
476  raiseDQMError("DQMStore", "Attempt to create subdirectory '%s'"
477  " which already exists as a monitor element",
478  subdir.c_str());
479 
480  if (! dirs_.count(subdir))
481  dirs_.insert(subdir);
482 
483  // Stop if we've reached the end (including possibly a trailing slash).
484  if (slash+1 >= path.size())
485  break;
486 
487  // Find the next slash, making sure we progress. If reach the end,
488  // process the last path component; the next loop round will terminate.
489  prevname = slash ? slash+1 : slash;
490  prev = subdir;
491  if ((slash = path.find('/', ++slash)) == std::string::npos)
492  slash = path.size();
493  }
494 }
495 
497 bool
499 { return dirs_.count(path) > 0; }
500 
504 template <class HISTO, class COLLATE>
507  const char *context, int kind,
508  HISTO *h, COLLATE collate)
509 {
510  assert(name.find('/') == std::string::npos);
511  if (verbose_ > 3)
512  print_trace(dir, name);
514  mergePath(path, dir, name);
515 
516  // Put us in charge of h.
517  h->SetDirectory(0);
518 
519  // Check if the request monitor element already exists.
520  MonitorElement *me = findObject(dir, name);
521  if (me)
522  {
523  if (collateHistograms_)
524  {
525  collate(me, h);
526  delete h;
527  return me;
528  }
529  else
530  {
531  if (verbose_ > 1)
532  std::cout << "DQMStore: "
533  << context << ": monitor element '"
534  << path << "' already exists, collating" << std::endl;
535  me->Reset();
536  collate(me, h);
537  delete h;
538  return me;
539  }
540  }
541  else
542  {
543  // Create and initialise core object.
544  assert(dirs_.count(dir));
545  MonitorElement proto(&*dirs_.find(dir), name);
546  me = const_cast<MonitorElement &>(*data_.insert(proto).first)
548 
549  // Initialise quality test information.
550  QTestSpecs::iterator qi = qtestspecs_.begin();
551  QTestSpecs::iterator qe = qtestspecs_.end();
552  for ( ; qi != qe; ++qi)
553  {
554  if ( qi->first->match(path) )
555  me->addQReport(qi->second);
556  }
557 
558  // Assign reference if we have one.
559  std::string refdir;
560  refdir.reserve(s_referenceDirName.size() + dir.size() + 2);
561  refdir += s_referenceDirName;
562  refdir += '/';
563  refdir += dir;
564 
565  if (MonitorElement *refme = findObject(refdir, name))
566  {
567  me->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
568  me->reference_ = refme->object_;
569  }
570 
571  // Return the monitor element.
572  return me;
573  }
574 }
575 
578  const std::string &name,
579  const char *context)
580 {
581  assert(name.find('/') == std::string::npos);
582  if (verbose_ > 3)
583  print_trace(dir, name);
584 
585  // Check if the request monitor element already exists.
586  if (MonitorElement *me = findObject(dir, name))
587  {
588  if (verbose_ > 1)
589  {
591  mergePath(path, dir, name);
592 
593  std::cout << "DQMStore: "
594  << context << ": monitor element '"
595  << path << "' already exists, resetting" << std::endl;
596  }
597  me->Reset();
598  return me;
599  }
600  else
601  {
602  // Create it and return for initialisation.
603  assert(dirs_.count(dir));
604  MonitorElement nme(&*dirs_.find(dir), name);
605  return &const_cast<MonitorElement &>(*data_.insert(nme).first);
606  }
607 }
608 
609 // -------------------------------------------------------------------
613 {
614  if (collateHistograms_)
615  {
616  if (MonitorElement *me = findObject(dir, name))
617  {
618  me->Fill(0);
619  return me;
620  }
621  }
622 
623  return book(dir, name, "bookInt")
625 }
626 
630 { return bookInt(pwd_, name); }
631 
635 {
636  return bookInt(pwd_, name);
637 }
638 
639 // -------------------------------------------------------------------
643 {
644  if (collateHistograms_)
645  {
646  if (MonitorElement *me = findObject(dir, name))
647  {
648  me->Fill(0.);
649  return me;
650  }
651  }
652 
653  return book(dir, name, "bookFloat")
655 }
656 
660 { return bookFloat(pwd_, name); }
661 
665 {
666  return bookFloat(pwd_, name);
667 }
668 
669 // -------------------------------------------------------------------
673  const std::string &name,
674  const std::string &value)
675 {
676  if (collateHistograms_)
677  {
678  if (MonitorElement *me = findObject(dir, name))
679  return me;
680  }
681 
682  return book(dir, name, "bookString")
684 }
685 
688 DQMStore::bookString(const char *name, const char *value)
689 { return bookString(pwd_, name, value); }
690 
694 {
695  return bookString(pwd_, name, value);
696 }
697 
698 // -------------------------------------------------------------------
702 {
703  return book(dir, name, "book1D", MonitorElement::DQM_KIND_TH1F, h, collate1D);
704 }
705 
709 {
710  return book(dir, name, "book1S", MonitorElement::DQM_KIND_TH1S, h, collate1S);
711 }
712 
716 {
717  return book(dir, name, "book1DD", MonitorElement::DQM_KIND_TH1D, h, collate1DD);
718 }
719 
722 DQMStore::book1D(const char *name, const char *title,
723  int nchX, double lowX, double highX)
724 {
725  return book1D(pwd_, name, new TH1F(name, title, nchX, lowX, highX));
726 }
727 
731  int nchX, double lowX, double highX)
732 {
733  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, lowX, highX));
734 }
735 
738 DQMStore::book1S(const char *name, const char *title,
739  int nchX, double lowX, double highX)
740 {
741  return book1S(pwd_, name, new TH1S(name, title, nchX, lowX, highX));
742 }
743 
747  int nchX, double lowX, double highX)
748 {
749  return book1S(pwd_, name, new TH1S(name.c_str(), title.c_str(), nchX, lowX, highX));
750 }
751 
754 DQMStore::book1DD(const char *name, const char *title,
755  int nchX, double lowX, double highX)
756 {
757  return book1DD(pwd_, name, new TH1D(name, title, nchX, lowX, highX));
758 }
759 
763  int nchX, double lowX, double highX)
764 {
765  return book1DD(pwd_, name, new TH1D(name.c_str(), title.c_str(), nchX, lowX, highX));
766 }
767 
770 DQMStore::book1D(const char *name, const char *title,
771  int nchX, float *xbinsize)
772 {
773  return book1D(pwd_, name, new TH1F(name, title, nchX, xbinsize));
774 }
775 
779  int nchX, float *xbinsize)
780 {
781  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, xbinsize));
782 }
783 
786 DQMStore::book1D(const char *name, TH1F *source)
787 {
788  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name)));
789 }
790 
794 {
795  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name.c_str())));
796 }
797 
800 DQMStore::book1S(const char *name, TH1S *source)
801 {
802  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name)));
803 }
804 
808 {
809  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name.c_str())));
810 }
811 
814 DQMStore::book1DD(const char *name, TH1D *source)
815 {
816  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name)));
817 }
818 
822 {
823  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name.c_str())));
824 }
825 
826 // -------------------------------------------------------------------
830 {
831  return book(dir, name, "book2D", MonitorElement::DQM_KIND_TH2F, h, collate2D);
832 }
833 
837 {
838  return book(dir, name, "book2S", MonitorElement::DQM_KIND_TH2S, h, collate2S);
839 }
840 
844 {
845  return book(dir, name, "book2DD", MonitorElement::DQM_KIND_TH2D, h, collate2DD);
846 }
847 
850 DQMStore::book2D(const char *name, const char *title,
851  int nchX, double lowX, double highX,
852  int nchY, double lowY, double highY)
853 {
854  return book2D(pwd_, name, new TH2F(name, title,
855  nchX, lowX, highX,
856  nchY, lowY, highY));
857 }
858 
862  int nchX, double lowX, double highX,
863  int nchY, double lowY, double highY)
864 {
865  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
866  nchX, lowX, highX,
867  nchY, lowY, highY));
868 }
869 
872 DQMStore::book2S(const char *name, const char *title,
873  int nchX, double lowX, double highX,
874  int nchY, double lowY, double highY)
875 {
876  return book2S(pwd_, name, new TH2S(name, title,
877  nchX, lowX, highX,
878  nchY, lowY, highY));
879 }
880 
884  int nchX, double lowX, double highX,
885  int nchY, double lowY, double highY)
886 {
887  return book2S(pwd_, name, new TH2S(name.c_str(), title.c_str(),
888  nchX, lowX, highX,
889  nchY, lowY, highY));
890 }
891 
894 DQMStore::book2DD(const char *name, const char *title,
895  int nchX, double lowX, double highX,
896  int nchY, double lowY, double highY)
897 {
898  return book2DD(pwd_, name, new TH2D(name, title,
899  nchX, lowX, highX,
900  nchY, lowY, highY));
901 }
902 
906  int nchX, double lowX, double highX,
907  int nchY, double lowY, double highY)
908 {
909  return book2DD(pwd_, name, new TH2D(name.c_str(), title.c_str(),
910  nchX, lowX, highX,
911  nchY, lowY, highY));
912 }
913 
916 DQMStore::book2D(const char *name, const char *title,
917  int nchX, float *xbinsize, int nchY, float *ybinsize)
918 {
919  return book2D(pwd_, name, new TH2F(name, title,
920  nchX, xbinsize, nchY, ybinsize));
921 }
922 
926  int nchX, float *xbinsize, int nchY, float *ybinsize)
927 {
928  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
929  nchX, xbinsize, nchY, ybinsize));
930 }
931 
934 DQMStore::book2D(const char *name, TH2F *source)
935 {
936  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name)));
937 }
938 
942 {
943  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name.c_str())));
944 }
945 
948 DQMStore::book2S(const char *name, TH2S *source)
949 {
950  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name)));
951 }
952 
956 {
957  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name.c_str())));
958 }
959 
962 DQMStore::book2DD(const char *name, TH2D *source)
963 {
964  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name)));
965 }
966 
970 {
971  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name.c_str())));
972 }
973 
974 // -------------------------------------------------------------------
978 {
979  return book(dir, name, "book3D", MonitorElement::DQM_KIND_TH3F, h, collate3D);
980 }
981 
984 DQMStore::book3D(const char *name, const char *title,
985  int nchX, double lowX, double highX,
986  int nchY, double lowY, double highY,
987  int nchZ, double lowZ, double highZ)
988 {
989  return book3D(pwd_, name, new TH3F(name, title,
990  nchX, lowX, highX,
991  nchY, lowY, highY,
992  nchZ, lowZ, highZ));
993 }
994 
998  int nchX, double lowX, double highX,
999  int nchY, double lowY, double highY,
1000  int nchZ, double lowZ, double highZ)
1001 {
1002  return book3D(pwd_, name, new TH3F(name.c_str(), title.c_str(),
1003  nchX, lowX, highX,
1004  nchY, lowY, highY,
1005  nchZ, lowZ, highZ));
1006 }
1007 
1010 DQMStore::book3D(const char *name, TH3F *source)
1011 {
1012  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name)));
1013 }
1014 
1018 {
1019  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name.c_str())));
1020 }
1021 
1022 // -------------------------------------------------------------------
1026 {
1027  return book(dir, name, "bookProfile",
1029  h, collateProfile);
1030 }
1031 
1036 DQMStore::bookProfile(const char *name, const char *title,
1037  int nchX, double lowX, double highX,
1038  int /* nchY */, double lowY, double highY,
1039  const char *option /* = "s" */)
1040 {
1041  return bookProfile(pwd_, name, new TProfile(name, title,
1042  nchX, lowX, highX,
1043  lowY, highY,
1044  option));
1045 }
1046 
1052  int nchX, double lowX, double highX,
1053  int /* nchY */, double lowY, double highY,
1054  const char *option /* = "s" */)
1055 {
1056  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1057  nchX, lowX, highX,
1058  lowY, highY,
1059  option));
1060 }
1061 
1066 DQMStore::bookProfile(const char *name, const char *title,
1067  int nchX, double lowX, double highX,
1068  double lowY, double highY,
1069  const char *option /* = "s" */)
1070 {
1071  return bookProfile(pwd_, name, new TProfile(name, title,
1072  nchX, lowX, highX,
1073  lowY, highY,
1074  option));
1075 }
1076 
1082  int nchX, double lowX, double highX,
1083  double lowY, double highY,
1084  const char *option /* = "s" */)
1085 {
1086  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1087  nchX, lowX, highX,
1088  lowY, highY,
1089  option));
1090 }
1091 
1096 DQMStore::bookProfile(const char *name, const char *title,
1097  int nchX, double *xbinsize,
1098  int /* nchY */, double lowY, double highY,
1099  const char *option /* = "s" */)
1100 {
1101  return bookProfile(pwd_, name, new TProfile(name, title,
1102  nchX, xbinsize,
1103  lowY, highY,
1104  option));
1105 }
1106 
1112  int nchX, double *xbinsize,
1113  int /* nchY */, double lowY, double highY,
1114  const char *option /* = "s" */)
1115 {
1116  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1117  nchX, xbinsize,
1118  lowY, highY,
1119  option));
1120 }
1121 
1126 DQMStore::bookProfile(const char *name, const char *title,
1127  int nchX, double *xbinsize,
1128  double lowY, double highY,
1129  const char *option /* = "s" */)
1130 {
1131  return bookProfile(pwd_, name, new TProfile(name, title,
1132  nchX, xbinsize,
1133  lowY, highY,
1134  option));
1135 }
1136 
1142  int nchX, double *xbinsize,
1143  double lowY, double highY,
1144  const char *option /* = "s" */)
1145 {
1146  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1147  nchX, xbinsize,
1148  lowY, highY,
1149  option));
1150 }
1151 
1154 DQMStore::bookProfile(const char *name, TProfile *source)
1155 {
1156  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name)));
1157 }
1158 
1162 {
1163  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name.c_str())));
1164 }
1165 
1166 // -------------------------------------------------------------------
1170 {
1171  return book(dir, name, "bookProfile2D",
1173  h, collateProfile2D);
1174 }
1175 
1180 DQMStore::bookProfile2D(const char *name, const char *title,
1181  int nchX, double lowX, double highX,
1182  int nchY, double lowY, double highY,
1183  int /* nchZ */, double lowZ, double highZ,
1184  const char *option /* = "s" */)
1185 {
1186  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1187  nchX, lowX, highX,
1188  nchY, lowY, highY,
1189  lowZ, highZ,
1190  option));
1191 }
1192 
1198  int nchX, double lowX, double highX,
1199  int nchY, double lowY, double highY,
1200  int /* nchZ */, double lowZ, double highZ,
1201  const char *option /* = "s" */)
1202 {
1203  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1204  nchX, lowX, highX,
1205  nchY, lowY, highY,
1206  lowZ, highZ,
1207  option));
1208 }
1209 
1214 DQMStore::bookProfile2D(const char *name, const char *title,
1215  int nchX, double lowX, double highX,
1216  int nchY, double lowY, double highY,
1217  double lowZ, double highZ,
1218  const char *option /* = "s" */)
1219 {
1220  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1221  nchX, lowX, highX,
1222  nchY, lowY, highY,
1223  lowZ, highZ,
1224  option));
1225 }
1226 
1232  int nchX, double lowX, double highX,
1233  int nchY, double lowY, double highY,
1234  double lowZ, double highZ,
1235  const char *option /* = "s" */)
1236 {
1237  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1238  nchX, lowX, highX,
1239  nchY, lowY, highY,
1240  lowZ, highZ,
1241  option));
1242 }
1243 
1246 DQMStore::bookProfile2D(const char *name, TProfile2D *source)
1247 {
1248  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name)));
1249 }
1250 
1254 {
1255  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name.c_str())));
1256 }
1257 
1261 bool
1263 {
1264  if (me->getTH1()->GetNbinsX() != h->GetNbinsX()
1265  || me->getTH1()->GetNbinsY() != h->GetNbinsY()
1266  || me->getTH1()->GetNbinsZ() != h->GetNbinsZ()
1267  || me->getTH1()->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin()
1268  || me->getTH1()->GetYaxis()->GetXmin() != h->GetYaxis()->GetXmin()
1269  || me->getTH1()->GetZaxis()->GetXmin() != h->GetZaxis()->GetXmin()
1270  || me->getTH1()->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax()
1271  || me->getTH1()->GetYaxis()->GetXmax() != h->GetYaxis()->GetXmax()
1272  || me->getTH1()->GetZaxis()->GetXmax() != h->GetZaxis()->GetXmax())
1273  {
1274  // edm::LogWarning ("DQMStore")
1275  std::cout << "*** DQMStore: WARNING:"
1276  << "checkBinningMatches: different binning - cannot add object '"
1277  << h->GetName() << "' of type "
1278  << h->IsA()->GetName() << " to existing ME: '"
1279  << me->getFullname() << "'\n";
1280  return false;
1281  }
1282  return true;
1283 }
1284 
1285 void
1287 {
1288  if (checkBinningMatches(me,h))
1289  me->getTH1F()->Add(h);
1290 }
1291 
1292 void
1294 {
1295  if (checkBinningMatches(me,h))
1296  me->getTH1S()->Add(h);
1297 }
1298 
1299 void
1301 {
1302  if (checkBinningMatches(me,h))
1303  me->getTH1D()->Add(h);
1304 }
1305 
1306 void
1308 {
1309  if (checkBinningMatches(me,h))
1310  me->getTH2F()->Add(h);
1311 }
1312 
1313 void
1315 {
1316  if (checkBinningMatches(me,h))
1317  me->getTH2S()->Add(h);
1318 }
1319 
1320 void
1322 {
1323  if (checkBinningMatches(me,h))
1324  me->getTH2D()->Add(h);
1325 }
1326 
1327 void
1329 {
1330  if (checkBinningMatches(me,h))
1331  me->getTH3F()->Add(h);
1332 }
1333 
1334 void
1336 {
1337  if (checkBinningMatches(me,h))
1338  {
1339  TProfile *meh = me->getTProfile();
1340  me->addProfiles(h, meh, meh, 1, 1);
1341  }
1342 }
1343 
1344 void
1346 {
1347  if (checkBinningMatches(me,h))
1348  {
1349  TProfile2D *meh = me->getTProfile2D();
1350  me->addProfiles(h, meh, meh, 1, 1);
1351  }
1352 }
1353 
1358 void
1359 DQMStore::tag(MonitorElement *me, unsigned int myTag)
1360 {
1361  if (! myTag)
1362  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1363  " with a zero tag", me->getFullname().c_str());
1364  if ((me->data_.flags & DQMNet::DQM_PROP_TAGGED) && myTag != me->data_.tag)
1365  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1366  " twice with multiple tags", me->getFullname().c_str());
1367 
1368  me->data_.tag = myTag;
1370 }
1371 
1373 void
1374 DQMStore::tag(const std::string &path, unsigned int myTag)
1375 {
1376  std::string dir;
1377  std::string name;
1378  splitPath(dir, name, path);
1379 
1380  if (MonitorElement *me = findObject(dir, name))
1381  tag(me, myTag);
1382  else
1383  raiseDQMError("DQMStore", "Attempt to tag non-existent monitor element"
1384  " '%s' with tag %u", path.c_str(), myTag);
1385 
1386 }
1387 
1389 void
1390 DQMStore::tagContents(const std::string &path, unsigned int myTag)
1391 {
1392  MonitorElement proto(&path, std::string());
1393  MEMap::iterator e = data_.end();
1394  MEMap::iterator i = data_.lower_bound(proto);
1395  for ( ; i != e && path == *i->data_.dirname; ++i)
1396  tag(const_cast<MonitorElement *>(&*i), myTag);
1397 }
1398 
1401 void
1402 DQMStore::tagAllContents(const std::string &path, unsigned int myTag)
1403 {
1405  const std::string *cleaned = 0;
1406  cleanTrailingSlashes(path, clean, cleaned);
1407  MonitorElement proto(cleaned, std::string());
1408 
1409  // FIXME: WILDCARDS? Old one supported them, but nobody seemed to use them.
1410  MEMap::iterator e = data_.end();
1411  MEMap::iterator i = data_.lower_bound(proto);
1412  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
1413  {
1414  tag(const_cast<MonitorElement *>(&*i), myTag);
1415  ++i;
1416  }
1417 }
1418 
1423 std::vector<std::string>
1425 {
1426  std::vector<std::string> result;
1427  std::set<std::string>::const_iterator e = dirs_.end();
1428  std::set<std::string>::const_iterator i = dirs_.find(pwd_);
1429 
1430  // If we didn't find current directory, the tree is empty, so quit.
1431  if (i == e)
1432  return result;
1433 
1434  // Skip the current directory and then start looking for immediate
1435  // subdirectories in the dirs_ list. Stop when we are no longer in
1436  // (direct or indirect) subdirectories of pwd_. Note that we don't
1437  // "know" which order the set will sort A/B, A/B/C and A/D.
1438  while (++i != e && isSubdirectory(pwd_, *i))
1439  if (i->find('/', pwd_.size()+1) == std::string::npos)
1440  result.push_back(*i);
1441 
1442  return result;
1443 }
1444 
1446 std::vector<std::string>
1447 DQMStore::getMEs(void) const
1448 {
1449  MonitorElement proto(&pwd_, std::string());
1450  std::vector<std::string> result;
1451  MEMap::const_iterator e = data_.end();
1452  MEMap::const_iterator i = data_.lower_bound(proto);
1453  for ( ; i != e && isSubdirectory(pwd_, *i->data_.dirname); ++i)
1454  if (pwd_ == *i->data_.dirname)
1455  result.push_back(i->getName());
1456 
1457  return result;
1458 }
1459 
1462 bool
1464 {
1465  MonitorElement proto(&path, std::string());
1466  MEMap::const_iterator e = data_.end();
1467  MEMap::const_iterator i = data_.lower_bound(proto);
1468  return (i != e && isSubdirectory(path, *i->data_.dirname));
1469 }
1470 
1474 {
1475  std::string dir;
1476  std::string name;
1477  splitPath(dir, name, path);
1478  MonitorElement proto(&dir, name);
1479  MEMap::const_iterator mepos = data_.find(proto);
1480  return (mepos == data_.end() ? 0
1481  : const_cast<MonitorElement *>(&*mepos));
1482 }
1483 
1485 std::vector<MonitorElement *>
1486 DQMStore::get(unsigned int tag) const
1487 {
1488  // FIXME: Use reverse map [tag -> path] / [tag -> dir]?
1489  std::vector<MonitorElement *> result;
1490  for (MEMap::const_iterator i = data_.begin(), e = data_.end(); i != e; ++i)
1491  {
1492  const MonitorElement &me = *i;
1493  if ((me.data_.flags & DQMNet::DQM_PROP_TAGGED) && me.data_.tag == tag)
1494  result.push_back(const_cast<MonitorElement *>(&me));
1495  }
1496  return result;
1497 }
1498 
1501 std::vector<MonitorElement *>
1503 {
1505  const std::string *cleaned = 0;
1506  cleanTrailingSlashes(path, clean, cleaned);
1507  MonitorElement proto(cleaned, std::string());
1508 
1509  std::vector<MonitorElement *> result;
1510  MEMap::const_iterator e = data_.end();
1511  MEMap::const_iterator i = data_.lower_bound(proto);
1512  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1513  if (*cleaned == *i->data_.dirname)
1514  result.push_back(const_cast<MonitorElement *>(&*i));
1515 
1516  return result;
1517 }
1518 
1520 std::vector<MonitorElement *>
1521 DQMStore::getContents(const std::string &path, unsigned int tag) const
1522 {
1524  const std::string *cleaned = 0;
1525  cleanTrailingSlashes(path, clean, cleaned);
1526  MonitorElement proto(cleaned, std::string());
1527 
1528  std::vector<MonitorElement *> result;
1529  MEMap::const_iterator e = data_.end();
1530  MEMap::const_iterator i = data_.lower_bound(proto);
1531  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1532  if (*cleaned == *i->data_.dirname
1533  && (i->data_.flags & DQMNet::DQM_PROP_TAGGED)
1534  && i->data_.tag == tag)
1535  result.push_back(const_cast<MonitorElement *>(&*i));
1536 
1537  return result;
1538 }
1539 
1544 void
1545 DQMStore::getContents(std::vector<std::string> &into, bool showContents /* = true */) const
1546 {
1547  into.clear();
1548  into.reserve(dirs_.size());
1549 
1550  MEMap::const_iterator me = data_.end();
1551  std::set<std::string>::const_iterator di = dirs_.begin();
1552  std::set<std::string>::const_iterator de = dirs_.end();
1553  for ( ; di != de; ++di)
1554  {
1555  MonitorElement proto(&*di, std::string());
1556  MEMap::const_iterator mi = data_.lower_bound(proto);
1557  MEMap::const_iterator m = mi;
1558  size_t sz = di->size() + 2;
1559  size_t nfound = 0;
1560  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1561  if (*di == *m->data_.dirname)
1562  {
1563  sz += m->data_.objname.size() + 1;
1564  ++nfound;
1565  }
1566 
1567  if (! nfound)
1568  continue;
1569 
1570  std::vector<std::string>::iterator istr
1571  = into.insert(into.end(), std::string());
1572 
1573  if (showContents)
1574  {
1575  istr->reserve(sz);
1576 
1577  *istr += *di;
1578  *istr += ':';
1579  for (sz = 0; mi != m; ++mi)
1580  {
1581  if (*di != *mi->data_.dirname)
1582  continue;
1583 
1584  if (sz > 0)
1585  *istr += ',';
1586 
1587  *istr += mi->data_.objname;
1588  ++sz;
1589  }
1590  }
1591  else
1592  {
1593  istr->reserve(di->size() + 2);
1594  *istr += *di;
1595  *istr += ':';
1596  }
1597  }
1598 }
1599 
1604 {
1605  if (dir.find_first_not_of(s_safe) != std::string::npos)
1606  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1607  " unacceptable characters", dir.c_str());
1608  if (name.find_first_not_of(s_safe) != std::string::npos)
1609  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1610  " unacceptable characters", name.c_str());
1611 
1612  MonitorElement proto;
1613  proto.data_.dirname = &dir;
1614  proto.data_.objname = name;
1615 
1616  MEMap::const_iterator mepos = data_.find(proto);
1617  return (mepos == data_.end() ? 0
1618  : const_cast<MonitorElement *>(&*mepos));
1619 }
1620 
1623 void
1624 DQMStore::getAllTags(std::vector<std::string> &into) const
1625 {
1626  into.clear();
1627  into.reserve(dirs_.size());
1628 
1629  MEMap::const_iterator me = data_.end();
1630  std::set<std::string>::const_iterator di = dirs_.begin();
1631  std::set<std::string>::const_iterator de = dirs_.end();
1632  char tagbuf[32]; // more than enough for '/' and up to 10 digits
1633 
1634  for ( ; di != de; ++di)
1635  {
1636  MonitorElement proto(&*di, std::string());
1637  MEMap::const_iterator mi = data_.lower_bound(proto);
1638  MEMap::const_iterator m = mi;
1639  size_t sz = di->size() + 2;
1640  size_t nfound = 0;
1641  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1642  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1643  {
1644  // the tags count for '/' + up to 10 digits, otherwise ',' + ME name
1645  sz += 1 + m->data_.objname.size() + 11;
1646  ++nfound;
1647  }
1648 
1649  if (! nfound)
1650  continue;
1651 
1652  std::vector<std::string>::iterator istr
1653  = into.insert(into.end(), std::string());
1654 
1655  istr->reserve(sz);
1656 
1657  *istr += *di;
1658  *istr += ':';
1659  for (sz = 0; mi != m; ++mi)
1660  {
1661  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1662  {
1663  sprintf(tagbuf, "/%u", mi->data_.tag);
1664  if (sz > 0)
1665  *istr += ',';
1666  *istr += m->data_.objname;
1667  *istr += tagbuf;
1668  ++sz;
1669  }
1670  }
1671  }
1672 }
1673 
1676 std::vector<MonitorElement*>
1678 {
1680  const std::string *cleaned = 0;
1681  cleanTrailingSlashes(path, clean, cleaned);
1682  MonitorElement proto(cleaned, std::string());
1683 
1684  std::vector<MonitorElement *> result;
1685  MEMap::const_iterator e = data_.end();
1686  MEMap::const_iterator i = data_.lower_bound(proto);
1687  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1688  result.push_back(const_cast<MonitorElement *>(&*i));
1689 
1690  return result;
1691 }
1692 
1695 std::vector<MonitorElement*>
1696 DQMStore::getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType /* = Wildcard */) const
1697 {
1698  lat::Regexp rx;
1699  try
1700  {
1701  rx = lat::Regexp(pattern, 0, syntaxType);
1702  rx.study();
1703  }
1704  catch (lat::Error &e)
1705  {
1706  raiseDQMError("DQMStore", "Invalid regular expression '%s': %s",
1707  pattern.c_str(), e.explain().c_str());
1708  }
1709 
1710  std::string path;
1711  std::vector<MonitorElement *> result;
1712  MEMap::const_iterator i = data_.begin();
1713  MEMap::const_iterator e = data_.end();
1714  for ( ; i != e; ++i)
1715  {
1716  path.clear();
1717  mergePath(path, *i->data_.dirname, i->data_.objname);
1718  if (rx.match(path))
1719  result.push_back(const_cast<MonitorElement *>(&*i));
1720  }
1721 
1722  return result;
1723 }
1724 
1728 
1731 void
1733 {
1734  MEMap::iterator mi = data_.begin();
1735  MEMap::iterator me = data_.end();
1736  for ( ; mi != me; ++mi)
1737  {
1738  MonitorElement &me = const_cast<MonitorElement &>(*mi);
1739  if (mi->wasUpdated())
1740  {
1741  if (me.resetMe())
1742  me.Reset();
1743  me.resetUpdate();
1744  }
1745  }
1746 
1747  reset_ = true;
1748 }
1749 
1753 
1755 void
1757 {
1758  MEMap::iterator mi = data_.begin();
1759  MEMap::iterator me = data_.end();
1760  for ( ; mi != me; ++mi)
1761  {
1762  MonitorElement &me = const_cast<MonitorElement &>(*mi);
1763  me.Reset();
1764  me.resetUpdate();
1765  }
1766 
1767  reset_ = true;
1768 }
1769 
1775 bool
1776 DQMStore::extract(TObject *obj, const std::string &dir, bool overwrite)
1777 {
1778  // NB: Profile histograms inherit from TH*D, checking order matters.
1779  MonitorElement *refcheck = 0;
1780  if (TProfile *h = dynamic_cast<TProfile *>(obj))
1781  {
1782  MonitorElement *me = findObject(dir, h->GetName());
1783  if (! me)
1784  me = bookProfile(dir, h->GetName(), (TProfile *) h->Clone());
1785  else if (overwrite)
1786  me->copyFrom(h);
1787  else if (isCollateME(me) || collateHistograms_)
1788  collateProfile(me, h);
1789  refcheck = me;
1790  }
1791  else if (TProfile2D *h = dynamic_cast<TProfile2D *>(obj))
1792  {
1793  MonitorElement *me = findObject(dir, h->GetName());
1794  if (! me)
1795  me = bookProfile2D(dir, h->GetName(), (TProfile2D *) h->Clone());
1796  else if (overwrite)
1797  me->copyFrom(h);
1798  else if (isCollateME(me) || collateHistograms_)
1799  collateProfile2D(me, h);
1800  refcheck = me;
1801  }
1802  else if (TH1F *h = dynamic_cast<TH1F *>(obj))
1803  {
1804  MonitorElement *me = findObject(dir, h->GetName());
1805  if (! me)
1806  me = book1D(dir, h->GetName(), (TH1F *) h->Clone());
1807  else if (overwrite)
1808  me->copyFrom(h);
1809  else if (isCollateME(me) || collateHistograms_)
1810  collate1D(me, h);
1811  refcheck = me;
1812  }
1813  else if (TH1S *h = dynamic_cast<TH1S *>(obj))
1814  {
1815  MonitorElement *me = findObject(dir, h->GetName());
1816  if (! me)
1817  me = book1S(dir, h->GetName(), (TH1S *) h->Clone());
1818  else if (overwrite)
1819  me->copyFrom(h);
1820  else if (isCollateME(me) || collateHistograms_)
1821  collate1S(me, h);
1822  refcheck = me;
1823  }
1824  else if (TH1D *h = dynamic_cast<TH1D *>(obj))
1825  {
1826  MonitorElement *me = findObject(dir, h->GetName());
1827  if (! me)
1828  me = book1DD(dir, h->GetName(), (TH1D *) h->Clone());
1829  else if (overwrite)
1830  me->copyFrom(h);
1831  else if (isCollateME(me) || collateHistograms_)
1832  collate1DD(me, h);
1833  refcheck = me;
1834  }
1835  else if (TH2F *h = dynamic_cast<TH2F *>(obj))
1836  {
1837  MonitorElement *me = findObject(dir, h->GetName());
1838  if (! me)
1839  me = book2D(dir, h->GetName(), (TH2F *) h->Clone());
1840  else if (overwrite)
1841  me->copyFrom(h);
1842  else if (isCollateME(me) || collateHistograms_)
1843  collate2D(me, h);
1844  refcheck = me;
1845  }
1846  else if (TH2S *h = dynamic_cast<TH2S *>(obj))
1847  {
1848  MonitorElement *me = findObject(dir, h->GetName());
1849  if (! me)
1850  me = book2S(dir, h->GetName(), (TH2S *) h->Clone());
1851  else if (overwrite)
1852  me->copyFrom(h);
1853  else if (isCollateME(me) || collateHistograms_)
1854  collate2S(me, h);
1855  refcheck = me;
1856  }
1857  else if (TH2D *h = dynamic_cast<TH2D *>(obj))
1858  {
1859  MonitorElement *me = findObject(dir, h->GetName());
1860  if (! me)
1861  me = book2DD(dir, h->GetName(), (TH2D *) h->Clone());
1862  else if (overwrite)
1863  me->copyFrom(h);
1864  else if (isCollateME(me) || collateHistograms_)
1865  collate2DD(me, h);
1866  refcheck = me;
1867  }
1868  else if (TH3F *h = dynamic_cast<TH3F *>(obj))
1869  {
1870  MonitorElement *me = findObject(dir, h->GetName());
1871  if (! me)
1872  me = book3D(dir, h->GetName(), (TH3F *) h->Clone());
1873  else if (overwrite)
1874  me->copyFrom(h);
1875  else if (isCollateME(me) || collateHistograms_)
1876  collate3D(me, h);
1877  refcheck = me;
1878  }
1879  else if (dynamic_cast<TObjString *>(obj))
1880  {
1881  lat::RegexpMatch m;
1882  if (! s_rxmeval.match(obj->GetName(), 0, 0, &m))
1883  {
1884  if (strstr(obj->GetName(), "CMSSW"))
1885  {
1886  if (verbose_)
1887  std::cout << "Input file version: " << obj->GetName() << std::endl;
1888  return true;
1889  }
1890  else if (strstr(obj->GetName(), "DQMPATCH"))
1891  {
1892  if (verbose_)
1893  std::cout << "DQM patch version: " << obj->GetName() << std::endl;
1894  return true;
1895  }
1896  else
1897  {
1898  std::cout << "*** DQMStore: WARNING: cannot extract object '"
1899  << obj->GetName() << "' of type '"
1900  << obj->IsA()->GetName() << "'\n";
1901  return false;
1902  }
1903  }
1904 
1905  std::string label = m.matchString(obj->GetName(), 1);
1906  std::string kind = m.matchString(obj->GetName(), 2);
1907  std::string value = m.matchString(obj->GetName(), 3);
1908 
1909  if (kind == "i")
1910  {
1911  MonitorElement *me = findObject(dir, label);
1912  if (! me || overwrite)
1913  {
1914  if (! me) me = bookInt(dir, label);
1915  me->Fill(atoll(value.c_str()));
1916  }
1917  }
1918  else if (kind == "f")
1919  {
1920  MonitorElement *me = findObject(dir, label);
1921  if (! me || overwrite)
1922  {
1923  if (! me) me = bookFloat(dir, label);
1924  me->Fill(atof(value.c_str()));
1925  }
1926  }
1927  else if (kind == "s")
1928  {
1929  MonitorElement *me = findObject(dir, label);
1930  if (! me)
1931  me = bookString(dir, label, value);
1932  else if (overwrite)
1933  me->Fill(value);
1934  }
1935  else if (kind == "e")
1936  {
1937  MonitorElement *me = findObject(dir, label);
1938  if (! me)
1939  {
1940  std::cout << "*** DQMStore: WARNING: no monitor element '"
1941  << label << "' in directory '"
1942  << dir << "' to be marked as efficiency plot.\n";
1943  return false;
1944  }
1945  me->setEfficiencyFlag();
1946  }
1947  else if (kind == "t")
1948  {
1949  MonitorElement *me = findObject(dir, label);
1950  if (! me)
1951  {
1952  std::cout << "*** DQMStore: WARNING: no monitor element '"
1953  << label << "' in directory '"
1954  << dir << "' for a tag\n";
1955  return false;
1956  }
1957  errno = 0;
1958  char *endp = 0;
1959  unsigned long val = strtoul(value.c_str(), &endp, 10);
1960  if ((val == 0 && errno) || *endp || val > ~uint32_t(0))
1961  {
1962  std::cout << "*** DQMStore: WARNING: cannot restore tag '"
1963  << value << "' for monitor element '"
1964  << label << "' in directory '"
1965  << dir << "' - invalid value\n";
1966  return false;
1967  }
1968  tag(me, val);
1969  }
1970  else if (kind == "qr")
1971  {
1972  // Handle qreports, but skip them while reading in references.
1973  if (! isSubdirectory(s_referenceDirName, dir))
1974  {
1975  size_t dot = label.find('.');
1976  if (dot == std::string::npos)
1977  {
1978  std::cout << "*** DQMStore: WARNING: quality report label in '" << label
1979  << "' is missing a '.' and cannot be extracted\n";
1980  return false;
1981  }
1982 
1983  std::string mename (label, 0, dot);
1984  std::string qrname (label, dot+1, std::string::npos);
1985 
1986  m.reset();
1987  DQMNet::QValue qv;
1988  if (s_rxmeqr1.match(value, 0, 0, &m))
1989  {
1990  qv.code = atoi(m.matchString(value, 1).c_str());
1991  qv.qtresult = strtod(m.matchString(value, 2).c_str(), 0);
1992  qv.message = m.matchString(value, 4);
1993  qv.qtname = qrname;
1994  qv.algorithm = m.matchString(value, 3);
1995  }
1996  else if (s_rxmeqr2.match(value, 0, 0, &m))
1997  {
1998  qv.code = atoi(m.matchString(value, 1).c_str());
1999  qv.qtresult = 0; // unavailable in old format
2000  qv.message = m.matchString(value, 2);
2001  qv.qtname = qrname;
2002  // qv.algorithm unavailable in old format
2003  }
2004  else
2005  {
2006  std::cout << "*** DQMStore: WARNING: quality test value '"
2007  << value << "' is incorrectly formatted\n";
2008  return false;
2009  }
2010 
2011  MonitorElement *me = findObject(dir, mename);
2012  if (! me)
2013  {
2014  std::cout << "*** DQMStore: WARNING: no monitor element '"
2015  << mename << "' in directory '"
2016  << dir << "' for quality test '"
2017  << label << "'\n";
2018  return false;
2019  }
2020 
2021  me->addQReport(qv, /* FIXME: getQTest(qv.qtname)? */ 0);
2022  }
2023  }
2024  else
2025  {
2026  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2027  << obj->GetName() << "' of type '"
2028  << obj->IsA()->GetName() << "'\n";
2029  return false;
2030  }
2031  }
2032  else if (TNamed *n = dynamic_cast<TNamed *>(obj))
2033  {
2034  // For old DQM data.
2035  std::string s;
2036  s.reserve(6 + strlen(n->GetTitle()) + 2*strlen(n->GetName()));
2037  s += '<'; s += n->GetName(); s += '>';
2038  s += n->GetTitle();
2039  s += '<'; s += '/'; s += n->GetName(); s += '>';
2040  TObjString os(s.c_str());
2041  return extract(&os, dir, overwrite);
2042  }
2043  else
2044  {
2045  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2046  << obj->GetName() << "' of type '" << obj->IsA()->GetName()
2047  << "' and with title '" << obj->GetTitle() << "'\n";
2048  return false;
2049  }
2050 
2051  // If we just read in a reference monitor element, and there is a
2052  // monitor element with the same name, link the two together. The
2053  // other direction is handled by the initialise() method.
2054  if (refcheck && isSubdirectory(s_referenceDirName, dir))
2055  {
2056  std::string mdir(dir, s_referenceDirName.size()+1, std::string::npos);
2057  if (MonitorElement *master = findObject(mdir, obj->GetName()))
2058  {
2059  master->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
2060  master->reference_ = refcheck->object_;
2061  }
2062  }
2063 
2064  return true;
2065 }
2066 
2070 bool
2072 {
2073  assert(! path.empty());
2074 
2075  // Find the first path component.
2076  size_t start = 0;
2077  size_t end = path.find('/', start);
2078  if (end == std::string::npos)
2079  end = path.size();
2080 
2081  while (true)
2082  {
2083  // Check if this subdirectory component exists. If yes, make sure
2084  // it is actually a subdirectory. Otherwise create or cd into it.
2085  std::string part(path, start, end-start);
2086  TObject *o = gDirectory->Get(part.c_str());
2087  if (o && ! dynamic_cast<TDirectory *>(o))
2088  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2089  " fails because the part '%s' already exists and is not"
2090  " directory", path.c_str(), part.c_str());
2091  else if (! o)
2092  gDirectory->mkdir(part.c_str());
2093 
2094  if (! gDirectory->cd(part.c_str()))
2095  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2096  " fails because could not cd into subdirectory '%s'",
2097  path.c_str(), part.c_str());
2098 
2099  // Stop if we reached the end, ignoring any trailing '/'.
2100  if (end+1 >= path.size())
2101  break;
2102 
2103  // Find the next path component.
2104  start = end+1;
2105  end = path.find('/', start);
2106  if (end == std::string::npos)
2107  end = path.size();
2108  }
2109 
2110  return true;
2111 }
2112 
2117 void
2119  const std::string &path /* = "" */,
2120  const std::string &pattern /* = "" */,
2121  const std::string &rewrite /* = "" */,
2122  SaveReferenceTag ref /* = SaveWithReference */,
2123  int minStatus /* = dqm::qstatus::STATUS_OK */,
2124  const std::string &fileupdate /* = RECREATE */)
2125 {
2126  std::set<std::string>::iterator di, de;
2127  MEMap::iterator mi, me = data_.end();
2128  DQMNet::QReports::const_iterator qi, qe;
2129  int nme=0;
2130 
2131  // TFile flushes to disk with fsync() on every TDirectory written to the
2132  // file. This makes DQM file saving painfully slow, and ironically makes
2133  // it _more_ likely the file saving gets interrupted and corrupts the file.
2134  // The utility class below simply ignores the flush synchronisation.
2135  class TFileNoSync : public TFile
2136  {
2137  public:
2138  TFileNoSync(const char *file, const char *opt) : TFile(file, opt) {}
2139  virtual Int_t SysSync(Int_t) { return 0; }
2140  };
2141 
2142  // open output file, on 1st save recreate, later update
2143  if (verbose_)
2144  std::cout << "\n DQMStore: Opening TFile '" << filename
2145  << "' with option '" << fileupdate <<"'\n";
2146 
2147  TFileNoSync f(filename.c_str(), fileupdate.c_str()); // open file
2148  if(f.IsZombie())
2149  raiseDQMError("DQMStore", "Failed to create/update file '%s'", filename.c_str());
2150  f.cd();
2151 
2152  // Construct a regular expression from the pattern string.
2153  std::auto_ptr<lat::Regexp> rxpat;
2154  if (! pattern.empty())
2155  rxpat.reset(new lat::Regexp(pattern.c_str()));
2156 
2157  // Prepare a path for the reference object selection.
2158  std::string refpath;
2159  refpath.reserve(s_referenceDirName.size() + path.size() + 2);
2160  refpath += s_referenceDirName;
2161  if (! path.empty())
2162  {
2163  refpath += '/';
2164  refpath += path;
2165  }
2166 
2167  // Loop over the directory structure.
2168  for (di = dirs_.begin(), de = dirs_.end(); di != de; ++di)
2169  {
2170  // Check if we should process this directory. We process the
2171  // requested part of the object tree, including references.
2172  if (! path.empty()
2173  && ! isSubdirectory(path, *di)
2174  && ! isSubdirectory(refpath, *di))
2175  continue;
2176 
2177  // Loop over monitor elements in this directory.
2178  MonitorElement proto(&*di, std::string());
2179  mi = data_.lower_bound(proto);
2180  for ( ; mi != me && isSubdirectory(*di, *mi->data_.dirname); ++mi)
2181  {
2182  // Skip if it isn't a direct child.
2183  if (*di != *mi->data_.dirname)
2184  continue;
2185 
2186  // Handle reference histograms, with three distinct cases:
2187  // 1) Skip all references entirely on saving.
2188  // 2) Blanket saving of all references.
2189  // 3) Save only references for monitor elements with qtests.
2190  // The latter two are affected by "path" sub-tree selection,
2191  // i.e. references are saved only in the selected tree part.
2192  if (isSubdirectory(refpath, *mi->data_.dirname))
2193  {
2194  if (ref == SaveWithoutReference)
2195  // Skip the reference entirely.
2196  continue;
2197  else if (ref == SaveWithReference)
2198  // Save all references regardless of qtests.
2199  ;
2200  else if (ref == SaveWithReferenceForQTest)
2201  {
2202  // Save only references for monitor elements with qtests
2203  // with an optional cut on minimum quality test result.
2204  int status = -1;
2205  std::string mname(mi->getFullname(), s_referenceDirName.size()+1, std::string::npos);
2206  MonitorElement *master = get(mname);
2207  if (master)
2208  for (size_t i = 0, e = master->data_.qreports.size(); i != e; ++i)
2209  status = std::max(status, master->data_.qreports[i].code);
2210 
2211  if (! master || status < minStatus)
2212  {
2213  if (verbose_ > 1)
2214  std::cout << "DQMStore::save: skipping monitor element '"
2215  << mi->data_.objname << "' while saving, status is "
2216  << status << ", required minimum status is "
2217  << minStatus << std::endl;
2218  continue;
2219  }
2220  }
2221  }
2222 
2223  if (verbose_ > 1)
2224  std::cout << "DQMStore::save: saving monitor element '"
2225  << mi->data_.objname << "'\n";
2226  nme++; // count saved histograms
2227 
2228  // Create the directory.
2229  gDirectory->cd("/");
2230  if (di->empty())
2232  else if (rxpat.get())
2233  cdInto(s_monitorDirName + '/' + lat::StringOps::replace(*di, *rxpat, rewrite));
2234  else
2235  cdInto(s_monitorDirName + '/' + *di);
2236 
2237  // Save the object.
2238  switch (mi->kind())
2239  {
2243  TObjString(mi->tagString().c_str()).Write();
2244  break;
2245 
2246  default:
2247  mi->object_->Write();
2248  break;
2249  }
2250 
2251  // Save quality reports if this is not in reference section.
2252  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
2253  {
2254  qi = mi->data_.qreports.begin();
2255  qe = mi->data_.qreports.end();
2256  for ( ; qi != qe; ++qi)
2257  TObjString(mi->qualityTagString(*qi).c_str()).Write();
2258  }
2259 
2260  // Save efficiency tag, if any
2261  if (mi->data_.flags & DQMNet::DQM_PROP_EFFICIENCY_PLOT)
2262  TObjString(mi->effLabelString().c_str()).Write();
2263 
2264  // Save tag if any
2265  if (mi->data_.flags & DQMNet::DQM_PROP_TAGGED)
2266  TObjString(mi->tagLabelString().c_str()).Write();
2267  }
2268  }
2269 
2270  f.Close();
2271 
2272  // Maybe make some noise.
2273  if (verbose_)
2274  std::cout << "DQMStore::save: successfully wrote " << nme
2275  << " objects from path '" << path
2276  << "' into DQM file '" << filename << "'\n";
2277 }
2278 
2281 unsigned int
2283  bool overwrite,
2284  const std::string &onlypath,
2285  const std::string &prepend,
2286  const std::string &curdir,
2287  OpenRunDirs stripdirs)
2288 {
2289  unsigned int ntot = 0;
2290  unsigned int count = 0;
2291 
2292  if (! file->cd(curdir.c_str()))
2293  raiseDQMError("DQMStore", "Failed to process directory '%s' while"
2294  " reading file '%s'", curdir.c_str(), file->GetName());
2295 
2296  // Figure out current directory name, but strip out the top
2297  // directory into which we dump everything.
2298  std::string dirpart = curdir;
2299  if (dirpart.compare(0, s_monitorDirName.size(), s_monitorDirName) == 0)
2300  {
2301  if (dirpart.size() == s_monitorDirName.size())
2302  dirpart.clear();
2303  else if (dirpart[s_monitorDirName.size()] == '/')
2304  dirpart.erase(0, s_monitorDirName.size()+1);
2305  }
2306 
2307  // See if we are going to skip this directory.
2308  bool skip = (! onlypath.empty() && ! isSubdirectory(onlypath, dirpart));
2309 
2310  if (prepend == s_collateDirName ||
2311  prepend == s_referenceDirName ||
2312  stripdirs == StripRunDirs )
2313  {
2314  // Remove Run # and RunSummary dirs
2315  // first look for Run summary,
2316  // if that is found and erased, also erase Run dir
2317  size_t slash = dirpart.find('/');
2318  size_t pos = dirpart.find("/Run summary");
2319  if (slash != std::string::npos && pos !=std::string::npos)
2320  {
2321  dirpart.erase(pos,12);
2322 
2323  pos = dirpart.find("Run ");
2324  size_t length = dirpart.find('/',pos+1)-pos+1;
2325  if (pos !=std::string::npos)
2326  dirpart.erase(pos,length);
2327  }
2328  }
2329 
2330  // If we are prepending, add it to the directory name,
2331  // and suppress reading of already existing reference histograms
2332  if (prepend == s_collateDirName ||
2333  prepend == s_referenceDirName)
2334  {
2335  size_t slash = dirpart.find('/');
2336  // If we are reading reference, skip previous reference.
2337  if (slash == std::string::npos // skip if Reference is toplevel folder, i.e. no slash
2338  && slash+1+s_referenceDirName.size() == dirpart.size()
2339  && dirpart.compare(slash+1, s_referenceDirName.size(), s_referenceDirName) == 0)
2340  return 0;
2341 
2342  slash = dirpart.find('/');
2343  // Skip reading of EventInfo subdirectory.
2344  if (slash != std::string::npos
2345  && slash + 10 == dirpart.size()
2346  && dirpart.compare( slash+1 , 9 , "EventInfo") == 0) {
2347  if (verbose_)
2348  std::cout << "DQMStore::readDirectory: skipping '" << dirpart << "'\n";
2349  return 0;
2350  }
2351 
2352  // Add prefix.
2353  if (dirpart.empty())
2354  dirpart = prepend;
2355  else
2356  dirpart = prepend + '/' + dirpart;
2357  }
2358  else if (! prepend.empty())
2359  {
2360  if (dirpart.empty())
2361  dirpart = prepend;
2362  else
2363  dirpart = prepend + '/' + dirpart;
2364  }
2365 
2366  // Loop over the contents of this directory in the file.
2367  // Post-pone string object handling to happen after other
2368  // objects have been read in so we are guaranteed to have
2369  // histograms by the time we read in quality tests and tags.
2370  TKey *key;
2371  TIter next (gDirectory->GetListOfKeys());
2372  std::list<TObject *> delayed;
2373  while ((key = (TKey *) next()))
2374  {
2375  std::auto_ptr<TObject> obj(key->ReadObj());
2376  if (dynamic_cast<TDirectory *>(obj.get()))
2377  {
2378  std::string subdir;
2379  subdir.reserve(curdir.size() + strlen(obj->GetName()) + 2);
2380  subdir += curdir;
2381  if (! curdir.empty())
2382  subdir += '/';
2383  subdir += obj->GetName();
2384 
2385  ntot += readDirectory(file, overwrite, onlypath, prepend, subdir, stripdirs);
2386  }
2387  else if (skip)
2388  ;
2389  else if (dynamic_cast<TObjString *>(obj.get()))
2390  {
2391  delayed.push_back(obj.release());
2392  }
2393  else
2394  {
2395  if (verbose_ > 2)
2396  std::cout << "DQMStore: reading object '" << obj->GetName()
2397  << "' of type '" << obj->IsA()->GetName()
2398  << "' from '" << file->GetName()
2399  << "' into '" << dirpart << "'\n";
2400 
2401  makeDirectory(dirpart);
2402  if (extract(obj.get(), dirpart, overwrite))
2403  ++count;
2404  }
2405  }
2406 
2407  while (! delayed.empty())
2408  {
2409  if (verbose_ > 2)
2410  std::cout << "DQMStore: reading object '" << delayed.front()->GetName()
2411  << "' of type '" << delayed.front()->IsA()->GetName()
2412  << "' from '" << file->GetName()
2413  << "' into '" << dirpart << "'\n";
2414 
2415  makeDirectory(dirpart);
2416  if (extract(delayed.front(), dirpart, overwrite))
2417  ++count;
2418 
2419  delete delayed.front();
2420  delayed.pop_front();
2421  }
2422 
2423  if (verbose_ > 1)
2424  std::cout << "DQMStore: read " << count << '/' << ntot
2425  << " objects from directory '" << dirpart << "'\n";
2426 
2427  return ntot + count;
2428 }
2429 
2436 bool
2438  bool overwrite /* = false */,
2439  const std::string &onlypath /* ="" */,
2440  const std::string &prepend /* ="" */,
2441  OpenRunDirs stripdirs /* =KeepRunDirs */,
2442  bool fileMustExist /* =true */)
2443 {
2444  return readFile(filename,overwrite,onlypath,prepend,stripdirs,fileMustExist);
2445 }
2446 
2451 bool
2453  OpenRunDirs stripdirs /* =StripRunDirs */,
2454  bool fileMustExist /* =true */)
2455 {
2456  bool overwrite = true;
2457  if (collateHistograms_) overwrite = false;
2458  if (verbose_)
2459  {
2460  std::cout << "DQMStore::load: reading from file '" << filename << "'\n";
2461  if (collateHistograms_)
2462  std::cout << "DQMStore::load: in collate mode " << "\n";
2463  else
2464  std::cout << "DQMStore::load: in overwrite mode " << "\n";
2465  }
2466 
2467  return readFile(filename,overwrite,"","",stripdirs,fileMustExist);
2468 
2469 }
2470 
2476 bool
2478  bool overwrite /* = false */,
2479  const std::string &onlypath /* ="" */,
2480  const std::string &prepend /* ="" */,
2481  OpenRunDirs stripdirs /* =StripRunDirs */,
2482  bool fileMustExist /* =true */)
2483 {
2484 
2485  if (verbose_)
2486  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
2487 
2488  std::auto_ptr<TFile> f;
2489 
2490  try
2491  {
2492  f.reset(TFile::Open(filename.c_str()));
2493  if (! f.get() || f->IsZombie())
2494  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
2495  }
2496  catch (std::exception &)
2497  {
2498  if (fileMustExist)
2499  throw;
2500  else
2501  {
2502  if (verbose_)
2503  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
2504  return false;
2505  }
2506  }
2507 
2508  unsigned n = readDirectory(f.get(), overwrite, onlypath, prepend, "", stripdirs);
2509  f->Close();
2510 
2511  MEMap::iterator mi = data_.begin();
2512  MEMap::iterator me = data_.end();
2513  for ( ; mi != me; ++mi)
2514  const_cast<MonitorElement &>(*mi).updateQReportStats();
2515 
2516  if (verbose_)
2517  {
2518  std::cout << "DQMStore::open: successfully read " << n
2519  << " objects from file '" << filename << "'";
2520  if (! onlypath.empty())
2521  std::cout << " from directory '" << onlypath << "'";
2522  if (! prepend.empty())
2523  std::cout << " into directory '" << prepend << "'";
2524  std::cout << std::endl;
2525  }
2526  return true;
2527 }
2528 
2534 void
2536 {
2538  const std::string *cleaned = 0;
2539  cleanTrailingSlashes(path, clean, cleaned);
2540  MonitorElement proto(cleaned, std::string());
2541 
2542  MEMap::iterator e = data_.end();
2543  MEMap::iterator i = data_.lower_bound(proto);
2544  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
2545  data_.erase(i++);
2546 
2547  std::set<std::string>::iterator de = dirs_.end();
2548  std::set<std::string>::iterator di = dirs_.lower_bound(*cleaned);
2549  while (di != de && isSubdirectory(*cleaned, *di))
2550  dirs_.erase(di++);
2551 }
2552 
2554 void
2556 {
2557  MonitorElement proto(&dir, std::string());
2558  MEMap::iterator e = data_.end();
2559  MEMap::iterator i = data_.lower_bound(proto);
2560  while (i != e && isSubdirectory(dir, *i->data_.dirname))
2561  if (dir == *i->data_.dirname)
2562  data_.erase(i++);
2563  else
2564  ++i;
2565 }
2566 
2568 void
2570 {
2572 }
2573 
2576 void
2578 {
2579  removeElement(pwd_, name);
2580 }
2581 
2584 void
2586 {
2587  MonitorElement proto(&dir, name);
2588  MEMap::iterator pos = data_.find(proto);
2589  if (pos == data_.end() && warning)
2590  std::cout << "DQMStore: WARNING: attempt to remove non-existent"
2591  << " monitor element '" << name << "' in '" << dir << "'\n";
2592  else
2593  data_.erase(pos);
2594 }
2595 
2601 QCriterion *
2603 {
2604  QCMap::const_iterator i = qtests_.find(qtname);
2605  QCMap::const_iterator e = qtests_.end();
2606  return (i == e ? 0 : i->second);
2607 }
2608 
2612 QCriterion *
2613 DQMStore::createQTest(const std::string &algoname, const std::string &qtname)
2614 {
2615  if (qtests_.count(qtname))
2616  raiseDQMError("DQMStore", "Attempt to create duplicate quality test '%s'",
2617  qtname.c_str());
2618 
2619  QAMap::iterator i = qalgos_.find(algoname);
2620  if (i == qalgos_.end())
2621  raiseDQMError("DQMStore", "Cannot create a quality test using unknown"
2622  " algorithm '%s'", algoname.c_str());
2623 
2624  QCriterion *qc = i->second(qtname);
2625  qc->setVerbose(verboseQT_);
2626 
2627  qtests_[qtname] = qc;
2628  return qc;
2629 }
2630 
2633 void
2635 {
2636  // Clean the path
2638  const std::string *cleaned = 0;
2639  cleanTrailingSlashes(dir, clean, cleaned);
2640 
2641  // Validate the path.
2642  if (cleaned->find_first_not_of(s_safe) != std::string::npos)
2643  raiseDQMError("DQMStore", "Monitor element path name '%s'"
2644  " uses unacceptable characters", cleaned->c_str());
2645 
2646  // Redirect to the pattern match version.
2647  useQTestByMatch(*cleaned + "/*", qtname);
2648 }
2649 
2651 int
2653 {
2654  QCriterion *qc = getQCriterion(qtname);
2655  if (! qc)
2656  raiseDQMError("DQMStore", "Cannot apply non-existent quality test '%s'",
2657  qtname.c_str());
2658 
2659  fastmatch * fm = new fastmatch( pattern );
2660 
2661  // Record the test for future reference.
2662  QTestSpec qts(fm, qc);
2663  qtestspecs_.push_back(qts);
2664 
2665  // Apply the quality test.
2666  MEMap::iterator mi = data_.begin();
2667  MEMap::iterator me = data_.end();
2668  std::string path;
2669  int cases = 0;
2670  for ( ; mi != me; ++mi)
2671  {
2672  path.clear();
2673  mergePath(path, *mi->data_.dirname, mi->data_.objname);
2674  if (fm->match(path))
2675  {
2676  ++cases;
2677  const_cast<MonitorElement &>(*mi).addQReport(qts.second);
2678  }
2679  }
2680 
2681  //return the number of matched cases
2682  return cases;
2683 }
2686 void
2688 {
2689 
2690  if (verbose_ > 0)
2691  std::cout << "DQMStore: running runQTests() with reset = "
2692  << ( reset_ ? "true" : "false" ) << std::endl;
2693 
2694  // Apply quality tests to each monitor element, skipping references.
2695  MEMap::iterator mi = data_.begin();
2696  MEMap::iterator me = data_.end();
2697  for ( ; mi != me; ++mi)
2698  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
2699  const_cast<MonitorElement &>(*mi).runQTests();
2700 
2701  reset_ = false;
2702 }
2703 
2707 int
2708 DQMStore::getStatus(const std::string &path /* = "" */) const
2709 {
2711  const std::string *cleaned = 0;
2712  cleanTrailingSlashes(path, clean, cleaned);
2713 
2715  MEMap::const_iterator mi = data_.begin();
2716  MEMap::const_iterator me = data_.end();
2717  for ( ; mi != me; ++mi)
2718  {
2719  if (! cleaned->empty() && ! isSubdirectory(*cleaned, *mi->data_.dirname))
2720  continue;
2721 
2722  if (mi->hasError())
2723  return dqm::qstatus::ERROR;
2724  else if (mi->hasWarning())
2725  status = dqm::qstatus::WARNING;
2726  else if (status < dqm::qstatus::WARNING
2727  && mi->hasOtherReport())
2728  status = dqm::qstatus::OTHER;
2729  }
2730  return status;
2731 }
2732 
2738 void
2740 {
2741  if (me)
2742  me->softReset();
2743 }
2744 
2745 // reverts action of softReset
2746 void
2748 {
2749  if (me)
2750  me->disableSoftReset();
2751 }
2752 
2755 void
2757 {
2758  if (me)
2759  me->setAccumulate(flag);
2760 }
2761 
2765 void
2767 {
2768  std::vector<std::string> contents;
2769  getContents(contents);
2770 
2771  std::cout << " ------------------------------------------------------------\n"
2772  << " Directory structure: \n"
2773  << " ------------------------------------------------------------\n";
2774 
2775  std::copy(contents.begin(), contents.end(),
2776  std::ostream_iterator<std::string>(std::cout, "\n"));
2777 
2778  std::cout << " ------------------------------------------------------------\n";
2779 }
2780 
2784 // check if the collate option is active on the DQMStore
2785 bool
2787 {
2788  return collateHistograms_;
2789 }
2793 // check if the monitor element is in auto-collation folder
2794 bool
2796 { return me && isSubdirectory(s_collateDirName, *me->data_.dirname); }
2800 
2802 void
2804 {
2805  if (scaleFlag_ == 0.0) return;
2806  if (verbose_ > 0)
2807  std::cout << " =========== " << " ScaleFlag " << scaleFlag_ << std::endl;
2808  double factor = scaleFlag_;
2809  int events = 1;
2810  if (dirExists("Info/EventInfo")) {
2811  if ( scaleFlag_ == -1.0) {
2812  MonitorElement * scale_me = get("Info/EventInfo/ScaleFactor");
2813  if (scale_me && scale_me->kind()==MonitorElement::DQM_KIND_REAL) factor = scale_me->getFloatValue();
2814  }
2815  MonitorElement * event_me = get("Info/EventInfo/processedEvents");
2816  if (event_me && event_me->kind()==MonitorElement::DQM_KIND_INT) events = event_me->getIntValue();
2817  }
2818  factor = factor/(events*1.0);
2819 
2820  MEMap::iterator mi = data_.begin();
2821  MEMap::iterator me = data_.end();
2822  for ( ; mi != me; ++mi)
2823  {
2824  MonitorElement &me = const_cast<MonitorElement &>(*mi);
2825  switch (me.kind())
2826  {
2828  {
2829  me.getTH1F()->Scale(factor);
2830  break;
2831  }
2833  {
2834  me.getTH1S()->Scale(factor);
2835  break;
2836  }
2838  {
2839  me.getTH1D()->Scale(factor);
2840  break;
2841  }
2843  {
2844  me.getTH2F()->Scale(factor);
2845  break;
2846  }
2848  {
2849  me.getTH2S()->Scale(factor);
2850  break;
2851  }
2853  {
2854  me.getTH2D()->Scale(factor);
2855  break;
2856  }
2858  {
2859  me.getTH3F()->Scale(factor);
2860  break;
2861  }
2863  {
2864  me.getTProfile()->Scale(factor);
2865  break;
2866  }
2868  {
2869  me.getTProfile2D()->Scale(factor);
2870  break;
2871  }
2872  default:
2873  if (verbose_ > 0)
2874  std::cout << " The DQM object '" << me.getFullname() << "' is not scalable object " << std::endl;
2875  continue;
2876  }
2877  }
2878 }
static void collateProfile2D(MonitorElement *me, TProfile2D *h)
Definition: DQMStore.cc:1345
QCriterion * getQCriterion(const std::string &qtname) const
Definition: DQMStore.cc:2602
bool compare_strings_reverse(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:198
std::pair< fastmatch *, QCriterion * > QTestSpec
Definition: DQMStore.h:448
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:259
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:872
bool containsAnyMonitorable(const std::string &path) const
Definition: DQMStore.cc:1463
bool isCollateME(MonitorElement *me) const
Definition: DQMStore.cc:2795
void resetUpdate(void)
reset &quot;was updated&quot; flag
long int flag
Definition: mlp_lapack.h:47
tuple start
Check for commandline option errors.
Definition: dqm_diff.py:58
bool cdInto(const std::string &path) const
Definition: DQMStore.cc:2071
int getStatus(const std::string &path="") const
Definition: DQMStore.cc:2708
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:101
std::string algorithm
Definition: DQMNet.h:92
std::vector< std::string > getSubdirs(void) const
Definition: DQMStore.cc:1424
TProfile2D * getTProfile2D(void) const
static std::string s_collateDirName
Definition: DQMStore.cc:49
MonitorElement * book1D(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1D histogram.
Definition: DQMStore.cc:722
void rmdir(const std::string &fullpath)
Definition: DQMStore.cc:2535
bool match(std::string const &s) const
Definition: DQMStore.cc:240
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:2477
static void collate3D(MonitorElement *me, TH3F *h)
Definition: DQMStore.cc:1328
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:984
static void collate1D(MonitorElement *me, TH1F *h)
Definition: DQMStore.cc:1286
void cd(void)
go to top directory (ie. root)
Definition: DQMStore.cc:411
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:894
static void collate1DD(MonitorElement *me, TH1D *h)
Definition: DQMStore.cc:1300
static void splitPath(std::string &dir, std::string &name, const std::string &path)
Definition: DQMStore.cc:88
static std::string s_referenceDirName
Definition: DQMStore.cc:48
uint32_t flags
Definition: DQMNet.h:97
void save(const std::string &filename, const std::string &path="", const std::string &pattern="", const std::string &rewrite="", SaveReferenceTag ref=SaveWithReference, int minStatus=dqm::qstatus::STATUS_OK, const std::string &fileupdate="RECREATE")
Definition: DQMStore.cc:2118
void disableSoftReset(void)
reverts action of softReset
std::vector< MonitorElement * > getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType=lat::Regexp::Wildcard) const
Definition: DQMStore.cc:1696
static const int WARNING
TH3F * getTH3F(void) const
static const uint32_t DQM_PROP_TAGGED
Definition: DQMNet.h:54
TH1D * getTH1D(void) const
def replace
Definition: linker.py:10
MatchingHeuristicEnum matching_
Definition: DQMStore.h:64
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
void softReset(void)
TH2D * getTH2D(void) const
uint32_t tag
Definition: DQMNet.h:98
bool reset_
Definition: DQMStore.h:456
const std::string * dirname
Definition: DQMNet.h:100
MonitorElement * book1DD(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:754
void initializeFrom(const edm::ParameterSet &)
Definition: DQMStore.cc:296
OpenRunDirs
Definition: DQMStore.h:76
void initQCriterion(std::map< std::string, QCriterion *(*)(const std::string &)> &m)
Definition: DQMStore.cc:117
QCMap qtests_
Definition: DQMStore.h:465
MonitorElement * book(const std::string &dir, const std::string &name, const char *context)
Definition: DQMStore.cc:577
MonitorElement * bookFloat(const char *name)
Book float.
Definition: DQMStore.cc:659
dictionary map
Definition: Association.py:205
SaveReferenceTag
Definition: DQMStore.h:70
std::vector< MonitorElement * > getAllContents(const std::string &path) const
Definition: DQMStore.cc:1677
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:71
void tag(MonitorElement *me, unsigned int myTag)
Definition: DQMStore.cc:1359
~DQMStore(void)
Definition: DQMStore.cc:285
void disableSoftReset(MonitorElement *me)
Definition: DQMStore.cc:2747
static void collateProfile(MonitorElement *me, TProfile *h)
Definition: DQMStore.cc:1335
static const lat::Regexp s_rxmeval("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$")
void forceReset(void)
Definition: DQMStore.cc:1756
static bool isSubdirectory(const std::string &ofdir, const std::string &path)
Definition: DQMStore.cc:61
fastmatch(std::string const &_fastString)
Definition: DQMStore.cc:122
unsigned verboseQT_
Definition: DQMStore.h:455
bool extract(TObject *obj, const std::string &dir, bool overwrite)
Definition: DQMStore.cc:1776
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:2569
QTestSpecs qtestspecs_
Definition: DQMStore.h:467
double scaleFlag_
Definition: DQMStore.h:457
const T & max(const T &a, const T &b)
void watchPostSourceRun(PostSourceRun::slot_type const &iSlot)
MonitorElement * bookString(const char *name, const char *value)
Book string.
Definition: DQMStore.cc:688
static std::string s_safe
Definition: DQMStore.cc:50
static void collate1S(MonitorElement *me, TH1S *h)
Definition: DQMStore.cc:1293
void setAccumulate(bool)
bool isCollate(void) const
Definition: DQMStore.cc:2786
tuple result
Definition: query.py:137
void removeElement(const std::string &name)
Definition: DQMStore.cc:2577
void addProfiles(TProfile *h1, TProfile *h2, TProfile *sum, float c1, float c2)
static bool checkBinningMatches(MonitorElement *me, TH1 *h)
Definition: DQMStore.cc:1262
double getFloatValue(void) const
MonitorElement * findObject(const std::string &dir, const std::string &name) const
Definition: DQMStore.cc:1603
TH1 * getTH1(void) const
double f[11][100]
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:1036
QCriterion * makeQCriterion(const std::string &qtname)
Definition: DQMStore.cc:112
#define end
Definition: vmac.h:38
void setVerbose(unsigned level)
Definition: DQMStore.cc:398
void softReset(MonitorElement *me)
Definition: DQMStore.cc:2739
std::string pwd_
Definition: DQMStore.h:461
Kind kind(void) const
Get the type of the monitor element.
void runQTests(void)
Definition: DQMStore.cc:2687
lat::Regexp * regexp_
Definition: DQMStore.h:62
MonitorElement * get(const std::string &path) const
get ME from full pathname (e.g. &quot;my/long/dir/my_histo&quot;)
Definition: DQMStore.cc:1473
QAMap qalgos_
Definition: DQMStore.h:466
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:1502
std::string objname
Definition: DQMNet.h:101
std::string fastString_
Definition: DQMStore.h:63
std::vector< T * > clean
Definition: MVATrainer.cc:156
std::string qtname
Definition: DQMNet.h:91
DQMNet::CoreObject data_
bool dirExists(const std::string &path) const
true if directory exists
Definition: DQMStore.cc:498
void getAllTags(std::vector< std::string > &into) const
Definition: DQMStore.cc:1624
bool load(const std::string &filename, OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2452
void scaleElements(void)
Definition: DQMStore.cc:2803
~fastmatch()
Definition: DQMStore.cc:192
void tagAllContents(const std::string &path, unsigned int myTag)
Definition: DQMStore.cc:1402
MonitorElement * initialise(MonitorElement *me, const std::string &path)
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
unsigned verbose_
Definition: DQMStore.h:454
static void collate2S(MonitorElement *me, TH2S *h)
Definition: DQMStore.cc:1314
MEMap data_
Definition: DQMStore.h:462
part
Definition: HCALResponse.h:20
int64_t getIntValue(void) const
static void collate2D(MonitorElement *me, TH2F *h)
Definition: DQMStore.cc:1307
void print_trace(const std::string &dir, const std::string &name)
Definition: DQMStore.cc:347
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:2652
TH1F * getTH1F(void) const
std::vector< std::string > getMEs(void) const
get list of (non-dir) MEs of current directory
Definition: DQMStore.cc:1447
bool resetMe(void) const
true if ME should be reset at end of monitoring cycle
unsigned int readDirectory(TFile *file, bool overwrite, const std::string &path, const std::string &prepend, const std::string &curdir, OpenRunDirs stripdirs)
Definition: DQMStore.cc:2282
void setVerbose(int verbose)
probability limits for warnings, errors
Definition: QTest.h:115
static void collate2DD(MonitorElement *me, TH2D *h)
Definition: DQMStore.cc:1321
T dot(const Basic3DVector &v) const
Scalar product, or &quot;dot&quot; product, with a vector of same type.
void tagContents(const std::string &path, unsigned int myTag)
tag all children of folder (does NOT include subfolders)
Definition: DQMStore.cc:1390
list key
Definition: combine.py:13
tuple events
Definition: patZpeak.py:19
TProfile * getTProfile(void) const
void useQTest(const std::string &dir, const std::string &qtname)
Definition: DQMStore.cc:2634
tuple filename
Definition: lut2db_cfg.py:20
std::string message
Definition: DQMNet.h:90
void goUp(void)
equivalent to &quot;cd ..&quot;
Definition: DQMStore.cc:445
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:2437
static const int STATUS_OK
void setAccumulate(MonitorElement *me, bool flag)
Definition: DQMStore.cc:2756
tuple cout
Definition: gather_cfg.py:121
void setEfficiencyFlag(void)
QCriterion * createQTest(const std::string &algoname, const std::string &qtname)
Definition: DQMStore.cc:2613
dbl *** dir
Definition: mlp_gen.cc:35
void showDirStructure(void) const
Definition: DQMStore.cc:2766
void reset(void)
Definition: DQMStore.cc:1732
tuple status
Definition: ntuplemaker.py:245
TH2F * getTH2F(void) const
MonitorElement * bookInt(const char *name)
Book int.
Definition: DQMStore.cc:629
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:850
static std::string s_monitorDirName
name of global monitoring folder (containing all sources subdirectories)
Definition: DQMStore.cc:47
long double T
float qtresult
Definition: DQMNet.h:89
std::set< std::string > dirs_
Definition: DQMStore.h:463
bool collateHistograms_
Definition: DQMStore.h:458
void Reset(void)
reset ME (ie. contents, errors, etc)
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:738
tuple size
Write out results.
static const lat::Regexp s_rxmeqr1("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$")
void makeDirectory(const std::string &path)
get folder corresponding to inpath wrt to root (create subdirs if necessary)
Definition: DQMStore.cc:457
bool compare_strings(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:219
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:434
static const int ERROR
const std::string & pwd(void) const
Definition: DQMStore.cc:406
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:1180
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:11