CMS 3D CMS Logo

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