CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
QuickTrackAssociatorByHitsImpl.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <fstream>
3 
5 
7 
16 
17 //
18 // Use the unnamed namespace for utility functions only used in this file
19 //
20 namespace
21 {
22  //
23  // All of these functions are pretty straightforward but the implementation is type dependent.
24  // The templated methods call these for the type specific parts and the compiler will resolve
25  // the type and call the correct overload.
26  //
27 
28  template<class T_element>
29  size_t collectionSize( const edm::RefToBaseVector<T_element>& collection )
30  {
31  return collection.size();
32  }
33 
34  template<class T_element>
35  size_t collectionSize( const edm::Handle<T_element>& hCollection )
36  {
37  return hCollection->size();
38  }
39 
40  template<class T_element>
41  size_t collectionSize( const edm::RefVector<T_element>& collection )
42  {
43  return collection.size();
44  }
45 
46  const reco::Track* getTrackAt( const edm::RefToBaseVector<reco::Track>& trackCollection, size_t index )
47  {
48  return &*trackCollection[index]; // pretty obscure dereference
49  }
50 
51  const reco::Track* getTrackAt( const edm::Handle<edm::View<reco::Track> >& pTrackCollection, size_t index )
52  {
53  return &(*pTrackCollection.product())[index];
54  }
55 
56  const TrackingParticle* getTrackingParticleAt( const edm::Handle<TrackingParticleCollection>& pCollection, size_t index )
57  {
58  return &(*pCollection.product())[index];
59  }
60 
61  const TrackingParticle* getTrackingParticleAt( const edm::RefVector<TrackingParticleCollection>& collection, size_t index )
62  {
63  return &*collection[index];
64  }
65 
67  {
68  return trackCollection[index];
69  }
70 
71  edm::RefToBase<reco::Track> getRefToTrackAt( const edm::Handle<edm::View<reco::Track> >& pTrackCollection, size_t index )
72  {
73  return edm::RefToBase<reco::Track>( pTrackCollection, index );
74  }
75 
76  edm::Ref<TrackingParticleCollection> getRefToTrackingParticleAt( const edm::Handle<TrackingParticleCollection>& pCollection, size_t index )
77  {
78  return edm::Ref<TrackingParticleCollection>( pCollection, index );
79  }
80 
81  edm::Ref<TrackingParticleCollection> getRefToTrackingParticleAt( const edm::RefVector<TrackingParticleCollection>& collection, size_t index )
82  {
83  return collection[index];
84  }
85 
86 } // end of the unnamed namespace
87 
88 QuickTrackAssociatorByHitsImpl::QuickTrackAssociatorByHitsImpl(std::shared_ptr<const TrackerHitAssociator> hitAssoc,
89  std::shared_ptr<const ClusterTPAssociationList> clusterToTPMap,
90 
91  bool absoluteNumberOfHits,
92  double qualitySimToReco,
93  double puritySimToReco,
94  double cutRecoToSim,
95  bool threeHitTracksAreSpecial,
96  SimToRecoDenomType simToRecoDenominator):
97  hitAssociator_(std::move(hitAssoc)),
98  clusterToTPMap_(std::move(clusterToTPMap)),
99  qualitySimToReco_(qualitySimToReco),
100  puritySimToReco_(puritySimToReco),
101  cutRecoToSim_(cutRecoToSim),
102  simToRecoDenominator_(simToRecoDenominator) ,
103  threeHitTracksAreSpecial_(threeHitTracksAreSpecial),
104  absoluteNumberOfHits_(absoluteNumberOfHits)
105  {}
106 
107 
109  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
110 {
111  // Only pass the one that was successfully created to the templated method.
112  if( not clusterToTPMap_ ) return associateRecoToSimImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *hitAssociator_ );
113  else return associateRecoToSimImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *clusterToTPMap_ );
114 }
115 
117  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
118 {
119  // Only pass the one that was successfully created to the templated method.
120  if( not clusterToTPMap_ ) return associateSimToRecoImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *hitAssociator_ );
121  else return associateSimToRecoImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *clusterToTPMap_ );
122 }
123 
125  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection ) const
126 {
127  // Only pass the one that was successfully created to the templated method.
128  if( not clusterToTPMap_ ) return associateRecoToSimImplementation( trackCollection, trackingParticleCollection, *hitAssociator_ );
129  else return associateRecoToSimImplementation( trackCollection, trackingParticleCollection, *clusterToTPMap_ );
130 }
131 
133  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection) const
134 {
135  // Only pass the one that was successfully created to the templated method.
136  if( not clusterToTPMap_ ) return associateSimToRecoImplementation( trackCollection, trackingParticleCollection, *hitAssociator_ );
137  else return associateSimToRecoImplementation( trackCollection, trackingParticleCollection, *clusterToTPMap_ );
138 }
139 
140 
141 template<class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
142 reco::RecoToSimCollection QuickTrackAssociatorByHitsImpl::associateRecoToSimImplementation( T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator ) const
143 {
144  reco::RecoToSimCollection returnValue;
145 
146  size_t collectionSize=::collectionSize(trackCollection); // Delegate away type specific part
147 
148  for( size_t i=0; i < collectionSize; ++i )
149  {
150  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
151 
152  // The return of this function has first as the index and second as the number of associated hits
153  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
154 
155  // int nt = 0;
156  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
157  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
158  ++iTrackingParticleQualityPair )
159  {
160  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
161  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
162  size_t numberOfValidTrackHits=pTrack->found();
163 
164  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
165 
166  //if electron subtract double counting
167  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
168  {
169  numberOfSharedHits-=getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
170  }
171 
172  double quality;
173  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
174  else if( numberOfValidTrackHits != 0 ) quality=
175  (static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits ));
176  else quality=0;
177  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && numberOfValidTrackHits == 3 && numberOfSharedHits < 3) )
178  {
179  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
180  returnValue.insert( ::getRefToTrackAt(trackCollection,i), std::make_pair( trackingParticleRef, quality ) );
181  }
182  }
183  }
184  return returnValue;
185 }
186 
187 template<class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
188 reco::SimToRecoCollection QuickTrackAssociatorByHitsImpl::associateSimToRecoImplementation( T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator ) const
189 {
190  reco::SimToRecoCollection returnValue;
191 
192  size_t collectionSize=::collectionSize(trackCollection); // Delegate away type specific part
193 
194  for( size_t i=0; i<collectionSize; ++i )
195  {
196  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
197 
198  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
199  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
200 
201  // int nt = 0;
202  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
203  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
204  {
205  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
206  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
207  size_t numberOfValidTrackHits=pTrack->found();
208  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
209 
210  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
211 
212  if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
213  {
214  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
215  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
216  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
217  // hits in the tracker.
218  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
219  }
220 
221  //if electron subtract double counting
222  if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
223  {
224  numberOfSharedHits -= getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
225  }
226 
227  double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
228  double quality;
229  if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
230  else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
231  else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
232  else quality=0;
233 
234  if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
235  {
236  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
237  returnValue.insert( trackingParticleRef, std::make_pair( ::getRefToTrackAt(trackCollection,i), quality ) );
238  }
239  }
240  }
241  return returnValue;
242 
243 }
244 
245 template<typename T_TPCollection,typename iter> std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHitsImpl::associateTrack( const TrackerHitAssociator& hitAssociator, T_TPCollection trackingParticles, iter begin, iter end ) const
246 {
247  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated hits as "second"
248  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
249 
250  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
251  // 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
252  // number of reco hits. The pair::second entries should add up to the total number of reco hits though.
253  std::vector< std::pair<SimTrackIdentifiers,size_t> > hitIdentifiers=getAllSimTrackIdentifiers( hitAssociator, begin, end );
254 
255  // Loop over the TrackingParticles
256  size_t collectionSize=::collectionSize(trackingParticles);
257 
258  for( size_t i=0; i<collectionSize; ++i )
259  {
260  const TrackingParticle* pTrackingParticle=getTrackingParticleAt( trackingParticles, i );
261 
262  // Ignore TrackingParticles with no hits
263  if( pTrackingParticle->numberOfHits()==0 ) continue;
264 
265  size_t numberOfAssociatedHits=0;
266  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
267  // the number of reco hits associated to that sim track to the total number of associated hits.
268  for( std::vector< std::pair<SimTrackIdentifiers,size_t> >::const_iterator iIdentifierCountPair=hitIdentifiers.begin(); iIdentifierCountPair!=hitIdentifiers.end(); ++iIdentifierCountPair )
269  {
270  if( trackingParticleContainsIdentifier( pTrackingParticle, iIdentifierCountPair->first ) ) numberOfAssociatedHits+=iIdentifierCountPair->second;
271  }
272 
273  if( numberOfAssociatedHits>0 )
274  {
275  returnValue.push_back( std::make_pair( getRefToTrackingParticleAt(trackingParticles,i), numberOfAssociatedHits ) );
276  }
277  }
278 
279  return returnValue;
280 }
281 
282 template<typename T_TPCollection,typename iter> std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHitsImpl::associateTrack( const ClusterTPAssociationList& clusterToTPMap, T_TPCollection trackingParticles, iter begin, iter end ) const
283 {
284  // Note that the trackingParticles parameter is not actually required since all the information is in clusterToTPMap,
285  // but the method signature has to match the other overload because it is called from a templated method.
286 
287  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated clusters as "second"
288  // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
289  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
290  if( clusterToTPMap.empty() ) return returnValue;
291 
292  // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
293  // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this
294  // vector should be fewer than the number of clusters. The pair::second entries should add up to the total
295  // number of reco clusters though.
296  std::vector<OmniClusterRef> oClusters=getMatchedClusters( begin, end );
297 
298  std::map < TrackingParticleRef, size_t > lmap;
299  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
300  {
301 
302  std::pair < OmniClusterRef, TrackingParticleRef > clusterTPpairWithDummyTP( *it, TrackingParticleRef() ); //TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
303  auto range=std::equal_range( clusterToTPMap.begin(), clusterToTPMap.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater );
304  if( range.first != range.second )
305  {
306  for( auto ip=range.first; ip != range.second; ++ip )
307  {
308 
309  const TrackingParticleRef trackingParticle=(ip->second);
310 
311  // Ignore TrackingParticles with no hits
312  if( trackingParticle->numberOfHits() == 0 ) continue;
313 
314  /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
315  std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
316  auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
317  if ((tp_range.second-tp_range.first)>1) {
318  edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
319  }
320  if(tp_range.first != tp_range.second) {
321  tp_range.first->second++;
322  } else {
323  returnValue.push_back(tpIntPair);
324  std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
325  }
326  */
327  auto jpos=lmap.find( trackingParticle );
328  if( jpos != lmap.end() ) ++jpos->second;
329  else lmap.insert( std::make_pair( trackingParticle, 1 ) );
330  }
331  }
332  }
333  // now copy the map to returnValue
334  for( auto ip=lmap.begin(); ip != lmap.end(); ++ip )
335  {
336  returnValue.push_back( std::make_pair( ip->first, ip->second ) );
337  }
338  return returnValue;
339 }
340 
341 template<typename iter> std::vector<OmniClusterRef> QuickTrackAssociatorByHitsImpl::getMatchedClusters(iter begin, iter end) const
342 {
343  std::vector<OmniClusterRef> returnValue;
344  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
345  const TrackingRecHit* rhit = getHitFromIter(iRecHit);
346  if (rhit->isValid()) {
347  int subdetid = rhit->geographicalId().subdetId();
349  const SiPixelRecHit* pRHit = dynamic_cast<const SiPixelRecHit*>(rhit);
350  if (!pRHit->cluster().isNonnull())
351  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
352  returnValue.push_back(pRHit->omniClusterRef());
353  }
354  else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) {
355  const std::type_info &tid = typeid(*rhit);
356  if (tid == typeid(SiStripMatchedRecHit2D)) {
357  const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast<const SiStripMatchedRecHit2D*>(rhit);
358  if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull())
359  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
360  returnValue.push_back(sMatchedRHit->monoClusterRef());
361  returnValue.push_back(sMatchedRHit->stereoClusterRef());
362  }
363  else if (tid == typeid(SiStripRecHit2D)) {
364  const SiStripRecHit2D* sRHit = dynamic_cast<const SiStripRecHit2D*>(rhit);
365  if (!sRHit->cluster().isNonnull())
366  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
367  returnValue.push_back(sRHit->omniClusterRef());
368  }
369  else if (tid == typeid(SiStripRecHit1D)) {
370  const SiStripRecHit1D* sRHit = dynamic_cast<const SiStripRecHit1D*>(rhit);
371  if (!sRHit->cluster().isNonnull())
372  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
373  returnValue.push_back(sRHit->omniClusterRef());
374  }
375  else {
376  auto const & thit = static_cast<BaseTrackerRecHit const&>(*rhit);
377  if ( thit.isProjected() ) {
378  } else {
379  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid;
380  }
381  }
382  }
383  else {
384  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid;
385  }
386  }
387  }
388  return returnValue;
389 }
390 
391 template<typename iter> std::vector< std::pair<QuickTrackAssociatorByHitsImpl::SimTrackIdentifiers,size_t> > QuickTrackAssociatorByHitsImpl::getAllSimTrackIdentifiers( const TrackerHitAssociator& hitAssociator, iter begin, iter end ) const
392 {
393  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
394  std::vector < std::pair<SimTrackIdentifiers,size_t> > returnValue;
395 
396  std::vector<SimTrackIdentifiers> simTrackIdentifiers;
397  // Loop over all of the rec hits in the track
398  //iter tRHIterBeginEnd = getTRHIterBeginEnd( pTrack );
399  for( iter iRecHit=begin; iRecHit != end; ++iRecHit )
400  {
401  if( getHitFromIter( iRecHit )->isValid() )
402  {
403  simTrackIdentifiers.clear();
404 
405  // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
406  // have merged (as far as I know).
407  hitAssociator.associateHitId( *(getHitFromIter( iRecHit )), simTrackIdentifiers ); // This call fills simTrackIdentifiers
408  // Loop over each identifier, and add it to the return value only if it's not already in there
409  for( std::vector<SimTrackIdentifiers>::const_iterator iIdentifier=simTrackIdentifiers.begin(); iIdentifier != simTrackIdentifiers.end();
410  ++iIdentifier )
411  {
412  std::vector<std::pair<SimTrackIdentifiers,size_t> >::iterator iIdentifierCountPair;
413  for( iIdentifierCountPair=returnValue.begin(); iIdentifierCountPair != returnValue.end(); ++iIdentifierCountPair )
414  {
415  if( iIdentifierCountPair->first.first == iIdentifier->first && iIdentifierCountPair->first.second == iIdentifier->second )
416  {
417  // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
418  ++iIdentifierCountPair->second;
419  break;
420  }
421  }
422  if( iIdentifierCountPair == returnValue.end() ) returnValue.push_back( std::make_pair( *iIdentifier, 1 ) );
423  // This identifier wasn't found, so add it
424  }
425  }
426  }
427  return returnValue;
428 }
429 
431 {
432  // Loop over all of the g4 tracks in the tracking particle
433  for( std::vector<SimTrack>::const_iterator iSimTrack=pTrackingParticle->g4Track_begin(); iSimTrack != pTrackingParticle->g4Track_end();
434  ++iSimTrack )
435  {
436  // And see if the sim track identifiers match
437  if( iSimTrack->eventId() == identifier.second && iSimTrack->trackId() == identifier.first )
438  {
439  return true;
440  }
441  }
442 
443  // If control has made it this far then none of the identifiers were found in
444  // any of the g4 tracks, so return false.
445  return false;
446 }
447 
448 template<typename iter> int QuickTrackAssociatorByHitsImpl::getDoubleCount( const TrackerHitAssociator& hitAssociator, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
449 {
450  // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
451  // it makes I'll go through and comment it properly.
452 
453  int doubleCount=0;
454  std::vector < SimHitIdpr > SimTrackIdsDC;
455 
456  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
457  {
458  int idcount=0;
459 
460  SimTrackIdsDC.clear();
461  hitAssociator.associateHitId( *(getHitFromIter( iHit )), SimTrackIdsDC );
462  if( SimTrackIdsDC.size() > 1 )
463  {
464  for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle->g4Track_begin(); g4T != associatedTrackingParticle->g4Track_end();
465  ++g4T )
466  {
467  if( find( SimTrackIdsDC.begin(), SimTrackIdsDC.end(), SimHitIdpr( ( *g4T).trackId(), SimTrackIdsDC.begin()->second ) )
468  != SimTrackIdsDC.end() )
469  {
470  idcount++;
471  }
472  }
473  }
474  if( idcount > 1 ) doubleCount+=(idcount - 1);
475  }
476 
477  return doubleCount;
478 }
479 
480 template<typename iter> int QuickTrackAssociatorByHitsImpl::getDoubleCount( const ClusterTPAssociationList& clusterToTPList, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
481 {
482  // This code here was written by Subir Sarkar. I'm just splitting it off into a
483  // separate method. - Grimes 01/May/2014
484 
485  int doubleCount=0;
486  std::vector < SimHitIdpr > SimTrackIdsDC;
487 
488  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
489  {
490  int idcount=0;
491 
492  std::vector < OmniClusterRef > oClusters=getMatchedClusters( iHit, iHit + 1 ); //only for the cluster being checked
493  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
494  {
495  std::pair<OmniClusterRef,TrackingParticleRef> clusterTPpairWithDummyTP( *it, TrackingParticleRef() ); //TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
496  auto range=std::equal_range( clusterToTPList.begin(), clusterToTPList.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater );
497  if( range.first != range.second )
498  {
499  for( auto ip=range.first; ip != range.second; ++ip )
500  {
501  const TrackingParticleRef trackingParticle=(ip->second);
502  if( associatedTrackingParticle == trackingParticle )
503  {
504  idcount++;
505  }
506  }
507  }
508  }
509 
510  if( idcount > 1 ) doubleCount+=(idcount - 1);
511  }
512 
513  return doubleCount;
514 }
515 
517  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
518 {
519 
520  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHitsImpl::associateRecoToSim - #seeds=" << pSeedCollectionHandle_->size()
521  << " #TPs=" << trackingParticleCollectionHandle->size();
522 
523  reco::RecoToSimCollectionSeed returnValue;
524 
525  size_t collectionSize=pSeedCollectionHandle_->size();
526 
527  for( size_t i=0; i < collectionSize; ++i )
528  {
529  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
530 
531  // The return of this function has first as the index and second as the number of associated hits
532  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=
533  (clusterToTPMap_) ? associateTrack( *clusterToTPMap_, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *hitAssociator_, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second );
534  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
535  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
536  ++iTrackingParticleQualityPair )
537  {
538  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
539  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
540  size_t numberOfValidTrackHits=pSeed->recHits().second - pSeed->recHits().first;
541 
542  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
543 
544  //if electron subtract double counting
545  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
546  {
547  if( clusterToTPMap_ ) numberOfSharedHits-=getDoubleCount( *clusterToTPMap_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
548  else numberOfSharedHits-=getDoubleCount( *hitAssociator_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
549  }
550 
551  double quality;
552  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
553  else if( numberOfValidTrackHits != 0 ) quality=
554  (static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits ));
555  else quality=0;
556 
557  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && numberOfValidTrackHits == 3 && numberOfSharedHits < 3) )
558  {
559  returnValue.insert( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), std::make_pair( trackingParticleRef, quality ) );
560  }
561  }
562  }
563 
564  LogTrace( "TrackAssociator" ) << "% of Assoc Seeds=" << ((double)returnValue.size()) / ((double)pSeedCollectionHandle_->size());
565  returnValue.post_insert();
566  return returnValue;
567 
568 }
569 
571  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
572 {
573 
574  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHitsImpl::associateSimToReco - #seeds=" << pSeedCollectionHandle_->size()
575  << " #TPs=" << trackingParticleCollectionHandle->size();
576 
577  reco::SimToRecoCollectionSeed returnValue;
578 
579  size_t collectionSize=pSeedCollectionHandle_->size();
580 
581  for( size_t i=0; i < collectionSize; ++i )
582  {
583  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
584 
585  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
586  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=
587  (clusterToTPMap_) ? associateTrack( *clusterToTPMap_, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *hitAssociator_, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second );
588  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
589  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
590  ++iTrackingParticleQualityPair )
591  {
592  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
593  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
594  size_t numberOfValidTrackHits=pSeed->recHits().second - pSeed->recHits().first;
595  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
596 
597  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
598 
599  //if electron subtract double counting
600  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
601  {
602  if( clusterToTPMap_ ) numberOfSharedHits-=getDoubleCount( *clusterToTPMap_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
603  else numberOfSharedHits-=getDoubleCount( *hitAssociator_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
604  }
605 
606  if( simToRecoDenominator_ == denomsim || (numberOfSharedHits < 3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
607  {
608  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
609  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
610  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
611  // hits in the tracker.
612  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
613  }
614 
615  double purity=static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits );
616  double quality;
617  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
618  else if( simToRecoDenominator_ == denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>( numberOfSharedHits )
619  / static_cast<double>( numberOfSimulatedHits );
620  else if( simToRecoDenominator_ == denomreco && numberOfValidTrackHits != 0 ) quality=purity;
621  else quality=0;
622 
623  if( quality > qualitySimToReco_ && !(threeHitTracksAreSpecial_ && numberOfSimulatedHits == 3 && numberOfSharedHits < 3)
624  && (absoluteNumberOfHits_ || (purity > puritySimToReco_)) )
625  {
626  returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), quality ) );
627  }
628  }
629  }
630  return returnValue;
631 
632  LogTrace("TrackAssociator") << "% of Assoc TPs=" << ((double)returnValue.size())/((double)trackingParticleCollectionHandle->size());
633  returnValue.post_insert();
634  return returnValue;
635 }
ClusterRef cluster() const
int i
Definition: DBlmapReader.cc:9
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
std::vector< std::pair< OmniClusterRef, TrackingParticleRef > > ClusterTPAssociationList
std::shared_ptr< const ClusterTPAssociationList > clusterToTPMap_
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
g4t_iterator g4Track_begin() const
OmniClusterRef const & stereoClusterRef() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
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
reco::RecoToSimCollection associateRecoToSimImplementation(T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator) const
The method that does the work for both overloads of associateRecoToSim.
const TrackingRecHit * getHitFromIter(trackingRecHit_iterator iter) const
std::vector< std::pair< SimTrackIdentifiers, size_t > > 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 ...
void post_insert()
post insert action
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
ClusterRef cluster() const
#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)
bool clusterTPAssociationListGreater(std::pair< OmniClusterRef, TrackingParticleRef > i, std::pair< OmniClusterRef, TrackingParticleRef > j)
TrackToTrackingParticleAssociator that associates by hits a bit quicker than the normal TrackAssociat...
std::vector< SimTrack >::const_iterator g4t_iterator
std::shared_ptr< const TrackerHitAssociator > hitAssociator_
creates either a ClusterTPAssociationList OR a TrackerHitAssociator and stores it in the provided uni...
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
std::vector< std::pair< edm::Ref< TrackingParticleCollection >, size_t > > associateTrack(const TrackerHitAssociator &hitAssociator, T_TPCollection trackingParticles, iter begin, iter end) const
Returns the TrackingParticle that has the most associated hits to the given track.
int getDoubleCount(const TrackerHitAssociator &hitAssociator, iter begin, iter end, TrackingParticleRef associatedTrackingParticle) const
This method was copied almost verbatim from the standard TrackAssociatorByHits.
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
ClusterRef cluster() const
Definition: SiPixelRecHit.h:49
QuickTrackAssociatorByHitsImpl(std::shared_ptr< const TrackerHitAssociator > hitAssoc, std::shared_ptr< const ClusterTPAssociationList > clusterToTPMap, bool absoluteNumberOfHits, double qualitySimToReco, double puritySimToReco, double cutRecoToSim, bool threeHitTracksAreSpecial, SimToRecoDenomType simToRecoDenominator)
range recHits() const
bool isValid() const
string const
Definition: compareJSON.py:14
int numberOfHits() const
Gives the total number of hits, including muon hits. Hits on overlaps in the same layer count separat...
SiStripRecHit2D monoHit() const
std::vector< SimHitIdpr > associateHitId(const TrackingRecHit &thit) const
#define begin
Definition: vmac.h:30
reco::SimToRecoCollection associateSimToRecoImplementation(T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator) const
The method that does the work for both overloads of associateSimToReco.
unsigned short found() const
Number of valid hits on track.
Definition: Track.h:194
size_type size() const
Size of the RefVector.
Definition: RefVector.h:89
Monte Carlo truth information used for tracking validation.
DetId geographicalId() const
g4t_iterator g4Track_end() const
edm::Ref< TrackingParticleCollection > TrackingParticleRef
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
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.
Definition: Track.h:109