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  template <typename T>
87  void fillKeys(std::unordered_set<T>& keys, const edm::RefVector<TrackingParticleCollection>& collection) {
88  for(const auto& ref: collection) {
89  keys.insert(ref.key());
90  }
91  }
92 
93  template <typename Coll>
94  void checkClusterMapProductID(const ClusterTPAssociation& clusterToTPMap, const Coll& collection) {
95  clusterToTPMap.checkMappedProductID(collection.id());
96  }
97 
98  template <typename Coll>
99  void checkClusterMapProductID(const TrackerHitAssociator& hitAssociator, const Coll& collection) {}
100 
101 } // end of the unnamed namespace
102 
104  std::unique_ptr<const TrackerHitAssociator> hitAssoc,
105  const ClusterTPAssociation *clusterToTPMap,
106 
107  bool absoluteNumberOfHits,
108  double qualitySimToReco,
109  double puritySimToReco,
110  double cutRecoToSim,
111  bool threeHitTracksAreSpecial,
112  SimToRecoDenomType simToRecoDenominator):
113  productGetter_(&productGetter),
114  hitAssociator_(std::move(hitAssoc)),
115  clusterToTPMap_(clusterToTPMap),
116  qualitySimToReco_(qualitySimToReco),
117  puritySimToReco_(puritySimToReco),
118  cutRecoToSim_(cutRecoToSim),
119  simToRecoDenominator_(simToRecoDenominator) ,
120  threeHitTracksAreSpecial_(threeHitTracksAreSpecial),
121  absoluteNumberOfHits_(absoluteNumberOfHits)
122  {}
123 
124 
126  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
127 {
128  // Only pass the one that was successfully created to the templated method.
129  if( not clusterToTPMap_ ) return associateRecoToSimImplementation( trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *hitAssociator_ );
130  else return associateRecoToSimImplementation( trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *clusterToTPMap_ );
131 }
132 
134  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
135 {
136  // Only pass the one that was successfully created to the templated method.
137  if( not clusterToTPMap_ ) return associateSimToRecoImplementation( trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *hitAssociator_ );
138  else return associateSimToRecoImplementation( trackCollectionHandle, trackingParticleCollectionHandle, nullptr, *clusterToTPMap_ );
139 }
140 
142  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection ) const
143 {
144  // Only pass the one that was successfully created to the templated method.
145  if( not clusterToTPMap_ ) return associateRecoToSimImplementation( trackCollection, trackingParticleCollection, nullptr, *hitAssociator_ );
146  else {
148  fillKeys(tpKeys, trackingParticleCollection);
149  return associateRecoToSimImplementation( trackCollection, trackingParticleCollection, &tpKeys, *clusterToTPMap_ );
150  }
151 }
152 
154  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection) const
155 {
156  // Only pass the one that was successfully created to the templated method.
157  if( not clusterToTPMap_ ) return associateSimToRecoImplementation( trackCollection, trackingParticleCollection, nullptr, *hitAssociator_ );
158  else {
160  fillKeys(tpKeys, trackingParticleCollection);
161  return associateSimToRecoImplementation( trackCollection, trackingParticleCollection, &tpKeys, *clusterToTPMap_ );
162  }
163 }
164 
165 
166 template<class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
167 reco::RecoToSimCollection QuickTrackAssociatorByHitsImpl::associateRecoToSimImplementation( const T_TrackCollection& trackCollection, const T_TrackingParticleCollection& trackingParticleCollection, const TrackingParticleRefKeySet *trackingParticleKeys, T_hitOrClusterAssociator hitOrClusterAssociator ) const
168 {
170 
171  checkClusterMapProductID(hitOrClusterAssociator, trackingParticleCollection);
172 
173  size_t collectionSize=::collectionSize(trackCollection); // Delegate away type specific part
174 
175  for( size_t i=0; i < collectionSize; ++i )
176  {
177  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
178 
179  // The return of this function has first as the index and second as the number of associated hits
180  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, trackingParticleKeys, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
181 
182  // int nt = 0;
183  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
184  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
185  ++iTrackingParticleQualityPair )
186  {
187  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
188  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
189  size_t numberOfValidTrackHits=pTrack->found();
190 
191  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
192 
193  //if electron subtract double counting
194  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
195  {
196  numberOfSharedHits-=getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
197  }
198 
199  double quality;
200  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
201  else if( numberOfValidTrackHits != 0 ) quality=
202  (static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits ));
203  else quality=0;
204  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && numberOfValidTrackHits == 3 && numberOfSharedHits < 3) )
205  {
206  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
207  returnValue.insert( ::getRefToTrackAt(trackCollection,i), std::make_pair( trackingParticleRef, quality ) );
208  }
209  }
210  }
211  returnValue.post_insert();
212  return returnValue;
213 }
214 
215 template<class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
216 reco::SimToRecoCollection QuickTrackAssociatorByHitsImpl::associateSimToRecoImplementation( const T_TrackCollection& trackCollection, const T_TrackingParticleCollection& trackingParticleCollection, const TrackingParticleRefKeySet *trackingParticleKeys, T_hitOrClusterAssociator hitOrClusterAssociator ) const
217 {
219 
220  checkClusterMapProductID(hitOrClusterAssociator, trackingParticleCollection);
221 
222  size_t collectionSize=::collectionSize(trackCollection); // Delegate away type specific part
223 
224  for( size_t i=0; i<collectionSize; ++i )
225  {
226  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
227 
228  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
229  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, trackingParticleKeys, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
230 
231  // int nt = 0;
232  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
233  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
234  {
235  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
236  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
237  size_t numberOfValidTrackHits=pTrack->found();
238  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
239 
240  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
241 
242  if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
243  {
244  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
245  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
246  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
247  // hits in the tracker.
248  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
249  }
250 
251  //if electron subtract double counting
252  if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
253  {
254  numberOfSharedHits -= getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
255  }
256 
257  double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
258  double quality;
259  if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
260  else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
261  else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
262  else quality=0;
263 
264  if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
265  {
266  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
267  returnValue.insert( trackingParticleRef, std::make_pair( ::getRefToTrackAt(trackCollection,i), quality ) );
268  }
269  }
270  }
271  returnValue.post_insert();
272  return returnValue;
273 
274 }
275 
276 template<typename T_TPCollection,typename iter> std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHitsImpl::associateTrack( const TrackerHitAssociator& hitAssociator, const T_TPCollection& trackingParticles, const TrackingParticleRefKeySet *trackingParticleKeys, iter begin, iter end ) const
277 {
278  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated hits as "second"
279  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
280 
281  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
282  // 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
283  // number of reco hits. The pair::second entries should add up to the total number of reco hits though.
284  std::vector< std::pair<SimTrackIdentifiers,size_t> > hitIdentifiers=getAllSimTrackIdentifiers( hitAssociator, begin, end );
285 
286  // Loop over the TrackingParticles
287  size_t collectionSize=::collectionSize(trackingParticles);
288 
289  for( size_t i=0; i<collectionSize; ++i )
290  {
291  const TrackingParticle* pTrackingParticle=getTrackingParticleAt( trackingParticles, i );
292 
293  // Ignore TrackingParticles with no hits
294  if( pTrackingParticle->numberOfHits()==0 ) continue;
295 
296  size_t numberOfAssociatedHits=0;
297  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
298  // the number of reco hits associated to that sim track to the total number of associated hits.
299  for( std::vector< std::pair<SimTrackIdentifiers,size_t> >::const_iterator iIdentifierCountPair=hitIdentifiers.begin(); iIdentifierCountPair!=hitIdentifiers.end(); ++iIdentifierCountPair )
300  {
301  if( trackingParticleContainsIdentifier( pTrackingParticle, iIdentifierCountPair->first ) ) numberOfAssociatedHits+=iIdentifierCountPair->second;
302  }
303 
304  if( numberOfAssociatedHits>0 )
305  {
306  returnValue.push_back( std::make_pair( getRefToTrackingParticleAt(trackingParticles,i), numberOfAssociatedHits ) );
307  }
308  }
309 
310  return returnValue;
311 }
312 
313 template<typename T_TPCollection,typename iter> std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHitsImpl::associateTrack( const ClusterTPAssociation& clusterToTPMap, const T_TPCollection& trackingParticles, const TrackingParticleRefKeySet *trackingParticleKeys, iter begin, iter end ) const
314 {
315  // Note that the trackingParticles parameter is not actually required since all the information is in clusterToTPMap,
316  // but the method signature has to match the other overload because it is called from a templated method.
317 
318  // Note further, that we can't completely ignore the
319  // trackingParticles parameter, in case it is a subset of those
320  // TrackingParticles used to construct clusterToTPMap (via the
321  // TrackingParticleRefVector overloads). The trackingParticles
322  // parameter is still ignored since looping over it on every call
323  // would be expensive, but the keys of the TrackingParticleRefs are
324  // cached to an unordered_set (trackingParticleKeys) which is used
325  // as a fast search structure.
326 
327  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated clusters as "second"
328  // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
329  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
330  if( clusterToTPMap.empty() ) return returnValue;
331 
332  // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
333  // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this
334  // vector should be fewer than the number of clusters. The pair::second entries should add up to the total
335  // number of reco clusters though.
336  std::vector<OmniClusterRef> oClusters=getMatchedClusters( begin, end );
337 
338  std::map < TrackingParticleRef, size_t > lmap;
339  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
340  {
341  auto range = clusterToTPMap.equal_range(*it);
342  if( range.first != range.second )
343  {
344  for( auto ip=range.first; ip != range.second; ++ip )
345  {
346 
347  const TrackingParticleRef trackingParticle=(ip->second);
348 
349  if(trackingParticleKeys && trackingParticleKeys->find(trackingParticle.key()) == trackingParticleKeys->end())
350  continue;
351 
352  // Ignore TrackingParticles with no hits
353  if( trackingParticle->numberOfHits() == 0 ) continue;
354 
355  /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
356  std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
357  auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
358  if ((tp_range.second-tp_range.first)>1) {
359  edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
360  }
361  if(tp_range.first != tp_range.second) {
362  tp_range.first->second++;
363  } else {
364  returnValue.push_back(tpIntPair);
365  std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
366  }
367  */
368  auto jpos=lmap.find( trackingParticle );
369  if( jpos != lmap.end() ) ++jpos->second;
370  else lmap.insert( std::make_pair( trackingParticle, 1 ) );
371  }
372  }
373  }
374  // now copy the map to returnValue
375  for( auto ip=lmap.begin(); ip != lmap.end(); ++ip )
376  {
377  returnValue.push_back( std::make_pair( ip->first, ip->second ) );
378  }
379  return returnValue;
380 }
381 
382 template<typename iter> std::vector<OmniClusterRef> QuickTrackAssociatorByHitsImpl::getMatchedClusters(iter begin, iter end) const
383 {
384  std::vector<OmniClusterRef> returnValue;
385  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
386  const TrackingRecHit* rhit = getHitFromIter(iRecHit);
387  if (rhit->isValid()) {
388  int subdetid = rhit->geographicalId().subdetId();
390  const SiPixelRecHit* pRHit = dynamic_cast<const SiPixelRecHit*>(rhit);
391  if (!pRHit->cluster().isNonnull())
392  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
393  returnValue.push_back(pRHit->omniClusterRef());
394  }
395  else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) {
396  const std::type_info &tid = typeid(*rhit);
397  if (tid == typeid(SiStripMatchedRecHit2D)) {
398  const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast<const SiStripMatchedRecHit2D*>(rhit);
399  if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull())
400  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
401  returnValue.push_back(sMatchedRHit->monoClusterRef());
402  returnValue.push_back(sMatchedRHit->stereoClusterRef());
403  }
404  else if (tid == typeid(SiStripRecHit2D)) {
405  const SiStripRecHit2D* sRHit = dynamic_cast<const SiStripRecHit2D*>(rhit);
406  if (!sRHit->cluster().isNonnull())
407  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
408  returnValue.push_back(sRHit->omniClusterRef());
409  }
410  else if (tid == typeid(SiStripRecHit1D)) {
411  const SiStripRecHit1D* sRHit = dynamic_cast<const SiStripRecHit1D*>(rhit);
412  if (!sRHit->cluster().isNonnull())
413  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
414  returnValue.push_back(sRHit->omniClusterRef());
415  }
416  else {
417  auto const & thit = static_cast<BaseTrackerRecHit const&>(*rhit);
418  if ( thit.isProjected() ) {
419  } else {
420  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid;
421  }
422  }
423  }
424  else {
425  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid;
426  }
427  }
428  }
429  return returnValue;
430 }
431 
432 template<typename iter> std::vector< std::pair<QuickTrackAssociatorByHitsImpl::SimTrackIdentifiers,size_t> > QuickTrackAssociatorByHitsImpl::getAllSimTrackIdentifiers( const TrackerHitAssociator& hitAssociator, iter begin, iter end ) const
433 {
434  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
435  std::vector < std::pair<SimTrackIdentifiers,size_t> > returnValue;
436 
437  std::vector<SimTrackIdentifiers> simTrackIdentifiers;
438  // Loop over all of the rec hits in the track
439  //iter tRHIterBeginEnd = getTRHIterBeginEnd( pTrack );
440  for( iter iRecHit=begin; iRecHit != end; ++iRecHit )
441  {
442  if( getHitFromIter( iRecHit )->isValid() )
443  {
444  simTrackIdentifiers.clear();
445 
446  // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
447  // have merged (as far as I know).
448  hitAssociator.associateHitId( *(getHitFromIter( iRecHit )), simTrackIdentifiers ); // This call fills simTrackIdentifiers
449  // Loop over each identifier, and add it to the return value only if it's not already in there
450  for( std::vector<SimTrackIdentifiers>::const_iterator iIdentifier=simTrackIdentifiers.begin(); iIdentifier != simTrackIdentifiers.end();
451  ++iIdentifier )
452  {
453  std::vector<std::pair<SimTrackIdentifiers,size_t> >::iterator iIdentifierCountPair;
454  for( iIdentifierCountPair=returnValue.begin(); iIdentifierCountPair != returnValue.end(); ++iIdentifierCountPair )
455  {
456  if( iIdentifierCountPair->first.first == iIdentifier->first && iIdentifierCountPair->first.second == iIdentifier->second )
457  {
458  // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
459  ++iIdentifierCountPair->second;
460  break;
461  }
462  }
463  if( iIdentifierCountPair == returnValue.end() ) returnValue.push_back( std::make_pair( *iIdentifier, 1 ) );
464  // This identifier wasn't found, so add it
465  }
466  }
467  }
468  return returnValue;
469 }
470 
472 {
473  // Loop over all of the g4 tracks in the tracking particle
474  for( std::vector<SimTrack>::const_iterator iSimTrack=pTrackingParticle->g4Track_begin(); iSimTrack != pTrackingParticle->g4Track_end();
475  ++iSimTrack )
476  {
477  // And see if the sim track identifiers match
478  if( iSimTrack->eventId() == identifier.second && iSimTrack->trackId() == identifier.first )
479  {
480  return true;
481  }
482  }
483 
484  // If control has made it this far then none of the identifiers were found in
485  // any of the g4 tracks, so return false.
486  return false;
487 }
488 
489 template<typename iter> int QuickTrackAssociatorByHitsImpl::getDoubleCount( const TrackerHitAssociator& hitAssociator, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
490 {
491  // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
492  // it makes I'll go through and comment it properly.
493 
494  int doubleCount=0;
495  std::vector < SimHitIdpr > SimTrackIdsDC;
496 
497  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
498  {
499  int idcount=0;
500 
501  SimTrackIdsDC.clear();
502  hitAssociator.associateHitId( *(getHitFromIter( iHit )), SimTrackIdsDC );
503  if( SimTrackIdsDC.size() > 1 )
504  {
505  for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle->g4Track_begin(); g4T != associatedTrackingParticle->g4Track_end();
506  ++g4T )
507  {
508  if( find( SimTrackIdsDC.begin(), SimTrackIdsDC.end(), SimHitIdpr( ( *g4T).trackId(), SimTrackIdsDC.begin()->second ) )
509  != SimTrackIdsDC.end() )
510  {
511  idcount++;
512  }
513  }
514  }
515  if( idcount > 1 ) doubleCount+=(idcount - 1);
516  }
517 
518  return doubleCount;
519 }
520 
521 template<typename iter> int QuickTrackAssociatorByHitsImpl::getDoubleCount( const ClusterTPAssociation& clusterToTPList, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
522 {
523  // This code here was written by Subir Sarkar. I'm just splitting it off into a
524  // separate method. - Grimes 01/May/2014
525 
526  int doubleCount=0;
527  std::vector < SimHitIdpr > SimTrackIdsDC;
528 
529  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
530  {
531  int idcount=0;
532 
533  std::vector < OmniClusterRef > oClusters=getMatchedClusters( iHit, iHit + 1 ); //only for the cluster being checked
534  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
535  {
536  auto range = clusterToTPList.equal_range(*it);
537  if( range.first != range.second )
538  {
539  for( auto ip=range.first; ip != range.second; ++ip )
540  {
541  const TrackingParticleRef trackingParticle=(ip->second);
542  if( associatedTrackingParticle == trackingParticle )
543  {
544  idcount++;
545  }
546  }
547  }
548  }
549 
550  if( idcount > 1 ) doubleCount+=(idcount - 1);
551  }
552 
553  return doubleCount;
554 }
555 
557  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
558 {
559 
560  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHitsImpl::associateRecoToSim - #seeds=" << pSeedCollectionHandle_->size()
561  << " #TPs=" << trackingParticleCollectionHandle->size();
562 
564 
565  size_t collectionSize=pSeedCollectionHandle_->size();
566 
567  for( size_t i=0; i < collectionSize; ++i )
568  {
569  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
570 
571  // The return of this function has first as the index and second as the number of associated hits
572  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=
573  (clusterToTPMap_) ? associateTrack( *clusterToTPMap_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *hitAssociator_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second );
574  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
575  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
576  ++iTrackingParticleQualityPair )
577  {
578  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
579  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
580  size_t numberOfValidTrackHits=pSeed->recHits().second - pSeed->recHits().first;
581 
582  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
583 
584  //if electron subtract double counting
585  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
586  {
587  if( clusterToTPMap_ ) numberOfSharedHits-=getDoubleCount( *clusterToTPMap_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
588  else numberOfSharedHits-=getDoubleCount( *hitAssociator_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
589  }
590 
591  double quality;
592  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
593  else if( numberOfValidTrackHits != 0 ) quality=
594  (static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits ));
595  else quality=0;
596 
597  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && numberOfValidTrackHits == 3 && numberOfSharedHits < 3) )
598  {
599  returnValue.insert( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), std::make_pair( trackingParticleRef, quality ) );
600  }
601  }
602  }
603 
604  LogTrace( "TrackAssociator" ) << "% of Assoc Seeds=" << ((double)returnValue.size()) / ((double)pSeedCollectionHandle_->size());
605  returnValue.post_insert();
606  return returnValue;
607 
608 }
609 
611  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
612 {
613 
614  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHitsImpl::associateSimToReco - #seeds=" << pSeedCollectionHandle_->size()
615  << " #TPs=" << trackingParticleCollectionHandle->size();
616 
618 
619  if(clusterToTPMap_) {
620  checkClusterMapProductID(*clusterToTPMap_, trackingParticleCollectionHandle);
621  }
622 
623  size_t collectionSize=pSeedCollectionHandle_->size();
624 
625  for( size_t i=0; i < collectionSize; ++i )
626  {
627  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
628 
629  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
630  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=
631  (clusterToTPMap_) ? associateTrack( *clusterToTPMap_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *hitAssociator_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second );
632  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
633  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
634  ++iTrackingParticleQualityPair )
635  {
636  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
637  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
638  size_t numberOfValidTrackHits=pSeed->recHits().second - pSeed->recHits().first;
639  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
640 
641  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
642 
643  //if electron subtract double counting
644  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
645  {
646  if( clusterToTPMap_ ) numberOfSharedHits-=getDoubleCount( *clusterToTPMap_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
647  else numberOfSharedHits-=getDoubleCount( *hitAssociator_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
648  }
649 
650  if( simToRecoDenominator_ == denomsim || (numberOfSharedHits < 3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
651  {
652  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
653  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
654  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
655  // hits in the tracker.
656  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
657  }
658 
659  double purity=static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits );
660  double quality;
661  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
662  else if( simToRecoDenominator_ == denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>( numberOfSharedHits )
663  / static_cast<double>( numberOfSimulatedHits );
664  else if( simToRecoDenominator_ == denomreco && numberOfValidTrackHits != 0 ) quality=purity;
665  else quality=0;
666 
667  if( quality > qualitySimToReco_ && !(threeHitTracksAreSpecial_ && numberOfSimulatedHits == 3 && numberOfSharedHits < 3)
668  && (absoluteNumberOfHits_ || (purity > puritySimToReco_)) )
669  {
670  returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), quality ) );
671  }
672  }
673  }
674 
675  LogTrace("TrackAssociator") << "% of Assoc TPs=" << ((double)returnValue.size())/((double)trackingParticleCollectionHandle->size());
676  returnValue.post_insert();
677  return returnValue;
678 }
ClusterRef cluster() const
int i
Definition: DBlmapReader.cc:9
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:252
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.
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
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:7
EDProductGetter const * productGetter(std::atomic< void const * > const &iCache)
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::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.
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
def move
Definition: eostools.py:510
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< std::pair< edm::Ref< TrackingParticleCollection >, size_t > > 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.
ClusterRef cluster() const
range equal_range(const OmniClusterRef &key) 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)
std::vector< SimTrack >::const_iterator g4t_iterator
OmniClusterRef const & omniClusterRef() const
tuple trackCollection
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
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
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
void checkMappedProductID(const edm::HandleBase &mappedHandle) const
std::vector< SimHitIdpr > associateHitId(const TrackingRecHit &thit) const
std::unordered_set< reco::RecoToSimCollection::index_type > TrackingParticleRefKeySet
Set for TrackingParticleRef keys.
#define begin
Definition: vmac.h:30
unsigned short found() const
Number of valid hits on track.
Definition: Track.h:194
QuickTrackAssociatorByHitsImpl(edm::EDProductGetter const &productGetter, std::unique_ptr< const TrackerHitAssociator > hitAssoc, const ClusterTPAssociation *clusterToTPMap, bool absoluteNumberOfHits, double qualitySimToReco, double puritySimToReco, double cutRecoToSim, bool threeHitTracksAreSpecial, SimToRecoDenomType simToRecoDenominator)
size_type size() const
Size of the RefVector.
Definition: RefVector.h:99
Monte Carlo truth information used for tracking validation.
DetId geographicalId() const
g4t_iterator g4Track_end() const
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