CMS 3D CMS Logo

HLTGenValSource.cc
Go to the documentation of this file.
1 //********************************************************************************
2 //
3 // Description:
4 // Producing and filling histograms for generator-level HLT path efficiency histograms. Harvested by a HLTGenValClient.
5 //
6 // Implementation:
7 // Histograms for objects of a certain type are created for multiple paths chosen by the user: for all objects,
8 // and for objects passing filters in the path, determined by deltaR matching.
9 // Each HLTGenValSource can handle a single object type and any number of paths (and filters in them)
10 //
11 // Author: Finn Labe, UHH, Jul. 2022
12 //
13 //********************************************************************************
14 
15 // system include files
16 #include <memory>
17 #include <chrono>
18 #include <ctime>
19 
20 // user include files
23 
26 
27 // including GenParticles
29 
30 // icnluding GenMET
33 
34 // includes needed for histogram creation
37 
38 // FunctionDefs
40 
41 // includes of histogram collection class
43 
44 // DQMStore
47 
48 // trigger Event
51 
52 // object that can be a GenJet, GenParticle or energy sum
54 
56 public:
57  explicit HLTGenValSource(const edm::ParameterSet&);
58  ~HLTGenValSource() override = default;
59  HLTGenValSource(const HLTGenValSource&) = delete;
60  HLTGenValSource& operator=(const HLTGenValSource&) = delete;
61 
62  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
63 
64 private:
65  void analyze(const edm::Event&, const edm::EventSetup&) override;
66  void bookHistograms(DQMStore::IBooker&, edm::Run const& run, edm::EventSetup const& c) override;
67  void dqmBeginRun(const edm::Run&, const edm::EventSetup&) override;
68 
69  // functions to get correct object collection for chosen object type
70  std::vector<HLTGenValObject> getObjectCollection(const edm::Event&);
71  std::vector<HLTGenValObject> getGenParticles(const edm::Event&);
74 
75  // ----------member data ---------------------------
76 
77  // tokens to get collections
83 
84  // config strings/Psets
87  std::vector<edm::ParameterSet> histConfigs_;
88  std::vector<edm::ParameterSet> histConfigs2D_;
89  std::vector<edm::ParameterSet> binnings_;
91 
92  // constructing the info string, which will be written to the output file for display of information in the GUI
93  // 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
95 
96  // histogram collection per path
97  std::vector<HLTGenValHistCollPath> collectionPath_;
98 
99  // HLT config provider/getter
101 
102  // some miscellaneous member variables
103  std::vector<std::string> hltPathsToCheck_;
104  std::vector<std::string> hltPaths;
105  std::vector<std::string> hltPathSpecificCuts;
106  double dR2limit_;
108 };
109 
111  : genParticleToken_(consumes<reco::GenParticleCollection>(
112  iConfig.getParameterSet("inputCollections").getParameter<edm::InputTag>("genParticles"))),
113  genMETToken_(consumes<reco::GenMETCollection>(
114  iConfig.getParameterSet("inputCollections").getParameter<edm::InputTag>("genMET"))),
115  ak4genJetToken_(consumes<reco::GenJetCollection>(
116  iConfig.getParameterSet("inputCollections").getParameter<edm::InputTag>("ak4GenJets"))),
117  ak8genJetToken_(consumes<reco::GenJetCollection>(
118  iConfig.getParameterSet("inputCollections").getParameter<edm::InputTag>("ak8GenJets"))),
119  trigEventToken_(consumes<trigger::TriggerEvent>(
120  iConfig.getParameterSet("inputCollections").getParameter<edm::InputTag>("TrigEvent"))) {
121  // getting the histogram configurations
122  histConfigs_ = iConfig.getParameterSetVector("histConfigs");
123  histConfigs2D_ = iConfig.getParameterSetVector("histConfigs2D");
124  binnings_ = iConfig.getParameterSetVector("binnings");
125 
126  // getting all other configurations
127  dirName_ = iConfig.getParameter<std::string>("dqmDirName");
128  objType_ = iConfig.getParameter<std::string>("objType");
129  dR2limit_ = iConfig.getParameter<double>("dR2limit");
130  doOnlyLastFilter_ = iConfig.getParameter<bool>("doOnlyLastFilter");
131  hltProcessName_ = iConfig.getParameter<std::string>("hltProcessName");
132  hltPathsToCheck_ = iConfig.getParameter<std::vector<std::string>>("hltPathsToCheck");
133 }
134 
135 void HLTGenValSource::dqmBeginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
136  // writing general information to info JSON
137  auto t = std::time(nullptr);
138  auto tm = *std::localtime(&t);
139 
140  // date and time of running this
141  std::ostringstream timeStringStream;
142  timeStringStream << std::put_time(&tm, "%d-%m-%Y %H-%M-%S");
143  auto timeString = timeStringStream.str();
144  infoString_ += "\"date & time\":\"" + timeString + "\",";
145 
146  // CMSSW version
147  std::string cmsswVersion = std::getenv("CMSSW_VERSION");
148  infoString_ += std::string("\"CMSSW release\":\"") + cmsswVersion + "\",";
149 
150  // Initialize hltConfig, for cross-checking whether chosen paths exist
151  bool changedConfig;
152  if (!hltConfig_.init(iRun, iSetup, hltProcessName_, changedConfig)) {
153  edm::LogError("HLTGenValSource") << "Initialization of HLTConfigProvider failed!";
154  return;
155  }
156 
157  // global tag
158  infoString_ += std::string("\"global tag\":\"") + hltConfig_.globalTag() + "\",";
159 
160  // confDB table name
161  infoString_ += std::string("\"HLT ConfDB table\":\"") + hltConfig_.tableName() + "\",";
162 
163  // Get the set of trigger paths we want to make plots for
164  std::vector<std::string> notFoundPaths;
165  for (auto const& pathToCheck : hltPathsToCheck_) {
166  // It is possible to add additional requirements to each path, seperated by a colon from the path name
167  // these additional requirements are split from the path name here
168  std::string cleanedPathToCheck;
169  std::string pathSpecificCuts = "";
170  if (pathToCheck.find(':') != std::string::npos) {
171  // splitting the string
172  std::stringstream hltPathToCheckInputStream(pathToCheck);
173  std::string hltPathToCheckInputSegment;
174  std::vector<std::string> hltPathToCheckInputSeglist;
175  while (std::getline(hltPathToCheckInputStream, hltPathToCheckInputSegment, ':')) {
176  hltPathToCheckInputSeglist.push_back(hltPathToCheckInputSegment);
177  }
178 
179  // here, exactly two parts are expected
180  if (hltPathToCheckInputSeglist.size() != 2)
181  throw cms::Exception("InputError")
182  << "Path string can not be properly split into path and cuts: please use exactly one colon!.\n";
183 
184  // the first part is the name of the path
185  cleanedPathToCheck = hltPathToCheckInputSeglist.at(0);
186 
187  // second part are the cuts, to be parsed later
188  pathSpecificCuts = hltPathToCheckInputSeglist.at(1);
189 
190  } else {
191  cleanedPathToCheck = pathToCheck;
192  }
193 
194  bool pathfound = false;
195  for (auto const& pathFromConfig : hltConfig_.triggerNames()) {
196  if (pathFromConfig.find(cleanedPathToCheck) != std::string::npos) {
197  hltPaths.push_back(pathFromConfig);
198 
199  // in case the path was added twice, we'll add a tag automatically
200  int count = std::count(hltPaths.begin(), hltPaths.end(), pathFromConfig);
201  if (count > 1) {
202  pathSpecificCuts += std::string(",autotag=v") + std::to_string(count);
203  }
204  hltPathSpecificCuts.push_back(pathSpecificCuts);
205  pathfound = true;
206  }
207  }
208  if (!pathfound)
209  notFoundPaths.push_back(cleanedPathToCheck);
210  }
211  if (!notFoundPaths.empty()) {
212  // error handling in case some paths do not exist
213  std::string notFoundPathsMessage = "";
214  for (const auto& path : notFoundPaths)
215  notFoundPathsMessage += "- " + path + "\n";
216  edm::LogError("HLTGenValSource") << "The following paths could not be found and will not be used: \n"
217  << notFoundPathsMessage << std::endl;
218  }
219 
220  // before creating the collections for each path, we'll store the needed configurations in a pset
221  // we'll copy this base multiple times and add the respective path
222  // most of these options are not needed in the pathColl, but in the filterColls created in the pathColl
223  edm::ParameterSet pathCollConfig;
224  pathCollConfig.addParameter<std::string>("objType", objType_);
225  pathCollConfig.addParameter<double>("dR2limit", dR2limit_);
226  pathCollConfig.addParameter<bool>("doOnlyLastFilter", doOnlyLastFilter_);
227  pathCollConfig.addParameter<std::string>("hltProcessName", hltProcessName_);
228 
229  // creating a histogram collection for each path
230  for (const auto& path : hltPaths) {
231  edm::ParameterSet pathCollConfigStep = pathCollConfig;
232  pathCollConfigStep.addParameter<std::string>("triggerPath", path);
233  collectionPath_.emplace_back(HLTGenValHistCollPath(pathCollConfigStep, hltConfig_));
234  }
235 }
236 
237 // ------------ method called for each event ------------
239  // creating the collection of HLTGenValObjects
240  const std::vector<HLTGenValObject> objects = getObjectCollection(iEvent);
241 
242  // init triggerEvent, which is always needed
244  iEvent.getByToken(trigEventToken_, triggerEvent);
245 
246  // loop over all objects and fill hists
247  for (const auto& object : objects) {
248  for (auto& collection_path : collectionPath_) {
249  collection_path.fillHists(object, triggerEvent);
250  }
251  }
252 }
253 
254 // ------------ method called once each job just before starting event loop ------------
256  iBooker.setCurrentFolder(dirName_);
257 
258  if (infoString_.back() == ',')
259  infoString_.pop_back();
260  infoString_ += "}"; // adding the closing bracked to the JSON string
261  iBooker.bookString("HLTGenValInfo", infoString_);
262 
263  // booking all histograms
264  for (long unsigned int i = 0; i < collectionPath_.size(); i++) {
265  std::vector<edm::ParameterSet> histConfigs = histConfigs_;
266  for (auto& histConfig : histConfigs) {
267  histConfig.addParameter<std::string>("pathSpecificCuts", hltPathSpecificCuts.at(i));
268  histConfig.addParameter<std::vector<edm::ParameterSet>>("binnings",
269  binnings_); // passing along the user-defined binnings
270  }
271 
272  collectionPath_.at(i).bookHists(iBooker, histConfigs, histConfigs2D_);
273  }
274 }
275 
276 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
279 
280  // basic parameter strings
281  desc.add<std::string>(
282  "objType"); // this deliberately has no default, as this is the main thing the user needs to chose
283  desc.add<std::vector<std::string>>(
284  "hltPathsToCheck"); // this for the moment also has no default: maybe there can be some way to handle this later?
285  desc.add<std::string>("dqmDirName", "HLTGenVal");
286  desc.add<std::string>("hltProcessName", "HLT");
287  desc.add<double>("dR2limit", 0.1);
288  desc.add<bool>("doOnlyLastFilter", false);
289 
290  // input collections, a PSet
291  edm::ParameterSetDescription inputCollections;
292  inputCollections.add<edm::InputTag>("genParticles", edm::InputTag("genParticles"));
293  inputCollections.add<edm::InputTag>("genMET", edm::InputTag("genMetTrue"));
294  inputCollections.add<edm::InputTag>("ak4GenJets", edm::InputTag("ak4GenJets"));
295  inputCollections.add<edm::InputTag>("ak8GenJets", edm::InputTag("ak8GenJets"));
296  inputCollections.add<edm::InputTag>("TrigEvent", edm::InputTag("hltTriggerSummaryAOD"));
297  desc.add<edm::ParameterSetDescription>("inputCollections", inputCollections);
298 
299  // hist descriptors, which are a vector of PSets
300 
301  // defining single histConfig
302  // this is generally without default, but a default set of histConfigs is specified below
303  edm::ParameterSetDescription histConfig;
304  histConfig.add<std::string>("vsVar");
305  histConfig.add<std::vector<double>>("binLowEdges");
306  histConfig.addVPSet(
307  "rangeCuts", VarRangeCut<HLTGenValObject>::makePSetDescription(), std::vector<edm::ParameterSet>());
308 
309  // default set of histConfigs
310  std::vector<edm::ParameterSet> histConfigDefaults;
311 
312  edm::ParameterSet histConfigDefault0;
313  histConfigDefault0.addParameter<std::string>("vsVar", "pt");
314  std::vector<double> defaultPtBinning{0, 5, 10, 12.5, 15, 17.5, 20, 22.5, 25, 30, 35, 40,
315  45, 50, 60, 80, 100, 150, 200, 250, 300, 350, 400};
316  histConfigDefault0.addParameter<std::vector<double>>("binLowEdges", defaultPtBinning);
317  histConfigDefaults.push_back(histConfigDefault0);
318 
319  edm::ParameterSet histConfigDefault1;
320  histConfigDefault1.addParameter<std::string>("vsVar", "eta");
321  std::vector<double> defaultetaBinning{-10, -8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8, 10};
322  histConfigDefault1.addParameter<std::vector<double>>("binLowEdges", defaultetaBinning);
323  histConfigDefaults.push_back(histConfigDefault1);
324 
325  desc.addVPSet("histConfigs", histConfig, histConfigDefaults);
326 
327  // defining single histConfig2D
328  edm::ParameterSetDescription histConfig2D;
329  histConfig2D.add<std::string>("vsVarX");
330  histConfig2D.add<std::string>("vsVarY");
331  histConfig2D.add<std::vector<double>>("binLowEdgesX");
332  histConfig2D.add<std::vector<double>>("binLowEdgesY");
333 
334  // default set of histConfigs
335  std::vector<edm::ParameterSet> histConfigDefaults2D;
336 
337  edm::ParameterSet histConfigDefault2D0;
338  histConfigDefault2D0.addParameter<std::string>("vsVarX", "pt");
339  histConfigDefault2D0.addParameter<std::string>("vsVarY", "eta");
340  histConfigDefault2D0.addParameter<std::vector<double>>("binLowEdgesX", defaultPtBinning);
341  histConfigDefault2D0.addParameter<std::vector<double>>("binLowEdgesY", defaultetaBinning);
342  histConfigDefaults2D.push_back(histConfigDefault2D0);
343 
344  desc.addVPSet("histConfigs2D", histConfig2D, histConfigDefaults2D);
345 
346  // binnings, which are vectors of PSets
347  // there are no default for this
348  edm::ParameterSetDescription binningConfig;
349  binningConfig.add<std::string>("name");
350  binningConfig.add<std::string>("vsVar");
351  binningConfig.add<std::vector<double>>("binLowEdges");
352 
353  // this by default is empty
354  std::vector<edm::ParameterSet> binningConfigDefaults;
355 
356  desc.addVPSet("binnings", binningConfig, binningConfigDefaults);
357 
358  descriptions.addDefault(desc);
359 }
360 
361 // this method handles the different object types and collections that can be used for efficiency calculation
362 std::vector<HLTGenValObject> HLTGenValSource::getObjectCollection(const edm::Event& iEvent) {
363  std::vector<HLTGenValObject> objects; // the vector of objects to be filled
364 
365  // handle object type
366  std::vector<std::string> implementedGenParticles = {"ele", "pho", "mu", "tau"};
367  if (std::find(implementedGenParticles.begin(), implementedGenParticles.end(), objType_) !=
368  implementedGenParticles.end()) {
370  } else if (objType_ == "AK4jet") { // ak4 jets, using the ak4GenJets collection
371  const auto& genJets = iEvent.getHandle(ak4genJetToken_);
372  for (size_t i = 0; i < genJets->size(); i++) {
373  const reco::GenJet p = (*genJets)[i];
374  objects.emplace_back(p);
375  }
376  } else if (objType_ == "AK8jet") { // ak8 jets, using the ak8GenJets collection
377  const auto& genJets = iEvent.getHandle(ak8genJetToken_);
378  for (size_t i = 0; i < genJets->size(); i++) {
379  const reco::GenJet p = (*genJets)[i];
380  objects.emplace_back(p);
381  }
382  } else if (objType_ == "AK4HT") { // ak4-based HT, using the ak4GenJets collection
383  const auto& genJets = iEvent.getHandle(ak4genJetToken_);
384  if (!genJets->empty()) {
385  double HTsum = 0.;
386  for (const auto& genJet : *genJets) {
387  if (genJet.pt() > 30 && std::abs(genJet.eta()) < 2.5)
388  HTsum += genJet.pt();
389  }
390  if (HTsum > 0)
391  objects.emplace_back(reco::Candidate::PolarLorentzVector(HTsum, 0, 0, 0));
392  }
393  } else if (objType_ == "AK8HT") { // ak8-based HT, using the ak8GenJets collection
394  const auto& genJets = iEvent.getHandle(ak8genJetToken_);
395  if (!genJets->empty()) {
396  double HTsum = 0.;
397  for (const auto& genJet : *genJets) {
398  if (genJet.pt() > 200 && std::abs(genJet.eta()) < 2.5)
399  HTsum += genJet.pt();
400  }
401  if (HTsum > 0)
402  objects.emplace_back(reco::Candidate::PolarLorentzVector(HTsum, 0, 0, 0));
403  }
404  } else if (objType_ == "MET") { // MET, using genMET
405  const auto& genMET = iEvent.getHandle(genMETToken_);
406  if (!genMET->empty()) {
407  auto genMETpt = (*genMET)[0].pt();
408  objects.emplace_back(reco::Candidate::PolarLorentzVector(genMETpt, 0, 0, 0));
409  }
410  } else
411  throw cms::Exception("InputError") << "Generator-level validation is not available for type " << objType_ << ".\n"
412  << "Please check for a potential spelling error.\n";
413 
414  return objects;
415 }
416 
417 // in case of GenParticles, a subset of the entire collection needs to be chosen
418 std::vector<HLTGenValObject> HLTGenValSource::getGenParticles(const edm::Event& iEvent) {
419  std::vector<HLTGenValObject> objects; // vector to be filled
420 
421  const auto& genParticles = iEvent.getHandle(genParticleToken_); // getting all GenParticles
422 
423  // we need to ge the ID corresponding to the desired GenParticle type
424  int pdgID = -1; // setting to -1 should not be needed, but prevents the compiler warning :)
425  if (objType_ == "ele")
426  pdgID = 11;
427  else if (objType_ == "pho")
428  pdgID = 22;
429  else if (objType_ == "mu")
430  pdgID = 13;
431  else if (objType_ == "tau")
432  pdgID = 15;
433 
434  // main loop over GenParticles
435  for (size_t i = 0; i < genParticles->size(); ++i) {
436  const reco::GenParticle p = (*genParticles)[i];
437 
438  // only GenParticles with correct ID
439  if (std::abs(p.pdgId()) != pdgID)
440  continue;
441 
442  // checking if particle comes from "hard process"
443  if (p.isHardProcess()) {
444  // depending on the particle type, last particle before or after FSR is chosen
445  if ((objType_ == "ele") || (objType_ == "pho"))
446  objects.emplace_back(getLastCopyPreFSR(p));
447  else if ((objType_ == "mu") || (objType_ == "tau"))
448  objects.emplace_back(getLastCopy(p));
449  }
450  }
451 
452  return objects;
453 }
454 
455 // function returning the last GenParticle in a decay chain before FSR
457  const auto& daughters = part.daughterRefVector();
458  if (daughters.size() == 1 && daughters.at(0)->pdgId() == part.pdgId())
459  return getLastCopyPreFSR(*daughters.at(0).get()); // recursion, whooo
460  else
461  return part;
462 }
463 
464 // function returning the last GenParticle in a decay chain
466  for (const auto& daughter : part.daughterRefVector()) {
467  if (daughter->pdgId() == part.pdgId())
468  return getLastCopy(*daughter.get());
469  }
470  return part;
471 }
472 
473 //define this as a framework plug-in
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
std::string objType_
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
Collection of Gen MET.
std::string hltProcessName_
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
reco::GenParticle getLastCopy(reco::GenParticle part)
const std::string & globalTag() const
global tag
std::vector< GenJet > GenJetCollection
collection of GenJet objects
std::vector< std::string > hltPaths
Log< level::Error, false > LogError
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
void dqmBeginRun(const edm::Run &, const edm::EventSetup &) override
static std::string to_string(const XMLCh *ch)
std::vector< edm::ParameterSet > binnings_
MonitorElement * bookString(TString const &name, TString const &value, FUNC onbooking=NOOP())
Definition: DQMStore.h:87
const edm::EDGetTokenT< reco::GenParticleCollection > genParticleToken_
int iEvent
Definition: GenABIO.cc:224
void addDefault(ParameterSetDescription const &psetDescription)
std::vector< HLTGenValObject > getObjectCollection(const edm::Event &)
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:135
std::string infoString_
HLTGenValSource(const edm::ParameterSet &)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Jets made from MC generator particles.
Definition: GenJet.h:23
const edm::EDGetTokenT< reco::GenJetCollection > ak8genJetToken_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
std::vector< std::string > hltPathsToCheck_
ParameterDescriptionBase * add(U const &iLabel, T const &value)
const edm::EDGetTokenT< trigger::TriggerEvent > trigEventToken_
const edm::EDGetTokenT< reco::GenJetCollection > ak4genJetToken_
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::vector< edm::ParameterSet > histConfigs_
std::vector< HLTGenValObject > getGenParticles(const edm::Event &)
HLTConfigProvider hltConfig_
part
Definition: HCALResponse.h:20
std::string dirName_
bool init(const edm::Run &iRun, const edm::EventSetup &iSetup, const std::string &processName, bool &changed)
d&#39;tor
std::vector< edm::ParameterSet > histConfigs2D_
std::vector< std::string > hltPathSpecificCuts
const std::vector< std::string > & triggerNames() const
names of trigger paths
ParameterSet const & getParameterSet(ParameterSetID const &id)
fixed size matrix
const std::string & tableName() const
HLT ConfDB table name.
HLT enums.
VParameterSet const & getParameterSetVector(std::string const &name) const
~HLTGenValSource() override=default
const edm::EDGetTokenT< reco::GenMETCollection > genMETToken_
void bookHistograms(DQMStore::IBooker &, edm::Run const &run, edm::EventSetup const &c) override
void analyze(const edm::Event &, const edm::EventSetup &) override
HLTGenValSource & operator=(const HLTGenValSource &)=delete
reco::GenParticle getLastCopyPreFSR(reco::GenParticle part)
std::vector< HLTGenValHistCollPath > collectionPath_
Definition: Run.h:45
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: Candidate.h:38