CMS 3D CMS Logo

EventContentAnalyzer.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Modules
4 // Class: EventContentAnalyzer
5 //
12 //
13 // Original Author: Chris Jones
14 // Created: Mon Sep 19 11:47:28 CEST 2005
15 //
16 //
17 
18 // user include files
36 
37 // system include files
38 #include <algorithm>
39 #include <iomanip>
40 #include <iostream>
41 #include <map>
42 #include <sstream>
43 #include <string>
44 #include <vector>
45 
46 namespace edm {
48  namespace {
49  std::string formatClassName(std::string const& iName) {
50  return std::string("(")+iName+")";
51  }
52 
53  char const* kNameValueSep = "=";
55  template<typename T>
56  void doPrint(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
57  LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << *reinterpret_cast<T*>(iObject.address());// << "\n";
58  }
59 
60  template<>
61  void doPrint<char>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
62  LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << static_cast<int>(*reinterpret_cast<char*>(iObject.address()));// << "\n";
63  }
64 
65  template<>
66  void doPrint<unsigned char>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
67  LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << static_cast<unsigned int>(*reinterpret_cast<unsigned char*>(iObject.address()));// << "\n";
68  }
69 
70  template<>
71  void doPrint<bool>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
72  LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << ((*reinterpret_cast<bool*>(iObject.address()))?"true":"false");// << "\n";
73  }
74 
75  typedef void(*FunctionType)(std::string const&, ObjectWithDict const&, std::string const&);
76  typedef std::map<std::string, FunctionType> TypeToPrintMap;
77 
78  template<typename T>
79  void addToMap(TypeToPrintMap& iMap) {
80  iMap[typeid(T).name()] = doPrint<T>;
81  }
82 
83  bool printAsBuiltin(std::string const& iName,
84  ObjectWithDict const& iObject,
85  std::string const& iIndent) {
86  typedef void(*FunctionType)(std::string const&, ObjectWithDict const&, std::string const&);
87  typedef std::map<std::string, FunctionType> TypeToPrintMap;
88  static TypeToPrintMap s_map;
89  static bool isFirst = true;
90  if(isFirst) {
91  addToMap<bool>(s_map);
92  addToMap<char>(s_map);
93  addToMap<short>(s_map);
94  addToMap<int>(s_map);
95  addToMap<long>(s_map);
96  addToMap<unsigned char>(s_map);
97  addToMap<unsigned short>(s_map);
98  addToMap<unsigned int>(s_map);
99  addToMap<unsigned long>(s_map);
100  addToMap<float>(s_map);
101  addToMap<double>(s_map);
102  isFirst = false;
103  }
104  TypeToPrintMap::iterator itFound = s_map.find(iObject.typeOf().name());
105  if(itFound == s_map.end()) {
106 
107  return false;
108  }
109  itFound->second(iName, iObject, iIndent);
110  return true;
111  }
112 
113  bool printAsContainer(std::string const& iName,
114  ObjectWithDict const& iObject,
115  std::string const& iIndent,
116  std::string const& iIndentDelta);
117 
118  void printObject(std::string const& iName,
119  ObjectWithDict const& iObject,
120  std::string const& iIndent,
121  std::string const& iIndentDelta) {
122  const std::string& printName = iName;
123  const ObjectWithDict& objectToPrint = iObject;
124  std::string indent(iIndent);
125  if(iObject.typeOf().isPointer()) {
126  LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << formatClassName(iObject.typeOf().name()) << std::hex << iObject.address() << std::dec;// << "\n";
127  TypeWithDict pointedType = iObject.typeOf().toType(); // for Pointers, I get the real type this way
128  if(TypeWithDict::byName("void") == pointedType ||
129  pointedType.isPointer() ||
130  iObject.address() == nullptr) {
131  return;
132  }
133  return;
134  /*
135  //have the code that follows print the contents of the data to which the pointer points
136  objectToPrint = ObjectWithDict(pointedType, iObject.address());
137  //try to convert it to its actual type (assuming the original type was a base class)
138  objectToPrint = ObjectWithDict(objectToPrint.castObject(objectToPrint.dynamicType()));
139  printName = std::string("*")+iName;
140  indent += iIndentDelta;
141  */
142  }
143  std::string typeName(objectToPrint.typeOf().name());
144  if(typeName.empty()) {
145  typeName = "<unknown>";
146  }
147 
148  if(printAsBuiltin(printName, objectToPrint, indent)) {
149  return;
150  }
151  if(printAsContainer(printName, objectToPrint, indent, iIndentDelta)) {
152  return;
153  }
154 
155  LogAbsolute("EventContent") << indent << printName << " " << formatClassName(typeName);// << "\n";
156  indent += iIndentDelta;
157  //print all the data members
158  TypeDataMembers dataMembers(objectToPrint.typeOf());
159  for(auto const& dataMember : dataMembers) {
160  MemberWithDict const member(dataMember);
161  //LogAbsolute("EventContent") << " debug " << member.name() << " " << member.typeName() << "\n";
162  try {
163  printObject(member.name(),
164  member.get(objectToPrint),
165  indent,
166  iIndentDelta);
167  }catch(std::exception& iEx) {
168  LogAbsolute("EventContent") << indent << member.name() << " <exception caught(" << iEx.what() << ")>\n";
169  }
170  }
171  }
172 
173  bool printAsContainer(std::string const& iName,
174  ObjectWithDict const& iObject,
175  std::string const& iIndent,
176  std::string const& iIndentDelta) {
177  ObjectWithDict sizeObj;
178  try {
179  size_t temp; //used to hold the memory for the return value
180  FunctionWithDict sizeFunc = iObject.typeOf().functionMemberByName("size");
181  assert(sizeFunc.finalReturnType() == typeid(size_t));
182  sizeObj = ObjectWithDict(TypeWithDict(typeid(size_t)), &temp);
183  sizeFunc.invoke(iObject, &sizeObj);
184  //std::cout << "size of type '" << sizeObj.name() << "' " << sizeObj.typeName() << std::endl;
185  size_t size = *reinterpret_cast<size_t*>(sizeObj.address());
186  FunctionWithDict atMember;
187  try {
188  atMember = iObject.typeOf().functionMemberByName("at");
189  } catch(std::exception const& x) {
190  //std::cerr << "could not get 'at' member because " << x.what() << std::endl;
191  return false;
192  }
193  LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << "[size=" << size << "]";//"\n";
194  ObjectWithDict contained;
195  std::string indexIndent = iIndent + iIndentDelta;
196  TypeWithDict atReturnType(atMember.finalReturnType());
197  //std::cout << "return type " << atReturnType.name() << " size of " << atReturnType.SizeOf()
198  // << " pointer? " << atReturnType.isPointer() << " ref? " << atReturnType.isReference() << std::endl;
199 
200  //Return by reference must be treated differently since reflex will not properly create
201  // memory for a ref (which should just be a pointer to the object and not the object itself)
202  //So we will create memory on the stack which can be used to hold a reference
203  bool const isRef = atReturnType.isReference();
204  void* refMemoryBuffer = nullptr;
205  size_t index = 0;
206  //The argument to the 'at' function is the index. Since the argument list holds pointers to the arguments
207  // we only need to create it once and then when the value of index changes the pointer already
208  // gets the new value
209  std::vector<void*> args;
210  args.push_back(&index);
211  for(; index != size; ++index) {
212  std::ostringstream sizeS;
213  sizeS << "[" << index << "]";
214  if(isRef) {
215  ObjectWithDict refObject(atReturnType, &refMemoryBuffer);
216  atMember.invoke(iObject, &refObject, args);
217  //Although to hold the return value from a reference reflex requires you to pass it a
218  // void** when it tries to call methods on the reference it expects to be given a void*
219  contained = ObjectWithDict(atReturnType, refMemoryBuffer);
220  } else {
221  contained = atReturnType.construct();
222  atMember.invoke(iObject, &contained, args);
223  }
224  //LogAbsolute("EventContent") << "invoked 'at'" << std::endl;
225  try {
226  printObject(sizeS.str(), contained, indexIndent, iIndentDelta);
227  } catch(std::exception& iEx) {
228  LogAbsolute("EventContent") << indexIndent << iName << " <exception caught("
229  << iEx.what() << ")>\n";
230  }
231  if(!isRef) {
232  contained.destruct(true);
233  }
234  }
235  return true;
236  } catch(std::exception const& x) {
237  //std::cerr << "failed to invoke 'at' because " << x.what() << std::endl;
238  return false;
239  }
240  return false;
241  }
242 
243  void printObject(Event const& iEvent,
244  std::string const& iClassName,
245  std::string const& iModuleLabel,
246  std::string const& iInstanceLabel,
247  std::string const& iProcessName,
248  std::string const& iIndent,
249  std::string const& iIndentDelta) {
250  try {
251  GenericHandle handle(iClassName);
252  }catch(edm::Exception const&) {
253  LogAbsolute("EventContent") << iIndent << " \"" << iClassName << "\"" << " is an unknown type" << std::endl;
254  return;
255  }
256  GenericHandle handle(iClassName);
257  iEvent.getByLabel(InputTag(iModuleLabel, iInstanceLabel, iProcessName), handle);
258  std::string className = formatClassName(iClassName);
259  printObject(className, *handle, iIndent, iIndentDelta);
260  }
261  }
262 
264  public:
265  explicit EventContentAnalyzer(ParameterSet const&);
266  ~EventContentAnalyzer() override;
267 
268  void analyze(Event const&, EventSetup const&) override;
269  void endJob() override;
270 
271  static void fillDescriptions(ConfigurationDescriptions& descriptions);
272 
273  private:
274 
275  // ----------member data ---------------------------
276  std::string indentation_;
277  std::string verboseIndentation_;
278  std::vector<std::string> moduleLabels_;
279  bool verbose_;
280  std::vector<std::string> getModuleLabels_;
281  bool getData_;
282  int evno_;
283  std::map<std::string, int> cumulates_;
286  };
287 
288  //
289  // constructors and destructor
290  //
292  indentation_(iConfig.getUntrackedParameter("indentation", std::string("++"))),
293  verboseIndentation_(iConfig.getUntrackedParameter("verboseIndentation", std::string(" "))),
294  moduleLabels_(iConfig.getUntrackedParameter("verboseForModuleLabels", std::vector<std::string>())),
295  verbose_(iConfig.getUntrackedParameter("verbose", false) || !moduleLabels_.empty()),
296  getModuleLabels_(iConfig.getUntrackedParameter("getDataForModuleLabels", std::vector<std::string>())),
297  getData_(iConfig.getUntrackedParameter("getData", false) || !getModuleLabels_.empty()),
298  evno_(1),
299  listContent_(iConfig.getUntrackedParameter("listContent", true)),
300  listProvenance_(iConfig.getUntrackedParameter("listProvenance", false))
301  {
302  //now do what ever initialization is needed
305  if(getData_) {
307  if(getModuleLabels_.empty()) {
308  const std::string kPathStatus("edm::PathStatus");
309  const std::string kEndPathStatus("edm::EndPathStatus");
310  if(iBranch.className() != kPathStatus && iBranch.className() != kEndPathStatus) {
312  edm::InputTag{iBranch.moduleLabel(),iBranch.productInstanceName(),iBranch.processName()});
313  }
314  } else {
315  for (auto const& mod : this->getModuleLabels_) {
316  if (iBranch.moduleLabel() == mod) {
318  edm::InputTag{mod,iBranch.productInstanceName(),iBranch.processName()});
319  break;
320  }
321  }
322  }
323  }
324  );
325  }
326 
327  }
328 
330 
331  // do anything here that needs to be done at destruction time
332  // (e.g. close files, deallocate resources etc.)
333 
334  }
335 
336  //
337  // member functions
338  //
339 
340  // ------------ method called to produce the data ------------
341  void
343  typedef std::vector<StableProvenance const*> Provenances;
344  Provenances provenances;
345 
346  iEvent.getAllStableProvenance(provenances);
347 
348  if(listContent_) {
349  LogAbsolute("EventContent") << "\n" << indentation_ << "Event " << std::setw(5) << evno_ << " contains "
350  << provenances.size() << " product" << (provenances.size() == 1 ? "" : "s")
351  << " with friendlyClassName, moduleLabel, productInstanceName and processName:"
352  << std::endl;
353  }
354 
355  std::string startIndent = indentation_+verboseIndentation_;
356  for(auto const& provenance : provenances) {
357  std::string const& className = provenance->className();
358  const std::string kPathStatus("edm::PathStatus");
359  const std::string kEndPathStatus("edm::EndPathStatus");
360  if(className == kPathStatus || className == kEndPathStatus) {
361  continue;
362  }
363  std::string const& friendlyName = provenance->friendlyClassName();
364  //if(friendlyName.empty()) friendlyName = std::string("||");
365 
366  std::string const& modLabel = provenance->moduleLabel();
367  //if(modLabel.empty()) modLabel = std::string("||");
368 
369  std::string const& instanceName = provenance->productInstanceName();
370  //if(instanceName.empty()) instanceName = std::string("||");
371 
372  std::string const& processName = provenance->processName();
373 
374  bool doVerbose = verbose_ && (moduleLabels_.empty() ||
375  binary_search_all(moduleLabels_, modLabel));
376 
377  if(listContent_ || doVerbose) {
378  LogAbsolute("EventContent") << indentation_ << friendlyName
379  << " \"" << modLabel
380  << "\" \"" << instanceName << "\" \""
381  << processName << "\""
382  << " (productId = " << provenance->productID() << ")"
383  << std::endl;
384 
385  if(listProvenance_) {
386  auto const& prov = iEvent.getProvenance(provenance->branchID());
387  auto const *productProvenance = prov.productProvenance();
388  if(productProvenance) {
389  const bool isAlias = productProvenance->branchID() != provenance->branchID();
390  std::string aliasForModLabel;
391  LogAbsolute("EventContent") << prov;
392  if(isAlias) {
393  aliasForModLabel = iEvent.getProvenance(productProvenance->branchID()).moduleLabel();
394  LogAbsolute("EventContent") << "Is an alias for " << aliasForModLabel;
395  }
396  ProcessHistory const *processHistory = prov.processHistoryPtr();
397  if(processHistory) {
398  for(ProcessConfiguration const& pc: *processHistory) {
399  if(pc.processName() == prov.processName()) {
400  ParameterSetID const& psetID = pc.parameterSetID();
401  pset::Registry const* psetRegistry = pset::Registry::instance();
402  ParameterSet const* processPset = psetRegistry->getMapped(psetID);
403  if (processPset) {
404  if(processPset->existsAs<ParameterSet>(modLabel)) {
405  if(isAlias) {
406  LogAbsolute("EventContent") << "Alias PSet";
407  }
408  LogAbsolute("EventContent") << processPset->getParameterSet(modLabel);
409  }
410  if(isAlias and processPset->existsAs<ParameterSet>(aliasForModLabel)) {
411  LogAbsolute("EventContent") << processPset->getParameterSet(aliasForModLabel);
412  }
413  }
414  }
415  }
416  }
417  }
418  }
419  }
420  std::string key = friendlyName
421  + std::string(" + \"") + modLabel
422  + std::string("\" + \"") + instanceName + "\" \"" + processName + "\"";
423  ++cumulates_[key];
424 
425  if(doVerbose) {
426  //indent one level before starting to print
427  printObject(iEvent,
428  className,
429  modLabel,
430  instanceName,
431  processName,
432  startIndent,
433  verboseIndentation_);
434  continue;
435  }
436  if(getData_) {
437  std::string class_and_label = friendlyName + "_" + modLabel;
438  if(getModuleLabels_.empty() ||
439  binary_search_all(getModuleLabels_, modLabel) ||
440  binary_search_all(getModuleLabels_, class_and_label)) {
441  try {
442  GenericHandle handle(className);
443  } catch(edm::Exception const&) {
444  LogAbsolute("EventContent") << startIndent << " \"" << className << "\"" << " is an unknown type" << std::endl;
445  return;
446  }
447  GenericHandle handle(className);
448  iEvent.getByLabel(InputTag(modLabel,
449  instanceName,
450  processName),
451  handle);
452  }
453  }
454  }
455  //std::cout << "Mine" << std::endl;
456  ++evno_;
457  }
458 
459  // ------------ method called at end of job -------------------
460  void
462  typedef std::map<std::string, int> nameMap;
463 
464  LogAbsolute("EventContent") << "\nSummary for key being the concatenation of friendlyClassName, moduleLabel, productInstanceName and processName" << std::endl;
465  for(nameMap::const_iterator it = cumulates_.begin(), itEnd = cumulates_.end();
466  it != itEnd;
467  ++it) {
468  LogAbsolute("EventContent") << std::setw(6) << it->second << " occurrences of key " << it->first << std::endl;
469  }
470 
471  // Test boost::lexical_cast We don't need this right now so comment it out.
472  // int k = 137;
473  // std::string ktext = boost::lexical_cast<std::string>(k);
474  // std::cout << "\nInteger " << k << " expressed as a string is |" << ktext << "|" << std::endl;
475  }
476 
477  void
479 
480  descriptions.setComment("This plugin will print a list of all products in the event "
481  "provenance. It also has options to print and/or get each product.");
482 
484 
486 
487  std::string defaultString("++");
488  np = desc.addOptionalUntracked<std::string>("indentation", defaultString);
489  np->setComment("This string is printed at the beginning of every line printed during event processing.");
490 
491  np = desc.addOptionalUntracked<bool>("verbose", false);
492  np->setComment("If true, the contents of products are printed.");
493 
494  defaultString = " ";
495  np = desc.addOptionalUntracked<std::string>("verboseIndentation", defaultString);
496  np->setComment("This string is used to further indent lines when printing the contents of products in verbose mode.");
497 
498  std::vector<std::string> defaultVString;
499 
500  np = desc.addOptionalUntracked<std::vector<std::string> >("verboseForModuleLabels", defaultVString);
501  np->setComment("If this vector is not empty, then only products with module labels on this list are printed.");
502 
503  np = desc.addOptionalUntracked<bool>("getData", false);
504  np->setComment("If true the products will be retrieved using getByLabel.");
505 
506  np = desc.addOptionalUntracked<std::vector<std::string> >("getDataForModuleLabels", defaultVString);
507  np->setComment("If this vector is not empty, then only products with module labels on this list are retrieved by getByLabel.");
508 
509  np = desc.addOptionalUntracked<bool>("listContent", true);
510  np->setComment("If true then print a list of all the event content.");
511 
512  np = desc.addOptionalUntracked<bool>("listProvenance", false);
513  np->setComment("If true, and if listContent or verbose is true, print provenance information for each product");
514 
515  descriptions.add("printContent", desc);
516  }
517 }
518 
size
Write out results.
std::vector< std::string > getModuleLabels_
void setComment(std::string const &value)
BranchID const & branchID() const
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:185
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
std::string const & processName() const
std::map< std::string, int > cumulates_
ProductProvenance const * productProvenance() const
Definition: Provenance.cc:35
static TypeWithDict byName(std::string const &name)
Definition: TypeWithDict.cc:82
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
int iEvent
Definition: GenABIO.cc:230
void analyze(Event const &, EventSetup const &) override
std::string const & className() const
int np
Definition: AMPTWrapper.h:33
std::string friendlyName(std::string const &iFullName)
std::string const & moduleLabel() const
std::string const & productInstanceName() const
TypeID unwrappedTypeID() const
bool getMapped(key_type const &k, value_type &result) const
Definition: Registry.cc:19
static void fillDescriptions(ConfigurationDescriptions &descriptions)
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
Definition: Event.h:535
isFirst
Definition: cuy.py:419
void setComment(std::string const &value)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void sort_all(RandomAccessSequence &s)
wrappers for std::sort
Definition: Algorithms.h:120
ParameterSet const & getParameterSet(std::string const &) const
std::vector< std::string > moduleLabels_
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void callWhenNewProductsRegistered(std::function< void(BranchDescription const &)> const &func)
Definition: EDAnalyzer.cc:104
HLT enums.
bool binary_search_all(ForwardSequence const &s, Datum const &d)
wrappers for std::binary_search
Definition: Algorithms.h:76
ParameterDescriptionBase * addOptionalUntracked(U const &iLabel, T const &value)
bool isPointer() const
Provenance getProvenance(BranchID const &theID) const
Definition: Event.cc:129
long double T
T mod(const T &a, const T &b)
Definition: ecalDccMap.h:4
static const bool doPrint
EventContentAnalyzer(ParameterSet const &)
virtual example_stream void analyze(const edm::Event &, const edm::EventSetup &) override
static Registry * instance()
Definition: Registry.cc:13
std::string className(const T &t)
Definition: ClassName.h:30
void getAllStableProvenance(std::vector< StableProvenance const * > &provenances) const
Definition: Event.cc:144