CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
QuickTrackAssociatorByHits.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 
66  edm::RefToBase<reco::Track> getRefToTrackAt( const edm::RefToBaseVector<reco::Track>& trackCollection, size_t index )
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 
90  absoluteNumberOfHits_( config.getParameter<bool>( "AbsoluteNumberOfHits" ) ),
91  qualitySimToReco_( config.getParameter<double>( "Quality_SimToReco" ) ),
92  puritySimToReco_( config.getParameter<double>( "Purity_SimToReco" ) ),
93  cutRecoToSim_( config.getParameter<double>( "Cut_RecoToSim" ) ),
94  threeHitTracksAreSpecial_( config.getParameter<bool>( "ThreeHitTracksAreSpecial" ) ),
95  useClusterTPAssociation_( config.getParameter<bool>( "useClusterTPAssociation" ) ),
96  cluster2TPSrc_( config.getParameter < edm::InputTag > ("cluster2TPSrc") )
97 {
98  //
99  // Check whether the denominator when working out the percentage of shared hits should
100  // be the number of simulated hits or the number of reconstructed hits.
101  //
102  std::string denominatorString=config.getParameter<std::string>("SimToRecoDenominator");
103  if( denominatorString=="sim" ) simToRecoDenominator_=denomsim;
104  else if( denominatorString=="reco" ) simToRecoDenominator_=denomreco;
105  else throw cms::Exception( "QuickTrackAssociatorByHits" ) << "SimToRecoDenominator not specified as sim or reco";
106 
107  //
108  // Set up the parameter set for the hit associator
109  //
110  hitAssociatorParameters_.addParameter<bool>( "associatePixel", config.getParameter<bool>("associatePixel") );
111  hitAssociatorParameters_.addParameter<bool>( "associateStrip", config.getParameter<bool>("associateStrip") );
112  // This is the important one, it stops the hit associator searching through the list of sim hits.
113  // I only want to use the hit associator methods that work on the hit IDs (i.e. the uint32_t trackId
114  // and the EncodedEventId eventId) so I'm not interested in matching that to the PSimHit objects.
115  hitAssociatorParameters_.addParameter<bool>("associateRecoTracks",true);
116 
117  //
118  // Do some checks on whether UseGrouped or UseSplitting have been set. They're not used
119  // unlike the standard TrackAssociatorByHits so show a warning.
120  //
121  bool useGrouped, useSplitting;
122  if( config.exists("UseGrouped") ) useGrouped=config.getParameter<bool>("UseGrouped");
123  else useGrouped=true;
124 
125  if( config.exists("UseSplitting") ) useSplitting=config.getParameter<bool>("UseSplitting");
126  else useSplitting=true;
127 
128  // This associator works as though both UseGrouped and UseSplitting were set to true, so show a
129  // warning if this isn't the case.
130  if( !(useGrouped && useSplitting) )
131  {
132  edm::LogWarning("QuickTrackAssociatorByHits") << "UseGrouped and/or UseSplitting has been set to false, but this associator ignores that setting.";
133  }
134 }
135 
137 {
138  // No operation
139 }
140 
142  TrackingParticleCollection>& trackingParticleCollectionHandle, const edm::Event* pEvent, const edm::EventSetup* pSetup ) const
143 {
144  std::unique_ptr<ClusterTPAssociationList> pClusterToTPMap;
145  std::unique_ptr<TrackerHitAssociator> pHitAssociator;
146  // This call will set EITHER pClusterToTPMap OR pHitAssociator depending on what the user requested in the configuration.
147  prepareEitherHitAssociatorOrClusterToTPMap( pEvent, pClusterToTPMap, pHitAssociator );
148 
149  // Only pass the one that was successfully created to the templated method.
150  if( pClusterToTPMap==nullptr ) return associateRecoToSimImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *pHitAssociator );
151  else return associateRecoToSimImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *pClusterToTPMap );
152 }
153 
155  TrackingParticleCollection>& trackingParticleCollectionHandle, const edm::Event * pEvent, const edm::EventSetup * pSetup ) const
156 {
157  std::unique_ptr<ClusterTPAssociationList> pClusterToTPMap;
158  std::unique_ptr<TrackerHitAssociator> pHitAssociator;
159  // This call will set EITHER pClusterToTPMap OR pHitAssociator depending on what the user requested in the configuration.
160  prepareEitherHitAssociatorOrClusterToTPMap( pEvent, pClusterToTPMap, pHitAssociator );
161 
162  // Only pass the one that was successfully created to the templated method.
163  if( pClusterToTPMap==nullptr ) return associateSimToRecoImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *pHitAssociator );
164  else return associateSimToRecoImplementation( trackCollectionHandle, trackingParticleCollectionHandle, *pClusterToTPMap );
165 }
166 
168  TrackingParticleCollection>& trackingParticleCollection, const edm::Event* pEvent, const edm::EventSetup* pSetup ) const
169 {
170  std::unique_ptr<ClusterTPAssociationList> pClusterToTPMap;
171  std::unique_ptr<TrackerHitAssociator> pHitAssociator;
172  // This call will set EITHER pClusterToTPMap OR pHitAssociator depending on what the user requested in the configuration.
173  prepareEitherHitAssociatorOrClusterToTPMap( pEvent, pClusterToTPMap, pHitAssociator );
174 
175  // Only pass the one that was successfully created to the templated method.
176  if( pClusterToTPMap==nullptr ) return associateRecoToSimImplementation( trackCollection, trackingParticleCollection, *pHitAssociator );
177  else return associateRecoToSimImplementation( trackCollection, trackingParticleCollection, *pClusterToTPMap );
178 }
179 
181  TrackingParticleCollection>& trackingParticleCollection, const edm::Event* pEvent, const edm::EventSetup* pSetup ) const
182 {
183  std::unique_ptr<ClusterTPAssociationList> pClusterToTPMap;
184  std::unique_ptr<TrackerHitAssociator> pHitAssociator;
185  // This call will set EITHER pClusterToTPMap OR pHitAssociator depending on what the user requested in the configuration.
186  prepareEitherHitAssociatorOrClusterToTPMap( pEvent, pClusterToTPMap, pHitAssociator );
187 
188  // Only pass the one that was successfully created to the templated method.
189  if( pClusterToTPMap==nullptr ) return associateSimToRecoImplementation( trackCollection, trackingParticleCollection, *pHitAssociator );
190  else return associateSimToRecoImplementation( trackCollection, trackingParticleCollection, *pClusterToTPMap );
191 }
192 
193 
194 template<class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
195 reco::RecoToSimCollection QuickTrackAssociatorByHits::associateRecoToSimImplementation( T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator ) const
196 {
197  reco::RecoToSimCollection returnValue;
198 
199  size_t collectionSize=::collectionSize(trackCollection); // Delegate away type specific part
200 
201  for( size_t i=0; i < collectionSize; ++i )
202  {
203  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
204 
205  // The return of this function has first as the index and second as the number of associated hits
206  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
207 
208  // int nt = 0;
209  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
210  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
211  ++iTrackingParticleQualityPair )
212  {
213  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
214  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
215  size_t numberOfValidTrackHits=pTrack->found();
216 
217  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
218 
219  //if electron subtract double counting
220  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
221  {
222  numberOfSharedHits-=getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
223  }
224 
225  double quality;
226  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
227  else if( numberOfValidTrackHits != 0 ) quality=
228  (static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits ));
229  else quality=0;
230  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && numberOfValidTrackHits == 3 && numberOfSharedHits < 3) )
231  {
232  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
233  returnValue.insert( ::getRefToTrackAt(trackCollection,i), std::make_pair( trackingParticleRef, quality ) );
234  }
235  }
236  }
237  return returnValue;
238 }
239 
240 template<class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
241 reco::SimToRecoCollection QuickTrackAssociatorByHits::associateSimToRecoImplementation( T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator ) const
242 {
243  reco::SimToRecoCollection returnValue;
244 
245  size_t collectionSize=::collectionSize(trackCollection); // Delegate away type specific part
246 
247  for( size_t i=0; i<collectionSize; ++i )
248  {
249  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
250 
251  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
252  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
253 
254  // int nt = 0;
255  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
256  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
257  {
258  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
259  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
260  size_t numberOfValidTrackHits=pTrack->found();
261  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
262 
263  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
264 
265  if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
266  {
267  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
268  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
269  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
270  // hits in the tracker.
271  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
272  }
273 
274  //if electron subtract double counting
275  if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
276  {
277  numberOfSharedHits -= getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
278  }
279 
280  double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
281  double quality;
282  if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
283  else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
284  else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
285  else quality=0;
286 
287  if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
288  {
289  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
290  returnValue.insert( trackingParticleRef, std::make_pair( ::getRefToTrackAt(trackCollection,i), quality ) );
291  }
292  }
293  }
294  return returnValue;
295 
296 }
297 
298 template<typename T_TPCollection,typename iter> std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHits::associateTrack( const TrackerHitAssociator& hitAssociator, T_TPCollection trackingParticles, iter begin, iter end ) const
299 {
300  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated hits as "second"
301  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
302 
303  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
304  // 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
305  // number of reco hits. The pair::second entries should add up to the total number of reco hits though.
306  std::vector< std::pair<SimTrackIdentifiers,size_t> > hitIdentifiers=getAllSimTrackIdentifiers( hitAssociator, begin, end );
307 
308  // Loop over the TrackingParticles
309  size_t collectionSize=::collectionSize(trackingParticles);
310 
311  for( size_t i=0; i<collectionSize; ++i )
312  {
313  const TrackingParticle* pTrackingParticle=getTrackingParticleAt( trackingParticles, i );
314 
315  // Ignore TrackingParticles with no hits
316  if( pTrackingParticle->numberOfHits()==0 ) continue;
317 
318  size_t numberOfAssociatedHits=0;
319  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
320  // the number of reco hits associated to that sim track to the total number of associated hits.
321  for( std::vector< std::pair<SimTrackIdentifiers,size_t> >::const_iterator iIdentifierCountPair=hitIdentifiers.begin(); iIdentifierCountPair!=hitIdentifiers.end(); ++iIdentifierCountPair )
322  {
323  if( trackingParticleContainsIdentifier( pTrackingParticle, iIdentifierCountPair->first ) ) numberOfAssociatedHits+=iIdentifierCountPair->second;
324  }
325 
326  if( numberOfAssociatedHits>0 )
327  {
328  returnValue.push_back( std::make_pair( getRefToTrackingParticleAt(trackingParticles,i), numberOfAssociatedHits ) );
329  }
330  }
331 
332  return returnValue;
333 }
334 
335 void QuickTrackAssociatorByHits::prepareEitherHitAssociatorOrClusterToTPMap( const edm::Event* pEvent, std::unique_ptr<ClusterTPAssociationList>& pClusterToTPMap, std::unique_ptr<TrackerHitAssociator>& pHitAssociator ) const
336 {
338  {
339  edm::Handle<ClusterTPAssociationList> pCluster2TPListH;
340  pEvent->getByLabel( cluster2TPSrc_, pCluster2TPListH );
341  if( pCluster2TPListH.isValid() )
342  {
343  pClusterToTPMap.reset( new ClusterTPAssociationList( *(pCluster2TPListH.product()) ) );
344  //make sure it is properly sorted
345  std::sort( pClusterToTPMap->begin(), pClusterToTPMap->end(), clusterTPAssociationListGreater );
346  // Make sure that pHitAssociator is null. There may have been something there before the call.
347  pHitAssociator.reset();
348  return;
349  }
350  else
351  {
352  edm::LogInfo( "TrackAssociator" ) << "ClusterTPAssociationList with label "<< cluster2TPSrc_
353  << " not found. Using DigiSimLink based associator";
354  // Can't do this next line anymore because useClusterTPAssociation_ is no longer mutable
355  //useClusterTPAssociation_=false;
356  }
357  }
358 
359  // If control got this far then either useClusterTPAssociation_ was false or getting the cluster
360  // to TrackingParticle association from the event failed. Either way I need to create a hit associator.
361  pHitAssociator.reset( new TrackerHitAssociator( *pEvent, hitAssociatorParameters_ ) );
362  // Make sure that pClusterToTPMap is null. There may have been something there before the call.
363  pClusterToTPMap.reset();
364 }
365 
366 
367 template<typename T_TPCollection,typename iter> std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHits::associateTrack( const ClusterTPAssociationList& clusterToTPMap, T_TPCollection trackingParticles, iter begin, iter end ) const
368 {
369  // Note that the trackingParticles parameter is not actually required since all the information is in clusterToTPMap,
370  // but the method signature has to match the other overload because it is called from a templated method.
371 
372  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated clusters as "second"
373  // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
374  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
375  if( clusterToTPMap.empty() ) return returnValue;
376 
377  // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
378  // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this
379  // vector should be fewer than the number of clusters. The pair::second entries should add up to the total
380  // number of reco clusters though.
381  std::vector<OmniClusterRef> oClusters=getMatchedClusters( begin, end );
382 
383  std::map < TrackingParticleRef, size_t > lmap;
384  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
385  {
386 
387  std::pair < OmniClusterRef, TrackingParticleRef > clusterTPpairWithDummyTP( *it, TrackingParticleRef() ); //TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
388  auto range=std::equal_range( clusterToTPMap.begin(), clusterToTPMap.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater );
389  if( range.first != range.second )
390  {
391  for( auto ip=range.first; ip != range.second; ++ip )
392  {
393 
394  const TrackingParticleRef trackingParticle=(ip->second);
395 
396  // Ignore TrackingParticles with no hits
397  if( trackingParticle->numberOfHits() == 0 ) continue;
398 
399  /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
400  std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
401  auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
402  if ((tp_range.second-tp_range.first)>1) {
403  edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
404  }
405  if(tp_range.first != tp_range.second) {
406  tp_range.first->second++;
407  } else {
408  returnValue.push_back(tpIntPair);
409  std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
410  }
411  */
412  auto jpos=lmap.find( trackingParticle );
413  if( jpos != lmap.end() ) ++jpos->second;
414  else lmap.insert( std::make_pair( trackingParticle, 1 ) );
415  }
416  }
417  }
418  // now copy the map to returnValue
419  for( auto ip=lmap.begin(); ip != lmap.end(); ++ip )
420  {
421  returnValue.push_back( std::make_pair( ip->first, ip->second ) );
422  }
423  return returnValue;
424 }
425 
426 template<typename iter> std::vector<OmniClusterRef> QuickTrackAssociatorByHits::getMatchedClusters(iter begin, iter end) const
427 {
428  std::vector<OmniClusterRef> returnValue;
429  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
430  const TrackingRecHit* rhit = getHitFromIter(iRecHit);
431  if (rhit->isValid()) {
432  int subdetid = rhit->geographicalId().subdetId();
434  const SiPixelRecHit* pRHit = dynamic_cast<const SiPixelRecHit*>(rhit);
435  if (!pRHit->cluster().isNonnull())
436  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
437  returnValue.push_back(pRHit->omniClusterRef());
438  }
439  else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) {
440  const std::type_info &tid = typeid(*rhit);
441  if (tid == typeid(SiStripMatchedRecHit2D)) {
442  const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast<const SiStripMatchedRecHit2D*>(rhit);
443  if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull())
444  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
445  returnValue.push_back(sMatchedRHit->monoClusterRef());
446  returnValue.push_back(sMatchedRHit->stereoClusterRef());
447  }
448  else if (tid == typeid(SiStripRecHit2D)) {
449  const SiStripRecHit2D* sRHit = dynamic_cast<const SiStripRecHit2D*>(rhit);
450  if (!sRHit->cluster().isNonnull())
451  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
452  returnValue.push_back(sRHit->omniClusterRef());
453  }
454  else if (tid == typeid(SiStripRecHit1D)) {
455  const SiStripRecHit1D* sRHit = dynamic_cast<const SiStripRecHit1D*>(rhit);
456  if (!sRHit->cluster().isNonnull())
457  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
458  returnValue.push_back(sRHit->omniClusterRef());
459  }
460  else {
461  auto const & thit = static_cast<BaseTrackerRecHit const&>(*rhit);
462  if ( thit.isProjected() ) {
463  } else {
464  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid;
465  }
466  }
467  }
468  else {
469  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid;
470  }
471  }
472  }
473  return returnValue;
474 }
475 
476 template<typename iter> std::vector< std::pair<QuickTrackAssociatorByHits::SimTrackIdentifiers,size_t> > QuickTrackAssociatorByHits::getAllSimTrackIdentifiers( const TrackerHitAssociator& hitAssociator, iter begin, iter end ) const
477 {
478  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
479  std::vector < std::pair<SimTrackIdentifiers,size_t> > returnValue;
480 
481  std::vector<SimTrackIdentifiers> simTrackIdentifiers;
482  // Loop over all of the rec hits in the track
483  //iter tRHIterBeginEnd = getTRHIterBeginEnd( pTrack );
484  for( iter iRecHit=begin; iRecHit != end; ++iRecHit )
485  {
486  if( getHitFromIter( iRecHit )->isValid() )
487  {
488  simTrackIdentifiers.clear();
489 
490  // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
491  // have merged (as far as I know).
492  hitAssociator.associateHitId( *(getHitFromIter( iRecHit )), simTrackIdentifiers ); // This call fills simTrackIdentifiers
493  // Loop over each identifier, and add it to the return value only if it's not already in there
494  for( std::vector<SimTrackIdentifiers>::const_iterator iIdentifier=simTrackIdentifiers.begin(); iIdentifier != simTrackIdentifiers.end();
495  ++iIdentifier )
496  {
497  std::vector<std::pair<SimTrackIdentifiers,size_t> >::iterator iIdentifierCountPair;
498  for( iIdentifierCountPair=returnValue.begin(); iIdentifierCountPair != returnValue.end(); ++iIdentifierCountPair )
499  {
500  if( iIdentifierCountPair->first.first == iIdentifier->first && iIdentifierCountPair->first.second == iIdentifier->second )
501  {
502  // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
503  ++iIdentifierCountPair->second;
504  break;
505  }
506  }
507  if( iIdentifierCountPair == returnValue.end() ) returnValue.push_back( std::make_pair( *iIdentifier, 1 ) );
508  // This identifier wasn't found, so add it
509  }
510  }
511  }
512  return returnValue;
513 }
514 
516 {
517  // Loop over all of the g4 tracks in the tracking particle
518  for( std::vector<SimTrack>::const_iterator iSimTrack=pTrackingParticle->g4Track_begin(); iSimTrack != pTrackingParticle->g4Track_end();
519  ++iSimTrack )
520  {
521  // And see if the sim track identifiers match
522  if( iSimTrack->eventId() == identifier.second && iSimTrack->trackId() == identifier.first )
523  {
524  return true;
525  }
526  }
527 
528  // If control has made it this far then none of the identifiers were found in
529  // any of the g4 tracks, so return false.
530  return false;
531 }
532 
533 template<typename iter> int QuickTrackAssociatorByHits::getDoubleCount( const TrackerHitAssociator& hitAssociator, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
534 {
535  // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
536  // it makes I'll go through and comment it properly.
537 
538  int doubleCount=0;
539  std::vector < SimHitIdpr > SimTrackIdsDC;
540 
541  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
542  {
543  int idcount=0;
544 
545  SimTrackIdsDC.clear();
546  hitAssociator.associateHitId( *(getHitFromIter( iHit )), SimTrackIdsDC );
547  if( SimTrackIdsDC.size() > 1 )
548  {
549  for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle->g4Track_begin(); g4T != associatedTrackingParticle->g4Track_end();
550  ++g4T )
551  {
552  if( find( SimTrackIdsDC.begin(), SimTrackIdsDC.end(), SimHitIdpr( ( *g4T).trackId(), SimTrackIdsDC.begin()->second ) )
553  != SimTrackIdsDC.end() )
554  {
555  idcount++;
556  }
557  }
558  }
559  if( idcount > 1 ) doubleCount+=(idcount - 1);
560  }
561 
562  return doubleCount;
563 }
564 
565 template<typename iter> int QuickTrackAssociatorByHits::getDoubleCount( const ClusterTPAssociationList& clusterToTPList, iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
566 {
567  // This code here was written by Subir Sarkar. I'm just splitting it off into a
568  // separate method. - Grimes 01/May/2014
569 
570  int doubleCount=0;
571  std::vector < SimHitIdpr > SimTrackIdsDC;
572 
573  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
574  {
575  int idcount=0;
576 
577  std::vector < OmniClusterRef > oClusters=getMatchedClusters( iHit, iHit + 1 ); //only for the cluster being checked
578  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
579  {
580  std::pair<OmniClusterRef,TrackingParticleRef> clusterTPpairWithDummyTP( *it, TrackingParticleRef() ); //TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
581  auto range=std::equal_range( clusterToTPList.begin(), clusterToTPList.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater );
582  if( range.first != range.second )
583  {
584  for( auto ip=range.first; ip != range.second; ++ip )
585  {
586  const TrackingParticleRef trackingParticle=(ip->second);
587  if( associatedTrackingParticle == trackingParticle )
588  {
589  idcount++;
590  }
591  }
592  }
593  }
594 
595  if( idcount > 1 ) doubleCount+=(idcount - 1);
596  }
597 
598  return doubleCount;
599 }
600 
602  TrackingParticleCollection>& trackingParticleCollectionHandle, const edm::Event * pEvent, const edm::EventSetup *setup ) const
603 {
604 
605  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHits::associateRecoToSim - #seeds=" << pSeedCollectionHandle_->size()
606  << " #TPs=" << trackingParticleCollectionHandle->size();
607 
608  //
609  // First create either the hit associator or the cluster to TrackingParticle map
610  // depending on how the user set the configuration. Depending on the logic here
611  // only one of pClusterToTPList or pTrackerHitAssociator will ever be non-null.
612  //
613  std::unique_ptr<ClusterTPAssociationList> pClusterToTPList;
614  std::unique_ptr<TrackerHitAssociator> pTrackerHitAssociator;
615  // This call will set EITHER pClusterToTPList OR pHitAssociator depending on what the user requested in the configuration.
616  prepareEitherHitAssociatorOrClusterToTPMap( pEvent, pClusterToTPList, pTrackerHitAssociator );
617 
618  //
619  // Now that either pClusterToTPList or pTrackerHitAssociator have been initialised
620  // (never both) I can carry on and do the association.
621  //
622  reco::RecoToSimCollectionSeed returnValue;
623 
624  size_t collectionSize=pSeedCollectionHandle_->size();
625 
626  for( size_t i=0; i < collectionSize; ++i )
627  {
628  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
629 
630  // The return of this function has first as the index and second as the number of associated hits
631  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=
632  (pClusterToTPList!=nullptr) ? associateTrack( *pClusterToTPList, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *pTrackerHitAssociator, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second );
633  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
634  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
635  ++iTrackingParticleQualityPair )
636  {
637  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
638  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
639  size_t numberOfValidTrackHits=pSeed->recHits().second - pSeed->recHits().first;
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( pClusterToTPList!=nullptr ) numberOfSharedHits-=getDoubleCount( *pClusterToTPList, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
647  else numberOfSharedHits-=getDoubleCount( *pTrackerHitAssociator, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
648  }
649 
650  double quality;
651  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
652  else if( numberOfValidTrackHits != 0 ) quality=
653  (static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits ));
654  else quality=0;
655 
656  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && numberOfValidTrackHits == 3 && numberOfSharedHits < 3) )
657  {
658  returnValue.insert( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), std::make_pair( trackingParticleRef, quality ) );
659  }
660  }
661  }
662 
663  LogTrace( "TrackAssociator" ) << "% of Assoc Seeds=" << ((double)returnValue.size()) / ((double)pSeedCollectionHandle_->size());
664  returnValue.post_insert();
665  return returnValue;
666 
667 }
668 
670  TrackingParticleCollection>& trackingParticleCollectionHandle, const edm::Event * pEvent, const edm::EventSetup *setup ) const
671 {
672 
673  edm::LogVerbatim( "TrackAssociator" ) << "Starting TrackAssociatorByHits::associateSimToReco - #seeds=" << pSeedCollectionHandle_->size()
674  << " #TPs=" << trackingParticleCollectionHandle->size();
675 
676  //
677  // First create either the hit associator or the cluster to TrackingParticle map
678  // depending on how the user set the configuration. Depending on the logic here
679  // only one of pClusterToTPList or pTrackerHitAssociator will ever be non-null.
680  //
681  std::unique_ptr<ClusterTPAssociationList> pClusterToTPList;
682  std::unique_ptr<TrackerHitAssociator> pTrackerHitAssociator;
683  // This call will set EITHER pClusterToTPList OR pHitAssociator depending on what the user requested in the configuration.
684  prepareEitherHitAssociatorOrClusterToTPMap( pEvent, pClusterToTPList, pTrackerHitAssociator );
685 
686  //
687  // Now that either pClusterToTPList or pTrackerHitAssociator have been initialised
688  // (never both) I can carry on and do the association.
689  //
690  reco::SimToRecoCollectionSeed returnValue;
691 
692  size_t collectionSize=pSeedCollectionHandle_->size();
693 
694  for( size_t i=0; i < collectionSize; ++i )
695  {
696  const TrajectorySeed* pSeed= &( *pSeedCollectionHandle_)[i];
697 
698  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
699  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=
700  (pClusterToTPList!=nullptr) ? associateTrack( *pClusterToTPList, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second ) : associateTrack( *pTrackerHitAssociator, trackingParticleCollectionHandle, pSeed->recHits().first, pSeed->recHits().second );
701  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
702  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
703  ++iTrackingParticleQualityPair )
704  {
705  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
706  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
707  size_t numberOfValidTrackHits=pSeed->recHits().second - pSeed->recHits().first;
708  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
709 
710  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
711 
712  //if electron subtract double counting
713  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
714  {
715  if( pClusterToTPList!=nullptr ) numberOfSharedHits-=getDoubleCount( *pClusterToTPList, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
716  else numberOfSharedHits-=getDoubleCount( *pTrackerHitAssociator, pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
717  }
718 
719  if( simToRecoDenominator_ == denomsim || (numberOfSharedHits < 3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
720  {
721  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
722  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
723  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
724  // hits in the tracker.
725  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
726  }
727 
728  double purity=static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits );
729  double quality;
730  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
731  else if( simToRecoDenominator_ == denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>( numberOfSharedHits )
732  / static_cast<double>( numberOfSimulatedHits );
733  else if( simToRecoDenominator_ == denomreco && numberOfValidTrackHits != 0 ) quality=purity;
734  else quality=0;
735 
736  if( quality > qualitySimToReco_ && !(threeHitTracksAreSpecial_ && numberOfSimulatedHits == 3 && numberOfSharedHits < 3)
737  && (absoluteNumberOfHits_ || (purity > puritySimToReco_)) )
738  {
739  returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase < TrajectorySeed > (pSeedCollectionHandle_, i), quality ) );
740  }
741  }
742  }
743  return returnValue;
744 
745  LogTrace("TrackAssociator") << "% of Assoc TPs=" << ((double)returnValue.size())/((double)trackingParticleCollectionHandle->size());
746  returnValue.post_insert();
747  return returnValue;
748 }
ClusterRef cluster() const
reco::SimToRecoCollection associateSimToRecoImplementation(T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator) const
The method that does the work for both overloads of associateSimToReco.
T getParameter(std::string const &) const
const TrackingRecHit * getHitFromIter(trackingRecHit_iterator iter) const
int i
Definition: DBlmapReader.cc:9
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
static bool clusterTPAssociationListGreater(std::pair< OmniClusterRef, TrackingParticleRef > i, std::pair< OmniClusterRef, TrackingParticleRef > j)
std::vector< TrackingParticle > TrackingParticleCollection
bool trackingParticleContainsIdentifier(const TrackingParticle *pTrackingParticle, const SimTrackIdentifiers &identifier) const
Returns true if the supplied TrackingParticle has the supplied g4 track identifiers.
g4t_iterator g4Track_begin() const
OmniClusterRef const & stereoClusterRef() const
virtual reco::SimToRecoCollection associateSimToReco(edm::Handle< edm::View< reco::Track > > &trackCollectionHandle, edm::Handle< TrackingParticleCollection > &trackingParticleCollectionHandle, const edm::Event *pEvent=0, const edm::EventSetup *pSetup=0) const override
compare reco to sim the handle of reco::Track and TrackingParticle collections
bool exists(std::string const &parameterName) const
checks if a parameter exists
QuickTrackAssociatorByHits(const edm::ParameterSet &config)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
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.
std::pair< uint32_t, EncodedEventId > SimTrackIdentifiers
This is enough information to uniquely identify a sim track.
void post_insert()
post insert action
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:142
std::vector< std::pair< OmniClusterRef, TrackingParticleRef > > ClusterTPAssociationList
virtual reco::RecoToSimCollection associateRecoToSim(edm::Handle< edm::View< reco::Track > > &trackCollectionHandle, edm::Handle< TrackingParticleCollection > &trackingParticleCollectionHandle, const edm::Event *pEvent=0, const edm::EventSetup *pSetup=0) const override
compare reco to sim the handle of reco::Track and TrackingParticle collections
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
bool isValid() const
Definition: HandleBase.h:76
int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:37
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
Definition: Event.h:402
#define LogTrace(id)
std::vector< SimTrack >::const_iterator g4t_iterator
OmniClusterRef const & omniClusterRef() const
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
void prepareEitherHitAssociatorOrClusterToTPMap(const edm::Event *pEvent, std::unique_ptr< ClusterTPAssociationList > &pClusterToTPMap, std::unique_ptr< TrackerHitAssociator > &pHitAssociator) const
creates either a ClusterTPAssociationList OR a TrackerHitAssociator and stores it in the provided uni...
int getDoubleCount(const TrackerHitAssociator &hitAssociator, iter begin, iter end, TrackingParticleRef associatedTrackingParticle) const
This method was copied almost verbatim from the standard TrackAssociatorByHits.
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...
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 ...
SiStripRecHit2D monoHit() const
std::vector< SimHitIdpr > associateHitId(const TrackingRecHit &thit) const
#define begin
Definition: vmac.h:30
std::vector< OmniClusterRef > getMatchedClusters(iter begin, iter end) const
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
reco::RecoToSimCollection associateRecoToSimImplementation(T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator) const
The method that does the work for both overloads of associateRecoToSim.
Monte Carlo truth information used for tracking validation.
DetId geographicalId() const
g4t_iterator g4Track_end() const
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
edm::Ref< TrackingParticleCollection > TrackingParticleRef
Our base class.
Definition: SiPixelRecHit.h:23
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.
Definition: Track.h:109