CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 
375  const edm::SimVertexContainer* simVertices) {
377  int vtxInd = simTrack.vertIndex();
378  if (vtxInd < 0) {
379  edm::LogImportant("l1tOmtfEventPrint") << "Track with no vertex, defaulting to (0,0,0)";
380  } else {
381  simVertex = simVertices->at(vtxInd);
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  //for displaced muons in H2ll
445  double treshold = 0.15; //pt > 30
446  if (simTrack.momentum().pt() <
447  10) //TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! tune the threshold!!!!!!
448  treshold = 0.3;
449  else if (simTrack.momentum().pt() <
450  30) //TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! tune the threshold!!!!!!
451  treshold = 0.22;
452 
453  if (std::abs(result.deltaPhi - mean) < treshold && std::abs(result.deltaEta) < 0.3)
455 
456  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match: simTrack type " << simTrack.type() << " pt "
457  << std::setw(8) << simTrack.momentum().pt() << " eta " << std::setw(8)
458  << simTrack.momentum().eta() << " phi " << std::setw(8) << simTrack.momentum().phi()
459  << " propagation eta " << std::setw(8) << tsof.globalPosition().eta() << " phi "
460  << tsof.globalPosition().phi() << "\n muonCand pt " << std::setw(8)
461  << muonCand->hwPt() << " candGloablEta " << std::setw(8) << candGloablEta
462  << " candGlobalPhi " << std::setw(8) << candGlobalPhi << " hwQual "
463  << muonCand->hwQual() << " deltaEta " << std::setw(8) << result.deltaEta
464  << " deltaPhi " << std::setw(8) << result.deltaPhi << " sigma " << std::setw(8)
465  << sigma << " Likelihood " << std::setw(8) << result.matchingLikelihood << " result "
466  << (short)result.result << std::endl;
467  }
468 
469  return result;
470 }
471 
473  const AlgoMuonPtr& procMuon,
474  const TrackingParticle& trackingParticle,
475  TrajectoryStateOnSurface& tsof) {
476  MatchingResult result(trackingParticle);
477 
478  double candGloablEta = muonCand->hwEta() * 0.010875;
479  //if (std::abs(trackingParticle.momentum().eta() - candGloablEta) < 0.3) //has no sense for displaced muons
480  {
481  double candGlobalPhi = omtfConfig->calcGlobalPhi(muonCand->hwPhi(), muonCand->processor());
482  candGlobalPhi = hwGmtPhiToGlobalPhi(candGlobalPhi);
483 
484  if (candGlobalPhi > M_PI)
485  candGlobalPhi = candGlobalPhi - (2. * M_PI);
486 
487  result.deltaPhi = foldPhi(tsof.globalPosition().phi() - candGlobalPhi);
488  result.deltaEta = tsof.globalPosition().eta() - candGloablEta;
489 
490  result.propagatedPhi = tsof.globalPosition().phi();
491  result.propagatedEta = tsof.globalPosition().eta();
492 
493  double mean = 0;
494  double sigma = 1;
495  //if(!fillMean)
496  {
497  auto ptBin = deltaPhiPropCandMean->FindBin(trackingParticle.pt());
498 
499  mean = deltaPhiPropCandMean->GetBinContent(ptBin);
500  sigma = deltaPhiPropCandStdDev->GetBinContent(ptBin);
501  }
502 
503  result.matchingLikelihood = normal_pdf(result.deltaPhi, mean, sigma); //TODO temporary solution
504 
505  result.muonCand = muonCand;
506  result.procMuon = procMuon;
507 
508  double treshold = 6. * sigma;
509  if (trackingParticle.pt() > 20)
510  treshold = 7. * sigma;
511  if (trackingParticle.pt() > 100)
512  treshold = 20. * sigma;
513 
514  if (std::abs(result.deltaPhi - mean) < treshold && std::abs(result.deltaEta) < 0.3)
516 
517  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match: trackingParticle type "
518  << trackingParticle.pdgId() << " pt " << std::setw(8) << trackingParticle.pt()
519  << " eta " << std::setw(8) << trackingParticle.momentum().eta() << " phi "
520  << std::setw(8) << trackingParticle.momentum().phi() << " propagation eta "
521  << std::setw(8) << tsof.globalPosition().eta() << " phi "
522  << tsof.globalPosition().phi() << " muonCand pt " << std::setw(8) << muonCand->hwPt()
523  << " candGloablEta " << std::setw(8) << candGloablEta << " candGlobalPhi "
524  << std::setw(8) << candGlobalPhi << " hwQual " << muonCand->hwQual() << " deltaEta "
525  << std::setw(8) << result.deltaEta << " deltaPhi " << std::setw(8) << result.deltaPhi
526  << " Likelihood " << std::setw(8) << result.matchingLikelihood << " result "
527  << (short)result.result << std::endl;
528  }
529 
530  return result;
531 }
532 
533 std::vector<MatchingResult> CandidateSimMuonMatcher::cleanMatching(std::vector<MatchingResult> matchingResults,
534  std::vector<const l1t::RegionalMuonCand*>& muonCands,
535  AlgoMuons& ghostBustedProcMuons) {
536  //Cleaning the matching
537  std::sort(
538  matchingResults.begin(), matchingResults.end(), [](const MatchingResult& a, const MatchingResult& b) -> bool {
539  return a.matchingLikelihood > b.matchingLikelihood;
540  });
541 
542  for (unsigned int i1 = 0; i1 < matchingResults.size(); i1++) {
544  for (unsigned int i2 = i1 + 1; i2 < matchingResults.size(); i2++) {
545  if ((matchingResults[i1].trackingParticle &&
546  matchingResults[i1].trackingParticle == matchingResults[i2].trackingParticle) ||
547  (matchingResults[i1].simTrack && matchingResults[i1].simTrack == matchingResults[i2].simTrack) ||
548  (matchingResults[i1].muonCand == matchingResults[i2].muonCand)) {
549  //if matchingResults[i1].muonCand == false, then it is also OK here
551  }
552  }
553  }
554  }
555 
556  std::vector<MatchingResult> cleanedMatchingResults;
557  for (auto& matchingResult : matchingResults) {
558  if (matchingResult.result == MatchingResult::ResultType::matched || matchingResult.muonCand == nullptr)
559  //adding also the simTracks that are not matched at all, before it is assured that they are not duplicates
560  cleanedMatchingResults.push_back(matchingResult);
561  if (matchingResult.result == MatchingResult::ResultType::matched) {
562  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
563  if(fillMean) {
564  double ptGen = matchingResult.genPt;
565  deltaPhiPropCandMean->Fill(ptGen, matchingResult.deltaPhi); //filling overflow is ok here
566  deltaPhiPropCandStdDev->Fill(ptGen, matchingResult.deltaPhi * matchingResult.deltaPhi);
567  }*/
568  }
569  }
570 
571  //adding the muonCand-s that were not matched, i.e. in order to analyze them later
572  unsigned int iCand = 0;
573  for (auto& muonCand : muonCands) {
574  bool isMatched = false;
575  for (auto& matchingResult : cleanedMatchingResults) {
576  if (matchingResult.muonCand == muonCand) {
577  isMatched = true;
578  break;
579  }
580  }
581 
582  if (!isMatched) {
584  result.muonCand = muonCand;
585  result.procMuon = ghostBustedProcMuons.at(iCand);
586  cleanedMatchingResults.push_back(result);
587  }
588  iCand++;
589  }
590 
591  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::cleanMatching:" << __LINE__
592  << " cleanedMatchingResults:" << std::endl;
593  for (auto& result : cleanedMatchingResults) {
594  if (result.trackingParticle || result.simTrack)
595  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::cleanMatching:" << __LINE__ << " simTrack type "
596  << result.pdgId << " pt " << std::setw(8) << result.genPt << " eta " << std::setw(8)
597  << result.genEta << " phi " << std::setw(8) << result.genPhi;
598  else
599  LogTrace("l1tOmtfEventPrint") << "no matched track ";
600 
601  if (result.muonCand) {
602  LogTrace("l1tOmtfEventPrint") << " muonCand pt " << std::setw(8) << result.muonCand->hwPt() << " hwQual "
603  << result.muonCand->hwQual() << " hwEta " << result.muonCand->hwEta()
604  << " deltaEta " << std::setw(8) << result.deltaEta << " deltaPhi " << std::setw(8)
605  << result.deltaPhi << " Likelihood " << std::setw(8) << result.matchingLikelihood
606  << " result " << (short)result.result;
607  LogTrace("l1tOmtfEventPrint") << " procMuon " << *(result.procMuon) << std::endl;
608  } else
609  LogTrace("l1tOmtfEventPrint") << " no muonCand "
610  << " result " << (short)result.result << std::endl;
611  }
612  LogTrace("l1tOmtfEventPrint") << " " << std::endl;
613 
614  return cleanedMatchingResults;
615 }
616 
617 std::vector<MatchingResult> CandidateSimMuonMatcher::match(std::vector<const l1t::RegionalMuonCand*>& muonCands,
618  AlgoMuons& ghostBustedProcMuons,
620  const edm::SimVertexContainer* simVertices,
621  std::function<bool(const SimTrack&)> const& simTrackFilter) {
622  std::vector<MatchingResult> matchingResults;
623 
624  for (auto& simTrack : *simTracks) {
625  if (!simTrackFilter(simTrack))
626  continue;
627 
628  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, simTrack type " << std::setw(3) << simTrack.type()
629  << " pt " << std::setw(9) << simTrack.momentum().pt() << " eta " << std::setw(9)
630  << simTrack.momentum().eta() << " phi " << std::setw(9) << simTrack.momentum().phi()
631  << std::endl;
632 
633  bool matched = false;
634 
635  TrajectoryStateOnSurface tsof = propagate(simTrack, simVertices);
636  if (!tsof.isValid()) { //no sense to do matching
639  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " propagation failed: genPt " << result.genPt
640  << " genEta " << result.genEta << " eventId " << simTrack.eventId().event()
641  << std::endl;
642 
643  matchingResults.push_back(result);
644  } else {
645  //checking if the propagated track is inside the OMTF range, TODO - tune the range!!!!!!!!!!!!!!!!!
646  //eta 0.7 is the beginning of the MB2,
647  //the eta range wider than the nominal OMTF region is needed, as in any case muons outside this region are seen by the OMTF
648  //so it better to train the nn suich that is able to measure its pt, as it may affect the rate
649  if ((std::abs(tsof.globalPosition().eta()) >= 0.7) && (std::abs(tsof.globalPosition().eta()) <= 1.31)) {
650  LogTrace("l1tOmtfEventPrint")
651  << "CandidateSimMuonMatcher::match simTrack IS in OMTF region, matching to the omtfCands";
652  } else {
653  LogTrace("l1tOmtfEventPrint") << "simTrack NOT in OMTF region ";
654  continue;
655  }
656 
657  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
658  double ptGen = simTrack.momentum().pt();
659  if(ptGen >= deltaPhiVertexProp->GetXaxis()->GetXmax())
660  ptGen = deltaPhiVertexProp->GetXaxis()->GetXmax() - 0.01;
661 
662  deltaPhiVertexProp->Fill(ptGen, simTrack.momentum().phi() - tsof.globalPosition().phi());*/
663 
664  unsigned int iCand = 0;
665  for (auto& muonCand : muonCands) {
666  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive
667  //if(muonCand->hwQual() > 1)
668  {
670  if (tsof.isValid()) {
671  result = match(muonCand, ghostBustedProcMuons.at(iCand), simTrack, tsof);
672  }
673  int vtxInd = simTrack.vertIndex();
674  if (vtxInd >= 0) {
675  result.simVertex = &(simVertices->at(
676  vtxInd)); //TODO ?????? something strange is here, was commented in the previous version
677  }
679  matchingResults.push_back(result);
680  matched = true;
681  }
682  }
683  iCand++;
684  }
685 
686  if (!matched) { //we are adding also if it was not matching to any candidate
688  matchingResults.push_back(result);
689  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
690  }
691  }
692  }
693 
694  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
695 }
696 
697 std::vector<MatchingResult> CandidateSimMuonMatcher::match(
698  std::vector<const l1t::RegionalMuonCand*>& muonCands,
699  AlgoMuons& ghostBustedProcMuons,
701  std::function<bool(const TrackingParticle&)> const& simTrackFilter) {
702  std::vector<MatchingResult> matchingResults;
703  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match trackingParticles->size() "
704  << trackingParticles->size() << std::endl;
705 
706  for (auto& trackingParticle : *trackingParticles) {
707  //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;
708 
709  if (simTrackFilter(trackingParticle) == false)
710  continue;
711 
712  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, trackingParticle type " << std::setw(3)
713  << trackingParticle.pdgId() << " pt " << std::setw(9) << trackingParticle.pt()
714  << " eta " << std::setw(9) << trackingParticle.momentum().eta() << " phi "
715  << std::setw(9) << trackingParticle.momentum().phi() << std::endl;
716 
717  bool matched = false;
718 
719  TrajectoryStateOnSurface tsof = propagate(trackingParticle);
720  if (!tsof.isValid()) {
721  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match:" << __LINE__ << " propagation failed"
722  << std::endl;
725  continue; //no sense to do matching
726  }
727 
728  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::match, tsof.globalPosition().eta() "
729  << tsof.globalPosition().eta();
730 
731  //checking if the propagated track is inside the OMTF range, TODO - tune the range!!!!!!!!!!!!!!!!!
732  //eta 0.7 is the beginning of the MB2, while 1.31 is mid of RE2 + some margin
733  if ((std::abs(tsof.globalPosition().eta()) >= 0.7) && (std::abs(tsof.globalPosition().eta()) <= 1.31)) {
734  LogTrace("l1tOmtfEventPrint")
735  << "CandidateSimMuonMatcher::match trackingParticle IS in OMTF region, matching to the omtfCands";
736  } else {
737  LogTrace("l1tOmtfEventPrint") << "trackingParticle NOT in OMTF region ";
738  continue;
739  }
740 
741  /* TODO fix if filling of the deltaPhiPropCandMean and deltaPhiPropCandStdDev is needed
742  double ptGen = trackingParticle.pt();
743  if(ptGen >= deltaPhiVertexProp->GetXaxis()->GetXmax())
744  ptGen = deltaPhiVertexProp->GetXaxis()->GetXmax() - 0.01;
745 
746  deltaPhiVertexProp->Fill(ptGen, trackingParticle.momentum().phi() - tsof.globalPosition().phi());
747  */
748 
749  unsigned int iCand = 0;
750  for (auto& muonCand : muonCands) {
751  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive then
752  /*if(muonCand->hwQual() <= 1)
753  continue; */
754 
756  if (tsof.isValid()) {
757  result = match(muonCand, ghostBustedProcMuons.at(iCand), trackingParticle, tsof);
758  }
759  iCand++;
760 
762  matchingResults.push_back(result);
763  matched = true;
764  }
765  }
766 
767  if (!matched) { //we are adding result also if it there was no matching to any candidate
768  MatchingResult result(trackingParticle);
769  matchingResults.push_back(result);
770  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
771  }
772  }
773 
774  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
775 }
776 
777 std::vector<MatchingResult> CandidateSimMuonMatcher::matchSimple(
778  std::vector<const l1t::RegionalMuonCand*>& muonCands,
779  AlgoMuons& ghostBustedProcMuons,
781  const edm::SimVertexContainer* simVertices,
782  std::function<bool(const SimTrack&)> const& simTrackFilter) {
783  std::vector<MatchingResult> matchingResults;
784 
785  for (auto& simTrack : *simTracks) {
786  if (!simTrackFilter(simTrack))
787  continue;
788 
789  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::matchSimple: simTrack type " << std::setw(3)
790  << simTrack.type() << " pt " << std::setw(9) << simTrack.momentum().pt() << " eta "
791  << std::setw(9) << simTrack.momentum().eta() << " phi " << std::setw(9)
792  << simTrack.momentum().phi() << std::endl;
793 
794  bool matched = false;
795 
796  unsigned int iCand = 0;
797  for (auto& muonCand : muonCands) {
798  //dropping very low quality candidates, as they are fakes usually - but it has no sense, then the results are not conclusive
799  //if(muonCand->hwQual() > 1)
800  {
802 
803  double candGloablEta = muonCand->hwEta() * 0.010875;
804  double candGlobalPhi = omtfConfig->calcGlobalPhi(muonCand->hwPhi(), muonCand->processor());
805  candGlobalPhi = hwGmtPhiToGlobalPhi(candGlobalPhi);
806 
807  if (candGlobalPhi > M_PI)
808  candGlobalPhi = candGlobalPhi - (2. * M_PI);
809 
810  result.deltaPhi = foldPhi(result.genPhi - candGlobalPhi);
811  result.deltaEta = result.genEta - candGloablEta;
812 
813  result.propagatedPhi = 0;
814  result.propagatedEta = 0;
815 
816  result.muonCand = muonCand;
817  result.procMuon = ghostBustedProcMuons.at(iCand);
818 
819  //TODO histogram can be used, like in the usercode/L1MuonAnalyzer MuonMatcher::matchWithoutPorpagation
820  //for prompt muons
821  /*double treshold = 0.3;
822  if (simTrack.momentum().pt() < 5)
823  treshold = 1.5;
824  else if (simTrack.momentum().pt() < 8)
825  treshold = 0.8;
826  else if (simTrack.momentum().pt() < 10)
827  treshold = 0.6;
828  else if (simTrack.momentum().pt() < 20)
829  treshold = 0.5;*/
830 
831  //for displaced muons
832  double treshold = 0.7;
833  if (simTrack.momentum().pt() < 5)
834  treshold = 1.5;
835  else if (simTrack.momentum().pt() < 10)
836  treshold = 1.0;
837  else if (simTrack.momentum().pt() < 20)
838  treshold = 0.7;
839 
840  if (std::abs(result.deltaPhi) < treshold && std::abs(result.deltaEta) < 0.5) {
842  //matchingLikelihood is needed in the cleanMatching, so we put something
843  if (std::abs(result.deltaPhi) < 0.001)
844  result.matchingLikelihood = 1. / 0.001;
845  else
846  result.matchingLikelihood = 1. / std::abs(result.deltaPhi);
847  }
848 
849  LogTrace("l1tOmtfEventPrint") << "CandidateSimMuonMatcher::matchSimple: simTrack type " << simTrack.type()
850  << " pt " << std::setw(8) << simTrack.momentum().pt() << " eta " << std::setw(8)
851  << simTrack.momentum().eta() << " phi " << std::setw(8)
852  << simTrack.momentum().phi() << "\n muonCand pt " << std::setw(8)
853  << muonCand->hwPt() << " candGloablEta " << std::setw(8) << candGloablEta
854  << " candGlobalPhi " << std::setw(8) << candGlobalPhi << " hwQual "
855  << muonCand->hwQual() << " deltaEta " << std::setw(8) << result.deltaEta
856  << " deltaPhi " << std::setw(8) << result.deltaPhi << " matchingLikelihood "
857  << result.matchingLikelihood << " result " << (short)result.result << std::endl;
858 
859  int vtxInd = simTrack.vertIndex();
860  if (vtxInd >= 0) {
861  result.simVertex = &(
862  simVertices->at(vtxInd)); //TODO ?????? something strange is here, was commented in the previous version
863  }
865  matchingResults.push_back(result);
866  matched = true;
867  }
868  }
869  iCand++;
870  }
871 
872  if (!matched) { //we are adding also if it was not matched to any candidate
874  matchingResults.push_back(result);
875  LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " no matching candidate found" << std::endl;
876  }
877  }
878 
879  return cleanMatching(matchingResults, muonCands, ghostBustedProcMuons);
880 }
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:232
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