CMS 3D CMS Logo

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