CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     FwkIO
00004 // Class  :     DQMRootSource
00005 // 
00006 // Implementation:
00007 //     [Notes on implementation]
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Tue May  3 11:13:47 CDT 2011
00011 // $Id: DQMRootSource.cc,v 1.22 2011/07/11 07:46:20 chrjones Exp $
00012 //
00013 
00014 // system include files
00015 #include <vector>
00016 #include <string>
00017 #include <map>
00018 #include <list>
00019 #include <set>
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/InputSource.h"
00029 #include "FWCore/Catalog/interface/InputFileCatalog.h"
00030 #include "FWCore/ParameterSet/interface/ParameterSet.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/MessageLogger/interface/JobReport.h"
00035 //#include "FWCore/Utilities/interface/GlobalIdentifier.h"
00036 
00037 #include "FWCore/Framework/interface/RunPrincipal.h"
00038 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00039 
00040 #include "FWCore/Framework/interface/Run.h"
00041 #include "FWCore/Framework/interface/LuminosityBlock.h"
00042 
00043 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00044 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00045 
00046 #include "FWCore/Framework/interface/InputSourceMacros.h"
00047 #include "FWCore/Framework/interface/FileBlock.h"
00048 
00049 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00050 
00051 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00052 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00053 #include "FWCore/ParameterSet/interface/Registry.h"
00054 
00055 #include "FWCore/Utilities/interface/Digest.h"
00056 
00057 #include "format.h"
00058 
00059 namespace {
00060   //adapter functions
00061   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH1F* iHist) {
00062     //std::cout <<"create: hist size "<<iName <<" "<<iHist->GetEffectiveEntries()<<std::endl;
00063     return iStore.book1D(iName, iHist);
00064   }
00065   //NOTE: the merge logic comes from DataFormats/Histograms/interface/MEtoEDMFormat.h
00066   void mergeTogether(TH1* iOriginal,TH1* iToAdd) {
00067     if(iOriginal->TestBit(TH1::kCanRebin)==true && iToAdd->TestBit(TH1::kCanRebin) ==true) {
00068       TList list;
00069       list.Add(iToAdd);
00070       if( -1 == iOriginal->Merge(&list)) {
00071         edm::LogError("MergeFailure")<<"Failed to merge DQM element "<<iOriginal->GetName();
00072       }
00073     } else {
00074       if (iOriginal->GetNbinsX() == iToAdd->GetNbinsX() &&
00075           iOriginal->GetXaxis()->GetXmin() == iToAdd->GetXaxis()->GetXmin() &&
00076           iOriginal->GetXaxis()->GetXmax() == iToAdd->GetXaxis()->GetXmax() &&
00077           iOriginal->GetNbinsY() == iToAdd->GetNbinsY() &&
00078           iOriginal->GetYaxis()->GetXmin() == iToAdd->GetYaxis()->GetXmin() &&
00079           iOriginal->GetYaxis()->GetXmax() == iToAdd->GetYaxis()->GetXmax() &&
00080           iOriginal->GetNbinsZ() == iToAdd->GetNbinsZ() &&
00081           iOriginal->GetZaxis()->GetXmin() == iToAdd->GetZaxis()->GetXmin() &&
00082           iOriginal->GetZaxis()->GetXmax() == iToAdd->GetZaxis()->GetXmax()) {
00083           iOriginal->Add(iToAdd);
00084       } else {
00085         edm::LogError("MergeFailure")<<"Found histograms with different axis limitsm '"<<iOriginal->GetName()<<"' not merged.";
00086       }
00087     } 
00088   }
00089   void mergeWithElement(MonitorElement* iElement, TH1F* iHist) {
00090     //std::cout <<"merge: hist size "<<iElement->getName() <<" "<<iHist->GetEffectiveEntries()<<std::endl;
00091     mergeTogether(iElement->getTH1F(),iHist);
00092   }
00093   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH1S* iHist) {
00094     return iStore.book1S(iName, iHist);
00095   }
00096   void mergeWithElement(MonitorElement* iElement, TH1S* iHist) {
00097     mergeTogether(iElement->getTH1S(),iHist);
00098   }  
00099   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH1D* iHist) {
00100     return iStore.book1DD(iName, iHist);
00101   }
00102   void mergeWithElement(MonitorElement* iElement, TH1D* iHist) {
00103     mergeTogether(iElement->getTH1D(),iHist);
00104   }
00105   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH2F* iHist) {
00106     return iStore.book2D(iName, iHist);
00107   }
00108   void mergeWithElement(MonitorElement* iElement, TH2F* iHist) {
00109     mergeTogether(iElement->getTH2F(),iHist);
00110   }
00111   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH2S* iHist) {
00112     return iStore.book2S(iName, iHist);
00113   }
00114   void mergeWithElement(MonitorElement* iElement, TH2S* iHist) {
00115     mergeTogether(iElement->getTH2S(),iHist);
00116   }  
00117   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH2D* iHist) {
00118     return iStore.book2DD(iName, iHist);
00119   }
00120   void mergeWithElement(MonitorElement* iElement, TH2D* iHist) {
00121     mergeTogether(iElement->getTH2D(),iHist);
00122   }
00123   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH3F* iHist) {
00124     return iStore.book3D(iName, iHist);
00125   }
00126   void mergeWithElement(MonitorElement* iElement, TH3F* iHist) {
00127     mergeTogether(iElement->getTH3F(),iHist);
00128   }
00129   MonitorElement* createElement(DQMStore& iStore, const char* iName, TProfile* iHist) {
00130     return iStore.bookProfile(iName, iHist);
00131   }
00132   void mergeWithElement(MonitorElement* iElement, TProfile* iHist) {
00133     mergeTogether(iElement->getTProfile(),iHist);
00134   }
00135   MonitorElement* createElement(DQMStore& iStore, const char* iName, TProfile2D* iHist) {
00136     return iStore.bookProfile2D(iName, iHist);
00137   }
00138   void mergeWithElement(MonitorElement* iElement, TProfile2D* iHist) {
00139     mergeTogether(iElement->getTProfile2D(),iHist);
00140   }
00141 
00142   MonitorElement* createElement(DQMStore& iStore, const char* iName, Long64_t& iValue) {
00143     MonitorElement* e = iStore.bookInt(iName);
00144     e->Fill(iValue);
00145     return e;
00146   }
00147   
00148   //NOTE: the merge logic comes from DataFormats/Histograms/interface/MEtoEDMFormat.h
00149   void mergeWithElement(MonitorElement* iElement, Long64_t& iValue) {
00150     const std::string& name = iElement->getFullname();
00151     if(name.find("EventInfo/processedEvents") != std::string::npos) {
00152       iElement->Fill(iValue+iElement->getIntValue());
00153     } else {
00154       if(name.find("EventInfo/iEvent") != std::string::npos ||
00155          name.find("EventInfo/iLumiSection") != std::string::npos) {
00156         if(iValue > iElement->getIntValue()) {
00157              iElement->Fill(iValue);
00158         }
00159       }
00160     }
00161   }
00162 
00163   MonitorElement* createElement(DQMStore& iStore, const char* iName, double& iValue) {
00164     MonitorElement* e = iStore.bookFloat(iName);
00165     e->Fill(iValue);
00166     return e;
00167   }
00168   void mergeWithElement(MonitorElement* iElement, double& iValue) {
00169     //no merging    
00170   }
00171   MonitorElement* createElement(DQMStore& iStore, const char* iName, std::string* iValue) {
00172     return iStore.bookString(iName,*iValue);
00173   }
00174   void mergeWithElement(MonitorElement* , std::string* ) {
00175     //no merging    
00176   }
00177   
00178   void splitName(const std::string& iFullName, std::string& oPath,const char*& oName) {
00179     oPath = iFullName;
00180     size_t index = oPath.find_last_of('/');
00181     if(index == std::string::npos) {
00182       oPath = std::string();
00183       oName = iFullName.c_str();
00184     } else {
00185       oPath.resize(index);
00186       oName = iFullName.c_str()+index+1;
00187     }
00188   }
00189   
00190   struct RunLumiToRange { 
00191     unsigned int m_run, m_lumi,m_historyIDIndex;
00192     ULong64_t m_beginTime;
00193     ULong64_t m_endTime;
00194     ULong64_t m_firstIndex, m_lastIndex; //last is inclusive
00195     unsigned int m_type; //A value in TypeIndex 
00196   };
00197   
00198   class TreeReaderBase {
00199   public:
00200     TreeReaderBase() {}
00201     virtual ~TreeReaderBase() {}
00202     
00203     MonitorElement* read(ULong64_t iIndex, DQMStore& iStore, bool iIsLumi){
00204       return doRead(iIndex,iStore,iIsLumi);
00205     }
00206     virtual void setTree(TTree* iTree) =0;
00207   protected:
00208     TTree* m_tree;
00209   private:
00210     virtual MonitorElement* doRead(ULong64_t iIndex, DQMStore& iStore, bool iIsLumi)=0;
00211   };
00212   
00213   template<class T>
00214   class TreeObjectReader: public TreeReaderBase {
00215   public:
00216     TreeObjectReader():m_tree(0),m_fullName(0),m_buffer(0),m_tag(0){
00217     }
00218     virtual MonitorElement* doRead(ULong64_t iIndex, DQMStore& iStore, bool iIsLumi) {
00219       m_tree->GetEntry(iIndex);
00220       MonitorElement* element = iStore.get(*m_fullName);
00221       if(0 == element) {
00222         std::string path;
00223         const char* name;
00224         splitName(*m_fullName, path,name);
00225         iStore.setCurrentFolder(path);
00226          element = createElement(iStore,name,m_buffer);
00227         if(iIsLumi) { element->setLumiFlag();}
00228       } else {
00229         mergeWithElement(element,m_buffer);
00230       }
00231       if(0!= m_tag) {
00232         iStore.tag(element,m_tag);
00233       }
00234       return element;
00235     }
00236     virtual void setTree(TTree* iTree)  {
00237       m_tree = iTree;
00238       m_tree->SetBranchAddress(kFullNameBranch,&m_fullName);
00239       m_tree->SetBranchAddress(kFlagBranch,&m_tag);
00240       m_tree->SetBranchAddress(kValueBranch,&m_buffer);
00241     }
00242   private:
00243     TTree* m_tree;
00244     std::string* m_fullName;
00245     T* m_buffer;
00246     uint32_t m_tag;
00247   };
00248   
00249   template<class T>
00250   class TreeSimpleReader : public TreeReaderBase {
00251   public:
00252     TreeSimpleReader():m_tree(0),m_fullName(0),m_buffer(),m_tag(0){
00253     }
00254     virtual MonitorElement* doRead(ULong64_t iIndex, DQMStore& iStore,bool iIsLumi) {
00255       m_tree->GetEntry(iIndex);
00256       MonitorElement* element = iStore.get(*m_fullName);
00257       if(0 == element) {
00258         std::string path;
00259         const char* name;
00260         splitName(*m_fullName, path,name);
00261         iStore.setCurrentFolder(path);
00262         element = createElement(iStore,name,m_buffer);
00263         if(iIsLumi) { element->setLumiFlag();}
00264       } else {
00265         mergeWithElement(element, m_buffer);
00266       }
00267       if(0!=m_tag) {
00268         iStore.tag(element,m_tag);
00269       }
00270       return element;
00271     }
00272     virtual void setTree(TTree* iTree)  {
00273       m_tree = iTree;
00274       m_tree->SetBranchAddress(kFullNameBranch,&m_fullName);
00275       m_tree->SetBranchAddress(kFlagBranch,&m_tag);
00276       m_tree->SetBranchAddress(kValueBranch,&m_buffer);
00277     }
00278   private:
00279     TTree* m_tree;
00280     std::string* m_fullName;
00281     T m_buffer;
00282     uint32_t m_tag;
00283   };
00284   
00285 }
00286 
00287 class DQMRootSource : public edm::InputSource
00288 {
00289 
00290    public:
00291       DQMRootSource(edm::ParameterSet const&, const edm::InputSourceDescription&);
00292       virtual ~DQMRootSource();
00293 
00294       // ---------- const member functions ---------------------
00295 
00296       // ---------- static member functions --------------------
00297 
00298       // ---------- member functions ---------------------------
00299       static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
00300    protected:
00301      virtual void endLuminosityBlock(edm::LuminosityBlock&);
00302      virtual void endRun(edm::Run&);
00303      
00304    private:
00305       DQMRootSource(const DQMRootSource&); // stop default
00306 
00307       virtual edm::InputSource::ItemType getNextItemType();
00308       //NOTE: the following is really read next run auxiliary
00309       virtual boost::shared_ptr<edm::RunAuxiliary> readRunAuxiliary_() ;
00310       virtual boost::shared_ptr<edm::LuminosityBlockAuxiliary> readLuminosityBlockAuxiliary_() ;
00311       virtual boost::shared_ptr<edm::RunPrincipal> readRun_(boost::shared_ptr<edm::RunPrincipal> rpCache);
00312       virtual boost::shared_ptr<edm::LuminosityBlockPrincipal> readLuminosityBlock_( boost::shared_ptr<edm::LuminosityBlockPrincipal> lbCache);
00313       virtual edm::EventPrincipal* readEvent_() ;
00314       
00315       virtual boost::shared_ptr<edm::FileBlock> readFile_();
00316       virtual void closeFile_();
00317       
00318       void readNextItemType();
00319       void setupFile(unsigned int iIndex);
00320       void readElements();
00321       
00322       const DQMRootSource& operator=(const DQMRootSource&); // stop default
00323 
00324       // ---------- member data --------------------------------
00325       edm::InputFileCatalog m_catalog;
00326       edm::RunAuxiliary m_runAux;
00327       edm::LuminosityBlockAuxiliary m_lumiAux;
00328       edm::InputSource::ItemType m_nextItemType;
00329 
00330       size_t m_fileIndex;
00331       std::list<unsigned int>::iterator m_nextIndexItr;
00332       std::list<unsigned int>::iterator m_presentIndexItr;
00333       std::vector<RunLumiToRange> m_runlumiToRange;
00334       std::auto_ptr<TFile> m_file;
00335       std::vector<TTree*> m_trees;
00336       std::vector<boost::shared_ptr<TreeReaderBase> > m_treeReaders;
00337       
00338       std::list<unsigned int> m_orderedIndices;
00339       unsigned int m_lastSeenRun;
00340       bool m_justOpenedFileSoNeedToGenerateRunTransition;
00341       bool m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating;
00342       std::set<MonitorElement*> m_lumiElements;
00343       std::set<MonitorElement*> m_runElements;
00344       std::vector<edm::ProcessHistoryID> m_historyIDs;
00345       
00346       edm::JobReport::Token m_jrToken;
00347 };
00348 
00349 //
00350 // constants, enums and typedefs
00351 //
00352 
00353 //
00354 // static data member definitions
00355 //
00356 
00357 void 
00358 DQMRootSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
00359   edm::ParameterSetDescription desc;
00360   desc.addUntracked<std::vector<std::string> >("fileNames")
00361     ->setComment("Names of files to be processed.");
00362   desc.addUntracked<std::string>("overrideCatalog",std::string())
00363     ->setComment("An alternate file catalog to use instead of the standard site one.");
00364   descriptions.addDefault(desc);
00365 }
00366 //
00367 // constructors and destructor
00368 //
00369 DQMRootSource::DQMRootSource(edm::ParameterSet const& iPSet, const edm::InputSourceDescription& iDesc):
00370 edm::InputSource(iPSet,iDesc),
00371 m_catalog(iPSet.getUntrackedParameter<std::vector<std::string> >("fileNames"), 
00372           iPSet.getUntrackedParameter<std::string>("overrideCatalog")),
00373 m_nextItemType(edm::InputSource::IsFile),
00374 m_fileIndex(0),
00375 m_trees(kNIndicies,static_cast<TTree*>(0)),
00376 m_treeReaders(kNIndicies,boost::shared_ptr<TreeReaderBase>()),
00377 m_lastSeenRun(0),
00378 m_justOpenedFileSoNeedToGenerateRunTransition(false),
00379 m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating(false)
00380 {
00381   if(m_fileIndex ==m_catalog.fileNames().size()) {
00382     m_nextItemType=edm::InputSource::IsStop;
00383   } else{
00384     m_treeReaders[kIntIndex].reset(new TreeSimpleReader<Long64_t>());
00385     m_treeReaders[kFloatIndex].reset(new TreeSimpleReader<double>());
00386     m_treeReaders[kStringIndex].reset(new TreeObjectReader<std::string>());
00387     m_treeReaders[kTH1FIndex].reset(new TreeObjectReader<TH1F>());
00388     m_treeReaders[kTH1SIndex].reset(new TreeObjectReader<TH1S>());
00389     m_treeReaders[kTH1DIndex].reset(new TreeObjectReader<TH1D>());
00390     m_treeReaders[kTH2FIndex].reset(new TreeObjectReader<TH2F>());
00391     m_treeReaders[kTH2SIndex].reset(new TreeObjectReader<TH2S>());
00392     m_treeReaders[kTH2DIndex].reset(new TreeObjectReader<TH2D>());
00393     m_treeReaders[kTH3FIndex].reset(new TreeObjectReader<TH3F>());
00394     m_treeReaders[kTProfileIndex].reset(new TreeObjectReader<TProfile>());
00395     m_treeReaders[kTProfile2DIndex].reset(new TreeObjectReader<TProfile2D>());
00396   }
00397   
00398 }
00399 
00400 // DQMRootSource::DQMRootSource(const DQMRootSource& rhs)
00401 // {
00402 //    // do actual copying here;
00403 // }
00404 
00405 DQMRootSource::~DQMRootSource()
00406 {
00407 }
00408 
00409 //
00410 // assignment operators
00411 //
00412 // const DQMRootSource& DQMRootSource::operator=(const DQMRootSource& rhs)
00413 // {
00414 //   //An exception safe implementation is
00415 //   DQMRootSource temp(rhs);
00416 //   swap(rhs);
00417 //
00418 //   return *this;
00419 // }
00420 
00421 //
00422 // member functions
00423 //
00424 namespace {
00425   struct no_deleter {
00426     void operator()(void*) {}
00427   };
00428 }
00429 
00430 edm::EventPrincipal*
00431 DQMRootSource::readEvent_() 
00432 {
00433   return 0;
00434 }
00435 
00436 edm::InputSource::ItemType 
00437 DQMRootSource::getNextItemType()
00438 {
00439   //std::cout <<"getNextItemType "<<m_nextItemType<<std::endl;
00440   return m_nextItemType;
00441 }
00442 boost::shared_ptr<edm::RunAuxiliary> 
00443 DQMRootSource::readRunAuxiliary_()
00444 {
00445   //std::cout <<"readRunAuxiliary_"<<std::endl;
00446   assert(m_nextIndexItr != m_orderedIndices.end());
00447   unsigned int index = *m_nextIndexItr;
00448   RunLumiToRange runLumiRange = m_runlumiToRange[index];
00449   //NOTE: this could be a lumi instead of the actual run. We need to find the time for the run
00450   // so we will scan forward
00451   while(runLumiRange.m_lumi !=0 && ++index<m_runlumiToRange.size()) {
00452     const RunLumiToRange& next = m_runlumiToRange[index];
00453     if(runLumiRange.m_run == next.m_run) {
00454       runLumiRange = next;
00455     } else {
00456       break;
00457     }
00458   }
00459 
00460   //NOTE: the setBeginTime and setEndTime functions of RunAuxiliary only work if the previous value was invalid
00461   // therefore we must copy
00462   m_runAux = edm::RunAuxiliary(runLumiRange.m_run,edm::Timestamp(runLumiRange.m_beginTime),edm::Timestamp(runLumiRange.m_endTime));
00463   assert(m_historyIDs.size() > runLumiRange.m_historyIDIndex);
00464   //std::cout <<"readRunAuxiliary_ "<<m_historyIDs[runLumiRange.m_historyIDIndex]<<std::endl;
00465   m_runAux.setProcessHistoryID(m_historyIDs[runLumiRange.m_historyIDIndex]);    
00466   return boost::shared_ptr<edm::RunAuxiliary>( new edm::RunAuxiliary(m_runAux) );
00467 }
00468 boost::shared_ptr<edm::LuminosityBlockAuxiliary> 
00469 DQMRootSource::readLuminosityBlockAuxiliary_()
00470 {
00471   //std::cout <<"readLuminosityBlockAuxiliary_"<<std::endl;
00472   assert(m_nextIndexItr != m_orderedIndices.end());
00473   const RunLumiToRange runLumiRange = m_runlumiToRange[*m_nextIndexItr];
00474   m_lumiAux = edm::LuminosityBlockAuxiliary(edm::LuminosityBlockID(runLumiRange.m_run,runLumiRange.m_lumi),
00475                                             edm::Timestamp(runLumiRange.m_beginTime),
00476                                             edm::Timestamp(runLumiRange.m_endTime));
00477   assert(m_historyIDs.size() > runLumiRange.m_historyIDIndex);
00478   //std::cout <<"lumi "<<m_lumiAux.beginTime().value()<<" "<<runLumiRange.m_beginTime<<std::endl;
00479   m_lumiAux.setProcessHistoryID(m_historyIDs[runLumiRange.m_historyIDIndex]);    
00480   
00481   return boost::shared_ptr<edm::LuminosityBlockAuxiliary>(new edm::LuminosityBlockAuxiliary(m_lumiAux));
00482 }
00483 boost::shared_ptr<edm::RunPrincipal> 
00484 DQMRootSource::readRun_(boost::shared_ptr<edm::RunPrincipal> rpCache) 
00485 {
00486   m_justOpenedFileSoNeedToGenerateRunTransition = false;
00487   unsigned int runID =rpCache->id().run();
00488   unsigned int lastRunID = m_lastSeenRun;
00489   m_lastSeenRun = runID;
00490   readNextItemType();
00491   //std::cout <<"readRun_"<<std::endl;
00492   
00493   //NOTE: need to reset all run elements at this point
00494   if(lastRunID != runID) {
00495     for(std::set<MonitorElement*>::iterator it = m_runElements.begin(), itEnd = m_runElements.end();
00496         it != itEnd;
00497         ++it) {
00498           //std::cout <<"RESETTING "<<(*it)->getName()<<std::endl;
00499           (*it)->Reset();        
00500     }
00501   }
00502 
00503   rpCache->addToProcessHistory();
00504 
00505   if(m_presentIndexItr != m_orderedIndices.end()) {
00506     RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00507     //NOTE: it is possible to have an Run when all we have stored is lumis
00508     if(runLumiRange.m_lumi == 0 && 
00509        runLumiRange.m_run == rpCache->id().run()) {
00510       readElements();
00511     }
00512   }
00513   
00514   edm::Service<edm::JobReport> jr;
00515   jr->reportInputRunNumber(rpCache->id().run());
00516   return rpCache;
00517 }
00518 boost::shared_ptr<edm::LuminosityBlockPrincipal> 
00519 DQMRootSource::readLuminosityBlock_( boost::shared_ptr<edm::LuminosityBlockPrincipal> lbCache) 
00520 {
00521   //NOTE: need to reset all lumi block elements at this point
00522   for(std::set<MonitorElement*>::iterator it = m_lumiElements.begin(), itEnd = m_lumiElements.end();
00523       it != itEnd;
00524       ++it) {
00525         //std::cout <<"RESETTING "<<(*it)->getName()<<std::endl;      
00526       (*it)->Reset();
00527   }
00528   readNextItemType();
00529   //std::cout <<"readLuminosityBlock_"<<std::endl;
00530   RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00531   if(runLumiRange.m_run == lbCache->id().run() &&
00532      runLumiRange.m_lumi == lbCache->id().luminosityBlock()) {
00533        readElements();
00534   }
00535   
00536   edm::Service<edm::JobReport> jr;
00537   jr->reportInputLumiSection(lbCache->id().run(),lbCache->id().luminosityBlock());
00538   
00539   return lbCache;
00540 }
00541 
00542 boost::shared_ptr<edm::FileBlock>
00543 DQMRootSource::readFile_() {
00544   //std::cout <<"readFile_"<<std::endl;
00545   setupFile(m_fileIndex);
00546   ++m_fileIndex;
00547   readNextItemType();
00548 
00549   edm::Service<edm::JobReport> jr;
00550   m_jrToken = jr->inputFileOpened(m_catalog.fileNames()[m_fileIndex-1],
00551                                   m_catalog.logicalFileNames()[m_fileIndex-1],
00552                                   std::string(),
00553                                   std::string(),
00554                                   "DQMRootSource",
00555                                   "source",
00556                                   m_file->GetUUID().AsString(),//edm::createGlobalIdentifier(),
00557                                   std::vector<std::string>()
00558                                   );
00559   
00560   m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating = false;
00561   return boost::shared_ptr<edm::FileBlock>(new edm::FileBlock);
00562 }
00563 
00564 
00565 void 
00566 DQMRootSource::endLuminosityBlock(edm::LuminosityBlock& iLumi) {
00567   //std::cout <<"DQMRootSource::endLumi"<<std::endl;
00568 }
00569 void 
00570 DQMRootSource::endRun(edm::Run& iRun){
00571   //std::cout <<"DQMRootSource::endRun"<<std::endl;
00572   //NOTE: the framework will call endRun before closeFile in the case
00573   // where the frameworks is terminating
00574   m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating=true;
00575 }
00576 
00577 
00578 void
00579 DQMRootSource::closeFile_() {
00580   //std::cout <<"closeFile_"<<std::endl;
00581   //when going from one file to the next the framework does not call
00582   // 'endRun' or 'endLumi' until it looks to see if the other file contains
00583   // a new run or lumi. If the other file doesn't then  
00584   if(not m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating) {
00585     while(m_presentIndexItr != m_orderedIndices.end()) {
00586       readElements();
00587     }
00588   }
00589   edm::Service<edm::JobReport> jr;
00590   jr->inputFileClosed(m_jrToken);
00591 }
00592 
00593 void 
00594 DQMRootSource::readElements() {
00595   edm::Service<DQMStore> store;
00596   RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00597   bool shouldContinue = false;
00598   do {
00599     shouldContinue = false;
00600     if(runLumiRange.m_type == kNoTypesStored) {continue;}
00601     boost::shared_ptr<TreeReaderBase> reader = m_treeReaders[runLumiRange.m_type];
00602     for(ULong64_t index = runLumiRange.m_firstIndex, endIndex=runLumiRange.m_lastIndex+1;
00603     index != endIndex;
00604     ++index) {
00605       bool isLumi = runLumiRange.m_lumi !=0;
00606       MonitorElement* element = reader->read(index,*store,isLumi);
00607       if(isLumi) {
00608         //std::cout <<"  lumi element "<< element->getName()<<" "<<index<<std::endl;
00609         m_lumiElements.insert(element);
00610       } else {
00611         //std::cout <<"  run element "<< element->getName()<<" "<<index<<std::endl;
00612         m_runElements.insert(element);
00613       }
00614     }
00615     ++m_presentIndexItr;
00616     if(m_presentIndexItr != m_orderedIndices.end()) {
00617       //are there more parts to this same run/lumi?
00618       const RunLumiToRange nextRunLumiRange = m_runlumiToRange[*m_presentIndexItr];
00619       //continue to the next item if that item is either
00620       if( (nextRunLumiRange.m_run == runLumiRange.m_run) && 
00621           (nextRunLumiRange.m_lumi == runLumiRange.m_lumi) ) {
00622            shouldContinue= true;
00623            runLumiRange = nextRunLumiRange;
00624       } 
00625     }
00626   }while(shouldContinue);
00627 }
00628 
00629 
00630 void 
00631 DQMRootSource::readNextItemType()
00632 {
00633   //Do the work of actually figuring out where next to go
00634   RunLumiToRange runLumiRange = m_runlumiToRange[*m_nextIndexItr];
00635   if(m_nextItemType !=edm::InputSource::IsFile) {
00636     assert(m_nextIndexItr != m_orderedIndices.end());
00637 
00638     if(runLumiRange.m_lumi ==0) {
00639       //std::cout <<"reading run "<<runLumiRange.m_run<<std::endl;
00640       m_runAux.id() = edm::RunID(runLumiRange.m_run);    
00641     } else {
00642       if(m_nextItemType == edm::InputSource::IsRun) {
00643         //std::cout <<" proceeding with dummy run";
00644         m_nextItemType = edm::InputSource::IsLumi;
00645         return;
00646       }
00647       //std::cout <<"reading lumi "<<runLumiRange.m_run<<","<<runLumiRange.m_lumi<<std::endl;
00648       m_lumiAux.id() = edm::LuminosityBlockID(runLumiRange.m_run,runLumiRange.m_lumi);
00649     }
00650     ++m_nextIndexItr;
00651   } else {
00652     //NOTE: the following causes the iterator to move to before 'begin' but that is OK
00653     // since the first thing in the 'do while' loop is to advance the iterator which puts
00654     // us at the first entry in the file
00655     runLumiRange.m_run=0;
00656   } 
00657   
00658   bool shouldContinue = false;
00659   do {
00660     shouldContinue = false;
00661     if(m_nextIndexItr == m_orderedIndices.end()) {
00662       //go to next file
00663       m_nextItemType = edm::InputSource::IsFile;
00664       //std::cout <<"going to next file"<<std::endl;
00665       if(m_fileIndex == m_catalog.fileNames().size()) {
00666         m_nextItemType = edm::InputSource::IsStop;
00667       }       
00668       break;
00669     }
00670     const RunLumiToRange nextRunLumiRange = m_runlumiToRange[*m_nextIndexItr];
00671     //continue to the next item if that item is the same run or lumi as we just did
00672     if( (nextRunLumiRange.m_run == runLumiRange.m_run) && (
00673          nextRunLumiRange.m_lumi == runLumiRange.m_lumi) ) {
00674          shouldContinue= true;
00675          runLumiRange = nextRunLumiRange;
00676          ++m_nextIndexItr;
00677          //std::cout <<"  advancing " <<nextRunLumiRange.m_run<<" "<<nextRunLumiRange.m_lumi<<std::endl;
00678     } 
00679     
00680   } while(shouldContinue);
00681   
00682   if(m_nextIndexItr != m_orderedIndices.end()) {
00683     if(m_runlumiToRange[*m_nextIndexItr].m_lumi == 0 && (m_justOpenedFileSoNeedToGenerateRunTransition || m_lastSeenRun != m_runlumiToRange[*m_nextIndexItr].m_run) ) {
00684       m_nextItemType = edm::InputSource::IsRun;
00685       //std::cout <<"  next is run"<<std::endl;
00686     } else {
00687       if(m_runlumiToRange[*m_nextIndexItr].m_run != m_lastSeenRun || m_justOpenedFileSoNeedToGenerateRunTransition ) {
00688         //we have to create a dummy Run since we switched to a lumi in a new run
00689         //std::cout <<"  next is dummy run "<<m_justOpenedFileSoNeedToGenerateRunTransition<<std::endl;
00690         m_nextItemType = edm::InputSource::IsRun;
00691       } else {
00692         m_nextItemType = edm::InputSource::IsLumi;      
00693       }
00694     }
00695   }
00696 }
00697 
00698 void 
00699 DQMRootSource::setupFile(unsigned int iIndex)
00700 {
00701   
00702   m_file = std::auto_ptr<TFile>(TFile::Open(m_catalog.fileNames()[iIndex].c_str()));
00703   
00704   //Check file format version, which is encoded in the Title of the TFile
00705   assert(0==strcmp(m_file->GetTitle(),"1"));
00706   
00707   //Get meta Data
00708   TDirectory* metaDir = m_file->GetDirectory(kMetaDataDirectoryAbsolute);
00709   assert(0!=metaDir);
00710   TTree* parameterSetTree = dynamic_cast<TTree*>(metaDir->Get(kParameterSetTree));
00711   assert(0!=parameterSetTree);
00712   
00713   edm::pset::Registry* psr = edm::pset::Registry::instance();
00714   assert(0!=psr);
00715   {
00716     std::string blob;
00717     std::string* pBlob = &blob;
00718     parameterSetTree->SetBranchAddress(kParameterSetBranch,&pBlob);
00719     for(unsigned int index = 0; index != parameterSetTree->GetEntries();++index) {
00720       parameterSetTree->GetEntry(index);
00721       cms::Digest dg(blob);
00722       edm::ParameterSetID psID(dg.digest().toString());
00723       edm::ParameterSet temp(blob,psID);
00724     } 
00725   }
00726 
00727   {
00728     TTree* processHistoryTree = dynamic_cast<TTree*>(metaDir->Get(kProcessHistoryTree));
00729     assert(0!=processHistoryTree);
00730     unsigned int phIndex = 0;
00731     processHistoryTree->SetBranchAddress(kPHIndexBranch,&phIndex);
00732     std::string processName;
00733     std::string* pProcessName = &processName;
00734     processHistoryTree->SetBranchAddress(kProcessConfigurationProcessNameBranch,&pProcessName);
00735     std::string parameterSetIDBlob;
00736     std::string* pParameterSetIDBlob = &parameterSetIDBlob;
00737     processHistoryTree->SetBranchAddress(kProcessConfigurationParameterSetIDBranch,&pParameterSetIDBlob);
00738     std::string releaseVersion;
00739     std::string* pReleaseVersion = &releaseVersion;
00740     processHistoryTree->SetBranchAddress(kProcessConfigurationReleaseVersion,&pReleaseVersion);
00741     std::string passID;
00742     std::string* pPassID = &passID;
00743     processHistoryTree->SetBranchAddress(kProcessConfigurationPassID,&pPassID);
00744 
00745     edm::ProcessConfigurationRegistry* pcr = edm::ProcessConfigurationRegistry::instance();
00746     assert(0!=pcr);
00747     edm::ProcessHistoryRegistry* phr = edm::ProcessHistoryRegistry::instance();
00748     assert(0!=phr);
00749     std::vector<edm::ProcessConfiguration> configs;
00750     configs.reserve(5);
00751     for(unsigned int i=0; i != processHistoryTree->GetEntries(); ++i) {
00752       processHistoryTree->GetEntry();
00753       if(phIndex==0) {
00754         if(not configs.empty()) {
00755           edm::ProcessHistory ph(configs);
00756           m_historyIDs.push_back(ph.id());
00757           phr->insertMapped(ph);
00758         }
00759         configs.clear();
00760       }
00761       edm::ParameterSetID psetID(parameterSetIDBlob);
00762       edm::ProcessConfiguration pc(processName, psetID,releaseVersion,passID);
00763       pcr->insertMapped(pc);
00764       configs.push_back(pc);
00765     }
00766     if(not configs.empty()) {
00767       edm::ProcessHistory ph(configs);
00768       m_historyIDs.push_back(ph.id());
00769       phr->insertMapped( ph);
00770       //std::cout <<"inserted "<<ph.id()<<std::endl;
00771     }
00772   }
00773   
00774   //Setup the indices
00775   TTree* indicesTree = dynamic_cast<TTree*>(m_file->Get(kIndicesTree));
00776   assert(0!=indicesTree);
00777   
00778   m_runlumiToRange.clear();
00779   m_runlumiToRange.reserve(indicesTree->GetEntries());
00780   m_orderedIndices.clear();
00781 
00782   RunLumiToRange temp;
00783   indicesTree->SetBranchAddress(kRunBranch,&temp.m_run);
00784   indicesTree->SetBranchAddress(kLumiBranch,&temp.m_lumi);
00785   indicesTree->SetBranchAddress(kBeginTimeBranch,&temp.m_beginTime);
00786   indicesTree->SetBranchAddress(kEndTimeBranch,&temp.m_endTime);
00787   indicesTree->SetBranchAddress(kProcessHistoryIndexBranch,&temp.m_historyIDIndex);
00788   indicesTree->SetBranchAddress(kTypeBranch,&temp.m_type);
00789   indicesTree->SetBranchAddress(kFirstIndex,&temp.m_firstIndex);
00790   indicesTree->SetBranchAddress(kLastIndex,&temp.m_lastIndex);
00791 
00792   //Need to reorder items since if there was a merge done the same  Run and/or Lumi can appear multiple times
00793   // but we want to process them all at once
00794   
00795   //We use a std::list for m_orderedIndices since inserting into the middle of a std::list does not 
00796   // disrupt the iterators to already existing entries
00797   
00798   //The Map is used to see if a Run/Lumi pair has appeared before
00799   typedef std::map<std::pair<unsigned int, unsigned int>, std::list<unsigned int>::iterator > RunLumiToLastEntryMap;
00800   RunLumiToLastEntryMap runLumiToLastEntryMap;
00801   
00802   //Need to group all lumis for the same run together and move the run entry to the beginning
00803   typedef std::map<unsigned int, std::pair<std::list<unsigned int>::iterator,std::list<unsigned int>::iterator> > RunToFirstLastEntryMap;
00804   RunToFirstLastEntryMap runToFirstLastEntryMap;
00805   
00806   for(Long64_t index = 0; index != indicesTree->GetEntries();++index) {
00807     indicesTree->GetEntry(index);
00808     //std::cout <<"read r:"<<temp.m_run<<" l:"<<temp.m_lumi<<" b:"<<temp.m_beginTime<<" e:"<<temp.m_endTime<<std::endl;
00809     m_runlumiToRange.push_back(temp);
00810     
00811     std::pair<unsigned int, unsigned int> runLumi(temp.m_run,temp.m_lumi);
00812     
00813     RunLumiToLastEntryMap::iterator itFind = runLumiToLastEntryMap.find(runLumi);
00814     if(itFind == runLumiToLastEntryMap.end()) {
00815       //does not already exist
00816 
00817       //does the run for this already exist?
00818       std::list<unsigned int>::iterator itLastOfRun = m_orderedIndices.end();
00819       RunToFirstLastEntryMap::iterator itRunFirstLastEntryFind = runToFirstLastEntryMap.find(temp.m_run);
00820       bool needNewEntryInRunFirstLastEntryMap = true;
00821       if(itRunFirstLastEntryFind != runToFirstLastEntryMap.end()) {
00822         needNewEntryInRunFirstLastEntryMap=false;
00823         if(temp.m_lumi!=0) {
00824           //lumis go to the end
00825           itLastOfRun = itRunFirstLastEntryFind->second.second;
00826           //we want to insert after this one so must advanced the iterator
00827           ++itLastOfRun;
00828         } else {
00829           //runs go at the beginning
00830           itLastOfRun = itRunFirstLastEntryFind->second.first;
00831         }
00832       } 
00833       
00834       std::list<unsigned int>::iterator iter = m_orderedIndices.insert(itLastOfRun,index);
00835       runLumiToLastEntryMap[runLumi]=iter;
00836       if(needNewEntryInRunFirstLastEntryMap) {
00837         runToFirstLastEntryMap[temp.m_run]=std::make_pair(iter,iter);
00838       } else {
00839         if(temp.m_lumi!=0) {
00840           //lumis go at end
00841           runToFirstLastEntryMap[temp.m_run].second = iter;
00842         } else {
00843           //since we haven't yet seen this run/lumi combination it means we haven't yet seen
00844           // a run so we can put this first
00845           runToFirstLastEntryMap[temp.m_run].first = iter;
00846         }
00847       }
00848     } else {
00849       //We need to do a merge since the run/lumi already appeared. Put it after the existing entry
00850       //std::cout <<" found a second instance of "<<runLumi.first<<" "<<runLumi.second<<" at "<<index<<std::endl;
00851       std::list<unsigned int>::iterator itNext = itFind->second;
00852       ++itNext;
00853       std::list<unsigned int>::iterator iter = m_orderedIndices.insert(itNext,index);
00854       RunToFirstLastEntryMap::iterator itRunFirstLastEntryFind = runToFirstLastEntryMap.find(temp.m_run);
00855       if(itRunFirstLastEntryFind->second.second == itFind->second) {
00856         //if the previous one was the last in the run, we need to update to make this one the last
00857         itRunFirstLastEntryFind->second.second = iter;
00858       }
00859       itFind->second = iter;
00860     }
00861   }
00862   m_nextIndexItr = m_orderedIndices.begin();
00863   m_presentIndexItr = m_orderedIndices.begin();
00864   
00865   if(m_nextIndexItr != m_orderedIndices.end()) {
00866     for( size_t index = 0; index < kNIndicies; ++index) {
00867       m_trees[index] = dynamic_cast<TTree*>(m_file->Get(kTypeNames[index]));
00868       assert(0!=m_trees[index]);
00869       m_treeReaders[index]->setTree(m_trees[index]);
00870     }
00871   }
00872   //After a file open, the framework expects to see a new 'IsRun'
00873   //m_lastSeenRun = 0;
00874   m_justOpenedFileSoNeedToGenerateRunTransition=true;
00875 }
00876 
00877 //
00878 // const member functions
00879 //
00880 
00881 //
00882 // static member functions
00883 //
00884 DEFINE_FWK_INPUT_SOURCE(DQMRootSource);