Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-10-08 02:27:21

0001 // -*- C++ -*-
0002 //
0003 // Package:    Modules
0004 // Class:      EventContentAnalyzer
0005 //
0006 /**
0007  Description: <one line class summary>
0008 
0009  Implementation:
0010      <Notes on implementation>
0011 */
0012 //
0013 // Original Author:  Chris Jones
0014 //         Created:  Mon Sep 19 11:47:28 CEST 2005
0015 //
0016 //
0017 
0018 // user include files
0019 #include "DataFormats/Provenance/interface/Provenance.h"
0020 #include "FWCore/Framework/interface/one/EDAnalyzer.h"
0021 #include "FWCore/Framework/interface/Event.h"
0022 #include "FWCore/Framework/interface/GenericHandle.h"
0023 #include "FWCore/Framework/interface/MakerMacros.h"
0024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0025 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0026 #include "FWCore/ParameterSet/interface/ParameterDescriptionNode.h"
0027 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0028 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0029 #include "FWCore/Utilities/interface/Algorithms.h"
0030 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0031 #include "FWCore/Reflection/interface/MemberWithDict.h"
0032 #include "FWCore/Reflection/interface/ObjectWithDict.h"
0033 #include "FWCore/Reflection/interface/TypeWithDict.h"
0034 #include "FWCore/Utilities/interface/TypeToGet.h"
0035 #include "FWCore/ParameterSet/interface/Registry.h"
0036 
0037 // system include files
0038 #include <algorithm>
0039 #include <iomanip>
0040 #include <iostream>
0041 #include <map>
0042 #include <sstream>
0043 #include <string>
0044 #include <vector>
0045 
0046 namespace edm {
0047   class ConfigurationDescriptions;
0048   namespace {
0049     std::string formatClassName(std::string const& iName) { return std::string("(") + iName + ")"; }
0050 
0051     char const* kNameValueSep = "=";
0052     ///convert the object information to the correct type and print it
0053     template <typename T>
0054     void doPrint(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
0055       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep
0056                                   << *reinterpret_cast<T*>(iObject.address());  // << "\n";
0057     }
0058 
0059     template <>
0060     void doPrint<char>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
0061       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep
0062                                   << static_cast<int>(*reinterpret_cast<char*>(iObject.address()));  // << "\n";
0063     }
0064 
0065     template <>
0066     void doPrint<unsigned char>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
0067       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep
0068                                   << static_cast<unsigned int>(
0069                                          *reinterpret_cast<unsigned char*>(iObject.address()));  // << "\n";
0070     }
0071 
0072     template <>
0073     void doPrint<bool>(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
0074       LogAbsolute("EventContent") << iIndent << iName << kNameValueSep
0075                                   << ((*reinterpret_cast<bool*>(iObject.address())) ? "true" : "false");  // << "\n";
0076     }
0077 
0078     typedef void (*FunctionType)(std::string const&, ObjectWithDict const&, std::string const&);
0079     typedef std::map<std::string, FunctionType> TypeToPrintMap;
0080 
0081     template <typename T>
0082     void addToMap(TypeToPrintMap& iMap) {
0083       iMap[typeid(T).name()] = doPrint<T>;
0084     }
0085 
0086     bool printAsBuiltin(std::string const& iName, ObjectWithDict const& iObject, std::string const& iIndent) {
0087       typedef void (*FunctionType)(std::string const&, ObjectWithDict const&, std::string const&);
0088       typedef std::map<std::string, FunctionType> TypeToPrintMap;
0089       static TypeToPrintMap s_map;
0090       static bool isFirst = true;
0091       if (isFirst) {
0092         addToMap<bool>(s_map);
0093         addToMap<char>(s_map);
0094         addToMap<short>(s_map);
0095         addToMap<int>(s_map);
0096         addToMap<long>(s_map);
0097         addToMap<unsigned char>(s_map);
0098         addToMap<unsigned short>(s_map);
0099         addToMap<unsigned int>(s_map);
0100         addToMap<unsigned long>(s_map);
0101         addToMap<float>(s_map);
0102         addToMap<double>(s_map);
0103         isFirst = false;
0104       }
0105       TypeToPrintMap::iterator itFound = s_map.find(iObject.typeOf().name());
0106       if (itFound == s_map.end()) {
0107         return false;
0108       }
0109       itFound->second(iName, iObject, iIndent);
0110       return true;
0111     }
0112 
0113     bool printAsContainer(std::string const& iName,
0114                           ObjectWithDict const& iObject,
0115                           std::string const& iIndent,
0116                           std::string const& iIndentDelta);
0117 
0118     void printObject(std::string const& iName,
0119                      ObjectWithDict const& iObject,
0120                      std::string const& iIndent,
0121                      std::string const& iIndentDelta) {
0122       const std::string& printName = iName;
0123       const ObjectWithDict& objectToPrint = iObject;
0124       std::string indent(iIndent);
0125       if (iObject.typeOf().isPointer()) {
0126         LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << formatClassName(iObject.typeOf().name())
0127                                     << std::hex << iObject.address() << std::dec;  // << "\n";
0128         TypeWithDict pointedType = iObject.typeOf().toType();  // for Pointers, I get the real type this way
0129         if (TypeWithDict::byName("void") == pointedType || pointedType.isPointer() || iObject.address() == nullptr) {
0130           return;
0131         }
0132         return;
0133         /*
0134           //have the code that follows print the contents of the data to which the pointer points
0135           objectToPrint = ObjectWithDict(pointedType, iObject.address());
0136           //try to convert it to its actual type (assuming the original type was a base class)
0137           objectToPrint = ObjectWithDict(objectToPrint.castObject(objectToPrint.dynamicType()));
0138           printName = std::string("*")+iName;
0139           indent += iIndentDelta;
0140           */
0141       }
0142       std::string typeName(objectToPrint.typeOf().name());
0143       if (typeName.empty()) {
0144         typeName = "<unknown>";
0145       }
0146 
0147       if (printAsBuiltin(printName, objectToPrint, indent)) {
0148         return;
0149       }
0150       if (printAsContainer(printName, objectToPrint, indent, iIndentDelta)) {
0151         return;
0152       }
0153 
0154       LogAbsolute("EventContent") << indent << printName << " " << formatClassName(typeName);  // << "\n";
0155       indent += iIndentDelta;
0156       //print all the data members
0157       TypeDataMembers dataMembers(objectToPrint.typeOf());
0158       for (auto const& dataMember : dataMembers) {
0159         MemberWithDict const member(dataMember);
0160         //LogAbsolute("EventContent") << "     debug " << member.name() << " " << member.typeName() << "\n";
0161         try {
0162           printObject(member.name(), member.get(objectToPrint), indent, iIndentDelta);
0163         } catch (std::exception& iEx) {
0164           LogAbsolute("EventContent") << indent << member.name() << " <exception caught(" << iEx.what() << ")>\n";
0165         }
0166       }
0167     }
0168 
0169     bool printAsContainer(std::string const& iName,
0170                           ObjectWithDict const& iObject,
0171                           std::string const& iIndent,
0172                           std::string const& iIndentDelta) {
0173       ObjectWithDict sizeObj;
0174       try {
0175         size_t temp;  //used to hold the memory for the return value
0176         FunctionWithDict sizeFunc = iObject.typeOf().functionMemberByName("size");
0177         assert(sizeFunc.finalReturnType() == typeid(size_t));
0178         sizeObj = ObjectWithDict(TypeWithDict(typeid(size_t)), &temp);
0179         sizeFunc.invoke(iObject, &sizeObj);
0180         //std::cout << "size of type '" << sizeObj.name() << "' " << sizeObj.typeName() << std::endl;
0181         size_t size = *reinterpret_cast<size_t*>(sizeObj.address());
0182         FunctionWithDict atMember;
0183         try {
0184           atMember = iObject.typeOf().functionMemberByName("at");
0185         } catch (std::exception const& x) {
0186           //std::cerr << "could not get 'at' member because " << x.what() << std::endl;
0187           return false;
0188         }
0189         LogAbsolute("EventContent") << iIndent << iName << kNameValueSep << "[size=" << size << "]";  //"\n";
0190         ObjectWithDict contained;
0191         std::string indexIndent = iIndent + iIndentDelta;
0192         TypeWithDict atReturnType(atMember.finalReturnType());
0193         //std::cout << "return type " << atReturnType.name() << " size of " << atReturnType.SizeOf()
0194         // << " pointer? " << atReturnType.isPointer() << " ref? " << atReturnType.isReference() << std::endl;
0195 
0196         //Return by reference must be treated differently since reflex will not properly create
0197         // memory for a ref (which should just be a pointer to the object and not the object itself)
0198         //So we will create memory on the stack which can be used to hold a reference
0199         bool const isRef = atReturnType.isReference();
0200         void* refMemoryBuffer = nullptr;
0201         size_t index = 0;
0202         //The argument to the 'at' function is the index. Since the argument list holds pointers to the arguments
0203         // we only need to create it once and then when the value of index changes the pointer already
0204         // gets the new value
0205         std::vector<void*> args;
0206         args.push_back(&index);
0207         for (; index != size; ++index) {
0208           std::ostringstream sizeS;
0209           sizeS << "[" << index << "]";
0210           if (isRef) {
0211             ObjectWithDict refObject(atReturnType, &refMemoryBuffer);
0212             atMember.invoke(iObject, &refObject, args);
0213             //Although to hold the return value from a reference reflex requires you to pass it a
0214             // void** when it tries to call methods on the reference it expects to be given a void*
0215             contained = ObjectWithDict(atReturnType, refMemoryBuffer);
0216           } else {
0217             contained = atReturnType.construct();
0218             atMember.invoke(iObject, &contained, args);
0219           }
0220           //LogAbsolute("EventContent") << "invoked 'at'" << std::endl;
0221           try {
0222             printObject(sizeS.str(), contained, indexIndent, iIndentDelta);
0223           } catch (std::exception& iEx) {
0224             LogAbsolute("EventContent") << indexIndent << iName << " <exception caught(" << iEx.what() << ")>\n";
0225           }
0226           if (!isRef) {
0227             contained.destruct(true);
0228           }
0229         }
0230         return true;
0231       } catch (std::exception const& x) {
0232         //std::cerr << "failed to invoke 'at' because " << x.what() << std::endl;
0233         return false;
0234       }
0235       return false;
0236     }
0237 
0238     void printObject(Event const& iEvent,
0239                      std::string const& iClassName,
0240                      std::string const& iModuleLabel,
0241                      std::string const& iInstanceLabel,
0242                      std::string const& iProcessName,
0243                      std::string const& iIndent,
0244                      std::string const& iIndentDelta) {
0245       try {
0246         GenericHandle handle(iClassName);
0247       } catch (edm::Exception const&) {
0248         LogAbsolute("EventContent") << iIndent << " \"" << iClassName << "\""
0249                                     << " is an unknown type" << std::endl;
0250         return;
0251       }
0252       GenericHandle handle(iClassName);
0253       iEvent.getByLabel(InputTag(iModuleLabel, iInstanceLabel, iProcessName), handle);
0254       std::string className = formatClassName(iClassName);
0255       printObject(className, *handle, iIndent, iIndentDelta);
0256     }
0257   }  // namespace
0258 
0259   class EventContentAnalyzer : public one::EDAnalyzer<> {
0260   public:
0261     explicit EventContentAnalyzer(ParameterSet const&);
0262     ~EventContentAnalyzer() override;
0263 
0264     void analyze(Event const&, EventSetup const&) override;
0265     void endJob() override;
0266 
0267     static void fillDescriptions(ConfigurationDescriptions& descriptions);
0268 
0269   private:
0270     // ----------member data ---------------------------
0271     std::string indentation_;
0272     std::string verboseIndentation_;
0273     std::vector<std::string> moduleLabels_;
0274     bool verbose_;
0275     std::vector<std::string> getModuleLabels_;
0276     bool getData_;
0277     int evno_;
0278     std::map<std::string, int> cumulates_;
0279     bool listContent_;
0280     bool listProvenance_;
0281   };
0282 
0283   //
0284   // constructors and destructor
0285   //
0286   EventContentAnalyzer::EventContentAnalyzer(ParameterSet const& iConfig)
0287       : indentation_(iConfig.getUntrackedParameter("indentation", std::string("++"))),
0288         verboseIndentation_(iConfig.getUntrackedParameter("verboseIndentation", std::string("  "))),
0289         moduleLabels_(iConfig.getUntrackedParameter("verboseForModuleLabels", std::vector<std::string>())),
0290         verbose_(iConfig.getUntrackedParameter("verbose", false) || !moduleLabels_.empty()),
0291         getModuleLabels_(iConfig.getUntrackedParameter("getDataForModuleLabels", std::vector<std::string>())),
0292         getData_(iConfig.getUntrackedParameter("getData", false) || !getModuleLabels_.empty()),
0293         evno_(1),
0294         listContent_(iConfig.getUntrackedParameter("listContent", true)),
0295         listProvenance_(iConfig.getUntrackedParameter("listProvenance", false)) {
0296     //now do what ever initialization is needed
0297     sort_all(moduleLabels_);
0298     sort_all(getModuleLabels_);
0299     if (getData_) {
0300       callWhenNewProductsRegistered([this](edm::BranchDescription const& iBranch) {
0301         if (getModuleLabels_.empty()) {
0302           const std::string kPathStatus("edm::PathStatus");
0303           const std::string kEndPathStatus("edm::EndPathStatus");
0304           if (iBranch.className() != kPathStatus && iBranch.className() != kEndPathStatus) {
0305             this->consumes(edm::TypeToGet{iBranch.unwrappedTypeID(), PRODUCT_TYPE},
0306                            edm::InputTag{iBranch.moduleLabel(), iBranch.productInstanceName(), iBranch.processName()});
0307           }
0308         } else {
0309           for (auto const& mod : this->getModuleLabels_) {
0310             if (iBranch.moduleLabel() == mod) {
0311               this->consumes(edm::TypeToGet{iBranch.unwrappedTypeID(), PRODUCT_TYPE},
0312                              edm::InputTag{mod, iBranch.productInstanceName(), iBranch.processName()});
0313               break;
0314             }
0315           }
0316         }
0317       });
0318     }
0319   }
0320 
0321   EventContentAnalyzer::~EventContentAnalyzer() {
0322     // do anything here that needs to be done at destruction time
0323     // (e.g. close files, deallocate resources etc.)
0324   }
0325 
0326   //
0327   // member functions
0328   //
0329 
0330   // ------------ method called to produce the data  ------------
0331   void EventContentAnalyzer::analyze(Event const& iEvent, EventSetup const&) {
0332     typedef std::vector<StableProvenance const*> Provenances;
0333     Provenances provenances;
0334 
0335     iEvent.getAllStableProvenance(provenances);
0336 
0337     if (listContent_) {
0338       LogAbsolute("EventContent") << "\n"
0339                                   << indentation_ << "Event " << std::setw(5) << evno_ << " contains "
0340                                   << provenances.size() << " product" << (provenances.size() == 1 ? "" : "s")
0341                                   << " with friendlyClassName, moduleLabel, productInstanceName and processName:"
0342                                   << std::endl;
0343     }
0344 
0345     std::string startIndent = indentation_ + verboseIndentation_;
0346     for (auto const& provenance : provenances) {
0347       std::string const& className = provenance->className();
0348       const std::string kPathStatus("edm::PathStatus");
0349       const std::string kEndPathStatus("edm::EndPathStatus");
0350       if (className == kPathStatus || className == kEndPathStatus) {
0351         continue;
0352       }
0353       std::string const& friendlyName = provenance->friendlyClassName();
0354       //if(friendlyName.empty())  friendlyName = std::string("||");
0355 
0356       std::string const& modLabel = provenance->moduleLabel();
0357       //if(modLabel.empty()) modLabel = std::string("||");
0358 
0359       std::string const& instanceName = provenance->productInstanceName();
0360       //if(instanceName.empty()) instanceName = std::string("||");
0361 
0362       std::string const& processName = provenance->processName();
0363 
0364       bool doVerbose = verbose_ && (moduleLabels_.empty() || binary_search_all(moduleLabels_, modLabel));
0365 
0366       if (listContent_ || doVerbose) {
0367         LogAbsolute("EventContent") << indentation_ << friendlyName << " \"" << modLabel << "\" \"" << instanceName
0368                                     << "\" \"" << processName << "\""
0369                                     << " (productId = " << provenance->productID() << ")" << std::endl;
0370 
0371         if (listProvenance_) {
0372           const bool isAlias = provenance->branchDescription().isAlias();
0373           std::string aliasForModLabel;
0374           LogAbsolute("EventContent") << *provenance;
0375           if (isAlias) {
0376             aliasForModLabel = iEvent.getStableProvenance(provenance->originalBranchID()).moduleLabel();
0377             LogAbsolute("EventContent") << "Is an alias for " << aliasForModLabel;
0378           }
0379           ProcessHistory const& processHistory = iEvent.processHistory();
0380           for (ProcessConfiguration const& pc : processHistory) {
0381             if (pc.processName() == provenance->processName()) {
0382               ParameterSetID const& psetID = pc.parameterSetID();
0383               pset::Registry const* psetRegistry = pset::Registry::instance();
0384               ParameterSet const* processPset = psetRegistry->getMapped(psetID);
0385               if (processPset) {
0386                 if (processPset->existsAs<ParameterSet>(modLabel)) {
0387                   if (isAlias) {
0388                     LogAbsolute("EventContent") << "Alias PSet";
0389                   }
0390                   LogAbsolute("EventContent") << processPset->getParameterSet(modLabel);
0391                 }
0392                 if (isAlias and processPset->existsAs<ParameterSet>(aliasForModLabel)) {
0393                   LogAbsolute("EventContent") << processPset->getParameterSet(aliasForModLabel);
0394                 }
0395               }
0396             }
0397           }
0398         }
0399       }
0400       std::string key = friendlyName + std::string(" + \"") + modLabel + std::string("\" + \"") + instanceName +
0401                         "\" \"" + processName + "\"";
0402       ++cumulates_[key];
0403 
0404       if (doVerbose) {
0405         //indent one level before starting to print
0406         printObject(iEvent, className, modLabel, instanceName, processName, startIndent, verboseIndentation_);
0407         continue;
0408       }
0409       if (getData_) {
0410         std::string class_and_label = friendlyName + "_" + modLabel;
0411         if (getModuleLabels_.empty() || binary_search_all(getModuleLabels_, modLabel) ||
0412             binary_search_all(getModuleLabels_, class_and_label)) {
0413           try {
0414             GenericHandle handle(className);
0415           } catch (edm::Exception const&) {
0416             LogAbsolute("EventContent") << startIndent << " \"" << className << "\""
0417                                         << " is an unknown type" << std::endl;
0418             return;
0419           }
0420           GenericHandle handle(className);
0421           iEvent.getByLabel(InputTag(modLabel, instanceName, processName), handle);
0422         }
0423       }
0424     }
0425     //std::cout << "Mine" << std::endl;
0426     ++evno_;
0427   }
0428 
0429   // ------------ method called at end of job -------------------
0430   void EventContentAnalyzer::endJob() {
0431     typedef std::map<std::string, int> nameMap;
0432 
0433     LogAbsolute("EventContent") << "\nSummary for key being the concatenation of friendlyClassName, moduleLabel, "
0434                                    "productInstanceName and processName"
0435                                 << std::endl;
0436     for (nameMap::const_iterator it = cumulates_.begin(), itEnd = cumulates_.end(); it != itEnd; ++it) {
0437       LogAbsolute("EventContent") << std::setw(6) << it->second << " occurrences of key " << it->first << std::endl;
0438     }
0439   }
0440 
0441   void EventContentAnalyzer::fillDescriptions(ConfigurationDescriptions& descriptions) {
0442     descriptions.setComment(
0443         "This plugin will print a list of all products in the event "
0444         "provenance.  It also has options to print and/or get each product.");
0445 
0446     ParameterSetDescription desc;
0447 
0448     ParameterDescriptionNode* np;
0449 
0450     std::string defaultString("++");
0451     np = desc.addOptionalUntracked<std::string>("indentation", defaultString);
0452     np->setComment("This string is printed at the beginning of every line printed during event processing.");
0453 
0454     np = desc.addOptionalUntracked<bool>("verbose", false);
0455     np->setComment("If true, the contents of products are printed.");
0456 
0457     defaultString = "  ";
0458     np = desc.addOptionalUntracked<std::string>("verboseIndentation", defaultString);
0459     np->setComment(
0460         "This string is used to further indent lines when printing the contents of products in verbose mode.");
0461 
0462     std::vector<std::string> defaultVString;
0463 
0464     np = desc.addOptionalUntracked<std::vector<std::string> >("verboseForModuleLabels", defaultVString);
0465     np->setComment("If this vector is not empty, then only products with module labels on this list are printed.");
0466 
0467     np = desc.addOptionalUntracked<bool>("getData", false);
0468     np->setComment("If true the products will be retrieved using getByLabel.");
0469 
0470     np = desc.addOptionalUntracked<std::vector<std::string> >("getDataForModuleLabels", defaultVString);
0471     np->setComment(
0472         "If this vector is not empty, then only products with module labels on this list are retrieved by getByLabel.");
0473 
0474     np = desc.addOptionalUntracked<bool>("listContent", true);
0475     np->setComment("If true then print a list of all the event content.");
0476 
0477     np = desc.addOptionalUntracked<bool>("listProvenance", false);
0478     np->setComment("If true, and if listContent or verbose is true, print provenance information for each product");
0479 
0480     descriptions.add("printContent", desc);
0481   }
0482 }  // namespace edm
0483 
0484 using edm::EventContentAnalyzer;
0485 DEFINE_FWK_MODULE(EventContentAnalyzer);