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  deltaPhiPropCandMean = (TH1D*)inFile.Get("deltaPhiPropCandMean");
57  deltaPhiPropCandStdDev = (TH1D*)inFile.Get("deltaPhiPropCandStdDev");
58 }
59 
61 
63  //TODO use edm::ESWatcher<MagneticField> magneticFieldRecordWatcher;
66 }
67 
69 
71  l1t::tftype mtfType,
72  const std::shared_ptr<OMTFinput>& input,
73  const AlgoMuons& algoCandidates,
74  const AlgoMuons& gbCandidates,
75  const std::vector<l1t::RegionalMuonCand>& candMuons) {
76  //debug
77  unsigned int procIndx = omtfConfig->getProcIndx(iProcessor, mtfType);
78  for (auto& gbCandidate : gbCandidates) {
79  if (gbCandidate->getPtConstr() > 0) {
80  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::observeProcesorEmulation procIndx" << procIndx << " "
81  << *gbCandidate << std::endl;
82  this->gbCandidates.emplace_back(gbCandidate);
83  }
84  }
85 }
86 
88  if (std::abs(simTrack.type()) == 13 ||
89  std::abs(simTrack.type()) == 1000015) { // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
90  //only muons
91  } else
92  return false;
93 
94  //in the overlap, the propagation of muons with pt less then ~3.2 fails - the actual threshold depends slightly on eta,
95  if (simTrack.momentum().pt() < 2.5)
96  return false;
97 
98  LogTrace("l1tOmtfEventPrint") << "simTrackIsMuonInOmtf, simTrack type " << std::setw(3) << simTrack.type() << " pt "
99  << std::setw(9) << simTrack.momentum().pt() << " eta " << std::setw(9)
100  << simTrack.momentum().eta() << " phi " << std::setw(9) << simTrack.momentum().phi()
101  << std::endl;
102 
103  //some margin for matching must be used on top of actual OMTF region,
104  //i.e. (0.82-1.24)=>(0.72-1.3),
105  //otherwise many candidates are marked as ghosts
106  if ((std::abs(simTrack.momentum().eta()) >= 0.72) && (std::abs(simTrack.momentum().eta()) <= 1.3)) {
107  } else
108  return false;
109 
110  return true;
111 }
112 
114  if (simTrack.eventId().bunchCrossing() != 0)
115  return false;
116 
118 }
119 
121  if (std::abs(simTrack.type()) == 13 ||
122  std::abs(simTrack.type()) == 1000015) { // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
123  //only muons
124  if (simTrack.eventId().bunchCrossing() == 0)
125  return true;
126  }
127  return false;
128 }
129 
130 bool trackingParticleIsMuonInBx0(const TrackingParticle& trackingParticle) {
131  if (std::abs(trackingParticle.pdgId()) == 13 ||
132  std::abs(trackingParticle.pdgId()) ==
133  1000015) { // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
134  //only muons
135  if (trackingParticle.eventId().bunchCrossing() == 0)
136  return true;
137  }
138  return false;
139 }
140 
141 bool trackingParticleIsMuonInOmtfBx0(const TrackingParticle& trackingParticle) {
142  if (trackingParticle.eventId().bunchCrossing() != 0)
143  return false;
144 
145  if (std::abs(trackingParticle.pdgId()) == 13 || std::abs(trackingParticle.pdgId()) == 1000015) {
146  // 1000015 is stau, todo use other selection (e.g. pt>20) if needed
147  //only muons
148  } else
149  return false;
150 
151  //in the overlap, the propagation of muons with pt less then ~3.2 fails, the actual threshold depends slightly on eta,
152  if (trackingParticle.pt() < 2.5)
153  return false;
154 
155  if (trackingParticle.parentVertex().isNonnull())
156  LogTrace("l1tOmtfEventPrint") << "trackingParticleIsMuonInOmtfBx0, pdgId " << std::setw(3)
157  << trackingParticle.pdgId() << " pt " << std::setw(9) << trackingParticle.pt()
158  << " eta " << std::setw(9) << trackingParticle.momentum().eta() << " phi "
159  << std::setw(9) << trackingParticle.momentum().phi() << " event "
160  << trackingParticle.eventId().event() << " trackId "
161  << trackingParticle.g4Tracks().at(0).trackId() << " parentVertex Rho "
162  << trackingParticle.parentVertex()->position().Rho() << " eta "
163  << trackingParticle.parentVertex()->position().eta() << " phi "
164  << trackingParticle.parentVertex()->position().phi() << std::endl;
165  else
166  LogTrace("l1tOmtfEventPrint") << "trackingParticleIsMuonInOmtfBx0, pdgId " << std::setw(3)
167  << trackingParticle.pdgId() << " pt " << std::setw(9) << trackingParticle.pt()
168  << " eta " << std::setw(9) << trackingParticle.momentum().eta() << " phi "
169  << std::setw(9) << trackingParticle.momentum().phi() << " trackId "
170  << trackingParticle.g4Tracks().at(0).trackId();
171 
172  //some margin for matching must be used on top of actual OMTF region,
173  //i.e. (0.82-1.24)=>(0.72-1.3),
174  //otherwise many candidates are marked as ghosts
175  if ((std::abs(trackingParticle.momentum().eta()) >= 0.72) && (std::abs(trackingParticle.momentum().eta()) <= 1.3)) {
176  } else
177  return false;
178 
179  return true;
180 }
181 
183  if (trackingParticle.eventId().event() != 0)
184  return false;
185 
186  return trackingParticleIsMuonInOmtfBx0(trackingParticle);
187 }
188 
190  std::unique_ptr<l1t::RegionalMuonCandBxCollection>& finalCandidates) {
191  LogTrace("l1tOmtfEventPrint") << "\nCandidateSimMuonMatcher::observeEventEnd" << std::endl;
192  AlgoMuons ghostBustedProcMuons;
193  std::vector<const l1t::RegionalMuonCand*> ghostBustedRegionalCands =
194  CandidateSimMuonMatcher::ghostBust(finalCandidates.get(), gbCandidates, ghostBustedProcMuons);
195 
196  matchingResults.clear();
197  if (edmCfg.exists("simTracksTag")) {
199  event.getByLabel(edmCfg.getParameter<edm::InputTag>("simTracksTag"), simTraksHandle);
200 
202  event.getByLabel(edmCfg.getParameter<edm::InputTag>("simVertexesTag"), simVertices);
203 
204  LogTrace("l1tOmtfEventPrint") << "simTraksHandle size " << simTraksHandle.product()->size() << std::endl;
205  LogTrace("l1tOmtfEventPrint") << "simVertices size " << simVertices.product()->size() << std::endl;
206 
207  //TODO use other simTrackFilter if needed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
208  //we dont want to check the eta of the generated muon, as it is on the vertex,
209  //instead inside match, we check the eta of the propagated track to the second muons station
210  std::function<bool(const SimTrack&)> const& simTrackFilter = simTrackIsMuonInBx0; //simTrackIsMuonInOmtfBx0;
211 
213  ghostBustedRegionalCands, ghostBustedProcMuons, simTraksHandle.product(), simVertices.product(), simTrackFilter);
214 
215  } else if (edmCfg.exists("trackingParticleTag")) {
216  edm::Handle<TrackingParticleCollection> trackingParticleHandle;
217  event.getByLabel(edmCfg.getParameter<edm::InputTag>("trackingParticleTag"), trackingParticleHandle);
218  LogTrace("l1tOmtfEventPrint") << "\nCandidateSimMuonMatcher::observeEventEnd trackingParticleHandle size "
219  << trackingParticleHandle.product()->size() << std::endl;
220 
221  //TODO use other trackParticleFilter if needed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
222  std::function<bool(const TrackingParticle&)> trackParticleFilter =
223  trackingParticleIsMuonInBx0; //trackingParticleIsMuonInOmtfBx0;
225  match(ghostBustedRegionalCands, ghostBustedProcMuons, trackingParticleHandle.product(), trackParticleFilter);
226  }
227 }
228 
230 
231 std::vector<const l1t::RegionalMuonCand*> CandidateSimMuonMatcher::ghostBust(
232  const l1t::RegionalMuonCandBxCollection* mtfCands, const AlgoMuons& gbCandidates, AlgoMuons& ghostBustedProcMuons) {
233  if (gbCandidates.size() != mtfCands->size(0)) {
234  edm::LogError("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::ghostBust(): gbCandidates.size() "
235  << gbCandidates.size() << " != mtfCands.size() " << mtfCands->size();
236  }
237 
238  boost::dynamic_bitset<> isKilled(mtfCands->size(0), false);
239 
240  for (unsigned int i1 = 0; i1 < mtfCands->size(0); ++i1) {
241  if (mtfCands->at(0, i1).hwPt() == 0)
242  continue;
243  LogTrace("l1tOmtfEventPrint") << "\nCandidateSimMuonMatcher::ghostBust regionalCand pt " << std::setw(3)
244  << mtfCands->at(0, i1).hwPt() << " qual " << std::setw(2)
245  << mtfCands->at(0, i1).hwQual() << " proc " << std::setw(2)
246  << mtfCands->at(0, i1).processor();
247  for (unsigned int i2 = i1 + 1; i2 < mtfCands->size(0); ++i2) {
248  auto& mtfCand1 = mtfCands->at(0, i1);
249  auto& mtfCand2 = mtfCands->at(0, i2);
250  if (mtfCand2.hwPt() == 0)
251  continue;
252 
253  if (std::abs(mtfCand1.hwEta() - mtfCand2.hwEta()) < (0.3 / 0.010875)) {
254  int gloablHwPhi1 = omtfConfig->calcGlobalPhi(mtfCand1.hwPhi(), mtfCand1.processor());
255  int gloablHwPhi2 = omtfConfig->calcGlobalPhi(mtfCand2.hwPhi(), mtfCand2.processor());
256 
257  //one can use the phi in radians like that:
258  //double globalPhi1 = hwGmtPhiToGlobalPhi(omtfConfig->calcGlobalPhi( mtfCand1.hwPhi(), mtfCand1.processor() ) );
259  //double globalPhi2 = hwGmtPhiToGlobalPhi(omtfConfig->calcGlobalPhi( mtfCand2.hwPhi(), mtfCand2.processor() ) );
260 
261  //0.0872664626 = 5 deg, i.e. the same window as in the OMTF ghost buster
262  if (std::abs(gloablHwPhi1 - gloablHwPhi2) < 8) {
263  //if (mtfCand1.hwQual() > mtfCand2.hwQual()) //TODO this is used in the uGMT
264  if (gbCandidates[i1]->getFiredLayerCnt() >
265  gbCandidates[i2]->getFiredLayerCnt()) //but this should be better - but probably the difference is not big
266  {
267  isKilled[i2] = true;
268  } else
269  isKilled[i1] = true;
270  }
271  }
272  }
273  }
274 
275  std::vector<const l1t::RegionalMuonCand*> resultCands;
276 
277  for (unsigned int i1 = 0; i1 < mtfCands->size(0); ++i1) {
278  //dropping candidates with quality 0 !!!!!!!!!!!!!!!!!!!! fixme if not needed
279  if (!isKilled[i1] && mtfCands->at(0, i1).hwPt()) {
280  resultCands.push_back(&(mtfCands->at(0, i1)));
281  ghostBustedProcMuons.push_back(gbCandidates.at(i1));
282  }
283 
284  if (mtfCands->at(0, i1).hwPt()) {
285  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::ghostBust\n regionalCand pt " << std::setw(3)
286  << mtfCands->at(0, i1).hwPt() << " qual " << std::setw(2)
287  << mtfCands->at(0, i1).hwQual() << " proc " << std::setw(2)
288  << mtfCands->at(0, i1).processor() << " eta " << std::setw(4)
289  << mtfCands->at(0, i1).hwEta() << " gloablEta " << std::setw(8)
290  << mtfCands->at(0, i1).hwEta() * 0.010875 << " hwPhi " << std::setw(3)
291  << mtfCands->at(0, i1).hwPhi() << " globalPhi " << std::setw(8)
292  << hwGmtPhiToGlobalPhi(omtfConfig->calcGlobalPhi(mtfCands->at(0, i1).hwPhi(),
293  mtfCands->at(0, i1).processor()))
294  << " fireadLayers " << std::bitset<18>(mtfCands->at(0, i1).trackAddress().at(0))
295  << " gb isKilled " << isKilled.test(i1) << std::endl;
296 
297  LogTrace("l1tOmtfEventPrint") << *(gbCandidates.at(i1)) << std::endl;
298  }
299  }
300 
301  if (resultCands.size() >= 3)
302  LogTrace("l1tOmtfEventPrint") << " ghost !!!!!! " << std::endl;
303  LogTrace("l1tOmtfEventPrint") << std::endl;
304 
305  return resultCands;
306 }
307 
309  // first propagate to MB2 assuming that muon is within barrel+overlap
310  // 512.401cm is R of middle of the MB2
312  GlobalPoint(0., 0., 0.), TkRotation<float>(), SimpleCylinderBounds(512.401, 512.401, -900, 900)));
313  TrajectoryStateOnSurface trackAtRPC = propagator->propagate(ftsStart, *rpc);
314  float zAtRPC = trackAtRPC.globalPosition().z();
315  // check if propagated track within barrel+overlap, |z| = 660.5cm is edge of MB2 (B field on)
316  if (std::abs(zAtRPC) > 660.5) { //endcap, RE2, z = +-790cm
317  rpc = ReferenceCountingPointer<Surface>(new BoundDisk(GlobalPoint(0., 0., std::copysign(790., zAtRPC)),
319  SimpleDiskBounds(300., 810., -10., 10.)));
320  trackAtRPC = propagator->propagate(ftsStart, *rpc);
321  }
322  return trackAtRPC;
323 }
324 
326  int charge = simTrackPtr.type() > 0 ? -1 : 1; //works for muons
327 
328  GlobalVector p3GV(simTrackPtr.momentum().x(), simTrackPtr.momentum().y(), simTrackPtr.momentum().z());
329  GlobalPoint r3GP(simVertex.position().x(), simVertex.position().y(), simVertex.position().z());
330 
331  GlobalTrajectoryParameters tPars(r3GP, p3GV, charge, &*magField);
332 
333  return FreeTrajectoryState(tPars);
334 }
335 
337  int charge = trackingParticle.pdgId() > 0 ? -1 : 1; //works for muons
338 
339  GlobalVector p3GV(trackingParticle.momentum().x(), trackingParticle.momentum().y(), trackingParticle.momentum().z());
340  GlobalPoint r3GP(trackingParticle.vx(), trackingParticle.vy(), trackingParticle.vz());
341 
342  GlobalTrajectoryParameters tPars(r3GP, p3GV, charge, &*magField);
343 
344  return FreeTrajectoryState(tPars);
345 }
346 
350  int vtxInd = simTrack.vertIndex();
351  if (vtxInd < 0) {
352  edm::LogImportant("l1tOmtfEventPrint") << "Track with no vertex, defaulting to (0,0,0)";
353  } else {
355  if (((int)simVertex.vertexId()) != vtxInd) {
356  edm::LogImportant("l1tOmtfEventPrint") << "simVertex.vertexId() != vtxInd. simVertex.vertexId() "
357  << simVertex.vertexId() << " vtxInd " << vtxInd << " !!!!!!!!!!!!!!!!!";
358  }
359  }
360 
362 
363  TrajectoryStateOnSurface tsof = atStation2(ftsTrack); //propagation
364 
365  return tsof;
366 }
367 
369  FreeTrajectoryState ftsTrack = simTrackToFts(trackingParticle);
370 
371  TrajectoryStateOnSurface tsof = atStation2(ftsTrack); //propagation
372 
373  return tsof;
374 }
375 
376 float normal_pdf(float x, float m, float s) {
377  static const float inv_sqrt_2pi = 0.3989422804014327;
378  float a = (x - m) / s;
379 
380  return inv_sqrt_2pi / s * std::exp(-0.5 * a * a);
381 }
382 
384  const AlgoMuonPtr& procMuon,
385  const SimTrack& simTrack,
386  TrajectoryStateOnSurface& tsof) {
388 
389  double candGloablEta = muonCand->hwEta() * 0.010875;
390  //if (std::abs(simTrack.momentum().eta() - candGloablEta) < 0.3) //has no sense for displaced muons
391  {
392  double candGlobalPhi = omtfConfig->calcGlobalPhi(muonCand->hwPhi(), muonCand->processor());
393  candGlobalPhi = hwGmtPhiToGlobalPhi(candGlobalPhi);
394 
395  if (candGlobalPhi > M_PI)
396  candGlobalPhi = candGlobalPhi - (2. * M_PI);
397 
398  result.deltaPhi = foldPhi(tsof.globalPosition().phi() - candGlobalPhi);
399  result.deltaEta = tsof.globalPosition().eta() - candGloablEta;
400 
401  result.propagatedPhi = tsof.globalPosition().phi();
402  result.propagatedEta = tsof.globalPosition().eta();
403 
404  double mean = 0;
405  double sigma = 1;
406  //if(!fillMean)
407  {
408  auto ptBin = deltaPhiPropCandMean->FindBin(simTrack.momentum().pt());
409  mean = deltaPhiPropCandMean->GetBinContent(ptBin);
410  sigma = deltaPhiPropCandStdDev->GetBinContent(ptBin);
411  }
412  result.matchingLikelihood = normal_pdf(result.deltaPhi, mean, sigma); //TODO temporary solution
413 
414  result.muonCand = muonCand;
415  result.procMuon = procMuon;
416 
417  double treshold = 6. * sigma;
418  if (simTrack.momentum().pt() > 20)
419  treshold = 7. * sigma;
420  if (simTrack.momentum().pt() > 100)
421  treshold = 20. * sigma;
422 
423  if (std::abs(result.deltaPhi - mean) < treshold && std::abs(result.deltaEta) < 0.3)
425 
426  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match: simTrack type " << simTrack.type() << " pt "
427  << std::setw(8) << simTrack.momentum().pt() << " eta " << std::setw(8)
428  << simTrack.momentum().eta() << " phi " << std::setw(8) << simTrack.momentum().phi()
429  << " propagation eta " << std::setw(8) << tsof.globalPosition().eta() << " phi "
430  << tsof.globalPosition().phi() << "\n muonCand pt " << std::setw(8)
431  << muonCand->hwPt() << " candGloablEta " << std::setw(8) << candGloablEta
432  << " candGlobalPhi " << std::setw(8) << candGlobalPhi << " hwQual "
433  << muonCand->hwQual() << " deltaEta " << std::setw(8) << result.deltaEta
434  << " deltaPhi " << std::setw(8) << result.deltaPhi << " sigma " << std::setw(8)
435  << sigma << " Likelihood " << std::setw(8) << result.matchingLikelihood << " result "
436  << (short)result.result << std::endl;
437  }
438 
439  return result;
440 }
441 
443  const AlgoMuonPtr& procMuon,
444  const TrackingParticle& trackingParticle,
445  TrajectoryStateOnSurface& tsof) {
446  MatchingResult result(trackingParticle);
447 
448  double candGloablEta = muonCand->hwEta() * 0.010875;
449  //if (std::abs(trackingParticle.momentum().eta() - candGloablEta) < 0.3) //has no sense for displaced muons
450  {
451  double candGlobalPhi = omtfConfig->calcGlobalPhi(muonCand->hwPhi(), muonCand->processor());
452  candGlobalPhi = hwGmtPhiToGlobalPhi(candGlobalPhi);
453 
454  if (candGlobalPhi > M_PI)
455  candGlobalPhi = candGlobalPhi - (2. * M_PI);
456 
457  result.deltaPhi = foldPhi(tsof.globalPosition().phi() - candGlobalPhi);
458  result.deltaEta = tsof.globalPosition().eta() - candGloablEta;
459 
460  result.propagatedPhi = tsof.globalPosition().phi();
461  result.propagatedEta = tsof.globalPosition().eta();
462 
463  double mean = 0;
464  double sigma = 1;
465  //if(!fillMean)
466  {
467  auto ptBin = deltaPhiPropCandMean->FindBin(trackingParticle.pt());
468 
469  mean = deltaPhiPropCandMean->GetBinContent(ptBin);
470  sigma = deltaPhiPropCandStdDev->GetBinContent(ptBin);
471  }
472 
473  result.matchingLikelihood = normal_pdf(result.deltaPhi, mean, sigma); //TODO temporary solution
474 
475  result.muonCand = muonCand;
476  result.procMuon = procMuon;
477 
478  double treshold = 6. * sigma;
479  if (trackingParticle.pt() > 20)
480  treshold = 7. * sigma;
481  if (trackingParticle.pt() > 100)
482  treshold = 20. * sigma;
483 
484  if (std::abs(result.deltaPhi - mean) < treshold && std::abs(result.deltaEta) < 0.3)
486 
487  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match: trackingParticle type "
488  << trackingParticle.pdgId() << " pt " << std::setw(8) << trackingParticle.pt()
489  << " eta " << std::setw(8) << trackingParticle.momentum().eta() << " phi "
490  << std::setw(8) << trackingParticle.momentum().phi() << " propagation eta "
491  << std::setw(8) << tsof.globalPosition().eta() << " phi "
492  << tsof.globalPosition().phi() << " muonCand pt " << std::setw(8) << muonCand->hwPt()
493  << " candGloablEta " << std::setw(8) << candGloablEta << " candGlobalPhi "
494  << std::setw(8) << candGlobalPhi << " hwQual " << muonCand->hwQual() << " deltaEta "
495  << std::setw(8) << result.deltaEta << " deltaPhi " << std::setw(8) << result.deltaPhi
496  << " Likelihood " << std::setw(8) << result.matchingLikelihood << " result "
497  << (short)result.result << std::endl;
498  }
499 
500  return result;
501 }
502 
503 std::vector<MatchingResult> CandidateSimMuonMatcher::cleanMatching(std::vector<MatchingResult> matchingResults,
504  std::vector<const l1t::RegionalMuonCand*>& muonCands,
505  AlgoMuons& ghostBustedProcMuons) {
506  //Cleaning the matching
507  std::sort(
508  matchingResults.begin(), matchingResults.end(), [](const MatchingResult& a, const MatchingResult& b) -> bool {
509  return a.matchingLikelihood > b.matchingLikelihood;
510  });
511 
512  for (unsigned int i1 = 0; i1 < matchingResults.size(); i1++) {
514  for (unsigned int i2 = i1 + 1; i2 < matchingResults.size(); i2++) {
515  if ((matchingResults[i1].trackingParticle &&
516  matchingResults[i1].trackingParticle == matchingResults[i2].trackingParticle) ||
517  (matchingResults[i1].simTrack && matchingResults[i1].simTrack == matchingResults[i2].simTrack) ||
518  (matchingResults[i1].muonCand == matchingResults[i2].muonCand)) {
519  //if matchingResults[i1].muonCand == false, then it is also OK here
521  }
522  }
523  }
524  }
525 
526  std::vector<MatchingResult> cleanedMatchingResults;
527  for (auto& matchingResult : matchingResults) {
528  if (matchingResult.result == MatchingResult::ResultType::matched ||
529  matchingResult.muonCand ==
530  nullptr) //adding also the simTracks that are not matched at all, before it is assured that they are not duplicates
531  cleanedMatchingResults.push_back(matchingResult);
532  if (matchingResult.result == MatchingResult::ResultType::matched) {
533  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
534  if(fillMean) {
535  double ptGen = matchingResult.genPt;
536  deltaPhiPropCandMean->Fill(ptGen, matchingResult.deltaPhi); //filling overflow is ok here
537  deltaPhiPropCandStdDev->Fill(ptGen, matchingResult.deltaPhi * matchingResult.deltaPhi);
538  }*/
539  }
540  }
541 
542  //adding the muonCand-s that were not matched, i.e. in order to analyze them later
543  unsigned int iCand = 0;
544  for (auto& muonCand : muonCands) {
545  bool isMatched = false;
546  for (auto& matchingResult : cleanedMatchingResults) {
547  if (matchingResult.muonCand == muonCand) {
548  isMatched = true;
549  break;
550  }
551  }
552 
553  if (!isMatched) {
555  result.muonCand = muonCand;
556  result.procMuon = ghostBustedProcMuons.at(iCand);
557  cleanedMatchingResults.push_back(result);
558  }
559  iCand++;
560  }
561 
562  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::cleanMatching:" << __LINE__
563  << " CandidateSimMuonMatcher::match cleanedMatchingResults:" << std::endl;
564  for (auto& result : cleanedMatchingResults) {
565  if (result.trackingParticle || result.simTrack)
566  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::cleanMatching:" << __LINE__ << " simTrack type "
567  << result.pdgId << " pt " << std::setw(8) << result.genPt << " eta " << std::setw(8)
568  << result.genEta << " phi " << std::setw(8) << result.genPhi;
569  else
570  LogTrace("l1tOmtfEventPrint") << "no matched track ";
571 
572  if (result.muonCand) {
573  LogTrace("l1tOmtfEventPrint") << " muonCand pt " << std::setw(8) << result.muonCand->hwPt() << " hwQual "
574  << result.muonCand->hwQual() << " hwEta " << result.muonCand->hwEta()
575  << " deltaEta " << std::setw(8) << result.deltaEta << " deltaPhi " << std::setw(8)
576  << result.deltaPhi << " Likelihood " << std::setw(8) << result.matchingLikelihood
577  << " result " << (short)result.result;
578  LogTrace("l1tOmtfEventPrint") << " procMuon " << *(result.procMuon) << std::endl;
579  } else
580  LogTrace("l1tOmtfEventPrint") << " no muonCand "
581  << " result " << (short)result.result << std::endl;
582  }
583  LogTrace("l1tOmtfEventPrint") << " " << std::endl;
584 
585  return cleanedMatchingResults;
586 }
587 
588 std::vector<MatchingResult> CandidateSimMuonMatcher::match(std::vector<const l1t::RegionalMuonCand*>& muonCands,
589  AlgoMuons& ghostBustedProcMuons,
592  std::function<bool(const SimTrack&)> const& simTrackFilter) {
593  std::vector<MatchingResult> matchingResults;
594 
595  for (auto& simTrack : *simTracks) {
596  if (!simTrackFilter(simTrack))
597  continue;
598 
599  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, simTrack type " << std::setw(3) << simTrack.type()
600  << " pt " << std::setw(9) << simTrack.momentum().pt() << " eta " << std::setw(9)
601  << simTrack.momentum().eta() << " phi " << std::setw(9) << simTrack.momentum().phi()
602  << std::endl;
603 
604  bool matched = false;
605 
607  if (!tsof.isValid()) {
608  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " propagation failed" << std::endl;
611  continue; //no sense to do matching
612  }
613 
614  //checking if the propagated track is inside the OMTF range, TODO - tune the range!!!!!!!!!!!!!!!!!
615  //eta 0.7 is the beginning of the MB2, while 1.31 is mid of RE2 + some margin
616  //the eta range wider than the nominal OMTF region is needed, as in any case muons outside this region are seen by the OMTF
617  //so it better to train the nn suich that is able to measure its pt, as it may affect the rate
618  if ((std::abs(tsof.globalPosition().eta()) >= 0.7) && (std::abs(tsof.globalPosition().eta()) <= 1.31)) {
619  LogTrace("l1tOmtfEventPrint")
620  << "CandidateSimMuonMatcher::match simTrack IS in OMTF region, matching to the omtfCands";
621  } else {
622  LogTrace("l1tOmtfEventPrint") << "simTrack NOT in OMTF region ";
623  continue;
624  }
625 
626  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
627  double ptGen = simTrack.momentum().pt();
628  if(ptGen >= deltaPhiVertexProp->GetXaxis()->GetXmax())
629  ptGen = deltaPhiVertexProp->GetXaxis()->GetXmax() - 0.01;
630 
631  deltaPhiVertexProp->Fill(ptGen, simTrack.momentum().phi() - tsof.globalPosition().phi());*/
632 
633  unsigned int iCand = 0;
634  for (auto& muonCand : muonCands) {
635  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive
636  //if(muonCand->hwQual() > 1)
637  {
639  if (tsof.isValid()) {
640  result = match(muonCand, ghostBustedProcMuons.at(iCand), simTrack, tsof);
641  }
642  int vtxInd = simTrack.vertIndex();
643  if (vtxInd >= 0) {
644  result.simVertex = &(
645  simVertices->at(vtxInd)); //TODO ?????? something strange is here, was commented in the previous version
646  }
648  matchingResults.push_back(result);
649  matched = true;
650  }
651  }
652  iCand++;
653  }
654 
655  if (!matched) { //we are adding also if it was not matching to any candidate
657  matchingResults.push_back(result);
658  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
659  }
660  }
661 
662  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
663 }
664 
665 std::vector<MatchingResult> CandidateSimMuonMatcher::match(
666  std::vector<const l1t::RegionalMuonCand*>& muonCands,
667  AlgoMuons& ghostBustedProcMuons,
669  std::function<bool(const TrackingParticle&)> const& simTrackFilter) {
670  std::vector<MatchingResult> matchingResults;
671  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match trackingParticles->size() "
672  << trackingParticles->size() << std::endl;
673 
674  for (auto& trackingParticle : *trackingParticles) {
675  //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;
676 
677  if (simTrackFilter(trackingParticle) == false)
678  continue;
679 
680  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, trackingParticle type " << std::setw(3)
681  << trackingParticle.pdgId() << " pt " << std::setw(9) << trackingParticle.pt()
682  << " eta " << std::setw(9) << trackingParticle.momentum().eta() << " phi "
683  << std::setw(9) << trackingParticle.momentum().phi() << std::endl;
684 
685  bool matched = false;
686 
687  TrajectoryStateOnSurface tsof = propagate(trackingParticle);
688  if (!tsof.isValid()) {
689  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match:" << __LINE__ << " propagation failed"
690  << std::endl;
693  continue; //no sense to do matching
694  }
695 
696  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, tsof.globalPosition().eta() "
697  << tsof.globalPosition().eta();
698 
699  //checking if the propagated track is inside the OMTF range, TODO - tune the range!!!!!!!!!!!!!!!!!
700  //eta 0.7 is the beginning of the MB2, while 1.31 is mid of RE2 + some margin
701  if ((std::abs(tsof.globalPosition().eta()) >= 0.7) && (std::abs(tsof.globalPosition().eta()) <= 1.31)) {
702  LogTrace("l1tOmtfEventPrint")
703  << "CandidateSimMuonMatcher::match trackingParticle IS in OMTF region, matching to the omtfCands";
704  } else {
705  LogTrace("l1tOmtfEventPrint") << "trackingParticle NOT in OMTF region ";
706  continue;
707  }
708 
709  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
710  double ptGen = trackingParticle.pt();
711  if(ptGen >= deltaPhiVertexProp->GetXaxis()->GetXmax())
712  ptGen = deltaPhiVertexProp->GetXaxis()->GetXmax() - 0.01;
713 
714  deltaPhiVertexProp->Fill(ptGen, trackingParticle.momentum().phi() - tsof.globalPosition().phi());
715 */
716 
717  unsigned int iCand = 0;
718  for (auto& muonCand : muonCands) {
719  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive then
720  /*if(muonCand->hwQual() <= 1)
721  continue; */
722 
724  if (tsof.isValid()) {
725  result = match(muonCand, ghostBustedProcMuons.at(iCand), trackingParticle, tsof);
726  }
727  iCand++;
728 
730  matchingResults.push_back(result);
731  matched = true;
732  }
733  }
734 
735  if (!matched) { //we are adding result also if it there was no matching to any candidate
736  MatchingResult result(trackingParticle);
737  matchingResults.push_back(result);
738  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
739  }
740  }
741 
742  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
743 }
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
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
Disk BoundDisk
Definition: BoundDisk.h:54
std::vector< AlgoMuonPtr > AlgoMuons
Definition: AlgoMuon.h:183
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:182
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