Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-05-06 02:46:16

0001 // -*- C++ -*-
0002 //
0003 // Package:     FwkIO
0004 // Class  :     DQMRootOutputModule
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Fri Apr 29 13:26:29 CDT 2011
0011 //
0012 
0013 // system include files
0014 #include <algorithm>
0015 #include <iostream>
0016 #include <memory>
0017 
0018 #include <map>
0019 #include <memory>
0020 #include <string>
0021 #include <vector>
0022 
0023 #include "TFile.h"
0024 #include "TTree.h"
0025 #include "TString.h"
0026 #include "TH1.h"
0027 #include "TH2.h"
0028 #include "TProfile.h"
0029 
0030 #include "oneapi/tbb/task_arena.h"
0031 
0032 // user include files
0033 #include "FWCore/Framework/interface/GetterOfProducts.h"
0034 #include "FWCore/Framework/interface/one/OutputModule.h"
0035 #include "FWCore/Framework/interface/RunForOutput.h"
0036 #include "FWCore/Framework/interface/LuminosityBlockForOutput.h"
0037 #include "FWCore/Framework/interface/TypeMatch.h"
0038 #include "DQMServices/Core/interface/DQMStore.h"
0039 #include "FWCore/ServiceRegistry/interface/Service.h"
0040 #include "FWCore/Framework/interface/MakerMacros.h"
0041 #include "FWCore/MessageLogger/interface/JobReport.h"
0042 #include "FWCore/Utilities/interface/BranchType.h"
0043 #include "FWCore/Utilities/interface/Digest.h"
0044 #include "FWCore/Utilities/interface/GlobalIdentifier.h"
0045 
0046 #include "DataFormats/Provenance/interface/ProcessHistory.h"
0047 #include "DataFormats/Provenance/interface/ProcessHistoryID.h"
0048 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
0049 #include "FWCore/ParameterSet/interface/Registry.h"
0050 
0051 #include "DataFormats/Histograms/interface/DQMToken.h"
0052 
0053 #include "format.h"
0054 
0055 namespace {
0056   typedef dqm::legacy::MonitorElement MonitorElement;
0057   typedef dqm::legacy::DQMStore DQMStore;
0058 
0059   class TreeHelperBase {
0060   public:
0061     TreeHelperBase() : m_wasFilled(false), m_firstIndex(0), m_lastIndex(0) {}
0062     virtual ~TreeHelperBase() {}
0063     void fill(MonitorElement* iElement) {
0064       doFill(iElement);
0065       if (m_wasFilled) {
0066         ++m_lastIndex;
0067       }
0068       m_wasFilled = true;
0069     }
0070     bool wasFilled() const { return m_wasFilled; }
0071     void getRangeAndReset(ULong64_t& iFirstIndex, ULong64_t& iLastIndex) {
0072       iFirstIndex = m_firstIndex;
0073       iLastIndex = m_lastIndex;
0074       m_wasFilled = false;
0075       m_firstIndex = m_lastIndex + 1;
0076       m_lastIndex = m_firstIndex;
0077     }
0078 
0079   private:
0080     virtual void doFill(MonitorElement*) = 0;
0081     bool m_wasFilled;
0082     ULong64_t m_firstIndex;
0083     ULong64_t m_lastIndex;
0084   };
0085 
0086   template <class T>
0087   class TreeHelper : public TreeHelperBase {
0088   public:
0089     TreeHelper(TTree* iTree, std::string* iFullNameBufferPtr)
0090         : m_tree(iTree), m_flagBuffer(0), m_fullNameBufferPtr(iFullNameBufferPtr) {
0091       setup();
0092     }
0093     void doFill(MonitorElement* iElement) override {
0094       *m_fullNameBufferPtr = iElement->getFullname();
0095       m_flagBuffer = 0;
0096       m_bufferPtr = dynamic_cast<T*>(iElement->getRootObject());
0097       assert(nullptr != m_bufferPtr);
0098       //std::cout <<"#entries: "<<m_bufferPtr->GetEntries()<<std::endl;
0099       tbb::this_task_arena::isolate([&] { m_tree->Fill(); });
0100     }
0101 
0102   private:
0103     void setup() {
0104       m_tree->Branch(kFullNameBranch, &m_fullNameBufferPtr);
0105       m_tree->Branch(kFlagBranch, &m_flagBuffer);
0106 
0107       m_bufferPtr = nullptr;
0108       m_tree->Branch(kValueBranch, &m_bufferPtr, 128 * 1024, 0);
0109     }
0110     TTree* m_tree;
0111     uint32_t m_flagBuffer;
0112     std::string* m_fullNameBufferPtr;
0113     T* m_bufferPtr;
0114   };
0115 
0116   class IntTreeHelper : public TreeHelperBase {
0117   public:
0118     IntTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr)
0119         : m_tree(iTree), m_flagBuffer(0), m_fullNameBufferPtr(iFullNameBufferPtr) {
0120       setup();
0121     }
0122 
0123     void doFill(MonitorElement* iElement) override {
0124       *m_fullNameBufferPtr = iElement->getFullname();
0125       m_flagBuffer = 0;
0126       m_buffer = iElement->getIntValue();
0127       tbb::this_task_arena::isolate([&] { m_tree->Fill(); });
0128     }
0129 
0130   private:
0131     void setup() {
0132       m_tree->Branch(kFullNameBranch, &m_fullNameBufferPtr);
0133       m_tree->Branch(kFlagBranch, &m_flagBuffer);
0134       m_tree->Branch(kValueBranch, &m_buffer);
0135     }
0136     TTree* m_tree;
0137     uint32_t m_flagBuffer;
0138     std::string* m_fullNameBufferPtr;
0139     Long64_t m_buffer;
0140   };
0141 
0142   class FloatTreeHelper : public TreeHelperBase {
0143   public:
0144     FloatTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr)
0145         : m_tree(iTree), m_flagBuffer(0), m_fullNameBufferPtr(iFullNameBufferPtr) {
0146       setup();
0147     }
0148     void doFill(MonitorElement* iElement) override {
0149       *m_fullNameBufferPtr = iElement->getFullname();
0150       m_flagBuffer = 0;
0151       m_buffer = iElement->getFloatValue();
0152       tbb::this_task_arena::isolate([&] { m_tree->Fill(); });
0153     }
0154 
0155   private:
0156     void setup() {
0157       m_tree->Branch(kFullNameBranch, &m_fullNameBufferPtr);
0158       m_tree->Branch(kFlagBranch, &m_flagBuffer);
0159       m_tree->Branch(kValueBranch, &m_buffer);
0160     }
0161 
0162     TTree* m_tree;
0163     uint32_t m_flagBuffer;
0164     std::string* m_fullNameBufferPtr;
0165     double m_buffer;
0166   };
0167 
0168   class StringTreeHelper : public TreeHelperBase {
0169   public:
0170     StringTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr)
0171         : m_tree(iTree), m_flagBuffer(0), m_fullNameBufferPtr(iFullNameBufferPtr), m_bufferPtr(&m_buffer) {
0172       setup();
0173     }
0174     void doFill(MonitorElement* iElement) override {
0175       *m_fullNameBufferPtr = iElement->getFullname();
0176       m_flagBuffer = 0;
0177       m_buffer = iElement->getStringValue();
0178       tbb::this_task_arena::isolate([&] { m_tree->Fill(); });
0179     }
0180 
0181   private:
0182     void setup() {
0183       m_tree->Branch(kFullNameBranch, &m_fullNameBufferPtr);
0184       m_tree->Branch(kFlagBranch, &m_flagBuffer);
0185       m_tree->Branch(kValueBranch, &m_bufferPtr);
0186     }
0187 
0188     TTree* m_tree;
0189     uint32_t m_flagBuffer;
0190     std::string* m_fullNameBufferPtr;
0191     std::string m_buffer;
0192     std::string* m_bufferPtr;
0193   };
0194 
0195 }  // namespace
0196 
0197 namespace edm {
0198   class ModuleCallingContext;
0199 }
0200 
0201 class DQMRootOutputModule : public edm::one::OutputModule<> {
0202 public:
0203   explicit DQMRootOutputModule(edm::ParameterSet const& pset);
0204   void beginJob() override;
0205   ~DQMRootOutputModule() override;
0206   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0207 
0208 private:
0209   void write(edm::EventForOutput const& e) override;
0210   void writeLuminosityBlock(edm::LuminosityBlockForOutput const&) override;
0211   void writeRun(edm::RunForOutput const&) override;
0212   bool isFileOpen() const override;
0213   void openFile(edm::FileBlock const&) override;
0214   void reallyCloseFile() override;
0215 
0216   void startEndFile();
0217   void finishEndFile();
0218   std::string m_fileName;
0219   std::string m_logicalFileName;
0220   std::unique_ptr<TFile> m_file;
0221   std::vector<std::shared_ptr<TreeHelperBase> > m_treeHelpers;
0222 
0223   unsigned int m_run;
0224   unsigned int m_lumi;
0225   unsigned int m_type;
0226   unsigned int m_presentHistoryIndex;
0227   ULong64_t m_beginTime;
0228   ULong64_t m_endTime;
0229   ULong64_t m_firstIndex;
0230   ULong64_t m_lastIndex;
0231   unsigned int m_filterOnRun;
0232 
0233   std::string m_fullNameBuffer;
0234   std::string* m_fullNameBufferPtr;
0235   std::map<unsigned int, unsigned int> m_dqmKindToTypeIndex;
0236   TTree* m_indicesTree;
0237 
0238   std::vector<edm::ProcessHistoryID> m_seenHistories;
0239   edm::ProcessHistoryRegistry m_processHistoryRegistry;
0240   edm::JobReport::Token m_jrToken;
0241 
0242   edm::GetterOfProducts<DQMToken> m_getterOfProductsLumi;
0243   edm::GetterOfProducts<DQMToken> m_getterOfProductsRun;
0244 };
0245 
0246 //
0247 // constants, enums and typedefs
0248 //
0249 
0250 static TreeHelperBase* makeHelper(unsigned int iTypeIndex, TTree* iTree, std::string* iFullNameBufferPtr) {
0251   switch (iTypeIndex) {
0252     case kIntIndex:
0253       return new IntTreeHelper(iTree, iFullNameBufferPtr);
0254     case kFloatIndex:
0255       return new FloatTreeHelper(iTree, iFullNameBufferPtr);
0256     case kStringIndex:
0257       return new StringTreeHelper(iTree, iFullNameBufferPtr);
0258     case kTH1FIndex:
0259       return new TreeHelper<TH1F>(iTree, iFullNameBufferPtr);
0260     case kTH1SIndex:
0261       return new TreeHelper<TH1S>(iTree, iFullNameBufferPtr);
0262     case kTH1DIndex:
0263       return new TreeHelper<TH1D>(iTree, iFullNameBufferPtr);
0264     case kTH1IIndex:
0265       return new TreeHelper<TH1I>(iTree, iFullNameBufferPtr);
0266     case kTH2FIndex:
0267       return new TreeHelper<TH2F>(iTree, iFullNameBufferPtr);
0268     case kTH2SIndex:
0269       return new TreeHelper<TH2S>(iTree, iFullNameBufferPtr);
0270     case kTH2DIndex:
0271       return new TreeHelper<TH2D>(iTree, iFullNameBufferPtr);
0272     case kTH2IIndex:
0273       return new TreeHelper<TH2I>(iTree, iFullNameBufferPtr);
0274     case kTH3FIndex:
0275       return new TreeHelper<TH3F>(iTree, iFullNameBufferPtr);
0276     case kTProfileIndex:
0277       return new TreeHelper<TProfile>(iTree, iFullNameBufferPtr);
0278     case kTProfile2DIndex:
0279       return new TreeHelper<TProfile2D>(iTree, iFullNameBufferPtr);
0280   }
0281   assert(false);
0282   return nullptr;
0283 }
0284 
0285 //
0286 // static data member definitions
0287 //
0288 
0289 //
0290 // constructors and destructor
0291 //
0292 DQMRootOutputModule::DQMRootOutputModule(edm::ParameterSet const& pset)
0293     : edm::one::OutputModuleBase::OutputModuleBase(pset),
0294       edm::one::OutputModule<>(pset),
0295       m_fileName(pset.getUntrackedParameter<std::string>("fileName")),
0296       m_logicalFileName(pset.getUntrackedParameter<std::string>("logicalFileName")),
0297       m_file(nullptr),
0298       m_treeHelpers(kNIndicies, std::shared_ptr<TreeHelperBase>()),
0299       m_presentHistoryIndex(0),
0300       m_filterOnRun(pset.getUntrackedParameter<unsigned int>("filterOnRun")),
0301       m_fullNameBufferPtr(&m_fullNameBuffer),
0302       m_indicesTree(nullptr),
0303       m_getterOfProductsLumi(edm::TypeMatch(), this, edm::InLumi),
0304       m_getterOfProductsRun(edm::TypeMatch(), this, edm::InRun) {
0305   // Declare dependencies for all Lumi and Run tokens here. In
0306   // principle could use the keep statements, but then DQMToken would
0307   // have to be made persistent (transient products are ignored),
0308   // which would lead to a need to (finally) remove underscores from
0309   // DQM module labels.
0310   // This is needed to support unscheduled DQM modules now that
0311   // non-consumed EDProducers are deleted from the job at beginJob.
0312   callWhenNewProductsRegistered([this](edm::BranchDescription const& bd) {
0313     m_getterOfProductsLumi(bd);
0314     m_getterOfProductsRun(bd);
0315   });
0316 }
0317 
0318 // DQMRootOutputModule::DQMRootOutputModule(const DQMRootOutputModule& rhs)
0319 // {
0320 //    // do actual copying here;
0321 // }
0322 
0323 void DQMRootOutputModule::beginJob() {}
0324 
0325 DQMRootOutputModule::~DQMRootOutputModule() {}
0326 
0327 //
0328 // assignment operators
0329 //
0330 // const DQMRootOutputModule& DQMRootOutputModule::operator=(const DQMRootOutputModule& rhs)
0331 // {
0332 //   //An exception safe implementation is
0333 //   DQMRootOutputModule temp(rhs);
0334 //   swap(rhs);
0335 //
0336 //   return *this;
0337 // }
0338 
0339 //
0340 // member functions
0341 //
0342 bool DQMRootOutputModule::isFileOpen() const { return nullptr != m_file.get(); }
0343 
0344 void DQMRootOutputModule::openFile(edm::FileBlock const&) {
0345   //NOTE: I need to also set the I/O performance settings
0346 
0347   m_file = std::make_unique<TFile>(m_fileName.c_str(),
0348                                    "RECREATE",
0349                                    "1"  //This is the file format version number
0350   );
0351 
0352   edm::Service<edm::JobReport> jr;
0353   cms::Digest branchHash;
0354   std::string guid{edm::createGlobalIdentifier()};
0355   std::transform(guid.begin(), guid.end(), guid.begin(), (int (*)(int))std::toupper);
0356 
0357   m_file->WriteObject(&guid, kCmsGuid);
0358   m_jrToken = jr->outputFileOpened(m_fileName,
0359                                    m_logicalFileName,
0360                                    std::string(),
0361                                    "DQMRootOutputModule",
0362                                    description().moduleLabel(),
0363                                    guid,
0364                                    std::string(),
0365                                    branchHash.digest().toString(),
0366                                    std::vector<std::string>());
0367 
0368   m_indicesTree = new TTree(kIndicesTree, kIndicesTree);
0369   m_indicesTree->Branch(kRunBranch, &m_run);
0370   m_indicesTree->Branch(kLumiBranch, &m_lumi);
0371   m_indicesTree->Branch(kProcessHistoryIndexBranch, &m_presentHistoryIndex);
0372   m_indicesTree->Branch(kBeginTimeBranch, &m_beginTime);
0373   m_indicesTree->Branch(kEndTimeBranch, &m_endTime);
0374   m_indicesTree->Branch(kTypeBranch, &m_type);
0375   m_indicesTree->Branch(kFirstIndex, &m_firstIndex);
0376   m_indicesTree->Branch(kLastIndex, &m_lastIndex);
0377   m_indicesTree->SetDirectory(m_file.get());
0378 
0379   unsigned int i = 0;
0380   for (std::vector<std::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
0381        it != itEnd;
0382        ++it, ++i) {
0383     //std::cout <<"making "<<kTypeNames[i]<<std::endl;
0384     TTree* tree = new TTree(kTypeNames[i], kTypeNames[i]);
0385     *it = std::shared_ptr<TreeHelperBase>(makeHelper(i, tree, m_fullNameBufferPtr));
0386     tree->SetDirectory(m_file.get());  //TFile takes ownership
0387   }
0388 
0389   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::INT] = kIntIndex;
0390   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::REAL] = kFloatIndex;
0391   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::STRING] = kStringIndex;
0392   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH1F] = kTH1FIndex;
0393   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH1S] = kTH1SIndex;
0394   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH1D] = kTH1DIndex;
0395   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH1I] = kTH1IIndex;
0396   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH2F] = kTH2FIndex;
0397   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH2S] = kTH2SIndex;
0398   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH2D] = kTH2DIndex;
0399   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH2I] = kTH2IIndex;
0400   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TH3F] = kTH3FIndex;
0401   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TPROFILE] = kTProfileIndex;
0402   m_dqmKindToTypeIndex[(int)MonitorElement::Kind::TPROFILE2D] = kTProfile2DIndex;
0403 }
0404 
0405 void DQMRootOutputModule::write(edm::EventForOutput const&) {}
0406 
0407 void DQMRootOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput const& iLumi) {
0408   //std::cout << "DQMRootOutputModule::writeLuminosityBlock"<< std::endl;
0409   edm::Service<DQMStore> dstore;
0410   m_run = iLumi.id().run();
0411   m_lumi = iLumi.id().value();
0412   m_beginTime = iLumi.beginTime().value();
0413   m_endTime = iLumi.endTime().value();
0414   bool shouldWrite = (m_filterOnRun == 0 || (m_filterOnRun != 0 && m_filterOnRun == m_run));
0415 
0416   if (!shouldWrite)
0417     return;
0418   std::vector<MonitorElement*> items(dstore->getAllContents("", m_run, m_lumi));
0419   for (std::vector<MonitorElement*>::iterator it = items.begin(), itEnd = items.end(); it != itEnd; ++it) {
0420     assert((*it)->getScope() == MonitorElementData::Scope::LUMI);
0421     std::map<unsigned int, unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((int)(*it)->kind());
0422     assert(itFound != m_dqmKindToTypeIndex.end());
0423     m_treeHelpers[itFound->second]->fill(*it);
0424   }
0425 
0426   const edm::ProcessHistoryID& id = iLumi.processHistoryID();
0427   std::vector<edm::ProcessHistoryID>::iterator itFind = std::find(m_seenHistories.begin(), m_seenHistories.end(), id);
0428   if (itFind == m_seenHistories.end()) {
0429     m_processHistoryRegistry.registerProcessHistory(iLumi.processHistory());
0430     m_presentHistoryIndex = m_seenHistories.size();
0431     m_seenHistories.push_back(id);
0432   } else {
0433     m_presentHistoryIndex = itFind - m_seenHistories.begin();
0434   }
0435 
0436   //Now store the relationship between run/lumi and indices in the other TTrees
0437   bool storedLumiIndex = false;
0438   unsigned int typeIndex = 0;
0439   for (std::vector<std::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
0440        it != itEnd;
0441        ++it, ++typeIndex) {
0442     if ((*it)->wasFilled()) {
0443       m_type = typeIndex;
0444       (*it)->getRangeAndReset(m_firstIndex, m_lastIndex);
0445       storedLumiIndex = true;
0446       tbb::this_task_arena::isolate([&] { m_indicesTree->Fill(); });
0447     }
0448   }
0449   if (not storedLumiIndex) {
0450     //need to record lumis even if we stored no MonitorElements since some later DQM modules
0451     // look to see what lumis were processed
0452     m_type = kNoTypesStored;
0453     m_firstIndex = 0;
0454     m_lastIndex = 0;
0455     tbb::this_task_arena::isolate([&] { m_indicesTree->Fill(); });
0456   }
0457 
0458   edm::Service<edm::JobReport> jr;
0459   jr->reportLumiSection(m_jrToken, m_run, m_lumi);
0460 }
0461 
0462 void DQMRootOutputModule::writeRun(edm::RunForOutput const& iRun) {
0463   //std::cout << "DQMRootOutputModule::writeRun"<< std::endl;
0464   edm::Service<DQMStore> dstore;
0465   m_run = iRun.id().run();
0466   m_lumi = 0;
0467   m_beginTime = iRun.beginTime().value();
0468   m_endTime = iRun.endTime().value();
0469   bool shouldWrite = (m_filterOnRun == 0 || (m_filterOnRun != 0 && m_filterOnRun == m_run));
0470 
0471   if (!shouldWrite)
0472     return;
0473 
0474   std::vector<MonitorElement*> items(dstore->getAllContents("", m_run, 0));
0475   for (std::vector<MonitorElement*>::iterator it = items.begin(), itEnd = items.end(); it != itEnd; ++it) {
0476     assert((*it)->getScope() == MonitorElementData::Scope::RUN);
0477     std::map<unsigned int, unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((int)(*it)->kind());
0478     assert(itFound != m_dqmKindToTypeIndex.end());
0479     m_treeHelpers[itFound->second]->fill(*it);
0480   }
0481 
0482   const edm::ProcessHistoryID& id = iRun.processHistoryID();
0483   std::vector<edm::ProcessHistoryID>::iterator itFind = std::find(m_seenHistories.begin(), m_seenHistories.end(), id);
0484   if (itFind == m_seenHistories.end()) {
0485     m_processHistoryRegistry.registerProcessHistory(iRun.processHistory());
0486     m_presentHistoryIndex = m_seenHistories.size();
0487     m_seenHistories.push_back(id);
0488   } else {
0489     m_presentHistoryIndex = itFind - m_seenHistories.begin();
0490   }
0491 
0492   //Now store the relationship between run/lumi and indices in the other TTrees
0493   unsigned int typeIndex = 0;
0494   for (std::vector<std::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
0495        it != itEnd;
0496        ++it, ++typeIndex) {
0497     if ((*it)->wasFilled()) {
0498       m_type = typeIndex;
0499       (*it)->getRangeAndReset(m_firstIndex, m_lastIndex);
0500       tbb::this_task_arena::isolate([&] { m_indicesTree->Fill(); });
0501     }
0502   }
0503 
0504   edm::Service<edm::JobReport> jr;
0505   jr->reportRunNumber(m_jrToken, m_run);
0506 }
0507 
0508 void DQMRootOutputModule::reallyCloseFile() {
0509   startEndFile();
0510   finishEndFile();
0511 }
0512 
0513 void DQMRootOutputModule::startEndFile() {
0514   //std::cout << "DQMRootOutputModule::startEndFile"<< std::endl;
0515   //fill in the meta data
0516   m_file->cd();
0517   TDirectory* metaDataDirectory = m_file->mkdir(kMetaDataDirectory);
0518 
0519   //Write out the Process History
0520   TTree* processHistoryTree = new TTree(kProcessHistoryTree, kProcessHistoryTree);
0521   processHistoryTree->SetDirectory(metaDataDirectory);
0522 
0523   unsigned int index = 0;
0524   processHistoryTree->Branch(kPHIndexBranch, &index);
0525   std::string processName;
0526   processHistoryTree->Branch(kProcessConfigurationProcessNameBranch, &processName);
0527   std::string parameterSetID;
0528   processHistoryTree->Branch(kProcessConfigurationParameterSetIDBranch, &parameterSetID);
0529   std::string releaseVersion;
0530   processHistoryTree->Branch(kProcessConfigurationReleaseVersion, &releaseVersion);
0531   std::string passID;
0532   processHistoryTree->Branch(kProcessConfigurationPassID, &passID);
0533 
0534   for (std::vector<edm::ProcessHistoryID>::iterator it = m_seenHistories.begin(), itEnd = m_seenHistories.end();
0535        it != itEnd;
0536        ++it) {
0537     const edm::ProcessHistory* history = m_processHistoryRegistry.getMapped(*it);
0538     assert(nullptr != history);
0539     index = 0;
0540     for (edm::ProcessHistory::collection_type::const_iterator itPC = history->begin(), itPCEnd = history->end();
0541          itPC != itPCEnd;
0542          ++itPC, ++index) {
0543       processName = itPC->processName();
0544       releaseVersion = itPC->releaseVersion();
0545       passID = itPC->passID();
0546       parameterSetID = itPC->parameterSetID().compactForm();
0547       tbb::this_task_arena::isolate([&] { processHistoryTree->Fill(); });
0548     }
0549   }
0550 
0551   //Store the ParameterSets
0552   TTree* parameterSetsTree = new TTree(kParameterSetTree, kParameterSetTree);
0553   parameterSetsTree->SetDirectory(metaDataDirectory);
0554   std::string blob;
0555   parameterSetsTree->Branch(kParameterSetBranch, &blob);
0556 
0557   edm::pset::Registry* psr = edm::pset::Registry::instance();
0558   assert(nullptr != psr);
0559   for (edm::pset::Registry::const_iterator it = psr->begin(), itEnd = psr->end(); it != itEnd; ++it) {
0560     blob.clear();
0561     it->second.toString(blob);
0562     tbb::this_task_arena::isolate([&] { parameterSetsTree->Fill(); });
0563   }
0564 }
0565 
0566 void DQMRootOutputModule::finishEndFile() {
0567   //std::cout << "DQMRootOutputModule::finishEndFile"<< std::endl;
0568   m_file->Write();
0569   m_file->Close();
0570   edm::Service<edm::JobReport> jr;
0571   jr->outputFileClosed(m_jrToken);
0572 }
0573 
0574 //
0575 // const member functions
0576 //
0577 
0578 //
0579 // static member functions
0580 //
0581 void DQMRootOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0582   edm::ParameterSetDescription desc;
0583 
0584   desc.addUntracked<std::string>("fileName");
0585   desc.addUntracked<std::string>("logicalFileName", "");
0586   desc.addUntracked<unsigned int>("filterOnRun", 0)
0587       ->setComment("Only write the run with this run number. 0 means write all runs.");
0588   desc.addOptionalUntracked<int>("splitLevel", 99)
0589       ->setComment("UNUSED Only here to allow older configurations written for PoolOutputModule to work.");
0590   const std::vector<std::string> keep = {"drop *", "keep DQMToken_*_*_*"};
0591   edm::one::OutputModule<>::fillDescription(desc, keep);
0592 
0593   edm::ParameterSetDescription dataSet;
0594   dataSet.setAllowAnything();
0595   desc.addUntracked<edm::ParameterSetDescription>("dataset", dataSet)
0596       ->setComment("PSet is only used by Data Operations and not by this module.");
0597 
0598   descriptions.addDefault(desc);
0599 }
0600 
0601 DEFINE_FWK_MODULE(DQMRootOutputModule);