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 }
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
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.
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
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:63
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:390
#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
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
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 ...
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: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
Our base class.
Definition: SiPixelRecHit.h:23
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.
Definition: Track.h:65