CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/FWCore/Modules/src/EventContentAnalyzer.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    Modules
00004 // Class:      EventContentAnalyzer
00005 //
00012 //
00013 // Original Author:  Chris Jones
00014 //         Created:  Mon Sep 19 11:47:28 CEST 2005
00015 //
00016 //
00017 
00018 // user include files
00019 #include "DataFormats/Provenance/interface/Provenance.h"
00020 #include "FWCore/Framework/interface/EDAnalyzer.h"
00021 #include "FWCore/Framework/interface/Event.h"
00022 #include "FWCore/Framework/interface/GenericHandle.h"
00023 #include "FWCore/Framework/interface/MakerMacros.h"
00024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00025 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00026 #include "FWCore/ParameterSet/interface/ParameterDescriptionNode.h"
00027 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00028 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00029 #include "FWCore/Utilities/interface/Algorithms.h"
00030 #include "FWCore/Utilities/interface/FunctionWithDict.h"
00031 #include "FWCore/Utilities/interface/MemberWithDict.h"
00032 #include "FWCore/Utilities/interface/ObjectWithDict.h"
00033 #include "FWCore/Utilities/interface/TypeWithDict.h"
00034 
00035 // system include files
00036 #include <algorithm>
00037 #include <iomanip>
00038 #include <iostream>
00039 #include <map>
00040 #include <sstream>
00041 #include <string>
00042 #include <vector>
00043 
00044 namespace edm {
00045   class ConfigurationDescriptions;
00046   namespace {
00047     std::string formatClassName(std::string const& iName) {
00048        return std::string("(")+iName+")";
00049     }
00050 
00051     char const* kNameValueSep = "=";
00053     template<typename T>
00054     void doPrint(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
00055       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << *reinterpret_cast<T*>(iObject.address());// << "\n";
00056     }
00057 
00058     template<>
00059     void doPrint<char>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
00060       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << static_cast<int>(*reinterpret_cast<char*>(iObject.address()));// << "\n";
00061     }
00062 
00063     template<>
00064     void doPrint<unsigned char>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
00065       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << static_cast<unsigned int>(*reinterpret_cast<unsigned char*>(iObject.address()));// << "\n";
00066     }
00067 
00068     template<>
00069     void doPrint<bool>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
00070       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << ((*reinterpret_cast<bool*>(iObject.address()))?"true":"false");// << "\n";
00071     }
00072 
00073     typedef void(*FunctionType)(std::string const&, ObjectWithDict const&, std::string const&);
00074     typedef std::map<std::string, FunctionType> TypeToPrintMap;
00075 
00076     template<typename T>
00077     void addToMap(TypeToPrintMap& iMap) {
00078        iMap[typeid(T).name()] = doPrint<T>;
00079     }
00080 
00081     bool printAsBuiltin(std::string const& iName,
00082                                ObjectWithDict const& iObject,
00083                                std::string const& iIndent) {
00084        typedef void(*FunctionType)(std::string const&, ObjectWithDict const&, std::string const&);
00085        typedef std::map<std::string, FunctionType> TypeToPrintMap;
00086        static TypeToPrintMap s_map;
00087        static bool isFirst = true;
00088        if(isFirst) {
00089           addToMap<bool>(s_map);
00090           addToMap<char>(s_map);
00091           addToMap<short>(s_map);
00092           addToMap<int>(s_map);
00093           addToMap<long>(s_map);
00094           addToMap<unsigned char>(s_map);
00095           addToMap<unsigned short>(s_map);
00096           addToMap<unsigned int>(s_map);
00097           addToMap<unsigned long>(s_map);
00098           addToMap<float>(s_map);
00099           addToMap<double>(s_map);
00100           isFirst = false;
00101        }
00102        TypeToPrintMap::iterator itFound = s_map.find(iObject.typeOf().name());
00103        if(itFound == s_map.end()) {
00104 
00105           return false;
00106        }
00107        itFound->second(iName, iObject, iIndent);
00108        return true;
00109     }
00110 
00111     bool printAsContainer(std::string const& iName,
00112                           ObjectWithDict const& iObject,
00113                           std::string const& iIndent,
00114                           std::string const& iIndentDelta);
00115 
00116     void printObject(std::string const& iName,
00117                      ObjectWithDict const& iObject,
00118                      std::string const& iIndent,
00119                      std::string const& iIndentDelta) {
00120        std::string printName = iName;
00121        ObjectWithDict objectToPrint = iObject;
00122        std::string indent(iIndent);
00123        if(iObject.typeOf().isPointer()) {
00124          LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << formatClassName(iObject.typeOf().name()) << std::hex << iObject.address() << std::dec;// << "\n";
00125           TypeWithDict pointedType = iObject.typeOf().toType(); // for Pointers, I get the real type this way
00126           if(TypeWithDict::byName("void") == pointedType ||
00127              pointedType.isPointer() ||
00128              iObject.address() == 0) {
00129              return;
00130           }
00131           return;
00132           /*
00133           //have the code that follows print the contents of the data to which the pointer points
00134           objectToPrint = ObjectWithDict(pointedType, iObject.address());
00135           //try to convert it to its actual type (assuming the original type was a base class)
00136           objectToPrint = ObjectWithDict(objectToPrint.castObject(objectToPrint.dynamicType()));
00137           printName = std::string("*")+iName;
00138           indent += iIndentDelta;
00139           */
00140        }
00141        std::string typeName(objectToPrint.typeOf().name());
00142        if(typeName.empty()) {
00143           typeName = "<unknown>";
00144        }
00145 
00146        if(printAsBuiltin(printName, objectToPrint, indent)) {
00147           return;
00148        }
00149        if(printAsContainer(printName, objectToPrint, indent, iIndentDelta)) {
00150           return;
00151        }
00152 
00153        LogAbsolute("EventContent") << indent << printName << " " << formatClassName(typeName);// << "\n";
00154        indent += iIndentDelta;
00155        //print all the data members
00156        TypeDataMembers dataMembers(objectToPrint.typeOf());
00157        for(auto const& dataMember : dataMembers) {
00158           MemberWithDict const member(dataMember);
00159           //LogAbsolute("EventContent") << "     debug " << member.name() << " " << member.typeName() << "\n";
00160           try {
00161              printObject(member.name(),
00162                          member.get(objectToPrint),
00163                          indent,
00164                          iIndentDelta);
00165           }catch(std::exception& iEx) {
00166             LogAbsolute("EventContent") << indent << member.name() << " <exception caught(" << iEx.what() << ")>\n";
00167           }
00168        }
00169     }
00170 
00171     bool printAsContainer(std::string const& iName,
00172                           ObjectWithDict const& iObject,
00173                           std::string const& iIndent,
00174                           std::string const& iIndentDelta) {
00175        ObjectWithDict sizeObj;
00176        try {
00177           size_t temp; //used to hold the memory for the return value
00178           sizeObj = ObjectWithDict(TypeWithDict(typeid(size_t)), &temp);
00179           iObject.typeOf().functionMemberByName("size").invoke(iObject, &sizeObj);
00180           assert(iObject.typeOf().functionMemberByName("size").returnType().typeInfo() == typeid(size_t));
00181           //std::cout << "size of type '" << sizeObj.name() << "' " << sizeObj.typeName() << std::endl;
00182           assert(sizeObj.typeOf().typeInfo() == typeid(size_t));
00183           size_t size = *reinterpret_cast<size_t*>(sizeObj.address());
00184           FunctionWithDict atMember;
00185           try {
00186              atMember = iObject.typeOf().functionMemberByName("at");
00187           } catch(std::exception const& x) {
00188              //std::cerr << "could not get 'at' member because " << x.what() << std::endl;
00189              return false;
00190           }
00191           LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << "[size=" << size << "]";//"\n";
00192           ObjectWithDict contained;
00193           std::string indexIndent = iIndent + iIndentDelta;
00194           TypeWithDict atReturnType(atMember.returnType());
00195           //std::cout << "return type " << atReturnType.name() << " size of " << atReturnType.SizeOf()
00196           // << " pointer? " << atReturnType.isPointer() << " ref? " << atReturnType.isReference() << std::endl;
00197 
00198           //Return by reference must be treated differently since reflex will not properly create
00199           // memory for a ref (which should just be a pointer to the object and not the object itself)
00200           //So we will create memory on the stack which can be used to hold a reference
00201           bool const isRef = atReturnType.isReference();
00202           void* refMemoryBuffer = 0;
00203           size_t index = 0;
00204           //The argument to the 'at' function is the index. Since the argument list holds pointers to the arguments
00205           // we only need to create it once and then when the value of index changes the pointer already
00206           // gets the new value
00207           std::vector<void*> args;
00208           args.push_back(&index);
00209           for(; index != size; ++index) {
00210              std::ostringstream sizeS;
00211              sizeS << "[" << index << "]";
00212              if(isRef) {
00213                 ObjectWithDict refObject(atReturnType, &refMemoryBuffer);
00214                 atMember.invoke(iObject, &refObject, args);
00215                 //Although to hold the return value from a reference reflex requires you to pass it a
00216                 // void** when it tries to call methods on the reference it expects to be given a void*
00217                 contained = ObjectWithDict(atReturnType, refMemoryBuffer);
00218              } else {
00219                 contained = atReturnType.construct();
00220                 atMember.invoke(iObject, &contained, args);
00221              }
00222              //LogAbsolute("EventContent") << "invoked 'at'" << std::endl;
00223              try {
00224                 printObject(sizeS.str(), contained, indexIndent, iIndentDelta);
00225              } catch(std::exception& iEx) {
00226                     LogAbsolute("EventContent") << indexIndent << iName << " <exception caught("
00227                       << iEx.what() << ")>\n";
00228              }
00229              if(!isRef) {
00230                 atReturnType.destruct(contained.address(), true);
00231              }
00232           }
00233           return true;
00234        } catch(std::exception const& x) {
00235           //std::cerr << "failed to invoke 'at' because " << x.what() << std::endl;
00236           return false;
00237        }
00238        return false;
00239     }
00240 
00241     void printObject(Event const& iEvent,
00242                      std::string const& iClassName,
00243                      std::string const& iModuleLabel,
00244                      std::string const& iInstanceLabel,
00245                      std::string const& iProcessName,
00246                      std::string const& iIndent,
00247                      std::string const& iIndentDelta) {
00248        try {
00249           GenericHandle handle(iClassName);
00250        }catch(edm::Exception const&) {
00251           LogAbsolute("EventContent") << iIndent << " \"" << iClassName << "\"" << " is an unknown type" << std::endl;
00252           return;
00253        }
00254        GenericHandle handle(iClassName);
00255        iEvent.getByLabel(InputTag(iModuleLabel, iInstanceLabel, iProcessName), handle);
00256        std::string className = formatClassName(iClassName);
00257        printObject(className, *handle, iIndent, iIndentDelta);
00258     }
00259   }
00260 
00261   class EventContentAnalyzer : public EDAnalyzer {
00262   public:
00263      explicit EventContentAnalyzer(ParameterSet const&);
00264      ~EventContentAnalyzer();
00265 
00266      virtual void analyze(Event const&, EventSetup const&);
00267      virtual void endJob();
00268 
00269      static void fillDescriptions(ConfigurationDescriptions& descriptions);
00270 
00271   private:
00272 
00273      // ----------member data ---------------------------
00274      std::string indentation_;
00275      std::string verboseIndentation_;
00276      std::vector<std::string> moduleLabels_;
00277      bool        verbose_;
00278      std::vector<std::string> getModuleLabels_;
00279      bool        getData_;
00280      int         evno_;
00281      std::map<std::string, int> cumulates_;
00282      bool        listContent_;
00283   };
00284 
00285   //
00286   // constructors and destructor
00287   //
00288   EventContentAnalyzer::EventContentAnalyzer(ParameterSet const& iConfig) :
00289     indentation_(iConfig.getUntrackedParameter("indentation", std::string("++"))),
00290     verboseIndentation_(iConfig.getUntrackedParameter("verboseIndentation", std::string("  "))),
00291     moduleLabels_(iConfig.getUntrackedParameter("verboseForModuleLabels", std::vector<std::string>())),
00292     verbose_(iConfig.getUntrackedParameter("verbose", false) || moduleLabels_.size()>0),
00293     getModuleLabels_(iConfig.getUntrackedParameter("getDataForModuleLabels", std::vector<std::string>())),
00294     getData_(iConfig.getUntrackedParameter("getData", false) || getModuleLabels_.size()>0),
00295     evno_(1),
00296     listContent_(iConfig.getUntrackedParameter("listContent", true)){
00297      //now do what ever initialization is needed
00298      sort_all(moduleLabels_);
00299      sort_all(getModuleLabels_);
00300   }
00301 
00302   EventContentAnalyzer::~EventContentAnalyzer() {
00303 
00304      // do anything here that needs to be done at destruction time
00305      // (e.g. close files, deallocate resources etc.)
00306 
00307   }
00308 
00309   //
00310   // member functions
00311   //
00312 
00313   // ------------ method called to produce the data  ------------
00314   void
00315   EventContentAnalyzer::analyze(Event const& iEvent, EventSetup const&) {
00316      typedef std::vector<Provenance const*> Provenances;
00317      Provenances provenances;
00318 
00319      iEvent.getAllProvenance(provenances);
00320 
00321      if(listContent_) {
00322        LogAbsolute("EventContent") << "\n" << indentation_ << "Event " << std::setw(5) << evno_ << " contains "
00323                                    << provenances.size() << " product" << (provenances.size() == 1 ? "" : "s")
00324                                    << " with friendlyClassName, moduleLabel, productInstanceName and processName:"
00325                                    << std::endl;
00326      }
00327 
00328      std::string startIndent = indentation_+verboseIndentation_;
00329      for(Provenances::iterator itProv = provenances.begin(), itProvEnd = provenances.end();
00330                                itProv != itProvEnd;
00331                              ++itProv) {
00332          std::string const& className = (*itProv)->className();
00333 
00334          std::string const& friendlyName = (*itProv)->friendlyClassName();
00335          //if(friendlyName.empty())  friendlyName = std::string("||");
00336 
00337          std::string const& modLabel = (*itProv)->moduleLabel();
00338          //if(modLabel.empty()) modLabel = std::string("||");
00339 
00340          std::string const& instanceName = (*itProv)->productInstanceName();
00341          //if(instanceName.empty()) instanceName = std::string("||");
00342 
00343          std::string const& processName = (*itProv)->processName();
00344 
00345          bool doVerbose = verbose_ && (moduleLabels_.empty() ||
00346                                        binary_search_all(moduleLabels_, modLabel));
00347 
00348          if(listContent_ || doVerbose) {
00349            LogAbsolute("EventContent") << indentation_ << friendlyName
00350                                        << " \"" << modLabel
00351                                        << "\" \"" << instanceName << "\" \""
00352                                        << processName << "\""
00353                                        << " (productId = " << (*itProv)->productID() << ")"
00354                                        << std::endl;
00355          }
00356 
00357          std::string key = friendlyName
00358            + std::string(" + \"") + modLabel
00359            + std::string("\" + \"") + instanceName + "\" \"" + processName + "\"";
00360          ++cumulates_[key];
00361 
00362          if(doVerbose) {
00363              //indent one level before starting to print
00364              printObject(iEvent,
00365                          className,
00366                          modLabel,
00367                          instanceName,
00368                          processName,
00369                          startIndent,
00370                          verboseIndentation_);
00371              continue;
00372          }
00373          if(getData_) {
00374            std::string class_and_label = friendlyName + "_" + modLabel;
00375            if(getModuleLabels_.empty() ||
00376              binary_search_all(getModuleLabels_, modLabel) ||
00377              binary_search_all(getModuleLabels_, class_and_label)) {
00378              try {
00379                GenericHandle handle(className);
00380              } catch(edm::Exception const&) {
00381                LogAbsolute("EventContent") << startIndent << " \"" << className << "\"" << " is an unknown type" << std::endl;
00382                return;
00383              }
00384              GenericHandle handle(className);
00385              iEvent.getByLabel(InputTag(modLabel,
00386                                         instanceName,
00387                                         processName),
00388                                         handle);
00389            }
00390          }
00391      }
00392      //std::cout << "Mine" << std::endl;
00393      ++evno_;
00394   }
00395 
00396   // ------------ method called at end of job -------------------
00397   void
00398   EventContentAnalyzer::endJob() {
00399      typedef std::map<std::string, int> nameMap;
00400 
00401      LogAbsolute("EventContent") << "\nSummary for key being the concatenation of friendlyClassName, moduleLabel, productInstanceName and processName" << std::endl;
00402      for(nameMap::const_iterator it = cumulates_.begin(), itEnd = cumulates_.end();
00403                                  it != itEnd;
00404                                  ++it) {
00405         LogAbsolute("EventContent") << std::setw(6) << it->second << " occurrences of key " << it->first << std::endl;
00406      }
00407 
00408   // Test boost::lexical_cast  We don't need this right now so comment it out.
00409   // int k = 137;
00410   // std::string ktext = boost::lexical_cast<std::string>(k);
00411   // std::cout << "\nInteger " << k << " expressed as a string is |" << ktext << "|" << std::endl;
00412   }
00413 
00414   void
00415   EventContentAnalyzer::fillDescriptions(ConfigurationDescriptions& descriptions) {
00416 
00417      descriptions.setComment("This plugin will print a list of all products in the event "
00418                              "provenance.  It also has options to print and/or get each product.");
00419 
00420      ParameterSetDescription desc;
00421 
00422      ParameterDescriptionNode* np;
00423 
00424      std::string defaultString("++");
00425      np = desc.addOptionalUntracked<std::string>("indentation", defaultString);
00426      np->setComment("This string is printed at the beginning of every line printed during event processing.");
00427 
00428      np = desc.addOptionalUntracked<bool>("verbose", false);
00429      np->setComment("If true, the contents of products are printed.");
00430 
00431      defaultString = "  ";
00432      np = desc.addOptionalUntracked<std::string>("verboseIndentation", defaultString);
00433      np->setComment("This string is used to further indent lines when printing the contents of products in verbose mode.");
00434 
00435      std::vector<std::string> defaultVString;
00436 
00437      np = desc.addOptionalUntracked<std::vector<std::string> >("verboseForModuleLabels", defaultVString);
00438      np->setComment("If this vector is not empty, then only products with module labels on this list are printed.");
00439 
00440      np = desc.addOptionalUntracked<bool>("getData", false);
00441      np->setComment("If true the products will be retrieved using getByLabel.");
00442 
00443      np = desc.addOptionalUntracked<std::vector<std::string> >("getDataForModuleLabels", defaultVString);
00444      np->setComment("If this vector is not empty, then only products with module labels on this list are retrieved by getByLabel.");
00445 
00446      np = desc.addOptionalUntracked<bool>("listContent", true);
00447      np->setComment("If true then print a list of all the event content.");
00448 
00449 
00450      descriptions.add("printContent", desc);
00451   }
00452 }
00453 
00454 using edm::EventContentAnalyzer;
00455 DEFINE_FWK_MODULE(EventContentAnalyzer);