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