00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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
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
00260
00261
00262
00263
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
00279
00280
00281
00282
00283 DQMRootOutputModule::~DQMRootOutputModule()
00284 {
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
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
00312
00313 m_file = std::auto_ptr<TFile>(new TFile(m_fileName.c_str(),"RECREATE",
00314 "1"
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
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());
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
00370 unsigned int digits = 0;
00371 while (numberOfChildren != 0) {
00372 ++digits;
00373 numberOfChildren /= 10;
00374 }
00375
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
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
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
00440
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
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
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
00503
00504 m_file->cd();
00505 TDirectory* metaDataDirectory = m_file->mkdir(kMetaDataDirectory);
00506
00507
00508
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,¶meterSetID);
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
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
00562 m_file->Write();
00563 m_file->Close();
00564 edm::Service<edm::JobReport> jr;
00565 jr->outputFileClosed(m_jrToken);
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575 void
00576 DQMRootOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
00577
00578
00579 edm::ParameterSetDescription desc;
00580 desc.setUnknown();
00581 descriptions.addDefault(desc);
00582
00583
00584
00585 }
00586
00587
00588 DEFINE_FWK_MODULE(DQMRootOutputModule);