CMS 3D CMS Logo

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