Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-02-13 02:58:34

0001 //********************************************************************************
0002 //
0003 //  Description:
0004 //    Producing and filling histograms for generator-level HLT path efficiency histograms. Harvested by a HLTGenValClient.
0005 //
0006 // Implementation:
0007 //   Histograms for objects of a certain type are created for multiple paths chosen by the user: for all objects,
0008 //   and for objects passing filters in the path, determined by deltaR matching.
0009 //   Each HLTGenValSource can handle a single object type and any number of paths (and filters in them)
0010 //
0011 //  Author: Finn Labe, UHH, Jul. 2022
0012 //
0013 //********************************************************************************
0014 
0015 // system include files
0016 #include <memory>
0017 #include <chrono>
0018 #include <ctime>
0019 
0020 // user include files
0021 #include "FWCore/Framework/interface/Event.h"
0022 #include "FWCore/Framework/interface/MakerMacros.h"
0023 
0024 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0025 #include "FWCore/Utilities/interface/InputTag.h"
0026 
0027 // including GenParticles
0028 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0029 
0030 // icnluding GenMET
0031 #include "DataFormats/METReco/interface/GenMETCollection.h"
0032 #include "DataFormats/METReco/interface/GenMET.h"
0033 
0034 // includes needed for histogram creation
0035 #include "FWCore/ServiceRegistry/interface/Service.h"
0036 #include "CommonTools/UtilAlgos/interface/TFileService.h"
0037 
0038 // FunctionDefs
0039 #include "DQMOffline/Trigger/interface/FunctionDefs.h"
0040 
0041 // includes of histogram collection class
0042 #include "Validation/HLTrigger/interface/HLTGenValHistCollPath.h"
0043 
0044 // DQMStore
0045 #include "DQMServices/Core/interface/DQMStore.h"
0046 #include "DQMServices/Core/interface/DQMEDAnalyzer.h"
0047 
0048 // trigger Event
0049 #include "HLTrigger/HLTcore/interface/HLTConfigProvider.h"
0050 #include "DataFormats/HLTReco/interface/TriggerEvent.h"
0051 
0052 // object that can be a GenJet, GenParticle or energy sum
0053 #include "Validation/HLTrigger/interface/HLTGenValObject.h"
0054 #include "Validation/HLTrigger/interface/HLTGenValObjectMgr.h"
0055 
0056 class HLTGenValSource : public DQMEDAnalyzer {
0057 public:
0058   explicit HLTGenValSource(const edm::ParameterSet&);
0059   ~HLTGenValSource() override = default;
0060   HLTGenValSource(const HLTGenValSource&) = delete;
0061   HLTGenValSource& operator=(const HLTGenValSource&) = delete;
0062 
0063   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0064 
0065 private:
0066   void analyze(const edm::Event&, const edm::EventSetup&) override;
0067   void bookHistograms(DQMStore::IBooker&, edm::Run const& run, edm::EventSetup const& c) override;
0068   void dqmBeginRun(const edm::Run&, const edm::EventSetup&) override;
0069   void initCfgs(const edm::Run&, const edm::EventSetup&);
0070 
0071   // functions to get correct object collection for chosen object type
0072   std::vector<HLTGenValObject> getObjectCollection(const edm::Event&);
0073   std::vector<HLTGenValObject> getGenParticles(const edm::Event&);
0074   reco::GenParticle getLastCopyPreFSR(reco::GenParticle part);
0075   reco::GenParticle getLastCopy(reco::GenParticle part);
0076   bool passGenJetID(const reco::GenJet& jet);
0077   // ----------member data ---------------------------
0078 
0079   HLTGenValObjectMgr genObjMgr_;
0080 
0081   const edm::EDGetTokenT<trigger::TriggerEvent> trigEventToken_;
0082 
0083   bool initalised_;
0084   bool booked_;
0085 
0086   // config strings/Psets
0087   std::string objType_;
0088   std::string dirName_;
0089   std::vector<edm::ParameterSet> histConfigs_;
0090   std::vector<edm::ParameterSet> histConfigs2D_;
0091   std::vector<edm::ParameterSet> binnings_;
0092   std::string hltProcessName_;
0093   std::string sampleLabel_;  //this if set is the label in the legend
0094 
0095   // constructing the info string, which will be written to the output file for display of information in the GUI
0096   // the string will have a JSON formating, thus starting here with the opening bracket, which will be close directly before saving to the root file
0097   std::string infoString_ = "{";
0098 
0099   // histogram collection per path
0100   std::vector<HLTGenValHistCollPath> collectionPath_;
0101 
0102   // HLT config provider/getter
0103   HLTConfigProvider hltConfig_;
0104 
0105   // some miscellaneous member variables
0106   std::vector<std::string> hltPathsToCheck_;
0107   std::vector<std::string> hltPaths_;
0108   std::vector<std::string> hltPathSpecificCuts_;
0109   double dR2limit_;
0110   bool doOnlyLastFilter_;
0111 };
0112 
0113 HLTGenValSource::HLTGenValSource(const edm::ParameterSet& iConfig)
0114     : genObjMgr_(iConfig.getParameter<edm::ParameterSet>("genConfig"), consumesCollector()),
0115       trigEventToken_(consumes<trigger::TriggerEvent>(iConfig.getParameter<edm::InputTag>("trigEvent"))),
0116       initalised_(false),
0117       booked_(false)
0118 
0119 {
0120   // getting the histogram configurations
0121   histConfigs_ = iConfig.getParameterSetVector("histConfigs");
0122   histConfigs2D_ = iConfig.getParameterSetVector("histConfigs2D");
0123   binnings_ = iConfig.getParameterSetVector("binnings");
0124 
0125   // getting all other configurations
0126   dirName_ = iConfig.getParameter<std::string>("dqmDirName");
0127   objType_ = iConfig.getParameter<std::string>("objType");
0128   dR2limit_ = iConfig.getParameter<double>("dR2limit");
0129   doOnlyLastFilter_ = iConfig.getParameter<bool>("doOnlyLastFilter");
0130   hltProcessName_ = iConfig.getParameter<std::string>("hltProcessName");
0131   sampleLabel_ = iConfig.getParameter<std::string>("sampleLabel");
0132   hltPathsToCheck_ = iConfig.getParameter<std::vector<std::string>>("hltPathsToCheck");
0133 }
0134 
0135 void HLTGenValSource::initCfgs(const edm::Run& iRun, const edm::EventSetup& iSetup) {
0136   // writing general information to info JSON
0137   auto t = std::time(nullptr);
0138   auto tm = *std::localtime(&t);
0139 
0140   // date and time of running this
0141   std::ostringstream timeStringStream;
0142   timeStringStream << std::put_time(&tm, "%d-%m-%Y %H-%M-%S");
0143   auto timeString = timeStringStream.str();
0144   infoString_ += "\"date & time\":\"" + timeString + "\",";
0145 
0146   std::string cmsswVersion;
0147   const edm::ProcessHistory& processHistory = iRun.processHistory();
0148   for (const auto& process : processHistory) {
0149     if (process.processName() == hltProcessName_) {
0150       cmsswVersion = process.releaseVersion();  //this has quotes around it
0151       break;
0152     }
0153   }
0154   if (cmsswVersion.empty()) {
0155     cmsswVersion =
0156         "\"" + std::string(std::getenv("CMSSW_VERSION")) + "\"";  //using convention it already has quotes on it
0157   }
0158   infoString_ += std::string("\"CMSSW release\":") + cmsswVersion + ",";
0159   infoString_ += std::string("\"sample label\":\"") + sampleLabel_ + "\",";
0160 
0161   // Initialize hltConfig, for cross-checking whether chosen paths exist
0162   bool changedConfig;
0163   if (!hltConfig_.init(iRun, iSetup, hltProcessName_, changedConfig)) {
0164     edm::LogError("HLTGenValSource") << "Initialization of HLTConfigProvider failed!";
0165     return;
0166   }
0167 
0168   // global tag
0169   infoString_ += std::string("\"global tag\":\"") + hltConfig_.globalTag() + "\",";
0170 
0171   // confDB table name
0172   infoString_ += std::string("\"HLT ConfDB table\":\"") + hltConfig_.tableName() + "\"}";
0173 
0174   // Get the set of trigger paths we want to make plots for
0175   std::vector<std::string> notFoundPaths;
0176   for (auto const& pathToCheck : hltPathsToCheck_) {
0177     // It is possible to add additional requirements to each path, seperated by a colon from the path name
0178     // these additional requirements are split from the path name here
0179     std::string cleanedPathToCheck;
0180     std::string pathSpecificCuts = "";
0181     if (pathToCheck.find(':') != std::string::npos) {
0182       // splitting the string
0183       std::stringstream hltPathToCheckInputStream(pathToCheck);
0184       std::string hltPathToCheckInputSegment;
0185       std::vector<std::string> hltPathToCheckInputSeglist;
0186       while (std::getline(hltPathToCheckInputStream, hltPathToCheckInputSegment, ':')) {
0187         hltPathToCheckInputSeglist.push_back(hltPathToCheckInputSegment);
0188       }
0189 
0190       // here, exactly two parts are expected
0191       if (hltPathToCheckInputSeglist.size() != 2)
0192         throw cms::Exception("InputError")
0193             << "Path string " << pathToCheck
0194             << " can not be properly split into path and cuts: please use exactly one colon!.\n";
0195 
0196       // the first part is the name of the path
0197       cleanedPathToCheck = hltPathToCheckInputSeglist.at(0);
0198 
0199       // second part are the cuts, to be parsed later
0200       pathSpecificCuts = hltPathToCheckInputSeglist.at(1);
0201 
0202     } else {
0203       cleanedPathToCheck = pathToCheck;
0204     }
0205 
0206     bool pathfound = false;
0207     for (auto const& pathFromConfig : hltConfig_.triggerNames()) {
0208       if (pathFromConfig.find(cleanedPathToCheck) != std::string::npos) {
0209         hltPaths_.push_back(pathFromConfig);
0210 
0211         // in case the path was added twice, we'll add a tag automatically
0212         int count = std::count(hltPaths_.begin(), hltPaths_.end(), pathFromConfig);
0213         if (count > 1) {
0214           pathSpecificCuts += std::string(",autotag=v") + std::to_string(count);
0215         }
0216         hltPathSpecificCuts_.push_back(pathSpecificCuts);
0217         pathfound = true;
0218       }
0219     }
0220     if (!pathfound)
0221       notFoundPaths.push_back(cleanedPathToCheck);
0222   }
0223   if (!notFoundPaths.empty()) {
0224     // error handling in case some paths do not exist
0225     std::string notFoundPathsMessage = "";
0226     for (const auto& path : notFoundPaths)
0227       notFoundPathsMessage += "- " + path + "\n";
0228     edm::LogError("HLTGenValSource") << "The following paths could not be found and will not be used: \n"
0229                                      << notFoundPathsMessage << std::endl;
0230   }
0231 
0232   // before creating the collections for each path, we'll store the needed configurations in a pset
0233   // we'll copy this base multiple times and add the respective path
0234   // most of these options are not needed in the pathColl, but in the filterColls created in the pathColl
0235   edm::ParameterSet pathCollConfig;
0236   pathCollConfig.addParameter<std::string>("objType", objType_);
0237   pathCollConfig.addParameter<double>("dR2limit", dR2limit_);
0238   pathCollConfig.addParameter<bool>("doOnlyLastFilter", doOnlyLastFilter_);
0239   pathCollConfig.addParameter<std::string>("hltProcessName", hltProcessName_);
0240 
0241   // creating a histogram collection for each path
0242   for (const auto& path : hltPaths_) {
0243     edm::ParameterSet pathCollConfigStep = pathCollConfig;
0244     pathCollConfigStep.addParameter<std::string>("triggerPath", path);
0245     collectionPath_.emplace_back(HLTGenValHistCollPath(pathCollConfigStep, hltConfig_));
0246   }
0247   initalised_ = true;
0248 }
0249 
0250 void HLTGenValSource::dqmBeginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
0251   if (!initalised_)
0252     initCfgs(iRun, iSetup);
0253 }
0254 
0255 // ------------ method called for each event  ------------
0256 void HLTGenValSource::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
0257   // creating the collection of HLTGenValObjects
0258   const std::vector<HLTGenValObject> objects = genObjMgr_.getGenValObjects(iEvent, objType_);
0259 
0260   // init triggerEvent, which is always needed
0261   edm::Handle<trigger::TriggerEvent> triggerEvent;
0262   iEvent.getByToken(trigEventToken_, triggerEvent);
0263 
0264   // loop over all objects and fill hists
0265   for (const auto& object : objects) {
0266     for (auto& collection_path : collectionPath_) {
0267       collection_path.fillHists(object, triggerEvent);
0268     }
0269   }
0270 }
0271 
0272 // ------------ method called once each job just before starting event loop  ------------
0273 void HLTGenValSource::bookHistograms(DQMStore::IBooker& iBooker, const edm::Run& run, const edm::EventSetup& setup) {
0274   iBooker.setCurrentFolder(dirName_);
0275   iBooker.bookString("HLTGenValInfo", infoString_);
0276 
0277   // booking all histograms
0278   for (long unsigned int i = 0; i < collectionPath_.size(); i++) {
0279     std::vector<edm::ParameterSet> histConfigs = histConfigs_;
0280     for (auto& histConfig : histConfigs) {
0281       histConfig.addParameter<std::string>("pathSpecificCuts", hltPathSpecificCuts_.at(i));
0282       histConfig.addParameter<std::vector<edm::ParameterSet>>("binnings",
0283                                                               binnings_);  // passing along the user-defined binnings
0284     }
0285 
0286     collectionPath_.at(i).bookHists(iBooker, histConfigs, histConfigs2D_);
0287   }
0288   booked_ = true;
0289 }
0290 
0291 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0292 void HLTGenValSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0293   edm::ParameterSetDescription desc;
0294 
0295   // basic parameter strings
0296   desc.add<std::string>(
0297       "objType");  // this deliberately has no default, as this is the main thing the user needs to chose
0298   desc.add<std::vector<std::string>>(
0299       "hltPathsToCheck");  // this for the moment also has no default: maybe there can be some way to handle this later?
0300   desc.add<std::string>("dqmDirName", "HLTGenVal");
0301   desc.add<std::string>("hltProcessName", "HLT");
0302   desc.add<std::string>("sampleLabel", "");  //this is the label in the legend
0303   desc.add<double>("dR2limit", 0.1);
0304   desc.add<bool>("doOnlyLastFilter", false);
0305 
0306   desc.add<edm::ParameterSetDescription>("genConfig", HLTGenValObjectMgr::makePSetDescription());
0307   desc.add<edm::InputTag>("trigEvent", edm::InputTag("hltTriggerSummaryAOD"));
0308 
0309   // hist descriptors, which are a vector of PSets
0310 
0311   // defining single histConfig
0312   // this is generally without default, but a default set of histConfigs is specified below
0313   edm::ParameterSetDescription histConfig;
0314   histConfig.add<std::string>("vsVar");
0315   histConfig.add<std::vector<double>>("binLowEdges");
0316   histConfig.addVPSet(
0317       "rangeCuts", VarRangeCut<HLTGenValObject>::makePSetDescription(), std::vector<edm::ParameterSet>());
0318 
0319   // default set of histConfigs
0320   std::vector<edm::ParameterSet> histConfigDefaults;
0321 
0322   edm::ParameterSet histConfigDefault0;
0323   histConfigDefault0.addParameter<std::string>("vsVar", "pt");
0324   std::vector<double> defaultPtBinning{0,  5,  10, 12.5, 15,  17.5, 20,  22.5, 25,  30,  35, 40,
0325                                        45, 50, 60, 80,   100, 150,  200, 250,  300, 350, 400};
0326   histConfigDefault0.addParameter<std::vector<double>>("binLowEdges", defaultPtBinning);
0327   histConfigDefaults.push_back(histConfigDefault0);
0328 
0329   edm::ParameterSet histConfigDefault1;
0330   histConfigDefault1.addParameter<std::string>("vsVar", "eta");
0331   std::vector<double> defaultetaBinning{-10, -8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8, 10};
0332   histConfigDefault1.addParameter<std::vector<double>>("binLowEdges", defaultetaBinning);
0333   histConfigDefaults.push_back(histConfigDefault1);
0334 
0335   desc.addVPSet("histConfigs", histConfig, histConfigDefaults);
0336 
0337   // defining single histConfig2D
0338   edm::ParameterSetDescription histConfig2D;
0339   histConfig2D.add<std::string>("vsVarX");
0340   histConfig2D.add<std::string>("vsVarY");
0341   histConfig2D.add<std::vector<double>>("binLowEdgesX");
0342   histConfig2D.add<std::vector<double>>("binLowEdgesY");
0343   histConfig2D.addVPSet(
0344       "rangeCuts", VarRangeCut<HLTGenValObject>::makePSetDescription(), std::vector<edm::ParameterSet>());
0345   // default set of histConfigs
0346   std::vector<edm::ParameterSet> histConfigDefaults2D;
0347 
0348   edm::ParameterSet histConfigDefault2D0;
0349   histConfigDefault2D0.addParameter<std::string>("vsVarX", "pt");
0350   histConfigDefault2D0.addParameter<std::string>("vsVarY", "eta");
0351   histConfigDefault2D0.addParameter<std::vector<double>>("binLowEdgesX", defaultPtBinning);
0352   histConfigDefault2D0.addParameter<std::vector<double>>("binLowEdgesY", defaultetaBinning);
0353 
0354   histConfigDefaults2D.push_back(histConfigDefault2D0);
0355 
0356   desc.addVPSet("histConfigs2D", histConfig2D, histConfigDefaults2D);
0357 
0358   // binnings, which are vectors of PSets
0359   // there are no default for this
0360   edm::ParameterSetDescription binningConfig;
0361   binningConfig.add<std::string>("name");
0362   binningConfig.add<std::string>("vsVar");
0363   binningConfig.add<std::vector<double>>("binLowEdges");
0364 
0365   // this by default is empty
0366   std::vector<edm::ParameterSet> binningConfigDefaults;
0367 
0368   desc.addVPSet("binnings", binningConfig, binningConfigDefaults);
0369 
0370   descriptions.addDefault(desc);
0371 }
0372 
0373 //define this as a framework plug-in
0374 DEFINE_FWK_MODULE(HLTGenValSource);