Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-18 22:30:34

0001 #include "DataFormats/Common/interface/setIsMergeable.h"
0002 #include "DataFormats/Provenance/interface/BranchType.h"
0003 #include "DataFormats/Provenance/interface/EventSelectionID.h"
0004 #include "DataFormats/Provenance/interface/History.h"
0005 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
0006 #include "DataFormats/Provenance/interface/ParameterSetID.h"
0007 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
0008 #include "DataFormats/Provenance/interface/ProductRegistry.h"
0009 #include "DataFormats/Provenance/interface/Parentage.h"
0010 #include "DataFormats/Provenance/interface/ProductProvenance.h"
0011 #include "DataFormats/Provenance/interface/StoredProductProvenance.h"
0012 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
0013 #include "FWCore/Catalog/interface/InputFileCatalog.h"
0014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0015 #include "FWCore/ParameterSet/interface/Registry.h"
0016 #include "FWCore/Services/interface/setupSiteLocalConfig.h"
0017 
0018 #include "FWCore/Utilities/interface/Algorithms.h"
0019 #include "FWCore/Utilities/interface/Exception.h"
0020 #include "FWCore/Utilities/interface/propagate_const.h"
0021 
0022 #include "TError.h"
0023 #include "TFile.h"
0024 #include "TTree.h"
0025 
0026 #include "boost/program_options.hpp"
0027 
0028 #include <cassert>
0029 #include <iostream>
0030 #include <memory>
0031 #include <map>
0032 #include <set>
0033 #include <sstream>
0034 #include <vector>
0035 
0036 typedef std::map<std::string, std::vector<edm::BranchDescription>> IdToBranches;
0037 typedef std::map<std::pair<std::string, std::string>, IdToBranches> ModuleToIdBranches;
0038 
0039 static std::ostream& prettyPrint(std::ostream& oStream,
0040                                  edm::ParameterSet const& iPSet,
0041                                  std::string const& iIndent,
0042                                  std::string const& iIndentDelta);
0043 
0044 static std::string const triggerResults = std::string("TriggerResults");
0045 static std::string const triggerPaths = std::string("@trigger_paths");
0046 static std::string const source = std::string("source");
0047 static std::string const input = std::string("@main_input");
0048 
0049 namespace {
0050   typedef std::map<edm::ParameterSetID, edm::ParameterSetBlob> ParameterSetMap;
0051 
0052   class HistoryNode {
0053   public:
0054     HistoryNode() : config_(), simpleId_(0) {}
0055 
0056     HistoryNode(edm::ProcessConfiguration const& iConfig, unsigned int iSimpleId)
0057         : config_(iConfig), simpleId_(iSimpleId) {}
0058 
0059     void addChild(HistoryNode const& child) { children_.push_back(child); }
0060 
0061     edm::ParameterSetID const& parameterSetID() const { return config_.parameterSetID(); }
0062 
0063     std::string const& processName() const { return config_.processName(); }
0064 
0065     std::size_t size() const { return children_.size(); }
0066 
0067     HistoryNode* lastChildAddress() { return &children_.back(); }
0068 
0069     typedef std::vector<HistoryNode>::const_iterator const_iterator;
0070     typedef std::vector<HistoryNode>::iterator iterator;
0071 
0072     iterator begin() { return children_.begin(); }
0073     iterator end() { return children_.end(); }
0074 
0075     const_iterator begin() const { return children_.begin(); }
0076     const_iterator end() const { return children_.end(); }
0077 
0078     void print(std::ostream& os) const {
0079       os << config_.processName() << " '" << config_.passID() << "' '" << config_.releaseVersion() << "' [" << simpleId_
0080          << "]  (" << config_.parameterSetID() << ")" << std::endl;
0081     }
0082 
0083     void printHistory(std::string const& iIndent = std::string("  ")) const;
0084     void printEventSetupHistory(ParameterSetMap const& iPSM,
0085                                 std::vector<std::string> const& iFindMatch,
0086                                 std::ostream& oErrorLog) const;
0087     void printOtherModulesHistory(ParameterSetMap const& iPSM,
0088                                   ModuleToIdBranches const&,
0089                                   std::vector<std::string> const& iFindMatch,
0090                                   std::ostream& oErrorLog) const;
0091     void printTopLevelPSetsHistory(ParameterSetMap const& iPSM,
0092                                    std::vector<std::string> const& iFindMatch,
0093                                    std::ostream& oErrorLog) const;
0094 
0095     edm::ProcessConfigurationID configurationID() const { return config_.id(); }
0096 
0097     static bool sort_;
0098 
0099   private:
0100     edm::ProcessConfiguration config_;
0101     std::vector<HistoryNode> children_;
0102     unsigned int simpleId_;
0103   };
0104 
0105   std::ostream& operator<<(std::ostream& os, HistoryNode const& node) {
0106     node.print(os);
0107     return os;
0108   }
0109   bool HistoryNode::sort_ = false;
0110 }  // namespace
0111 
0112 std::ostream& operator<<(std::ostream& os, edm::ProcessHistory& iHist) {
0113   std::string const indentDelta("  ");
0114   std::string indent = indentDelta;
0115   for (auto const& process : iHist) {
0116     os << indent << process.processName() << " '" << process.passID() << "' '" << process.releaseVersion() << "' ("
0117        << process.parameterSetID() << ")" << std::endl;
0118     indent += indentDelta;
0119   }
0120   return os;
0121 }
0122 
0123 void HistoryNode::printHistory(std::string const& iIndent) const {
0124   std::string const indentDelta("  ");
0125   const std::string& indent = iIndent;
0126   for (auto const& item : *this) {
0127     std::cout << indent << item;
0128     item.printHistory(indent + indentDelta);
0129   }
0130 }
0131 
0132 std::string eventSetupComponent(char const* iType,
0133                                 std::string const& iCompName,
0134                                 edm::ParameterSet const& iProcessConfig,
0135                                 std::string const& iProcessName) {
0136   std::ostringstream result;
0137   edm::ParameterSet const& pset = iProcessConfig.getParameterSet(iCompName);
0138   std::string name(pset.getParameter<std::string>("@module_label"));
0139   if (name.empty()) {
0140     name = pset.getParameter<std::string>("@module_type");
0141   }
0142 
0143   result << iType << ": " << name << " " << iProcessName << "\n"
0144          << " parameters: ";
0145   prettyPrint(result, pset, " ", " ");
0146   return result.str();
0147 }
0148 
0149 void HistoryNode::printEventSetupHistory(ParameterSetMap const& iPSM,
0150                                          std::vector<std::string> const& iFindMatch,
0151                                          std::ostream& oErrorLog) const {
0152   for (auto const& itH : *this) {
0153     //Get ParameterSet for process
0154     ParameterSetMap::const_iterator itFind = iPSM.find(itH.parameterSetID());
0155     if (itFind == iPSM.end()) {
0156       oErrorLog << "No ParameterSetID for " << itH.parameterSetID() << std::endl;
0157     } else {
0158       edm::ParameterSet processConfig(itFind->second.pset());
0159       std::vector<std::string> sourceStrings, moduleStrings;
0160       //get the sources
0161       std::vector<std::string> sources = processConfig.getParameter<std::vector<std::string>>("@all_essources");
0162       for (auto& itM : sources) {
0163         std::string retValue = eventSetupComponent("ESSource", itM, processConfig, itH.processName());
0164         bool foundMatch = true;
0165         if (!iFindMatch.empty()) {
0166           for (auto const& stringToFind : iFindMatch) {
0167             if (retValue.find(stringToFind) == std::string::npos) {
0168               foundMatch = false;
0169               break;
0170             }
0171           }
0172         }
0173         if (foundMatch) {
0174           sourceStrings.push_back(std::move(retValue));
0175         }
0176       }
0177       //get the modules
0178       std::vector<std::string> modules = processConfig.getParameter<std::vector<std::string>>("@all_esmodules");
0179       for (auto& itM : modules) {
0180         std::string retValue = eventSetupComponent("ESModule", itM, processConfig, itH.processName());
0181         bool foundMatch = true;
0182         if (!iFindMatch.empty()) {
0183           for (auto const& stringToFind : iFindMatch) {
0184             if (retValue.find(stringToFind) == std::string::npos) {
0185               foundMatch = false;
0186               break;
0187             }
0188           }
0189         }
0190         if (foundMatch) {
0191           moduleStrings.push_back(std::move(retValue));
0192         }
0193       }
0194       if (sort_) {
0195         std::sort(sourceStrings.begin(), sourceStrings.end());
0196         std::sort(moduleStrings.begin(), moduleStrings.end());
0197       }
0198       std::copy(sourceStrings.begin(), sourceStrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
0199       std::copy(moduleStrings.begin(), moduleStrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
0200     }
0201     itH.printEventSetupHistory(iPSM, iFindMatch, oErrorLog);
0202   }
0203 }
0204 
0205 std::string nonProducerComponent(std::string const& iCompName,
0206                                  edm::ParameterSet const& iProcessConfig,
0207                                  std::string const& iProcessName) {
0208   std::ostringstream result;
0209   edm::ParameterSet const& pset = iProcessConfig.getParameterSet(iCompName);
0210   std::string label(pset.getParameter<std::string>("@module_label"));
0211 
0212   result << "Module: " << label << " " << iProcessName << "\n"
0213          << " parameters: ";
0214   prettyPrint(result, pset, " ", " ");
0215   return result.str();
0216 }
0217 
0218 void HistoryNode::printOtherModulesHistory(ParameterSetMap const& iPSM,
0219                                            ModuleToIdBranches const& iModules,
0220                                            std::vector<std::string> const& iFindMatch,
0221                                            std::ostream& oErrorLog) const {
0222   for (auto const& itH : *this) {
0223     //Get ParameterSet for process
0224     ParameterSetMap::const_iterator itFind = iPSM.find(itH.parameterSetID());
0225     if (itFind == iPSM.end()) {
0226       oErrorLog << "No ParameterSetID for " << itH.parameterSetID() << std::endl;
0227     } else {
0228       edm::ParameterSet processConfig(itFind->second.pset());
0229       std::vector<std::string> moduleStrings;
0230       //get all modules
0231       std::vector<std::string> modules = processConfig.getParameter<std::vector<std::string>>("@all_modules");
0232       for (auto& itM : modules) {
0233         //if we didn't already handle this from the branches
0234         if (iModules.end() == iModules.find(std::make_pair(itH.processName(), itM))) {
0235           std::string retValue(nonProducerComponent(itM, processConfig, itH.processName()));
0236           bool foundMatch = true;
0237           if (!iFindMatch.empty()) {
0238             for (auto const& stringToFind : iFindMatch) {
0239               if (retValue.find(stringToFind) == std::string::npos) {
0240                 foundMatch = false;
0241                 break;
0242               }
0243             }
0244           }
0245           if (foundMatch) {
0246             moduleStrings.push_back(std::move(retValue));
0247           }
0248         }
0249       }
0250       if (sort_) {
0251         std::sort(moduleStrings.begin(), moduleStrings.end());
0252       }
0253       std::copy(moduleStrings.begin(), moduleStrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
0254     }
0255     itH.printOtherModulesHistory(iPSM, iModules, iFindMatch, oErrorLog);
0256   }
0257 }
0258 
0259 static void appendToSet(std::set<std::string>& iSet, std::vector<std::string> const& iFrom) {
0260   for (auto const& n : iFrom) {
0261     iSet.insert(n);
0262   }
0263 }
0264 
0265 static std::string topLevelPSet(std::string const& iName,
0266                                 edm::ParameterSet const& iProcessConfig,
0267                                 std::string const& iProcessName) {
0268   std::ostringstream result;
0269   edm::ParameterSet const& pset = iProcessConfig.getParameterSet(iName);
0270 
0271   result << "PSet: " << iName << " " << iProcessName << "\n"
0272          << " parameters: ";
0273   prettyPrint(result, pset, " ", " ");
0274   return result.str();
0275 }
0276 
0277 void HistoryNode::printTopLevelPSetsHistory(ParameterSetMap const& iPSM,
0278                                             std::vector<std::string> const& iFindMatch,
0279                                             std::ostream& oErrorLog) const {
0280   for (auto const& itH : *this) {
0281     //Get ParameterSet for process
0282     ParameterSetMap::const_iterator itFind = iPSM.find(itH.parameterSetID());
0283     if (itFind == iPSM.end()) {
0284       oErrorLog << "No ParameterSetID for " << itH.parameterSetID() << std::endl;
0285     } else {
0286       edm::ParameterSet processConfig(itFind->second.pset());
0287       //Need to get the names of PSets which are used by the framework (e.g. names of modules)
0288       std::set<std::string> namesToExclude;
0289       appendToSet(namesToExclude, processConfig.getParameter<std::vector<std::string>>("@all_modules"));
0290       appendToSet(namesToExclude, processConfig.getParameter<std::vector<std::string>>("@all_sources"));
0291       appendToSet(namesToExclude, processConfig.getParameter<std::vector<std::string>>("@all_loopers"));
0292       //appendToSet(namesToExclude,processConfig.getParameter<std::vector<std::string> >("@all_subprocesses"));//untracked
0293       appendToSet(namesToExclude, processConfig.getParameter<std::vector<std::string>>("@all_esmodules"));
0294       appendToSet(namesToExclude, processConfig.getParameter<std::vector<std::string>>("@all_essources"));
0295       appendToSet(namesToExclude, processConfig.getParameter<std::vector<std::string>>("@all_esprefers"));
0296       if (processConfig.existsAs<std::vector<std::string>>("all_aliases")) {
0297         appendToSet(namesToExclude, processConfig.getParameter<std::vector<std::string>>("@all_aliases"));
0298       }
0299 
0300       std::vector<std::string> allNames{};
0301       processConfig.getParameterSetNames(allNames);
0302 
0303       std::vector<std::string> results;
0304       for (auto const& name : allNames) {
0305         if (name.empty() || '@' == name[0] || namesToExclude.find(name) != namesToExclude.end()) {
0306           continue;
0307         }
0308         std::string retValue = topLevelPSet(name, processConfig, itH.processName());
0309 
0310         bool foundMatch = true;
0311         if (!iFindMatch.empty()) {
0312           for (auto const& stringToFind : iFindMatch) {
0313             if (retValue.find(stringToFind) == std::string::npos) {
0314               foundMatch = false;
0315               break;
0316             }
0317           }
0318         }
0319         if (foundMatch) {
0320           results.push_back(std::move(retValue));
0321         }
0322       }
0323       if (sort_) {
0324         std::sort(results.begin(), results.end());
0325       }
0326       std::copy(results.begin(), results.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
0327     }
0328     itH.printTopLevelPSetsHistory(iPSM, iFindMatch, oErrorLog);
0329   }
0330 }
0331 
0332 namespace {
0333   std::unique_ptr<TFile> makeTFileWithLookup(std::string const& filename) {
0334     // See if it is a logical file name.
0335     auto operate = edm::setupSiteLocalConfig();
0336     std::string override;
0337     std::vector<std::string> fileNames;
0338     fileNames.push_back(filename);
0339     edm::InputFileCatalog catalog(fileNames, override, true);
0340     if (catalog.fileNames(0)[0] == filename) {
0341       throw cms::Exception("FileNotFound", "RootFile::RootFile()")
0342           << "File " << filename << " was not found or could not be opened.\n";
0343     }
0344     // filename is a valid LFN.
0345     std::unique_ptr<TFile> result(TFile::Open(catalog.fileNames(0)[0].c_str()));
0346     if (!result.get()) {
0347       throw cms::Exception("FileNotFound", "RootFile::RootFile()")
0348           << "File " << fileNames[0] << " was not found or could not be opened.\n";
0349     }
0350     return result;
0351   }
0352 
0353   // Open the input file, returning the TFile object that represents it.
0354   // The returned unique_ptr will not be null. The argument must not be null.
0355   // We first try the file name as a PFN, so that the catalog and related
0356   // services are not loaded unless needed.
0357   std::unique_ptr<TFile> makeTFile(std::string const& filename) {
0358     gErrorIgnoreLevel = kFatal;
0359     std::unique_ptr<TFile> result(TFile::Open(filename.c_str()));
0360     gErrorIgnoreLevel = kError;
0361     if (!result.get()) {
0362       // Try again with catalog.
0363       return makeTFileWithLookup(filename);
0364     }
0365     return result;
0366   }
0367 }  // namespace
0368 
0369 static std::ostream& prettyPrint(std::ostream& os,
0370                                  edm::ParameterSetEntry const& psetEntry,
0371                                  std::string const& iIndent,
0372                                  std::string const& iIndentDelta) {
0373   char const* trackiness = (psetEntry.isTracked() ? "tracked" : "untracked");
0374   os << "PSet " << trackiness << " = (";
0375   prettyPrint(os, psetEntry.pset(), iIndent + iIndentDelta, iIndentDelta);
0376   os << ")";
0377   return os;
0378 }
0379 
0380 static std::ostream& prettyPrint(std::ostream& os,
0381                                  edm::VParameterSetEntry const& vpsetEntry,
0382                                  std::string const& iIndent,
0383                                  std::string const& iIndentDelta) {
0384   std::vector<edm::ParameterSet> const& vps = vpsetEntry.vpset();
0385   os << "VPSet " << (vpsetEntry.isTracked() ? "tracked" : "untracked") << " = ({" << std::endl;
0386   std::string newIndent = iIndent + iIndentDelta;
0387   std::string start;
0388   std::string const between(",\n");
0389   for (auto const& item : vps) {
0390     os << start << newIndent;
0391     prettyPrint(os, item, newIndent, iIndentDelta);
0392     start = between;
0393   }
0394   if (!vps.empty()) {
0395     os << std::endl;
0396   }
0397   os << iIndent << "})";
0398   return os;
0399 }
0400 
0401 static std::ostream& prettyPrint(std::ostream& oStream,
0402                                  edm::ParameterSet const& iPSet,
0403                                  std::string const& iIndent,
0404                                  std::string const& iIndentDelta) {
0405   std::string newIndent = iIndent + iIndentDelta;
0406 
0407   oStream << "{" << std::endl;
0408   for (auto const& item : iPSet.tbl()) {
0409     // indent a bit
0410     oStream << newIndent << item.first << ": " << item.second << std::endl;
0411   }
0412   for (auto const& item : iPSet.psetTable()) {
0413     // indent a bit
0414     edm::ParameterSetEntry const& pe = item.second;
0415     oStream << newIndent << item.first << ": ";
0416     prettyPrint(oStream, pe, iIndent, iIndentDelta);
0417     oStream << std::endl;
0418   }
0419   for (auto const& item : iPSet.vpsetTable()) {
0420     // indent a bit
0421     edm::VParameterSetEntry const& pe = item.second;
0422     oStream << newIndent << item.first << ": ";
0423     prettyPrint(oStream, pe, newIndent, iIndentDelta);
0424     oStream << std::endl;
0425   }
0426   oStream << iIndent << "}";
0427 
0428   return oStream;
0429 }
0430 
0431 class ProvenanceDumper {
0432 public:
0433   // It is illegal to call this constructor with a null pointer; a
0434   // legal C-style string is required.
0435   ProvenanceDumper(std::string const& filename,
0436                    bool showDependencies,
0437                    bool extendedAncestors,
0438                    bool extendedDescendants,
0439                    bool excludeESModules,
0440                    bool showAllModules,
0441                    bool showTopLevelPSets,
0442                    std::vector<std::string> const& findMatch,
0443                    bool dontPrintProducts,
0444                    std::string const& dumpPSetID);
0445 
0446   ProvenanceDumper(ProvenanceDumper const&) = delete;             // Disallow copying and moving
0447   ProvenanceDumper& operator=(ProvenanceDumper const&) = delete;  // Disallow copying and moving
0448 
0449   // Write the provenenace information to the given stream.
0450   void dump();
0451   void printErrors(std::ostream& os);
0452   int exitCode() const;
0453 
0454 private:
0455   void addAncestors(edm::BranchID const& branchID,
0456                     std::set<edm::BranchID>& ancestorBranchIDs,
0457                     std::ostringstream& sout,
0458                     std::map<edm::BranchID, std::set<edm::ParentageID>>& perProductParentage) const;
0459 
0460   void addDescendants(edm::BranchID const& branchID,
0461                       std::set<edm::BranchID>& descendantBranchIDs,
0462                       std::ostringstream& sout,
0463                       std::map<edm::BranchID, std::set<edm::BranchID>>& parentToChildren) const;
0464 
0465   std::string filename_;
0466   edm::propagate_const<std::unique_ptr<TFile>> inputFile_;
0467   int exitCode_;
0468   std::stringstream errorLog_;
0469   int errorCount_;
0470   edm::ProductRegistry reg_;
0471   edm::ProcessConfigurationVector phc_;
0472   edm::ProcessHistoryVector phv_;
0473   ParameterSetMap psm_;
0474   HistoryNode historyGraph_;
0475   bool showDependencies_;
0476   bool extendedAncestors_;
0477   bool extendedDescendants_;
0478   bool excludeESModules_;
0479   bool showOtherModules_;
0480   bool productRegistryPresent_;
0481   bool showTopLevelPSets_;
0482   std::vector<std::string> findMatch_;
0483   bool dontPrintProducts_;
0484   std::string dumpPSetID_;
0485 
0486   void work_();
0487   void dumpProcessHistory_();
0488   void dumpEventFilteringParameterSets_(TFile* file);
0489   void dumpEventFilteringParameterSets(edm::EventSelectionIDVector const& ids);
0490   void dumpParameterSetForID_(edm::ParameterSetID const& id);
0491 };
0492 
0493 ProvenanceDumper::ProvenanceDumper(std::string const& filename,
0494                                    bool showDependencies,
0495                                    bool extendedAncestors,
0496                                    bool extendedDescendants,
0497                                    bool excludeESModules,
0498                                    bool showOtherModules,
0499                                    bool showTopLevelPSets,
0500                                    std::vector<std::string> const& findMatch,
0501                                    bool dontPrintProducts,
0502                                    std::string const& dumpPSetID)
0503     : filename_(filename),
0504       inputFile_(makeTFile(filename)),
0505       exitCode_(0),
0506       errorLog_(),
0507       errorCount_(0),
0508       showDependencies_(showDependencies),
0509       extendedAncestors_(extendedAncestors),
0510       extendedDescendants_(extendedDescendants),
0511       excludeESModules_(excludeESModules),
0512       showOtherModules_(showOtherModules),
0513       productRegistryPresent_(true),
0514       showTopLevelPSets_(showTopLevelPSets),
0515       findMatch_(findMatch),
0516       dontPrintProducts_(dontPrintProducts),
0517       dumpPSetID_(dumpPSetID) {}
0518 
0519 void ProvenanceDumper::dump() { work_(); }
0520 
0521 void ProvenanceDumper::printErrors(std::ostream& os) {
0522   if (errorCount_ > 0)
0523     os << errorLog_.str() << std::endl;
0524 }
0525 
0526 int ProvenanceDumper::exitCode() const { return exitCode_; }
0527 
0528 void ProvenanceDumper::dumpEventFilteringParameterSets(edm::EventSelectionIDVector const& ids) {
0529   edm::EventSelectionIDVector::size_type num_ids = ids.size();
0530   if (num_ids == 0) {
0531     std::cout << "No event filtering information is available.\n";
0532     std::cout << "------------------------------\n";
0533   } else {
0534     std::cout << "Event filtering information for " << num_ids << " processing steps is available.\n"
0535               << "The ParameterSets will be printed out, "
0536               << "with the oldest printed first.\n";
0537     for (edm::EventSelectionIDVector::size_type i = 0; i != num_ids; ++i) {
0538       dumpParameterSetForID_(ids[i]);
0539     }
0540   }
0541 }
0542 
0543 void ProvenanceDumper::dumpEventFilteringParameterSets_(TFile* file) {
0544   TTree* history = dynamic_cast<TTree*>(file->Get(edm::poolNames::eventHistoryTreeName().c_str()));
0545   if (history != nullptr) {
0546     edm::History h;
0547     edm::History* ph = &h;
0548 
0549     history->SetBranchAddress(edm::poolNames::eventHistoryBranchName().c_str(), &ph);
0550     if (history->GetEntry(0) <= 0) {
0551       std::cout << "No event filtering information is available; the event history tree has no entries\n";
0552     } else {
0553       dumpEventFilteringParameterSets(h.eventSelectionIDs());
0554     }
0555   } else {
0556     TTree* events = dynamic_cast<TTree*>(file->Get(edm::poolNames::eventTreeName().c_str()));
0557     assert(events != nullptr);
0558     TBranch* eventSelectionsBranch = events->GetBranch(edm::poolNames::eventSelectionsBranchName().c_str());
0559     if (eventSelectionsBranch == nullptr)
0560       return;
0561     edm::EventSelectionIDVector ids;
0562     edm::EventSelectionIDVector* pids = &ids;
0563     eventSelectionsBranch->SetAddress(&pids);
0564     if (eventSelectionsBranch->GetEntry(0) <= 0) {
0565       std::cout << "No event filtering information is available; the event selections branch has no entries\n";
0566     } else {
0567       dumpEventFilteringParameterSets(ids);
0568     }
0569   }
0570 }
0571 
0572 void ProvenanceDumper::dumpParameterSetForID_(edm::ParameterSetID const& id) {
0573   std::cout << "ParameterSetID: " << id << '\n';
0574   if (id.isValid()) {
0575     ParameterSetMap::const_iterator i = psm_.find(id);
0576     if (i == psm_.end()) {
0577       std::cout << "We are unable to find the corresponding ParameterSet\n";
0578       edm::ParameterSet empty;
0579       empty.registerIt();
0580       if (id == empty.id()) {
0581         std::cout << "But it would have been empty anyway\n";
0582       }
0583     } else {
0584       edm::ParameterSet ps(i->second.pset());
0585       prettyPrint(std::cout, ps, " ", " ");
0586       std::cout << '\n';
0587     }
0588   } else {
0589     std::cout << "This ID is not valid\n";
0590   }
0591   std::cout << "     -------------------------\n";
0592 }
0593 
0594 void ProvenanceDumper::dumpProcessHistory_() {
0595   std::cout << "Processing History:" << std::endl;
0596   std::map<edm::ProcessConfigurationID, unsigned int> simpleIDs;
0597   for (auto const& ph : phv_) {
0598     //loop over the history entries looking for matches
0599     HistoryNode* parent = &historyGraph_;
0600     for (auto const& pc : ph) {
0601       if (parent->size() == 0) {
0602         unsigned int id = simpleIDs[pc.id()];
0603         if (0 == id) {
0604           id = 1;
0605           simpleIDs[pc.id()] = id;
0606         }
0607         parent->addChild(HistoryNode(pc, id));
0608         parent = parent->lastChildAddress();
0609       } else {
0610         //see if this is unique
0611         bool isUnique = true;
0612         for (auto& child : *parent) {
0613           if (child.configurationID() == pc.id()) {
0614             isUnique = false;
0615             parent = &child;
0616             break;
0617           }
0618         }
0619         if (isUnique) {
0620           simpleIDs[pc.id()] = parent->size() + 1;
0621           parent->addChild(HistoryNode(pc, simpleIDs[pc.id()]));
0622           parent = parent->lastChildAddress();
0623         }
0624       }
0625     }
0626   }
0627   historyGraph_.printHistory();
0628 }
0629 
0630 void ProvenanceDumper::work_() {
0631   TTree* meta = dynamic_cast<TTree*>(inputFile_->Get(edm::poolNames::metaDataTreeName().c_str()));
0632   assert(nullptr != meta);
0633 
0634   edm::ProductRegistry* pReg = &reg_;
0635   if (meta->FindBranch(edm::poolNames::productDescriptionBranchName().c_str()) != nullptr) {
0636     meta->SetBranchAddress(edm::poolNames::productDescriptionBranchName().c_str(), &pReg);
0637   } else {
0638     productRegistryPresent_ = false;
0639   }
0640 
0641   ParameterSetMap* pPsm = &psm_;
0642   if (meta->FindBranch(edm::poolNames::parameterSetMapBranchName().c_str()) != nullptr) {
0643     meta->SetBranchAddress(edm::poolNames::parameterSetMapBranchName().c_str(), &pPsm);
0644   } else {
0645     TTree* psetTree = dynamic_cast<TTree*>(inputFile_->Get(edm::poolNames::parameterSetsTreeName().c_str()));
0646     assert(nullptr != psetTree);
0647     typedef std::pair<edm::ParameterSetID, edm::ParameterSetBlob> IdToBlobs;
0648     IdToBlobs idToBlob;
0649     IdToBlobs* pIdToBlob = &idToBlob;
0650     psetTree->SetBranchAddress(edm::poolNames::idToParameterSetBlobsBranchName().c_str(), &pIdToBlob);
0651     for (long long i = 0; i != psetTree->GetEntries(); ++i) {
0652       psetTree->GetEntry(i);
0653       psm_.insert(idToBlob);
0654     }
0655   }
0656 
0657   edm::ProcessHistoryVector* pPhv = &phv_;
0658   if (meta->FindBranch(edm::poolNames::processHistoryBranchName().c_str()) != nullptr) {
0659     meta->SetBranchAddress(edm::poolNames::processHistoryBranchName().c_str(), &pPhv);
0660   }
0661 
0662   edm::ProcessHistoryMap phm;
0663   edm::ProcessHistoryMap* pPhm = &phm;
0664   if (meta->FindBranch(edm::poolNames::processHistoryMapBranchName().c_str()) != nullptr) {
0665     meta->SetBranchAddress(edm::poolNames::processHistoryMapBranchName().c_str(), &pPhm);
0666   }
0667 
0668   if (meta->FindBranch(edm::poolNames::moduleDescriptionMapBranchName().c_str()) != nullptr) {
0669     if (meta->GetBranch(edm::poolNames::moduleDescriptionMapBranchName().c_str())->GetSplitLevel() != 0) {
0670       meta->SetBranchStatus((edm::poolNames::moduleDescriptionMapBranchName() + ".*").c_str(), false);
0671     } else {
0672       meta->SetBranchStatus(edm::poolNames::moduleDescriptionMapBranchName().c_str(), false);
0673     }
0674   }
0675 
0676   meta->GetEntry(0);
0677   assert(nullptr != pReg);
0678 
0679   edm::pset::Registry& psetRegistry = *edm::pset::Registry::instance();
0680   for (auto const& item : psm_) {
0681     edm::ParameterSet pset(item.second.pset());
0682     pset.setID(item.first);
0683     psetRegistry.insertMapped(pset);
0684   }
0685 
0686   if (!phv_.empty()) {
0687     for (auto const& history : phv_) {
0688       for (auto const& process : history) {
0689         phc_.push_back(process);
0690       }
0691     }
0692     edm::sort_all(phc_);
0693     phc_.erase(std::unique(phc_.begin(), phc_.end()), phc_.end());
0694 
0695   }
0696   // backward compatibility
0697   else if (!phm.empty()) {
0698     for (auto const& history : phm) {
0699       phv_.push_back(history.second);
0700       for (auto const& process : history.second) {
0701         phc_.push_back(process);
0702       }
0703     }
0704     edm::sort_all(phc_);
0705     phc_.erase(std::unique(phc_.begin(), phc_.end()), phc_.end());
0706   }
0707 
0708   if (!dumpPSetID_.empty()) {
0709     edm::ParameterSetID psetID;
0710     try {
0711       psetID = edm::ParameterSetID(dumpPSetID_);
0712     } catch (cms::Exception const& x) {
0713       throw cms::Exception("Command Line Argument")
0714           << "Illegal ParameterSetID string. It should contain 32 hexadecimal characters";
0715     }
0716     dumpParameterSetForID_(psetID);
0717     return;
0718   }
0719 
0720   //Prepare the parentage information if requested
0721   std::map<edm::BranchID, std::set<edm::ParentageID>> perProductParentage;
0722 
0723   if (showDependencies_ || extendedAncestors_ || extendedDescendants_) {
0724     TTree* parentageTree = dynamic_cast<TTree*>(inputFile_->Get(edm::poolNames::parentageTreeName().c_str()));
0725     if (nullptr == parentageTree) {
0726       std::cerr << "ERROR, no Parentage tree available so cannot show dependencies, ancestors, or descendants.\n";
0727       std::cerr << "Possibly this is not a standard EDM format file. For example, dependency, ancestor, and\n";
0728       std::cerr << "descendant options to edmProvDump will not work with nanoAOD format files.\n\n";
0729       showDependencies_ = false;
0730       extendedAncestors_ = false;
0731       extendedDescendants_ = false;
0732     } else {
0733       edm::ParentageRegistry& registry = *edm::ParentageRegistry::instance();
0734 
0735       std::vector<edm::ParentageID> orderedParentageIDs;
0736       orderedParentageIDs.reserve(parentageTree->GetEntries());
0737       for (Long64_t i = 0, numEntries = parentageTree->GetEntries(); i < numEntries; ++i) {
0738         edm::Parentage parentageBuffer;
0739         edm::Parentage* pParentageBuffer = &parentageBuffer;
0740         parentageTree->SetBranchAddress(edm::poolNames::parentageBranchName().c_str(), &pParentageBuffer);
0741         parentageTree->GetEntry(i);
0742         registry.insertMapped(parentageBuffer);
0743         orderedParentageIDs.push_back(parentageBuffer.id());
0744       }
0745       parentageTree->SetBranchAddress(edm::poolNames::parentageBranchName().c_str(), nullptr);
0746 
0747       TTree* eventMetaTree =
0748           dynamic_cast<TTree*>(inputFile_->Get(edm::BranchTypeToMetaDataTreeName(edm::InEvent).c_str()));
0749       if (nullptr == eventMetaTree) {
0750         eventMetaTree = dynamic_cast<TTree*>(inputFile_->Get(edm::BranchTypeToProductTreeName(edm::InEvent).c_str()));
0751       }
0752       if (nullptr == eventMetaTree) {
0753         std::cerr << "ERROR, no '" << edm::BranchTypeToProductTreeName(edm::InEvent)
0754                   << "' Tree in file so can not show dependencies\n";
0755         showDependencies_ = false;
0756         extendedAncestors_ = false;
0757         extendedDescendants_ = false;
0758       } else {
0759         TBranch* storedProvBranch =
0760             eventMetaTree->GetBranch(edm::BranchTypeToProductProvenanceBranchName(edm::InEvent).c_str());
0761 
0762         if (nullptr != storedProvBranch) {
0763           std::vector<edm::StoredProductProvenance> info;
0764           std::vector<edm::StoredProductProvenance>* pInfo = &info;
0765           storedProvBranch->SetAddress(&pInfo);
0766           for (Long64_t i = 0, numEntries = eventMetaTree->GetEntries(); i < numEntries; ++i) {
0767             storedProvBranch->GetEntry(i);
0768             for (auto const& item : info) {
0769               edm::BranchID bid(item.branchID_);
0770               perProductParentage[bid].insert(orderedParentageIDs.at(item.parentageIDIndex_));
0771             }
0772           }
0773         } else {
0774           //backwards compatible check
0775           TBranch* productProvBranch =
0776               eventMetaTree->GetBranch(edm::BranchTypeToBranchEntryInfoBranchName(edm::InEvent).c_str());
0777           if (nullptr != productProvBranch) {
0778             std::vector<edm::ProductProvenance> info;
0779             std::vector<edm::ProductProvenance>* pInfo = &info;
0780             productProvBranch->SetAddress(&pInfo);
0781             for (Long64_t i = 0, numEntries = eventMetaTree->GetEntries(); i < numEntries; ++i) {
0782               productProvBranch->GetEntry(i);
0783               for (auto const& item : info) {
0784                 perProductParentage[item.branchID()].insert(item.parentageID());
0785               }
0786             }
0787           } else {
0788             std::cerr << " ERROR, could not find provenance information so can not show dependencies\n";
0789             showDependencies_ = false;
0790             extendedAncestors_ = false;
0791             extendedDescendants_ = false;
0792           }
0793         }
0794       }
0795     }
0796   }
0797 
0798   std::map<edm::BranchID, std::set<edm::BranchID>> parentToChildren;
0799   edm::ParentageRegistry& registry = *edm::ParentageRegistry::instance();
0800 
0801   if (extendedDescendants_) {
0802     for (auto const& itParentageSet : perProductParentage) {
0803       edm::BranchID childBranchID = itParentageSet.first;
0804       for (auto const& itParentageID : itParentageSet.second) {
0805         edm::Parentage const* parentage = registry.getMapped(itParentageID);
0806         if (nullptr != parentage) {
0807           for (auto const& branch : parentage->parents()) {
0808             parentToChildren[branch].insert(childBranchID);
0809           }
0810         } else {
0811           std::cerr << "  ERROR:parentage info not in registry ParentageID=" << itParentageID << std::endl;
0812         }
0813       }
0814     }
0815   }
0816 
0817   dumpEventFilteringParameterSets_(inputFile_.get());
0818 
0819   dumpProcessHistory_();
0820 
0821   if (productRegistryPresent_) {
0822     std::cout << "---------Producers with data in file---------" << std::endl;
0823   }
0824 
0825   //using edm::ParameterSetID as the key does not work
0826   //   typedef std::map<edm::ParameterSetID, std::vector<edm::BranchDescription> > IdToBranches
0827   ModuleToIdBranches moduleToIdBranches;
0828   //IdToBranches idToBranches;
0829 
0830   std::map<edm::BranchID, std::string> branchIDToBranchName;
0831 
0832   for (auto const& processConfig : phc_) {
0833     edm::ParameterSet const* processParameterSet =
0834         edm::pset::Registry::instance()->getMapped(processConfig.parameterSetID());
0835     if (nullptr == processParameterSet || processParameterSet->empty()) {
0836       continue;
0837     }
0838     for (auto& item : reg_.productListUpdator()) {
0839       auto& product = item.second;
0840       if (product.processName() != processConfig.processName()) {
0841         continue;
0842       }
0843       //force it to rebuild the branch name
0844       product.init();
0845       setIsMergeable(product);
0846 
0847       if (showDependencies_ || extendedAncestors_ || extendedDescendants_) {
0848         branchIDToBranchName[product.branchID()] = product.branchName();
0849       }
0850       /*
0851         std::cout << product.branchName()
0852         << " id " << product.productID() << std::endl;
0853       */
0854       std::string moduleLabel = product.moduleLabel();
0855       if (moduleLabel == source) {
0856         moduleLabel = input;
0857       } else if (moduleLabel == triggerResults) {
0858         moduleLabel = triggerPaths;
0859       }
0860 
0861       std::stringstream s;
0862 
0863       if (processParameterSet->existsAs<edm::ParameterSet>(moduleLabel)) {
0864         edm::ParameterSet const& moduleParameterSet = processParameterSet->getParameterSet(moduleLabel);
0865         if (!moduleParameterSet.isRegistered()) {
0866           edm::ParameterSet moduleParameterSetCopy = processParameterSet->getParameterSet(moduleLabel);
0867           moduleParameterSetCopy.registerIt();
0868           s << moduleParameterSetCopy.id();
0869         } else {
0870           s << moduleParameterSet.id();
0871         }
0872         moduleToIdBranches[std::make_pair(product.processName(), product.moduleLabel())][s.str()].push_back(product);
0873       }
0874     }
0875   }
0876 
0877   for (auto const& item : moduleToIdBranches) {
0878     std::ostringstream sout;
0879     sout << "Module: " << item.first.second << " " << item.first.first << std::endl;
0880     std::set<edm::BranchID> allBranchIDsForLabelAndProcess;
0881     IdToBranches const& idToBranches = item.second;
0882     for (auto const& idBranch : idToBranches) {
0883       sout << " PSet id:" << idBranch.first << std::endl;
0884       if (!dontPrintProducts_) {
0885         sout << " products: {" << std::endl;
0886       }
0887       std::set<edm::BranchID> branchIDs;
0888       for (auto const& branch : idBranch.second) {
0889         if (!dontPrintProducts_) {
0890           sout << "  " << branch.branchName() << std::endl;
0891         }
0892         branchIDs.insert(branch.branchID());
0893         allBranchIDsForLabelAndProcess.insert(branch.branchID());
0894       }
0895       sout << " }" << std::endl;
0896       edm::ParameterSetID psid(idBranch.first);
0897       ParameterSetMap::const_iterator itpsm = psm_.find(psid);
0898       if (psm_.end() == itpsm) {
0899         ++errorCount_;
0900         errorLog_ << "No ParameterSetID for " << psid << std::endl;
0901         exitCode_ = 1;
0902       } else {
0903         sout << " parameters: ";
0904         prettyPrint(sout, edm::ParameterSet((*itpsm).second.pset()), " ", " ");
0905         sout << std::endl;
0906       }
0907       if (showDependencies_) {
0908         sout << " dependencies: {" << std::endl;
0909         std::set<edm::ParentageID> parentageIDs;
0910         for (auto const& branch : branchIDs) {
0911           //Save these BranchIDs
0912           std::set<edm::ParentageID> const& temp = perProductParentage[branch];
0913           parentageIDs.insert(temp.begin(), temp.end());
0914         }
0915         for (auto const& parentID : parentageIDs) {
0916           edm::Parentage const* parentage = registry.getMapped(parentID);
0917           if (nullptr != parentage) {
0918             for (auto const& branch : parentage->parents()) {
0919               sout << "  " << branchIDToBranchName[branch] << std::endl;
0920             }
0921           } else {
0922             sout << "  ERROR:parentage info not in registry ParentageID=" << parentID << std::endl;
0923           }
0924         }
0925         if (parentageIDs.empty()) {
0926           sout << "  no dependencies recorded (event may not contain data from this module)" << std::endl;
0927         }
0928         sout << " }" << std::endl;
0929       }
0930     }  // end loop over PSetIDs
0931     if (extendedAncestors_) {
0932       sout << " extendedAncestors: {" << std::endl;
0933       std::set<edm::BranchID> ancestorBranchIDs;
0934       for (auto const& branchID : allBranchIDsForLabelAndProcess) {
0935         addAncestors(branchID, ancestorBranchIDs, sout, perProductParentage);
0936       }
0937       for (auto const& ancestorBranchID : ancestorBranchIDs) {
0938         sout << "  " << branchIDToBranchName[ancestorBranchID] << "\n";
0939       }
0940       sout << " }" << std::endl;
0941     }
0942 
0943     if (extendedDescendants_) {
0944       sout << " extendedDescendants: {" << std::endl;
0945       std::set<edm::BranchID> descendantBranchIDs;
0946       for (auto const& branchID : allBranchIDsForLabelAndProcess) {
0947         addDescendants(branchID, descendantBranchIDs, sout, parentToChildren);
0948       }
0949       for (auto const& descendantBranchID : descendantBranchIDs) {
0950         sout << "  " << branchIDToBranchName[descendantBranchID] << "\n";
0951       }
0952       sout << " }" << std::endl;
0953     }
0954     bool foundMatch = true;
0955     if (!findMatch_.empty()) {
0956       for (auto const& stringToFind : findMatch_) {
0957         if (sout.str().find(stringToFind) == std::string::npos) {
0958           foundMatch = false;
0959           break;
0960         }
0961       }
0962     }
0963     if (foundMatch) {
0964       std::cout << sout.str() << std::endl;
0965     }
0966   }  // end loop over module label/process
0967 
0968   if (productRegistryPresent_ && showOtherModules_) {
0969     std::cout << "---------Other Modules---------" << std::endl;
0970     historyGraph_.printOtherModulesHistory(psm_, moduleToIdBranches, findMatch_, errorLog_);
0971   } else if (!productRegistryPresent_) {
0972     std::cout << "---------All Modules---------" << std::endl;
0973     historyGraph_.printOtherModulesHistory(psm_, moduleToIdBranches, findMatch_, errorLog_);
0974   }
0975 
0976   if (!excludeESModules_) {
0977     std::cout << "---------EventSetup---------" << std::endl;
0978     historyGraph_.printEventSetupHistory(psm_, findMatch_, errorLog_);
0979   }
0980 
0981   if (showTopLevelPSets_) {
0982     std::cout << "---------Top Level PSets---------" << std::endl;
0983     historyGraph_.printTopLevelPSetsHistory(psm_, findMatch_, errorLog_);
0984   }
0985   if (errorCount_ != 0) {
0986     exitCode_ = 1;
0987   }
0988 }
0989 
0990 void ProvenanceDumper::addAncestors(edm::BranchID const& branchID,
0991                                     std::set<edm::BranchID>& ancestorBranchIDs,
0992                                     std::ostringstream& sout,
0993                                     std::map<edm::BranchID, std::set<edm::ParentageID>>& perProductParentage) const {
0994   edm::ParentageRegistry& registry = *edm::ParentageRegistry::instance();
0995 
0996   std::set<edm::ParentageID> const& parentIDs = perProductParentage[branchID];
0997   for (auto const& parentageID : parentIDs) {
0998     edm::Parentage const* parentage = registry.getMapped(parentageID);
0999     if (nullptr != parentage) {
1000       for (auto const& branch : parentage->parents()) {
1001         if (ancestorBranchIDs.insert(branch).second) {
1002           addAncestors(branch, ancestorBranchIDs, sout, perProductParentage);
1003         }
1004       }
1005     } else {
1006       sout << "  ERROR:parentage info not in registry ParentageID=" << parentageID << std::endl;
1007     }
1008   }
1009 }
1010 
1011 void ProvenanceDumper::addDescendants(edm::BranchID const& branchID,
1012                                       std::set<edm::BranchID>& descendantBranchIDs,
1013                                       std::ostringstream& sout,
1014                                       std::map<edm::BranchID, std::set<edm::BranchID>>& parentToChildren) const {
1015   for (auto const& childBranchID : parentToChildren[branchID]) {
1016     if (descendantBranchIDs.insert(childBranchID).second) {
1017       addDescendants(childBranchID, descendantBranchIDs, sout, parentToChildren);
1018     }
1019   }
1020 }
1021 
1022 static char const* const kSortOpt = "sort";
1023 static char const* const kSortCommandOpt = "sort,s";
1024 static char const* const kDependenciesOpt = "dependencies";
1025 static char const* const kDependenciesCommandOpt = "dependencies,d";
1026 static char const* const kExtendedAncestorsOpt = "extendedAncestors";
1027 static char const* const kExtendedAncestorsCommandOpt = "extendedAncestors,x";
1028 static char const* const kExtendedDescendantsOpt = "extendedDescendants";
1029 static char const* const kExtendedDescendantsCommandOpt = "extendedDescendants,c";
1030 static char const* const kExcludeESModulesOpt = "excludeESModules";
1031 static char const* const kExcludeESModulesCommandOpt = "excludeESModules,e";
1032 static char const* const kShowAllModulesOpt = "showAllModules";
1033 static char const* const kShowAllModulesCommandOpt = "showAllModules,a";
1034 static char const* const kFindMatchOpt = "findMatch";
1035 static char const* const kFindMatchCommandOpt = "findMatch,f";
1036 static char const* const kDontPrintProductsOpt = "dontPrintProducts";
1037 static char const* const kDontPrintProductsCommandOpt = "dontPrintProducts,p";
1038 static char const* const kShowTopLevelPSetsOpt = "showTopLevelPSets";
1039 static char const* const kShowTopLevelPSetsCommandOpt = "showTopLevelPSets,t";
1040 static char const* const kHelpOpt = "help";
1041 static char const* const kHelpCommandOpt = "help,h";
1042 static char const* const kFileNameOpt = "input-file";
1043 static char const* const kDumpPSetIDOpt = "dumpPSetID";
1044 static char const* const kDumpPSetIDCommandOpt = "dumpPSetID,i";
1045 
1046 int main(int argc, char* argv[]) {
1047   using namespace boost::program_options;
1048 
1049   std::string descString(argv[0]);
1050   descString += " [options] <filename>";
1051   descString += "\nAllowed options";
1052   options_description desc(descString);
1053 
1054   // clang-format off
1055   desc.add_options()(kHelpCommandOpt, "show help message")(kSortCommandOpt, "alphabetially sort EventSetup components")(
1056       kDependenciesCommandOpt, "print what data each EDProducer is directly dependent upon")(
1057       kExtendedAncestorsCommandOpt, "print what data each EDProducer is dependent upon including indirect dependences")(
1058       kExtendedDescendantsCommandOpt,
1059       "print what data depends on the data each EDProducer produces including indirect dependences")(
1060       kExcludeESModulesCommandOpt, "do not print ES module information")(
1061       kShowAllModulesCommandOpt, "show all modules (not just those that created data in the file)")(
1062       kShowTopLevelPSetsCommandOpt, "show all top level PSets")(
1063       kFindMatchCommandOpt,
1064       boost::program_options::value<std::vector<std::string>>(),
1065       "show only modules whose information contains the matching string (or all the matching strings, this option can "
1066       "be repeated with different strings)")(kDontPrintProductsCommandOpt, "do not print products produced by module")(
1067       kDumpPSetIDCommandOpt,
1068       value<std::string>(),
1069       "print the parameter set associated with the parameter set ID string (and print nothing else)");
1070   // clang-format on
1071 
1072   //we don't want users to see these in the help messages since this
1073   // name only exists since the parser needs it
1074   options_description hidden;
1075   hidden.add_options()(kFileNameOpt, value<std::string>(), "file name");
1076 
1077   //full list of options for the parser
1078   options_description cmdline_options;
1079   cmdline_options.add(desc).add(hidden);
1080 
1081   positional_options_description p;
1082   p.add(kFileNameOpt, -1);
1083 
1084   variables_map vm;
1085   try {
1086     store(command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm);
1087     notify(vm);
1088   } catch (error const& iException) {
1089     std::cerr << iException.what();
1090     return 1;
1091   }
1092 
1093   if (vm.count(kHelpOpt)) {
1094     std::cout << desc << std::endl;
1095     return 0;
1096   }
1097 
1098   if (vm.count(kSortOpt)) {
1099     HistoryNode::sort_ = true;
1100   }
1101 
1102   bool showDependencies = false;
1103   if (vm.count(kDependenciesOpt)) {
1104     showDependencies = true;
1105   }
1106 
1107   bool extendedAncestors = false;
1108   if (vm.count(kExtendedAncestorsOpt)) {
1109     extendedAncestors = true;
1110   }
1111 
1112   bool extendedDescendants = false;
1113   if (vm.count(kExtendedDescendantsOpt)) {
1114     extendedDescendants = true;
1115   }
1116 
1117   bool excludeESModules = false;
1118   if (vm.count(kExcludeESModulesOpt)) {
1119     excludeESModules = true;
1120   }
1121 
1122   bool showAllModules = false;
1123   if (vm.count(kShowAllModulesOpt)) {
1124     showAllModules = true;
1125   }
1126 
1127   bool showTopLevelPSets = false;
1128   if (vm.count(kShowTopLevelPSetsOpt)) {
1129     showTopLevelPSets = true;
1130   }
1131 
1132   std::string fileName;
1133   if (vm.count(kFileNameOpt)) {
1134     try {
1135       fileName = vm[kFileNameOpt].as<std::string>();
1136     } catch (boost::bad_any_cast const& e) {
1137       std::cout << e.what() << std::endl;
1138       return 2;
1139     }
1140   } else {
1141     std::cout << "Data file not specified." << std::endl;
1142     std::cout << desc << std::endl;
1143     return 2;
1144   }
1145 
1146   std::string dumpPSetID;
1147   if (vm.count(kDumpPSetIDOpt)) {
1148     try {
1149       dumpPSetID = vm[kDumpPSetIDOpt].as<std::string>();
1150     } catch (boost::bad_any_cast const& e) {
1151       std::cout << e.what() << std::endl;
1152       return 2;
1153     }
1154   }
1155 
1156   std::vector<std::string> findMatch;
1157   if (vm.count(kFindMatchOpt)) {
1158     try {
1159       findMatch = vm[kFindMatchOpt].as<std::vector<std::string>>();
1160     } catch (boost::bad_any_cast const& e) {
1161       std::cout << e.what() << std::endl;
1162       return 2;
1163     }
1164   }
1165 
1166   bool dontPrintProducts = false;
1167   if (vm.count(kDontPrintProductsOpt)) {
1168     dontPrintProducts = true;
1169   }
1170 
1171   //silence ROOT warnings about missing dictionaries
1172   gErrorIgnoreLevel = kError;
1173 
1174   ProvenanceDumper dumper(fileName,
1175                           showDependencies,
1176                           extendedAncestors,
1177                           extendedDescendants,
1178                           excludeESModules,
1179                           showAllModules,
1180                           showTopLevelPSets,
1181                           findMatch,
1182                           dontPrintProducts,
1183                           dumpPSetID);
1184   int exitCode(0);
1185   try {
1186     dumper.dump();
1187     exitCode = dumper.exitCode();
1188   } catch (cms::Exception const& x) {
1189     std::cerr << "cms::Exception caught\n";
1190     std::cerr << x.what() << '\n';
1191     exitCode = 2;
1192   } catch (std::exception& x) {
1193     std::cerr << "std::exception caught\n";
1194     std::cerr << x.what() << '\n';
1195     exitCode = 3;
1196   } catch (...) {
1197     std::cerr << "Unknown exception caught\n";
1198     exitCode = 4;
1199   }
1200 
1201   dumper.printErrors(std::cerr);
1202   return exitCode;
1203 }