CMS 3D CMS Logo

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