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  //std::cout << "#reco Tracks = " << collectionSize << std::endl;
202  for( size_t i=0; i < collectionSize; ++i )
203  {
204  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
205  // std::cout << ">>> recoTrack #index = " << i << " pt = " << pTrack->pt() << std::endl;
206 
207  // The return of this function has first as the index and second as the number of associated hits
208  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
209 
210  // int nt = 0;
211  for( std::vector<std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=
212  trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair != trackingParticleQualityPairs.end();
213  ++iTrackingParticleQualityPair )
214  {
215  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
216  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
217  size_t numberOfValidTrackHits=pTrack->found();
218 
219  //std::cout << ">>> reco2sim. numberOfSharedHits = " << nt++ << ", " << numberOfSharedHits << std::endl;
220  if( numberOfSharedHits == 0 ) continue; // No point in continuing if there was no association
221 
222  //if electron subtract double counting
223  if( abs( trackingParticleRef->pdgId() ) == 11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
224  {
225  numberOfSharedHits-=getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
226  }
227 
228  double quality;
229  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
230  else if( numberOfValidTrackHits != 0 ) quality=
231  (static_cast<double>( numberOfSharedHits ) / static_cast<double>( numberOfValidTrackHits ));
232  else quality=0;
233  if( quality > cutRecoToSim_ && !(threeHitTracksAreSpecial_ && numberOfValidTrackHits == 3 && numberOfSharedHits < 3) )
234  {
235  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
236  returnValue.insert( ::getRefToTrackAt(trackCollection,i), std::make_pair( trackingParticleRef, quality ) );
237  }
238  }
239  }
240  return returnValue;
241 }
242 
243 template<class T_TrackCollection, class T_TrackingParticleCollection, class T_hitOrClusterAssociator>
244 reco::SimToRecoCollection QuickTrackAssociatorByHits::associateSimToRecoImplementation( T_TrackCollection trackCollection, T_TrackingParticleCollection trackingParticleCollection, T_hitOrClusterAssociator hitOrClusterAssociator ) const
245 {
246  reco::SimToRecoCollection returnValue;
247 
248  size_t collectionSize=::collectionSize(trackCollection); // Delegate away type specific part
249 
250  for( size_t i=0; i<collectionSize; ++i )
251  {
252  const reco::Track* pTrack=::getTrackAt(trackCollection,i); // Get a normal pointer for ease of use. This part is type specific so delegate.
253 
254  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
255  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( hitOrClusterAssociator, trackingParticleCollection, pTrack->recHitsBegin(), pTrack->recHitsEnd() );
256 
257  // int nt = 0;
258  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
259  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
260  {
261  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
262  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
263  size_t numberOfValidTrackHits=pTrack->found();
264  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
265 
266  //std::cout << ">>> sim2reco. numberOfSharedHits = " << nt++ << ", " << numberOfSharedHits << std::endl;
267  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
268 
269  if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
270  {
271  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
272  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
273  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
274  // hits in the tracker.
275  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
276  }
277 
278  //if electron subtract double counting
279  if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
280  {
281  numberOfSharedHits -= getDoubleCount( hitOrClusterAssociator, pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
282  }
283 
284  double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
285  double quality;
286  if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
287  else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
288  else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
289  else quality=0;
290 
291  if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
292  {
293  // Getting the RefToBase is dependent on the type of trackCollection, so delegate that to an overload.
294  returnValue.insert( trackingParticleRef, std::make_pair( ::getRefToTrackAt(trackCollection,i), quality ) );
295  }
296  }
297  }
298  return returnValue;
299 
300 }
301 
302 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
303 {
304  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated hits as "second"
305  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
306 
307  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
308  // 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
309  // number of reco hits. The pair::second entries should add up to the total number of reco hits though.
310  std::vector< std::pair<SimTrackIdentifiers,size_t> > hitIdentifiers=getAllSimTrackIdentifiers( hitAssociator, begin, end );
311 
312  // Loop over the TrackingParticles
313  size_t collectionSize=::collectionSize(trackingParticles);
314 
315  for( size_t i=0; i<collectionSize; ++i )
316  {
317  const TrackingParticle* pTrackingParticle=getTrackingParticleAt( trackingParticles, i );
318 
319  // Ignore TrackingParticles with no hits
320  if( pTrackingParticle->numberOfHits()==0 ) continue;
321 
322  size_t numberOfAssociatedHits=0;
323  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
324  // the number of reco hits associated to that sim track to the total number of associated hits.
325  for( std::vector< std::pair<SimTrackIdentifiers,size_t> >::const_iterator iIdentifierCountPair=hitIdentifiers.begin(); iIdentifierCountPair!=hitIdentifiers.end(); ++iIdentifierCountPair )
326  {
327  if( trackingParticleContainsIdentifier( pTrackingParticle, iIdentifierCountPair->first ) ) numberOfAssociatedHits+=iIdentifierCountPair->second;
328  }
329 
330  if( numberOfAssociatedHits>0 )
331  {
332  returnValue.push_back( std::make_pair( getRefToTrackingParticleAt(trackingParticles,i), numberOfAssociatedHits ) );
333  }
334  }
335 
336  return returnValue;
337 }
338 
339 void QuickTrackAssociatorByHits::prepareEitherHitAssociatorOrClusterToTPMap( const edm::Event* pEvent, std::unique_ptr<ClusterTPAssociationList>& pClusterToTPMap, std::unique_ptr<TrackerHitAssociator>& pHitAssociator ) const
340 {
342  {
343  edm::Handle<ClusterTPAssociationList> pCluster2TPListH;
344  pEvent->getByLabel( cluster2TPSrc_, pCluster2TPListH );
345  if( pCluster2TPListH.isValid() )
346  {
347  pClusterToTPMap.reset( new ClusterTPAssociationList( *(pCluster2TPListH.product()) ) );
348  //make sure it is properly sorted
349  std::sort( pClusterToTPMap->begin(), pClusterToTPMap->end(), clusterTPAssociationListGreater );
350  // Make sure that pHitAssociator is null. There may have been something there before the call.
351  pHitAssociator.reset();
352  return;
353  }
354  else
355  {
356  edm::LogInfo( "TrackAssociator" ) << "ClusterTPAssociationList with label "<< cluster2TPSrc_
357  << " not found. Using DigiSimLink based associator";
358  // Can't do this next line anymore because useClusterTPAssociation_ is no longer mutable
359  //useClusterTPAssociation_=false;
360  }
361  }
362 
363  // If control got this far then either useClusterTPAssociation_ was false or getting the cluster
364  // to TrackingParticle association from the event failed. Either way I need to create a hit associator.
365  pHitAssociator.reset( new TrackerHitAssociator( *pEvent, hitAssociatorParameters_ ) );
366  // Make sure that pClusterToTPMap is null. There may have been something there before the call.
367  pClusterToTPMap.reset();
368 }
369 
370 
371 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
372 {
373  // Note that the trackingParticles parameter is not actually required since all the information is in clusterToTPMap,
374  // but the method signature has to match the other overload because it is called from a templated method.
375 
376  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated clusters as "second"
377  // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
378  std::vector < std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
379  if( clusterToTPMap.empty() ) return returnValue;
380 
381  // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
382  // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this
383  // vector should be fewer than the number of clusters. The pair::second entries should add up to the total
384  // number of reco clusters though.
385  std::vector<OmniClusterRef> oClusters=getMatchedClusters( begin, end );
386 
387  std::map < TrackingParticleRef, size_t > lmap;
388  for( std::vector<OmniClusterRef>::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it )
389  {
390 
391  std::pair < OmniClusterRef, TrackingParticleRef > clusterTPpairWithDummyTP( *it, TrackingParticleRef() ); //TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
392  auto range=std::equal_range( clusterToTPMap.begin(), clusterToTPMap.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater );
393  if( range.first != range.second )
394  {
395  for( auto ip=range.first; ip != range.second; ++ip )
396  {
397 
398  const TrackingParticleRef trackingParticle=(ip->second);
399 
400  // Ignore TrackingParticles with no hits
401  if( trackingParticle->numberOfHits() == 0 ) continue;
402 
403  /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
404  std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
405  auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
406  if ((tp_range.second-tp_range.first)>1) {
407  edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
408  }
409  if(tp_range.first != tp_range.second) {
410  tp_range.first->second++;
411  } else {
412  returnValue.push_back(tpIntPair);
413  std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
414  }
415  */
416  auto jpos=lmap.find( trackingParticle );
417  if( jpos != lmap.end() ) ++jpos->second;
418  else lmap.insert( std::make_pair( trackingParticle, 1 ) );
419  }
420  }
421  }
422  // now copy the map to returnValue
423  for( auto ip=lmap.begin(); ip != lmap.end(); ++ip )
424  {
425  returnValue.push_back( std::make_pair( ip->first, ip->second ) );
426  }
427  return returnValue;
428 }
429 
430 template<typename iter> std::vector<OmniClusterRef> QuickTrackAssociatorByHits::getMatchedClusters(iter begin, iter end) const
431 {
432  std::vector<OmniClusterRef> returnValue;
433  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
434  const TrackingRecHit* rhit = getHitFromIter(iRecHit);
435  if (rhit->isValid()) {
436  int subdetid = rhit->geographicalId().subdetId();
438  const SiPixelRecHit* pRHit = dynamic_cast<const SiPixelRecHit*>(rhit);
439  if (!pRHit->cluster().isNonnull())
440  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
441  returnValue.push_back(pRHit->omniClusterRef());
442  }
443  else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) {
444  const std::type_info &tid = typeid(*rhit);
445  if (tid == typeid(SiStripMatchedRecHit2D)) {
446  const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast<const SiStripMatchedRecHit2D*>(rhit);
447  if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull())
448  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
449  returnValue.push_back(sMatchedRHit->monoClusterRef());
450  returnValue.push_back(sMatchedRHit->stereoClusterRef());
451  }
452  else if (tid == typeid(SiStripRecHit2D)) {
453  const SiStripRecHit2D* sRHit = dynamic_cast<const SiStripRecHit2D*>(rhit);
454  if (!sRHit->cluster().isNonnull())
455  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
456  returnValue.push_back(sRHit->omniClusterRef());
457  }
458  else if (tid == typeid(SiStripRecHit1D)) {
459  const SiStripRecHit1D* sRHit = dynamic_cast<const SiStripRecHit1D*>(rhit);
460  if (!sRHit->cluster().isNonnull())
461  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
462  returnValue.push_back(sRHit->omniClusterRef());
463  }
464  else {
465  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid;
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 }
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
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
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
#define end
Definition: vmac.h:37
size_type size() const
trackingRecHit_iterator recHitsBegin() const
Iterator to first hit on the track.
Definition: Track.h:63
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:390
#define LogTrace(id)
std::vector< SimTrack >::const_iterator g4t_iterator
std::pair< uint32_t, EncodedEventId > SimHitIdpr
size_type size() const
map size
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.
range recHits() const
bool isValid() const
int numberOfHits() const
Gives the total number of hits, including muon hits. Hits on overlaps in the same layer count separat...
T const * product() const
Definition: Handle.h:81
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 ...
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:100
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
Pixel Reconstructed Hit.
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.
Definition: Track.h:65