CMS 3D CMS Logo

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