CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DQMServices/Core/src/DQMStore.cc

Go to the documentation of this file.
00001 #include "DQMServices/Core/interface/Standalone.h"
00002 #include "DQMServices/Core/interface/DQMStore.h"
00003 #include "DQMServices/Core/interface/QReport.h"
00004 #include "DQMServices/Core/interface/QTest.h"
00005 #include "DQMServices/Core/src/DQMError.h"
00006 #include "classlib/utils/RegexpMatch.h"
00007 #include "classlib/utils/Regexp.h"
00008 #include "classlib/utils/StringOps.h"
00009 #include "TFile.h"
00010 #include "TROOT.h"
00011 #include "TKey.h"
00012 #include "TClass.h"
00013 #include "TSystem.h"
00014 #include <iterator>
00015 #include <cerrno>
00016 
00043 
00044 
00045 static std::string s_monitorDirName = "DQMData";
00046 static std::string s_referenceDirName = "Reference";
00047 static std::string s_collateDirName = "Collate";
00048 static std::string s_safe = "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# ";
00049 
00050 static const lat::Regexp s_rxmeval ("^<(.*)>(i|f|s|t|qr)=(.*)</\\1>$");
00051 static const lat::Regexp s_rxmeqr1 ("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$");
00052 static const lat::Regexp s_rxmeqr2 ("^st\\.(\\d+)\\.(.*)$");
00053 
00057 static bool
00058 isSubdirectory(const std::string &ofdir, const std::string &path)
00059 {
00060   return (ofdir.empty()
00061           || (path.size() >= ofdir.size()
00062               && path.compare(0, ofdir.size(), ofdir) == 0
00063               && (path.size() == ofdir.size()
00064                   || path[ofdir.size()] == '/')));
00065 }
00066 
00067 static void
00068 cleanTrailingSlashes(const std::string &path, std::string &clean, const std::string *&cleaned)
00069 {
00070   clean.clear();
00071   cleaned = &path;
00072 
00073   size_t len = path.size();
00074   for ( ; len > 0 && path[len-1] == '/'; --len)
00075     ;
00076 
00077   if (len != path.size())
00078   {
00079     clean = path.substr(0, len);
00080     cleaned = &clean;
00081   }
00082 }
00083 
00084 static void
00085 splitPath(std::string &dir, std::string &name, const std::string &path)
00086 {
00087   size_t slash = path.rfind('/');
00088   if (slash != std::string::npos)
00089   {
00090     dir.append(path, 0, slash);
00091     name.append(path, slash+1, std::string::npos);
00092   }
00093   else
00094     name = path;
00095 }
00096 
00097 static void
00098 mergePath(std::string &path, const std::string &dir, const std::string &name)
00099 {
00100   path.reserve(dir.size() + name.size() + 2);
00101   path += dir;
00102   if (! path.empty())
00103     path += '/';
00104   path += name;
00105 }
00106 
00107 template <class T>
00108 QCriterion *
00109 makeQCriterion(const std::string &qtname)
00110 { return new T(qtname); }
00111 
00112 template <class T>
00113 void
00114 initQCriterion(std::map<std::string, QCriterion *(*)(const std::string &)> &m)
00115 { m[T::getAlgoName()] = &makeQCriterion<T>; }
00116 
00118 DQMStore::DQMStore(const edm::ParameterSet &pset, edm::ActivityRegistry& ar)
00119   : verbose_ (1),
00120     verboseQT_ (1),
00121     reset_ (false),
00122     collateHistograms_ (false),
00123     readSelectedDirectory_ (""),
00124     pwd_ ("")
00125 {
00126   initializeFrom(pset);
00127   if(pset.getUntrackedParameter<bool>("forceResetOnBeginRun",false)) {
00128     ar.watchPostSourceRun(this,&DQMStore::forceReset);
00129   }
00130 }
00131 
00132 DQMStore::DQMStore(const edm::ParameterSet &pset)
00133   : verbose_ (1),
00134     verboseQT_ (1),
00135     reset_ (false),
00136     collateHistograms_ (false),
00137     readSelectedDirectory_ (""),
00138     pwd_ ("")
00139 {
00140   initializeFrom(pset);
00141 }
00142 
00143 DQMStore::~DQMStore(void)
00144 {
00145   for (QCMap::iterator i = qtests_.begin(), e = qtests_.end(); i != e; ++i)
00146     delete i->second;
00147 
00148   for (QTestSpecs::iterator i = qtestspecs_.begin(), e = qtestspecs_.end(); i != e; ++i)
00149     delete i->first;
00150 
00151 }
00152 
00153 void
00154 DQMStore::initializeFrom(const edm::ParameterSet& pset) {
00155   makeDirectory("");
00156   reset();
00157 
00158   // set steerable parameters
00159   verbose_ = pset.getUntrackedParameter<int>("verbose", 0);
00160   if (verbose_ > 0)
00161     std::cout << "DQMStore: verbosity set to " << verbose_ << std::endl;
00162   
00163   verboseQT_ = pset.getUntrackedParameter<int>("verboseQT", 0);
00164   if (verbose_ > 0)
00165     std::cout << "DQMStore: QTest verbosity set to " << verboseQT_ << std::endl;
00166   
00167   collateHistograms_ = pset.getUntrackedParameter<bool>("collateHistograms", false);
00168   if (collateHistograms_)
00169     std::cout << "DQMStore: histogram collation is enabled\n";
00170 
00171   std::string ref = pset.getUntrackedParameter<std::string>("referenceFileName", "");
00172   if (! ref.empty())
00173   {
00174     std::cout << "DQMStore: using reference file '" << ref << "'\n";
00175     readFile(ref, true, "", s_referenceDirName, StripRunDirs, false);
00176   }  
00177 
00178   initQCriterion<Comp2RefChi2>(qalgos_);
00179   initQCriterion<Comp2RefKolmogorov>(qalgos_);
00180   initQCriterion<ContentsXRange>(qalgos_);
00181   initQCriterion<ContentsYRange>(qalgos_);
00182   initQCriterion<MeanWithinExpected>(qalgos_);
00183   initQCriterion<Comp2RefEqualH>(qalgos_);
00184   initQCriterion<DeadChannel>(qalgos_);
00185   initQCriterion<NoisyChannel>(qalgos_);
00186   initQCriterion<ContentsWithinExpected>(qalgos_);
00187   initQCriterion<CompareToMedian>(qalgos_);
00188   
00189 }
00190 
00195 void
00196 DQMStore::setVerbose(unsigned level) 
00197 { return; }
00198 
00203 const std::string &
00204 DQMStore::pwd(void) const
00205 { return pwd_; }
00206 
00208 void
00209 DQMStore::cd(void)
00210 { setCurrentFolder(""); }
00211 
00213 void
00214 DQMStore::cd(const std::string &subdir)
00215 {
00216   std::string clean;
00217   const std::string *cleaned = 0;
00218   cleanTrailingSlashes(subdir, clean, cleaned);
00219 
00220   if (! dirExists(*cleaned))
00221     raiseDQMError("DQMStore", "Cannot 'cd' into non-existent directory '%s'",
00222                   cleaned->c_str());
00223   
00224   setCurrentFolder(*cleaned);
00225 }
00226 
00231 void
00232 DQMStore::setCurrentFolder(const std::string &fullpath)
00233 {
00234   std::string clean;
00235   const std::string *cleaned = 0;
00236   cleanTrailingSlashes(fullpath, clean, cleaned);
00237   makeDirectory(*cleaned);
00238   pwd_ = *cleaned;
00239 }
00240 
00242 void
00243 DQMStore::goUp(void)
00244 {
00245   size_t pos = pwd_.rfind('/');
00246   if (pos == std::string::npos)
00247     setCurrentFolder("");
00248   else
00249     setCurrentFolder(pwd_.substr(0, pos));
00250 }
00251 
00252 // -------------------------------------------------------------------
00254 void
00255 DQMStore::makeDirectory(const std::string &path)
00256 {
00257   std::string prev;
00258   std::string subdir;
00259   std::string name;
00260   prev.reserve(path.size());
00261   subdir.reserve(path.size());
00262   name.reserve(path.size());
00263   size_t prevname = 0;
00264   size_t slash = 0;
00265 
00266   while (true)
00267   {
00268     // Create this subdirectory component.
00269     subdir.clear();
00270     subdir.append(path, 0, slash);
00271     name.clear();
00272     name.append(subdir, prevname, std::string::npos);
00273     if (! prev.empty() && findObject(prev, name))
00274       raiseDQMError("DQMStore", "Attempt to create subdirectory '%s'"
00275                     " which already exists as a monitor element",
00276                     subdir.c_str());
00277 
00278     if (! dirs_.count(subdir))
00279       dirs_.insert(subdir);
00280 
00281     // Stop if we've reached the end (including possibly a trailing slash).
00282     if (slash+1 >= path.size())
00283       break;
00284 
00285     // Find the next slash, making sure we progress.  If reach the end,
00286     // process the last path component; the next loop round will terminate.
00287     prevname = slash ? slash+1 : slash;
00288     prev = subdir;
00289     if ((slash = path.find('/', ++slash)) == std::string::npos)
00290       slash = path.size();
00291   }
00292 }
00293 
00295 bool
00296 DQMStore::dirExists(const std::string &path) const
00297 { return dirs_.count(path) > 0; }
00298 
00302 template <class HISTO, class COLLATE>
00303 MonitorElement *
00304 DQMStore::book(const std::string &dir, const std::string &name,
00305                const char *context, int kind,
00306                HISTO *h, COLLATE collate)
00307 {
00308   assert(name.find('/') == std::string::npos);
00309   std::string path;
00310   mergePath(path, dir, name);
00311 
00312   // Put us in charge of h.
00313   h->SetDirectory(0);
00314 
00315   // Check if the request monitor element already exists.
00316   MonitorElement *me = findObject(dir, name);
00317   if (me)
00318   {
00319     if (collateHistograms_)
00320     {
00321       collate(me, h);
00322       delete h;
00323       return me;
00324     }
00325     else
00326     {    
00327       if (verbose_ > 1)
00328         std::cout << "DQMStore: "
00329                   << context << ": monitor element '"
00330                   << path << "' already exists, collating" << std::endl;
00331       me->Reset();
00332       collate(me, h);
00333       delete h;
00334       return me;
00335     }
00336   }
00337   else
00338   {
00339     // Create and initialise core object.
00340     assert(dirs_.count(dir));
00341     MonitorElement proto(&*dirs_.find(dir), name);
00342     me = const_cast<MonitorElement &>(*data_.insert(proto).first)
00343       .initialise((MonitorElement::Kind)kind, h);
00344 
00345     // Initialise quality test information.
00346     QTestSpecs::iterator qi = qtestspecs_.begin();
00347     QTestSpecs::iterator qe = qtestspecs_.end();
00348     for ( ; qi != qe; ++qi)
00349       if (qi->first->match(path))
00350         me->addQReport(qi->second);
00351 
00352     // Assign reference if we have one.
00353     std::string refdir;
00354     refdir.reserve(s_referenceDirName.size() + dir.size() + 2);
00355     refdir += s_referenceDirName;
00356     refdir += '/';
00357     refdir += dir;
00358 
00359     if (MonitorElement *refme = findObject(refdir, name))
00360     {
00361       me->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
00362       me->reference_ = refme->object_;
00363     }
00364 
00365     // Return the monitor element.
00366     return me;
00367   }
00368 }
00369 
00370 MonitorElement *
00371 DQMStore::book(const std::string &dir,
00372                const std::string &name,
00373                const char *context)
00374 {
00375   assert(name.find('/') == std::string::npos);
00376 
00377   // Check if the request monitor element already exists.
00378   if (MonitorElement *me = findObject(dir, name))
00379   {
00380     if (verbose_ > 1)
00381     {
00382       std::string path;
00383       mergePath(path, dir, name);
00384 
00385       std::cout << "DQMStore: "
00386                 << context << ": monitor element '"
00387                 << path << "' already exists, resetting" << std::endl;
00388     }
00389     me->Reset();
00390     return me;
00391   }
00392   else
00393   {
00394     // Create it and return for initialisation.
00395     assert(dirs_.count(dir));
00396     MonitorElement me(&*dirs_.find(dir), name);
00397     return &const_cast<MonitorElement &>(*data_.insert(me).first);
00398   }
00399 }
00400 
00401 // -------------------------------------------------------------------
00403 MonitorElement *
00404 DQMStore::bookInt(const std::string &dir, const std::string &name)
00405 {
00406   if (collateHistograms_)
00407   {
00408     if (MonitorElement *me = findObject(dir, name))
00409     {
00410       me->Fill(0);
00411       return me;
00412     }
00413   }
00414 
00415   return book(dir, name, "bookInt")
00416     ->initialise(MonitorElement::DQM_KIND_INT);
00417 }
00418 
00420 MonitorElement *
00421 DQMStore::bookInt(const char *name)
00422 { return bookInt(pwd_, name); }
00423 
00425 MonitorElement *
00426 DQMStore::bookInt(const std::string &name)
00427 {
00428   return bookInt(pwd_, name);
00429 }
00430 
00431 // -------------------------------------------------------------------
00433 MonitorElement *
00434 DQMStore::bookFloat(const std::string &dir, const std::string &name)
00435 {
00436   if (collateHistograms_)
00437   {
00438     if (MonitorElement *me = findObject(dir, name))
00439     {
00440       me->Fill(0.);
00441       return me;
00442     }
00443   }
00444 
00445   return book(dir, name, "bookFloat")
00446     ->initialise(MonitorElement::DQM_KIND_REAL);
00447 }
00448 
00450 MonitorElement *
00451 DQMStore::bookFloat(const char *name)
00452 { return bookFloat(pwd_, name); }
00453 
00455 MonitorElement *
00456 DQMStore::bookFloat(const std::string &name)
00457 {
00458   return bookFloat(pwd_, name);
00459 }
00460 
00461 // -------------------------------------------------------------------
00463 MonitorElement *
00464 DQMStore::bookString(const std::string &dir,
00465                      const std::string &name,
00466                      const std::string &value)
00467 {
00468   if (collateHistograms_)
00469   {
00470     if (MonitorElement *me = findObject(dir, name))
00471       return me;
00472   }
00473 
00474   return book(dir, name, "bookString")
00475     ->initialise(MonitorElement::DQM_KIND_STRING, value);
00476 }
00477 
00479 MonitorElement *
00480 DQMStore::bookString(const char *name, const char *value)
00481 { return bookString(pwd_, name, value); }
00482 
00484 MonitorElement *
00485 DQMStore::bookString(const std::string &name, const std::string &value)
00486 {
00487   return bookString(pwd_, name, value);
00488 }
00489 
00490 // -------------------------------------------------------------------
00492 MonitorElement *
00493 DQMStore::book1D(const std::string &dir, const std::string &name, TH1F *h)
00494 {
00495   return book(dir, name, "book1D", MonitorElement::DQM_KIND_TH1F, h, collate1D);
00496 }
00497 
00499 MonitorElement *
00500 DQMStore::book1S(const std::string &dir, const std::string &name, TH1S *h)
00501 {
00502   return book(dir, name, "book1S", MonitorElement::DQM_KIND_TH1S, h, collate1S);
00503 }
00504 
00506 MonitorElement *
00507 DQMStore::book1DD(const std::string &dir, const std::string &name, TH1D *h)
00508 {
00509   return book(dir, name, "book1DD", MonitorElement::DQM_KIND_TH1D, h, collate1DD);
00510 }
00511 
00513 MonitorElement *
00514 DQMStore::book1D(const char *name, const char *title,
00515                  int nchX, double lowX, double highX)
00516 {
00517   return book1D(pwd_, name, new TH1F(name, title, nchX, lowX, highX));
00518 }
00519 
00521 MonitorElement *
00522 DQMStore::book1D(const std::string &name, const std::string &title,
00523                  int nchX, double lowX, double highX)
00524 {
00525   return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, lowX, highX));
00526 }
00527 
00529 MonitorElement *
00530 DQMStore::book1S(const char *name, const char *title,
00531                  int nchX, double lowX, double highX)
00532 {
00533   return book1S(pwd_, name, new TH1S(name, title, nchX, lowX, highX));
00534 }
00535 
00537 MonitorElement *
00538 DQMStore::book1S(const std::string &name, const std::string &title,
00539                  int nchX, double lowX, double highX)
00540 {
00541   return book1S(pwd_, name, new TH1S(name.c_str(), title.c_str(), nchX, lowX, highX));
00542 }
00543 
00545 MonitorElement *
00546 DQMStore::book1DD(const char *name, const char *title,
00547                   int nchX, double lowX, double highX)
00548 {
00549   return book1DD(pwd_, name, new TH1D(name, title, nchX, lowX, highX));
00550 }
00551 
00553 MonitorElement *
00554 DQMStore::book1DD(const std::string &name, const std::string &title,
00555                   int nchX, double lowX, double highX)
00556 {
00557   return book1DD(pwd_, name, new TH1D(name.c_str(), title.c_str(), nchX, lowX, highX));
00558 }
00559 
00561 MonitorElement *
00562 DQMStore::book1D(const char *name, const char *title,
00563                  int nchX, float *xbinsize)
00564 {
00565   return book1D(pwd_, name, new TH1F(name, title, nchX, xbinsize));
00566 }
00567 
00569 MonitorElement *
00570 DQMStore::book1D(const std::string &name, const std::string &title,
00571                  int nchX, float *xbinsize)
00572 {
00573   return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, xbinsize));
00574 }
00575 
00577 MonitorElement *
00578 DQMStore::book1D(const char *name, TH1F *source)
00579 {
00580   return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name)));
00581 }
00582 
00584 MonitorElement *
00585 DQMStore::book1D(const std::string &name, TH1F *source)
00586 {
00587   return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name.c_str())));
00588 }
00589 
00591 MonitorElement *
00592 DQMStore::book1S(const char *name, TH1S *source)
00593 {
00594   return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name)));
00595 }
00596 
00598 MonitorElement *
00599 DQMStore::book1S(const std::string &name, TH1S *source)
00600 {
00601   return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name.c_str())));
00602 }
00603 
00605 MonitorElement *
00606 DQMStore::book1DD(const char *name, TH1D *source)
00607 {
00608   return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name)));
00609 }
00610 
00612 MonitorElement *
00613 DQMStore::book1DD(const std::string &name, TH1D *source)
00614 {
00615   return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name.c_str())));
00616 }
00617 
00618 // -------------------------------------------------------------------
00620 MonitorElement *
00621 DQMStore::book2D(const std::string &dir, const std::string &name, TH2F *h)
00622 {
00623   return book(dir, name, "book2D", MonitorElement::DQM_KIND_TH2F, h, collate2D);
00624 }
00625 
00627 MonitorElement *
00628 DQMStore::book2S(const std::string &dir, const std::string &name, TH2S *h)
00629 {
00630   return book(dir, name, "book2S", MonitorElement::DQM_KIND_TH2S, h, collate2S);
00631 }
00632 
00634 MonitorElement *
00635 DQMStore::book2DD(const std::string &dir, const std::string &name, TH2D *h)
00636 {
00637   return book(dir, name, "book2DD", MonitorElement::DQM_KIND_TH2D, h, collate2DD);
00638 }
00639 
00641 MonitorElement *
00642 DQMStore::book2D(const char *name, const char *title,
00643                  int nchX, double lowX, double highX,
00644                  int nchY, double lowY, double highY)
00645 {
00646   return book2D(pwd_, name, new TH2F(name, title,
00647                                      nchX, lowX, highX,
00648                                      nchY, lowY, highY));
00649 }
00650 
00652 MonitorElement *
00653 DQMStore::book2D(const std::string &name, const std::string &title,
00654                  int nchX, double lowX, double highX,
00655                  int nchY, double lowY, double highY)
00656 {
00657   return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
00658                                      nchX, lowX, highX,
00659                                      nchY, lowY, highY));
00660 }
00661 
00663 MonitorElement *
00664 DQMStore::book2S(const char *name, const char *title,
00665                  int nchX, double lowX, double highX,
00666                  int nchY, double lowY, double highY)
00667 {
00668   return book2S(pwd_, name, new TH2S(name, title,
00669                                      nchX, lowX, highX,
00670                                      nchY, lowY, highY));
00671 }
00672 
00674 MonitorElement *
00675 DQMStore::book2S(const std::string &name, const std::string &title,
00676                  int nchX, double lowX, double highX,
00677                  int nchY, double lowY, double highY)
00678 {
00679   return book2S(pwd_, name, new TH2S(name.c_str(), title.c_str(),
00680                                      nchX, lowX, highX,
00681                                      nchY, lowY, highY));
00682 }
00683 
00685 MonitorElement *
00686 DQMStore::book2DD(const char *name, const char *title,
00687                   int nchX, double lowX, double highX,
00688                   int nchY, double lowY, double highY)
00689 {
00690   return book2DD(pwd_, name, new TH2D(name, title,
00691                                       nchX, lowX, highX,
00692                                       nchY, lowY, highY));
00693 }
00694 
00696 MonitorElement *
00697 DQMStore::book2DD(const std::string &name, const std::string &title,
00698                   int nchX, double lowX, double highX,
00699                   int nchY, double lowY, double highY)
00700 {
00701   return book2DD(pwd_, name, new TH2D(name.c_str(), title.c_str(),
00702                                       nchX, lowX, highX,
00703                                       nchY, lowY, highY));
00704 }
00705 
00707 MonitorElement *
00708 DQMStore::book2D(const char *name, const char *title,
00709                  int nchX, float *xbinsize, int nchY, float *ybinsize)
00710 {
00711   return book2D(pwd_, name, new TH2F(name, title, 
00712                                      nchX, xbinsize, nchY, ybinsize));
00713 }
00714 
00716 MonitorElement *
00717 DQMStore::book2D(const std::string &name, const std::string &title,
00718                  int nchX, float *xbinsize, int nchY, float *ybinsize)
00719 {
00720   return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(), 
00721                                      nchX, xbinsize, nchY, ybinsize));
00722 }
00723 
00725 MonitorElement *
00726 DQMStore::book2D(const char *name, TH2F *source)
00727 {
00728   return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name)));
00729 }
00730 
00732 MonitorElement *
00733 DQMStore::book2D(const std::string &name, TH2F *source)
00734 {
00735   return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name.c_str())));
00736 }
00737 
00739 MonitorElement *
00740 DQMStore::book2S(const char *name, TH2S *source)
00741 {
00742   return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name)));
00743 }
00744 
00746 MonitorElement *
00747 DQMStore::book2S(const std::string &name, TH2S *source)
00748 {
00749   return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name.c_str())));
00750 }
00751 
00753 MonitorElement *
00754 DQMStore::book2DD(const char *name, TH2D *source)
00755 {
00756   return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name)));
00757 }
00758 
00760 MonitorElement *
00761 DQMStore::book2DD(const std::string &name, TH2D *source)
00762 {
00763   return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name.c_str())));
00764 }
00765 
00766 // -------------------------------------------------------------------
00768 MonitorElement *
00769 DQMStore::book3D(const std::string &dir, const std::string &name, TH3F *h)
00770 {
00771   return book(dir, name, "book3D", MonitorElement::DQM_KIND_TH3F, h, collate3D);
00772 }
00773 
00775 MonitorElement *
00776 DQMStore::book3D(const char *name, const char *title,
00777                  int nchX, double lowX, double highX,
00778                  int nchY, double lowY, double highY,
00779                  int nchZ, double lowZ, double highZ)
00780 {
00781   return book3D(pwd_, name, new TH3F(name, title,
00782                                      nchX, lowX, highX,
00783                                      nchY, lowY, highY,
00784                                      nchZ, lowZ, highZ));
00785 }
00786 
00788 MonitorElement *
00789 DQMStore::book3D(const std::string &name, const std::string &title,
00790                  int nchX, double lowX, double highX,
00791                  int nchY, double lowY, double highY,
00792                  int nchZ, double lowZ, double highZ)
00793 {
00794   return book3D(pwd_, name, new TH3F(name.c_str(), title.c_str(),
00795                                      nchX, lowX, highX,
00796                                      nchY, lowY, highY,
00797                                      nchZ, lowZ, highZ));
00798 }
00799 
00801 MonitorElement *
00802 DQMStore::book3D(const char *name, TH3F *source)
00803 {
00804   return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name)));
00805 }
00806 
00808 MonitorElement *
00809 DQMStore::book3D(const std::string &name, TH3F *source)
00810 {
00811   return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name.c_str())));
00812 }
00813 
00814 // -------------------------------------------------------------------
00816 MonitorElement *
00817 DQMStore::bookProfile(const std::string &dir, const std::string &name, TProfile *h)
00818 {
00819   return book(dir, name, "bookProfile",
00820               MonitorElement::DQM_KIND_TPROFILE,
00821               h, collateProfile);
00822 }
00823 
00827 MonitorElement *
00828 DQMStore::bookProfile(const char *name, const char *title,
00829                       int nchX, double lowX, double highX,
00830                       int nchY, double lowY, double highY,
00831                       const char *option /* = "s" */)
00832 {
00833   return bookProfile(pwd_, name, new TProfile(name, title,
00834                                               nchX, lowX, highX,
00835                                               lowY, highY,
00836                                               option));
00837 }
00838 
00842 MonitorElement *
00843 DQMStore::bookProfile(const std::string &name, const std::string &title,
00844                       int nchX, double lowX, double highX,
00845                       int nchY, double lowY, double highY,
00846                       const char *option /* = "s" */)
00847 {
00848   return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
00849                                               nchX, lowX, highX,
00850                                               lowY, highY,
00851                                               option));
00852 }
00853 
00857 MonitorElement *
00858 DQMStore::bookProfile(const char *name, const char *title,
00859                       int nchX, double lowX, double highX,
00860                       double lowY, double highY,
00861                       const char *option /* = "s" */)
00862 {
00863   return bookProfile(pwd_, name, new TProfile(name, title,
00864                                               nchX, lowX, highX,
00865                                               lowY, highY,
00866                                               option));
00867 }
00868 
00872 MonitorElement *
00873 DQMStore::bookProfile(const std::string &name, const std::string &title,
00874                       int nchX, double lowX, double highX,
00875                       double lowY, double highY,
00876                       const char *option /* = "s" */)
00877 {
00878   return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
00879                                               nchX, lowX, highX,
00880                                               lowY, highY,
00881                                               option));
00882 }
00883 
00887 MonitorElement *
00888 DQMStore::bookProfile(const char *name, const char *title,
00889                       int nchX, double *xbinsize,
00890                       int nchY, double lowY, double highY,
00891                       const char *option /* = "s" */)
00892 {
00893   return bookProfile(pwd_, name, new TProfile(name, title,
00894                                               nchX, xbinsize,
00895                                               lowY, highY,
00896                                               option));
00897 }
00898 
00902 MonitorElement *
00903 DQMStore::bookProfile(const std::string &name, const std::string &title,
00904                       int nchX, double *xbinsize,
00905                       int nchY, double lowY, double highY,
00906                       const char *option /* = "s" */)
00907 {
00908   return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
00909                                               nchX, xbinsize,
00910                                               lowY, highY,
00911                                               option));
00912 }
00913 
00917 MonitorElement *
00918 DQMStore::bookProfile(const char *name, const char *title,
00919                       int nchX, double *xbinsize,
00920                       double lowY, double highY,
00921                       const char *option /* = "s" */)
00922 {
00923   return bookProfile(pwd_, name, new TProfile(name, title,
00924                                               nchX, xbinsize,
00925                                               lowY, highY,
00926                                               option));
00927 }
00928 
00932 MonitorElement *
00933 DQMStore::bookProfile(const std::string &name, const std::string &title,
00934                       int nchX, double *xbinsize,
00935                       double lowY, double highY,
00936                       const char *option /* = "s" */)
00937 {
00938   return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
00939                                               nchX, xbinsize,
00940                                               lowY, highY,
00941                                               option));
00942 }
00943 
00945 MonitorElement *
00946 DQMStore::bookProfile(const char *name, TProfile *source)
00947 {
00948   return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name)));
00949 }
00950 
00952 MonitorElement *
00953 DQMStore::bookProfile(const std::string &name, TProfile *source)
00954 {
00955   return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name.c_str())));
00956 }
00957 
00958 // -------------------------------------------------------------------
00960 MonitorElement *
00961 DQMStore::bookProfile2D(const std::string &dir, const std::string &name, TProfile2D *h)
00962 {
00963   return book(dir, name, "bookProfile2D",
00964               MonitorElement::DQM_KIND_TPROFILE2D,
00965               h, collateProfile2D);
00966 }
00967 
00971 MonitorElement *
00972 DQMStore::bookProfile2D(const char *name, const char *title,
00973                         int nchX, double lowX, double highX,
00974                         int nchY, double lowY, double highY,
00975                         int nchZ, double lowZ, double highZ,
00976                         const char *option /* = "s" */)
00977 {
00978   return bookProfile2D(pwd_, name, new TProfile2D(name, title,
00979                                                   nchX, lowX, highX,
00980                                                   nchY, lowY, highY,
00981                                                   lowZ, highZ,
00982                                                   option));
00983 }
00984 
00988 MonitorElement *
00989 DQMStore::bookProfile2D(const std::string &name, const std::string &title,
00990                         int nchX, double lowX, double highX,
00991                         int nchY, double lowY, double highY,
00992                         int nchZ, double lowZ, double highZ,
00993                         const char *option /* = "s" */)
00994 {
00995   return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
00996                                                   nchX, lowX, highX,
00997                                                   nchY, lowY, highY,
00998                                                   lowZ, highZ,
00999                                                   option));
01000 }
01001 
01005 MonitorElement *
01006 DQMStore::bookProfile2D(const char *name, const char *title,
01007                         int nchX, double lowX, double highX,
01008                         int nchY, double lowY, double highY,
01009                         double lowZ, double highZ,
01010                         const char *option /* = "s" */)
01011 {
01012   return bookProfile2D(pwd_, name, new TProfile2D(name, title,
01013                                                   nchX, lowX, highX,
01014                                                   nchY, lowY, highY,
01015                                                   lowZ, highZ,
01016                                                   option));
01017 }
01018 
01022 MonitorElement *
01023 DQMStore::bookProfile2D(const std::string &name, const std::string &title,
01024                         int nchX, double lowX, double highX,
01025                         int nchY, double lowY, double highY,
01026                         double lowZ, double highZ,
01027                         const char *option /* = "s" */)
01028 {
01029   return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
01030                                                   nchX, lowX, highX,
01031                                                   nchY, lowY, highY,
01032                                                   lowZ, highZ,
01033                                                   option));
01034 }
01035 
01037 MonitorElement *
01038 DQMStore::bookProfile2D(const char *name, TProfile2D *source)
01039 {
01040   return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name)));
01041 }
01042 
01044 MonitorElement *
01045 DQMStore::bookProfile2D(const std::string &name, TProfile2D *source)
01046 {
01047   return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name.c_str())));
01048 }
01049 
01053 bool
01054 DQMStore::checkBinningMatches(MonitorElement *me, TH1 *h)
01055 {
01056   if (me->getTH1()->GetNbinsX() != h->GetNbinsX()
01057       || me->getTH1()->GetNbinsY() != h->GetNbinsY()
01058       || me->getTH1()->GetNbinsZ() != h->GetNbinsZ()
01059       || me->getTH1()->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin()
01060       || me->getTH1()->GetYaxis()->GetXmin() != h->GetYaxis()->GetXmin()
01061       || me->getTH1()->GetZaxis()->GetXmin() != h->GetZaxis()->GetXmin()
01062       || me->getTH1()->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax()
01063       || me->getTH1()->GetYaxis()->GetXmax() != h->GetYaxis()->GetXmax()
01064       || me->getTH1()->GetZaxis()->GetXmax() != h->GetZaxis()->GetXmax())
01065   {
01066     //  edm::LogWarning ("DQMStore")
01067     std::cout << "*** DQMStore: WARNING:"
01068               << "checkBinningMatches: different binning - cannot add object '"
01069               << h->GetName() << "' of type "
01070               << h->IsA()->GetName() << " to existing ME: '"
01071               << me->getFullname() << "'\n";
01072     return false;
01073   }
01074   return true;     
01075 }
01076 
01077 void
01078 DQMStore::collate1D(MonitorElement *me, TH1F *h)
01079 { 
01080   if (checkBinningMatches(me,h)) 
01081     me->getTH1F()->Add(h); 
01082 }
01083 
01084 void
01085 DQMStore::collate1S(MonitorElement *me, TH1S *h)
01086 {  
01087   if (checkBinningMatches(me,h)) 
01088     me->getTH1S()->Add(h); 
01089 }
01090 
01091 void
01092 DQMStore::collate1DD(MonitorElement *me, TH1D *h)
01093 {  
01094   if (checkBinningMatches(me,h)) 
01095     me->getTH1D()->Add(h); 
01096 }
01097 
01098 void
01099 DQMStore::collate2D(MonitorElement *me, TH2F *h)
01100 {  
01101   if (checkBinningMatches(me,h)) 
01102     me->getTH2F()->Add(h); 
01103 }
01104 
01105 void
01106 DQMStore::collate2S(MonitorElement *me, TH2S *h)
01107 {  
01108   if (checkBinningMatches(me,h)) 
01109     me->getTH2S()->Add(h); 
01110 }
01111 
01112 void
01113 DQMStore::collate2DD(MonitorElement *me, TH2D *h)
01114 {  
01115   if (checkBinningMatches(me,h)) 
01116     me->getTH2D()->Add(h); 
01117 }
01118 
01119 void
01120 DQMStore::collate3D(MonitorElement *me, TH3F *h)
01121 {  
01122   if (checkBinningMatches(me,h)) 
01123     me->getTH3F()->Add(h); 
01124 }
01125 
01126 void
01127 DQMStore::collateProfile(MonitorElement *me, TProfile *h)
01128 {
01129   if (checkBinningMatches(me,h)) 
01130   {
01131     TProfile *meh = me->getTProfile();
01132     me->addProfiles(h, meh, meh, 1, 1);
01133   }
01134 }
01135 
01136 void
01137 DQMStore::collateProfile2D(MonitorElement *me, TProfile2D *h)
01138 {
01139   if (checkBinningMatches(me,h)) 
01140   {
01141     TProfile2D *meh = me->getTProfile2D();
01142     me->addProfiles(h, meh, meh, 1, 1);
01143   }
01144 }
01145 
01150 void
01151 DQMStore::tag(MonitorElement *me, unsigned int myTag)
01152 {
01153   if (! myTag)
01154     raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
01155                   " with a zero tag", me->getFullname().c_str());
01156   if ((me->data_.flags & DQMNet::DQM_PROP_TAGGED) && myTag != me->data_.tag)
01157     raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
01158                   " twice with multiple tags", me->getFullname().c_str());
01159 
01160   me->data_.tag = myTag;
01161   me->data_.flags |= DQMNet::DQM_PROP_TAGGED;
01162 }
01163 
01165 void
01166 DQMStore::tag(const std::string &path, unsigned int myTag)
01167 {
01168   std::string dir;
01169   std::string name;
01170   splitPath(dir, name, path);
01171 
01172   if (MonitorElement *me = findObject(dir, name))
01173     tag(me, myTag);
01174   else
01175     raiseDQMError("DQMStore", "Attempt to tag non-existent monitor element"
01176                   " '%s' with tag %u", path.c_str(), myTag);
01177 
01178 }
01179 
01181 void
01182 DQMStore::tagContents(const std::string &path, unsigned int myTag)
01183 {
01184   MonitorElement proto(&path, std::string());
01185   MEMap::iterator e = data_.end();
01186   MEMap::iterator i = data_.lower_bound(proto);
01187   for ( ; i != e && path == *i->data_.dirname; ++i)
01188     tag(const_cast<MonitorElement *>(&*i), myTag);
01189 }
01190 
01193 void
01194 DQMStore::tagAllContents(const std::string &path, unsigned int myTag)
01195 {
01196   std::string clean;
01197   const std::string *cleaned = 0;
01198   cleanTrailingSlashes(path, clean, cleaned);
01199   MonitorElement proto(cleaned, std::string());
01200 
01201   // FIXME: WILDCARDS? Old one supported them, but nobody seemed to use them.
01202   MEMap::iterator e = data_.end();
01203   MEMap::iterator i = data_.lower_bound(proto);
01204   while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
01205   {
01206     tag(const_cast<MonitorElement *>(&*i), myTag);
01207     ++i;
01208   }
01209 }
01210 
01215 std::vector<std::string>
01216 DQMStore::getSubdirs(void) const
01217 {
01218   std::vector<std::string> result;
01219   std::set<std::string>::const_iterator e = dirs_.end();
01220   std::set<std::string>::const_iterator i = dirs_.find(pwd_);
01221 
01222   // If we didn't find current directory, the tree is empty, so quit.
01223   if (i == e)
01224     return result;
01225 
01226   // Skip the current directory and then start looking for immediate
01227   // subdirectories in the dirs_ list.  Stop when we are no longer in
01228   // (direct or indirect) subdirectories of pwd_.  Note that we don't
01229   // "know" which order the set will sort A/B, A/B/C and A/D.
01230   while (++i != e && isSubdirectory(pwd_, *i))
01231     if (i->find('/', pwd_.size()+1) == std::string::npos)
01232       result.push_back(*i);
01233 
01234   return result;
01235 }
01236 
01238 std::vector<std::string>
01239 DQMStore::getMEs(void) const
01240 {
01241   MonitorElement proto(&pwd_, std::string());
01242   std::vector<std::string> result;
01243   MEMap::const_iterator e = data_.end();
01244   MEMap::const_iterator i = data_.lower_bound(proto);
01245   for ( ; i != e && isSubdirectory(pwd_, *i->data_.dirname); ++i)
01246     if (pwd_ == *i->data_.dirname)
01247       result.push_back(i->getName());
01248 
01249   return result;
01250 }
01251 
01254 bool
01255 DQMStore::containsAnyMonitorable(const std::string &path) const
01256 {
01257   MonitorElement proto(&path, std::string());
01258   MEMap::const_iterator e = data_.end();
01259   MEMap::const_iterator i = data_.lower_bound(proto);
01260   return (i != e && isSubdirectory(path, *i->data_.dirname));
01261 }
01262 
01264 MonitorElement *
01265 DQMStore::get(const std::string &path) const
01266 {
01267   std::string dir;
01268   std::string name;
01269   splitPath(dir, name, path);
01270   MonitorElement proto(&dir, name);
01271   MEMap::const_iterator mepos = data_.find(proto);
01272   return (mepos == data_.end() ? 0
01273           : const_cast<MonitorElement *>(&*mepos));
01274 }
01275 
01277 std::vector<MonitorElement *>
01278 DQMStore::get(unsigned int tag) const
01279 {
01280   // FIXME: Use reverse map [tag -> path] / [tag -> dir]?
01281   std::vector<MonitorElement *> result;
01282   for (MEMap::const_iterator i = data_.begin(), e = data_.end(); i != e; ++i)
01283   {
01284     const MonitorElement &me = *i;
01285     if ((me.data_.flags & DQMNet::DQM_PROP_TAGGED) && me.data_.tag == tag)
01286       result.push_back(const_cast<MonitorElement *>(&me));
01287   }
01288   return result;
01289 }
01290 
01293 std::vector<MonitorElement *>
01294 DQMStore::getContents(const std::string &path) const
01295 {
01296   std::string clean;
01297   const std::string *cleaned = 0;
01298   cleanTrailingSlashes(path, clean, cleaned);
01299   MonitorElement proto(cleaned, std::string());
01300 
01301   std::vector<MonitorElement *> result;
01302   MEMap::const_iterator e = data_.end();
01303   MEMap::const_iterator i = data_.lower_bound(proto);
01304   for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
01305     if (*cleaned == *i->data_.dirname)
01306       result.push_back(const_cast<MonitorElement *>(&*i));
01307 
01308   return result;
01309 }
01310 
01312 std::vector<MonitorElement *>
01313 DQMStore::getContents(const std::string &path, unsigned int tag) const
01314 {
01315   std::string clean;
01316   const std::string *cleaned = 0;
01317   cleanTrailingSlashes(path, clean, cleaned);
01318   MonitorElement proto(cleaned, std::string());
01319 
01320   std::vector<MonitorElement *> result;
01321   MEMap::const_iterator e = data_.end();
01322   MEMap::const_iterator i = data_.lower_bound(proto);
01323   for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
01324     if (*cleaned == *i->data_.dirname
01325         && (i->data_.flags & DQMNet::DQM_PROP_TAGGED)
01326         && i->data_.tag == tag)
01327       result.push_back(const_cast<MonitorElement *>(&*i));
01328 
01329   return result;
01330 }
01331 
01336 void
01337 DQMStore::getContents(std::vector<std::string> &into, bool showContents /* = true */) const
01338 {
01339   into.clear();
01340   into.reserve(dirs_.size());
01341 
01342   MEMap::const_iterator me = data_.end();
01343   std::set<std::string>::const_iterator di = dirs_.begin();
01344   std::set<std::string>::const_iterator de = dirs_.end();
01345   for ( ; di != de; ++di)
01346   {
01347     MonitorElement proto(&*di, std::string());
01348     MEMap::const_iterator mi = data_.lower_bound(proto);
01349     MEMap::const_iterator m = mi;
01350     size_t sz = di->size() + 2;
01351     size_t nfound = 0;
01352     for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
01353       if (*di == *m->data_.dirname)
01354       {
01355         sz += m->data_.objname.size() + 1;
01356         ++nfound;
01357       }
01358 
01359     if (! nfound)
01360       continue;
01361 
01362     std::vector<std::string>::iterator istr
01363       = into.insert(into.end(), std::string());
01364 
01365     if (showContents)
01366     {
01367       istr->reserve(sz);
01368 
01369       *istr += *di;
01370       *istr += ':';
01371       for (sz = 0; mi != m; ++mi)
01372       {
01373         if (*di != *mi->data_.dirname)
01374           continue;
01375 
01376         if (sz > 0)
01377           *istr += ',';
01378 
01379         *istr += mi->data_.objname;
01380         ++sz;
01381       }
01382     }
01383     else
01384     {
01385       istr->reserve(di->size() + 2);
01386       *istr += *di;
01387       *istr += ':';
01388     }
01389   }
01390 }
01391 
01394 MonitorElement *
01395 DQMStore::findObject(const std::string &dir, const std::string &name) const
01396 {
01397   if (dir.find_first_not_of(s_safe) != std::string::npos)
01398     raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
01399                   " unacceptable characters", dir.c_str());
01400   if (name.find_first_not_of(s_safe) != std::string::npos)
01401     raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
01402                   " unacceptable characters", name.c_str());
01403 
01404   MonitorElement proto;
01405   proto.data_.dirname = &dir;
01406   proto.data_.objname = name;
01407 
01408   MEMap::const_iterator mepos = data_.find(proto);
01409   return (mepos == data_.end() ? 0
01410           : const_cast<MonitorElement *>(&*mepos));
01411 }
01412 
01415 void
01416 DQMStore::getAllTags(std::vector<std::string> &into) const
01417 {
01418   into.clear();
01419   into.reserve(dirs_.size());
01420 
01421   MEMap::const_iterator me = data_.end();
01422   std::set<std::string>::const_iterator di = dirs_.begin();
01423   std::set<std::string>::const_iterator de = dirs_.end();
01424   char tagbuf[32]; // more than enough for '/' and up to 10 digits
01425 
01426   for ( ; di != de; ++di)
01427   {
01428     MonitorElement proto(&*di, std::string());
01429     MEMap::const_iterator mi = data_.lower_bound(proto);
01430     MEMap::const_iterator m = mi;
01431     size_t sz = di->size() + 2;
01432     size_t nfound = 0;
01433     for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
01434       if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
01435       {
01436         // the tags count for '/' + up to 10 digits, otherwise ',' + ME name
01437         sz += 1 + m->data_.objname.size() + 11;
01438         ++nfound;
01439       }
01440 
01441     if (! nfound)
01442       continue;
01443 
01444     std::vector<std::string>::iterator istr
01445       = into.insert(into.end(), std::string());
01446 
01447     istr->reserve(sz);
01448 
01449     *istr += *di;
01450     *istr += ':';
01451     for (sz = 0; mi != m; ++mi)
01452     {
01453       if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
01454       {
01455         sprintf(tagbuf, "/%u", mi->data_.tag);
01456         if (sz > 0)
01457           *istr += ',';
01458         *istr += m->data_.objname;
01459         *istr += tagbuf;
01460         ++sz;
01461       }
01462     }
01463   }
01464 }
01465 
01468 std::vector<MonitorElement*>
01469 DQMStore::getAllContents(const std::string &path) const
01470 {
01471   std::string clean;
01472   const std::string *cleaned = 0;
01473   cleanTrailingSlashes(path, clean, cleaned);
01474   MonitorElement proto(cleaned, std::string());
01475 
01476   std::vector<MonitorElement *> result;
01477   MEMap::const_iterator e = data_.end();
01478   MEMap::const_iterator i = data_.lower_bound(proto);
01479   for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
01480     result.push_back(const_cast<MonitorElement *>(&*i));
01481 
01482   return result;
01483 }
01484 
01487 std::vector<MonitorElement*>
01488 DQMStore::getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType /* = Wildcard */) const
01489 {
01490   lat::Regexp rx;
01491   try
01492   {
01493     rx = lat::Regexp(pattern, 0, syntaxType);
01494     rx.study();
01495   }
01496   catch (lat::Error &e)
01497   {
01498     raiseDQMError("DQMStore", "Invalid regular expression '%s': %s",
01499                   pattern.c_str(), e.explain().c_str());
01500   }
01501 
01502   std::string path;
01503   std::vector<MonitorElement *> result;
01504   MEMap::const_iterator i = data_.begin();
01505   MEMap::const_iterator e = data_.end();
01506   for ( ; i != e; ++i)
01507   {
01508     path.clear();
01509     mergePath(path, *i->data_.dirname, i->data_.objname);
01510     if (rx.match(path))
01511       result.push_back(const_cast<MonitorElement *>(&*i));
01512   }
01513 
01514   return result;
01515 }
01516 
01520 
01523 void
01524 DQMStore::reset(void)
01525 {
01526   MEMap::iterator mi = data_.begin();
01527   MEMap::iterator me = data_.end();
01528   for ( ; mi != me; ++mi)
01529   {
01530     MonitorElement &me = const_cast<MonitorElement &>(*mi);
01531     if (mi->wasUpdated())
01532     {
01533       if (me.resetMe())
01534         me.Reset();
01535       me.resetUpdate();
01536     }
01537   }
01538 
01539   reset_ = true;
01540 }
01541 
01545 
01547 void
01548 DQMStore::forceReset(void)
01549 {
01550   MEMap::iterator mi = data_.begin();
01551   MEMap::iterator me = data_.end();
01552   for ( ; mi != me; ++mi)
01553   {
01554     MonitorElement &me = const_cast<MonitorElement &>(*mi);
01555     me.Reset();
01556     me.resetUpdate();
01557   }
01558 
01559   reset_ = true;
01560 }
01561 
01567 bool
01568 DQMStore::extract(TObject *obj, const std::string &dir, bool overwrite)
01569 {
01570   // NB: Profile histograms inherit from TH*D, checking order matters.
01571   MonitorElement *refcheck = 0;
01572   if (TProfile *h = dynamic_cast<TProfile *>(obj))
01573   {
01574     MonitorElement *me = findObject(dir, h->GetName());
01575     if (! me)
01576       me = bookProfile(dir, h->GetName(), (TProfile *) h->Clone());
01577     else if (overwrite)
01578       me->copyFrom(h);
01579     else if (isCollateME(me) || collateHistograms_)
01580       collateProfile(me, h);
01581     refcheck = me;
01582   }
01583   else if (TProfile2D *h = dynamic_cast<TProfile2D *>(obj))
01584   {
01585     MonitorElement *me = findObject(dir, h->GetName());
01586     if (! me)
01587       me = bookProfile2D(dir, h->GetName(), (TProfile2D *) h->Clone());
01588     else if (overwrite)
01589       me->copyFrom(h);
01590     else if (isCollateME(me) || collateHistograms_)
01591       collateProfile2D(me, h);
01592     refcheck = me;
01593   }
01594   else if (TH1F *h = dynamic_cast<TH1F *>(obj))
01595   {
01596     MonitorElement *me = findObject(dir, h->GetName());
01597     if (! me)
01598       me = book1D(dir, h->GetName(), (TH1F *) h->Clone());
01599     else if (overwrite)
01600       me->copyFrom(h);
01601     else if (isCollateME(me) || collateHistograms_)
01602       collate1D(me, h);
01603     refcheck = me;
01604   }
01605   else if (TH1S *h = dynamic_cast<TH1S *>(obj))
01606   {
01607     MonitorElement *me = findObject(dir, h->GetName());
01608     if (! me)
01609       me = book1S(dir, h->GetName(), (TH1S *) h->Clone());
01610     else if (overwrite)
01611       me->copyFrom(h);
01612     else if (isCollateME(me) || collateHistograms_)
01613       collate1S(me, h);
01614     refcheck = me;
01615   }
01616   else if (TH1D *h = dynamic_cast<TH1D *>(obj))
01617   {
01618     MonitorElement *me = findObject(dir, h->GetName());
01619     if (! me)
01620       me = book1DD(dir, h->GetName(), (TH1D *) h->Clone());
01621     else if (overwrite)
01622       me->copyFrom(h);
01623     else if (isCollateME(me) || collateHistograms_)
01624       collate1DD(me, h);
01625     refcheck = me;
01626   }
01627   else if (TH2F *h = dynamic_cast<TH2F *>(obj))
01628   {
01629     MonitorElement *me = findObject(dir, h->GetName());
01630     if (! me)
01631       me = book2D(dir, h->GetName(), (TH2F *) h->Clone());
01632     else if (overwrite)
01633       me->copyFrom(h);
01634     else if (isCollateME(me) || collateHistograms_)
01635       collate2D(me, h);
01636     refcheck = me;
01637   }
01638   else if (TH2S *h = dynamic_cast<TH2S *>(obj))
01639   {
01640     MonitorElement *me = findObject(dir, h->GetName());
01641     if (! me)
01642       me = book2S(dir, h->GetName(), (TH2S *) h->Clone());
01643     else if (overwrite)
01644       me->copyFrom(h);
01645     else if (isCollateME(me) || collateHistograms_)
01646       collate2S(me, h);
01647     refcheck = me;
01648   }
01649   else if (TH2D *h = dynamic_cast<TH2D *>(obj))
01650   {
01651     MonitorElement *me = findObject(dir, h->GetName());
01652     if (! me)
01653       me = book2DD(dir, h->GetName(), (TH2D *) h->Clone());
01654     else if (overwrite)
01655       me->copyFrom(h);
01656     else if (isCollateME(me) || collateHistograms_)
01657       collate2DD(me, h);
01658     refcheck = me;
01659   }
01660   else if (TH3F *h = dynamic_cast<TH3F *>(obj))
01661   {
01662     MonitorElement *me = findObject(dir, h->GetName());
01663     if (! me)
01664       me = book3D(dir, h->GetName(), (TH3F *) h->Clone());
01665     else if (overwrite)
01666       me->copyFrom(h);
01667     else if (isCollateME(me) || collateHistograms_)
01668       collate3D(me, h);
01669     refcheck = me;
01670   }
01671   else if (dynamic_cast<TObjString *>(obj))
01672   {
01673     lat::RegexpMatch m;
01674     if (! s_rxmeval.match(obj->GetName(), 0, 0, &m))
01675     {
01676       if (strstr(obj->GetName(), "CMSSW"))
01677       {
01678         if (verbose_)
01679           std::cout << "Input file version: " << obj->GetName() << std::endl;
01680         return true;
01681       }
01682       else if (strstr(obj->GetName(), "DQMPATCH"))
01683       {
01684         if (verbose_)
01685           std::cout << "DQM patch version: " << obj->GetName() << std::endl;
01686         return true;
01687       }
01688       else
01689       {
01690         std::cout << "*** DQMStore: WARNING: cannot extract object '"
01691                   << obj->GetName() << "' of type '"
01692                   << obj->IsA()->GetName() << "'\n";
01693         return false;
01694       }
01695     }
01696 
01697     std::string label = m.matchString(obj->GetName(), 1);
01698     std::string kind = m.matchString(obj->GetName(), 2);
01699     std::string value = m.matchString(obj->GetName(), 3);
01700 
01701     if (kind == "i")
01702     {
01703       MonitorElement *me = findObject(dir, label);
01704       if (! me || overwrite)
01705       {
01706         if (! me) me = bookInt(dir, label);
01707         me->Fill(atoll(value.c_str()));
01708       }
01709     }
01710     else if (kind == "f")
01711     {
01712       MonitorElement *me = findObject(dir, label);
01713       if (! me || overwrite)
01714       {
01715         if (! me) me = bookFloat(dir, label);
01716         me->Fill(atof(value.c_str()));
01717       }
01718     }
01719     else if (kind == "s")
01720     {
01721       MonitorElement *me = findObject(dir, label);
01722       if (! me)
01723         me = bookString(dir, label, value);
01724       else if (overwrite)
01725         me->Fill(value);
01726     }
01727     else if (kind == "t")
01728     {
01729       MonitorElement *me = findObject(dir, label);
01730       if (! me)
01731       {
01732         std::cout << "*** DQMStore: WARNING: no monitor element '"
01733                   << label << "' in directory '"
01734                   << dir << "' for a tag\n";
01735         return false;
01736       }
01737       errno = 0;
01738       char *endp = 0;
01739       unsigned long val = strtoul(value.c_str(), &endp, 10);
01740       if ((val == 0 && errno) || *endp || val > ~uint32_t(0))
01741       {
01742         std::cout << "*** DQMStore: WARNING: cannot restore tag '"
01743                   << value << "' for monitor element '"
01744                   << label << "' in directory '"
01745                   << dir << "' - invalid value\n";
01746         return false;
01747       }
01748       tag(me, val);
01749     }
01750     else if (kind == "qr")
01751     {
01752       // Handle qreports, but skip them while reading in references.
01753       if (! isSubdirectory(s_referenceDirName, dir))
01754       {
01755         size_t dot = label.find('.');
01756         if (dot == std::string::npos)
01757         {
01758           std::cout << "*** DQMStore: WARNING: quality report label in '" << label
01759                     << "' is missing a '.' and cannot be extracted\n";
01760           return false;
01761         }
01762 
01763         std::string mename (label, 0, dot);
01764         std::string qrname (label, dot+1, std::string::npos);
01765 
01766         m.reset();
01767         DQMNet::QValue qv;
01768         if (s_rxmeqr1.match(value, 0, 0, &m))
01769         {
01770           qv.code = atoi(m.matchString(value, 1).c_str());
01771           qv.qtresult = strtod(m.matchString(value, 2).c_str(), 0);
01772           qv.message = m.matchString(value, 4);
01773           qv.qtname = qrname;
01774           qv.algorithm = m.matchString(value, 3);
01775         }
01776         else if (s_rxmeqr2.match(value, 0, 0, &m))
01777         {
01778           qv.code = atoi(m.matchString(value, 1).c_str());
01779           qv.qtresult = 0; // unavailable in old format
01780           qv.message = m.matchString(value, 2);
01781           qv.qtname = qrname;
01782           // qv.algorithm unavailable in old format
01783         }
01784         else
01785         {
01786           std::cout << "*** DQMStore: WARNING: quality test value '"
01787                     << value << "' is incorrectly formatted\n";
01788           return false;
01789         }
01790 
01791         MonitorElement *me = findObject(dir, mename);
01792         if (! me)
01793         {
01794           std::cout << "*** DQMStore: WARNING: no monitor element '"
01795                     << mename << "' in directory '"
01796                     << dir << "' for quality test '"
01797                     << label << "'\n";
01798           return false;
01799         }
01800 
01801         me->addQReport(qv, /* FIXME: getQTest(qv.qtname)? */ 0);
01802       }
01803     }
01804     else
01805     {
01806       std::cout << "*** DQMStore: WARNING: cannot extract object '"
01807                 << obj->GetName() << "' of type '"
01808                 << obj->IsA()->GetName() << "'\n";
01809       return false;
01810     }
01811   }
01812   else if (TNamed *n = dynamic_cast<TNamed *>(obj))
01813   {
01814     // For old DQM data.
01815     std::string s;
01816     s.reserve(6 + strlen(n->GetTitle()) + 2*strlen(n->GetName()));
01817     s += '<'; s += n->GetName(); s += '>';
01818     s += n->GetTitle();
01819     s += '<'; s += '/'; s += n->GetName(); s += '>';
01820     TObjString os(s.c_str());
01821     return extract(&os, dir, overwrite);
01822   }
01823   else
01824   {
01825     std::cout << "*** DQMStore: WARNING: cannot extract object '"
01826               << obj->GetName() << "' of type '" << obj->IsA()->GetName()
01827               << "' and with title '" << obj->GetTitle() << "'\n";
01828     return false;
01829   }
01830 
01831   // If we just read in a reference monitor element, and there is a
01832   // monitor element with the same name, link the two together. The
01833   // other direction is handled by the initialise() method.
01834   if (refcheck && isSubdirectory(s_referenceDirName, dir))
01835   {
01836     std::string mdir(dir, s_referenceDirName.size()+1, std::string::npos);
01837     if (MonitorElement *master = findObject(mdir, obj->GetName()))
01838     {
01839       master->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
01840       master->reference_ = refcheck->object_;
01841     }
01842   }
01843 
01844   return true;
01845 }
01846 
01850 bool
01851 DQMStore::cdInto(const std::string &path) const
01852 {
01853   assert(! path.empty());
01854 
01855   // Find the first path component.
01856   size_t start = 0;
01857   size_t end = path.find('/', start);
01858   if (end == std::string::npos)
01859     end = path.size();
01860 
01861   while (true)
01862   {
01863     // Check if this subdirectory component exists.  If yes, make sure
01864     // it is actually a subdirectory.  Otherwise create or cd into it.
01865     std::string part(path, start, end-start);
01866     TObject *o = gDirectory->Get(part.c_str());
01867     if (o && ! dynamic_cast<TDirectory *>(o))
01868       raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
01869                     " fails because the part '%s' already exists and is not"
01870                     " directory", path.c_str(), part.c_str());
01871     else if (! o)
01872       gDirectory->mkdir(part.c_str());
01873 
01874     if (! gDirectory->cd(part.c_str()))
01875       raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
01876                     " fails because could not cd into subdirectory '%s'",
01877                     path.c_str(), part.c_str());
01878 
01879     // Stop if we reached the end, ignoring any trailing '/'.
01880     if (end+1 >= path.size())
01881       break;
01882 
01883     // Find the next path component.
01884     start = end+1;
01885     end = path.find('/', start);
01886     if (end == std::string::npos)
01887       end = path.size();
01888   }
01889 
01890   return true;
01891 }
01892 
01897 void
01898 DQMStore::save(const std::string &filename,
01899                const std::string &path /* = "" */,
01900                const std::string &pattern /* = "" */,
01901                const std::string &rewrite /* = "" */,
01902                SaveReferenceTag ref /* = SaveWithReference */,
01903                int minStatus /* = dqm::qstatus::STATUS_OK */,
01904                const std::string &fileupdate /* = RECREATE */)
01905 {
01906   std::set<std::string>::iterator di, de;
01907   MEMap::iterator mi, me = data_.end();
01908   DQMNet::QReports::const_iterator qi, qe;
01909   int nme=0;
01910 
01911   // TFile flushes to disk with fsync() on every TDirectory written to the
01912   // file.  This makes DQM file saving painfully slow, and ironically makes
01913   // it _more_ likely the file saving gets interrupted and corrupts the file.
01914   // The utility class below simply ignores the flush synchronisation.
01915   class TFileNoSync : public TFile
01916   {
01917   public:
01918     TFileNoSync(const char *file, const char *opt) : TFile(file, opt) {}
01919     virtual Int_t SysSync(Int_t) { return 0; }
01920   };
01921 
01922   // open output file, on 1st save recreate, later update
01923   if (verbose_)
01924     std::cout << "\n DQMStore: Opening TFile '" << filename 
01925               << "' with option '" << fileupdate <<"'\n";
01926 
01927   TFileNoSync f(filename.c_str(), fileupdate.c_str()); // open file
01928   if(f.IsZombie())
01929     raiseDQMError("DQMStore", "Failed to create/update file '%s'", filename.c_str());
01930   f.cd();
01931   
01932   // Construct a regular expression from the pattern string.
01933   std::auto_ptr<lat::Regexp> rxpat;
01934   if (! pattern.empty())
01935     rxpat.reset(new lat::Regexp(pattern.c_str()));
01936 
01937   // Prepare a path for the reference object selection.
01938   std::string refpath;
01939   refpath.reserve(s_referenceDirName.size() + path.size() + 2);
01940   refpath += s_referenceDirName;
01941   if (! path.empty())
01942   {
01943     refpath += '/';
01944     refpath += path;
01945   }
01946 
01947   // Loop over the directory structure.
01948   for (di = dirs_.begin(), de = dirs_.end(); di != de; ++di)
01949   {
01950     // Check if we should process this directory.  We process the
01951     // requested part of the object tree, including references.
01952     if (! path.empty()
01953         && ! isSubdirectory(path, *di)
01954         && ! isSubdirectory(refpath, *di))
01955       continue;
01956     
01957     // Loop over monitor elements in this directory.
01958     MonitorElement proto(&*di, std::string());
01959     mi = data_.lower_bound(proto);
01960     for ( ; mi != me && isSubdirectory(*di, *mi->data_.dirname); ++mi)
01961     {
01962       // Skip if it isn't a direct child.
01963       if (*di != *mi->data_.dirname)
01964         continue;
01965 
01966       // Handle reference histograms, with three distinct cases:
01967       // 1) Skip all references entirely on saving.
01968       // 2) Blanket saving of all references.
01969       // 3) Save only references for monitor elements with qtests.
01970       // The latter two are affected by "path" sub-tree selection,
01971       // i.e. references are saved only in the selected tree part.
01972       if (isSubdirectory(refpath, *mi->data_.dirname))
01973       {
01974         if (ref == SaveWithoutReference)
01975           // Skip the reference entirely.
01976           continue;
01977         else if (ref == SaveWithReference)
01978           // Save all references regardless of qtests.
01979           ;
01980         else if (ref == SaveWithReferenceForQTest)
01981         {
01982           // Save only references for monitor elements with qtests
01983           // with an optional cut on minimum quality test result.
01984           int status = -1;
01985           std::string mname(mi->getFullname(), s_referenceDirName.size()+1, std::string::npos);
01986           MonitorElement *master = get(mname);
01987           if (master)
01988             for (size_t i = 0, e = master->data_.qreports.size(); i != e; ++i)
01989               status = std::max(status, master->data_.qreports[i].code);
01990 
01991           if (! master || status < minStatus)
01992           {
01993             if (verbose_ > 1)
01994               std::cout << "DQMStore::save: skipping monitor element '"
01995                         << mi->data_.objname << "' while saving, status is "
01996                         << status << ", required minimum status is "
01997                         << minStatus << std::endl;
01998             continue;
01999           }
02000         }
02001       }
02002 
02003       if (verbose_ > 1)
02004         std::cout << "DQMStore::save: saving monitor element '"
02005                   << mi->data_.objname << "'\n";
02006       nme++; // count saved histograms
02007 
02008       // Create the directory.
02009       gDirectory->cd("/");
02010       if (di->empty())
02011         cdInto(s_monitorDirName);
02012       else if (rxpat.get())
02013         cdInto(s_monitorDirName + '/' + lat::StringOps::replace(*di, *rxpat, rewrite));
02014       else
02015         cdInto(s_monitorDirName + '/' + *di);
02016 
02017       // Save the object.
02018       switch (mi->kind())
02019       {
02020       case MonitorElement::DQM_KIND_INT:
02021       case MonitorElement::DQM_KIND_REAL:
02022       case MonitorElement::DQM_KIND_STRING:
02023         TObjString(mi->tagString().c_str()).Write();
02024         break;
02025 
02026       default:
02027         mi->object_->Write();
02028         break;
02029       }
02030 
02031       // Save quality reports if this is not in reference section.
02032       if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
02033       {
02034         qi = mi->data_.qreports.begin();
02035         qe = mi->data_.qreports.end();
02036         for ( ; qi != qe; ++qi)
02037           TObjString(mi->qualityTagString(*qi).c_str()).Write();
02038       }
02039 
02040       // Save tag if any
02041       if (mi->data_.flags & DQMNet::DQM_PROP_TAGGED)
02042         TObjString(mi->tagLabelString().c_str()).Write();
02043     }
02044   }
02045 
02046   f.Close();
02047 
02048   // Maybe make some noise.
02049   if (verbose_)
02050     std::cout << "DQMStore::save: successfully wrote " << nme 
02051               << " objects from path '" << path  
02052               << "' into DQM file '" << filename << "'\n";
02053 }
02054 
02057 unsigned int
02058 DQMStore::readDirectory(TFile *file,
02059                         bool overwrite,
02060                         const std::string &onlypath,
02061                         const std::string &prepend,
02062                         const std::string &curdir,
02063                         OpenRunDirs stripdirs)
02064 {
02065   unsigned int ntot = 0;
02066   unsigned int count = 0;
02067 
02068   if (! file->cd(curdir.c_str()))
02069     raiseDQMError("DQMStore", "Failed to process directory '%s' while"
02070                   " reading file '%s'", curdir.c_str(), file->GetName());
02071 
02072   // Figure out current directory name, but strip out the top
02073   // directory into which we dump everything.
02074   std::string dirpart = curdir;
02075   if (dirpart.compare(0, s_monitorDirName.size(), s_monitorDirName) == 0)
02076   {
02077     if (dirpart.size() == s_monitorDirName.size())
02078       dirpart.clear();
02079     else if (dirpart[s_monitorDirName.size()] == '/')
02080       dirpart.erase(0, s_monitorDirName.size()+1);
02081   }
02082 
02083   // See if we are going to skip this directory.
02084   bool skip = (! onlypath.empty() && ! isSubdirectory(onlypath, dirpart));
02085   
02086   if (prepend == s_collateDirName || 
02087       prepend == s_referenceDirName || 
02088       stripdirs == StripRunDirs )
02089   {
02090     // Remove Run # and RunSummary dirs
02091     // first look for Run summary, 
02092     // if that is found and erased, also erase Run dir
02093     size_t slash = dirpart.find('/');
02094     size_t pos = dirpart.find("/Run summary");
02095     if (slash != std::string::npos && pos !=std::string::npos) 
02096     {
02097       dirpart.erase(pos,12);
02098     
02099       pos = dirpart.find("Run ");
02100       size_t length = dirpart.find('/',pos+1)-pos+1;
02101       if (pos !=std::string::npos) 
02102         dirpart.erase(pos,length);
02103     }
02104   } 
02105 
02106   // If we are prepending, add it to the directory name, 
02107   // and suppress reading of already existing reference histograms
02108   if (prepend == s_collateDirName || 
02109       prepend == s_referenceDirName)
02110   {
02111     size_t slash = dirpart.find('/');
02112     // If we are reading reference, skip previous reference.
02113     if (slash == std::string::npos   // skip if Reference is toplevel folder, i.e. no slash
02114         && slash+1+s_referenceDirName.size() == dirpart.size()
02115         && dirpart.compare(slash+1, s_referenceDirName.size(), s_referenceDirName) == 0)
02116       return 0;
02117 
02118     slash = dirpart.find('/');    
02119     // Skip reading of EventInfo subdirectory.
02120     if (slash != std::string::npos
02121         && slash + 10 == dirpart.size()
02122         && dirpart.compare( slash+1 , 9 , "EventInfo") == 0) {
02123       if (verbose_)
02124         std::cout << "DQMStore::readDirectory: skipping '" << dirpart << "'\n";
02125       return 0;
02126     }
02127 
02128     // Add prefix.
02129     if (dirpart.empty())
02130       dirpart = prepend;
02131     else
02132       dirpart = prepend + '/' + dirpart;
02133   }
02134   else if (! prepend.empty())
02135   {
02136     if (dirpart.empty())
02137       dirpart = prepend;
02138     else
02139       dirpart = prepend + '/' + dirpart;
02140   }
02141 
02142   // Loop over the contents of this directory in the file.
02143   // Post-pone string object handling to happen after other
02144   // objects have been read in so we are guaranteed to have
02145   // histograms by the time we read in quality tests and tags.
02146   TKey *key;
02147   TIter next (gDirectory->GetListOfKeys());
02148   std::list<TObject *> delayed;
02149   while ((key = (TKey *) next()))
02150   {
02151     std::auto_ptr<TObject> obj(key->ReadObj());
02152     if (dynamic_cast<TDirectory *>(obj.get()))
02153     {
02154       std::string subdir;
02155       subdir.reserve(curdir.size() + strlen(obj->GetName()) + 2);
02156       subdir += curdir;
02157       if (! curdir.empty())
02158         subdir += '/';
02159       subdir += obj->GetName();
02160 
02161       ntot += readDirectory(file, overwrite, onlypath, prepend, subdir, stripdirs);
02162     }
02163     else if (skip)
02164       ;
02165     else if (dynamic_cast<TObjString *>(obj.get()))
02166     {
02167       delayed.push_back(obj.release());
02168     }
02169     else
02170     {
02171       if (verbose_ > 2)
02172         std::cout << "DQMStore: reading object '" << obj->GetName()
02173                   << "' of type '" << obj->IsA()->GetName()
02174                   << "' from '" << file->GetName()
02175                   << "' into '" << dirpart << "'\n";
02176 
02177       makeDirectory(dirpart);
02178       if (extract(obj.get(), dirpart, overwrite))
02179         ++count;
02180     }
02181   }
02182 
02183   while (! delayed.empty())
02184   {
02185     if (verbose_ > 2)
02186       std::cout << "DQMStore: reading object '" << delayed.front()->GetName()
02187                 << "' of type '" << delayed.front()->IsA()->GetName()
02188                 << "' from '" << file->GetName()
02189                 << "' into '" << dirpart << "'\n";
02190 
02191     makeDirectory(dirpart);
02192     if (extract(delayed.front(), dirpart, overwrite))
02193       ++count;
02194 
02195     delete delayed.front();
02196     delayed.pop_front();
02197   }
02198 
02199   if (verbose_ > 1)
02200     std::cout << "DQMStore: read " << count << '/' << ntot
02201               << " objects from directory '" << dirpart << "'\n";
02202 
02203   return ntot + count;
02204 }
02205 
02212 bool
02213 DQMStore::open(const std::string &filename,
02214                bool overwrite /* = false */,
02215                const std::string &onlypath /* ="" */,
02216                const std::string &prepend /* ="" */, 
02217                OpenRunDirs stripdirs /* =KeepRunDirs */, 
02218                bool fileMustExist /* =true */)
02219 {
02220   return readFile(filename,overwrite,onlypath,prepend,stripdirs,fileMustExist);
02221 }
02222 
02227 bool 
02228 DQMStore::load(const std::string &filename,
02229                OpenRunDirs stripdirs /* =StripRunDirs */, 
02230                bool fileMustExist /* =true */)
02231 {
02232   bool overwrite = true;
02233   if (collateHistograms_) overwrite = false;
02234   if (verbose_) 
02235   {
02236     std::cout << "DQMStore::load: reading from file '" << filename << "'\n";
02237     if (collateHistograms_)
02238       std::cout << "DQMStore::load: in collate mode   " << "\n";
02239     else
02240       std::cout << "DQMStore::load: in overwrite mode   " << "\n";
02241   }
02242     
02243   return readFile(filename,overwrite,"","",stripdirs,fileMustExist);
02244      
02245 }
02246 
02252 bool
02253 DQMStore::readFile(const std::string &filename,
02254                    bool overwrite /* = false */,
02255                    const std::string &onlypath /* ="" */,
02256                    const std::string &prepend /* ="" */,
02257                    OpenRunDirs stripdirs /* =StripRunDirs */,
02258                    bool fileMustExist /* =true */)
02259 {
02260   
02261   if (verbose_)
02262     std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
02263 
02264   std::auto_ptr<TFile> f;
02265 
02266   try 
02267   {
02268     f.reset(TFile::Open(filename.c_str()));
02269     if (! f.get() || f->IsZombie())
02270       raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
02271   }
02272   catch (std::exception &)
02273   {
02274     if (fileMustExist)
02275       throw;
02276     else
02277     {  
02278     if (verbose_)
02279       std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
02280     return false;
02281     }
02282   }
02283 
02284   unsigned n = readDirectory(f.get(), overwrite, onlypath, prepend, "", stripdirs);
02285   f->Close();
02286 
02287   MEMap::iterator mi = data_.begin();
02288   MEMap::iterator me = data_.end();
02289   for ( ; mi != me; ++mi)
02290     const_cast<MonitorElement &>(*mi).updateQReportStats();
02291 
02292   if (verbose_)
02293   {
02294     std::cout << "DQMStore::open: successfully read " << n
02295               << " objects from file '" << filename << "'";
02296     if (! onlypath.empty())
02297       std::cout << " from directory '" << onlypath << "'";
02298     if (! prepend.empty())
02299       std::cout << " into directory '" << prepend << "'";
02300     std::cout << std::endl;
02301   }
02302   return true;
02303 }
02304 
02310 void
02311 DQMStore::rmdir(const std::string &path)
02312 {
02313   std::string clean;
02314   const std::string *cleaned = 0;
02315   cleanTrailingSlashes(path, clean, cleaned);
02316   MonitorElement proto(cleaned, std::string());
02317 
02318   MEMap::iterator e = data_.end();
02319   MEMap::iterator i = data_.lower_bound(proto);
02320   while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
02321     data_.erase(i++);
02322 
02323   std::set<std::string>::iterator de = dirs_.end();
02324   std::set<std::string>::iterator di = dirs_.lower_bound(*cleaned);
02325   while (di != de && isSubdirectory(*cleaned, *di))
02326     dirs_.erase(di++);
02327 }
02328 
02330 void
02331 DQMStore::removeContents(const std::string &dir)
02332 {
02333   MonitorElement proto(&dir, std::string());
02334   MEMap::iterator e = data_.end();
02335   MEMap::iterator i = data_.lower_bound(proto);
02336   while (i != e && isSubdirectory(dir, *i->data_.dirname))
02337     if (dir == *i->data_.dirname)
02338       data_.erase(i++);
02339     else
02340       ++i;
02341 }
02342 
02344 void
02345 DQMStore::removeContents(void)
02346 {
02347   removeContents(pwd_);
02348 }
02349 
02352 void
02353 DQMStore::removeElement(const std::string &name)
02354 {
02355   removeElement(pwd_, name);
02356 }
02357 
02360 void
02361 DQMStore::removeElement(const std::string &dir, const std::string &name, bool warning /* = true */)
02362 {
02363   MonitorElement proto(&dir, name);
02364   MEMap::iterator pos = data_.find(proto);
02365   if (pos == data_.end() && warning)
02366     std::cout << "DQMStore: WARNING: attempt to remove non-existent"
02367               << " monitor element '" << name << "' in '" << dir << "'\n";
02368   else
02369     data_.erase(pos);
02370 }
02371 
02377 QCriterion *
02378 DQMStore::getQCriterion(const std::string &qtname) const
02379 {
02380   QCMap::const_iterator i = qtests_.find(qtname);
02381   QCMap::const_iterator e = qtests_.end();
02382   return (i == e ? 0 : i->second);
02383 }
02384 
02388 QCriterion *
02389 DQMStore::createQTest(const std::string &algoname, const std::string &qtname)
02390 {
02391   if (qtests_.count(qtname))
02392     raiseDQMError("DQMStore", "Attempt to create duplicate quality test '%s'",
02393                   qtname.c_str());
02394 
02395   QAMap::iterator i = qalgos_.find(algoname);
02396   if (i == qalgos_.end())
02397     raiseDQMError("DQMStore", "Cannot create a quality test using unknown"
02398                   " algorithm '%s'", algoname.c_str());
02399 
02400   QCriterion *qc = i->second(qtname);
02401   qc->setVerbose(verboseQT_);
02402 
02403   qtests_[qtname] = qc;
02404   return qc;
02405 }
02406 
02409 void
02410 DQMStore::useQTest(const std::string &dir, const std::string &qtname)
02411 {
02412   // Clean the path
02413   std::string clean;
02414   const std::string *cleaned = 0;
02415   cleanTrailingSlashes(dir, clean, cleaned);
02416 
02417   // Validate the path.
02418   if (cleaned->find_first_not_of(s_safe) != std::string::npos)
02419     raiseDQMError("DQMStore", "Monitor element path name '%s'"
02420                   " uses unacceptable characters", cleaned->c_str());
02421 
02422   // Redirect to the pattern match version.
02423   useQTestByMatch(*cleaned + "/*", qtname);
02424 }
02425 
02427 int 
02428 DQMStore::useQTestByMatch(const std::string &pattern, const std::string &qtname)
02429 {
02430   QCriterion *qc = getQCriterion(qtname);
02431   if (! qc)
02432     raiseDQMError("DQMStore", "Cannot apply non-existent quality test '%s'",
02433                   qtname.c_str());
02434 
02435   // Clean the path
02436   lat::Regexp *rx = 0;
02437   try
02438   {
02439     rx = new lat::Regexp(pattern, 0, lat::Regexp::Wildcard);
02440     rx->study();
02441   }
02442   catch (lat::Error &e)
02443   {
02444     delete rx;
02445     raiseDQMError("DQMStore", "Invalid wildcard pattern '%s' in quality"
02446                   " test specification", pattern.c_str());
02447   }
02448 
02449   // Record the test for future reference.
02450   QTestSpec qts(rx, qc);
02451   qtestspecs_.push_back(qts);
02452 
02453   // Apply the quality test.
02454   MEMap::iterator mi = data_.begin();
02455   MEMap::iterator me = data_.end();
02456   std::string path;
02457   int cases = 0;
02458   for ( ; mi != me; ++mi)
02459   {
02460     path.clear();
02461     mergePath(path, *mi->data_.dirname, mi->data_.objname);
02462     if (rx->match(path))
02463     {
02464       ++cases;
02465       const_cast<MonitorElement &>(*mi).addQReport(qts.second);
02466     }
02467   }
02468 
02469   //return the number of matched cases
02470   return cases;
02471 }
02474 void
02475 DQMStore::runQTests(void)
02476 {
02477 
02478   if (verbose_ > 0)
02479     std::cout << "DQMStore: running runQTests() with reset = "
02480               << ( reset_ ? "true" : "false" ) << std::endl;
02481 
02482   // Apply quality tests to each monitor element, skipping references.
02483   MEMap::iterator mi = data_.begin();
02484   MEMap::iterator me = data_.end();
02485   for ( ; mi != me; ++mi)
02486     if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
02487       const_cast<MonitorElement &>(*mi).runQTests();
02488 
02489   reset_ = false;
02490 }
02491 
02495 int
02496 DQMStore::getStatus(const std::string &path /* = "" */) const
02497 {
02498   std::string clean;
02499   const std::string *cleaned = 0;
02500   cleanTrailingSlashes(path, clean, cleaned);
02501 
02502   int status = dqm::qstatus::STATUS_OK;
02503   MEMap::const_iterator mi = data_.begin();
02504   MEMap::const_iterator me = data_.end();
02505   for ( ; mi != me; ++mi)
02506   {
02507     if (! cleaned->empty() && ! isSubdirectory(*cleaned, *mi->data_.dirname))
02508       continue;
02509 
02510     if (mi->hasError())
02511       return dqm::qstatus::ERROR;
02512     else if (mi->hasWarning())
02513       status = dqm::qstatus::WARNING;
02514     else if (status < dqm::qstatus::WARNING
02515              && mi->hasOtherReport())
02516       status = dqm::qstatus::OTHER;
02517   }
02518   return status;
02519 }
02520 
02526 void
02527 DQMStore::softReset(MonitorElement *me)
02528 {
02529   if (me)
02530     me->softReset();
02531 }
02532 
02533 // reverts action of softReset
02534 void
02535 DQMStore::disableSoftReset(MonitorElement *me)
02536 {
02537   if (me)
02538     me->disableSoftReset();
02539 }
02540 
02543 void
02544 DQMStore::setAccumulate(MonitorElement *me, bool flag)
02545 {
02546   if (me)
02547     me->setAccumulate(flag);
02548 }
02549 
02553 void
02554 DQMStore::showDirStructure(void) const
02555 {
02556   std::vector<std::string> contents;
02557   getContents(contents);
02558 
02559   std::cout << " ------------------------------------------------------------\n"
02560             << "                    Directory structure:                     \n"
02561             << " ------------------------------------------------------------\n";
02562 
02563   std::copy(contents.begin(), contents.end(),
02564             std::ostream_iterator<std::string>(std::cout, "\n"));
02565 
02566   std::cout << " ------------------------------------------------------------\n";
02567 }
02568 
02572 // check if the monitor element is in auto-collation folder
02573 bool
02574 DQMStore::isCollateME(MonitorElement *me) const
02575 { return me && isSubdirectory(s_collateDirName, *me->data_.dirname); }