CMS 3D CMS Logo

GlobalCosmicMuonTrajectoryBuilder.cc
Go to the documentation of this file.
1 
11 
14 
22 
23 using namespace std;
24 using namespace edm;
25 
26 //
27 // constructor
28 //
32  : theService(service),
33  theTrackerRecHitBuilderToken(
34  iC.esConsumes(edm::ESInputTag("", par.getParameter<string>("TrackerRecHitBuilder")))),
35  theMuonRecHitBuilderToken(iC.esConsumes(edm::ESInputTag("", par.getParameter<string>("MuonRecHitBuilder")))) {
36  ParameterSet smootherPSet = par.getParameter<ParameterSet>("SmootherParameters");
37  theSmoother = new CosmicMuonSmoother(smootherPSet, theService);
38 
39  ParameterSet trackMatcherPSet = par.getParameter<ParameterSet>("GlobalMuonTrackMatcher");
40  theTrackMatcher = new GlobalMuonTrackMatcher(trackMatcherPSet, theService);
41 
42  theTkTrackToken = iC.consumes<reco::TrackCollection>(par.getParameter<InputTag>("TkTrackCollectionLabel"));
43 
44  thePropagatorName = par.getParameter<string>("Propagator");
45  category_ = "Muon|RecoMuon|CosmicMuon|GlobalCosmicMuonTrajectoryBuilder";
46 }
47 
48 //
49 // destructor
50 //
51 
53  if (theSmoother)
54  delete theSmoother;
55  if (theTrackMatcher)
56  delete theTrackMatcher;
57 }
58 
59 //
60 // set Event
61 //
63  event.getByToken(theTkTrackToken, theTrackerTracks);
64 
65  // edm::Handle<std::vector<Trajectory> > handleTrackerTrajs;
66  // if ( event.getByLabel(theTkTrackLabel,handleTrackerTrajs) && handleTrackerTrajs.isValid() ) {
67  // tkTrajsAvailable = true;
68  // allTrackerTrajs = &*handleTrackerTrajs;
69  // LogInfo("GlobalCosmicMuonTrajectoryBuilder")
70  // << "Tk Trajectories Found! " << endl;
71  // } else {
72  // LogInfo("GlobalCosmicMuonTrajectoryBuilder")
73  // << "No Tk Trajectories Found! " << endl;
74  // tkTrajsAvailable = false;
75  // }
76 
79 }
80 
81 //
82 // reconstruct trajectories
83 //
86 
87  if (!theTrackerTracks.isValid()) {
88  LogTrace(category_) << "Tracker Track collection is invalid!!!";
89  return result;
90  }
91 
92  LogTrace(category_) << "Found " << theTrackerTracks->size() << " tracker Tracks";
93  if (theTrackerTracks->empty())
94  return result;
95 
96  vector<TrackCand> matched = match(muCand, theTrackerTracks);
97 
98  LogTrace(category_) << "TrackMatcher found " << matched.size() << "tracker tracks matched";
99 
100  if (matched.empty())
101  return result;
102  reco::TrackRef tkTrack = matched.front().second;
103 
104  if (tkTrack.isNull())
105  return result;
106  reco::TrackRef muTrack = muCand.second;
107 
108  ConstRecHitContainer muRecHits;
109 
110  if (muCand.first == nullptr || !muCand.first->isValid()) {
111  muRecHits = getTransientRecHits(*muTrack);
112  } else {
113  muRecHits = muCand.first->recHits();
114  }
115 
116  LogTrace(category_) << "mu RecHits: " << muRecHits.size();
117 
118  ConstRecHitContainer tkRecHits = getTransientRecHits(*tkTrack);
119 
120  // if ( !tkTrajsAvailable ) {
121  // tkRecHits = getTransientRecHits(*tkTrack);
122  // } else {
123  // tkRecHits = allTrackerTrajs->front().recHits();
124  // }
125 
126  ConstRecHitContainer hits; //= tkRecHits;
127  LogTrace(category_) << "tk RecHits: " << tkRecHits.size();
128 
129  // hits.insert(hits.end(), muRecHits.begin(), muRecHits.end());
130  // stable_sort(hits.begin(), hits.end(), DecreasingGlobalY());
131 
132  sortHits(hits, muRecHits, tkRecHits);
133 
134  // LogTrace(category_)<< "Used RecHits after sort: "<<hits.size()<<endl;;
135  // LogTrace(category_) <<utilities()->print(hits)<<endl;
136  // LogTrace(category_) << "== End of Used RecHits == "<<endl;
137 
139  *muTrack, *theService->trackingGeometry(), &*theService->magneticField());
141  *tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
142 
144  *muTrack, *theService->trackingGeometry(), &*theService->magneticField());
146  *tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
147 
148  TrajectoryStateOnSurface firstState1 =
149  (muonState1.globalPosition().y() > tkState1.globalPosition().y()) ? muonState1 : tkState1;
150  TrajectoryStateOnSurface firstState2 =
151  (muonState2.globalPosition().y() > tkState2.globalPosition().y()) ? muonState2 : tkState2;
152 
153  TrajectoryStateOnSurface firstState =
154  (firstState1.globalPosition().y() > firstState2.globalPosition().y()) ? firstState1 : firstState2;
155 
156  GlobalPoint front, back;
157  if (!hits.empty()) {
158  front = hits.front()->globalPosition();
159  back = hits.back()->globalPosition();
160  if ((front.perp() < 130 && fabs(front.z()) < 300) || (back.perp() < 130 && fabs(back.z()) < 300)) {
161  if (hits.front()->globalPosition().perp() > hits.back()->globalPosition().perp())
162  reverse(hits.begin(), hits.end());
164  *tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
166  *tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
167  firstState = (tkState1.globalPosition().perp() < tkState2.globalPosition().perp()) ? tkState1 : tkState2;
168  }
169  }
170  if (!firstState.isValid())
171  return result;
172  LogTrace(category_) << "firstTSOS pos: " << firstState.globalPosition() << "mom: " << firstState.globalMomentum();
173 
174  // begin refitting
175 
177  vector<Trajectory> refitted = theSmoother->trajectories(seed, hits, firstState);
178 
179  if (refitted.empty()) {
180  LogTrace(category_) << "smoothing trajectories fail";
181  refitted = theSmoother->fit(seed, hits, firstState); //FIXME
182  }
183 
184  if (refitted.empty()) {
185  LogTrace(category_) << "refit fail";
186  return result;
187  }
188 
189  auto myTraj = std::make_unique<Trajectory>(refitted.front());
190 
191  const std::vector<TrajectoryMeasurement>& mytms = myTraj->measurements();
192  LogTrace(category_) << "measurements in final trajectory " << mytms.size();
193  LogTrace(category_) << "Orignally there are " << tkTrack->found() << " tk rhs and " << muTrack->found() << " mu rhs.";
194 
195  if (mytms.size() <= tkTrack->found()) {
196  LogTrace(category_) << "insufficient measurements. skip... ";
197  return result;
198  }
199 
200  result.push_back(std::make_unique<MuonCandidate>(std::move(myTraj), muTrack, tkTrack));
201  LogTrace(category_) << "final global cosmic muon: ";
202  for (std::vector<TrajectoryMeasurement>::const_iterator itm = mytms.begin(); itm != mytms.end(); ++itm) {
203  LogTrace(category_) << "updated pos " << itm->updatedState().globalPosition() << "mom "
204  << itm->updatedState().globalMomentum();
205  }
206  return result;
207 }
208 
210  ConstRecHitContainer& muonHits,
211  ConstRecHitContainer& tkHits) {
212  if (tkHits.empty()) {
213  LogTrace(category_) << "No valid tracker hits";
214  return;
215  }
216  if (muonHits.empty()) {
217  LogTrace(category_) << "No valid muon hits";
218  return;
219  }
220 
221  ConstRecHitContainer::const_iterator frontTkHit = tkHits.begin();
222  ConstRecHitContainer::const_iterator backTkHit = tkHits.end() - 1;
223  while (!(*frontTkHit)->isValid() && frontTkHit != backTkHit) {
224  frontTkHit++;
225  }
226  while (!(*backTkHit)->isValid() && backTkHit != frontTkHit) {
227  backTkHit--;
228  }
229 
230  ConstRecHitContainer::const_iterator frontMuHit = muonHits.begin();
231  ConstRecHitContainer::const_iterator backMuHit = muonHits.end() - 1;
232  while (!(*frontMuHit)->isValid() && frontMuHit != backMuHit) {
233  frontMuHit++;
234  }
235  while (!(*backMuHit)->isValid() && backMuHit != frontMuHit) {
236  backMuHit--;
237  }
238 
239  if (frontTkHit == backTkHit) {
240  LogTrace(category_) << "No valid tracker hits";
241  return;
242  }
243  if (frontMuHit == backMuHit) {
244  LogTrace(category_) << "No valid muon hits";
245  return;
246  }
247 
248  GlobalPoint frontTkPos = (*frontTkHit)->globalPosition();
249  GlobalPoint backTkPos = (*backTkHit)->globalPosition();
250 
251  GlobalPoint frontMuPos = (*frontMuHit)->globalPosition();
252  GlobalPoint backMuPos = (*backMuHit)->globalPosition();
253 
254  //sort hits going from higher to lower positions
255  if (frontTkPos.y() < backTkPos.y()) { //check if tk hits order same direction
256  reverse(tkHits.begin(), tkHits.end());
257  }
258 
259  if (frontMuPos.y() < backMuPos.y()) {
260  reverse(muonHits.begin(), muonHits.end());
261  }
262 
263  // LogTrace(category_)<< "tkHits after sort: "<<tkHits.size()<<endl;;
264  // LogTrace(category_) <<utilities()->print(tkHits)<<endl;
265  // LogTrace(category_) << "== End of tkHits == "<<endl;
266 
267  // LogTrace(category_)<< "muonHits after sort: "<<muonHits.size()<<endl;;
268  // LogTrace(category_) <<utilities()->print(muonHits)<<endl;
269  // LogTrace(category_)<< "== End of muonHits == "<<endl;
270 
271  //separate muon hits into 2 different hemisphere
272  ConstRecHitContainer::iterator middlepoint = muonHits.begin();
273  bool insertInMiddle = false;
274 
275  for (ConstRecHitContainer::iterator ihit = muonHits.begin(); ihit != muonHits.end() - 1; ihit++) {
276  GlobalPoint ipos = (*ihit)->globalPosition();
277  GlobalPoint nextpos = (*(ihit + 1))->globalPosition();
278  if ((ipos - nextpos).mag() < 100.0)
279  continue;
280 
281  GlobalPoint middle((ipos.x() + nextpos.x()) / 2, (ipos.y() + nextpos.y()) / 2, (ipos.z() + nextpos.z()) / 2);
282  LogTrace(category_) << "ipos " << ipos << "nextpos" << nextpos << " middle " << middle << endl;
283  if ((middle.perp() < ipos.perp()) && (middle.perp() < nextpos.perp())) {
284  LogTrace(category_) << "found middlepoint" << endl;
285  middlepoint = ihit;
286  insertInMiddle = true;
287  break;
288  }
289  }
290 
291  //insert track hits in correct order
292  if (insertInMiddle) { //if tk hits should be sandwich
293  GlobalPoint jointpointpos = (*middlepoint)->globalPosition();
294  LogTrace(category_) << "jointpoint " << jointpointpos << endl;
295  if ((frontTkPos - jointpointpos).mag() >
296  (backTkPos - jointpointpos).mag()) { //check if tk hits order same direction
297  reverse(tkHits.begin(), tkHits.end());
298  }
299  muonHits.insert(middlepoint + 1, tkHits.begin(), tkHits.end());
300  hits = muonHits;
301  } else { // append at one end
302  if (frontTkPos.y() < frontMuPos.y()) { //insert at the end
303  LogTrace(category_) << "insert at the end " << frontTkPos << frontMuPos << endl;
304 
305  hits = muonHits;
306  hits.insert(hits.end(), tkHits.begin(), tkHits.end());
307  } else { //insert at the beginning
308  LogTrace(category_) << "insert at the beginning " << frontTkPos << frontMuPos << endl;
309  hits = tkHits;
310  hits.insert(hits.end(), muonHits.begin(), muonHits.end());
311  }
312  }
313 }
314 
316 
318  const reco::Track& track) const {
320 
321  auto hitCloner = static_cast<TkTransientTrackingRecHitBuilder const*>(theTrackerRecHitBuilder.product())->cloner();
323  track, *theService->trackingGeometry(), &*theService->magneticField());
324  for (trackingRecHit_iterator hit = track.recHitsBegin(); hit != track.recHitsEnd(); ++hit) {
325  if ((*hit)->isValid()) {
326  DetId recoid = (*hit)->geographicalId();
327  if (recoid.det() == DetId::Tracker) {
328  TrajectoryStateOnSurface predTsos =
329  theService->propagator(thePropagatorName)
330  ->propagate(currTsos, theService->trackingGeometry()->idToDet(recoid)->surface());
331  LogTrace(category_) << "predtsos " << predTsos.isValid();
332  if (predTsos.isValid()) {
333  currTsos = predTsos;
334  result.emplace_back(hitCloner(**hit, predTsos));
335  }
336  } else if (recoid.det() == DetId::Muon) {
337  result.push_back(theMuonRecHitBuilder->build(&**hit));
338  }
339  }
340  }
341  return result;
342 }
343 
344 std::vector<GlobalCosmicMuonTrajectoryBuilder::TrackCand> GlobalCosmicMuonTrajectoryBuilder::match(
345  const TrackCand& mu, const edm::Handle<reco::TrackCollection>& tktracks) {
346  std::vector<TrackCand> result;
347 
349  *(mu.second), *theService->trackingGeometry(), &*theService->magneticField());
351  *(mu.second), *theService->trackingGeometry(), &*theService->magneticField());
352  //build tracker TrackCands and pick the best match if size greater than 2
353  vector<TrackCand> tkTrackCands;
354  for (reco::TrackCollection::size_type i = 0; i < theTrackerTracks->size(); ++i) {
356  TrackCand tkCand = TrackCand((Trajectory*)nullptr, tkTrack);
357  tkTrackCands.push_back(tkCand);
358  LogTrace(category_) << "chisq is " << theTrackMatcher->match(mu, tkCand, 0, 0);
359  LogTrace(category_) << "d is " << theTrackMatcher->match(mu, tkCand, 1, 0);
360  LogTrace(category_) << "r_pos is " << theTrackMatcher->match(mu, tkCand, 2, 0);
361  }
362 
363  // now if only 1 tracker tracks, return it
364  if (tkTrackCands.size() <= 1) {
365  return tkTrackCands;
366  }
367 
368  // if there're many tracker tracks
369 
370  // if muon is only on one side
371  GlobalPoint innerPos = innerTsos.globalPosition();
372  GlobalPoint outerPos = outerTsos.globalPosition();
373 
374  if ((innerPos.basicVector().dot(innerTsos.globalMomentum().basicVector()) *
375  outerPos.basicVector().dot(outerTsos.globalMomentum().basicVector()) >
376  0)) {
377  GlobalPoint geoInnerPos = (innerPos.mag() < outerPos.mag()) ? innerPos : outerPos;
378  LogTrace(category_) << "geoInnerPos Mu " << geoInnerPos << endl;
379 
380  // if there're tracker tracks totally on the other half
381  // and there're tracker tracks on the same half
382  // remove the tracks on the other half
383  for (vector<TrackCand>::const_iterator itkCand = tkTrackCands.begin(); itkCand != tkTrackCands.end(); ++itkCand) {
384  reco::TrackRef tkTrack = itkCand->second;
385 
386  GlobalPoint tkInnerPos(tkTrack->innerPosition().x(), tkTrack->innerPosition().y(), tkTrack->innerPosition().z());
387  GlobalPoint tkOuterPos(tkTrack->outerPosition().x(), tkTrack->outerPosition().y(), tkTrack->outerPosition().z());
388  LogTrace(category_) << "tkTrack " << tkInnerPos << " " << tkOuterPos << endl;
389 
390  float closetDistance11 = (geoInnerPos - tkInnerPos).mag();
391  float closetDistance12 = (geoInnerPos - tkOuterPos).mag();
392  float closetDistance1 = (closetDistance11 < closetDistance12) ? closetDistance11 : closetDistance12;
393  LogTrace(category_) << "closetDistance1 " << closetDistance1 << endl;
394 
395  if (true || !isTraversing(*tkTrack)) {
396  bool keep = true;
397  for (vector<TrackCand>::const_iterator itkCand2 = tkTrackCands.begin(); itkCand2 != tkTrackCands.end();
398  ++itkCand2) {
399  if (itkCand2 == itkCand)
400  continue;
401  reco::TrackRef tkTrack2 = itkCand2->second;
402 
403  GlobalPoint tkInnerPos2(
404  tkTrack2->innerPosition().x(), tkTrack2->innerPosition().y(), tkTrack2->innerPosition().z());
405  GlobalPoint tkOuterPos2(
406  tkTrack2->outerPosition().x(), tkTrack2->outerPosition().y(), tkTrack2->outerPosition().z());
407  LogTrace(category_) << "tkTrack2 " << tkInnerPos2 << " " << tkOuterPos2 << endl;
408 
409  float farthestDistance21 = (geoInnerPos - tkInnerPos2).mag();
410  float farthestDistance22 = (geoInnerPos - tkOuterPos2).mag();
411  float farthestDistance2 = (farthestDistance21 > farthestDistance22) ? farthestDistance21 : farthestDistance22;
412  LogTrace(category_) << "farthestDistance2 " << farthestDistance2 << endl;
413 
414  if (closetDistance1 > farthestDistance2 - 1e-3) {
415  keep = false;
416  break;
417  }
418  }
419  if (keep)
420  result.push_back(*itkCand);
421  else
422  LogTrace(category_) << "The Track is on different hemisphere" << endl;
423  } else {
424  result.push_back(*itkCand);
425  }
426  }
427  if (result.empty()) {
428  //if all tk tracks on the other side, still keep them
429  result = tkTrackCands;
430  }
431  } else { // muon is traversing
432  result = tkTrackCands;
433  }
434 
435  // match muCand to tkTrackCands
436  vector<TrackCand> matched_trackerTracks = theTrackMatcher->match(mu, result);
437 
438  LogTrace(category_) << "TrackMatcher found " << matched_trackerTracks.size() << "tracker tracks matched";
439 
440  //now pick the best matched one
441  if (matched_trackerTracks.size() < 2) {
442  return matched_trackerTracks;
443  } else {
444  // in case of more than 1 tkTrack,
445  // select the best-one based on distance (matchOption==1)
446  // at innermost Mu hit surface. (surfaceOption == 0)
447  result.clear();
449 
450  double quality = 1e6;
451  double max_quality = 1e6;
452  for (vector<TrackCand>::const_iterator iter = matched_trackerTracks.begin(); iter != matched_trackerTracks.end();
453  iter++) {
454  quality = theTrackMatcher->match(mu, *iter, 1, 0);
455  LogTrace(category_) << " quality of tracker track is " << quality;
456  if (quality < max_quality) {
457  max_quality = quality;
458  bestMatch = (*iter);
459  }
460  }
461  LogTrace(category_) << " Picked tracker track with quality " << max_quality;
462  result.push_back(bestMatch);
463  return result;
464  }
465 }
466 
469  for (trackingRecHit_iterator hit = track.recHitsBegin(); hit != track.recHitsEnd(); ++hit) {
470  if ((*hit)->isValid()) {
471  firstValid = hit;
472  break;
473  }
474  }
475 
476  trackingRecHit_iterator lastValid;
477  for (trackingRecHit_iterator hit = track.recHitsEnd() - 1; hit != track.recHitsBegin() - 1; --hit) {
478  if ((*hit)->isValid()) {
479  lastValid = hit;
480  break;
481  }
482  }
483 
484  GlobalPoint posFirst = theService->trackingGeometry()->idToDet((*firstValid)->geographicalId())->position();
485 
486  GlobalPoint posLast = theService->trackingGeometry()->idToDet((*lastValid)->geographicalId())->position();
487 
488  GlobalPoint middle(
489  (posFirst.x() + posLast.x()) / 2, (posFirst.y() + posLast.y()) / 2, (posFirst.z() + posLast.z()) / 2);
490 
491  if ((middle.mag() < posFirst.mag()) && (middle.mag() < posLast.mag())) {
492  return true;
493  }
494  return false;
495 }
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
T perp() const
Definition: PV3DBase.h:69
edm::ESHandle< TransientTrackingRecHitBuilder > theTrackerRecHitBuilder
edm::EDGetTokenT< reco::TrackCollection > theTkTrackToken
TrajectoryStateOnSurface outerStateOnSurface(const reco::Track &tk, const TrackingGeometry &geom, const MagneticField *field, bool withErr=true)
T z() const
Definition: PV3DBase.h:61
edm::ESHandle< TransientTrackingRecHitBuilder > theMuonRecHitBuilder
std::vector< Track > TrackCollection
collection of Tracks
Definition: TrackFwd.h:14
TrajectoryContainer trajectories(const TrajectorySeed &) override
dummy implementation, unused in this class
uint16_t size_type
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:46
ConstRecHitContainer getTransientRecHits(const reco::Track &) const
GlobalCosmicMuonTrajectoryBuilder(const edm::ParameterSet &, const MuonServiceProxy *service, edm::ConsumesCollector &iC)
Constructor.
#define LogTrace(id)
TransientTrackingRecHit::ConstRecHitContainer ConstRecHitContainer
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
T const * product() const
Definition: ESHandle.h:86
GlobalPoint globalPosition() const
bool isTraversing(const reco::Track &tk) const
virtual RecHitPointer build(const TrackingRecHit *p) const =0
build a tracking rechit from an existing rechit
T mag() const
Definition: PV3DBase.h:64
void sortHits(ConstRecHitContainer &, ConstRecHitContainer &, ConstRecHitContainer &)
std::vector< Trajectory > fit(const Trajectory &) const
bool isNull() const
Checks for null.
Definition: Ref.h:235
const BasicVectorType & basicVector() const
Definition: PV3DBase.h:53
double match(const TrackCand &sta, const TrackCand &track, int matchOption=0, int surfaceOption=1) const
std::vector< ConstRecHitPointer > ConstRecHitContainer
Definition: DetId.h:17
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
std::vector< std::unique_ptr< MuonCandidate > > CandidateContainer
Definition: MuonCandidate.h:18
def bestMatch(object, matchCollection)
Definition: deltar.py:138
GlobalVector globalMomentum() const
std::vector< TrackCand > match(const TrackCand &, const edm::Handle< reco::TrackCollection > &)
check if tk and muon Tracks are matched
bool isValid() const
Definition: HandleBase.h:70
const edm::ESGetToken< TransientTrackingRecHitBuilder, TransientRecHitRecord > theTrackerRecHitBuilderToken
void setEvent(const edm::Event &) override
pass the Event to the algo at each event
HLT enums.
static int position[264][3]
Definition: ReadPGInfo.cc:289
TrajectoryContainer trajectories(const Trajectory &traj) const override
std::pair< const Trajectory *, reco::TrackRef > TrackCand
const edm::ESGetToken< TransientTrackingRecHitBuilder, TransientRecHitRecord > theMuonRecHitBuilderToken
string quality
T dot(const Basic3DVector &rh) const
Scalar product, or "dot" product, with a vector of same type.
def move(src, dest)
Definition: eostools.py:511
edm::Handle< reco::TrackCollection > theTrackerTracks
Definition: event.py:1
TrajectoryStateOnSurface innerStateOnSurface(const reco::Track &tk, const TrackingGeometry &geom, const MagneticField *field, bool withErr=true)