CMS 3D CMS Logo

QuickTrackAssociatorByHitsImpl.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <fstream>
3 
5 
7 
11 
13 
14 //
15 // Use the unnamed namespace for utility functions only used in this file
16 //
17 namespace {
18  //
19  // All of these functions are pretty straightforward but the implementation is type dependent.
20  // The templated methods call these for the type specific parts and the compiler will resolve
21  // the type and call the correct overload.
22  //
23 
24  template <class T_element>
25  size_t collectionSize(const edm::RefToBaseVector<T_element>& collection) {
26  return collection.size();
27  }
28 
29  template <class T_element>
30  size_t collectionSize(const edm::Handle<T_element>& hCollection) {
31  return hCollection->size();
32  }
33 
34  template <class T_element>
35  size_t collectionSize(const edm::RefVector<T_element>& collection) {
36  return collection.size();
37  }
38 
39  const reco::Track* getTrackAt(const edm::RefToBaseVector<reco::Track>& trackCollection, size_t index) {
40  return &*trackCollection[index]; // pretty obscure dereference
41  }
42 
43  const reco::Track* getTrackAt(const edm::Handle<edm::View<reco::Track> >& pTrackCollection, size_t index) {
44  return &(*pTrackCollection.product())[index];
45  }
46 
47  const TrackingParticle* getTrackingParticleAt(const edm::Handle<TrackingParticleCollection>& pCollection,
48  size_t index) {
49  return &(*pCollection.product())[index];
50  }
51 
53  size_t index) {
54  return &*collection[index];
55  }
56 
58  return trackCollection[index];
59  }
60 
61  edm::RefToBase<reco::Track> getRefToTrackAt(const edm::Handle<edm::View<reco::Track> >& pTrackCollection,
62  size_t index) {
63  return edm::RefToBase<reco::Track>(pTrackCollection, index);
64  }
65 
66  edm::Ref<TrackingParticleCollection> getRefToTrackingParticleAt(
67  const edm::Handle<TrackingParticleCollection>& pCollection, size_t index) {
68  return edm::Ref<TrackingParticleCollection>(pCollection, index);
69  }
70 
71  edm::Ref<TrackingParticleCollection> getRefToTrackingParticleAt(
73  return collection[index];
74  }
75 
77  keys.reserve(collection.size());
78  for (const auto& ref : collection) {
79  keys.insert(ref.key());
80  }
81  }
82 
83  template <typename Coll>
84  void checkClusterMapProductID(const ClusterTPAssociation& clusterToTPMap, const Coll& collection) {
85  clusterToTPMap.checkMappedProductID(collection.id());
86  }
87 
88  template <typename Coll>
89  void checkClusterMapProductID(const TrackerHitAssociator& hitAssociator, const Coll& collection) {}
90 
91 } // namespace
92 
94  std::unique_ptr<const TrackerHitAssociator> hitAssoc,
95  const ClusterTPAssociation* clusterToTPMap,
96 
97  bool absoluteNumberOfHits,
98  double qualitySimToReco,
99  double puritySimToReco,
100  double pixelHitWeight,
101  double cutRecoToSim,
102  bool threeHitTracksAreSpecial,
103  SimToRecoDenomType simToRecoDenominator)
104  : productGetter_(&productGetter),
105  hitAssociator_(std::move(hitAssoc)),
106  clusterToTPMap_(clusterToTPMap),
107  qualitySimToReco_(qualitySimToReco),
108  puritySimToReco_(puritySimToReco),
109  pixelHitWeight_(pixelHitWeight),
110  cutRecoToSim_(cutRecoToSim),
111  simToRecoDenominator_(simToRecoDenominator),
112  threeHitTracksAreSpecial_(threeHitTracksAreSpecial),
113  absoluteNumberOfHits_(absoluteNumberOfHits) {}
114 
116  const edm::Handle<edm::View<reco::Track> >& trackCollectionHandle,
117  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const {
118  // Only pass the one that was successfully created to the templated method.
119  if (not clusterToTPMap_)
121  trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *hitAssociator_);
122  else
124  trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *clusterToTPMap_);
125 }
126 
128  const edm::Handle<edm::View<reco::Track> >& trackCollectionHandle,
129  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const {
130  // Only pass the one that was successfully created to the templated method.
131  if (not clusterToTPMap_)
133  trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *hitAssociator_);
134  else
136  trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *clusterToTPMap_);
137 }
138 
142  // Only pass the one that was successfully created to the templated method.
143  if (not clusterToTPMap_)
145  else {
147  fillKeys(tpKeys, trackingParticleCollection);
149  }
150 }
151 
155  // Only pass the one that was successfully created to the templated method.
156  if (not clusterToTPMap_)
158  else {
160  fillKeys(tpKeys, trackingParticleCollection);
162  }
163 }
164 
165 template <class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
167  const T_TrackCollection& trackCollection,
168  const T_TrackingParticleCollection& trackingParticleCollection,
169  const TrackingParticleRefKeySet* trackingParticleKeys,
170  T_hitOrClusterAssociator hitOrClusterAssociator) const {
172  if (::collectionSize(trackingParticleCollection) == 0)
173  return returnValue;
174 
175  checkClusterMapProductID(hitOrClusterAssociator, trackingParticleCollection);
176 
177  size_t collectionSize = ::collectionSize(trackCollection); // Delegate away type specific part
178 
179  for (size_t i = 0; i < collectionSize; ++i) {
180  const reco::Track* pTrack = ::getTrackAt(
181  trackCollection, i); // Get a normal pointer for ease of use. This part is type specific so delegate.
182 
183  // The return of this function has first as the index and second as the number of associated hits
184  std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > trackingParticleQualityPairs =
185  associateTrack(hitOrClusterAssociator,
187  trackingParticleKeys,
188  pTrack->recHitsBegin(),
189  pTrack->recHitsEnd());
190 
191  // int nt = 0;
192  for (auto iTrackingParticleQualityPair = trackingParticleQualityPairs.begin();
193  iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
194  ++iTrackingParticleQualityPair) {
195  const edm::Ref<TrackingParticleCollection>& trackingParticleRef = iTrackingParticleQualityPair->first;
196  double numberOfSharedClusters = iTrackingParticleQualityPair->second;
197  double numberOfValidTrackClusters = weightedNumberOfTrackClusters(*pTrack, hitOrClusterAssociator);
198 
199  if (numberOfSharedClusters == 0.0)
200  continue; // No point in continuing if there was no association
201 
202  //if electron subtract double counting
203  if (abs(trackingParticleRef->pdgId()) == 11 &&
204  (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1) {
205  numberOfSharedClusters -=
206  getDoubleCount(hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef);
207  }
208 
209  double quality;
211  quality = numberOfSharedClusters;
212  else if (numberOfValidTrackClusters != 0.0)
213  quality = numberOfSharedClusters / numberOfValidTrackClusters;
214  else
215  quality = 0;
216  if (quality > cutRecoToSim_ &&
217  !(threeHitTracksAreSpecial_ && pTrack->numberOfValidHits() == 3 && numberOfSharedClusters < 3.0)) {
218  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
219  returnValue.insert(::getRefToTrackAt(trackCollection, i), std::make_pair(trackingParticleRef, quality));
220  }
221  }
222  }
223  returnValue.post_insert();
224  return returnValue;
225 }
226 
227 template <class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
229  const T_TrackCollection& trackCollection,
230  const T_TrackingParticleCollection& trackingParticleCollection,
231  const TrackingParticleRefKeySet* trackingParticleKeys,
232  T_hitOrClusterAssociator hitOrClusterAssociator) const {
234  if (::collectionSize(trackingParticleCollection) == 0)
235  return returnValue;
236 
237  checkClusterMapProductID(hitOrClusterAssociator, trackingParticleCollection);
238 
239  size_t collectionSize = ::collectionSize(trackCollection); // Delegate away type specific part
240 
241  for (size_t i = 0; i < collectionSize; ++i) {
242  const reco::Track* pTrack = ::getTrackAt(
243  trackCollection, i); // Get a normal pointer for ease of use. This part is type specific so delegate.
244 
245  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
246  std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > trackingParticleQualityPairs =
247  associateTrack(hitOrClusterAssociator,
249  trackingParticleKeys,
250  pTrack->recHitsBegin(),
251  pTrack->recHitsEnd());
252 
253  // int nt = 0;
254  for (auto iTrackingParticleQualityPair = trackingParticleQualityPairs.begin();
255  iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
256  ++iTrackingParticleQualityPair) {
257  const edm::Ref<TrackingParticleCollection>& trackingParticleRef = iTrackingParticleQualityPair->first;
258  double numberOfSharedClusters = iTrackingParticleQualityPair->second;
259  double numberOfValidTrackClusters = weightedNumberOfTrackClusters(*pTrack, hitOrClusterAssociator);
260  size_t numberOfSimulatedHits = 0; // Set a few lines below, but only if required.
261 
262  if (numberOfSharedClusters == 0.0)
263  continue; // No point in continuing if there was no association
264 
266  (numberOfSharedClusters < 3.0 &&
267  threeHitTracksAreSpecial_)) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
268  {
269  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
270  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
271  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
272  // hits in the tracker.
273  numberOfSimulatedHits = trackingParticleRef->numberOfTrackerHits();
274  }
275 
276  //if electron subtract double counting
277  if (abs(trackingParticleRef->pdgId()) == 11 &&
278  (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1) {
279  numberOfSharedClusters -=
280  getDoubleCount(hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef);
281  }
282 
283  double purity = numberOfSharedClusters / numberOfValidTrackClusters;
284  double quality;
286  quality = numberOfSharedClusters;
287  else if (simToRecoDenominator_ == denomsim && numberOfSimulatedHits != 0)
288  quality = numberOfSharedClusters / static_cast<double>(numberOfSimulatedHits);
289  else if (simToRecoDenominator_ == denomreco && numberOfValidTrackClusters != 0)
290  quality = purity;
291  else
292  quality = 0;
293 
294  if (quality > qualitySimToReco_ &&
295  !(threeHitTracksAreSpecial_ && numberOfSimulatedHits == 3 && numberOfSharedClusters < 3.0) &&
296  (absoluteNumberOfHits_ || (purity > puritySimToReco_))) {
297  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
298  returnValue.insert(trackingParticleRef, std::make_pair(::getRefToTrackAt(trackCollection, i), quality));
299  }
300  }
301  }
302  returnValue.post_insert();
303  return returnValue;
304 }
305 
306 template <typename T_TPCollection, typename iter>
307 std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > QuickTrackAssociatorByHitsImpl::associateTrack(
309  const T_TPCollection& trackingParticles,
310  const TrackingParticleRefKeySet* trackingParticleKeys,
311  iter begin,
312  iter end) const {
313  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the weighted number of associated hits as "second"
314  std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > returnValue;
315 
316  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
317  // Most reco hits will probably have come from the same sim track, so the number of entries in this vector should be fewer than the
318  // number of reco hits. The pair::second entries should add up to the total number of reco hits though.
319  std::vector<std::pair<SimTrackIdentifiers, double> > hitIdentifiers =
321 
322  // Loop over the TrackingParticles
323  size_t collectionSize = ::collectionSize(trackingParticles);
324 
325  for (size_t i = 0; i < collectionSize; ++i) {
326  const TrackingParticle* pTrackingParticle = getTrackingParticleAt(trackingParticles, i);
327 
328  // Historically there was a requirement that pTrackingParticle->numberOfHits() > 0
329  // However, in TrackingTruthAccumulator, the numberOfHits is calculated from a subset
330  // of the SimHits of the SimTracks of a TrackingParticle (essentially limiting the
331  // processType and particleType to those of the "first" hit, and particleType to the pdgId of the SimTrack).
332  // But, here the association between tracks and TrackingParticles is done with *all* the hits of
333  // TrackingParticle, so we should not rely on the numberOfHits() calculated with a subset of SimHits.
334 
335  double numberOfAssociatedHits = 0;
336  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
337  // the number of reco hits associated to that sim track to the total number of associated hits.
338  for (const auto& identifierCountPair : hitIdentifiers) {
339  if (trackingParticleContainsIdentifier(pTrackingParticle, identifierCountPair.first))
340  numberOfAssociatedHits += identifierCountPair.second;
341  }
342 
343  if (numberOfAssociatedHits > 0) {
344  returnValue.push_back(std::make_pair(getRefToTrackingParticleAt(trackingParticles, i), numberOfAssociatedHits));
345  }
346  }
347 
348  return returnValue;
349 }
350 
351 template <typename T_TPCollection, typename iter>
352 std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > QuickTrackAssociatorByHitsImpl::associateTrack(
353  const ClusterTPAssociation& clusterToTPMap,
354  const T_TPCollection& trackingParticles,
355  const TrackingParticleRefKeySet* trackingParticleKeys,
356  iter begin,
357  iter end) const {
358  // Note that the trackingParticles parameter is not actually required since all the information is in clusterToTPMap,
359  // but the method signature has to match the other overload because it is called from a templated method.
360 
361  // Note further, that we can't completely ignore the
362  // trackingParticles parameter, in case it is a subset of those
363  // TrackingParticles used to construct clusterToTPMap (via the
364  // TrackingParticleRefVector overloads). The trackingParticles
365  // parameter is still ignored since looping over it on every call
366  // would be expensive, but the keys of the TrackingParticleRefs are
367  // cached to an IndexSet (trackingParticleKeys) which is used
368  // as a fast search structure.
369 
370  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the weighted number of associated clusters as "second"
371  // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
372  std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > returnValue;
373  if (clusterToTPMap.empty())
374  return returnValue;
375 
376  // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
377  // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this
378  // vector should be fewer than the number of clusters. The pair::second entries should add up to the total
379  // number of reco clusters though.
380  std::vector<OmniClusterRef> oClusters = track_associator::hitsToClusterRefs(begin, end);
381 
382  std::map<TrackingParticleRef, double> lmap;
383  for (std::vector<OmniClusterRef>::const_iterator it = oClusters.begin(); it != oClusters.end(); ++it) {
384  auto range = clusterToTPMap.equal_range(*it);
385  const double weight = it->isPixel() ? pixelHitWeight_ : 1.0;
386  if (range.first != range.second) {
387  for (auto ip = range.first; ip != range.second; ++ip) {
388  const TrackingParticleRef trackingParticle = (ip->second);
389 
390  if (trackingParticleKeys && !trackingParticleKeys->has(trackingParticle.key()))
391  continue;
392 
393  // Historically there was a requirement that pTrackingParticle->numberOfHits() > 0
394  // However, in TrackingTruthAccumulator, the numberOfHits is calculated from a subset
395  // of the SimHits of the SimTracks of a TrackingParticle (essentially limiting the
396  // processType and particleType to those of the "first" hit, and particleType to the pdgId of the SimTrack).
397  // But, here the association between tracks and TrackingParticles is done with *all* the hits of
398  // TrackingParticle, so we should not rely on the numberOfHits() calculated with a subset of SimHits.
399 
400  /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
401  std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
402  auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
403  if ((tp_range.second-tp_range.first)>1) {
404  edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
405  }
406  if(tp_range.first != tp_range.second) {
407  tp_range.first->second++;
408  } else {
409  returnValue.push_back(tpIntPair);
410  std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
411  }
412  */
413  auto jpos = lmap.find(trackingParticle);
414  if (jpos != lmap.end())
415  jpos->second += weight;
416  else
417  lmap.insert(std::make_pair(trackingParticle, weight));
418  }
419  }
420  }
421  // now copy the map to returnValue
422  for (auto ip = lmap.begin(); ip != lmap.end(); ++ip) {
423  returnValue.push_back(std::make_pair(ip->first, ip->second));
424  }
425  return returnValue;
426 }
427 
428 template <typename iter>
429 std::vector<std::pair<QuickTrackAssociatorByHitsImpl::SimTrackIdentifiers, double> >
431  iter begin,
432  iter end) const {
433  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
434  std::vector<std::pair<SimTrackIdentifiers, double> > returnValue;
435 
436  std::vector<SimTrackIdentifiers> simTrackIdentifiers;
437  // Loop over all of the rec hits in the track
438  //iter tRHIterBeginEnd = getTRHIterBeginEnd( pTrack );
439  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
440  if (track_associator::getHitFromIter(iRecHit)->isValid()) {
441  simTrackIdentifiers.clear();
442 
443  // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
444  // have merged (as far as I know).
445  hitAssociator.associateHitId(*(track_associator::getHitFromIter(iRecHit)),
446  simTrackIdentifiers); // This call fills simTrackIdentifiers
447 
448  const auto subdetId = track_associator::getHitFromIter(iRecHit)->geographicalId().subdetId();
449  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap)
451  : 1.0;
452 
453  // Loop over each identifier, and add it to the return value only if it's not already in there
454  for (std::vector<SimTrackIdentifiers>::const_iterator iIdentifier = simTrackIdentifiers.begin();
455  iIdentifier != simTrackIdentifiers.end();
456  ++iIdentifier) {
457  std::vector<std::pair<SimTrackIdentifiers, double> >::iterator iIdentifierCountPair;
458  for (auto iIdentifierCountPair = returnValue.begin(); iIdentifierCountPair != returnValue.end();
459  ++iIdentifierCountPair) {
460  if (iIdentifierCountPair->first.first == iIdentifier->first &&
461  iIdentifierCountPair->first.second == iIdentifier->second) {
462  // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
463  iIdentifierCountPair->second += weight;
464  break;
465  }
466  }
467  if (iIdentifierCountPair == returnValue.end())
468  returnValue.push_back(std::make_pair(*iIdentifier, 1.0));
469  // This identifier wasn't found, so add it
470  }
471  }
472  }
473  return returnValue;
474 }
475 
477  const SimTrackIdentifiers& identifier) const {
478  // Loop over all of the g4 tracks in the tracking particle
479  for (std::vector<SimTrack>::const_iterator iSimTrack = pTrackingParticle->g4Track_begin();
480  iSimTrack != pTrackingParticle->g4Track_end();
481  ++iSimTrack) {
482  // And see if the sim track identifiers match
483  if (iSimTrack->eventId() == identifier.second && iSimTrack->trackId() == identifier.first) {
484  return true;
485  }
486  }
487 
488  // If control has made it this far then none of the identifiers were found in
489  // any of the g4 tracks, so return false.
490  return false;
491 }
492 
493 template <typename iter>
495  iter startIterator,
496  iter endIterator,
497  TrackingParticleRef associatedTrackingParticle) const {
498  // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
499  // it makes I'll go through and comment it properly.
500 
501  // FIXME: It may be that this piece is not fully correct for
502  // counting how many times a single *cluster* is matched to many
503  // SimTracks of a single TrackingParticle (see comments in
504  // getDoubleCount(ClusterTPAssociation) overload). To be verified
505  // some time.
506 
507  double doubleCount = 0.0;
508  std::vector<SimHitIdpr> SimTrackIdsDC;
509 
510  for (iter iHit = startIterator; iHit != endIterator; iHit++) {
511  int idcount = 0;
512 
513  SimTrackIdsDC.clear();
514  hitAssociator.associateHitId(*(track_associator::getHitFromIter(iHit)), SimTrackIdsDC);
515  if (SimTrackIdsDC.size() > 1) {
516  for (TrackingParticle::g4t_iterator g4T = associatedTrackingParticle->g4Track_begin();
517  g4T != associatedTrackingParticle->g4Track_end();
518  ++g4T) {
519  if (find(SimTrackIdsDC.begin(),
520  SimTrackIdsDC.end(),
521  SimHitIdpr((*g4T).trackId(), SimTrackIdsDC.begin()->second)) != SimTrackIdsDC.end()) {
522  idcount++;
523  }
524  }
525  }
526  if (idcount > 1) {
527  const auto subdetId = track_associator::getHitFromIter(iHit)->geographicalId().subdetId();
528  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap)
530  : 1.0;
531  doubleCount += weight * (idcount - 1);
532  }
533  }
534 
535  return doubleCount;
536 }
537 
538 template <typename iter>
540  iter startIterator,
541  iter endIterator,
542  TrackingParticleRef associatedTrackingParticle) const {
543  // This code here was written by Subir Sarkar. I'm just splitting it off into a
544  // separate method. - Grimes 01/May/2014
545 
546  // The point here is that the electron TrackingParticles may contain
547  // multiple SimTracks (from the bremsstrahling), and (historically)
548  // the each matched hit/cluster has been multiplied by "how many
549  // SimTracks from the TrackingParticle" it contains charge from.
550  // Here the amount of this double counting is calculated, so that it
551  // can be subtracted by the calling code.
552  //
553  // Note that recently (hence "historically" in the paragraph above)
554  // the ClusterTPAssociationProducer was changed to remove the
555  // duplicate cluster->TP associations (hence making this function
556  // obsolete), but there is more recent proof that there is some
557  // duplication left (to be investigated).
558 
559  double doubleCount = 0;
560  std::vector<SimHitIdpr> SimTrackIdsDC;
561 
562  for (iter iHit = startIterator; iHit != endIterator; iHit++) {
563  std::vector<OmniClusterRef> oClusters =
564  track_associator::hitsToClusterRefs(iHit, iHit + 1); //only for the cluster being checked
565  for (std::vector<OmniClusterRef>::const_iterator it = oClusters.begin(); it != oClusters.end(); ++it) {
566  int idcount = 0;
567 
568  auto range = clusterToTPList.equal_range(*it);
569  if (range.first != range.second) {
570  for (auto ip = range.first; ip != range.second; ++ip) {
571  const TrackingParticleRef trackingParticle = (ip->second);
572  if (associatedTrackingParticle == trackingParticle) {
573  idcount++;
574  }
575  }
576  }
577 
578  if (idcount > 1) {
579  const auto subdetId = track_associator::getHitFromIter(iHit)->geographicalId().subdetId();
580  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap)
582  : 1.0;
583  doubleCount += weight * (idcount - 1);
584  }
585  }
586  }
587 
588  return doubleCount;
589 }
590 
592  const edm::Handle<edm::View<TrajectorySeed> >& pSeedCollectionHandle_,
593  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const {
594  edm::LogVerbatim("TrackAssociator") << "Starting TrackAssociatorByHitsImpl::associateRecoToSim - #seeds="
595  << pSeedCollectionHandle_->size()
596  << " #TPs=" << trackingParticleCollectionHandle->size();
597 
599 
600  size_t collectionSize = pSeedCollectionHandle_->size();
601 
602  for (size_t i = 0; i < collectionSize; ++i) {
603  const TrajectorySeed* pSeed = &(*pSeedCollectionHandle_)[i];
604 
605  // The return of this function has first as the index and second as the number of associated hits
606  std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > trackingParticleQualityPairs =
608  trackingParticleCollectionHandle,
609  nullptr,
610  pSeed->recHits().begin(),
611  pSeed->recHits().end())
613  trackingParticleCollectionHandle,
614  nullptr,
615  pSeed->recHits().begin(),
616  pSeed->recHits().end());
617  for (auto iTrackingParticleQualityPair = trackingParticleQualityPairs.begin();
618  iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
619  ++iTrackingParticleQualityPair) {
620  const edm::Ref<TrackingParticleCollection>& trackingParticleRef = iTrackingParticleQualityPair->first;
621  double numberOfSharedClusters = iTrackingParticleQualityPair->second;
622  double numberOfValidTrackClusters = clusterToTPMap_ ? weightedNumberOfTrackClusters(*pSeed, *clusterToTPMap_)
624 
625  if (numberOfSharedClusters == 0.0)
626  continue; // No point in continuing if there was no association
627 
628  //if electron subtract double counting
629  if (abs(trackingParticleRef->pdgId()) == 11 &&
630  (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1) {
631  if (clusterToTPMap_)
632  numberOfSharedClusters -=
633  getDoubleCount(*clusterToTPMap_, pSeed->recHits().begin(), pSeed->recHits().end(), trackingParticleRef);
634  else
635  numberOfSharedClusters -=
636  getDoubleCount(*hitAssociator_, pSeed->recHits().begin(), pSeed->recHits().end(), trackingParticleRef);
637  }
638 
639  double quality;
641  quality = numberOfSharedClusters;
642  else if (numberOfValidTrackClusters != 0.0)
643  quality = numberOfSharedClusters / numberOfValidTrackClusters;
644  else
645  quality = 0;
646 
647  if (quality > cutRecoToSim_ &&
648  !(threeHitTracksAreSpecial_ && pSeed->nHits() == 3 && numberOfSharedClusters < 3.0)) {
649  returnValue.insert(edm::RefToBase<TrajectorySeed>(pSeedCollectionHandle_, i),
650  std::make_pair(trackingParticleRef, quality));
651  }
652  }
653  }
654 
655  LogTrace("TrackAssociator") << "% of Assoc Seeds="
656  << ((double)returnValue.size()) / ((double)pSeedCollectionHandle_->size());
657  returnValue.post_insert();
658  return returnValue;
659 }
660 
662  const edm::Handle<edm::View<TrajectorySeed> >& pSeedCollectionHandle_,
663  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const {
664  edm::LogVerbatim("TrackAssociator") << "Starting TrackAssociatorByHitsImpl::associateSimToReco - #seeds="
665  << pSeedCollectionHandle_->size()
666  << " #TPs=" << trackingParticleCollectionHandle->size();
667 
669  if (trackingParticleCollectionHandle->empty())
670  return returnValue;
671 
672  if (clusterToTPMap_) {
673  checkClusterMapProductID(*clusterToTPMap_, trackingParticleCollectionHandle);
674  }
675 
676  size_t collectionSize = pSeedCollectionHandle_->size();
677 
678  for (size_t i = 0; i < collectionSize; ++i) {
679  const TrajectorySeed* pSeed = &(*pSeedCollectionHandle_)[i];
680 
681  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
682  std::vector<std::pair<edm::Ref<TrackingParticleCollection>, double> > trackingParticleQualityPairs =
684  trackingParticleCollectionHandle,
685  nullptr,
686  pSeed->recHits().begin(),
687  pSeed->recHits().end())
689  trackingParticleCollectionHandle,
690  nullptr,
691  pSeed->recHits().begin(),
692  pSeed->recHits().end());
693  for (auto iTrackingParticleQualityPair = trackingParticleQualityPairs.begin();
694  iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
695  ++iTrackingParticleQualityPair) {
696  const edm::Ref<TrackingParticleCollection>& trackingParticleRef = iTrackingParticleQualityPair->first;
697  double numberOfSharedClusters = iTrackingParticleQualityPair->second;
698  double numberOfValidTrackClusters = clusterToTPMap_ ? weightedNumberOfTrackClusters(*pSeed, *clusterToTPMap_)
700  size_t numberOfSimulatedHits = 0; // Set a few lines below, but only if required.
701 
702  if (numberOfSharedClusters == 0.0)
703  continue; // No point in continuing if there was no association
704 
705  //if electron subtract double counting
706  if (abs(trackingParticleRef->pdgId()) == 11 &&
707  (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1) {
708  if (clusterToTPMap_)
709  numberOfSharedClusters -=
710  getDoubleCount(*clusterToTPMap_, pSeed->recHits().begin(), pSeed->recHits().end(), trackingParticleRef);
711  else
712  numberOfSharedClusters -=
713  getDoubleCount(*hitAssociator_, pSeed->recHits().begin(), pSeed->recHits().end(), trackingParticleRef);
714  }
715 
717  (numberOfSharedClusters < 3.0 &&
718  threeHitTracksAreSpecial_)) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
719  {
720  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
721  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
722  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
723  // hits in the tracker.
724  numberOfSimulatedHits = trackingParticleRef->numberOfTrackerHits();
725  }
726 
727  double purity = numberOfSharedClusters / numberOfValidTrackClusters;
728  double quality;
730  quality = numberOfSharedClusters;
731  else if (simToRecoDenominator_ == denomsim && numberOfSimulatedHits != 0)
732  quality = numberOfSharedClusters / static_cast<double>(numberOfSimulatedHits);
733  else if (simToRecoDenominator_ == denomreco && numberOfValidTrackClusters != 0.0)
734  quality = purity;
735  else
736  quality = 0;
737 
738  if (quality > qualitySimToReco_ &&
739  !(threeHitTracksAreSpecial_ && numberOfSimulatedHits == 3 && numberOfSharedClusters < 3.0) &&
740  (absoluteNumberOfHits_ || (purity > puritySimToReco_))) {
741  returnValue.insert(trackingParticleRef,
742  std::make_pair(edm::RefToBase<TrajectorySeed>(pSeedCollectionHandle_, i), quality));
743  }
744  }
745  }
746 
747  LogTrace("TrackAssociator") << "% of Assoc TPs="
748  << ((double)returnValue.size()) / ((double)trackingParticleCollectionHandle->size());
749  returnValue.post_insert();
750  return returnValue;
751 }
752 
753 // count hits
755  const TrackerHitAssociator&) const {
756  const reco::HitPattern& p = track.hitPattern();
757  const auto pixelHits = p.numberOfValidPixelHits();
758  const auto otherHits = p.numberOfValidHits() - pixelHits;
759  return pixelHits * pixelHitWeight_ + otherHits;
760 }
761 
763  const TrackerHitAssociator&) const {
764  double sum = 0.0;
765  for (auto iHit = seed.recHits().begin(); iHit != seed.recHits().end(); ++iHit) {
766  const auto subdetId = track_associator::getHitFromIter(iHit)->geographicalId().subdetId();
767  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap)
769  : 1.0;
770  sum += weight;
771  }
772  return sum;
773 }
774 
775 // count clusters
777  const ClusterTPAssociation&) const {
778  return weightedNumberOfTrackClusters(track.recHitsBegin(), track.recHitsEnd());
779 }
781  const ClusterTPAssociation&) const {
782  const auto& hitRange = seed.recHits();
783  return weightedNumberOfTrackClusters(hitRange.begin(), hitRange.end());
784 }
785 
786 template <typename iter>
788  double weightedClusters = 0.0;
789  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
790  const auto subdetId = track_associator::getHitFromIter(iRecHit)->geographicalId().subdetId();
791  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap)
793  : 1.0;
794  LogTrace("QuickTrackAssociatorByHitsImpl")
795  << " detId: " << track_associator::getHitFromIter(iRecHit)->geographicalId().rawId();
796  LogTrace("QuickTrackAssociatorByHitsImpl") << " weight: " << weight;
797  std::vector<OmniClusterRef> oClusters =
798  track_associator::hitsToClusterRefs(iRecHit, iRecHit + 1); //only for the cluster being checked
799  for (std::vector<OmniClusterRef>::const_iterator it = oClusters.begin(); it != oClusters.end(); ++it) {
800  weightedClusters += weight;
801  }
802  }
803  LogTrace("QuickTrackAssociatorByHitsImpl") << " total weighted clusters: " << weightedClusters;
804  return weightedClusters;
805 }
track_associator::getHitFromIter
const TrackingRecHit * getHitFromIter(trackingRecHit_iterator iter)
Definition: trackHitsToClusterRefs.h:16
QuickTrackAssociatorByHitsImpl::associateRecoToSimImplementation
reco::RecoToSimCollection associateRecoToSimImplementation(const T_TrackCollection &trackCollection, const T_TrackingParticleCollection &trackingParticleCollection, const TrackingParticleRefKeySet *trackingParticleKeys, T_hitOrClusterAssociator hitOrClusterAssociator) const
The method that does the work for both overloads of associateRecoToSim.
Definition: QuickTrackAssociatorByHitsImpl.cc:166
FastTimerService_cff.range
range
Definition: FastTimerService_cff.py:34
QuickTrackAssociatorByHitsImpl::absoluteNumberOfHits_
bool absoluteNumberOfHits_
Definition: QuickTrackAssociatorByHitsImpl.h:233
mps_fire.i
i
Definition: mps_fire.py:428
trackHitsToClusterRefs.h
PixelSubdetector.h
HLT_FULL_cff.track
track
Definition: HLT_FULL_cff.py:11724
QuickTrackAssociatorByHitsImpl::associateRecoToSim
reco::RecoToSimCollection associateRecoToSim(const edm::Handle< edm::View< reco::Track > > &trackCollectionHandle, const edm::Handle< TrackingParticleCollection > &trackingParticleCollectionHandle) const override
Definition: QuickTrackAssociatorByHitsImpl.cc:115
MessageLogger.h
PixelSubdetector::PixelEndcap
Definition: PixelSubdetector.h:11
PixelSubdetector::PixelBarrel
Definition: PixelSubdetector.h:11
edm::Handle::product
T const * product() const
Definition: Handle.h:70
QuickTrackAssociatorByHitsImpl::associateSimToRecoImplementation
reco::SimToRecoCollection associateSimToRecoImplementation(const T_TrackCollection &trackCollection, const T_TrackingParticleCollection &trackingParticleCollection, const TrackingParticleRefKeySet *trackingParticleKeys, T_hitOrClusterAssociator hitOrClusterAssociator) const
The method that does the work for both overloads of associateSimToReco.
Definition: QuickTrackAssociatorByHitsImpl.cc:228
reco::Track::recHitsBegin
trackingRecHit_iterator recHitsBegin() const
Iterator to first hit on the track.
Definition: Track.h:88
TrackingParticle::g4Track_begin
g4t_iterator g4Track_begin() const
Definition: TrackingParticle.cc:29
SimHitIdpr
std::pair< uint32_t, EncodedEventId > SimHitIdpr
Definition: TrackerHitAssociator.h:54
QuickTrackAssociatorByHitsImpl::QuickTrackAssociatorByHitsImpl
QuickTrackAssociatorByHitsImpl(edm::EDProductGetter const &productGetter, std::unique_ptr< const TrackerHitAssociator > hitAssoc, const ClusterTPAssociation *clusterToTPMap, bool absoluteNumberOfHits, double qualitySimToReco, double puritySimToReco, double cutRecoToSim, double pixelHitWeight, bool threeHitTracksAreSpecial, SimToRecoDenomType simToRecoDenominator)
Definition: QuickTrackAssociatorByHitsImpl.cc:93
TrajectorySeed::nHits
unsigned int nHits() const
Definition: TrajectorySeed.h:53
QuickTrackAssociatorByHitsImpl.h
QuickTrackAssociatorByHitsImpl::associateSimToReco
reco::SimToRecoCollection associateSimToReco(const edm::Handle< edm::View< reco::Track > > &trackCollectionHandle, const edm::Handle< TrackingParticleCollection > &trackingParticleCollectionHandle) const override
Definition: QuickTrackAssociatorByHitsImpl.cc:127
mps_merge.weight
weight
Definition: mps_merge.py:88
TrackingParticle::g4t_iterator
std::vector< SimTrack >::const_iterator g4t_iterator
Definition: TrackingParticle.h:41
ClusterTPAssociation
Definition: ClusterTPAssociation.h:21
QuickTrackAssociatorByHitsImpl::weightedNumberOfTrackClusters
double weightedNumberOfTrackClusters(const reco::Track &track, const TrackerHitAssociator &) const
Definition: QuickTrackAssociatorByHitsImpl.cc:754
QuickTrackAssociatorByHitsImpl::getDoubleCount
double getDoubleCount(const TrackerHitAssociator &hitAssociator, iter begin, iter end, TrackingParticleRef associatedTrackingParticle) const
This method was copied almost verbatim from the standard TrackAssociatorByHits.
Definition: QuickTrackAssociatorByHitsImpl.cc:494
TrackerHitAssociator.h
relativeConstraints.keys
keys
Definition: relativeConstraints.py:89
edm::RefVector
Definition: EDProductfwd.h:27
spr::find
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
edm::Handle
Definition: AssociativeIterator.h:50
TrackQuality_cff.hitAssociator
hitAssociator
Definition: TrackQuality_cff.py:10
reco::TrackBase::numberOfValidHits
unsigned short numberOfValidHits() const
number of valid hits found
Definition: TrackBase.h:798
TrackingRecHit::geographicalId
DetId geographicalId() const
Definition: TrackingRecHit.h:120
edm::Ref< TrackingParticleCollection >
quality
const uint32_t *__restrict__ Quality * quality
Definition: CAHitNtupletGeneratorKernelsImpl.h:122
fileCollector.seed
seed
Definition: fileCollector.py:127
edm::EDProductGetter
Definition: EDProductGetter.h:41
edm::Range::end
T end() const
Definition: Range.h:16
edm::AssociationMap::post_insert
void post_insert()
post insert action
Definition: AssociationMap.h:229
reco::HitPattern
Definition: HitPattern.h:147
track_associator::hitsToClusterRefs
std::vector< OmniClusterRef > hitsToClusterRefs(iter begin, iter end)
Definition: trackHitsToClusterRefs.h:21
edm::IndexSet::has
bool has(unsigned int index) const
Check if an element (=index) is in the set.
Definition: IndexSet.h:54
QuickTrackAssociatorByHitsImpl::puritySimToReco_
double puritySimToReco_
Definition: QuickTrackAssociatorByHitsImpl.h:228
QuickTrackAssociatorByHitsImpl::SimToRecoDenomType
SimToRecoDenomType
Definition: QuickTrackAssociatorByHitsImpl.h:68
QuickTrackAssociatorByHitsImpl::qualitySimToReco_
double qualitySimToReco_
Definition: QuickTrackAssociatorByHitsImpl.h:227
reco::Track::recHitsEnd
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.
Definition: Track.h:91
TrackingParticle
Monte Carlo truth information used for tracking validation.
Definition: TrackingParticle.h:29
mps_fire.end
end
Definition: mps_fire.py:242
PrimaryVertexAnalyzer4PUSlimmed_cfi.trackingParticleCollection
trackingParticleCollection
Definition: PrimaryVertexAnalyzer4PUSlimmed_cfi.py:21
reco::Track
Definition: Track.h:27
QuickTrackAssociatorByHitsImpl::denomsim
Definition: QuickTrackAssociatorByHitsImpl.h:68
sistrip::SpyUtilities::isValid
const bool isValid(const Frame &aFrame, const FrameQuality &aQuality, const uint16_t aExpectedPos)
Definition: SiStripSpyUtilities.cc:124
QuickTrackAssociatorByHitsImpl::threeHitTracksAreSpecial_
bool threeHitTracksAreSpecial_
Definition: QuickTrackAssociatorByHitsImpl.h:232
DetId::subdetId
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector's numbering enum)
Definition: DetId.h:48
QuickTrackAssociatorByHitsImpl::productGetter_
edm::EDProductGetter const * productGetter_
creates either a ClusterTPAssociation OR a TrackerHitAssociator and stores it in the provided unique_...
Definition: QuickTrackAssociatorByHitsImpl.h:223
QuickTrackAssociatorByHitsImpl::pixelHitWeight_
double pixelHitWeight_
Definition: QuickTrackAssociatorByHitsImpl.h:229
QuickTrackAssociatorByHitsImpl::getAllSimTrackIdentifiers
std::vector< std::pair< SimTrackIdentifiers, double > > getAllSimTrackIdentifiers(const TrackerHitAssociator &hitAssociator, iter begin, iter end) const
Returns a vector of pairs where first is a SimTrackIdentifiers (see typedef above) and second is the ...
Definition: QuickTrackAssociatorByHitsImpl.cc:430
edm::View
Definition: CaloClusterFwd.h:14
QuickTrackAssociatorByHitsImpl::trackingParticleContainsIdentifier
bool trackingParticleContainsIdentifier(const TrackingParticle *pTrackingParticle, const SimTrackIdentifiers &identifier) const
Returns true if the supplied TrackingParticle has the supplied g4 track identifiers.
Definition: QuickTrackAssociatorByHitsImpl.cc:476
edm::AssociationMap::size
size_type size() const
map size
Definition: AssociationMap.h:162
AlCaHLTBitMon_ParallelJobs.p
def p
Definition: AlCaHLTBitMon_ParallelJobs.py:153
edm::Range::begin
T begin() const
Definition: Range.h:15
QuickTrackAssociatorByHitsImpl::denomreco
Definition: QuickTrackAssociatorByHitsImpl.h:68
duplicaterechits_cfi.trackCollection
trackCollection
Definition: duplicaterechits_cfi.py:4
deltaR.h
edm::AssociationMap< edm::OneToManyWithQualityGeneric< edm::View< reco::Track >, TrackingParticleCollection, double > >
muonClassificationByHits_cfi.trackingParticles
trackingParticles
Definition: muonClassificationByHits_cfi.py:28
edm::IndexSet
Definition: IndexSet.h:22
universalConfigTemplate.collection
collection
Definition: universalConfigTemplate.py:81
ClusterTPAssociation::equal_range
range equal_range(const OmniClusterRef &key) const
Definition: ClusterTPAssociation.h:65
QuickTrackAssociatorByHitsImpl::associateTrack
std::vector< std::pair< edm::Ref< TrackingParticleCollection >, double > > associateTrack(const TrackerHitAssociator &hitAssociator, const T_TPCollection &trackingParticles, const TrackingParticleRefKeySet *trackingParticleKeys, iter begin, iter end) const
Returns the TrackingParticle that has the most associated hits to the given track.
Definition: QuickTrackAssociatorByHitsImpl.cc:307
edm::refcoreimpl::productGetter
EDProductGetter const * productGetter(std::atomic< void const * > const &iCache)
Definition: refcore_implementation.h:72
TrajectorySeed::recHits
RecHitRange recHits() const
Definition: TrajectorySeed.h:52
edm::RefToBaseVector
Definition: EDProductfwd.h:29
ClusterTPAssociation::checkMappedProductID
void checkMappedProductID(const edm::HandleBase &mappedHandle) const
Definition: ClusterTPAssociation.h:75
QuickTrackAssociatorByHitsImpl::cutRecoToSim_
double cutRecoToSim_
Definition: QuickTrackAssociatorByHitsImpl.h:230
edm::AssociationMap::insert
void insert(const key_type &k, const data_type &v)
insert an association
Definition: AssociationMap.h:166
TrackerHitAssociator
Definition: TrackerHitAssociator.h:55
QuickTrackAssociatorByHitsImpl::clusterToTPMap_
const ClusterTPAssociation * clusterToTPMap_
Definition: QuickTrackAssociatorByHitsImpl.h:225
eostools.move
def move(src, dest)
Definition: eostools.py:511
std
Definition: JetResolutionObject.h:76
DetId::rawId
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
QuickTrackAssociatorByHitsImpl::SimTrackIdentifiers
std::pair< uint32_t, EncodedEventId > SimTrackIdentifiers
This is enough information to uniquely identify a sim track.
Definition: QuickTrackAssociatorByHitsImpl.h:104
edm::LogVerbatim
Log< level::Info, true > LogVerbatim
Definition: MessageLogger.h:128
TrackingParticle::g4Track_end
g4t_iterator g4Track_end() const
Definition: TrackingParticle.cc:31
TrajectorySeed
Definition: TrajectorySeed.h:18
edm::RefToBase< reco::Track >
AlignmentPI::index
index
Definition: AlignmentPayloadInspectorHelper.h:46
edm::Ref::key
key_type key() const
Accessor for product key.
Definition: Ref.h:250
funct::abs
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
LogTrace
#define LogTrace(id)
Definition: MessageLogger.h:234
ClusterTPAssociation::empty
bool empty() const
Definition: ClusterTPAssociation.h:57
InitialStepPreSplitting_cff.pixelHits
pixelHits
Definition: InitialStepPreSplitting_cff.py:142
QuickTrackAssociatorByHitsImpl::hitAssociator_
std::unique_ptr< const TrackerHitAssociator > hitAssociator_
Definition: QuickTrackAssociatorByHitsImpl.h:224
weight
Definition: weight.py:1
QuickTrackAssociatorByHitsImpl::simToRecoDenominator_
SimToRecoDenomType simToRecoDenominator_
Definition: QuickTrackAssociatorByHitsImpl.h:231