CMS 3D CMS Logo

CandidateSimMuonMatcher.cc
Go to the documentation of this file.
1 /*
2  * CandidateSimMuonMatcher.cc
3  *
4  * Created on: Dec 14, 2020
5  * Author: kbunkow
6  */
7 
10 
14 
20 
22 
23 #include "boost/dynamic_bitset.hpp"
24 
25 #include "TFile.h"
26 #include "TH1D.h"
27 
28 double hwGmtPhiToGlobalPhi(int phi) {
29  double phiGmtUnit = 2. * M_PI / 576.;
30  return phi * phiGmtUnit;
31 }
32 
33 double foldPhi(double phi) {
34  if (phi > M_PI)
35  return (phi - 2 * M_PI);
36  else if (phi < -M_PI)
37  return (phi + 2 * M_PI);
38 
39  return phi;
40 }
41 
43  const edm::ParameterSet& edmCfg,
44  const OMTFConfiguration* omtfConfig,
47  : omtfConfig(omtfConfig),
48  edmCfg(edmCfg),
49  magneticFieldEsToken(magneticFieldEsToken),
50  propagatorEsToken(propagatorEsToken) {
51  std::string muonMatcherFileName = edmCfg.getParameter<edm::FileInPath>("muonMatcherFile").fullPath();
52  TFile inFile(muonMatcherFileName.c_str());
53  edm::LogImportant("l1tOmtfEventPrint") << " CandidateSimMuonMatcher: using muonMatcherFileName "
54  << muonMatcherFileName << std::endl;
55 
56  if (edmCfg.exists("candidateSimMuonMatcherType")) {
57  if (edmCfg.getParameter<std::string>("candidateSimMuonMatcherType") == "propagation")
58  usePropagation = true;
59  else if (edmCfg.getParameter<std::string>("candidateSimMuonMatcherType") == "matchSimple")
60  usePropagation = false;
61 
62  edm::LogImportant("l1tOmtfEventPrint")
63  << " CandidateSimMuonMatcher: candidateSimMuonMatcherType "
64  << edmCfg.getParameter<std::string>("candidateSimMuonMatcherType") << std::endl;
65  }
66 
67  edm::LogImportant("l1tOmtfEventPrint") << " CandidateSimMuonMatcher: usePropagation " << usePropagation << std::endl;
68 
69  deltaPhiPropCandMean = (TH1D*)inFile.Get("deltaPhiPropCandMean");
70  deltaPhiPropCandStdDev = (TH1D*)inFile.Get("deltaPhiPropCandStdDev");
71 }
72 
74 
76  //TODO use edm::ESWatcher<MagneticField> magneticFieldRecordWatcher;
79 }
80 
82 
84  l1t::tftype mtfType,
85  const std::shared_ptr<OMTFinput>& input,
86  const AlgoMuons& algoCandidates,
87  const AlgoMuons& gbCandidates,
88  const std::vector<l1t::RegionalMuonCand>& candMuons) {
89  //debug
90  unsigned int procIndx = omtfConfig->getProcIndx(iProcessor, mtfType);
91  for (auto& gbCandidate : gbCandidates) {
92  if (gbCandidate->getPtConstr() > 0) {
93  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::observeProcesorEmulation procIndx" << procIndx << " "
94  << *gbCandidate << std::endl;
95  this->gbCandidates.emplace_back(gbCandidate);
96  }
97  }
98 }
99 
101  if (std::abs(simTrack.type()) == 13 ||
102  std::abs(simTrack.type()) == 1000015) { // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
103  //only muons
104  } else
105  return false;
106 
107  //in the overlap, the propagation of muons with pt less then ~3.2 fails - the actual threshold depends slightly on eta,
108  if (simTrack.momentum().pt() < 2.5)
109  return false;
110 
111  LogTrace("l1tOmtfEventPrint") << "simTrackIsMuonInOmtf: simTrack type " << std::setw(3) << simTrack.type() << " pt "
112  << std::setw(9) << simTrack.momentum().pt() << " eta " << std::setw(9)
113  << simTrack.momentum().eta() << " phi " << std::setw(9) << simTrack.momentum().phi()
114  << std::endl;
115 
116  //some margin for matching must be used on top of actual OMTF region,
117  //i.e. (0.82-1.24)=>(0.72-1.3),
118  //otherwise many candidates are marked as ghosts
119  if ((std::abs(simTrack.momentum().eta()) >= 0.72) && (std::abs(simTrack.momentum().eta()) <= 1.3)) {
120  LogTrace("l1tOmtfEventPrint") << "simTrackIsMuonInOmtf: is in OMTF";
121  } else {
122  LogTrace("l1tOmtfEventPrint") << "simTrackIsMuonInOmtf: not in OMTF";
123  return false;
124  }
125 
126  return true;
127 }
128 
130  if (simTrack.eventId().bunchCrossing() != 0)
131  return false;
132 
134 }
135 
137  if (std::abs(simTrack.type()) == 13 ||
138  std::abs(simTrack.type()) == 1000015) { // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
139  //only muons
140  if (simTrack.eventId().bunchCrossing() == 0)
141  return true;
142  }
143  return false;
144 }
145 
146 bool trackingParticleIsMuonInBx0(const TrackingParticle& trackingParticle) {
147  if (std::abs(trackingParticle.pdgId()) == 13 ||
148  std::abs(trackingParticle.pdgId()) ==
149  1000015) { // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
150  //only muons
151  if (trackingParticle.eventId().bunchCrossing() == 0)
152  return true;
153  }
154  return false;
155 }
156 
157 bool trackingParticleIsMuonInOmtfBx0(const TrackingParticle& trackingParticle) {
158  if (trackingParticle.eventId().bunchCrossing() != 0)
159  return false;
160 
161  if (std::abs(trackingParticle.pdgId()) == 13 || std::abs(trackingParticle.pdgId()) == 1000015) {
162  // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
163  //only muons
164  } else
165  return false;
166 
167  //in the overlap, the propagation of muons with pt less then ~3.2 fails, the actual threshold depends slightly on eta,
168  if (trackingParticle.pt() < 2.5)
169  return false;
170 
171  if (trackingParticle.parentVertex().isNonnull())
172  LogTrace("l1tOmtfEventPrint") << "trackingParticleIsMuonInOmtfBx0, pdgId " << std::setw(3)
173  << trackingParticle.pdgId() << " pt " << std::setw(9) << trackingParticle.pt()
174  << " eta " << std::setw(9) << trackingParticle.momentum().eta() << " phi "
175  << std::setw(9) << trackingParticle.momentum().phi() << " event "
176  << trackingParticle.eventId().event() << " trackId "
177  << trackingParticle.g4Tracks().at(0).trackId() << " parentVertex Rho "
178  << trackingParticle.parentVertex()->position().Rho() << " eta "
179  << trackingParticle.parentVertex()->position().eta() << " phi "
180  << trackingParticle.parentVertex()->position().phi() << std::endl;
181  else
182  LogTrace("l1tOmtfEventPrint") << "trackingParticleIsMuonInOmtfBx0, pdgId " << std::setw(3)
183  << trackingParticle.pdgId() << " pt " << std::setw(9) << trackingParticle.pt()
184  << " eta " << std::setw(9) << trackingParticle.momentum().eta() << " phi "
185  << std::setw(9) << trackingParticle.momentum().phi() << " trackId "
186  << trackingParticle.g4Tracks().at(0).trackId();
187 
188  //some margin for matching must be used on top of actual OMTF region,
189  //i.e. (0.82-1.24)=>(0.72-1.3),
190  //otherwise many candidates are marked as ghosts
191  if ((std::abs(trackingParticle.momentum().eta()) >= 0.72) && (std::abs(trackingParticle.momentum().eta()) <= 1.3)) {
192  } else
193  return false;
194 
195  return true;
196 }
197 
199  if (trackingParticle.eventId().event() != 0)
200  return false;
201 
202  return trackingParticleIsMuonInOmtfBx0(trackingParticle);
203 }
204 
206  std::unique_ptr<l1t::RegionalMuonCandBxCollection>& finalCandidates) {
207  LogTrace("l1tOmtfEventPrint") << "\nCandidateSimMuonMatcher::observeEventEnd" << std::endl;
208  AlgoMuons ghostBustedProcMuons;
209  std::vector<const l1t::RegionalMuonCand*> ghostBustedRegionalCands =
210  CandidateSimMuonMatcher::ghostBust(finalCandidates.get(), gbCandidates, ghostBustedProcMuons);
211 
212  matchingResults.clear();
213  if (edmCfg.exists("simTracksTag")) {
215  event.getByLabel(edmCfg.getParameter<edm::InputTag>("simTracksTag"), simTraksHandle);
216 
218  event.getByLabel(edmCfg.getParameter<edm::InputTag>("simVertexesTag"), simVertices);
219 
220  LogTrace("l1tOmtfEventPrint") << "simTraksHandle size " << simTraksHandle.product()->size() << std::endl;
221  LogTrace("l1tOmtfEventPrint") << "simVertices size " << simVertices.product()->size() << std::endl;
222 
223  if (usePropagation) {
224  //TODO use other simTrackFilter if needed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
225  //we dont want to check the eta of the generated muon, as it is on the vertex,
226  //instead inside match, we check the eta of the propagated track to the second muons station
227  std::function<bool(const SimTrack&)> const& simTrackFilter = simTrackIsMuonInBx0; //simTrackIsMuonInOmtfBx0;
228 
229  matchingResults = match(ghostBustedRegionalCands,
230  ghostBustedProcMuons,
231  simTraksHandle.product(),
232  simVertices.product(),
233  simTrackFilter);
234  } else {
235  std::function<bool(const SimTrack&)> const& simTrackFilter = simTrackIsMuonInOmtfBx0;
236  //simTrackIsMuonInOmtfBx0 provides appropriate eta cut
237 
238  matchingResults = matchSimple(ghostBustedRegionalCands,
239  ghostBustedProcMuons,
240  simTraksHandle.product(),
241  simVertices.product(),
242  simTrackFilter);
243  }
244 
245  } else if (edmCfg.exists("trackingParticleTag")) {
246  edm::Handle<TrackingParticleCollection> trackingParticleHandle;
247  event.getByLabel(edmCfg.getParameter<edm::InputTag>("trackingParticleTag"), trackingParticleHandle);
248  LogTrace("l1tOmtfEventPrint") << "\nCandidateSimMuonMatcher::observeEventEnd trackingParticleHandle size "
249  << trackingParticleHandle.product()->size() << std::endl;
250 
251  //TODO use other trackParticleFilter if needed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
252  std::function<bool(const TrackingParticle&)> trackParticleFilter =
253  trackingParticleIsMuonInBx0; //trackingParticleIsMuonInOmtfBx0;
255  match(ghostBustedRegionalCands, ghostBustedProcMuons, trackingParticleHandle.product(), trackParticleFilter);
256  }
257 }
258 
260 
261 std::vector<const l1t::RegionalMuonCand*> CandidateSimMuonMatcher::ghostBust(
262  const l1t::RegionalMuonCandBxCollection* mtfCands, const AlgoMuons& gbCandidates, AlgoMuons& ghostBustedProcMuons) {
263  if (gbCandidates.size() != mtfCands->size(0)) {
264  edm::LogError("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::ghostBust(): gbCandidates.size() "
265  << gbCandidates.size() << " != mtfCands.size() " << mtfCands->size();
266  }
267 
268  boost::dynamic_bitset<> isKilled(mtfCands->size(0), false);
269 
270  for (unsigned int i1 = 0; i1 < mtfCands->size(0); ++i1) {
271  if (mtfCands->at(0, i1).hwPt() == 0)
272  continue;
273  LogTrace("l1tOmtfEventPrint") << "\nCandidateSimMuonMatcher::ghostBust regionalCand pt " << std::setw(3)
274  << mtfCands->at(0, i1).hwPt() << " qual " << std::setw(2)
275  << mtfCands->at(0, i1).hwQual() << " proc " << std::setw(2)
276  << mtfCands->at(0, i1).processor();
277  for (unsigned int i2 = i1 + 1; i2 < mtfCands->size(0); ++i2) {
278  auto& mtfCand1 = mtfCands->at(0, i1);
279  auto& mtfCand2 = mtfCands->at(0, i2);
280  if (mtfCand2.hwPt() == 0)
281  continue;
282 
283  if (std::abs(mtfCand1.hwEta() - mtfCand2.hwEta()) < (0.3 / 0.010875)) {
284  int gloablHwPhi1 = omtfConfig->calcGlobalPhi(mtfCand1.hwPhi(), mtfCand1.processor());
285  int gloablHwPhi2 = omtfConfig->calcGlobalPhi(mtfCand2.hwPhi(), mtfCand2.processor());
286 
287  //folding phi
288  int deltaPhi = std::abs(gloablHwPhi1 - gloablHwPhi2);
289  if (deltaPhi > 576 / 2)
290  deltaPhi = std::abs(deltaPhi - 576);
291 
292  //one can use the phi in radians like that:
293  //double globalPhi1 = hwGmtPhiToGlobalPhi(omtfConfig->calcGlobalPhi( mtfCand1.hwPhi(), mtfCand1.processor() ) );
294  //double globalPhi2 = hwGmtPhiToGlobalPhi(omtfConfig->calcGlobalPhi( mtfCand2.hwPhi(), mtfCand2.processor() ) );
295 
296  //0.0872664626 = 5 deg, i.e. the same window as in the OMTF ghost buster
297  if (deltaPhi < 8) {
298  //if (mtfCand1.hwQual() > mtfCand2.hwQual()) //TODO this is used in the uGMT
299  //but this should be better - but probably the difference is not big
300  if (gbCandidates[i1]->getFiredLayerCnt() > gbCandidates[i2]->getFiredLayerCnt()) {
301  isKilled[i2] = true;
302  } else
303  isKilled[i1] = true;
304  }
305  }
306  }
307  }
308 
309  std::vector<const l1t::RegionalMuonCand*> resultCands;
310 
311  for (unsigned int i1 = 0; i1 < mtfCands->size(0); ++i1) {
312  //dropping candidates with quality 0 !!!!!!!!!!!!!!!!!!!! fixme if not needed
313  if (!isKilled[i1] && mtfCands->at(0, i1).hwPt()) {
314  resultCands.push_back(&(mtfCands->at(0, i1)));
315  ghostBustedProcMuons.push_back(gbCandidates.at(i1));
316  }
317 
318  if (mtfCands->at(0, i1).hwPt()) {
319  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::ghostBust\n regionalCand pt " << std::setw(3)
320  << mtfCands->at(0, i1).hwPt() << " qual " << std::setw(2)
321  << mtfCands->at(0, i1).hwQual() << " proc " << std::setw(2)
322  << mtfCands->at(0, i1).processor() << " eta " << std::setw(4)
323  << mtfCands->at(0, i1).hwEta() << " gloablEta " << std::setw(8)
324  << mtfCands->at(0, i1).hwEta() * 0.010875 << " hwPhi " << std::setw(3)
325  << mtfCands->at(0, i1).hwPhi() << " globalPhi " << std::setw(8)
326  << hwGmtPhiToGlobalPhi(omtfConfig->calcGlobalPhi(mtfCands->at(0, i1).hwPhi(),
327  mtfCands->at(0, i1).processor()))
328  << " fireadLayers " << std::bitset<18>(mtfCands->at(0, i1).trackAddress().at(0))
329  << " gb isKilled " << isKilled.test(i1) << std::endl;
330 
331  LogTrace("l1tOmtfEventPrint") << *(gbCandidates.at(i1)) << std::endl;
332  }
333  }
334 
335  if (resultCands.size() >= 3)
336  LogTrace("l1tOmtfEventPrint") << " ghost !!!!!! " << std::endl;
337  LogTrace("l1tOmtfEventPrint") << std::endl;
338 
339  return resultCands;
340 }
341 
343  // propagate to MB1, which defines the OMTF region (W+-2 MB1 is connected only to the OMTF)
344  // 415 cm is R of RB1in, 660.5cm is |z| of the edge of MB2 (B field on)
346  new BoundCylinder(GlobalPoint(0., 0., 0.), TkRotation<float>(), SimpleCylinderBounds(415., 415., -660.5, 660.5)));
347  TrajectoryStateOnSurface trackAtRPC = propagator->propagate(ftsStart, *rpc);
348 
349  return trackAtRPC;
350 }
351 
353  int charge = simTrackPtr.type() > 0 ? -1 : 1; //works for muons
354 
355  GlobalVector p3GV(simTrackPtr.momentum().x(), simTrackPtr.momentum().y(), simTrackPtr.momentum().z());
356  GlobalPoint r3GP(simVertex.position().x(), simVertex.position().y(), simVertex.position().z());
357 
358  GlobalTrajectoryParameters tPars(r3GP, p3GV, charge, &*magField);
359 
360  return FreeTrajectoryState(tPars);
361 }
362 
364  int charge = trackingParticle.pdgId() > 0 ? -1 : 1; //works for muons
365 
366  GlobalVector p3GV(trackingParticle.momentum().x(), trackingParticle.momentum().y(), trackingParticle.momentum().z());
367  GlobalPoint r3GP(trackingParticle.vx(), trackingParticle.vy(), trackingParticle.vz());
368 
369  GlobalTrajectoryParameters tPars(r3GP, p3GV, charge, &*magField);
370 
371  return FreeTrajectoryState(tPars);
372 }
373 
377  int vtxInd = simTrack.vertIndex();
378  if (vtxInd < 0) {
379  edm::LogImportant("l1tOmtfEventPrint") << "Track with no vertex, defaulting to (0,0,0)";
380  } else {
382  if (((int)simVertex.vertexId()) != vtxInd) {
383  edm::LogImportant("l1tOmtfEventPrint") << "simVertex.vertexId() != vtxInd. simVertex.vertexId() "
384  << simVertex.vertexId() << " vtxInd " << vtxInd << " !!!!!!!!!!!!!!!!!";
385  }
386  }
387 
389 
390  TrajectoryStateOnSurface tsof = atStation2(ftsTrack); //propagation
391 
392  return tsof;
393 }
394 
396  FreeTrajectoryState ftsTrack = simTrackToFts(trackingParticle);
397 
398  TrajectoryStateOnSurface tsof = atStation2(ftsTrack); //propagation
399 
400  return tsof;
401 }
402 
403 float normal_pdf(float x, float m, float s) {
404  static const float inv_sqrt_2pi = 0.3989422804014327;
405  float a = (x - m) / s;
406 
407  return inv_sqrt_2pi / s * std::exp(-0.5 * a * a);
408 }
409 
411  const AlgoMuonPtr& procMuon,
412  const SimTrack& simTrack,
413  TrajectoryStateOnSurface& tsof) {
415 
416  double candGloablEta = muonCand->hwEta() * 0.010875;
417  //if (std::abs(simTrack.momentum().eta() - candGloablEta) < 0.3) //has no sense for displaced muons
418  {
419  double candGlobalPhi = omtfConfig->calcGlobalPhi(muonCand->hwPhi(), muonCand->processor());
420  candGlobalPhi = hwGmtPhiToGlobalPhi(candGlobalPhi);
421 
422  if (candGlobalPhi > M_PI)
423  candGlobalPhi = candGlobalPhi - (2. * M_PI);
424 
425  result.deltaPhi = foldPhi(tsof.globalPosition().phi() - candGlobalPhi);
426  result.deltaEta = tsof.globalPosition().eta() - candGloablEta;
427 
428  result.propagatedPhi = tsof.globalPosition().phi();
429  result.propagatedEta = tsof.globalPosition().eta();
430 
431  double mean = 0;
432  double sigma = 1;
433  //if(!fillMean)
434  {
435  auto ptBin = deltaPhiPropCandMean->FindBin(simTrack.momentum().pt());
436  mean = deltaPhiPropCandMean->GetBinContent(ptBin);
437  sigma = deltaPhiPropCandStdDev->GetBinContent(ptBin);
438  }
439  result.matchingLikelihood = normal_pdf(result.deltaPhi, mean, sigma); //TODO temporary solution
440 
441  result.muonCand = muonCand;
442  result.procMuon = procMuon;
443 
444  double treshold = 6. * sigma;
445  if (simTrack.momentum().pt() > 20)
446  treshold = 7. * sigma;
447  if (simTrack.momentum().pt() > 100)
448  treshold = 20. * sigma;
449 
450  //for displaced muons in H2ll
451  treshold = 0.15; //pt > 30
452  if (simTrack.momentum().pt() <
453  10) //TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! tune the threshold!!!!!!
454  treshold = 0.3;
455  else if (simTrack.momentum().pt() <
456  30) //TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! tune the threshold!!!!!!
457  treshold = 0.22;
458 
459  if (std::abs(result.deltaPhi - mean) < treshold && std::abs(result.deltaEta) < 0.3)
461 
462  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match: simTrack type " << simTrack.type() << " pt "
463  << std::setw(8) << simTrack.momentum().pt() << " eta " << std::setw(8)
464  << simTrack.momentum().eta() << " phi " << std::setw(8) << simTrack.momentum().phi()
465  << " propagation eta " << std::setw(8) << tsof.globalPosition().eta() << " phi "
466  << tsof.globalPosition().phi() << "\n muonCand pt " << std::setw(8)
467  << muonCand->hwPt() << " candGloablEta " << std::setw(8) << candGloablEta
468  << " candGlobalPhi " << std::setw(8) << candGlobalPhi << " hwQual "
469  << muonCand->hwQual() << " deltaEta " << std::setw(8) << result.deltaEta
470  << " deltaPhi " << std::setw(8) << result.deltaPhi << " sigma " << std::setw(8)
471  << sigma << " Likelihood " << std::setw(8) << result.matchingLikelihood << " result "
472  << (short)result.result << std::endl;
473  }
474 
475  return result;
476 }
477 
479  const AlgoMuonPtr& procMuon,
480  const TrackingParticle& trackingParticle,
481  TrajectoryStateOnSurface& tsof) {
482  MatchingResult result(trackingParticle);
483 
484  double candGloablEta = muonCand->hwEta() * 0.010875;
485  //if (std::abs(trackingParticle.momentum().eta() - candGloablEta) < 0.3) //has no sense for displaced muons
486  {
487  double candGlobalPhi = omtfConfig->calcGlobalPhi(muonCand->hwPhi(), muonCand->processor());
488  candGlobalPhi = hwGmtPhiToGlobalPhi(candGlobalPhi);
489 
490  if (candGlobalPhi > M_PI)
491  candGlobalPhi = candGlobalPhi - (2. * M_PI);
492 
493  result.deltaPhi = foldPhi(tsof.globalPosition().phi() - candGlobalPhi);
494  result.deltaEta = tsof.globalPosition().eta() - candGloablEta;
495 
496  result.propagatedPhi = tsof.globalPosition().phi();
497  result.propagatedEta = tsof.globalPosition().eta();
498 
499  double mean = 0;
500  double sigma = 1;
501  //if(!fillMean)
502  {
503  auto ptBin = deltaPhiPropCandMean->FindBin(trackingParticle.pt());
504 
505  mean = deltaPhiPropCandMean->GetBinContent(ptBin);
506  sigma = deltaPhiPropCandStdDev->GetBinContent(ptBin);
507  }
508 
509  result.matchingLikelihood = normal_pdf(result.deltaPhi, mean, sigma); //TODO temporary solution
510 
511  result.muonCand = muonCand;
512  result.procMuon = procMuon;
513 
514  double treshold = 6. * sigma;
515  if (trackingParticle.pt() > 20)
516  treshold = 7. * sigma;
517  if (trackingParticle.pt() > 100)
518  treshold = 20. * sigma;
519 
520  if (std::abs(result.deltaPhi - mean) < treshold && std::abs(result.deltaEta) < 0.3)
522 
523  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match: trackingParticle type "
524  << trackingParticle.pdgId() << " pt " << std::setw(8) << trackingParticle.pt()
525  << " eta " << std::setw(8) << trackingParticle.momentum().eta() << " phi "
526  << std::setw(8) << trackingParticle.momentum().phi() << " propagation eta "
527  << std::setw(8) << tsof.globalPosition().eta() << " phi "
528  << tsof.globalPosition().phi() << " muonCand pt " << std::setw(8) << muonCand->hwPt()
529  << " candGloablEta " << std::setw(8) << candGloablEta << " candGlobalPhi "
530  << std::setw(8) << candGlobalPhi << " hwQual " << muonCand->hwQual() << " deltaEta "
531  << std::setw(8) << result.deltaEta << " deltaPhi " << std::setw(8) << result.deltaPhi
532  << " Likelihood " << std::setw(8) << result.matchingLikelihood << " result "
533  << (short)result.result << std::endl;
534  }
535 
536  return result;
537 }
538 
539 std::vector<MatchingResult> CandidateSimMuonMatcher::cleanMatching(std::vector<MatchingResult> matchingResults,
540  std::vector<const l1t::RegionalMuonCand*>& muonCands,
541  AlgoMuons& ghostBustedProcMuons) {
542  //Cleaning the matching
543  std::sort(
544  matchingResults.begin(), matchingResults.end(), [](const MatchingResult& a, const MatchingResult& b) -> bool {
545  return a.matchingLikelihood > b.matchingLikelihood;
546  });
547 
548  for (unsigned int i1 = 0; i1 < matchingResults.size(); i1++) {
550  for (unsigned int i2 = i1 + 1; i2 < matchingResults.size(); i2++) {
551  if ((matchingResults[i1].trackingParticle &&
552  matchingResults[i1].trackingParticle == matchingResults[i2].trackingParticle) ||
553  (matchingResults[i1].simTrack && matchingResults[i1].simTrack == matchingResults[i2].simTrack) ||
554  (matchingResults[i1].muonCand == matchingResults[i2].muonCand)) {
555  //if matchingResults[i1].muonCand == false, then it is also OK here
557  }
558  }
559  }
560  }
561 
562  std::vector<MatchingResult> cleanedMatchingResults;
563  for (auto& matchingResult : matchingResults) {
564  if (matchingResult.result == MatchingResult::ResultType::matched || matchingResult.muonCand == nullptr)
565  //adding also the simTracks that are not matched at all, before it is assured that they are not duplicates
566  cleanedMatchingResults.push_back(matchingResult);
567  if (matchingResult.result == MatchingResult::ResultType::matched) {
568  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
569  if(fillMean) {
570  double ptGen = matchingResult.genPt;
571  deltaPhiPropCandMean->Fill(ptGen, matchingResult.deltaPhi); //filling overflow is ok here
572  deltaPhiPropCandStdDev->Fill(ptGen, matchingResult.deltaPhi * matchingResult.deltaPhi);
573  }*/
574  }
575  }
576 
577  //adding the muonCand-s that were not matched, i.e. in order to analyze them later
578  unsigned int iCand = 0;
579  for (auto& muonCand : muonCands) {
580  bool isMatched = false;
581  for (auto& matchingResult : cleanedMatchingResults) {
582  if (matchingResult.muonCand == muonCand) {
583  isMatched = true;
584  break;
585  }
586  }
587 
588  if (!isMatched) {
590  result.muonCand = muonCand;
591  result.procMuon = ghostBustedProcMuons.at(iCand);
592  cleanedMatchingResults.push_back(result);
593  }
594  iCand++;
595  }
596 
597  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::cleanMatching:" << __LINE__
598  << " cleanedMatchingResults:" << std::endl;
599  for (auto& result : cleanedMatchingResults) {
600  if (result.trackingParticle || result.simTrack)
601  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::cleanMatching:" << __LINE__ << " simTrack type "
602  << result.pdgId << " pt " << std::setw(8) << result.genPt << " eta " << std::setw(8)
603  << result.genEta << " phi " << std::setw(8) << result.genPhi;
604  else
605  LogTrace("l1tOmtfEventPrint") << "no matched track ";
606 
607  if (result.muonCand) {
608  LogTrace("l1tOmtfEventPrint") << " muonCand pt " << std::setw(8) << result.muonCand->hwPt() << " hwQual "
609  << result.muonCand->hwQual() << " hwEta " << result.muonCand->hwEta()
610  << " deltaEta " << std::setw(8) << result.deltaEta << " deltaPhi " << std::setw(8)
611  << result.deltaPhi << " Likelihood " << std::setw(8) << result.matchingLikelihood
612  << " result " << (short)result.result;
613  LogTrace("l1tOmtfEventPrint") << " procMuon " << *(result.procMuon) << std::endl;
614  } else
615  LogTrace("l1tOmtfEventPrint") << " no muonCand "
616  << " result " << (short)result.result << std::endl;
617  }
618  LogTrace("l1tOmtfEventPrint") << " " << std::endl;
619 
620  return cleanedMatchingResults;
621 }
622 
623 std::vector<MatchingResult> CandidateSimMuonMatcher::match(std::vector<const l1t::RegionalMuonCand*>& muonCands,
624  AlgoMuons& ghostBustedProcMuons,
627  std::function<bool(const SimTrack&)> const& simTrackFilter) {
628  std::vector<MatchingResult> matchingResults;
629 
630  for (auto& simTrack : *simTracks) {
631  if (!simTrackFilter(simTrack))
632  continue;
633 
634  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, simTrack type " << std::setw(3) << simTrack.type()
635  << " pt " << std::setw(9) << simTrack.momentum().pt() << " eta " << std::setw(9)
636  << simTrack.momentum().eta() << " phi " << std::setw(9) << simTrack.momentum().phi()
637  << std::endl;
638 
639  bool matched = false;
640 
642  if (!tsof.isValid()) { //no sense to do matching
645  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " propagation failed: genPt " << result.genPt
646  << " genEta " << result.genEta << " eventId " << simTrack.eventId().event()
647  << std::endl;
648 
649  matchingResults.push_back(result);
650  } else {
651  //checking if the propagated track is inside the OMTF range, TODO - tune the range!!!!!!!!!!!!!!!!!
652  //eta 0.7 is the beginning of the MB2,
653  //the eta range wider than the nominal OMTF region is needed, as in any case muons outside this region are seen by the OMTF
654  //so it better to train the nn suich that is able to measure its pt, as it may affect the rate
655  if ((std::abs(tsof.globalPosition().eta()) >= 0.7) && (std::abs(tsof.globalPosition().eta()) <= 1.31)) {
656  LogTrace("l1tOmtfEventPrint")
657  << "CandidateSimMuonMatcher::match simTrack IS in OMTF region, matching to the omtfCands";
658  } else {
659  LogTrace("l1tOmtfEventPrint") << "simTrack NOT in OMTF region ";
660  continue;
661  }
662 
663  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
664  double ptGen = simTrack.momentum().pt();
665  if(ptGen >= deltaPhiVertexProp->GetXaxis()->GetXmax())
666  ptGen = deltaPhiVertexProp->GetXaxis()->GetXmax() - 0.01;
667 
668  deltaPhiVertexProp->Fill(ptGen, simTrack.momentum().phi() - tsof.globalPosition().phi());*/
669 
670  unsigned int iCand = 0;
671  for (auto& muonCand : muonCands) {
672  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive
673  //if(muonCand->hwQual() > 1)
674  {
676  if (tsof.isValid()) {
677  result = match(muonCand, ghostBustedProcMuons.at(iCand), simTrack, tsof);
678  }
679  int vtxInd = simTrack.vertIndex();
680  if (vtxInd >= 0) {
681  result.simVertex = &(simVertices->at(
682  vtxInd)); //TODO ?????? something strange is here, was commented in the previous version
683  }
685  matchingResults.push_back(result);
686  matched = true;
687  }
688  }
689  iCand++;
690  }
691 
692  if (!matched) { //we are adding also if it was not matching to any candidate
694  matchingResults.push_back(result);
695  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
696  }
697  }
698  }
699 
700  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
701 }
702 
703 std::vector<MatchingResult> CandidateSimMuonMatcher::match(
704  std::vector<const l1t::RegionalMuonCand*>& muonCands,
705  AlgoMuons& ghostBustedProcMuons,
707  std::function<bool(const TrackingParticle&)> const& simTrackFilter) {
708  std::vector<MatchingResult> matchingResults;
709  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match trackingParticles->size() "
710  << trackingParticles->size() << std::endl;
711 
712  for (auto& trackingParticle : *trackingParticles) {
713  //LogTrace("l1tOmtfEventPrint") <<"CandidateSimMuonMatcher::match:"<<__LINE__<<" trackingParticle type "<<std::setw(3)<<trackingParticle.pdgId()<<" pt "<<std::setw(9)<<trackingParticle.pt()<<" eta "<<std::setw(9)<<trackingParticle.momentum().eta()<<" phi "<<std::setw(9)<<trackingParticle.momentum().phi()<<std::endl;
714 
715  if (simTrackFilter(trackingParticle) == false)
716  continue;
717 
718  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, trackingParticle type " << std::setw(3)
719  << trackingParticle.pdgId() << " pt " << std::setw(9) << trackingParticle.pt()
720  << " eta " << std::setw(9) << trackingParticle.momentum().eta() << " phi "
721  << std::setw(9) << trackingParticle.momentum().phi() << std::endl;
722 
723  bool matched = false;
724 
725  TrajectoryStateOnSurface tsof = propagate(trackingParticle);
726  if (!tsof.isValid()) {
727  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match:" << __LINE__ << " propagation failed"
728  << std::endl;
731  continue; //no sense to do matching
732  }
733 
734  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, tsof.globalPosition().eta() "
735  << tsof.globalPosition().eta();
736 
737  //checking if the propagated track is inside the OMTF range, TODO - tune the range!!!!!!!!!!!!!!!!!
738  //eta 0.7 is the beginning of the MB2, while 1.31 is mid of RE2 + some margin
739  if ((std::abs(tsof.globalPosition().eta()) >= 0.7) && (std::abs(tsof.globalPosition().eta()) <= 1.31)) {
740  LogTrace("l1tOmtfEventPrint")
741  << "CandidateSimMuonMatcher::match trackingParticle IS in OMTF region, matching to the omtfCands";
742  } else {
743  LogTrace("l1tOmtfEventPrint") << "trackingParticle NOT in OMTF region ";
744  continue;
745  }
746 
747  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
748  double ptGen = trackingParticle.pt();
749  if(ptGen >= deltaPhiVertexProp->GetXaxis()->GetXmax())
750  ptGen = deltaPhiVertexProp->GetXaxis()->GetXmax() - 0.01;
751 
752  deltaPhiVertexProp->Fill(ptGen, trackingParticle.momentum().phi() - tsof.globalPosition().phi());
753  */
754 
755  unsigned int iCand = 0;
756  for (auto& muonCand : muonCands) {
757  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive then
758  /*if(muonCand->hwQual() <= 1)
759  continue; */
760 
762  if (tsof.isValid()) {
763  result = match(muonCand, ghostBustedProcMuons.at(iCand), trackingParticle, tsof);
764  }
765  iCand++;
766 
768  matchingResults.push_back(result);
769  matched = true;
770  }
771  }
772 
773  if (!matched) { //we are adding result also if it there was no matching to any candidate
774  MatchingResult result(trackingParticle);
775  matchingResults.push_back(result);
776  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
777  }
778  }
779 
780  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
781 }
782 
783 std::vector<MatchingResult> CandidateSimMuonMatcher::matchSimple(
784  std::vector<const l1t::RegionalMuonCand*>& muonCands,
785  AlgoMuons& ghostBustedProcMuons,
788  std::function<bool(const SimTrack&)> const& simTrackFilter) {
789  std::vector<MatchingResult> matchingResults;
790 
791  for (auto& simTrack : *simTracks) {
792  if (!simTrackFilter(simTrack))
793  continue;
794 
795  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::matchSimple: simTrack type " << std::setw(3)
796  << simTrack.type() << " pt " << std::setw(9) << simTrack.momentum().pt() << " eta "
797  << std::setw(9) << simTrack.momentum().eta() << " phi " << std::setw(9)
798  << simTrack.momentum().phi() << std::endl;
799 
800  bool matched = false;
801 
802  unsigned int iCand = 0;
803  for (auto& muonCand : muonCands) {
804  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive
805  //if(muonCand->hwQual() > 1)
806  {
808 
809  double candGloablEta = muonCand->hwEta() * 0.010875;
810  double candGlobalPhi = omtfConfig->calcGlobalPhi(muonCand->hwPhi(), muonCand->processor());
811  candGlobalPhi = hwGmtPhiToGlobalPhi(candGlobalPhi);
812 
813  if (candGlobalPhi > M_PI)
814  candGlobalPhi = candGlobalPhi - (2. * M_PI);
815 
816  result.deltaPhi = foldPhi(result.genPhi - candGlobalPhi);
817  result.deltaEta = result.genEta - candGloablEta;
818 
819  result.propagatedPhi = 0;
820  result.propagatedEta = 0;
821 
822  result.muonCand = muonCand;
823  result.procMuon = ghostBustedProcMuons.at(iCand);
824 
825  //TODO histogram can be used, like in the usercode/L1MuonAnalyzer MuonMatcher::matchWithoutPorpagation
826  //for prompt muons
827  /*double treshold = 0.3;
828  if (simTrack.momentum().pt() < 5)
829  treshold = 1.5;
830  else if (simTrack.momentum().pt() < 8)
831  treshold = 0.8;
832  else if (simTrack.momentum().pt() < 10)
833  treshold = 0.6;
834  else if (simTrack.momentum().pt() < 20)
835  treshold = 0.5;*/
836 
837  //for displaced muons
838  double treshold = 0.7;
839  if (simTrack.momentum().pt() < 5)
840  treshold = 1.5;
841  else if (simTrack.momentum().pt() < 10)
842  treshold = 1.0;
843  else if (simTrack.momentum().pt() < 20)
844  treshold = 0.7;
845 
846  if (std::abs(result.deltaPhi) < treshold && std::abs(result.deltaEta) < 0.5) {
848  //matchingLikelihood is needed in the cleanMatching, so we put something
849  if (std::abs(result.deltaPhi) < 0.001)
850  result.matchingLikelihood = 1. / 0.001;
851  else
852  result.matchingLikelihood = 1. / std::abs(result.deltaPhi);
853  }
854 
855  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::matchSimple: simTrack type " << simTrack.type()
856  << " pt " << std::setw(8) << simTrack.momentum().pt() << " eta " << std::setw(8)
857  << simTrack.momentum().eta() << " phi " << std::setw(8)
858  << simTrack.momentum().phi() << "\n muonCand pt " << std::setw(8)
859  << muonCand->hwPt() << " candGloablEta " << std::setw(8) << candGloablEta
860  << " candGlobalPhi " << std::setw(8) << candGlobalPhi << " hwQual "
861  << muonCand->hwQual() << " deltaEta " << std::setw(8) << result.deltaEta
862  << " deltaPhi " << std::setw(8) << result.deltaPhi << " matchingLikelihood "
863  << result.matchingLikelihood << " result " << (short)result.result << std::endl;
864 
865  int vtxInd = simTrack.vertIndex();
866  if (vtxInd >= 0) {
867  result.simVertex = &(
868  simVertices->at(vtxInd)); //TODO ?????? something strange is here, was commented in the previous version
869  }
871  matchingResults.push_back(result);
872  matched = true;
873  }
874  }
875  iCand++;
876  }
877 
878  if (!matched) { //we are adding also if it was not matched to any candidate
880  matchingResults.push_back(result);
881  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
882  }
883  }
884 
885  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
886 }
const int hwPhi() const
Get compressed local phi (returned int * 2*pi/576 = local phi in rad)
MatchingResult match(const l1t::RegionalMuonCand *omtfCand, const AlgoMuonPtr &procMuon, const SimTrack &simTrack, TrajectoryStateOnSurface &tsof)
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
int pdgId() const
PDG ID.
EncodedEventId eventId() const
Signal source, crossing number.
Vector momentum() const
spatial momentum vector
int event() const
get the contents of the subdetector field (should be protected?)
double hwGmtPhiToGlobalPhi(int phi)
double vx() const
x coordinate of parent vertex position
bool trackingParticleIsMuonInOmtfEvent0(const TrackingParticle &trackingParticle)
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
edm::ESHandle< MagneticField > magField
bool exists(std::string const &parameterName) const
checks if a parameter exists
T eta() const
Definition: PV3DBase.h:73
const int processor() const
Get processor ID on which the candidate was found (0..5 for OMTF/EMTF; 0..11 for BMTF) ...
TrajectoryStateOnSurface atStation2(const FreeTrajectoryState &ftsStart) const
T const * product() const
Definition: Handle.h:70
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
float normal_pdf(float x, float m, float s)
Cylinder BoundCylinder
Definition: BoundCylinder.h:17
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
void beginRun(edm::EventSetup const &eventSetup) override
TrajectoryStateOnSurface propagate(const SimTrack &simTrack, const edm::SimVertexContainer *simVertices)
Log< level::Error, false > LogError
const int hwPt() const
Get compressed pT (returned int * 0.5 = pT (GeV))
TrajectoryStateOnSurface propagate(STA const &state, SUR const &surface) const
Definition: Propagator.h:50
CandidateSimMuonMatcher(const edm::ParameterSet &edmCfg, const OMTFConfiguration *omtfConfig, const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > &magneticFieldEsToken, const edm::ESGetToken< Propagator, TrackingComponentsRecord > &propagatorEsToken)
void observeProcesorEmulation(unsigned int iProcessor, l1t::tftype mtfType, const std::shared_ptr< OMTFinput > &, const AlgoMuons &algoCandidates, const AlgoMuons &gbCandidates, const std::vector< l1t::RegionalMuonCand > &candMuons) override
const OMTFConfiguration * omtfConfig
const math::XYZTLorentzVectorD & momentum() const
Definition: CoreSimTrack.h:19
const std::vector< SimTrack > & g4Tracks() const
#define LogTrace(id)
static std::string const input
Definition: EdmProvDump.cc:50
bool simTrackIsMuonInOmtf(const SimTrack &simTrack)
const int hwQual() const
Get quality code.
bool trackingParticleIsMuonInBx0(const TrackingParticle &trackingParticle)
const int hwEta() const
Get compressed eta (returned int * 0.010875 = eta)
std::vector< MatchingResult > cleanMatching(std::vector< MatchingResult > matchingResults, std::vector< const l1t::RegionalMuonCand *> &muonCands, AlgoMuons &ghostBustedProcMuons)
unsigned size(int bx) const
int type() const
particle type (HEP PDT convension)
Definition: CoreSimTrack.h:22
std::vector< MatchingResult > matchSimple(std::vector< const l1t::RegionalMuonCand *> &muonCands, AlgoMuons &ghostBustedProcMuons, const edm::SimTrackContainer *simTracks, const edm::SimVertexContainer *simVertices, std::function< bool(const SimTrack &)> const &simTrackFilter)
bool simTrackIsMuonInOmtfBx0(const SimTrack &simTrack)
double foldPhi(double phi)
const edm::ESGetToken< Propagator, TrackingComponentsRecord > & propagatorEsToken
GlobalPoint globalPosition() const
const edm::ParameterSet & edmCfg
int bunchCrossing() const
get the detector field from this detid
bool simTrackIsMuonInBx0(const SimTrack &simTrack)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Log< level::Error, true > LogImportant
bool isMatched(TrackingRecHit const &hit)
const T & at(int bx, unsigned i) const
#define M_PI
FreeTrajectoryState simTrackToFts(const SimTrack &simTrack, const SimVertex &simVertex)
void observeEventBegin(const edm::Event &event) override
const TrackingVertexRef & parentVertex() const
int calcGlobalPhi(int locPhi, int proc) const
double vy() const
y coordinate of parent vertex position
std::vector< SimVertex > SimVertexContainer
double b
Definition: hdecay.h:120
edm::ESHandle< Propagator > propagator
std::vector< AlgoMuonPtr > AlgoMuons
Definition: AlgoMuon.h:176
double a
Definition: hdecay.h:121
unsigned int getProcIndx(unsigned int iProcessor, l1t::tftype mtfType) const
input phi should be in the hardware scale (nPhiBins units for 2pi), can be in range -nPhiBins ...
float x
Monte Carlo truth information used for tracking validation.
bool trackingParticleIsMuonInOmtfBx0(const TrackingParticle &trackingParticle)
std::shared_ptr< AlgoMuon > AlgoMuonPtr
Definition: AlgoMuon.h:175
std::vector< TrackingParticle > TrackingParticleCollection
double pt() const
Transverse momentum. Note this is taken from the first SimTrack only.
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > & magneticFieldEsToken
std::vector< MatchingResult > matchingResults
std::vector< SimTrack > SimTrackContainer
Definition: event.py:1
void observeEventEnd(const edm::Event &event, std::unique_ptr< l1t::RegionalMuonCandBxCollection > &finalCandidates) override
std::vector< const l1t::RegionalMuonCand * > ghostBust(const l1t::RegionalMuonCandBxCollection *mtfCands, const AlgoMuons &gbCandidates, AlgoMuons &ghostBustedProcMuons)
double vz() const
z coordinate of parent vertex position