Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:49

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     bool listPathStatus_;
0282   };
0283 
0284   //
0285   // constructors and destructor
0286   //
0287   EventContentAnalyzer::EventContentAnalyzer(ParameterSet const& iConfig)
0288       : indentation_(iConfig.getUntrackedParameter<std::string>("indentation")),
0289         verboseIndentation_(iConfig.getUntrackedParameter<std::string>("verboseIndentation")),
0290         moduleLabels_(iConfig.getUntrackedParameter<std::vector<std::string>>("verboseForModuleLabels")),
0291         verbose_(iConfig.getUntrackedParameter<bool>("verbose") || !moduleLabels_.empty()),
0292         getModuleLabels_(iConfig.getUntrackedParameter<std::vector<std::string>>("getDataForModuleLabels")),
0293         getData_(iConfig.getUntrackedParameter<bool>("getData") || !getModuleLabels_.empty()),
0294         evno_(1),
0295         listContent_(iConfig.getUntrackedParameter<bool>("listContent")),
0296         listProvenance_(iConfig.getUntrackedParameter<bool>("listProvenance")),
0297         listPathStatus_(iConfig.getUntrackedParameter<bool>("listPathStatus")) {
0298     //now do what ever initialization is needed
0299     sort_all(moduleLabels_);
0300     sort_all(getModuleLabels_);
0301     if (getData_) {
0302       callWhenNewProductsRegistered([this](edm::BranchDescription const& iBranch) {
0303         if (getModuleLabels_.empty()) {
0304           const std::string kPathStatus("edm::PathStatus");
0305           const std::string kEndPathStatus("edm::EndPathStatus");
0306           if (iBranch.className() != kPathStatus && iBranch.className() != kEndPathStatus) {
0307             this->consumes(edm::TypeToGet{iBranch.unwrappedTypeID(), PRODUCT_TYPE},
0308                            edm::InputTag{iBranch.moduleLabel(), iBranch.productInstanceName(), iBranch.processName()});
0309           }
0310         } else {
0311           for (auto const& mod : this->getModuleLabels_) {
0312             if (iBranch.moduleLabel() == mod) {
0313               this->consumes(edm::TypeToGet{iBranch.unwrappedTypeID(), PRODUCT_TYPE},
0314                              edm::InputTag{mod, iBranch.productInstanceName(), iBranch.processName()});
0315               break;
0316             }
0317           }
0318         }
0319       });
0320     }
0321   }
0322 
0323   EventContentAnalyzer::~EventContentAnalyzer() {
0324     // do anything here that needs to be done at destruction time
0325     // (e.g. close files, deallocate resources etc.)
0326   }
0327 
0328   //
0329   // member functions
0330   //
0331 
0332   // ------------ method called to produce the data  ------------
0333   void EventContentAnalyzer::analyze(Event const& iEvent, EventSetup const&) {
0334     typedef std::vector<StableProvenance const*> Provenances;
0335     Provenances provenances;
0336 
0337     iEvent.getAllStableProvenance(provenances);
0338 
0339     if (listContent_) {
0340       LogAbsolute("EventContent") << "\n"
0341                                   << indentation_ << "Event " << std::setw(5) << evno_ << " contains "
0342                                   << provenances.size() << " product" << (provenances.size() == 1 ? "" : "s")
0343                                   << " with friendlyClassName, moduleLabel, productInstanceName and processName:"
0344                                   << std::endl;
0345     }
0346 
0347     std::string startIndent = indentation_ + verboseIndentation_;
0348     for (auto const& provenance : provenances) {
0349       std::string const& className = provenance->className();
0350       const std::string kPathStatus("edm::PathStatus");
0351       const std::string kEndPathStatus("edm::EndPathStatus");
0352       if (not listPathStatus_ and (className == kPathStatus || className == kEndPathStatus)) {
0353         continue;
0354       }
0355       std::string const& friendlyName = provenance->friendlyClassName();
0356       //if(friendlyName.empty())  friendlyName = std::string("||");
0357 
0358       std::string const& modLabel = provenance->moduleLabel();
0359       //if(modLabel.empty()) modLabel = std::string("||");
0360 
0361       std::string const& instanceName = provenance->productInstanceName();
0362       //if(instanceName.empty()) instanceName = std::string("||");
0363 
0364       std::string const& processName = provenance->processName();
0365 
0366       bool doVerbose = verbose_ && (moduleLabels_.empty() || binary_search_all(moduleLabels_, modLabel));
0367 
0368       if (listContent_ || doVerbose) {
0369         LogAbsolute("EventContent") << indentation_ << friendlyName << " \"" << modLabel << "\" \"" << instanceName
0370                                     << "\" \"" << processName << "\""
0371                                     << " (productId = " << provenance->productID() << ")" << std::endl;
0372 
0373         if (listProvenance_) {
0374           const bool isAlias = provenance->branchDescription().isAlias();
0375           std::string aliasForModLabel;
0376           LogAbsolute("EventContent") << *provenance;
0377           if (isAlias) {
0378             aliasForModLabel = iEvent.getStableProvenance(provenance->originalBranchID()).moduleLabel();
0379             LogAbsolute("EventContent") << "Is an alias for " << aliasForModLabel;
0380           }
0381           ProcessHistory const& processHistory = iEvent.processHistory();
0382           for (ProcessConfiguration const& pc : processHistory) {
0383             if (pc.processName() == provenance->processName()) {
0384               ParameterSetID const& psetID = pc.parameterSetID();
0385               pset::Registry const* psetRegistry = pset::Registry::instance();
0386               ParameterSet const* processPset = psetRegistry->getMapped(psetID);
0387               if (processPset) {
0388                 if (processPset->existsAs<ParameterSet>(modLabel)) {
0389                   if (isAlias) {
0390                     LogAbsolute("EventContent") << "Alias PSet";
0391                   }
0392                   LogAbsolute("EventContent") << processPset->getParameterSet(modLabel);
0393                 }
0394                 if (isAlias and processPset->existsAs<ParameterSet>(aliasForModLabel)) {
0395                   LogAbsolute("EventContent") << processPset->getParameterSet(aliasForModLabel);
0396                 }
0397               }
0398             }
0399           }
0400         }
0401       }
0402       std::string key = friendlyName + std::string(" + \"") + modLabel + std::string("\" + \"") + instanceName +
0403                         "\" \"" + processName + "\"";
0404       ++cumulates_[key];
0405 
0406       if (doVerbose) {
0407         //indent one level before starting to print
0408         printObject(iEvent, className, modLabel, instanceName, processName, startIndent, verboseIndentation_);
0409         continue;
0410       }
0411       if (getData_) {
0412         std::string class_and_label = friendlyName + "_" + modLabel;
0413         if (getModuleLabels_.empty() || binary_search_all(getModuleLabels_, modLabel) ||
0414             binary_search_all(getModuleLabels_, class_and_label)) {
0415           try {
0416             GenericHandle handle(className);
0417           } catch (edm::Exception const&) {
0418             LogAbsolute("EventContent") << startIndent << " \"" << className << "\""
0419                                         << " is an unknown type" << std::endl;
0420             return;
0421           }
0422           GenericHandle handle(className);
0423           iEvent.getByLabel(InputTag(modLabel, instanceName, processName), handle);
0424         }
0425       }
0426     }
0427     //std::cout << "Mine" << std::endl;
0428     ++evno_;
0429   }
0430 
0431   // ------------ method called at end of job -------------------
0432   void EventContentAnalyzer::endJob() {
0433     typedef std::map<std::string, int> nameMap;
0434 
0435     LogAbsolute("EventContent") << "\nSummary for key being the concatenation of friendlyClassName, moduleLabel, "
0436                                    "productInstanceName and processName"
0437                                 << std::endl;
0438     for (nameMap::const_iterator it = cumulates_.begin(), itEnd = cumulates_.end(); it != itEnd; ++it) {
0439       LogAbsolute("EventContent") << std::setw(6) << it->second << " occurrences of key " << it->first << std::endl;
0440     }
0441   }
0442 
0443   void EventContentAnalyzer::fillDescriptions(ConfigurationDescriptions& descriptions) {
0444     descriptions.setComment(
0445         "This plugin will print a list of all products in the event "
0446         "provenance.  It also has options to print and/or get each product.");
0447 
0448     ParameterSetDescription desc;
0449 
0450     ParameterDescriptionNode* np;
0451 
0452     std::string defaultString("++");
0453     np = desc.addUntracked<std::string>("indentation", defaultString);
0454     np->setComment("This string is printed at the beginning of every line printed during event processing.");
0455 
0456     np = desc.addUntracked<bool>("verbose", false);
0457     np->setComment("If true, the contents of products are printed.");
0458 
0459     defaultString = "  ";
0460     np = desc.addUntracked<std::string>("verboseIndentation", defaultString);
0461     np->setComment(
0462         "This string is used to further indent lines when printing the contents of products in verbose mode.");
0463 
0464     std::vector<std::string> defaultVString;
0465 
0466     np = desc.addUntracked<std::vector<std::string>>("verboseForModuleLabels", defaultVString);
0467     np->setComment("If this vector is not empty, then only products with module labels on this list are printed.");
0468 
0469     np = desc.addUntracked<bool>("getData", false);
0470     np->setComment("If true the products will be retrieved using getByLabel.");
0471 
0472     np = desc.addUntracked<std::vector<std::string>>("getDataForModuleLabels", defaultVString);
0473     np->setComment(
0474         "If this vector is not empty, then only products with module labels on this list are retrieved by getByLabel.");
0475 
0476     np = desc.addUntracked<bool>("listContent", true);
0477     np->setComment("If true then print a list of all the event content.");
0478 
0479     np = desc.addUntracked<bool>("listProvenance", false);
0480     np->setComment("If true, and if listContent or verbose is true, print provenance information for each product");
0481 
0482     desc.addUntracked<bool>("listPathStatus", false)
0483         ->setComment("If true, also show PathStatus/EndPathStatus data products.");
0484     descriptions.add("printContent", desc);
0485     descriptions.addDefault(desc);
0486   }
0487 }  // namespace edm
0488 
0489 using edm::EventContentAnalyzer;
0490 DEFINE_FWK_MODULE(EventContentAnalyzer);