CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_9_patch3/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.14 2012/03/03 21:38:40 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 bool isFileOpen() const;
00186   virtual void openFile(edm::FileBlock const&);
00187 
00188 
00189   virtual void startEndFile();
00190   virtual void finishEndFile();
00191   std::string m_fileName;
00192   std::string m_logicalFileName;
00193   std::auto_ptr<TFile> m_file;
00194   std::vector<boost::shared_ptr<TreeHelperBase> > m_treeHelpers;
00195   
00196   unsigned int m_run;
00197   unsigned int m_lumi;
00198   unsigned int m_type;
00199   unsigned int m_presentHistoryIndex;
00200   ULong64_t m_beginTime;
00201   ULong64_t m_endTime;
00202   ULong64_t m_firstIndex;
00203   ULong64_t m_lastIndex;
00204   unsigned int m_filterOnRun;
00205   
00206   std::string m_fullNameBuffer;
00207   std::string* m_fullNameBufferPtr;
00208   std::map<unsigned int, unsigned int> m_dqmKindToTypeIndex;
00209   TTree* m_indicesTree;
00210   
00211   std::vector<edm::ProcessHistoryID> m_seenHistories;
00212   edm::JobReport::Token m_jrToken;
00213 };
00214 
00215 //
00216 // constants, enums and typedefs
00217 //
00218 
00219 static TreeHelperBase*
00220 makeHelper(unsigned int iTypeIndex,
00221            TTree* iTree, 
00222            std::string* iFullNameBufferPtr) {
00223   switch(iTypeIndex) {
00224     case kIntIndex:
00225     return new IntTreeHelper(iTree,iFullNameBufferPtr);
00226     case kFloatIndex:
00227     return new FloatTreeHelper(iTree,iFullNameBufferPtr);
00228     case kStringIndex:
00229     return new StringTreeHelper(iTree,iFullNameBufferPtr);
00230     case kTH1FIndex:
00231     return new TreeHelper<TH1F>(iTree,iFullNameBufferPtr);
00232     case kTH1SIndex:
00233     return new TreeHelper<TH1S>(iTree,iFullNameBufferPtr);
00234     case kTH1DIndex:
00235     return new TreeHelper<TH1D>(iTree,iFullNameBufferPtr);
00236     case kTH2FIndex:
00237     return new TreeHelper<TH2F>(iTree,iFullNameBufferPtr);
00238     case kTH2SIndex:
00239     return new TreeHelper<TH2S>(iTree,iFullNameBufferPtr);
00240     case kTH2DIndex:
00241     return new TreeHelper<TH2D>(iTree,iFullNameBufferPtr);
00242     case kTH3FIndex:
00243     return new TreeHelper<TH3F>(iTree,iFullNameBufferPtr);
00244     case kTProfileIndex:
00245     return new TreeHelper<TProfile>(iTree,iFullNameBufferPtr);
00246     case kTProfile2DIndex:
00247     return new TreeHelper<TProfile2D>(iTree,iFullNameBufferPtr);
00248   }
00249   assert(false);
00250   return 0;
00251 }
00252 
00253 //
00254 // static data member definitions
00255 //
00256 
00257 //
00258 // constructors and destructor
00259 //
00260 DQMRootOutputModule::DQMRootOutputModule(edm::ParameterSet const& pset):
00261 edm::OutputModule(pset),
00262 m_fileName(pset.getUntrackedParameter<std::string>("fileName")),
00263 m_logicalFileName(pset.getUntrackedParameter<std::string>("logicalFileName","")),
00264 m_file(0),
00265 m_treeHelpers(kNIndicies,boost::shared_ptr<TreeHelperBase>()),
00266 m_presentHistoryIndex(0),
00267 m_filterOnRun(pset.getUntrackedParameter<unsigned int>("filterOnRun",0)),
00268 m_fullNameBufferPtr(&m_fullNameBuffer),
00269 m_indicesTree(0)
00270 {
00271 }
00272 
00273 // DQMRootOutputModule::DQMRootOutputModule(const DQMRootOutputModule& rhs)
00274 // {
00275 //    // do actual copying here;
00276 // }
00277 
00278 DQMRootOutputModule::~DQMRootOutputModule()
00279 {
00280 }
00281 
00282 //
00283 // assignment operators
00284 //
00285 // const DQMRootOutputModule& DQMRootOutputModule::operator=(const DQMRootOutputModule& rhs)
00286 // {
00287 //   //An exception safe implementation is
00288 //   DQMRootOutputModule temp(rhs);
00289 //   swap(rhs);
00290 //
00291 //   return *this;
00292 // }
00293 
00294 //
00295 // member functions
00296 //
00297 bool 
00298 DQMRootOutputModule::isFileOpen() const
00299 {
00300   return nullptr!=m_file.get();
00301 }
00302 
00303 void 
00304 DQMRootOutputModule::openFile(edm::FileBlock const&)
00305 {
00306   //NOTE: I need to also set the I/O performance settings
00307   
00308   m_file = std::auto_ptr<TFile>(new TFile(m_fileName.c_str(),"RECREATE",
00309                                 "1" //This is the file format version number
00310                                 ));  
00311   
00312   edm::Service<edm::JobReport> jr;
00313   cms::Digest branchHash;
00314   m_jrToken = jr->outputFileOpened(m_fileName,
00315                                    m_logicalFileName,
00316                                    std::string(),
00317                                    "DQMRootOutputModule",
00318                                    description().moduleLabel(),
00319                                    m_file->GetUUID().AsString(),
00320                                    std::string(),
00321                                    branchHash.digest().toString(),
00322                                    std::vector<std::string>()
00323     );
00324 
00325 
00326   m_indicesTree = new TTree(kIndicesTree,kIndicesTree);
00327   m_indicesTree->Branch(kRunBranch,&m_run);
00328   m_indicesTree->Branch(kLumiBranch,&m_lumi);
00329   m_indicesTree->Branch(kProcessHistoryIndexBranch,&m_presentHistoryIndex);
00330   m_indicesTree->Branch(kBeginTimeBranch,&m_beginTime);
00331   m_indicesTree->Branch(kEndTimeBranch,&m_endTime);
00332   m_indicesTree->Branch(kTypeBranch,&m_type);
00333   m_indicesTree->Branch(kFirstIndex,&m_firstIndex);
00334   m_indicesTree->Branch(kLastIndex,&m_lastIndex);
00335   m_indicesTree->SetDirectory(m_file.get());
00336   
00337   unsigned int i = 0;
00338   for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
00339   it != itEnd;
00340   ++it,++i) {
00341     //std::cout <<"making "<<kTypeNames[i]<<std::endl;
00342     TTree* tree = new TTree(kTypeNames[i],kTypeNames[i]);
00343     *it = boost::shared_ptr<TreeHelperBase>(makeHelper(i,tree,m_fullNameBufferPtr));
00344     tree->SetDirectory(m_file.get()); //TFile takes ownership
00345   }
00346   
00347   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_INT]=kIntIndex;
00348   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_REAL]=kFloatIndex;
00349   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_STRING]=kStringIndex;
00350   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH1F]=kTH1FIndex;
00351   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH1S]=kTH1SIndex;
00352   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH1D]=kTH1DIndex;
00353   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH2F]=kTH2FIndex;
00354   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH2S]=kTH2SIndex;
00355   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH2D]=kTH2DIndex;
00356   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TH3F]=kTH3FIndex;
00357   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TPROFILE]=kTProfileIndex;
00358   m_dqmKindToTypeIndex[MonitorElement::DQM_KIND_TPROFILE2D]=kTProfile2DIndex;
00359 }
00360 
00361 
00362 void 
00363 DQMRootOutputModule::write(edm::EventPrincipal const& ){
00364   
00365 }
00366 void 
00367 DQMRootOutputModule::writeLuminosityBlock(edm::LuminosityBlockPrincipal const& iLumi) {
00368   //std::cout << "DQMRootOutputModule::writeLuminosityBlock"<< std::endl;
00369   edm::Service<DQMStore> dstore;
00370   m_run=iLumi.id().run();
00371   m_lumi = iLumi.id().value();
00372   m_beginTime = iLumi.beginTime().value();
00373   m_endTime = iLumi.endTime().value();
00374   bool shouldWrite = (m_filterOnRun == 0 ||
00375                       (m_filterOnRun != 0 && m_filterOnRun == m_run));
00376 
00377   if (! shouldWrite)
00378     return;
00379   std::vector<MonitorElement *> items(dstore->getAllContents(""));
00380   for(std::vector<MonitorElement*>::iterator it = items.begin(), itEnd=items.end();
00381       it!=itEnd;
00382       ++it) {
00383     if((*it)->getLumiFlag()) {
00384       std::map<unsigned int,unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((*it)->kind());
00385       assert(itFound !=m_dqmKindToTypeIndex.end());
00386       m_treeHelpers[itFound->second]->fill(*it);
00387     }
00388   }
00389   //Now store the relationship between run/lumi and indices in the other TTrees
00390   bool storedLumiIndex = false;
00391   unsigned int typeIndex = 0;
00392   for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
00393       it != itEnd;
00394       ++it,++typeIndex) {
00395     if((*it)->wasFilled()) {
00396       m_type = typeIndex;
00397       (*it)->getRangeAndReset(m_firstIndex,m_lastIndex);
00398       storedLumiIndex = true;
00399       m_indicesTree->Fill();
00400     }
00401   }
00402   if(not storedLumiIndex) {
00403     //need to record lumis even if we stored no MonitorElements since some later DQM modules
00404     // look to see what lumis were processed
00405     m_type = kNoTypesStored;
00406     m_firstIndex=0;
00407     m_lastIndex=0;
00408     m_indicesTree->Fill();
00409   }
00410   
00411   edm::Service<edm::JobReport> jr;
00412   jr->reportLumiSection(m_run,m_lumi);
00413 }
00414 
00415 
00416 void DQMRootOutputModule::writeRun(edm::RunPrincipal const& iRun){
00417   //std::cout << "DQMRootOutputModule::writeRun"<< std::endl;
00418   edm::Service<DQMStore> dstore;
00419   m_run=iRun.id().run();
00420   m_lumi = 0;
00421   m_beginTime = iRun.beginTime().value();
00422   m_endTime = iRun.endTime().value();
00423   bool shouldWrite = (m_filterOnRun == 0 ||
00424                       (m_filterOnRun != 0 && m_filterOnRun == m_run));
00425 
00426   if (! shouldWrite)
00427     return;
00428 
00429   std::vector<MonitorElement *> items(dstore->getAllContents(""));
00430   for(std::vector<MonitorElement*>::iterator it = items.begin(), itEnd=items.end();
00431       it!=itEnd;
00432       ++it) {
00433     if(not (*it)->getLumiFlag()) {
00434       std::map<unsigned int,unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((*it)->kind());
00435       assert  (itFound !=m_dqmKindToTypeIndex.end());
00436       m_treeHelpers[itFound->second]->fill(*it);
00437     }
00438   }
00439   
00440   //Now store the relationship between run/lumi and indices in the other TTrees
00441   unsigned int typeIndex = 0;
00442   for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
00443       it != itEnd;
00444       ++it,++typeIndex) {
00445     if((*it)->wasFilled()) {
00446       m_type = typeIndex;
00447       (*it)->getRangeAndReset(m_firstIndex,m_lastIndex);
00448       m_indicesTree->Fill();
00449     }
00450   }
00451   
00452   edm::Service<edm::JobReport> jr;
00453   jr->reportRunNumber(m_run);  
00454 }
00455 
00456 void DQMRootOutputModule::beginRun(edm::RunPrincipal const& iPrincipal) {
00457   //std::cout << "DQMRootOutputModule::beginRun"<< std::endl;
00458   //The ProcessHistory for a lumi must be the same as its Run so we only need to 
00459   // record it at Run time
00460   edm::ProcessHistoryID id = iPrincipal.processHistoryID();
00461   std::vector<edm::ProcessHistoryID>::iterator itFind = std::find(m_seenHistories.begin(),m_seenHistories.end(),id);
00462   if(itFind == m_seenHistories.end()) {
00463     m_presentHistoryIndex = m_seenHistories.size();
00464     m_seenHistories.push_back(id);
00465   } else {
00466     m_presentHistoryIndex = itFind - m_seenHistories.begin();
00467   }
00468 }
00469 
00470 void DQMRootOutputModule::startEndFile() {
00471   //std::cout << "DQMRootOutputModule::startEndFile"<< std::endl;
00472   //fill in the meta data
00473   m_file->cd();
00474   TDirectory* metaDataDirectory = m_file->mkdir(kMetaDataDirectory);
00475 
00476 
00477   //Write out the Process History
00478   TTree* processHistoryTree = new TTree(kProcessHistoryTree,kProcessHistoryTree);
00479   processHistoryTree->SetDirectory(metaDataDirectory);
00480   
00481   unsigned int index = 0;
00482   processHistoryTree->Branch(kPHIndexBranch,&index);
00483   std::string processName;
00484   processHistoryTree->Branch(kProcessConfigurationProcessNameBranch,&processName);
00485   std::string parameterSetID;
00486   processHistoryTree->Branch(kProcessConfigurationParameterSetIDBranch,&parameterSetID);
00487   std::string releaseVersion;
00488   processHistoryTree->Branch(kProcessConfigurationReleaseVersion,&releaseVersion);
00489   std::string passID;
00490   processHistoryTree->Branch(kProcessConfigurationPassID,&passID);
00491 
00492   edm::ProcessHistoryRegistry* phr = edm::ProcessHistoryRegistry::instance();
00493   assert(0!=phr);
00494   for(std::vector<edm::ProcessHistoryID>::iterator it = m_seenHistories.begin(), itEnd = m_seenHistories.end();
00495       it !=itEnd;
00496       ++it) {
00497     const edm::ProcessHistory* history = phr->getMapped(*it);
00498     assert(0!=history);
00499     index = 0;
00500     for(edm::ProcessHistory::collection_type::const_iterator itPC = history->begin(), itPCEnd = history->end();
00501         itPC != itPCEnd;
00502         ++itPC,++index) {
00503       processName = itPC->processName();
00504       releaseVersion = itPC->releaseVersion();
00505       passID = itPC->passID();
00506       parameterSetID = itPC->parameterSetID().compactForm();
00507       processHistoryTree->Fill();
00508     }
00509   }
00510   
00511   //Store the ParameterSets
00512   TTree* parameterSetsTree = new TTree(kParameterSetTree,kParameterSetTree);
00513   parameterSetsTree->SetDirectory(metaDataDirectory);
00514   std::string blob;
00515   parameterSetsTree->Branch(kParameterSetBranch,&blob);
00516   
00517   edm::pset::Registry* psr = edm::pset::Registry::instance();
00518   assert(0!=psr);
00519   for(edm::pset::Registry::const_iterator it = psr->begin(), itEnd = psr->end();
00520   it != itEnd;
00521   ++it) {
00522     blob.clear();
00523     it->second.toString(blob);
00524     parameterSetsTree->Fill();
00525   }
00526   
00527 }
00528 
00529 void DQMRootOutputModule::finishEndFile() {
00530   //std::cout << "DQMRootOutputModule::finishEndFile"<< std::endl;
00531   m_file->Write();
00532   m_file->Close();
00533   edm::Service<edm::JobReport> jr;
00534   jr->outputFileClosed(m_jrToken);
00535 }
00536 
00537 //
00538 // const member functions
00539 //
00540 
00541 //
00542 // static member functions
00543 //
00544 void
00545 DQMRootOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
00546   //The following says we do not know what parameters are allowed so do no validation
00547   // Please change this to state exactly what you do use, even if it is no parameters
00548   edm::ParameterSetDescription desc;
00549   desc.setUnknown();
00550   descriptions.addDefault(desc);
00551 
00552   //NOTE: when actually filling this in, do not forget to add a untracked PSet 'dataset'
00553   // which is used for bookkeeping by the DMWM
00554 }
00555 
00556 
00557 DEFINE_FWK_MODULE(DQMRootOutputModule);