CMS 3D CMS Logo

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