CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DQMServices/FwkIO/plugins/DQMRootOutputModule.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     FwkIO
00004 // Class  :     DQMRootOutputModule
00005 // 
00006 // Implementation:
00007 //     [Notes on implementation]
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Fri Apr 29 13:26:29 CDT 2011
00011 // $Id: DQMRootOutputModule.cc,v 1.11 2011/07/11 07:43:46 chrjones Exp $
00012 //
00013 
00014 // system include files
00015 #include <iostream>
00016 #include <string>
00017 #include <map>
00018 #include <memory>
00019 #include <boost/shared_ptr.hpp>
00020 #include "TFile.h"
00021 #include "TTree.h"
00022 #include "TString.h"
00023 #include "TH1.h"
00024 #include "TH2.h"
00025 #include "TProfile.h"
00026 
00027 // user include files
00028 #include "FWCore/Framework/interface/OutputModule.h"
00029 #include "FWCore/Framework/interface/RunPrincipal.h"
00030 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00031 #include "DQMServices/Core/interface/DQMStore.h"
00032 #include "DQMServices/Core/interface/MonitorElement.h"
00033 #include "FWCore/ServiceRegistry/interface/Service.h"
00034 #include "FWCore/Framework/interface/MakerMacros.h"
00035 #include "FWCore/MessageLogger/interface/JobReport.h"
00036 #include "FWCore/Utilities/interface/Digest.h"
00037 
00038 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00039 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00040 #include "FWCore/ParameterSet/interface/Registry.h"
00041 
00042 #include "format.h"
00043 
00044 namespace {
00045   class TreeHelperBase {
00046   public:
00047     TreeHelperBase(): m_wasFilled(false), m_firstIndex(0),m_lastIndex(0) {}
00048     virtual ~TreeHelperBase(){}
00049     void fill(MonitorElement* iElement) {
00050       doFill(iElement); 
00051       if(m_wasFilled) {++m_lastIndex;} 
00052       m_wasFilled = true; }
00053     bool wasFilled() const { return m_wasFilled;}
00054     void getRangeAndReset(ULong64_t& iFirstIndex, ULong64_t& iLastIndex) {
00055       iFirstIndex = m_firstIndex;
00056       iLastIndex = m_lastIndex;
00057       m_wasFilled = false;
00058       m_firstIndex = m_lastIndex +1;
00059       m_lastIndex = m_firstIndex;
00060     }
00061   private:
00062     virtual void doFill(MonitorElement*) = 0;
00063     bool m_wasFilled;
00064     ULong64_t m_firstIndex;
00065     ULong64_t m_lastIndex;
00066   };
00067   
00068   template<class T>
00069   class TreeHelper : public TreeHelperBase {
00070   public:
00071     TreeHelper(TTree* iTree, std::string* iFullNameBufferPtr ):
00072      m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr){ setup();}
00073      virtual void doFill(MonitorElement* iElement) {
00074        *m_fullNameBufferPtr = iElement->getFullname();
00075        m_flagBuffer = iElement->getTag();
00076        m_bufferPtr = dynamic_cast<T*>(iElement->getRootObject());
00077        assert(0!=m_bufferPtr);
00078        //std::cout <<"#entries: "<<m_bufferPtr->GetEntries()<<std::endl;
00079        m_tree->Fill();
00080      }
00081      
00082      
00083   private:
00084     void setup() {
00085       m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
00086       m_tree->Branch(kFlagBranch,&m_flagBuffer);
00087       
00088       m_bufferPtr = 0;
00089       m_tree->Branch(kValueBranch,&m_bufferPtr,128*1024,0);
00090     }
00091     TTree* m_tree;
00092     uint32_t m_flagBuffer;
00093     std::string* m_fullNameBufferPtr;
00094     T* m_bufferPtr;
00095   };
00096   
00097   class IntTreeHelper: public TreeHelperBase {
00098   public:
00099     IntTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr):
00100      m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr)
00101      {setup();}
00102 
00103     virtual void doFill(MonitorElement* iElement) {
00104      *m_fullNameBufferPtr = iElement->getFullname();
00105      m_flagBuffer = iElement->getTag();
00106      m_buffer = iElement->getIntValue();
00107      m_tree->Fill();
00108     }
00109 
00110   private:
00111     void setup() {
00112       m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
00113       m_tree->Branch(kFlagBranch,&m_flagBuffer);
00114       m_tree->Branch(kValueBranch,&m_buffer);
00115     }
00116     TTree* m_tree;
00117     uint32_t m_flagBuffer;
00118     std::string* m_fullNameBufferPtr;
00119     Long64_t m_buffer;
00120   };
00121 
00122   class FloatTreeHelper: public TreeHelperBase {
00123   public:
00124     FloatTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr):
00125      m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr)
00126      {setup();}
00127    virtual void doFill(MonitorElement* iElement) {
00128      *m_fullNameBufferPtr = iElement->getFullname();
00129      m_flagBuffer = iElement->getTag();
00130      m_buffer = iElement->getFloatValue();
00131      m_tree->Fill();
00132    }
00133   private:
00134     void setup() {
00135       m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
00136       m_tree->Branch(kFlagBranch,&m_flagBuffer);
00137       m_tree->Branch(kValueBranch,&m_buffer);
00138     }
00139     
00140     TTree* m_tree;
00141     uint32_t m_flagBuffer;
00142     std::string* m_fullNameBufferPtr;
00143     double m_buffer;
00144   };
00145 
00146   class StringTreeHelper: public TreeHelperBase {
00147   public:
00148     StringTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr):
00149      m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr), m_bufferPtr(&m_buffer)
00150      {setup();}
00151    virtual void doFill(MonitorElement* iElement) {
00152      *m_fullNameBufferPtr = iElement->getFullname();
00153      m_flagBuffer = iElement->getTag();
00154      m_buffer = iElement->getStringValue();
00155      m_tree->Fill();
00156    }
00157   private:
00158     void setup() {
00159       m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
00160       m_tree->Branch(kFlagBranch,&m_flagBuffer);
00161       m_tree->Branch(kValueBranch,&m_bufferPtr);
00162     }
00163     
00164     TTree* m_tree;
00165     uint32_t m_flagBuffer;
00166     std::string* m_fullNameBufferPtr;
00167     std::string m_buffer;
00168     std::string* m_bufferPtr;
00169   };
00170 
00171 }
00172 
00173 
00174 class DQMRootOutputModule : public edm::OutputModule {
00175 public:
00176   explicit DQMRootOutputModule(edm::ParameterSet const& pset);
00177   virtual ~DQMRootOutputModule();
00178   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
00179 
00180 private:
00181   virtual void write(edm::EventPrincipal const& e);
00182   virtual void writeLuminosityBlock(edm::LuminosityBlockPrincipal const&);
00183   virtual void writeRun(edm::RunPrincipal const&);
00184   virtual void beginRun(edm::RunPrincipal const& r);
00185   virtual void startEndFile();
00186   virtual void finishEndFile();
00187   std::string m_fileName;
00188   std::string m_logicalFileName;
00189   std::auto_ptr<TFile> m_file;
00190   std::vector<boost::shared_ptr<TreeHelperBase> > m_treeHelpers;
00191   
00192   unsigned int m_run;
00193   unsigned int m_lumi;
00194   unsigned int m_type;
00195   unsigned int m_presentHistoryIndex;
00196   ULong64_t m_beginTime;
00197   ULong64_t m_endTime;
00198   ULong64_t m_firstIndex;
00199   ULong64_t m_lastIndex;
00200   
00201   std::string m_fullNameBuffer;
00202   std::string* m_fullNameBufferPtr;
00203   std::map<unsigned int, unsigned int> m_dqmKindToTypeIndex;
00204   TTree* m_indicesTree;
00205   
00206   std::vector<edm::ProcessHistoryID> m_seenHistories;
00207   edm::JobReport::Token m_jrToken;
00208 };
00209 
00210 //
00211 // constants, enums and typedefs
00212 //
00213 
00214 static TreeHelperBase*
00215 makeHelper(unsigned int iTypeIndex,
00216            TTree* iTree, 
00217            std::string* iFullNameBufferPtr) {
00218   switch(iTypeIndex) {
00219     case kIntIndex:
00220     return new IntTreeHelper(iTree,iFullNameBufferPtr);
00221     case kFloatIndex:
00222     return new FloatTreeHelper(iTree,iFullNameBufferPtr);
00223     case kStringIndex:
00224     return new StringTreeHelper(iTree,iFullNameBufferPtr);
00225     case kTH1FIndex:
00226     return new TreeHelper<TH1F>(iTree,iFullNameBufferPtr);
00227     case kTH1SIndex:
00228     return new TreeHelper<TH1S>(iTree,iFullNameBufferPtr);
00229     case kTH1DIndex:
00230     return new TreeHelper<TH1D>(iTree,iFullNameBufferPtr);
00231     case kTH2FIndex:
00232     return new TreeHelper<TH2F>(iTree,iFullNameBufferPtr);
00233     case kTH2SIndex:
00234     return new TreeHelper<TH2S>(iTree,iFullNameBufferPtr);
00235     case kTH2DIndex:
00236     return new TreeHelper<TH2D>(iTree,iFullNameBufferPtr);
00237     case kTH3FIndex:
00238     return new TreeHelper<TH3F>(iTree,iFullNameBufferPtr);
00239     case kTProfileIndex:
00240     return new TreeHelper<TProfile>(iTree,iFullNameBufferPtr);
00241     case kTProfile2DIndex:
00242     return new TreeHelper<TProfile2D>(iTree,iFullNameBufferPtr);
00243   }
00244   assert(false);
00245   return 0;
00246 }
00247 
00248 //
00249 // static data member definitions
00250 //
00251 
00252 //
00253 // constructors and destructor
00254 //
00255 DQMRootOutputModule::DQMRootOutputModule(edm::ParameterSet const& pset):
00256 edm::OutputModule(pset),
00257 m_fileName(pset.getUntrackedParameter<std::string>("fileName")),
00258 m_logicalFileName(pset.getUntrackedParameter<std::string>("logicalFileName","")),
00259 m_file(0),
00260 m_treeHelpers(kNIndicies,boost::shared_ptr<TreeHelperBase>()),
00261 m_presentHistoryIndex(0),
00262 m_fullNameBufferPtr(&m_fullNameBuffer),
00263 m_indicesTree(0)
00264 {
00265   //NOTE: I need to also set the I/O performance settings
00266   
00267   m_file = std::auto_ptr<TFile>(new TFile(m_fileName.c_str(),"CREATE",
00268                                 "1" //This is the file format version number
00269                                 ));  
00270   
00271   edm::Service<edm::JobReport> jr;
00272   cms::Digest branchHash;
00273   m_jrToken = jr->outputFileOpened(m_fileName,
00274                                    m_logicalFileName,
00275                                    std::string(),
00276                                    "DQMRootOutputModule",
00277                                    pset.getParameter<std::string>("@module_label"),
00278                                    m_file->GetUUID().AsString(),
00279                                    std::string(),
00280                                    branchHash.digest().toString(),
00281                                    std::vector<std::string>()
00282     );
00283 
00284 
00285   m_indicesTree = new TTree(kIndicesTree,kIndicesTree);
00286   m_indicesTree->Branch(kRunBranch,&m_run);
00287   m_indicesTree->Branch(kLumiBranch,&m_lumi);
00288   m_indicesTree->Branch(kProcessHistoryIndexBranch,&m_presentHistoryIndex);
00289   m_indicesTree->Branch(kBeginTimeBranch,&m_beginTime);
00290   m_indicesTree->Branch(kEndTimeBranch,&m_endTime);
00291   m_indicesTree->Branch(kTypeBranch,&m_type);
00292   m_indicesTree->Branch(kFirstIndex,&m_firstIndex);
00293   m_indicesTree->Branch(kLastIndex,&m_lastIndex);
00294   m_indicesTree->SetDirectory(m_file.get());
00295   
00296   unsigned int i = 0;
00297   for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
00298   it != itEnd;
00299   ++it,++i) {
00300     //std::cout <<"making "<<kTypeNames[i]<<std::endl;
00301     TTree* tree = new TTree(kTypeNames[i],kTypeNames[i]);
00302     *it = boost::shared_ptr<TreeHelperBase>(makeHelper(i,tree,m_fullNameBufferPtr));
00303     tree->SetDirectory(m_file.get()); //TFile takes ownership
00304   }
00305   
00306   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_INT]=kIntIndex;
00307   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_REAL]=kFloatIndex;
00308   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_STRING]=kStringIndex;
00309   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH1F]=kTH1FIndex;
00310   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH1S]=kTH1SIndex;
00311   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH1D]=kTH1DIndex;
00312   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH2F]=kTH2FIndex;
00313   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH2S]=kTH2SIndex;
00314   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH2D]=kTH2DIndex;
00315   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH3F]=kTH3FIndex;
00316   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TPROFILE]=kTProfileIndex;
00317   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TPROFILE2D]=kTProfile2DIndex;
00318 }
00319 
00320 // DQMRootOutputModule::DQMRootOutputModule(const DQMRootOutputModule& rhs)
00321 // {
00322 //    // do actual copying here;
00323 // }
00324 
00325 DQMRootOutputModule::~DQMRootOutputModule()
00326 {
00327 }
00328 
00329 //
00330 // assignment operators
00331 //
00332 // const DQMRootOutputModule& DQMRootOutputModule::operator=(const DQMRootOutputModule& rhs)
00333 // {
00334 //   //An exception safe implementation is
00335 //   DQMRootOutputModule temp(rhs);
00336 //   swap(rhs);
00337 //
00338 //   return *this;
00339 // }
00340 
00341 //
00342 // member functions
00343 //
00344 void 
00345 DQMRootOutputModule::write(edm::EventPrincipal const& ){
00346   
00347 }
00348 void 
00349 DQMRootOutputModule::writeLuminosityBlock(edm::LuminosityBlockPrincipal const& iLumi) {
00350   edm::Service<DQMStore> dstore;
00351   m_run=iLumi.id().run();
00352   m_lumi = iLumi.id().value();
00353   m_beginTime = iLumi.beginTime().value();
00354   m_endTime = iLumi.endTime().value();
00355   
00356   std::vector<MonitorElement *> items(dstore->getAllContents(""));
00357   for(std::vector<MonitorElement*>::iterator it = items.begin(), itEnd=items.end();
00358       it!=itEnd;
00359       ++it) {
00360     if((*it)->getLumiFlag()) {
00361       std::map<unsigned int,unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((*it)->kind());
00362       assert(itFound !=m_dqmKindToTypeIndex.end());
00363       m_treeHelpers[itFound->second]->fill(*it);
00364     }
00365   }
00366   //Now store the relationship between run/lumi and indices in the other TTrees
00367   bool storedLumiIndex = false;
00368   unsigned int typeIndex = 0;
00369   for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
00370       it != itEnd;
00371       ++it,++typeIndex) {
00372     if((*it)->wasFilled()) {
00373       m_type = typeIndex;
00374       (*it)->getRangeAndReset(m_firstIndex,m_lastIndex);
00375       storedLumiIndex = true;
00376       m_indicesTree->Fill();
00377     }
00378   }
00379   if(not storedLumiIndex) {
00380     //need to record lumis even if we stored no MonitorElements since some later DQM modules
00381     // look to see what lumis were processed
00382     m_type = kNoTypesStored;
00383     m_firstIndex=0;
00384     m_lastIndex=0;
00385     m_indicesTree->Fill();
00386   }
00387   
00388   edm::Service<edm::JobReport> jr;
00389   jr->reportLumiSection(m_run,m_lumi);
00390 }
00391 
00392 void DQMRootOutputModule::writeRun(edm::RunPrincipal const& iRun){
00393   edm::Service<DQMStore> dstore;
00394   m_run=iRun.id().run();
00395   m_lumi = 0;
00396   m_beginTime = iRun.beginTime().value();
00397   m_endTime = iRun.endTime().value();
00398   
00399   std::vector<MonitorElement *> items(dstore->getAllContents(""));
00400   for(std::vector<MonitorElement*>::iterator it = items.begin(), itEnd=items.end();
00401       it!=itEnd;
00402       ++it) {
00403     if(not (*it)->getLumiFlag()) {
00404       std::map<unsigned int,unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((*it)->kind());
00405       assert  (itFound !=m_dqmKindToTypeIndex.end());
00406       m_treeHelpers[itFound->second]->fill(*it);
00407     }
00408   }
00409   
00410   //Now store the relationship between run/lumi and indices in the other TTrees
00411   unsigned int typeIndex = 0;
00412   for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
00413       it != itEnd;
00414       ++it,++typeIndex) {
00415     if((*it)->wasFilled()) {
00416       m_type = typeIndex;
00417       (*it)->getRangeAndReset(m_firstIndex,m_lastIndex);
00418       m_indicesTree->Fill();
00419     }
00420   }
00421   
00422   edm::Service<edm::JobReport> jr;
00423   jr->reportRunNumber(m_run);
00424 }
00425 
00426 void DQMRootOutputModule::beginRun(edm::RunPrincipal const& iPrincipal) {
00427   //The ProcessHistory for a lumi must be the same as its Run so we only need to 
00428   // record it at Run time
00429   edm::ProcessHistoryID id = iPrincipal.processHistoryID();
00430   std::vector<edm::ProcessHistoryID>::iterator itFind = std::find(m_seenHistories.begin(),m_seenHistories.end(),id);
00431   if(itFind == m_seenHistories.end()) {
00432     m_presentHistoryIndex = m_seenHistories.size();
00433     m_seenHistories.push_back(id);
00434   } else {
00435     m_presentHistoryIndex = itFind - m_seenHistories.begin();
00436   }
00437 }
00438 
00439 void DQMRootOutputModule::startEndFile() {
00440   //fill in the meta data
00441   m_file->cd();
00442   TDirectory* metaDataDirectory = m_file->mkdir(kMetaDataDirectory);
00443 
00444 
00445   //Write out the Process History
00446   TTree* processHistoryTree = new TTree(kProcessHistoryTree,kProcessHistoryTree);
00447   processHistoryTree->SetDirectory(metaDataDirectory);
00448   
00449   unsigned int index = 0;
00450   processHistoryTree->Branch(kPHIndexBranch,&index);
00451   std::string processName;
00452   processHistoryTree->Branch(kProcessConfigurationProcessNameBranch,&processName);
00453   std::string parameterSetID;
00454   processHistoryTree->Branch(kProcessConfigurationParameterSetIDBranch,&parameterSetID);
00455   std::string releaseVersion;
00456   processHistoryTree->Branch(kProcessConfigurationReleaseVersion,&releaseVersion);
00457   std::string passID;
00458   processHistoryTree->Branch(kProcessConfigurationPassID,&passID);
00459 
00460   edm::ProcessHistoryRegistry* phr = edm::ProcessHistoryRegistry::instance();
00461   assert(0!=phr);
00462   for(std::vector<edm::ProcessHistoryID>::iterator it = m_seenHistories.begin(), itEnd = m_seenHistories.end();
00463       it !=itEnd;
00464       ++it) {
00465     const edm::ProcessHistory* history = phr->getMapped(*it);
00466     assert(0!=history);
00467     index = 0;
00468     for(edm::ProcessHistory::collection_type::const_iterator itPC = history->begin(), itPCEnd = history->end();
00469         itPC != itPCEnd;
00470         ++itPC,++index) {
00471       processName = itPC->processName();
00472       releaseVersion = itPC->releaseVersion();
00473       passID = itPC->passID();
00474       parameterSetID = itPC->parameterSetID().compactForm();
00475       processHistoryTree->Fill();
00476     }
00477   }
00478   
00479   //Store the ParameterSets
00480   TTree* parameterSetsTree = new TTree(kParameterSetTree,kParameterSetTree);
00481   parameterSetsTree->SetDirectory(metaDataDirectory);
00482   std::string blob;
00483   parameterSetsTree->Branch(kParameterSetBranch,&blob);
00484   
00485   edm::pset::Registry* psr = edm::pset::Registry::instance();
00486   assert(0!=psr);
00487   for(edm::pset::Registry::const_iterator it = psr->begin(), itEnd = psr->end();
00488   it != itEnd;
00489   ++it) {
00490     blob.clear();
00491     it->second.toString(blob);
00492     parameterSetsTree->Fill();
00493   }
00494   
00495 }
00496 
00497 void DQMRootOutputModule::finishEndFile() {
00498   m_file->Write();
00499   m_file->Close();
00500   edm::Service<edm::JobReport> jr;
00501   jr->outputFileClosed(m_jrToken);
00502 }
00503 
00504 //
00505 // const member functions
00506 //
00507 
00508 //
00509 // static member functions
00510 //
00511 void
00512 DQMRootOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
00513   //The following says we do not know what parameters are allowed so do no validation
00514   // Please change this to state exactly what you do use, even if it is no parameters
00515   edm::ParameterSetDescription desc;
00516   desc.setUnknown();
00517   descriptions.addDefault(desc);
00518 
00519   //NOTE: when actually filling this in, do not forget to add a untracked PSet 'dataset'
00520   // which is used for bookkeeping by the DMWM
00521 }
00522 
00523 
00524 DEFINE_FWK_MODULE(DQMRootOutputModule);