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
61 isSubdirectory(const std::string &ofdir, const std::string &path)
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
71 cleanTrailingSlashes(const std::string &path, std::string &clean, const std::string *&cleaned)
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
88 splitPath(std::string &dir, std::string &name, const std::string &path)
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
101 mergePath(std::string &path, const std::string &dir, const std::string &name)
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 *
112 makeQCriterion(const std::string &qtname)
113 { return new T(qtname); }
114 
115 template <class T>
116 void
117 initQCriterion(std::map<std::string, QCriterion *(*)(const std::string &)> &m)
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 
219 bool fastmatch::compare_strings(std::string const& pattern,
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 }
272 
274  : verbose_ (1),
275  verboseQT_ (1),
276  reset_ (false),
277  collateHistograms_ (false),
278  readSelectedDirectory_ (""),
279  pwd_ ("")
280 {
281  initializeFrom(pset);
282 }
283 
285 {
286  for (QCMap::iterator i = qtests_.begin(), e = qtests_.end(); i != e; ++i)
287  delete i->second;
288 
289  for (QTestSpecs::iterator i = qtestspecs_.begin(), e = qtestspecs_.end(); i != e; ++i)
290  delete i->first;
291 
292 }
293 
294 void
296  makeDirectory("");
297  reset();
298 
299  // set steerable parameters
300  verbose_ = pset.getUntrackedParameter<int>("verbose", 0);
301  if (verbose_ > 0)
302  std::cout << "DQMStore: verbosity set to " << verbose_ << std::endl;
303 
304  verboseQT_ = pset.getUntrackedParameter<int>("verboseQT", 0);
305  if (verbose_ > 0)
306  std::cout << "DQMStore: QTest verbosity set to " << verboseQT_ << std::endl;
307 
308  collateHistograms_ = pset.getUntrackedParameter<bool>("collateHistograms", false);
309  if (collateHistograms_)
310  std::cout << "DQMStore: histogram collation is enabled\n";
311 
312  std::string ref = pset.getUntrackedParameter<std::string>("referenceFileName", "");
313  if (! ref.empty())
314  {
315  std::cout << "DQMStore: using reference file '" << ref << "'\n";
316  readFile(ref, true, "", s_referenceDirName, StripRunDirs, false);
317  }
318 
319  initQCriterion<Comp2RefChi2>(qalgos_);
320  initQCriterion<Comp2RefKolmogorov>(qalgos_);
321  initQCriterion<ContentsXRange>(qalgos_);
322  initQCriterion<ContentsYRange>(qalgos_);
323  initQCriterion<MeanWithinExpected>(qalgos_);
324  initQCriterion<Comp2RefEqualH>(qalgos_);
325  initQCriterion<DeadChannel>(qalgos_);
326  initQCriterion<NoisyChannel>(qalgos_);
327  initQCriterion<ContentsWithinExpected>(qalgos_);
328  initQCriterion<CompareToMedian>(qalgos_);
329  initQCriterion<CompareLastFilledBin>(qalgos_);
330 }
331 
332 /* Generic method to do a backtrace and print it to stdout. It is
333  customised to properly get the routine that called the booking of the
334  histograms, which, following the usual stack, is at position 4. The
335  name of the calling function is properly demangled and the original
336  shared library including this function is also printed. For a more
337  detailed explanation of the routines involved, see here:
338  http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
339  http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html.*/
340 
341 void
342 DQMStore::print_trace (const std::string &dir, const std::string &name)
343 {
344  static std::ofstream stream("histogramBookingBT.log");
345  void *array[10];
346  size_t size;
347  char **strings;
348  int r=0;
349  lat::RegexpMatch m;
350  m.reset();
351 
352  size = backtrace (array, 10);
353  strings = backtrace_symbols (array, size);
354 
355  if ((size > 4)
356  &&s_rxtrace.match(strings[4], 0, 0, &m))
357  {
358  char * demangled = abi::__cxa_demangle(m.matchString(strings[4], 2).c_str(), 0, 0, &r);
359  stream << "\"" << dir << "/"
360  << name << "\" "
361  << (r ? m.matchString(strings[4], 2) : demangled) << " "
362  << m.matchString(strings[4], 1) << "\n";
363  free(demangled);
364  }
365  else
366  stream << "Skipping "<< dir << "/" << name
367  << " with stack size " << size << "\n";
368  /* In this case print the full stack trace, up to main or to the
369  * maximum stack size, i.e. 10. */
370  if (verbose_ > 4)
371  {
372  size_t i;
373  m.reset();
374 
375  for (i = 0; i < size; i++)
376  if (s_rxtrace.match(strings[i], 0, 0, &m))
377  {
378  char * demangled = abi::__cxa_demangle(m.matchString(strings[i], 2).c_str(), 0, 0, &r);
379  stream << "\t\t" << i << "/" << size << " "
380  << (r ? m.matchString(strings[i], 2) : demangled) << " "
381  << m.matchString(strings[i], 1) << std::endl;
382  free (demangled);
383  }
384  }
385  free (strings);
386 }
387 
392 void
393 DQMStore::setVerbose(unsigned /* level */)
394 { return; }
395 
400 const std::string &
401 DQMStore::pwd(void) const
402 { return pwd_; }
403 
405 void
407 { setCurrentFolder(""); }
408 
410 void
411 DQMStore::cd(const std::string &subdir)
412 {
413  std::string clean;
414  const std::string *cleaned = 0;
415  cleanTrailingSlashes(subdir, clean, cleaned);
416 
417  if (! dirExists(*cleaned))
418  raiseDQMError("DQMStore", "Cannot 'cd' into non-existent directory '%s'",
419  cleaned->c_str());
420 
421  setCurrentFolder(*cleaned);
422 }
423 
428 void
429 DQMStore::setCurrentFolder(const std::string &fullpath)
430 {
431  std::string clean;
432  const std::string *cleaned = 0;
433  cleanTrailingSlashes(fullpath, clean, cleaned);
434  makeDirectory(*cleaned);
435  pwd_ = *cleaned;
436 }
437 
439 void
441 {
442  size_t pos = pwd_.rfind('/');
443  if (pos == std::string::npos)
444  setCurrentFolder("");
445  else
446  setCurrentFolder(pwd_.substr(0, pos));
447 }
448 
449 // -------------------------------------------------------------------
451 void
452 DQMStore::makeDirectory(const std::string &path)
453 {
454  std::string prev;
455  std::string subdir;
456  std::string name;
457  prev.reserve(path.size());
458  subdir.reserve(path.size());
459  name.reserve(path.size());
460  size_t prevname = 0;
461  size_t slash = 0;
462 
463  while (true)
464  {
465  // Create this subdirectory component.
466  subdir.clear();
467  subdir.append(path, 0, slash);
468  name.clear();
469  name.append(subdir, prevname, std::string::npos);
470  if (! prev.empty() && findObject(prev, name))
471  raiseDQMError("DQMStore", "Attempt to create subdirectory '%s'"
472  " which already exists as a monitor element",
473  subdir.c_str());
474 
475  if (! dirs_.count(subdir))
476  dirs_.insert(subdir);
477 
478  // Stop if we've reached the end (including possibly a trailing slash).
479  if (slash+1 >= path.size())
480  break;
481 
482  // Find the next slash, making sure we progress. If reach the end,
483  // process the last path component; the next loop round will terminate.
484  prevname = slash ? slash+1 : slash;
485  prev = subdir;
486  if ((slash = path.find('/', ++slash)) == std::string::npos)
487  slash = path.size();
488  }
489 }
490 
492 bool
493 DQMStore::dirExists(const std::string &path) const
494 { return dirs_.count(path) > 0; }
495 
499 template <class HISTO, class COLLATE>
501 DQMStore::book(const std::string &dir, const std::string &name,
502  const char *context, int kind,
503  HISTO *h, COLLATE collate)
504 {
505  assert(name.find('/') == std::string::npos);
506  if (verbose_ > 3)
507  print_trace(dir, name);
508  std::string path;
509  mergePath(path, dir, name);
510 
511  // Put us in charge of h.
512  h->SetDirectory(0);
513 
514  // Check if the request monitor element already exists.
515  MonitorElement *me = findObject(dir, name);
516  if (me)
517  {
518  if (collateHistograms_)
519  {
520  collate(me, h);
521  delete h;
522  return me;
523  }
524  else
525  {
526  if (verbose_ > 1)
527  std::cout << "DQMStore: "
528  << context << ": monitor element '"
529  << path << "' already exists, collating" << std::endl;
530  me->Reset();
531  collate(me, h);
532  delete h;
533  return me;
534  }
535  }
536  else
537  {
538  // Create and initialise core object.
539  assert(dirs_.count(dir));
540  MonitorElement proto(&*dirs_.find(dir), name);
541  me = const_cast<MonitorElement &>(*data_.insert(proto).first)
543 
544  // Initialise quality test information.
545  QTestSpecs::iterator qi = qtestspecs_.begin();
546  QTestSpecs::iterator qe = qtestspecs_.end();
547  for ( ; qi != qe; ++qi)
548  {
549  if ( qi->first->match(path) )
550  me->addQReport(qi->second);
551  }
552 
553  // Assign reference if we have one.
554  std::string refdir;
555  refdir.reserve(s_referenceDirName.size() + dir.size() + 2);
556  refdir += s_referenceDirName;
557  refdir += '/';
558  refdir += dir;
559 
560  if (MonitorElement *refme = findObject(refdir, name))
561  {
562  me->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
563  me->reference_ = refme->object_;
564  }
565 
566  // Return the monitor element.
567  return me;
568  }
569 }
570 
572 DQMStore::book(const std::string &dir,
573  const std::string &name,
574  const char *context)
575 {
576  assert(name.find('/') == std::string::npos);
577  if (verbose_ > 3)
578  print_trace(dir, name);
579 
580  // Check if the request monitor element already exists.
581  if (MonitorElement *me = findObject(dir, name))
582  {
583  if (verbose_ > 1)
584  {
585  std::string path;
586  mergePath(path, dir, name);
587 
588  std::cout << "DQMStore: "
589  << context << ": monitor element '"
590  << path << "' already exists, resetting" << std::endl;
591  }
592  me->Reset();
593  return me;
594  }
595  else
596  {
597  // Create it and return for initialisation.
598  assert(dirs_.count(dir));
599  MonitorElement nme(&*dirs_.find(dir), name);
600  return &const_cast<MonitorElement &>(*data_.insert(nme).first);
601  }
602 }
603 
604 // -------------------------------------------------------------------
607 DQMStore::bookInt(const std::string &dir, const std::string &name)
608 {
609  if (collateHistograms_)
610  {
611  if (MonitorElement *me = findObject(dir, name))
612  {
613  me->Fill(0);
614  return me;
615  }
616  }
617 
618  return book(dir, name, "bookInt")
620 }
621 
625 { return bookInt(pwd_, name); }
626 
629 DQMStore::bookInt(const std::string &name)
630 {
631  return bookInt(pwd_, name);
632 }
633 
634 // -------------------------------------------------------------------
637 DQMStore::bookFloat(const std::string &dir, const std::string &name)
638 {
639  if (collateHistograms_)
640  {
641  if (MonitorElement *me = findObject(dir, name))
642  {
643  me->Fill(0.);
644  return me;
645  }
646  }
647 
648  return book(dir, name, "bookFloat")
650 }
651 
655 { return bookFloat(pwd_, name); }
656 
659 DQMStore::bookFloat(const std::string &name)
660 {
661  return bookFloat(pwd_, name);
662 }
663 
664 // -------------------------------------------------------------------
667 DQMStore::bookString(const std::string &dir,
668  const std::string &name,
669  const std::string &value)
670 {
671  if (collateHistograms_)
672  {
673  if (MonitorElement *me = findObject(dir, name))
674  return me;
675  }
676 
677  return book(dir, name, "bookString")
679 }
680 
683 DQMStore::bookString(const char *name, const char *value)
684 { return bookString(pwd_, name, value); }
685 
688 DQMStore::bookString(const std::string &name, const std::string &value)
689 {
690  return bookString(pwd_, name, value);
691 }
692 
693 // -------------------------------------------------------------------
696 DQMStore::book1D(const std::string &dir, const std::string &name, TH1F *h)
697 {
698  return book(dir, name, "book1D", MonitorElement::DQM_KIND_TH1F, h, collate1D);
699 }
700 
703 DQMStore::book1S(const std::string &dir, const std::string &name, TH1S *h)
704 {
705  return book(dir, name, "book1S", MonitorElement::DQM_KIND_TH1S, h, collate1S);
706 }
707 
710 DQMStore::book1DD(const std::string &dir, const std::string &name, TH1D *h)
711 {
712  return book(dir, name, "book1DD", MonitorElement::DQM_KIND_TH1D, h, collate1DD);
713 }
714 
717 DQMStore::book1D(const char *name, const char *title,
718  int nchX, double lowX, double highX)
719 {
720  return book1D(pwd_, name, new TH1F(name, title, nchX, lowX, highX));
721 }
722 
725 DQMStore::book1D(const std::string &name, const std::string &title,
726  int nchX, double lowX, double highX)
727 {
728  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, lowX, highX));
729 }
730 
733 DQMStore::book1S(const char *name, const char *title,
734  int nchX, double lowX, double highX)
735 {
736  return book1S(pwd_, name, new TH1S(name, title, nchX, lowX, highX));
737 }
738 
741 DQMStore::book1S(const std::string &name, const std::string &title,
742  int nchX, double lowX, double highX)
743 {
744  return book1S(pwd_, name, new TH1S(name.c_str(), title.c_str(), nchX, lowX, highX));
745 }
746 
749 DQMStore::book1DD(const char *name, const char *title,
750  int nchX, double lowX, double highX)
751 {
752  return book1DD(pwd_, name, new TH1D(name, title, nchX, lowX, highX));
753 }
754 
757 DQMStore::book1DD(const std::string &name, const std::string &title,
758  int nchX, double lowX, double highX)
759 {
760  return book1DD(pwd_, name, new TH1D(name.c_str(), title.c_str(), nchX, lowX, highX));
761 }
762 
765 DQMStore::book1D(const char *name, const char *title,
766  int nchX, float *xbinsize)
767 {
768  return book1D(pwd_, name, new TH1F(name, title, nchX, xbinsize));
769 }
770 
773 DQMStore::book1D(const std::string &name, const std::string &title,
774  int nchX, float *xbinsize)
775 {
776  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, xbinsize));
777 }
778 
781 DQMStore::book1D(const char *name, TH1F *source)
782 {
783  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name)));
784 }
785 
788 DQMStore::book1D(const std::string &name, TH1F *source)
789 {
790  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name.c_str())));
791 }
792 
795 DQMStore::book1S(const char *name, TH1S *source)
796 {
797  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name)));
798 }
799 
802 DQMStore::book1S(const std::string &name, TH1S *source)
803 {
804  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name.c_str())));
805 }
806 
809 DQMStore::book1DD(const char *name, TH1D *source)
810 {
811  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name)));
812 }
813 
816 DQMStore::book1DD(const std::string &name, TH1D *source)
817 {
818  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name.c_str())));
819 }
820 
821 // -------------------------------------------------------------------
824 DQMStore::book2D(const std::string &dir, const std::string &name, TH2F *h)
825 {
826  return book(dir, name, "book2D", MonitorElement::DQM_KIND_TH2F, h, collate2D);
827 }
828 
831 DQMStore::book2S(const std::string &dir, const std::string &name, TH2S *h)
832 {
833  return book(dir, name, "book2S", MonitorElement::DQM_KIND_TH2S, h, collate2S);
834 }
835 
838 DQMStore::book2DD(const std::string &dir, const std::string &name, TH2D *h)
839 {
840  return book(dir, name, "book2DD", MonitorElement::DQM_KIND_TH2D, h, collate2DD);
841 }
842 
845 DQMStore::book2D(const char *name, const char *title,
846  int nchX, double lowX, double highX,
847  int nchY, double lowY, double highY)
848 {
849  return book2D(pwd_, name, new TH2F(name, title,
850  nchX, lowX, highX,
851  nchY, lowY, highY));
852 }
853 
856 DQMStore::book2D(const std::string &name, const std::string &title,
857  int nchX, double lowX, double highX,
858  int nchY, double lowY, double highY)
859 {
860  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
861  nchX, lowX, highX,
862  nchY, lowY, highY));
863 }
864 
867 DQMStore::book2S(const char *name, const char *title,
868  int nchX, double lowX, double highX,
869  int nchY, double lowY, double highY)
870 {
871  return book2S(pwd_, name, new TH2S(name, title,
872  nchX, lowX, highX,
873  nchY, lowY, highY));
874 }
875 
878 DQMStore::book2S(const std::string &name, const std::string &title,
879  int nchX, double lowX, double highX,
880  int nchY, double lowY, double highY)
881 {
882  return book2S(pwd_, name, new TH2S(name.c_str(), title.c_str(),
883  nchX, lowX, highX,
884  nchY, lowY, highY));
885 }
886 
889 DQMStore::book2DD(const char *name, const char *title,
890  int nchX, double lowX, double highX,
891  int nchY, double lowY, double highY)
892 {
893  return book2DD(pwd_, name, new TH2D(name, title,
894  nchX, lowX, highX,
895  nchY, lowY, highY));
896 }
897 
900 DQMStore::book2DD(const std::string &name, const std::string &title,
901  int nchX, double lowX, double highX,
902  int nchY, double lowY, double highY)
903 {
904  return book2DD(pwd_, name, new TH2D(name.c_str(), title.c_str(),
905  nchX, lowX, highX,
906  nchY, lowY, highY));
907 }
908 
911 DQMStore::book2D(const char *name, const char *title,
912  int nchX, float *xbinsize, int nchY, float *ybinsize)
913 {
914  return book2D(pwd_, name, new TH2F(name, title,
915  nchX, xbinsize, nchY, ybinsize));
916 }
917 
920 DQMStore::book2D(const std::string &name, const std::string &title,
921  int nchX, float *xbinsize, int nchY, float *ybinsize)
922 {
923  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
924  nchX, xbinsize, nchY, ybinsize));
925 }
926 
929 DQMStore::book2D(const char *name, TH2F *source)
930 {
931  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name)));
932 }
933 
936 DQMStore::book2D(const std::string &name, TH2F *source)
937 {
938  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name.c_str())));
939 }
940 
943 DQMStore::book2S(const char *name, TH2S *source)
944 {
945  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name)));
946 }
947 
950 DQMStore::book2S(const std::string &name, TH2S *source)
951 {
952  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name.c_str())));
953 }
954 
957 DQMStore::book2DD(const char *name, TH2D *source)
958 {
959  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name)));
960 }
961 
964 DQMStore::book2DD(const std::string &name, TH2D *source)
965 {
966  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name.c_str())));
967 }
968 
969 // -------------------------------------------------------------------
972 DQMStore::book3D(const std::string &dir, const std::string &name, TH3F *h)
973 {
974  return book(dir, name, "book3D", MonitorElement::DQM_KIND_TH3F, h, collate3D);
975 }
976 
979 DQMStore::book3D(const char *name, const char *title,
980  int nchX, double lowX, double highX,
981  int nchY, double lowY, double highY,
982  int nchZ, double lowZ, double highZ)
983 {
984  return book3D(pwd_, name, new TH3F(name, title,
985  nchX, lowX, highX,
986  nchY, lowY, highY,
987  nchZ, lowZ, highZ));
988 }
989 
992 DQMStore::book3D(const std::string &name, const std::string &title,
993  int nchX, double lowX, double highX,
994  int nchY, double lowY, double highY,
995  int nchZ, double lowZ, double highZ)
996 {
997  return book3D(pwd_, name, new TH3F(name.c_str(), title.c_str(),
998  nchX, lowX, highX,
999  nchY, lowY, highY,
1000  nchZ, lowZ, highZ));
1001 }
1002 
1005 DQMStore::book3D(const char *name, TH3F *source)
1006 {
1007  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name)));
1008 }
1009 
1012 DQMStore::book3D(const std::string &name, TH3F *source)
1013 {
1014  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name.c_str())));
1015 }
1016 
1017 // -------------------------------------------------------------------
1020 DQMStore::bookProfile(const std::string &dir, const std::string &name, TProfile *h)
1021 {
1022  return book(dir, name, "bookProfile",
1024  h, collateProfile);
1025 }
1026 
1031 DQMStore::bookProfile(const char *name, const char *title,
1032  int nchX, double lowX, double highX,
1033  int /* nchY */, double lowY, double highY,
1034  const char *option /* = "s" */)
1035 {
1036  return bookProfile(pwd_, name, new TProfile(name, title,
1037  nchX, lowX, highX,
1038  lowY, highY,
1039  option));
1040 }
1041 
1046 DQMStore::bookProfile(const std::string &name, const std::string &title,
1047  int nchX, double lowX, double highX,
1048  int /* nchY */, double lowY, double highY,
1049  const char *option /* = "s" */)
1050 {
1051  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1052  nchX, lowX, highX,
1053  lowY, highY,
1054  option));
1055 }
1056 
1061 DQMStore::bookProfile(const char *name, const char *title,
1062  int nchX, double lowX, double highX,
1063  double lowY, double highY,
1064  const char *option /* = "s" */)
1065 {
1066  return bookProfile(pwd_, name, new TProfile(name, title,
1067  nchX, lowX, highX,
1068  lowY, highY,
1069  option));
1070 }
1071 
1076 DQMStore::bookProfile(const std::string &name, const std::string &title,
1077  int nchX, double lowX, double highX,
1078  double lowY, double highY,
1079  const char *option /* = "s" */)
1080 {
1081  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1082  nchX, lowX, highX,
1083  lowY, highY,
1084  option));
1085 }
1086 
1091 DQMStore::bookProfile(const char *name, const char *title,
1092  int nchX, double *xbinsize,
1093  int /* nchY */, double lowY, double highY,
1094  const char *option /* = "s" */)
1095 {
1096  return bookProfile(pwd_, name, new TProfile(name, title,
1097  nchX, xbinsize,
1098  lowY, highY,
1099  option));
1100 }
1101 
1106 DQMStore::bookProfile(const std::string &name, const std::string &title,
1107  int nchX, double *xbinsize,
1108  int /* nchY */, double lowY, double highY,
1109  const char *option /* = "s" */)
1110 {
1111  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1112  nchX, xbinsize,
1113  lowY, highY,
1114  option));
1115 }
1116 
1121 DQMStore::bookProfile(const char *name, const char *title,
1122  int nchX, double *xbinsize,
1123  double lowY, double highY,
1124  const char *option /* = "s" */)
1125 {
1126  return bookProfile(pwd_, name, new TProfile(name, title,
1127  nchX, xbinsize,
1128  lowY, highY,
1129  option));
1130 }
1131 
1136 DQMStore::bookProfile(const std::string &name, const std::string &title,
1137  int nchX, double *xbinsize,
1138  double lowY, double highY,
1139  const char *option /* = "s" */)
1140 {
1141  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1142  nchX, xbinsize,
1143  lowY, highY,
1144  option));
1145 }
1146 
1149 DQMStore::bookProfile(const char *name, TProfile *source)
1150 {
1151  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name)));
1152 }
1153 
1156 DQMStore::bookProfile(const std::string &name, TProfile *source)
1157 {
1158  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name.c_str())));
1159 }
1160 
1161 // -------------------------------------------------------------------
1164 DQMStore::bookProfile2D(const std::string &dir, const std::string &name, TProfile2D *h)
1165 {
1166  return book(dir, name, "bookProfile2D",
1168  h, collateProfile2D);
1169 }
1170 
1175 DQMStore::bookProfile2D(const char *name, const char *title,
1176  int nchX, double lowX, double highX,
1177  int nchY, double lowY, double highY,
1178  int /* nchZ */, double lowZ, double highZ,
1179  const char *option /* = "s" */)
1180 {
1181  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1182  nchX, lowX, highX,
1183  nchY, lowY, highY,
1184  lowZ, highZ,
1185  option));
1186 }
1187 
1192 DQMStore::bookProfile2D(const std::string &name, const std::string &title,
1193  int nchX, double lowX, double highX,
1194  int nchY, double lowY, double highY,
1195  int /* nchZ */, double lowZ, double highZ,
1196  const char *option /* = "s" */)
1197 {
1198  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1199  nchX, lowX, highX,
1200  nchY, lowY, highY,
1201  lowZ, highZ,
1202  option));
1203 }
1204 
1209 DQMStore::bookProfile2D(const char *name, const char *title,
1210  int nchX, double lowX, double highX,
1211  int nchY, double lowY, double highY,
1212  double lowZ, double highZ,
1213  const char *option /* = "s" */)
1214 {
1215  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1216  nchX, lowX, highX,
1217  nchY, lowY, highY,
1218  lowZ, highZ,
1219  option));
1220 }
1221 
1226 DQMStore::bookProfile2D(const std::string &name, const std::string &title,
1227  int nchX, double lowX, double highX,
1228  int nchY, double lowY, double highY,
1229  double lowZ, double highZ,
1230  const char *option /* = "s" */)
1231 {
1232  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1233  nchX, lowX, highX,
1234  nchY, lowY, highY,
1235  lowZ, highZ,
1236  option));
1237 }
1238 
1241 DQMStore::bookProfile2D(const char *name, TProfile2D *source)
1242 {
1243  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name)));
1244 }
1245 
1248 DQMStore::bookProfile2D(const std::string &name, TProfile2D *source)
1249 {
1250  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name.c_str())));
1251 }
1252 
1256 bool
1258 {
1259  if (me->getTH1()->GetNbinsX() != h->GetNbinsX()
1260  || me->getTH1()->GetNbinsY() != h->GetNbinsY()
1261  || me->getTH1()->GetNbinsZ() != h->GetNbinsZ()
1262  || me->getTH1()->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin()
1263  || me->getTH1()->GetYaxis()->GetXmin() != h->GetYaxis()->GetXmin()
1264  || me->getTH1()->GetZaxis()->GetXmin() != h->GetZaxis()->GetXmin()
1265  || me->getTH1()->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax()
1266  || me->getTH1()->GetYaxis()->GetXmax() != h->GetYaxis()->GetXmax()
1267  || me->getTH1()->GetZaxis()->GetXmax() != h->GetZaxis()->GetXmax())
1268  {
1269  // edm::LogWarning ("DQMStore")
1270  std::cout << "*** DQMStore: WARNING:"
1271  << "checkBinningMatches: different binning - cannot add object '"
1272  << h->GetName() << "' of type "
1273  << h->IsA()->GetName() << " to existing ME: '"
1274  << me->getFullname() << "'\n";
1275  return false;
1276  }
1277  return true;
1278 }
1279 
1280 void
1282 {
1283  if (checkBinningMatches(me,h))
1284  me->getTH1F()->Add(h);
1285 }
1286 
1287 void
1289 {
1290  if (checkBinningMatches(me,h))
1291  me->getTH1S()->Add(h);
1292 }
1293 
1294 void
1296 {
1297  if (checkBinningMatches(me,h))
1298  me->getTH1D()->Add(h);
1299 }
1300 
1301 void
1303 {
1304  if (checkBinningMatches(me,h))
1305  me->getTH2F()->Add(h);
1306 }
1307 
1308 void
1310 {
1311  if (checkBinningMatches(me,h))
1312  me->getTH2S()->Add(h);
1313 }
1314 
1315 void
1317 {
1318  if (checkBinningMatches(me,h))
1319  me->getTH2D()->Add(h);
1320 }
1321 
1322 void
1324 {
1325  if (checkBinningMatches(me,h))
1326  me->getTH3F()->Add(h);
1327 }
1328 
1329 void
1331 {
1332  if (checkBinningMatches(me,h))
1333  {
1334  TProfile *meh = me->getTProfile();
1335  me->addProfiles(h, meh, meh, 1, 1);
1336  }
1337 }
1338 
1339 void
1341 {
1342  if (checkBinningMatches(me,h))
1343  {
1344  TProfile2D *meh = me->getTProfile2D();
1345  me->addProfiles(h, meh, meh, 1, 1);
1346  }
1347 }
1348 
1353 void
1354 DQMStore::tag(MonitorElement *me, unsigned int myTag)
1355 {
1356  if (! myTag)
1357  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1358  " with a zero tag", me->getFullname().c_str());
1359  if ((me->data_.flags & DQMNet::DQM_PROP_TAGGED) && myTag != me->data_.tag)
1360  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1361  " twice with multiple tags", me->getFullname().c_str());
1362 
1363  me->data_.tag = myTag;
1365 }
1366 
1368 void
1369 DQMStore::tag(const std::string &path, unsigned int myTag)
1370 {
1371  std::string dir;
1372  std::string name;
1373  splitPath(dir, name, path);
1374 
1375  if (MonitorElement *me = findObject(dir, name))
1376  tag(me, myTag);
1377  else
1378  raiseDQMError("DQMStore", "Attempt to tag non-existent monitor element"
1379  " '%s' with tag %u", path.c_str(), myTag);
1380 
1381 }
1382 
1384 void
1385 DQMStore::tagContents(const std::string &path, unsigned int myTag)
1386 {
1387  MonitorElement proto(&path, std::string());
1388  MEMap::iterator e = data_.end();
1389  MEMap::iterator i = data_.lower_bound(proto);
1390  for ( ; i != e && path == *i->data_.dirname; ++i)
1391  tag(const_cast<MonitorElement *>(&*i), myTag);
1392 }
1393 
1396 void
1397 DQMStore::tagAllContents(const std::string &path, unsigned int myTag)
1398 {
1399  std::string clean;
1400  const std::string *cleaned = 0;
1401  cleanTrailingSlashes(path, clean, cleaned);
1402  MonitorElement proto(cleaned, std::string());
1403 
1404  // FIXME: WILDCARDS? Old one supported them, but nobody seemed to use them.
1405  MEMap::iterator e = data_.end();
1406  MEMap::iterator i = data_.lower_bound(proto);
1407  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
1408  {
1409  tag(const_cast<MonitorElement *>(&*i), myTag);
1410  ++i;
1411  }
1412 }
1413 
1418 std::vector<std::string>
1420 {
1421  std::vector<std::string> result;
1422  std::set<std::string>::const_iterator e = dirs_.end();
1423  std::set<std::string>::const_iterator i = dirs_.find(pwd_);
1424 
1425  // If we didn't find current directory, the tree is empty, so quit.
1426  if (i == e)
1427  return result;
1428 
1429  // Skip the current directory and then start looking for immediate
1430  // subdirectories in the dirs_ list. Stop when we are no longer in
1431  // (direct or indirect) subdirectories of pwd_. Note that we don't
1432  // "know" which order the set will sort A/B, A/B/C and A/D.
1433  while (++i != e && isSubdirectory(pwd_, *i))
1434  if (i->find('/', pwd_.size()+1) == std::string::npos)
1435  result.push_back(*i);
1436 
1437  return result;
1438 }
1439 
1441 std::vector<std::string>
1442 DQMStore::getMEs(void) const
1443 {
1444  MonitorElement proto(&pwd_, std::string());
1445  std::vector<std::string> result;
1446  MEMap::const_iterator e = data_.end();
1447  MEMap::const_iterator i = data_.lower_bound(proto);
1448  for ( ; i != e && isSubdirectory(pwd_, *i->data_.dirname); ++i)
1449  if (pwd_ == *i->data_.dirname)
1450  result.push_back(i->getName());
1451 
1452  return result;
1453 }
1454 
1457 bool
1458 DQMStore::containsAnyMonitorable(const std::string &path) const
1459 {
1460  MonitorElement proto(&path, std::string());
1461  MEMap::const_iterator e = data_.end();
1462  MEMap::const_iterator i = data_.lower_bound(proto);
1463  return (i != e && isSubdirectory(path, *i->data_.dirname));
1464 }
1465 
1468 DQMStore::get(const std::string &path) const
1469 {
1470  std::string dir;
1471  std::string name;
1472  splitPath(dir, name, path);
1473  MonitorElement proto(&dir, name);
1474  MEMap::const_iterator mepos = data_.find(proto);
1475  return (mepos == data_.end() ? 0
1476  : const_cast<MonitorElement *>(&*mepos));
1477 }
1478 
1480 std::vector<MonitorElement *>
1481 DQMStore::get(unsigned int tag) const
1482 {
1483  // FIXME: Use reverse map [tag -> path] / [tag -> dir]?
1484  std::vector<MonitorElement *> result;
1485  for (MEMap::const_iterator i = data_.begin(), e = data_.end(); i != e; ++i)
1486  {
1487  const MonitorElement &me = *i;
1488  if ((me.data_.flags & DQMNet::DQM_PROP_TAGGED) && me.data_.tag == tag)
1489  result.push_back(const_cast<MonitorElement *>(&me));
1490  }
1491  return result;
1492 }
1493 
1496 std::vector<MonitorElement *>
1497 DQMStore::getContents(const std::string &path) const
1498 {
1499  std::string clean;
1500  const std::string *cleaned = 0;
1501  cleanTrailingSlashes(path, clean, cleaned);
1502  MonitorElement proto(cleaned, std::string());
1503 
1504  std::vector<MonitorElement *> result;
1505  MEMap::const_iterator e = data_.end();
1506  MEMap::const_iterator i = data_.lower_bound(proto);
1507  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1508  if (*cleaned == *i->data_.dirname)
1509  result.push_back(const_cast<MonitorElement *>(&*i));
1510 
1511  return result;
1512 }
1513 
1515 std::vector<MonitorElement *>
1516 DQMStore::getContents(const std::string &path, unsigned int tag) const
1517 {
1518  std::string clean;
1519  const std::string *cleaned = 0;
1520  cleanTrailingSlashes(path, clean, cleaned);
1521  MonitorElement proto(cleaned, std::string());
1522 
1523  std::vector<MonitorElement *> result;
1524  MEMap::const_iterator e = data_.end();
1525  MEMap::const_iterator i = data_.lower_bound(proto);
1526  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1527  if (*cleaned == *i->data_.dirname
1528  && (i->data_.flags & DQMNet::DQM_PROP_TAGGED)
1529  && i->data_.tag == tag)
1530  result.push_back(const_cast<MonitorElement *>(&*i));
1531 
1532  return result;
1533 }
1534 
1539 void
1540 DQMStore::getContents(std::vector<std::string> &into, bool showContents /* = true */) const
1541 {
1542  into.clear();
1543  into.reserve(dirs_.size());
1544 
1545  MEMap::const_iterator me = data_.end();
1546  std::set<std::string>::const_iterator di = dirs_.begin();
1547  std::set<std::string>::const_iterator de = dirs_.end();
1548  for ( ; di != de; ++di)
1549  {
1550  MonitorElement proto(&*di, std::string());
1551  MEMap::const_iterator mi = data_.lower_bound(proto);
1552  MEMap::const_iterator m = mi;
1553  size_t sz = di->size() + 2;
1554  size_t nfound = 0;
1555  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1556  if (*di == *m->data_.dirname)
1557  {
1558  sz += m->data_.objname.size() + 1;
1559  ++nfound;
1560  }
1561 
1562  if (! nfound)
1563  continue;
1564 
1565  std::vector<std::string>::iterator istr
1566  = into.insert(into.end(), std::string());
1567 
1568  if (showContents)
1569  {
1570  istr->reserve(sz);
1571 
1572  *istr += *di;
1573  *istr += ':';
1574  for (sz = 0; mi != m; ++mi)
1575  {
1576  if (*di != *mi->data_.dirname)
1577  continue;
1578 
1579  if (sz > 0)
1580  *istr += ',';
1581 
1582  *istr += mi->data_.objname;
1583  ++sz;
1584  }
1585  }
1586  else
1587  {
1588  istr->reserve(di->size() + 2);
1589  *istr += *di;
1590  *istr += ':';
1591  }
1592  }
1593 }
1594 
1598 DQMStore::findObject(const std::string &dir, const std::string &name) const
1599 {
1600  if (dir.find_first_not_of(s_safe) != std::string::npos)
1601  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1602  " unacceptable characters", dir.c_str());
1603  if (name.find_first_not_of(s_safe) != std::string::npos)
1604  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1605  " unacceptable characters", name.c_str());
1606 
1607  MonitorElement proto;
1608  proto.data_.dirname = &dir;
1609  proto.data_.objname = name;
1610 
1611  MEMap::const_iterator mepos = data_.find(proto);
1612  return (mepos == data_.end() ? 0
1613  : const_cast<MonitorElement *>(&*mepos));
1614 }
1615 
1618 void
1619 DQMStore::getAllTags(std::vector<std::string> &into) const
1620 {
1621  into.clear();
1622  into.reserve(dirs_.size());
1623 
1624  MEMap::const_iterator me = data_.end();
1625  std::set<std::string>::const_iterator di = dirs_.begin();
1626  std::set<std::string>::const_iterator de = dirs_.end();
1627  char tagbuf[32]; // more than enough for '/' and up to 10 digits
1628 
1629  for ( ; di != de; ++di)
1630  {
1631  MonitorElement proto(&*di, std::string());
1632  MEMap::const_iterator mi = data_.lower_bound(proto);
1633  MEMap::const_iterator m = mi;
1634  size_t sz = di->size() + 2;
1635  size_t nfound = 0;
1636  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1637  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1638  {
1639  // the tags count for '/' + up to 10 digits, otherwise ',' + ME name
1640  sz += 1 + m->data_.objname.size() + 11;
1641  ++nfound;
1642  }
1643 
1644  if (! nfound)
1645  continue;
1646 
1647  std::vector<std::string>::iterator istr
1648  = into.insert(into.end(), std::string());
1649 
1650  istr->reserve(sz);
1651 
1652  *istr += *di;
1653  *istr += ':';
1654  for (sz = 0; mi != m; ++mi)
1655  {
1656  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1657  {
1658  sprintf(tagbuf, "/%u", mi->data_.tag);
1659  if (sz > 0)
1660  *istr += ',';
1661  *istr += m->data_.objname;
1662  *istr += tagbuf;
1663  ++sz;
1664  }
1665  }
1666  }
1667 }
1668 
1671 std::vector<MonitorElement*>
1672 DQMStore::getAllContents(const std::string &path) const
1673 {
1674  std::string clean;
1675  const std::string *cleaned = 0;
1676  cleanTrailingSlashes(path, clean, cleaned);
1677  MonitorElement proto(cleaned, std::string());
1678 
1679  std::vector<MonitorElement *> result;
1680  MEMap::const_iterator e = data_.end();
1681  MEMap::const_iterator i = data_.lower_bound(proto);
1682  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1683  result.push_back(const_cast<MonitorElement *>(&*i));
1684 
1685  return result;
1686 }
1687 
1690 std::vector<MonitorElement*>
1691 DQMStore::getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType /* = Wildcard */) const
1692 {
1693  lat::Regexp rx;
1694  try
1695  {
1696  rx = lat::Regexp(pattern, 0, syntaxType);
1697  rx.study();
1698  }
1699  catch (lat::Error &e)
1700  {
1701  raiseDQMError("DQMStore", "Invalid regular expression '%s': %s",
1702  pattern.c_str(), e.explain().c_str());
1703  }
1704 
1705  std::string path;
1706  std::vector<MonitorElement *> result;
1707  MEMap::const_iterator i = data_.begin();
1708  MEMap::const_iterator e = data_.end();
1709  for ( ; i != e; ++i)
1710  {
1711  path.clear();
1712  mergePath(path, *i->data_.dirname, i->data_.objname);
1713  if (rx.match(path))
1714  result.push_back(const_cast<MonitorElement *>(&*i));
1715  }
1716 
1717  return result;
1718 }
1719 
1723 
1726 void
1728 {
1729  MEMap::iterator mi = data_.begin();
1730  MEMap::iterator me = data_.end();
1731  for ( ; mi != me; ++mi)
1732  {
1733  MonitorElement &me = const_cast<MonitorElement &>(*mi);
1734  if (mi->wasUpdated())
1735  {
1736  if (me.resetMe())
1737  me.Reset();
1738  me.resetUpdate();
1739  }
1740  }
1741 
1742  reset_ = true;
1743 }
1744 
1748 
1750 void
1752 {
1753  MEMap::iterator mi = data_.begin();
1754  MEMap::iterator me = data_.end();
1755  for ( ; mi != me; ++mi)
1756  {
1757  MonitorElement &me = const_cast<MonitorElement &>(*mi);
1758  me.Reset();
1759  me.resetUpdate();
1760  }
1761 
1762  reset_ = true;
1763 }
1764 
1770 bool
1771 DQMStore::extract(TObject *obj, const std::string &dir, bool overwrite)
1772 {
1773  // NB: Profile histograms inherit from TH*D, checking order matters.
1774  MonitorElement *refcheck = 0;
1775  if (TProfile *h = dynamic_cast<TProfile *>(obj))
1776  {
1777  MonitorElement *me = findObject(dir, h->GetName());
1778  if (! me)
1779  me = bookProfile(dir, h->GetName(), (TProfile *) h->Clone());
1780  else if (overwrite)
1781  me->copyFrom(h);
1782  else if (isCollateME(me) || collateHistograms_)
1783  collateProfile(me, h);
1784  refcheck = me;
1785  }
1786  else if (TProfile2D *h = dynamic_cast<TProfile2D *>(obj))
1787  {
1788  MonitorElement *me = findObject(dir, h->GetName());
1789  if (! me)
1790  me = bookProfile2D(dir, h->GetName(), (TProfile2D *) h->Clone());
1791  else if (overwrite)
1792  me->copyFrom(h);
1793  else if (isCollateME(me) || collateHistograms_)
1794  collateProfile2D(me, h);
1795  refcheck = me;
1796  }
1797  else if (TH1F *h = dynamic_cast<TH1F *>(obj))
1798  {
1799  MonitorElement *me = findObject(dir, h->GetName());
1800  if (! me)
1801  me = book1D(dir, h->GetName(), (TH1F *) h->Clone());
1802  else if (overwrite)
1803  me->copyFrom(h);
1804  else if (isCollateME(me) || collateHistograms_)
1805  collate1D(me, h);
1806  refcheck = me;
1807  }
1808  else if (TH1S *h = dynamic_cast<TH1S *>(obj))
1809  {
1810  MonitorElement *me = findObject(dir, h->GetName());
1811  if (! me)
1812  me = book1S(dir, h->GetName(), (TH1S *) h->Clone());
1813  else if (overwrite)
1814  me->copyFrom(h);
1815  else if (isCollateME(me) || collateHistograms_)
1816  collate1S(me, h);
1817  refcheck = me;
1818  }
1819  else if (TH1D *h = dynamic_cast<TH1D *>(obj))
1820  {
1821  MonitorElement *me = findObject(dir, h->GetName());
1822  if (! me)
1823  me = book1DD(dir, h->GetName(), (TH1D *) h->Clone());
1824  else if (overwrite)
1825  me->copyFrom(h);
1826  else if (isCollateME(me) || collateHistograms_)
1827  collate1DD(me, h);
1828  refcheck = me;
1829  }
1830  else if (TH2F *h = dynamic_cast<TH2F *>(obj))
1831  {
1832  MonitorElement *me = findObject(dir, h->GetName());
1833  if (! me)
1834  me = book2D(dir, h->GetName(), (TH2F *) h->Clone());
1835  else if (overwrite)
1836  me->copyFrom(h);
1837  else if (isCollateME(me) || collateHistograms_)
1838  collate2D(me, h);
1839  refcheck = me;
1840  }
1841  else if (TH2S *h = dynamic_cast<TH2S *>(obj))
1842  {
1843  MonitorElement *me = findObject(dir, h->GetName());
1844  if (! me)
1845  me = book2S(dir, h->GetName(), (TH2S *) h->Clone());
1846  else if (overwrite)
1847  me->copyFrom(h);
1848  else if (isCollateME(me) || collateHistograms_)
1849  collate2S(me, h);
1850  refcheck = me;
1851  }
1852  else if (TH2D *h = dynamic_cast<TH2D *>(obj))
1853  {
1854  MonitorElement *me = findObject(dir, h->GetName());
1855  if (! me)
1856  me = book2DD(dir, h->GetName(), (TH2D *) h->Clone());
1857  else if (overwrite)
1858  me->copyFrom(h);
1859  else if (isCollateME(me) || collateHistograms_)
1860  collate2DD(me, h);
1861  refcheck = me;
1862  }
1863  else if (TH3F *h = dynamic_cast<TH3F *>(obj))
1864  {
1865  MonitorElement *me = findObject(dir, h->GetName());
1866  if (! me)
1867  me = book3D(dir, h->GetName(), (TH3F *) h->Clone());
1868  else if (overwrite)
1869  me->copyFrom(h);
1870  else if (isCollateME(me) || collateHistograms_)
1871  collate3D(me, h);
1872  refcheck = me;
1873  }
1874  else if (dynamic_cast<TObjString *>(obj))
1875  {
1876  lat::RegexpMatch m;
1877  if (! s_rxmeval.match(obj->GetName(), 0, 0, &m))
1878  {
1879  if (strstr(obj->GetName(), "CMSSW"))
1880  {
1881  if (verbose_)
1882  std::cout << "Input file version: " << obj->GetName() << std::endl;
1883  return true;
1884  }
1885  else if (strstr(obj->GetName(), "DQMPATCH"))
1886  {
1887  if (verbose_)
1888  std::cout << "DQM patch version: " << obj->GetName() << std::endl;
1889  return true;
1890  }
1891  else
1892  {
1893  std::cout << "*** DQMStore: WARNING: cannot extract object '"
1894  << obj->GetName() << "' of type '"
1895  << obj->IsA()->GetName() << "'\n";
1896  return false;
1897  }
1898  }
1899 
1900  std::string label = m.matchString(obj->GetName(), 1);
1901  std::string kind = m.matchString(obj->GetName(), 2);
1902  std::string value = m.matchString(obj->GetName(), 3);
1903 
1904  if (kind == "i")
1905  {
1906  MonitorElement *me = findObject(dir, label);
1907  if (! me || overwrite)
1908  {
1909  if (! me) me = bookInt(dir, label);
1910  me->Fill(atoll(value.c_str()));
1911  }
1912  }
1913  else if (kind == "f")
1914  {
1915  MonitorElement *me = findObject(dir, label);
1916  if (! me || overwrite)
1917  {
1918  if (! me) me = bookFloat(dir, label);
1919  me->Fill(atof(value.c_str()));
1920  }
1921  }
1922  else if (kind == "s")
1923  {
1924  MonitorElement *me = findObject(dir, label);
1925  if (! me)
1926  me = bookString(dir, label, value);
1927  else if (overwrite)
1928  me->Fill(value);
1929  }
1930  else if (kind == "e")
1931  {
1932  MonitorElement *me = findObject(dir, label);
1933  if (! me)
1934  {
1935  std::cout << "*** DQMStore: WARNING: no monitor element '"
1936  << label << "' in directory '"
1937  << dir << "' to be marked as efficiency plot.\n";
1938  return false;
1939  }
1940  me->setEfficiencyFlag();
1941  }
1942  else if (kind == "t")
1943  {
1944  MonitorElement *me = findObject(dir, label);
1945  if (! me)
1946  {
1947  std::cout << "*** DQMStore: WARNING: no monitor element '"
1948  << label << "' in directory '"
1949  << dir << "' for a tag\n";
1950  return false;
1951  }
1952  errno = 0;
1953  char *endp = 0;
1954  unsigned long val = strtoul(value.c_str(), &endp, 10);
1955  if ((val == 0 && errno) || *endp || val > ~uint32_t(0))
1956  {
1957  std::cout << "*** DQMStore: WARNING: cannot restore tag '"
1958  << value << "' for monitor element '"
1959  << label << "' in directory '"
1960  << dir << "' - invalid value\n";
1961  return false;
1962  }
1963  tag(me, val);
1964  }
1965  else if (kind == "qr")
1966  {
1967  // Handle qreports, but skip them while reading in references.
1968  if (! isSubdirectory(s_referenceDirName, dir))
1969  {
1970  size_t dot = label.find('.');
1971  if (dot == std::string::npos)
1972  {
1973  std::cout << "*** DQMStore: WARNING: quality report label in '" << label
1974  << "' is missing a '.' and cannot be extracted\n";
1975  return false;
1976  }
1977 
1978  std::string mename (label, 0, dot);
1979  std::string qrname (label, dot+1, std::string::npos);
1980 
1981  m.reset();
1982  DQMNet::QValue qv;
1983  if (s_rxmeqr1.match(value, 0, 0, &m))
1984  {
1985  qv.code = atoi(m.matchString(value, 1).c_str());
1986  qv.qtresult = strtod(m.matchString(value, 2).c_str(), 0);
1987  qv.message = m.matchString(value, 4);
1988  qv.qtname = qrname;
1989  qv.algorithm = m.matchString(value, 3);
1990  }
1991  else if (s_rxmeqr2.match(value, 0, 0, &m))
1992  {
1993  qv.code = atoi(m.matchString(value, 1).c_str());
1994  qv.qtresult = 0; // unavailable in old format
1995  qv.message = m.matchString(value, 2);
1996  qv.qtname = qrname;
1997  // qv.algorithm unavailable in old format
1998  }
1999  else
2000  {
2001  std::cout << "*** DQMStore: WARNING: quality test value '"
2002  << value << "' is incorrectly formatted\n";
2003  return false;
2004  }
2005 
2006  MonitorElement *me = findObject(dir, mename);
2007  if (! me)
2008  {
2009  std::cout << "*** DQMStore: WARNING: no monitor element '"
2010  << mename << "' in directory '"
2011  << dir << "' for quality test '"
2012  << label << "'\n";
2013  return false;
2014  }
2015 
2016  me->addQReport(qv, /* FIXME: getQTest(qv.qtname)? */ 0);
2017  }
2018  }
2019  else
2020  {
2021  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2022  << obj->GetName() << "' of type '"
2023  << obj->IsA()->GetName() << "'\n";
2024  return false;
2025  }
2026  }
2027  else if (TNamed *n = dynamic_cast<TNamed *>(obj))
2028  {
2029  // For old DQM data.
2030  std::string s;
2031  s.reserve(6 + strlen(n->GetTitle()) + 2*strlen(n->GetName()));
2032  s += '<'; s += n->GetName(); s += '>';
2033  s += n->GetTitle();
2034  s += '<'; s += '/'; s += n->GetName(); s += '>';
2035  TObjString os(s.c_str());
2036  return extract(&os, dir, overwrite);
2037  }
2038  else
2039  {
2040  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2041  << obj->GetName() << "' of type '" << obj->IsA()->GetName()
2042  << "' and with title '" << obj->GetTitle() << "'\n";
2043  return false;
2044  }
2045 
2046  // If we just read in a reference monitor element, and there is a
2047  // monitor element with the same name, link the two together. The
2048  // other direction is handled by the initialise() method.
2049  if (refcheck && isSubdirectory(s_referenceDirName, dir))
2050  {
2051  std::string mdir(dir, s_referenceDirName.size()+1, std::string::npos);
2052  if (MonitorElement *master = findObject(mdir, obj->GetName()))
2053  {
2054  master->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
2055  master->reference_ = refcheck->object_;
2056  }
2057  }
2058 
2059  return true;
2060 }
2061 
2065 bool
2066 DQMStore::cdInto(const std::string &path) const
2067 {
2068  assert(! path.empty());
2069 
2070  // Find the first path component.
2071  size_t start = 0;
2072  size_t end = path.find('/', start);
2073  if (end == std::string::npos)
2074  end = path.size();
2075 
2076  while (true)
2077  {
2078  // Check if this subdirectory component exists. If yes, make sure
2079  // it is actually a subdirectory. Otherwise create or cd into it.
2080  std::string part(path, start, end-start);
2081  TObject *o = gDirectory->Get(part.c_str());
2082  if (o && ! dynamic_cast<TDirectory *>(o))
2083  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2084  " fails because the part '%s' already exists and is not"
2085  " directory", path.c_str(), part.c_str());
2086  else if (! o)
2087  gDirectory->mkdir(part.c_str());
2088 
2089  if (! gDirectory->cd(part.c_str()))
2090  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2091  " fails because could not cd into subdirectory '%s'",
2092  path.c_str(), part.c_str());
2093 
2094  // Stop if we reached the end, ignoring any trailing '/'.
2095  if (end+1 >= path.size())
2096  break;
2097 
2098  // Find the next path component.
2099  start = end+1;
2100  end = path.find('/', start);
2101  if (end == std::string::npos)
2102  end = path.size();
2103  }
2104 
2105  return true;
2106 }
2107 
2112 void
2113 DQMStore::save(const std::string &filename,
2114  const std::string &path /* = "" */,
2115  const std::string &pattern /* = "" */,
2116  const std::string &rewrite /* = "" */,
2117  SaveReferenceTag ref /* = SaveWithReference */,
2118  int minStatus /* = dqm::qstatus::STATUS_OK */,
2119  const std::string &fileupdate /* = RECREATE */)
2120 {
2121  std::set<std::string>::iterator di, de;
2122  MEMap::iterator mi, me = data_.end();
2123  DQMNet::QReports::const_iterator qi, qe;
2124  int nme=0;
2125 
2126  // TFile flushes to disk with fsync() on every TDirectory written to the
2127  // file. This makes DQM file saving painfully slow, and ironically makes
2128  // it _more_ likely the file saving gets interrupted and corrupts the file.
2129  // The utility class below simply ignores the flush synchronisation.
2130  class TFileNoSync : public TFile
2131  {
2132  public:
2133  TFileNoSync(const char *file, const char *opt) : TFile(file, opt) {}
2134  virtual Int_t SysSync(Int_t) { return 0; }
2135  };
2136 
2137  // open output file, on 1st save recreate, later update
2138  if (verbose_)
2139  std::cout << "\n DQMStore: Opening TFile '" << filename
2140  << "' with option '" << fileupdate <<"'\n";
2141 
2142  TFileNoSync f(filename.c_str(), fileupdate.c_str()); // open file
2143  if(f.IsZombie())
2144  raiseDQMError("DQMStore", "Failed to create/update file '%s'", filename.c_str());
2145  f.cd();
2146 
2147  // Construct a regular expression from the pattern string.
2148  std::auto_ptr<lat::Regexp> rxpat;
2149  if (! pattern.empty())
2150  rxpat.reset(new lat::Regexp(pattern.c_str()));
2151 
2152  // Prepare a path for the reference object selection.
2153  std::string refpath;
2154  refpath.reserve(s_referenceDirName.size() + path.size() + 2);
2155  refpath += s_referenceDirName;
2156  if (! path.empty())
2157  {
2158  refpath += '/';
2159  refpath += path;
2160  }
2161 
2162  // Loop over the directory structure.
2163  for (di = dirs_.begin(), de = dirs_.end(); di != de; ++di)
2164  {
2165  // Check if we should process this directory. We process the
2166  // requested part of the object tree, including references.
2167  if (! path.empty()
2168  && ! isSubdirectory(path, *di)
2169  && ! isSubdirectory(refpath, *di))
2170  continue;
2171 
2172  // Loop over monitor elements in this directory.
2173  MonitorElement proto(&*di, std::string());
2174  mi = data_.lower_bound(proto);
2175  for ( ; mi != me && isSubdirectory(*di, *mi->data_.dirname); ++mi)
2176  {
2177  // Skip if it isn't a direct child.
2178  if (*di != *mi->data_.dirname)
2179  continue;
2180 
2181  // Handle reference histograms, with three distinct cases:
2182  // 1) Skip all references entirely on saving.
2183  // 2) Blanket saving of all references.
2184  // 3) Save only references for monitor elements with qtests.
2185  // The latter two are affected by "path" sub-tree selection,
2186  // i.e. references are saved only in the selected tree part.
2187  if (isSubdirectory(refpath, *mi->data_.dirname))
2188  {
2189  if (ref == SaveWithoutReference)
2190  // Skip the reference entirely.
2191  continue;
2192  else if (ref == SaveWithReference)
2193  // Save all references regardless of qtests.
2194  ;
2195  else if (ref == SaveWithReferenceForQTest)
2196  {
2197  // Save only references for monitor elements with qtests
2198  // with an optional cut on minimum quality test result.
2199  int status = -1;
2200  std::string mname(mi->getFullname(), s_referenceDirName.size()+1, std::string::npos);
2201  MonitorElement *master = get(mname);
2202  if (master)
2203  for (size_t i = 0, e = master->data_.qreports.size(); i != e; ++i)
2204  status = std::max(status, master->data_.qreports[i].code);
2205 
2206  if (! master || status < minStatus)
2207  {
2208  if (verbose_ > 1)
2209  std::cout << "DQMStore::save: skipping monitor element '"
2210  << mi->data_.objname << "' while saving, status is "
2211  << status << ", required minimum status is "
2212  << minStatus << std::endl;
2213  continue;
2214  }
2215  }
2216  }
2217 
2218  if (verbose_ > 1)
2219  std::cout << "DQMStore::save: saving monitor element '"
2220  << mi->data_.objname << "'\n";
2221  nme++; // count saved histograms
2222 
2223  // Create the directory.
2224  gDirectory->cd("/");
2225  if (di->empty())
2227  else if (rxpat.get())
2228  cdInto(s_monitorDirName + '/' + lat::StringOps::replace(*di, *rxpat, rewrite));
2229  else
2230  cdInto(s_monitorDirName + '/' + *di);
2231 
2232  // Save the object.
2233  switch (mi->kind())
2234  {
2238  TObjString(mi->tagString().c_str()).Write();
2239  break;
2240 
2241  default:
2242  mi->object_->Write();
2243  break;
2244  }
2245 
2246  // Save quality reports if this is not in reference section.
2247  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
2248  {
2249  qi = mi->data_.qreports.begin();
2250  qe = mi->data_.qreports.end();
2251  for ( ; qi != qe; ++qi)
2252  TObjString(mi->qualityTagString(*qi).c_str()).Write();
2253  }
2254 
2255  // Save efficiency tag, if any
2256  if (mi->data_.flags & DQMNet::DQM_PROP_EFFICIENCY_PLOT)
2257  TObjString(mi->effLabelString().c_str()).Write();
2258 
2259  // Save tag if any
2260  if (mi->data_.flags & DQMNet::DQM_PROP_TAGGED)
2261  TObjString(mi->tagLabelString().c_str()).Write();
2262  }
2263  }
2264 
2265  f.Close();
2266 
2267  // Maybe make some noise.
2268  if (verbose_)
2269  std::cout << "DQMStore::save: successfully wrote " << nme
2270  << " objects from path '" << path
2271  << "' into DQM file '" << filename << "'\n";
2272 }
2273 
2276 unsigned int
2278  bool overwrite,
2279  const std::string &onlypath,
2280  const std::string &prepend,
2281  const std::string &curdir,
2282  OpenRunDirs stripdirs)
2283 {
2284  unsigned int ntot = 0;
2285  unsigned int count = 0;
2286 
2287  if (! file->cd(curdir.c_str()))
2288  raiseDQMError("DQMStore", "Failed to process directory '%s' while"
2289  " reading file '%s'", curdir.c_str(), file->GetName());
2290 
2291  // Figure out current directory name, but strip out the top
2292  // directory into which we dump everything.
2293  std::string dirpart = curdir;
2294  if (dirpart.compare(0, s_monitorDirName.size(), s_monitorDirName) == 0)
2295  {
2296  if (dirpart.size() == s_monitorDirName.size())
2297  dirpart.clear();
2298  else if (dirpart[s_monitorDirName.size()] == '/')
2299  dirpart.erase(0, s_monitorDirName.size()+1);
2300  }
2301 
2302  // See if we are going to skip this directory.
2303  bool skip = (! onlypath.empty() && ! isSubdirectory(onlypath, dirpart));
2304 
2305  if (prepend == s_collateDirName ||
2306  prepend == s_referenceDirName ||
2307  stripdirs == StripRunDirs )
2308  {
2309  // Remove Run # and RunSummary dirs
2310  // first look for Run summary,
2311  // if that is found and erased, also erase Run dir
2312  size_t slash = dirpart.find('/');
2313  size_t pos = dirpart.find("/Run summary");
2314  if (slash != std::string::npos && pos !=std::string::npos)
2315  {
2316  dirpart.erase(pos,12);
2317 
2318  pos = dirpart.find("Run ");
2319  size_t length = dirpart.find('/',pos+1)-pos+1;
2320  if (pos !=std::string::npos)
2321  dirpart.erase(pos,length);
2322  }
2323  }
2324 
2325  // If we are prepending, add it to the directory name,
2326  // and suppress reading of already existing reference histograms
2327  if (prepend == s_collateDirName ||
2328  prepend == s_referenceDirName)
2329  {
2330  size_t slash = dirpart.find('/');
2331  // If we are reading reference, skip previous reference.
2332  if (slash == std::string::npos // skip if Reference is toplevel folder, i.e. no slash
2333  && slash+1+s_referenceDirName.size() == dirpart.size()
2334  && dirpart.compare(slash+1, s_referenceDirName.size(), s_referenceDirName) == 0)
2335  return 0;
2336 
2337  slash = dirpart.find('/');
2338  // Skip reading of EventInfo subdirectory.
2339  if (slash != std::string::npos
2340  && slash + 10 == dirpart.size()
2341  && dirpart.compare( slash+1 , 9 , "EventInfo") == 0) {
2342  if (verbose_)
2343  std::cout << "DQMStore::readDirectory: skipping '" << dirpart << "'\n";
2344  return 0;
2345  }
2346 
2347  // Add prefix.
2348  if (dirpart.empty())
2349  dirpart = prepend;
2350  else
2351  dirpart = prepend + '/' + dirpart;
2352  }
2353  else if (! prepend.empty())
2354  {
2355  if (dirpart.empty())
2356  dirpart = prepend;
2357  else
2358  dirpart = prepend + '/' + dirpart;
2359  }
2360 
2361  // Loop over the contents of this directory in the file.
2362  // Post-pone string object handling to happen after other
2363  // objects have been read in so we are guaranteed to have
2364  // histograms by the time we read in quality tests and tags.
2365  TKey *key;
2366  TIter next (gDirectory->GetListOfKeys());
2367  std::list<TObject *> delayed;
2368  while ((key = (TKey *) next()))
2369  {
2370  std::auto_ptr<TObject> obj(key->ReadObj());
2371  if (dynamic_cast<TDirectory *>(obj.get()))
2372  {
2373  std::string subdir;
2374  subdir.reserve(curdir.size() + strlen(obj->GetName()) + 2);
2375  subdir += curdir;
2376  if (! curdir.empty())
2377  subdir += '/';
2378  subdir += obj->GetName();
2379 
2380  ntot += readDirectory(file, overwrite, onlypath, prepend, subdir, stripdirs);
2381  }
2382  else if (skip)
2383  ;
2384  else if (dynamic_cast<TObjString *>(obj.get()))
2385  {
2386  delayed.push_back(obj.release());
2387  }
2388  else
2389  {
2390  if (verbose_ > 2)
2391  std::cout << "DQMStore: reading object '" << obj->GetName()
2392  << "' of type '" << obj->IsA()->GetName()
2393  << "' from '" << file->GetName()
2394  << "' into '" << dirpart << "'\n";
2395 
2396  makeDirectory(dirpart);
2397  if (extract(obj.get(), dirpart, overwrite))
2398  ++count;
2399  }
2400  }
2401 
2402  while (! delayed.empty())
2403  {
2404  if (verbose_ > 2)
2405  std::cout << "DQMStore: reading object '" << delayed.front()->GetName()
2406  << "' of type '" << delayed.front()->IsA()->GetName()
2407  << "' from '" << file->GetName()
2408  << "' into '" << dirpart << "'\n";
2409 
2410  makeDirectory(dirpart);
2411  if (extract(delayed.front(), dirpart, overwrite))
2412  ++count;
2413 
2414  delete delayed.front();
2415  delayed.pop_front();
2416  }
2417 
2418  if (verbose_ > 1)
2419  std::cout << "DQMStore: read " << count << '/' << ntot
2420  << " objects from directory '" << dirpart << "'\n";
2421 
2422  return ntot + count;
2423 }
2424 
2431 bool
2432 DQMStore::open(const std::string &filename,
2433  bool overwrite /* = false */,
2434  const std::string &onlypath /* ="" */,
2435  const std::string &prepend /* ="" */,
2436  OpenRunDirs stripdirs /* =KeepRunDirs */,
2437  bool fileMustExist /* =true */)
2438 {
2439  return readFile(filename,overwrite,onlypath,prepend,stripdirs,fileMustExist);
2440 }
2441 
2446 bool
2447 DQMStore::load(const std::string &filename,
2448  OpenRunDirs stripdirs /* =StripRunDirs */,
2449  bool fileMustExist /* =true */)
2450 {
2451  bool overwrite = true;
2452  if (collateHistograms_) overwrite = false;
2453  if (verbose_)
2454  {
2455  std::cout << "DQMStore::load: reading from file '" << filename << "'\n";
2456  if (collateHistograms_)
2457  std::cout << "DQMStore::load: in collate mode " << "\n";
2458  else
2459  std::cout << "DQMStore::load: in overwrite mode " << "\n";
2460  }
2461 
2462  return readFile(filename,overwrite,"","",stripdirs,fileMustExist);
2463 
2464 }
2465 
2471 bool
2472 DQMStore::readFile(const std::string &filename,
2473  bool overwrite /* = false */,
2474  const std::string &onlypath /* ="" */,
2475  const std::string &prepend /* ="" */,
2476  OpenRunDirs stripdirs /* =StripRunDirs */,
2477  bool fileMustExist /* =true */)
2478 {
2479 
2480  if (verbose_)
2481  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
2482 
2483  std::auto_ptr<TFile> f;
2484 
2485  try
2486  {
2487  f.reset(TFile::Open(filename.c_str()));
2488  if (! f.get() || f->IsZombie())
2489  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
2490  }
2491  catch (std::exception &)
2492  {
2493  if (fileMustExist)
2494  throw;
2495  else
2496  {
2497  if (verbose_)
2498  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
2499  return false;
2500  }
2501  }
2502 
2503  unsigned n = readDirectory(f.get(), overwrite, onlypath, prepend, "", stripdirs);
2504  f->Close();
2505 
2506  MEMap::iterator mi = data_.begin();
2507  MEMap::iterator me = data_.end();
2508  for ( ; mi != me; ++mi)
2509  const_cast<MonitorElement &>(*mi).updateQReportStats();
2510 
2511  if (verbose_)
2512  {
2513  std::cout << "DQMStore::open: successfully read " << n
2514  << " objects from file '" << filename << "'";
2515  if (! onlypath.empty())
2516  std::cout << " from directory '" << onlypath << "'";
2517  if (! prepend.empty())
2518  std::cout << " into directory '" << prepend << "'";
2519  std::cout << std::endl;
2520  }
2521  return true;
2522 }
2523 
2529 void
2530 DQMStore::rmdir(const std::string &path)
2531 {
2532  std::string clean;
2533  const std::string *cleaned = 0;
2534  cleanTrailingSlashes(path, clean, cleaned);
2535  MonitorElement proto(cleaned, std::string());
2536 
2537  MEMap::iterator e = data_.end();
2538  MEMap::iterator i = data_.lower_bound(proto);
2539  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
2540  data_.erase(i++);
2541 
2542  std::set<std::string>::iterator de = dirs_.end();
2543  std::set<std::string>::iterator di = dirs_.lower_bound(*cleaned);
2544  while (di != de && isSubdirectory(*cleaned, *di))
2545  dirs_.erase(di++);
2546 }
2547 
2549 void
2550 DQMStore::removeContents(const std::string &dir)
2551 {
2552  MonitorElement proto(&dir, std::string());
2553  MEMap::iterator e = data_.end();
2554  MEMap::iterator i = data_.lower_bound(proto);
2555  while (i != e && isSubdirectory(dir, *i->data_.dirname))
2556  if (dir == *i->data_.dirname)
2557  data_.erase(i++);
2558  else
2559  ++i;
2560 }
2561 
2563 void
2565 {
2567 }
2568 
2571 void
2572 DQMStore::removeElement(const std::string &name)
2573 {
2574  removeElement(pwd_, name);
2575 }
2576 
2579 void
2580 DQMStore::removeElement(const std::string &dir, const std::string &name, bool warning /* = true */)
2581 {
2582  MonitorElement proto(&dir, name);
2583  MEMap::iterator pos = data_.find(proto);
2584  if (pos == data_.end() && warning)
2585  std::cout << "DQMStore: WARNING: attempt to remove non-existent"
2586  << " monitor element '" << name << "' in '" << dir << "'\n";
2587  else
2588  data_.erase(pos);
2589 }
2590 
2596 QCriterion *
2597 DQMStore::getQCriterion(const std::string &qtname) const
2598 {
2599  QCMap::const_iterator i = qtests_.find(qtname);
2600  QCMap::const_iterator e = qtests_.end();
2601  return (i == e ? 0 : i->second);
2602 }
2603 
2607 QCriterion *
2608 DQMStore::createQTest(const std::string &algoname, const std::string &qtname)
2609 {
2610  if (qtests_.count(qtname))
2611  raiseDQMError("DQMStore", "Attempt to create duplicate quality test '%s'",
2612  qtname.c_str());
2613 
2614  QAMap::iterator i = qalgos_.find(algoname);
2615  if (i == qalgos_.end())
2616  raiseDQMError("DQMStore", "Cannot create a quality test using unknown"
2617  " algorithm '%s'", algoname.c_str());
2618 
2619  QCriterion *qc = i->second(qtname);
2620  qc->setVerbose(verboseQT_);
2621 
2622  qtests_[qtname] = qc;
2623  return qc;
2624 }
2625 
2628 void
2629 DQMStore::useQTest(const std::string &dir, const std::string &qtname)
2630 {
2631  // Clean the path
2632  std::string clean;
2633  const std::string *cleaned = 0;
2634  cleanTrailingSlashes(dir, clean, cleaned);
2635 
2636  // Validate the path.
2637  if (cleaned->find_first_not_of(s_safe) != std::string::npos)
2638  raiseDQMError("DQMStore", "Monitor element path name '%s'"
2639  " uses unacceptable characters", cleaned->c_str());
2640 
2641  // Redirect to the pattern match version.
2642  useQTestByMatch(*cleaned + "/*", qtname);
2643 }
2644 
2646 int
2647 DQMStore::useQTestByMatch(const std::string &pattern, const std::string &qtname)
2648 {
2649  QCriterion *qc = getQCriterion(qtname);
2650  if (! qc)
2651  raiseDQMError("DQMStore", "Cannot apply non-existent quality test '%s'",
2652  qtname.c_str());
2653 
2654  fastmatch * fm = new fastmatch( pattern );
2655 
2656  // Record the test for future reference.
2657  QTestSpec qts(fm, qc);
2658  qtestspecs_.push_back(qts);
2659 
2660  // Apply the quality test.
2661  MEMap::iterator mi = data_.begin();
2662  MEMap::iterator me = data_.end();
2663  std::string path;
2664  int cases = 0;
2665  for ( ; mi != me; ++mi)
2666  {
2667  path.clear();
2668  mergePath(path, *mi->data_.dirname, mi->data_.objname);
2669  if (fm->match(path))
2670  {
2671  ++cases;
2672  const_cast<MonitorElement &>(*mi).addQReport(qts.second);
2673  }
2674  }
2675 
2676  //return the number of matched cases
2677  return cases;
2678 }
2681 void
2683 {
2684 
2685  if (verbose_ > 0)
2686  std::cout << "DQMStore: running runQTests() with reset = "
2687  << ( reset_ ? "true" : "false" ) << std::endl;
2688 
2689  // Apply quality tests to each monitor element, skipping references.
2690  MEMap::iterator mi = data_.begin();
2691  MEMap::iterator me = data_.end();
2692  for ( ; mi != me; ++mi)
2693  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
2694  const_cast<MonitorElement &>(*mi).runQTests();
2695 
2696  reset_ = false;
2697 }
2698 
2702 int
2703 DQMStore::getStatus(const std::string &path /* = "" */) const
2704 {
2705  std::string clean;
2706  const std::string *cleaned = 0;
2707  cleanTrailingSlashes(path, clean, cleaned);
2708 
2710  MEMap::const_iterator mi = data_.begin();
2711  MEMap::const_iterator me = data_.end();
2712  for ( ; mi != me; ++mi)
2713  {
2714  if (! cleaned->empty() && ! isSubdirectory(*cleaned, *mi->data_.dirname))
2715  continue;
2716 
2717  if (mi->hasError())
2718  return dqm::qstatus::ERROR;
2719  else if (mi->hasWarning())
2720  status = dqm::qstatus::WARNING;
2721  else if (status < dqm::qstatus::WARNING
2722  && mi->hasOtherReport())
2723  status = dqm::qstatus::OTHER;
2724  }
2725  return status;
2726 }
2727 
2733 void
2735 {
2736  if (me)
2737  me->softReset();
2738 }
2739 
2740 // reverts action of softReset
2741 void
2743 {
2744  if (me)
2745  me->disableSoftReset();
2746 }
2747 
2750 void
2752 {
2753  if (me)
2754  me->setAccumulate(flag);
2755 }
2756 
2760 void
2762 {
2763  std::vector<std::string> contents;
2764  getContents(contents);
2765 
2766  std::cout << " ------------------------------------------------------------\n"
2767  << " Directory structure: \n"
2768  << " ------------------------------------------------------------\n";
2769 
2770  std::copy(contents.begin(), contents.end(),
2771  std::ostream_iterator<std::string>(std::cout, "\n"));
2772 
2773  std::cout << " ------------------------------------------------------------\n";
2774 }
2775 
2779 // check if the monitor element is in auto-collation folder
2780 bool
2782 { return me && isSubdirectory(s_collateDirName, *me->data_.dirname); }
static void collateProfile2D(MonitorElement *me, TProfile2D *h)
Definition: DQMStore.cc:1340
QCriterion * getQCriterion(const std::string &qtname) const
Definition: DQMStore.cc:2597
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:444
TH2S * getTH2S(void) const
TH1S * getTH1S(void) const
Master< F > master(const F &f)
Definition: FunctClone.h:68
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:867
bool containsAnyMonitorable(const std::string &path) const
Definition: DQMStore.cc:1458
bool isCollateME(MonitorElement *me) const
Definition: DQMStore.cc:2781
void resetUpdate(void)
reset &quot;was updated&quot; flag
long int flag
Definition: mlp_lapack.h:47
bool cdInto(const std::string &path) const
Definition: DQMStore.cc:2066
int getStatus(const std::string &path="") const
Definition: DQMStore.cc:2703
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:1419
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:717
void rmdir(const std::string &fullpath)
Definition: DQMStore.cc:2530
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:2472
static void collate3D(MonitorElement *me, TH3F *h)
Definition: DQMStore.cc:1323
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:979
static void collate1D(MonitorElement *me, TH1F *h)
Definition: DQMStore.cc:1281
void cd(void)
go to top directory (ie. root)
Definition: DQMStore.cc:406
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:889
static void collate1DD(MonitorElement *me, TH1D *h)
Definition: DQMStore.cc:1295
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:2113
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:1691
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:452
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:749
void initializeFrom(const edm::ParameterSet &)
Definition: DQMStore.cc:295
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:460
MonitorElement * book(const std::string &dir, const std::string &name, const char *context)
Definition: DQMStore.cc:572
MonitorElement * bookFloat(const char *name)
Book float.
Definition: DQMStore.cc:654
dictionary map
Definition: Association.py:205
SaveReferenceTag
Definition: DQMStore.h:70
std::vector< MonitorElement * > getAllContents(const std::string &path) const
Definition: DQMStore.cc:1672
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:1354
~DQMStore(void)
Definition: DQMStore.cc:284
void disableSoftReset(MonitorElement *me)
Definition: DQMStore.cc:2742
static void collateProfile(MonitorElement *me, TProfile *h)
Definition: DQMStore.cc:1330
static const lat::Regexp s_rxmeval("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$")
void forceReset(void)
Definition: DQMStore.cc:1751
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:451
bool extract(TObject *obj, const std::string &dir, bool overwrite)
Definition: DQMStore.cc:1771
list path
Definition: scaleCards.py:51
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:2564
QTestSpecs qtestspecs_
Definition: DQMStore.h:462
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:683
static std::string s_safe
Definition: DQMStore.cc:50
static void collate1S(MonitorElement *me, TH1S *h)
Definition: DQMStore.cc:1288
void setAccumulate(bool)
tuple result
Definition: query.py:137
void removeElement(const std::string &name)
Definition: DQMStore.cc:2572
void addProfiles(TProfile *h1, TProfile *h2, TProfile *sum, float c1, float c2)
static bool checkBinningMatches(MonitorElement *me, TH1 *h)
Definition: DQMStore.cc:1257
MonitorElement * findObject(const std::string &dir, const std::string &name) const
Definition: DQMStore.cc:1598
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:1031
QCriterion * makeQCriterion(const std::string &qtname)
Definition: DQMStore.cc:112
#define end
Definition: vmac.h:38
void setVerbose(unsigned level)
Definition: DQMStore.cc:393
void softReset(MonitorElement *me)
Definition: DQMStore.cc:2734
std::string pwd_
Definition: DQMStore.h:456
void runQTests(void)
Definition: DQMStore.cc:2682
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:1468
QAMap qalgos_
Definition: DQMStore.h:461
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:1497
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:493
void getAllTags(std::vector< std::string > &into) const
Definition: DQMStore.cc:1619
bool load(const std::string &filename, OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2447
~fastmatch()
Definition: DQMStore.cc:192
void tagAllContents(const std::string &path, unsigned int myTag)
Definition: DQMStore.cc:1397
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:450
static void collate2S(MonitorElement *me, TH2S *h)
Definition: DQMStore.cc:1309
MEMap data_
Definition: DQMStore.h:457
part
Definition: HCALResponse.h:21
static void collate2D(MonitorElement *me, TH2F *h)
Definition: DQMStore.cc:1302
void print_trace(const std::string &dir, const std::string &name)
Definition: DQMStore.cc:342
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:2647
TH1F * getTH1F(void) const
std::vector< std::string > getMEs(void) const
get list of (non-dir) MEs of current directory
Definition: DQMStore.cc:1442
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:2277
void setVerbose(int verbose)
probability limits for warnings, errors
Definition: QTest.h:115
static void collate2DD(MonitorElement *me, TH2D *h)
Definition: DQMStore.cc:1316
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:1385
list key
Definition: combine.py:13
TProfile * getTProfile(void) const
void useQTest(const std::string &dir, const std::string &qtname)
Definition: DQMStore.cc:2629
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:440
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:2432
static const int STATUS_OK
void setAccumulate(MonitorElement *me, bool flag)
Definition: DQMStore.cc:2751
tuple cout
Definition: gather_cfg.py:121
void setEfficiencyFlag(void)
QCriterion * createQTest(const std::string &algoname, const std::string &qtname)
Definition: DQMStore.cc:2608
dbl *** dir
Definition: mlp_gen.cc:35
void showDirStructure(void) const
Definition: DQMStore.cc:2761
void reset(void)
Definition: DQMStore.cc:1727
tuple status
Definition: ntuplemaker.py:245
TH2F * getTH2F(void) const
MonitorElement * bookInt(const char *name)
Book int.
Definition: DQMStore.cc:624
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:845
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:458
bool collateHistograms_
Definition: DQMStore.h:453
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:733
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:452
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:429
static const int ERROR
const std::string & pwd(void) const
Definition: DQMStore.cc:401
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:1175
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:11