CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DQMRootOutputModule.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FwkIO
4 // Class : DQMRootOutputModule
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Chris Jones
10 // Created: Fri Apr 29 13:26:29 CDT 2011
11 // $Id: DQMRootOutputModule.cc,v 1.16 2013/02/01 16:38:32 wdd Exp $
12 //
13 
14 // system include files
15 #include <algorithm>
16 #include <iostream>
17 #include <string>
18 #include <map>
19 #include <memory>
20 #include <vector>
21 #include <boost/shared_ptr.hpp>
22 #include <boost/filesystem.hpp>
23 #include "TFile.h"
24 #include "TTree.h"
25 #include "TString.h"
26 #include "TH1.h"
27 #include "TH2.h"
28 #include "TProfile.h"
29 
30 // user include files
41 
46 
47 #include "format.h"
48 
49 namespace {
50  class TreeHelperBase {
51  public:
52  TreeHelperBase(): m_wasFilled(false), m_firstIndex(0),m_lastIndex(0) {}
53  virtual ~TreeHelperBase(){}
54  void fill(MonitorElement* iElement) {
55  doFill(iElement);
56  if(m_wasFilled) {++m_lastIndex;}
57  m_wasFilled = true; }
58  bool wasFilled() const { return m_wasFilled;}
59  void getRangeAndReset(ULong64_t& iFirstIndex, ULong64_t& iLastIndex) {
60  iFirstIndex = m_firstIndex;
61  iLastIndex = m_lastIndex;
62  m_wasFilled = false;
63  m_firstIndex = m_lastIndex +1;
64  m_lastIndex = m_firstIndex;
65  }
66  private:
67  virtual void doFill(MonitorElement*) = 0;
68  bool m_wasFilled;
69  ULong64_t m_firstIndex;
70  ULong64_t m_lastIndex;
71  };
72 
73  template<class T>
74  class TreeHelper : public TreeHelperBase {
75  public:
76  TreeHelper(TTree* iTree, std::string* iFullNameBufferPtr ):
77  m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr){ setup();}
78  virtual void doFill(MonitorElement* iElement) {
79  *m_fullNameBufferPtr = iElement->getFullname();
80  m_flagBuffer = iElement->getTag();
81  m_bufferPtr = dynamic_cast<T*>(iElement->getRootObject());
82  assert(0!=m_bufferPtr);
83  //std::cout <<"#entries: "<<m_bufferPtr->GetEntries()<<std::endl;
84  m_tree->Fill();
85  }
86 
87 
88  private:
89  void setup() {
90  m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
91  m_tree->Branch(kFlagBranch,&m_flagBuffer);
92 
93  m_bufferPtr = 0;
94  m_tree->Branch(kValueBranch,&m_bufferPtr,128*1024,0);
95  }
96  TTree* m_tree;
97  uint32_t m_flagBuffer;
98  std::string* m_fullNameBufferPtr;
99  T* m_bufferPtr;
100  };
101 
102  class IntTreeHelper: public TreeHelperBase {
103  public:
104  IntTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr):
105  m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr)
106  {setup();}
107 
108  virtual void doFill(MonitorElement* iElement) {
109  *m_fullNameBufferPtr = iElement->getFullname();
110  m_flagBuffer = iElement->getTag();
111  m_buffer = iElement->getIntValue();
112  m_tree->Fill();
113  }
114 
115  private:
116  void setup() {
117  m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
118  m_tree->Branch(kFlagBranch,&m_flagBuffer);
119  m_tree->Branch(kValueBranch,&m_buffer);
120  }
121  TTree* m_tree;
122  uint32_t m_flagBuffer;
123  std::string* m_fullNameBufferPtr;
124  Long64_t m_buffer;
125  };
126 
127  class FloatTreeHelper: public TreeHelperBase {
128  public:
129  FloatTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr):
130  m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr)
131  {setup();}
132  virtual void doFill(MonitorElement* iElement) {
133  *m_fullNameBufferPtr = iElement->getFullname();
134  m_flagBuffer = iElement->getTag();
135  m_buffer = iElement->getFloatValue();
136  m_tree->Fill();
137  }
138  private:
139  void setup() {
140  m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
141  m_tree->Branch(kFlagBranch,&m_flagBuffer);
142  m_tree->Branch(kValueBranch,&m_buffer);
143  }
144 
145  TTree* m_tree;
146  uint32_t m_flagBuffer;
147  std::string* m_fullNameBufferPtr;
148  double m_buffer;
149  };
150 
151  class StringTreeHelper: public TreeHelperBase {
152  public:
153  StringTreeHelper(TTree* iTree, std::string* iFullNameBufferPtr):
154  m_tree(iTree), m_flagBuffer(0),m_fullNameBufferPtr(iFullNameBufferPtr), m_bufferPtr(&m_buffer)
155  {setup();}
156  virtual void doFill(MonitorElement* iElement) {
157  *m_fullNameBufferPtr = iElement->getFullname();
158  m_flagBuffer = iElement->getTag();
159  m_buffer = iElement->getStringValue();
160  m_tree->Fill();
161  }
162  private:
163  void setup() {
164  m_tree->Branch(kFullNameBranch,&m_fullNameBufferPtr);
165  m_tree->Branch(kFlagBranch,&m_flagBuffer);
166  m_tree->Branch(kValueBranch,&m_bufferPtr);
167  }
168 
169  TTree* m_tree;
170  uint32_t m_flagBuffer;
171  std::string* m_fullNameBufferPtr;
172  std::string m_buffer;
173  std::string* m_bufferPtr;
174  };
175 
176 }
177 
178 
180 public:
181  explicit DQMRootOutputModule(edm::ParameterSet const& pset);
182  virtual ~DQMRootOutputModule();
183  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
184 
185 private:
186  virtual void write(edm::EventPrincipal const& e);
188  virtual void writeRun(edm::RunPrincipal const&);
189  virtual bool isFileOpen() const;
190  virtual void openFile(edm::FileBlock const&);
191  virtual void postForkReacquireResources(unsigned int childIndex, unsigned int numberOfChildren) override final;
192 
193 
194  virtual void startEndFile();
195  virtual void finishEndFile();
198  std::auto_ptr<TFile> m_file;
199  std::vector<boost::shared_ptr<TreeHelperBase> > m_treeHelpers;
200 
201  unsigned int m_run;
202  unsigned int m_lumi;
203  unsigned int m_type;
204  unsigned int m_presentHistoryIndex;
205  ULong64_t m_beginTime;
206  ULong64_t m_endTime;
207  ULong64_t m_firstIndex;
208  ULong64_t m_lastIndex;
209  unsigned int m_filterOnRun;
210 
213  std::map<unsigned int, unsigned int> m_dqmKindToTypeIndex;
215 
216  std::vector<edm::ProcessHistoryID> m_seenHistories;
218 };
219 
220 //
221 // constants, enums and typedefs
222 //
223 
224 static TreeHelperBase*
225 makeHelper(unsigned int iTypeIndex,
226  TTree* iTree,
227  std::string* iFullNameBufferPtr) {
228  switch(iTypeIndex) {
229  case kIntIndex:
230  return new IntTreeHelper(iTree,iFullNameBufferPtr);
231  case kFloatIndex:
232  return new FloatTreeHelper(iTree,iFullNameBufferPtr);
233  case kStringIndex:
234  return new StringTreeHelper(iTree,iFullNameBufferPtr);
235  case kTH1FIndex:
236  return new TreeHelper<TH1F>(iTree,iFullNameBufferPtr);
237  case kTH1SIndex:
238  return new TreeHelper<TH1S>(iTree,iFullNameBufferPtr);
239  case kTH1DIndex:
240  return new TreeHelper<TH1D>(iTree,iFullNameBufferPtr);
241  case kTH2FIndex:
242  return new TreeHelper<TH2F>(iTree,iFullNameBufferPtr);
243  case kTH2SIndex:
244  return new TreeHelper<TH2S>(iTree,iFullNameBufferPtr);
245  case kTH2DIndex:
246  return new TreeHelper<TH2D>(iTree,iFullNameBufferPtr);
247  case kTH3FIndex:
248  return new TreeHelper<TH3F>(iTree,iFullNameBufferPtr);
249  case kTProfileIndex:
250  return new TreeHelper<TProfile>(iTree,iFullNameBufferPtr);
251  case kTProfile2DIndex:
252  return new TreeHelper<TProfile2D>(iTree,iFullNameBufferPtr);
253  }
254  assert(false);
255  return 0;
256 }
257 
258 //
259 // static data member definitions
260 //
261 
262 //
263 // constructors and destructor
264 //
266 edm::OutputModule(pset),
267 m_fileName(pset.getUntrackedParameter<std::string>("fileName")),
268 m_logicalFileName(pset.getUntrackedParameter<std::string>("logicalFileName","")),
269 m_file(0),
270 m_treeHelpers(kNIndicies,boost::shared_ptr<TreeHelperBase>()),
271 m_presentHistoryIndex(0),
272 m_filterOnRun(pset.getUntrackedParameter<unsigned int>("filterOnRun",0)),
273 m_fullNameBufferPtr(&m_fullNameBuffer),
274 m_indicesTree(0)
275 {
276 }
277 
278 // DQMRootOutputModule::DQMRootOutputModule(const DQMRootOutputModule& rhs)
279 // {
280 // // do actual copying here;
281 // }
282 
284 {
285 }
286 
287 //
288 // assignment operators
289 //
290 // const DQMRootOutputModule& DQMRootOutputModule::operator=(const DQMRootOutputModule& rhs)
291 // {
292 // //An exception safe implementation is
293 // DQMRootOutputModule temp(rhs);
294 // swap(rhs);
295 //
296 // return *this;
297 // }
298 
299 //
300 // member functions
301 //
302 bool
304 {
305  return nullptr!=m_file.get();
306 }
307 
308 void
310 {
311  //NOTE: I need to also set the I/O performance settings
312 
313  m_file = std::auto_ptr<TFile>(new TFile(m_fileName.c_str(),"RECREATE",
314  "1" //This is the file format version number
315  ));
316 
318  cms::Digest branchHash;
321  std::string(),
322  "DQMRootOutputModule",
323  description().moduleLabel(),
325  std::string(),
326  branchHash.digest().toString(),
327  std::vector<std::string>()
328  );
329 
330 
332  m_indicesTree->Branch(kRunBranch,&m_run);
333  m_indicesTree->Branch(kLumiBranch,&m_lumi);
337  m_indicesTree->Branch(kTypeBranch,&m_type);
340  m_indicesTree->SetDirectory(m_file.get());
341 
342  unsigned int i = 0;
343  for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
344  it != itEnd;
345  ++it,++i) {
346  //std::cout <<"making "<<kTypeNames[i]<<std::endl;
347  TTree* tree = new TTree(kTypeNames[i],kTypeNames[i]);
348  *it = boost::shared_ptr<TreeHelperBase>(makeHelper(i,tree,m_fullNameBufferPtr));
349  tree->SetDirectory(m_file.get()); //TFile takes ownership
350  }
351 
364 }
365 
366 
367 void
368 DQMRootOutputModule::postForkReacquireResources(unsigned int childIndex, unsigned int numberOfChildren) {
369  // this is copied from IOPool/Output/src/PoolOutputModule.cc, for consistency
370  unsigned int digits = 0;
371  while (numberOfChildren != 0) {
372  ++digits;
373  numberOfChildren /= 10;
374  }
375  // protect against zero numberOfChildren
376  if (digits == 0) {
377  digits = 3;
378  }
379 
380  char buffer[digits + 2];
381  snprintf(buffer, digits + 2, "_%0*d", digits, childIndex);
382 
384  m_fileName = (filename.parent_path() / (filename.stem().string() + buffer + filename.extension().string())).string();
385 }
386 
387 
388 void
390 
391 }
392 void
394  //std::cout << "DQMRootOutputModule::writeLuminosityBlock"<< std::endl;
395  edm::Service<DQMStore> dstore;
396  m_run=iLumi.id().run();
397  m_lumi = iLumi.id().value();
398  m_beginTime = iLumi.beginTime().value();
399  m_endTime = iLumi.endTime().value();
400  bool shouldWrite = (m_filterOnRun == 0 ||
401  (m_filterOnRun != 0 && m_filterOnRun == m_run));
402 
403  if (! shouldWrite)
404  return;
405  std::vector<MonitorElement *> items(dstore->getAllContents(""));
406  for(std::vector<MonitorElement*>::iterator it = items.begin(), itEnd=items.end();
407  it!=itEnd;
408  ++it) {
409  if((*it)->getLumiFlag()) {
410  std::map<unsigned int,unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((*it)->kind());
411  assert(itFound !=m_dqmKindToTypeIndex.end());
412  m_treeHelpers[itFound->second]->fill(*it);
413  }
414  }
415 
417  std::vector<edm::ProcessHistoryID>::iterator itFind = std::find(m_seenHistories.begin(),m_seenHistories.end(),id);
418  if(itFind == m_seenHistories.end()) {
420  m_seenHistories.push_back(id);
421  } else {
422  m_presentHistoryIndex = itFind - m_seenHistories.begin();
423  }
424 
425  //Now store the relationship between run/lumi and indices in the other TTrees
426  bool storedLumiIndex = false;
427  unsigned int typeIndex = 0;
428  for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
429  it != itEnd;
430  ++it,++typeIndex) {
431  if((*it)->wasFilled()) {
432  m_type = typeIndex;
433  (*it)->getRangeAndReset(m_firstIndex,m_lastIndex);
434  storedLumiIndex = true;
435  m_indicesTree->Fill();
436  }
437  }
438  if(not storedLumiIndex) {
439  //need to record lumis even if we stored no MonitorElements since some later DQM modules
440  // look to see what lumis were processed
442  m_firstIndex=0;
443  m_lastIndex=0;
444  m_indicesTree->Fill();
445  }
446 
449 }
450 
451 
453  //std::cout << "DQMRootOutputModule::writeRun"<< std::endl;
454  edm::Service<DQMStore> dstore;
455  m_run=iRun.id().run();
456  m_lumi = 0;
457  m_beginTime = iRun.beginTime().value();
458  m_endTime = iRun.endTime().value();
459  bool shouldWrite = (m_filterOnRun == 0 ||
460  (m_filterOnRun != 0 && m_filterOnRun == m_run));
461 
462  if (! shouldWrite)
463  return;
464 
465  std::vector<MonitorElement *> items(dstore->getAllContents(""));
466  for(std::vector<MonitorElement*>::iterator it = items.begin(), itEnd=items.end();
467  it!=itEnd;
468  ++it) {
469  if(not (*it)->getLumiFlag()) {
470  std::map<unsigned int,unsigned int>::iterator itFound = m_dqmKindToTypeIndex.find((*it)->kind());
471  assert (itFound !=m_dqmKindToTypeIndex.end());
472  m_treeHelpers[itFound->second]->fill(*it);
473  }
474  }
475 
477  std::vector<edm::ProcessHistoryID>::iterator itFind = std::find(m_seenHistories.begin(),m_seenHistories.end(),id);
478  if(itFind == m_seenHistories.end()) {
480  m_seenHistories.push_back(id);
481  } else {
482  m_presentHistoryIndex = itFind - m_seenHistories.begin();
483  }
484 
485  //Now store the relationship between run/lumi and indices in the other TTrees
486  unsigned int typeIndex = 0;
487  for(std::vector<boost::shared_ptr<TreeHelperBase> >::iterator it = m_treeHelpers.begin(), itEnd = m_treeHelpers.end();
488  it != itEnd;
489  ++it,++typeIndex) {
490  if((*it)->wasFilled()) {
491  m_type = typeIndex;
492  (*it)->getRangeAndReset(m_firstIndex,m_lastIndex);
493  m_indicesTree->Fill();
494  }
495  }
496 
498  jr->reportRunNumber(m_run);
499 }
500 
502  //std::cout << "DQMRootOutputModule::startEndFile"<< std::endl;
503  //fill in the meta data
504  m_file->cd();
505  TDirectory* metaDataDirectory = m_file->mkdir(kMetaDataDirectory);
506 
507 
508  //Write out the Process History
509  TTree* processHistoryTree = new TTree(kProcessHistoryTree,kProcessHistoryTree);
510  processHistoryTree->SetDirectory(metaDataDirectory);
511 
512  unsigned int index = 0;
513  processHistoryTree->Branch(kPHIndexBranch,&index);
515  processHistoryTree->Branch(kProcessConfigurationProcessNameBranch,&processName);
516  std::string parameterSetID;
517  processHistoryTree->Branch(kProcessConfigurationParameterSetIDBranch,&parameterSetID);
518  std::string releaseVersion;
519  processHistoryTree->Branch(kProcessConfigurationReleaseVersion,&releaseVersion);
520  std::string passID;
521  processHistoryTree->Branch(kProcessConfigurationPassID,&passID);
522 
524  assert(0!=phr);
525  for(std::vector<edm::ProcessHistoryID>::iterator it = m_seenHistories.begin(), itEnd = m_seenHistories.end();
526  it !=itEnd;
527  ++it) {
528  const edm::ProcessHistory* history = phr->getMapped(*it);
529  assert(0!=history);
530  index = 0;
531  for(edm::ProcessHistory::collection_type::const_iterator itPC = history->begin(), itPCEnd = history->end();
532  itPC != itPCEnd;
533  ++itPC,++index) {
534  processName = itPC->processName();
535  releaseVersion = itPC->releaseVersion();
536  passID = itPC->passID();
537  parameterSetID = itPC->parameterSetID().compactForm();
538  processHistoryTree->Fill();
539  }
540  }
541 
542  //Store the ParameterSets
543  TTree* parameterSetsTree = new TTree(kParameterSetTree,kParameterSetTree);
544  parameterSetsTree->SetDirectory(metaDataDirectory);
545  std::string blob;
546  parameterSetsTree->Branch(kParameterSetBranch,&blob);
547 
549  assert(0!=psr);
550  for(edm::pset::Registry::const_iterator it = psr->begin(), itEnd = psr->end();
551  it != itEnd;
552  ++it) {
553  blob.clear();
554  it->second.toString(blob);
555  parameterSetsTree->Fill();
556  }
557 
558 }
559 
561  //std::cout << "DQMRootOutputModule::finishEndFile"<< std::endl;
562  m_file->Write();
563  m_file->Close();
566 }
567 
568 //
569 // const member functions
570 //
571 
572 //
573 // static member functions
574 //
575 void
577  //The following says we do not know what parameters are allowed so do no validation
578  // Please change this to state exactly what you do use, even if it is no parameters
580  desc.setUnknown();
581  descriptions.addDefault(desc);
582 
583  //NOTE: when actually filling this in, do not forget to add a untracked PSet 'dataset'
584  // which is used for bookkeeping by the DMWM
585 }
586 
587 
virtual bool isFileOpen() const
const_iterator begin() const
Token outputFileOpened(std::string const &physicalFileName, std::string const &logicalFileName, std::string const &catalog, std::string const &outputModuleClassName, std::string const &moduleLabel, std::string const &guid, std::string const &dataType, std::string const &branchHash, std::vector< std::string > const &branchNames)
Definition: JobReport.cc:561
int i
Definition: DBlmapReader.cc:9
static const char *const kProcessHistoryTree
Definition: format.h:55
static const char *const kRunBranch
Definition: format.h:42
virtual void write(edm::EventPrincipal const &e)
static const char *const kTypeNames[]
Definition: format.h:29
string fill
Definition: lumiContext.py:319
Timestamp const & beginTime() const
RunNumber_t run() const
Definition: RunID.h:44
virtual void writeRun(edm::RunPrincipal const &)
virtual void openFile(edm::FileBlock const &)
static ThreadSafeRegistry * instance()
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
static const char *const kIndicesTree
Definition: format.h:41
Timestamp const & endTime() const
unsigned int m_presentHistoryIndex
boost::uint64_t value() const
static TreeHelperBase * makeHelper(unsigned int iTypeIndex, TTree *iTree, std::string *iFullNameBufferPtr)
static const char *const kFirstIndex
Definition: format.h:48
std::string const & processName() const
Definition: OutputModule.h:60
bool getMapped(key_type const &k, value_type &result) const
static const char *const kLumiBranch
Definition: format.h:43
static const char *const kFullNameBranch
Definition: format.h:35
MD5Result digest() const
Definition: Digest.cc:194
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
void outputFileClosed(Token fileToken)
Definition: JobReport.cc:600
const uint32_t getTag(void) const
std::vector< MonitorElement * > getAllContents(const std::string &path) const
Definition: DQMStore.cc:1677
static const char *const kPHIndexBranch
Definition: format.h:56
static const char *const kParameterSetBranch
Definition: format.h:63
std::map< unsigned int, unsigned int > m_dqmKindToTypeIndex
void addDefault(ParameterSetDescription const &psetDescription)
virtual void finishEndFile()
ProcessHistoryID const & processHistoryID() const
Definition: Principal.h:129
static const char *const kMetaDataDirectory
Definition: format.h:53
Timestamp const & beginTime() const
Definition: RunPrincipal.h:54
std::auto_ptr< TFile > m_file
collection_type::const_iterator const_iterator
static const char *const kParameterSetTree
Definition: format.h:62
double getFloatValue(void) const
RunNumber_t run() const
Timestamp const & endTime() const
Definition: RunPrincipal.h:58
static const char *const kFlagBranch
Definition: format.h:36
static const char *const kTypeBranch
Definition: format.h:47
static const char *const kProcessHistoryIndexBranch
Definition: format.h:44
virtual void postForkReacquireResources(unsigned int childIndex, unsigned int numberOfChildren) overridefinal
static const char *const kEndTimeBranch
Definition: format.h:46
const std::string getFullname(void) const
get full name of ME including Pathname
const std::string & getStringValue(void) const
std::size_t Token
Definition: JobReport.h:43
DQMRootOutputModule(edm::ParameterSet const &pset)
static const char *const kProcessConfigurationPassID
Definition: format.h:60
doFill
Definition: cuy.py:574
RunID const & id() const
Definition: RunPrincipal.h:50
TimeValue_t value() const
Definition: Timestamp.cc:72
std::vector< boost::shared_ptr< TreeHelperBase > > m_treeHelpers
std::string * m_fullNameBufferPtr
TObject * getRootObject(void) const
void reportLumiSection(unsigned int run, unsigned int lumiSectId)
Definition: JobReport.cc:653
static const char *const kLastIndex
Definition: format.h:49
int64_t getIntValue(void) const
std::string toString() const
Definition: Digest.cc:87
static const char *const kProcessConfigurationReleaseVersion
Definition: format.h:59
static const char *const kProcessConfigurationProcessNameBranch
Definition: format.h:57
const_iterator end() const
static const char *const kBeginTimeBranch
Definition: format.h:45
virtual void writeLuminosityBlock(edm::LuminosityBlockPrincipal const &)
tuple filename
Definition: lut2db_cfg.py:20
edm::JobReport::Token m_jrToken
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
long double T
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
ModuleDescription const & description() const
std::string createGlobalIdentifier()
static const char *const kValueBranch
Definition: format.h:37
void reportRunNumber(unsigned int run)
Definition: JobReport.cc:663
static const char *const kProcessConfigurationParameterSetIDBranch
Definition: format.h:58
std::vector< edm::ProcessHistoryID > m_seenHistories