CMS 3D CMS Logo

HLTMuonMatchAndPlot.cc
Go to the documentation of this file.
1 
6 
15 #include <boost/algorithm/string/replace.hpp>
16 
17 #include <iostream>
18 #include <string>
19 #include <utility>
20 #include <utility>
21 
24 
25 using namespace std;
26 using namespace edm;
27 using namespace reco;
28 using namespace trigger;
29 using namespace l1extra;
30 
31 using vstring = std::vector<std::string>;
32 
35 
38  : hltProcessName_(pset.getParameter<string>("hltProcessName")),
39  destination_(pset.getUntrackedParameter<string>("destination")),
40  requiredTriggers_(pset.getUntrackedParameter<vstring>("requiredTriggers")),
41  targetParams_(pset.getParameterSet("targetParams")),
42  probeParams_(pset.getParameterSet("probeParams")),
43  hltPath_(std::move(hltPath)),
44  moduleLabel_(std::move(moduleLabel)),
45  isLastFilter_(islastfilter),
46  hasTargetRecoCuts(targetParams_.exists("recoCuts")),
47  hasProbeRecoCuts(probeParams_.exists("recoCuts")),
48  targetMuonSelector_(targetParams_.getUntrackedParameter<string>("recoCuts", "")),
49  targetZ0Cut_(targetParams_.getUntrackedParameter<double>("z0Cut", 0.)),
50  targetD0Cut_(targetParams_.getUntrackedParameter<double>("d0Cut", 0.)),
51  targetptCutZ_(targetParams_.getUntrackedParameter<double>("ptCut_Z", 20.)),
52  targetptCutJpsi_(targetParams_.getUntrackedParameter<double>("ptCut_Jpsi", 20.)),
53  probeMuonSelector_(probeParams_.getUntrackedParameter<string>("recoCuts", "")),
54  probeZ0Cut_(probeParams_.getUntrackedParameter<double>("z0Cut", 0.)),
55  probeD0Cut_(probeParams_.getUntrackedParameter<double>("d0Cut", 0.)),
56  triggerSelector_(targetParams_.getUntrackedParameter<string>("hltCuts", "")),
57  hasTriggerCuts_(targetParams_.exists("hltCuts")) {
58  // Create std::map<string, T> from ParameterSets.
59  fillMapFromPSet(binParams_, pset, "binParams");
60  fillMapFromPSet(plotCuts_, pset, "plotCuts");
61 
62  // Get the trigger level.
63  triggerLevel_ = "L3";
64  TPRegexp levelRegexp("L[1-3]");
65  // size_t nModules = moduleLabels_.size();
66  // cout << moduleLabel_ << " " << hltPath_ << endl;
67  TObjArray* levelArray = levelRegexp.MatchS(moduleLabel_);
68  if (levelArray->GetEntriesFast() > 0) {
69  triggerLevel_ = static_cast<const char*>(((TObjString*)levelArray->At(0))->GetString());
70  }
71  delete levelArray;
72 
73  // Get the pT cut by parsing the name of the HLT path.
74  cutMinPt_ = 3;
75  TPRegexp ptRegexp("Mu([0-9]*)");
76  TObjArray* objArray = ptRegexp.MatchS(hltPath_);
77  if (objArray->GetEntriesFast() >= 2) {
78  auto* ptCutString = (TObjString*)objArray->At(1);
79  cutMinPt_ = atoi(ptCutString->GetString());
80  cutMinPt_ = ceil(cutMinPt_ * plotCuts_["minPtFactor"]);
81  }
82  delete objArray;
83 }
84 
85 void HLTMuonMatchAndPlot::beginRun(DQMStore::IBooker& iBooker, const edm::Run& iRun, const edm::EventSetup& iSetup) {
86  TPRegexp suffixPtCut("Mu[0-9]+$");
87 
88  string baseDir = destination_;
89  if (baseDir[baseDir.size() - 1] != '/')
90  baseDir += '/';
91  string pathSansSuffix = hltPath_;
92  if (hltPath_.rfind("_v") < hltPath_.length())
93  pathSansSuffix = hltPath_.substr(0, hltPath_.rfind("_v"));
94 
95  if (isLastFilter_)
96  iBooker.setCurrentFolder(baseDir + pathSansSuffix);
97  else
98  iBooker.setCurrentFolder(baseDir + pathSansSuffix + "/" + moduleLabel_);
99 
100  // Form is book1D(name, binningType, title) where 'binningType' is used
101  // to fetch the bin settings from binParams_.
102 
103  for (const auto& suffix : EFFICIENCY_SUFFIXES) {
104  if (isLastFilter_)
105  iBooker.setCurrentFolder(baseDir + pathSansSuffix);
106  else
107  iBooker.setCurrentFolder(baseDir + pathSansSuffix + "/" + moduleLabel_);
108 
109  book1D(iBooker, "efficiencyEta_" + suffix, "eta", ";#eta;");
110  book1D(iBooker, "efficiencyPhi_" + suffix, "phi", ";#phi;");
111  book1D(iBooker, "efficiencyTurnOn_" + suffix, "pt", ";p_{T};");
112 
113  if (isLastFilter_)
114  iBooker.setCurrentFolder(baseDir + pathSansSuffix);
115  else
116  iBooker.setCurrentFolder(baseDir + pathSansSuffix + "/" + moduleLabel_);
117 
118  if (!isLastFilter_)
119  continue; //this will be plotted only for the last filter
120 
121  book1D(iBooker, "efficiencyCharge_" + suffix, "charge", ";charge;");
122  }
123 }
124 
125 void HLTMuonMatchAndPlot::endRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {}
126 
132  const edm::TriggerNames& trigNames) {
133  /*
134  if(gen != 0) {
135  for(g_part = gen->begin(); g_part != gen->end(); g_part++){
136  if( abs(g_part->pdgId()) == 13) {
137  if(!( g_part->status() ==1 || (g_part->status() ==2 && abs(g_part->pdgId())==5))) continue;
138  bool GenMomExists (true);
139  bool GenGrMomExists(true);
140  if( g_part->pt() < 10.0 ) continue;
141  if( fabs(g_part->eta()) > 2.4 ) continue;
142  int gen_id= g_part->pdgId();
143  const GenParticle* gen_lept = &(*g_part);
144  // get mother of gen_lept
145  const GenParticle* gen_mom = static_cast<const GenParticle*> (gen_lept->mother());
146  if(gen_mom==NULL) GenMomExists=false;
147  int m_id=-999;
148  if(GenMomExists) m_id = gen_mom->pdgId();
149  if(m_id != gen_id || !GenMomExists);
150  else{
151  int id= m_id;
152  while(id == gen_id && GenMomExists){
153  gen_mom = static_cast<const GenParticle*> (gen_mom->mother());
154  if(gen_mom==NULL){
155  GenMomExists=false;
156  }
157  if(GenMomExists) id=gen_mom->pdgId();
158  }
159  }
160  if(GenMomExists) m_id = gen_mom->pdgId();
161  gen_leptsp.push_back(gen_lept);
162  gen_momsp.push_back(gen_mom);
163  }
164  }
165  }
166  std::vector<GenParticle> gen_lepts;
167  for(size_t i = 0; i < gen_leptsp.size(); i++) {
168  gen_lepts.push_back(*gen_leptsp[i]);
169  }
170  */
171 
172  // Select objects based on the configuration.
173  MuonCollection targetMuons =
175  MuonCollection probeMuons =
177  TriggerObjectCollection allTriggerObjects = triggerSummary->getObjects();
180  // Fill plots for HLT muons.
181 
182  // Find the best trigger object matches for the targetMuons.
183  vector<size_t> matches = matchByDeltaR(targetMuons, hltMuons, plotCuts_[triggerLevel_ + "DeltaR"]);
184 
185  // Fill plots for matched muons.
186  for (size_t i = 0; i < targetMuons.size(); i++) {
187  Muon& muon = targetMuons[i];
188 
189  // Fill numerators and denominators for efficiency plots.
190  for (const auto& suffix : EFFICIENCY_SUFFIXES) {
191  // If no match was found, then the numerator plots don't get filled.
192  if (suffix == "numer" && matches[i] >= targetMuons.size())
193  continue;
194 
195  if (muon.pt() > cutMinPt_) {
196  hists_["efficiencyEta_" + suffix]->Fill(muon.eta());
197  }
198 
199  if (fabs(muon.eta()) < plotCuts_["maxEta"]) {
200  hists_["efficiencyTurnOn_" + suffix]->Fill(muon.pt());
201  }
202 
203  if (muon.pt() > cutMinPt_ && fabs(muon.eta()) < plotCuts_["maxEta"]) {
204  const Track* track = nullptr;
205  if (muon.isTrackerMuon())
206  track = &*muon.innerTrack();
207  else if (muon.isStandAloneMuon())
208  track = &*muon.outerTrack();
209  if (track) {
210  hists_["efficiencyPhi_" + suffix]->Fill(muon.phi());
211 
212  if (isLastFilter_) {
213  hists_["efficiencyCharge_" + suffix]->Fill(muon.charge());
214  }
215  }
216  }
217  } // finish loop numerator / denominator...
218 
219  if (!isLastFilter_)
220  continue;
221  // Fill plots for tag and probe
222  // Muon cannot be a tag because doesn't match an hlt muon
223  if (matches[i] >= targetMuons.size())
224  continue;
225  } // End loop over targetMuons.
226 
227  // fill eff histograms for reference trigger method
228  // Denominator: events passing reference trigger and two target muons
229  // Numerator: events in the denominator with two target muons
230  // matched to hlt muons
231  if (!isLastFilter_)
232  return;
233  unsigned int numTriggers = trigNames.size();
234  bool passTrigger = false;
235  if (requiredTriggers_.empty())
236  passTrigger = true;
237  for (auto const& requiredTrigger : requiredTriggers_) {
238  for (unsigned int hltIndex = 0; hltIndex < numTriggers; ++hltIndex) {
239  passTrigger = (trigNames.triggerName(hltIndex).find(requiredTrigger) != std::string::npos &&
240  triggerResults->wasrun(hltIndex) && triggerResults->accept(hltIndex));
241  if (passTrigger)
242  break;
243  }
244  }
245 
246  int nMatched = 0;
247  for (unsigned long matche : matches) {
248  if (matche < targetMuons.size())
249  nMatched++;
250  }
251 
252  string nonSameSignPath = hltPath_;
253  bool ssPath = false;
254  if (nonSameSignPath.rfind("_SameSign") < nonSameSignPath.length()) {
255  ssPath = true;
256  nonSameSignPath = boost::replace_all_copy<string>(nonSameSignPath, "_SameSign", "");
257  nonSameSignPath = nonSameSignPath.substr(0, nonSameSignPath.rfind("_v") + 2);
258  }
259  bool passTriggerSS = false;
260  if (ssPath) {
261  for (unsigned int hltIndex = 0; hltIndex < numTriggers; ++hltIndex) {
262  passTriggerSS =
263  passTriggerSS || (trigNames.triggerName(hltIndex).substr(0, nonSameSignPath.size()) == nonSameSignPath &&
264  triggerResults->wasrun(hltIndex) && triggerResults->accept(hltIndex));
265  }
266  }
267 
268  string nonDZPath = hltPath_;
269  bool dzPath = false;
270  if (nonDZPath.rfind("_DZ") < nonDZPath.length()) {
271  dzPath = true;
272  nonDZPath = boost::replace_all_copy<string>(nonDZPath, "_DZ", "");
273  nonDZPath = nonDZPath.substr(0, nonDZPath.rfind("_v") + 2);
274  }
275  bool passTriggerDZ = false;
276  if (dzPath) {
277  for (unsigned int hltIndex = 0; hltIndex < numTriggers; ++hltIndex) {
278  passTriggerDZ = passTriggerDZ || (trigNames.triggerName(hltIndex).find(nonDZPath) != std::string::npos &&
279  triggerResults->wasrun(hltIndex) && triggerResults->accept(hltIndex));
280  }
281  }
282 
283 } // End analyze() method.
284 
285 // Method to fill binning parameters from a vector of doubles.
286 void HLTMuonMatchAndPlot::fillEdges(size_t& nBins, float*& edges, const vector<double>& binning) {
287  if (binning.size() < 3) {
288  LogWarning("HLTMuonVal") << "Invalid binning parameters!";
289  return;
290  }
291 
292  // Fixed-width binning.
293  if (binning.size() == 3) {
294  nBins = binning[0];
295  edges = new float[nBins + 1];
296  const double min = binning[1];
297  const double binwidth = (binning[2] - binning[1]) / nBins;
298  for (size_t i = 0; i <= nBins; i++)
299  edges[i] = min + (binwidth * i);
300  }
301 
302  // Variable-width binning.
303  else {
304  nBins = binning.size() - 1;
305  edges = new float[nBins + 1];
306  for (size_t i = 0; i <= nBins; i++)
307  edges[i] = binning[i];
308  }
309 }
310 
311 // This is an unorthodox method of getting parameters, but cleaner in my mind
312 // It looks for parameter 'target' in the pset, and assumes that all entries
313 // have the same class (T), filling the values into a std::map.
314 template <class T>
315 void HLTMuonMatchAndPlot::fillMapFromPSet(map<string, T>& m, const ParameterSet& pset, const string& target) {
316  // Get the ParameterSet with name 'target' from 'pset'
317  ParameterSet targetPset;
318  if (pset.existsAs<ParameterSet>(target, true)) // target is tracked
319  targetPset = pset.getParameterSet(target);
320  else if (pset.existsAs<ParameterSet>(target, false)) // target is untracked
321  targetPset = pset.getUntrackedParameterSet(target);
322 
323  // Get the parameter names from targetPset
324  vector<string> names = targetPset.getParameterNames();
325  vector<string>::const_iterator iter;
326 
327  for (iter = names.begin(); iter != names.end(); ++iter) {
328  if (targetPset.existsAs<T>(*iter, true)) // target is tracked
329  m[*iter] = targetPset.getParameter<T>(*iter);
330  else if (targetPset.existsAs<T>(*iter, false)) // target is untracked
331  m[*iter] = targetPset.getUntrackedParameter<T>(*iter);
332  }
333 }
334 
335 // A generic method to find the best deltaR matches from 2 collections.
336 template <class T1, class T2>
337 vector<size_t> HLTMuonMatchAndPlot::matchByDeltaR(const vector<T1>& collection1,
338  const vector<T2>& collection2,
339  const double maxDeltaR) {
340  const size_t n1 = collection1.size();
341  const size_t n2 = collection2.size();
342 
343  vector<size_t> result(n1, -1);
344  vector<vector<double> > deltaRMatrix(n1, vector<double>(n2, NOMATCH));
345 
346  for (size_t i = 0; i < n1; i++)
347  for (size_t j = 0; j < n2; j++) {
348  deltaRMatrix[i][j] = deltaR(collection1[i], collection2[j]);
349  }
350 
351  // Run through the matrix n1 times to make sure we've found all matches.
352  for (size_t k = 0; k < n1; k++) {
353  size_t i_min = -1;
354  size_t j_min = -1;
355  double minDeltaR = maxDeltaR;
356  // find the smallest deltaR
357  for (size_t i = 0; i < n1; i++)
358  for (size_t j = 0; j < n2; j++)
359  if (deltaRMatrix[i][j] < minDeltaR) {
360  i_min = i;
361  j_min = j;
362  minDeltaR = deltaRMatrix[i][j];
363  }
364  // If a match has been made, save it and make those candidates unavailable.
365  if (minDeltaR < maxDeltaR) {
366  result[i_min] = j_min;
367  deltaRMatrix[i_min] = vector<double>(n2, NOMATCH);
368  for (size_t i = 0; i < n1; i++)
369  deltaRMatrix[i][j_min] = NOMATCH;
370  }
371  }
372 
373  return result;
374 }
375 
377  const BeamSpot& beamSpot,
378  bool hasRecoCuts,
379  const StringCutObjectSelector<reco::Muon>& selector,
380  double d0Cut,
381  double z0Cut) {
382  // If there is no selector (recoCuts does not exists), return an empty collection.
383  if (!hasRecoCuts)
384  return MuonCollection();
385 
386  MuonCollection reducedMuons;
387  for (auto const& mu : allMuons) {
388  const Track* track = nullptr;
389  if (mu.isTrackerMuon())
390  track = &*mu.innerTrack();
391  else if (mu.isStandAloneMuon())
392  track = &*mu.outerTrack();
393  if (track && selector(mu) && fabs(track->dxy(beamSpot.position())) < d0Cut &&
394  fabs(track->dz(beamSpot.position())) < z0Cut)
395  reducedMuons.push_back(mu);
396  }
397 
398  return reducedMuons;
399 }
400 
404  bool hasTriggerCuts,
405  const StringCutObjectSelector<TriggerObject>& triggerSelector) {
406  if (!hasTriggerCuts)
407  return TriggerObjectCollection();
408 
409  InputTag filterTag(moduleLabel_, "", hltProcessName_);
410  size_t filterIndex = triggerSummary.filterIndex(filterTag);
411 
412  TriggerObjectCollection selectedObjects;
413 
414  if (filterIndex < triggerSummary.sizeFilters()) {
415  const Keys& keys = triggerSummary.filterKeys(filterIndex);
416  for (unsigned short key : keys) {
417  TriggerObject foundObject = triggerObjects[key];
418  if (triggerSelector(foundObject))
419  selectedObjects.push_back(foundObject);
420  }
421  }
422 
423  return selectedObjects;
424 }
425 
426 void HLTMuonMatchAndPlot::book1D(DQMStore::IBooker& iBooker, string name, const string& binningType, string title) {
427  /* Properly delete the array of floats that has been allocated on
428  * the heap by fillEdges. Avoid multiple copies and internal ROOT
429  * clones by simply creating the histograms directly in the DQMStore
430  * using the appropriate book1D method to handle the variable bins
431  * case. */
432 
433  size_t nBins;
434  float* edges = nullptr;
435  fillEdges(nBins, edges, binParams_[binningType]);
436  hists_[name] = iBooker.book1D(name, title, nBins, edges);
437  if (hists_[name])
438  if (hists_[name]->getTH1F()->GetSumw2N())
439  hists_[name]->enableSumw2();
440 
441  if (edges)
442  delete[] edges;
443 }
444 
446  const string& name,
447  const string& binningTypeX,
448  const string& binningTypeY,
449  const string& title) {
450  /* Properly delete the arrays of floats that have been allocated on
451  * the heap by fillEdges. Avoid multiple copies and internal ROOT
452  * clones by simply creating the histograms directly in the DQMStore
453  * using the appropriate book2D method to handle the variable bins
454  * case. */
455 
456  size_t nBinsX;
457  float* edgesX = nullptr;
458  fillEdges(nBinsX, edgesX, binParams_[binningTypeX]);
459 
460  size_t nBinsY;
461  float* edgesY = nullptr;
462  fillEdges(nBinsY, edgesY, binParams_[binningTypeY]);
463 
464  hists_[name] = iBooker.book2D(name.c_str(), title.c_str(), nBinsX, edgesX, nBinsY, edgesY);
465  if (hists_[name])
466  if (hists_[name]->getTH2F()->GetSumw2N())
467  hists_[name]->enableSumw2();
468 
469  if (edgesX)
470  delete[] edgesX;
471  if (edgesY)
472  delete[] edgesY;
473 }
constexpr int32_t ceil(float num)
reco::MuonCollection selectedMuons(const reco::MuonCollection &, const reco::BeamSpot &, bool, const StringCutObjectSelector< reco::Muon > &, double, double)
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
StringCutObjectSelector< reco::Muon > probeMuonSelector_
The single EDProduct to be saved for each event (AOD case)
Definition: TriggerEvent.h:25
const std::string EFFICIENCY_SUFFIXES[2]
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:32
vector< string > vstring
Definition: ExoticaDQM.cc:8
std::map< std::string, std::vector< double > > binParams_
std::map< std::string, MonitorElement * > hists_
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:171
const std::string names[nVars_]
std::vector< Muon > MuonCollection
collection of Muon objects
Definition: MuonFwd.h:9
HLTMuonMatchAndPlot(const edm::ParameterSet &, std::string, std::string, bool)
Constructor.
std::vector< std::string > requiredTriggers_
T getUntrackedParameter(std::string const &, T const &) const
const double NOMATCH
void book2D(DQMStore::IBooker &, const std::string &, const std::string &, const std::string &, const std::string &)
std::vector< size_t > matchByDeltaR(const std::vector< T1 > &, const std::vector< T2 > &, const double maxDeltaR=NOMATCH)
Definition: Muon.py:1
void fillMapFromPSet(std::map< std::string, T > &, const edm::ParameterSet &, const std::string &)
trigger::TriggerObjectCollection selectedTriggerObjects(const trigger::TriggerObjectCollection &, const trigger::TriggerEvent &, bool hasTriggerCuts, const StringCutObjectSelector< trigger::TriggerObject > &triggerSelector)
static std::string const triggerResults
Definition: EdmProvDump.cc:44
void book1D(DQMStore::IBooker &, std::string, const std::string &, std::string)
std::vector< TriggerObject > TriggerObjectCollection
collection of trigger physics objects (e.g., all isolated muons)
Definition: TriggerObject.h:75
static const char *const trigNames[]
Definition: EcalDumpRaw.cc:57
void analyze(edm::Handle< reco::MuonCollection > &, edm::Handle< reco::BeamSpot > &, edm::Handle< reco::VertexCollection > &, edm::Handle< trigger::TriggerEvent > &, edm::Handle< edm::TriggerResults > &, const edm::TriggerNames &)
StringCutObjectSelector< reco::Muon > targetMuonSelector_
std::vector< size_type > Keys
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:212
ParameterSet const & getParameterSet(ParameterSetID const &id)
fixed size matrix
HLT enums.
StringCutObjectSelector< trigger::TriggerObject > triggerSelector_
void endRun(const edm::Run &, const edm::EventSetup &)
Log< level::Warning, false > LogWarning
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
long double T
std::vector< std::string > getParameterNames() const
std::map< std::string, double > plotCuts_
void fillEdges(size_t &nBins, float *&edges, const std::vector< double > &binning)
def move(src, dest)
Definition: eostools.py:511
Definition: Run.h:45
void beginRun(DQMStore::IBooker &, const edm::Run &, const edm::EventSetup &)