test
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 
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  template <typename T>
88  void fillKeys(std::unordered_set<T>& keys, const edm::RefVector<TrackingParticleCollection>& collection) {
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 
145  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection ) const
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 
157  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection) const
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  // Ignore TrackingParticles with no hits
300  if( pTrackingParticle->numberOfHits()==0 ) continue;
301 
302  double numberOfAssociatedHits=0;
303  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
304  // the number of reco hits associated to that sim track to the total number of associated hits.
305  for( const auto& identifierCountPair: hitIdentifiers)
306  {
307  if( trackingParticleContainsIdentifier( pTrackingParticle, identifierCountPair.first ) ) numberOfAssociatedHits+=identifierCountPair.second;
308  }
309 
310  if( numberOfAssociatedHits>0 )
311  {
312  returnValue.push_back( std::make_pair( getRefToTrackingParticleAt(trackingParticles,i), numberOfAssociatedHits ) );
313  }
314  }
315 
316  return returnValue;
317 }
318 
319 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
320 {
321  // Note that the trackingParticles parameter is not actually required since all the information is in clusterToTPMap,
322  // but the method signature has to match the other overload because it is called from a templated method.
323 
324  // Note further, that we can't completely ignore the
325  // trackingParticles parameter, in case it is a subset of those
326  // TrackingParticles used to construct clusterToTPMap (via the
327  // TrackingParticleRefVector overloads). The trackingParticles
328  // parameter is still ignored since looping over it on every call
329  // would be expensive, but the keys of the TrackingParticleRefs are
330  // cached to an unordered_set (trackingParticleKeys) which is used
331  // as a fast search structure.
332 
333  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the weighted number of associated clusters as "second"
334  // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
335  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,double> > returnValue;
336  if( clusterToTPMap.empty() ) return returnValue;
337 
338  // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
339  // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this
340  // vector should be fewer than the number of clusters. The pair::second entries should add up to the total
341  // number of reco clusters though.
342  std::vector<OmniClusterRef> oClusters=getMatchedClusters( begin, end );
343 
344  std::map < TrackingParticleRef, double > lmap;
345  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
346  {
347  auto range = clusterToTPMap.equal_range(*it);
348  const double weight = it->isPixel() ? pixelHitWeight_ : 1.0;
349  if( range.first != range.second )
350  {
351  for( auto ip=range.first; ip != range.second; ++ip )
352  {
353 
354  const TrackingParticleRef trackingParticle=(ip->second);
355 
356  if(trackingParticleKeys && trackingParticleKeys->find(trackingParticle.key()) == trackingParticleKeys->end())
357  continue;
358 
359  // Ignore TrackingParticles with no hits
360  if( trackingParticle->numberOfHits() == 0 ) continue;
361 
362  /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
363  std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
364  auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
365  if ((tp_range.second-tp_range.first)>1) {
366  edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
367  }
368  if(tp_range.first != tp_range.second) {
369  tp_range.first->second++;
370  } else {
371  returnValue.push_back(tpIntPair);
372  std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
373  }
374  */
375  auto jpos=lmap.find( trackingParticle );
376  if( jpos != lmap.end() ) jpos->second += weight;
377  else lmap.insert( std::make_pair( trackingParticle, weight ) );
378  }
379  }
380  }
381  // now copy the map to returnValue
382  for( auto ip=lmap.begin(); ip != lmap.end(); ++ip )
383  {
384  returnValue.push_back( std::make_pair( ip->first, ip->second ) );
385  }
386  return returnValue;
387 }
388 
389 template<typename iter> std::vector<OmniClusterRef> QuickTrackAssociatorByHitsImpl::getMatchedClusters(iter begin, iter end) const
390 {
391  std::vector<OmniClusterRef> returnValue;
392  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
393  const TrackingRecHit* rhit = getHitFromIter(iRecHit);
394  if (rhit->isValid()) {
395  int subdetid = rhit->geographicalId().subdetId();
397  const SiPixelRecHit* pRHit = dynamic_cast<const SiPixelRecHit*>(rhit);
398  if (!pRHit->cluster().isNonnull())
399  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
400  returnValue.push_back(pRHit->omniClusterRef());
401  }
402  else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) {
403  const std::type_info &tid = typeid(*rhit);
404  if (tid == typeid(SiStripMatchedRecHit2D)) {
405  const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast<const SiStripMatchedRecHit2D*>(rhit);
406  if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull())
407  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
408  returnValue.push_back(sMatchedRHit->monoClusterRef());
409  returnValue.push_back(sMatchedRHit->stereoClusterRef());
410  }
411  else if (tid == typeid(SiStripRecHit2D)) {
412  const SiStripRecHit2D* sRHit = dynamic_cast<const SiStripRecHit2D*>(rhit);
413  if (!sRHit->cluster().isNonnull())
414  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
415  returnValue.push_back(sRHit->omniClusterRef());
416  }
417  else if (tid == typeid(SiStripRecHit1D)) {
418  const SiStripRecHit1D* sRHit = dynamic_cast<const SiStripRecHit1D*>(rhit);
419  if (!sRHit->cluster().isNonnull())
420  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
421  returnValue.push_back(sRHit->omniClusterRef());
422  }
423  else if (tid == typeid(Phase2TrackerRecHit1D)) {
424  const Phase2TrackerRecHit1D* ph2Hit = dynamic_cast<const Phase2TrackerRecHit1D*>(rhit);
425  if (!ph2Hit->cluster().isNonnull() )
426  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
427  returnValue.push_back(ph2Hit->omniClusterRef());
428  }
429  else {
430  auto const & thit = static_cast<BaseTrackerRecHit const&>(*rhit);
431  if ( thit.isProjected() ) {
432  } else {
433  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid;
434  }
435  }
436  }
437  else {
438  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid;
439  }
440  }
441  }
442  return returnValue;
443 }
444 
445 template<typename iter> std::vector< std::pair<QuickTrackAssociatorByHitsImpl::SimTrackIdentifiers,double> > QuickTrackAssociatorByHitsImpl::getAllSimTrackIdentifiers( const TrackerHitAssociator& hitAssociator, iter begin, iter end ) const
446 {
447  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
448  std::vector < std::pair<SimTrackIdentifiers,double> > returnValue;
449 
450  std::vector<SimTrackIdentifiers> simTrackIdentifiers;
451  // Loop over all of the rec hits in the track
452  //iter tRHIterBeginEnd = getTRHIterBeginEnd( pTrack );
453  for( iter iRecHit=begin; iRecHit != end; ++iRecHit )
454  {
455  if( getHitFromIter( iRecHit )->isValid() )
456  {
457  simTrackIdentifiers.clear();
458 
459  // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
460  // have merged (as far as I know).
461  hitAssociator.associateHitId( *(getHitFromIter( iRecHit )), simTrackIdentifiers ); // This call fills simTrackIdentifiers
462 
463  const auto subdetId = getHitFromIter(iRecHit)->geographicalId().subdetId();
464  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0;
465 
466  // Loop over each identifier, and add it to the return value only if it's not already in there
467  for( std::vector<SimTrackIdentifiers>::const_iterator iIdentifier=simTrackIdentifiers.begin(); iIdentifier != simTrackIdentifiers.end();
468  ++iIdentifier )
469  {
470  std::vector<std::pair<SimTrackIdentifiers,double> >::iterator iIdentifierCountPair;
471  for(auto iIdentifierCountPair=returnValue.begin(); iIdentifierCountPair != returnValue.end(); ++iIdentifierCountPair )
472  {
473  if( iIdentifierCountPair->first.first == iIdentifier->first && iIdentifierCountPair->first.second == iIdentifier->second )
474  {
475  // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
476  iIdentifierCountPair->second += weight;
477  break;
478  }
479  }
480  if( iIdentifierCountPair == returnValue.end() ) returnValue.push_back( std::make_pair( *iIdentifier, 1.0 ) );
481  // This identifier wasn't found, so add it
482  }
483  }
484  }
485  return returnValue;
486 }
487 
489 {
490  // Loop over all of the g4 tracks in the tracking particle
491  for( std::vector<SimTrack>::const_iterator iSimTrack=pTrackingParticle->g4Track_begin(); iSimTrack != pTrackingParticle->g4Track_end();
492  ++iSimTrack )
493  {
494  // And see if the sim track identifiers match
495  if( iSimTrack->eventId() == identifier.second && iSimTrack->trackId() == identifier.first )
496  {
497  return true;
498  }
499  }
500 
501  // If control has made it this far then none of the identifiers were found in
502  // any of the g4 tracks, so return false.
503  return false;
504 }
505 
506 template<typename iter> double QuickTrackAssociatorByHitsImpl::getDoubleCount( const TrackerHitAssociator& hitAssociator, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
507 {
508  // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
509  // it makes I'll go through and comment it properly.
510 
511  double doubleCount=0.0;
512  std::vector < SimHitIdpr > SimTrackIdsDC;
513 
514  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
515  {
516  int idcount=0;
517 
518  SimTrackIdsDC.clear();
519  hitAssociator.associateHitId( *(getHitFromIter( iHit )), SimTrackIdsDC );
520  if( SimTrackIdsDC.size() > 1 )
521  {
522  for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle->g4Track_begin(); g4T != associatedTrackingParticle->g4Track_end();
523  ++g4T )
524  {
525  if( find( SimTrackIdsDC.begin(), SimTrackIdsDC.end(), SimHitIdpr( ( *g4T).trackId(), SimTrackIdsDC.begin()->second ) )
526  != SimTrackIdsDC.end() )
527  {
528  idcount++;
529  }
530  }
531  }
532  if( idcount > 1 ) {
533  const auto subdetId = getHitFromIter(iHit)->geographicalId().subdetId();
534  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0;
535  doubleCount += weight*(idcount - 1);
536  }
537  }
538 
539  return doubleCount;
540 }
541 
542 template<typename iter> double QuickTrackAssociatorByHitsImpl::getDoubleCount( const ClusterTPAssociation& clusterToTPList, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
543 {
544  // This code here was written by Subir Sarkar. I'm just splitting it off into a
545  // separate method. - Grimes 01/May/2014
546 
547  double doubleCount=0;
548  std::vector < SimHitIdpr > SimTrackIdsDC;
549 
550  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
551  {
552  int idcount=0;
553 
554  std::vector < OmniClusterRef > oClusters=getMatchedClusters( iHit, iHit + 1 ); //only for the cluster being checked
555  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
556  {
557  auto range = clusterToTPList.equal_range(*it);
558  if( range.first != range.second )
559  {
560  for( auto ip=range.first; ip != range.second; ++ip )
561  {
562  const TrackingParticleRef trackingParticle=(ip->second);
563  if( associatedTrackingParticle == trackingParticle )
564  {
565  idcount++;
566  }
567  }
568  }
569  }
570 
571  if( idcount > 1 ) {
572  const auto subdetId = getHitFromIter(iHit)->geographicalId().subdetId();
573  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0;
574  doubleCount += weight*(idcount - 1);
575  }
576  }
577 
578  return doubleCount;
579 }
580 
582  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
583 {
584 
585  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHitsImpl::associateRecoToSim - #seeds=" << pSeedCollectionHandle_->size()
586  << " #TPs=" << trackingParticleCollectionHandle->size();
587 
589 
590  size_t collectionSize=pSeedCollectionHandle_->size();
591 
592  for( size_t i=0; i < collectionSize; ++i )
593  {
594  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
595 
596  // The return of this function has first as the index and second as the number of associated hits
597  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,double> > trackingParticleQualityPairs=
598  (clusterToTPMap_) ? associateTrack( *clusterToTPMap_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *hitAssociator_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second );
599  for( auto iTrackingParticleQualityPair=
600  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
601  ++iTrackingParticleQualityPair )
602  {
603  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
604  double numberOfSharedHits=iTrackingParticleQualityPair->second;
605  double numberOfValidTrackHits=weightedNumberOfTrackHits(*pSeed);
606 
607  if( numberOfSharedHits == 0.0 ) continue; // No point in continuing if there was no association
608 
609  //if electron subtract double counting
610  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
611  {
612  if( clusterToTPMap_ ) numberOfSharedHits-=getDoubleCount( *clusterToTPMap_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
613  else numberOfSharedHits-=getDoubleCount( *hitAssociator_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
614  }
615 
616  double quality;
617  if( absoluteNumberOfHits_ ) quality = numberOfSharedHits;
618  else if( numberOfValidTrackHits != 0.0 ) quality = numberOfSharedHits / numberOfValidTrackHits;
619  else quality=0;
620 
621  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && pSeed->nHits() == 3 && numberOfSharedHits < 3.0) )
622  {
623  returnValue.insert( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), std::make_pair( trackingParticleRef, quality ) );
624  }
625  }
626  }
627 
628  LogTrace( "TrackAssociator" ) << "% of Assoc Seeds=" << ((double)returnValue.size()) / ((double)pSeedCollectionHandle_->size());
629  returnValue.post_insert();
630  return returnValue;
631 
632 }
633 
635  const edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle) const
636 {
637 
638  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHitsImpl::associateSimToReco - #seeds=" << pSeedCollectionHandle_->size()
639  << " #TPs=" << trackingParticleCollectionHandle->size();
640 
642  if(trackingParticleCollectionHandle->empty())
643  return returnValue;
644 
645  if(clusterToTPMap_) {
646  checkClusterMapProductID(*clusterToTPMap_, trackingParticleCollectionHandle);
647  }
648 
649  size_t collectionSize=pSeedCollectionHandle_->size();
650 
651  for( size_t i=0; i < collectionSize; ++i )
652  {
653  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
654 
655  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
656  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,double> > trackingParticleQualityPairs=
657  (clusterToTPMap_) ? associateTrack( *clusterToTPMap_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *hitAssociator_, trackingParticleCollectionHandle, nullptr, pSeed->recHits().first, pSeed->recHits().second );
658  for( auto iTrackingParticleQualityPair=
659  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
660  ++iTrackingParticleQualityPair )
661  {
662  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
663  double numberOfSharedHits=iTrackingParticleQualityPair->second;
664  double numberOfValidTrackHits=weightedNumberOfTrackHits(*pSeed);
665  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
666 
667  if( numberOfSharedHits == 0.0 ) continue; // No point in continuing if there was no association
668 
669  //if electron subtract double counting
670  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
671  {
672  if( clusterToTPMap_ ) numberOfSharedHits-=getDoubleCount( *clusterToTPMap_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
673  else numberOfSharedHits-=getDoubleCount( *hitAssociator_, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
674  }
675 
676  if( simToRecoDenominator_ == denomsim || (numberOfSharedHits < 3.0 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
677  {
678  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
679  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
680  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
681  // hits in the tracker.
682  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
683  }
684 
685  double purity = numberOfSharedHits / numberOfValidTrackHits;
686  double quality;
687  if( absoluteNumberOfHits_ ) quality = numberOfSharedHits;
688  else if( simToRecoDenominator_ == denomsim && numberOfSimulatedHits != 0 ) quality= numberOfSharedHits
689  / static_cast<double>( numberOfSimulatedHits );
690  else if( simToRecoDenominator_ == denomreco && numberOfValidTrackHits != 0.0 ) quality=purity;
691  else quality=0;
692 
693  if( quality > qualitySimToReco_ && !(threeHitTracksAreSpecial_ && numberOfSimulatedHits == 3 && numberOfSharedHits < 3.0)
694  && (absoluteNumberOfHits_ || (purity > puritySimToReco_)) )
695  {
696  returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), quality ) );
697  }
698  }
699  }
700 
701  LogTrace("TrackAssociator") << "% of Assoc TPs=" << ((double)returnValue.size())/((double)trackingParticleCollectionHandle->size());
702  returnValue.post_insert();
703  return returnValue;
704 }
705 
707  const reco::HitPattern& p = track.hitPattern();
708  const auto pixelHits = p.numberOfValidPixelHits();
709  const auto otherHits = p.numberOfValidHits() - pixelHits;
710  return pixelHits*pixelHitWeight_ + otherHits;
711 }
712 
714  double sum = 0.0;
715  for(auto iHit=seed.recHits().first; iHit!=seed.recHits().second; ++iHit) {
716  const auto subdetId = getHitFromIter(iHit)->geographicalId().subdetId();
717  const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0;
718  sum += weight;
719  }
720  return sum;
721 }
ClusterRef cluster() const
int i
Definition: DBlmapReader.cc:9
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.
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
int numberOfValidHits() const
Definition: HitPattern.h:823
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
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)
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
void post_insert()
post insert action
def move
Definition: eostools.py:510
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
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
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
unsigned int nHits() const
std::unordered_set< reco::RecoToSimCollection::index_type > TrackingParticleRefKeySet
Set for TrackingParticleRef keys.
#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.
DetId geographicalId() const
int weight
Definition: histoStyle.py:50
g4t_iterator g4Track_end() const
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 ...
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