Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-05-01 22:51:57

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