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 
18  : pHitAssociator_(nullptr), pEventForWhichAssociatorIsValid_(nullptr),
19  absoluteNumberOfHits_( config.getParameter<bool>( "AbsoluteNumberOfHits" ) ),
20  qualitySimToReco_( config.getParameter<double>( "Quality_SimToReco" ) ),
21  puritySimToReco_( config.getParameter<double>( "Purity_SimToReco" ) ),
22  cutRecoToSim_( config.getParameter<double>( "Cut_RecoToSim" ) ),
23  threeHitTracksAreSpecial_( config.getParameter<bool> ( "ThreeHitTracksAreSpecial" ) ),
24  useClusterTPAssociation_(config.getParameter<bool>("useClusterTPAssociation")),
25  cluster2TPSrc_(config.getParameter<edm::InputTag>("cluster2TPSrc"))
26 {
27  //
28  // Check whether the denominator when working out the percentage of shared hits should
29  // be the number of simulated hits or the number of reconstructed hits.
30  //
31  std::string denominatorString=config.getParameter<std::string>("SimToRecoDenominator");
32  if( denominatorString=="sim" ) simToRecoDenominator_=denomsim;
33  else if( denominatorString=="reco" ) simToRecoDenominator_=denomreco;
34  else throw cms::Exception( "QuickTrackAssociatorByHits" ) << "SimToRecoDenominator not specified as sim or reco";
35 
36  //
37  // Set up the parameter set for the hit associator
38  //
39  hitAssociatorParameters_.addParameter<bool>( "associatePixel", config.getParameter<bool>("associatePixel") );
40  hitAssociatorParameters_.addParameter<bool>( "associateStrip", config.getParameter<bool>("associateStrip") );
41  // This is the important one, it stops the hit associator searching through the list of sim hits.
42  // I only want to use the hit associator methods that work on the hit IDs (i.e. the uint32_t trackId
43  // and the EncodedEventId eventId) so I'm not interested in matching that to the PSimHit objects.
44  hitAssociatorParameters_.addParameter<bool>("associateRecoTracks",true);
45 
46  //
47  // Do some checks on whether UseGrouped or UseSplitting have been set. They're not used
48  // unlike the standard TrackAssociatorByHits so show a warning.
49  //
50  bool useGrouped, useSplitting;
51  if( config.exists("UseGrouped") ) useGrouped=config.getParameter<bool>("UseGrouped");
52  else useGrouped=true;
53 
54  if( config.exists("UseSplitting") ) useSplitting=config.getParameter<bool>("UseSplitting");
55  else useSplitting=true;
56 
57  // This associator works as though both UseGrouped and UseSplitting were set to true, so show a
58  // warning if this isn't the case.
59  if( !(useGrouped && useSplitting) )
60  {
61  edm::LogWarning("QuickTrackAssociatorByHits") << "UseGrouped and/or UseSplitting has been set to false, but this associator ignores that setting.";
62  }
63 }
64 
66 {
67  delete pHitAssociator_;
68 }
69 
71  : pEventForWhichAssociatorIsValid_(otherAssociator.pEventForWhichAssociatorIsValid_),
72  hitAssociatorParameters_(otherAssociator.hitAssociatorParameters_),
73  absoluteNumberOfHits_(otherAssociator.absoluteNumberOfHits_),
74  qualitySimToReco_(otherAssociator.qualitySimToReco_),
75  puritySimToReco_(otherAssociator.puritySimToReco_),
76  cutRecoToSim_(otherAssociator.cutRecoToSim_),
77  threeHitTracksAreSpecial_(otherAssociator.threeHitTracksAreSpecial_),
78  simToRecoDenominator_(otherAssociator.simToRecoDenominator_),
79  pTrackCollectionHandle_(otherAssociator.pTrackCollectionHandle_),
80  pTrackCollection_(otherAssociator.pTrackCollection_),
81  pTrackingParticleCollectionHandle_(otherAssociator.pTrackingParticleCollectionHandle_),
82  pTrackingParticleCollection_(otherAssociator.pTrackingParticleCollection_),
83  useClusterTPAssociation_(otherAssociator.useClusterTPAssociation_),
84  cluster2TPSrc_(otherAssociator.cluster2TPSrc_)
85 {
86  // No operation other than the initialiser list. That copies everything straight from the other
87  // associator, except for pHitAssociator_ which needs a deep copy or both instances will try
88  // and free it on deletion. If it wasn't for pHitAssociator_ the default copy constructor and
89  // assignment operator would be sufficient.
90 
91  // Actually, need to check the other hit associator isn't null or the pointer dereference would
92  // probably cause a segmentation fault.
93  if( otherAssociator.pHitAssociator_ ) pHitAssociator_=new TrackerHitAssociator(*otherAssociator.pHitAssociator_);
94  else pHitAssociator_=nullptr;
95 }
96 
98 {
99  // Free up the old pHitAssociator_
100  delete pHitAssociator_;
101 
102  //
103  // pHitAssociator_ needs to be given a deep copy of the object, but everything else can
104  // can be shallow copied from the other associator.
105  //
106  if( otherAssociator.pHitAssociator_ ) pHitAssociator_=new TrackerHitAssociator(*otherAssociator.pHitAssociator_);
107  else pHitAssociator_=nullptr;
111  qualitySimToReco_=otherAssociator.qualitySimToReco_;
112  puritySimToReco_=otherAssociator.puritySimToReco_;
113  cutRecoToSim_=otherAssociator.cutRecoToSim_;
116  cluster2TPSrc_ = otherAssociator.cluster2TPSrc_;
119  pTrackCollection_=otherAssociator.pTrackCollection_;
122 
123  return *this;
124 }
125 
127  edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
128  const edm::Event* pEvent,
129  const edm::EventSetup* pSetup ) const
130 {
131 
132  // get the Cluster2TPMap or initialize hit associator
134  else initialiseHitAssociator( pEvent );
135 
136  pTrackCollectionHandle_=&trackCollectionHandle;
137  pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
138  pTrackCollection_=nullptr;
140 
141  // This method checks which collection type is set to null, and uses the other one.
143 }
144 
146  edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
147  const edm::Event * pEvent,
148  const edm::EventSetup * pSetup ) const
149 {
150 
151  // get the Cluster2TPMap or initialize hit associator
153  else initialiseHitAssociator( pEvent );
154 
155  pTrackCollectionHandle_=&trackCollectionHandle;
156  pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
157  pTrackCollection_=nullptr;
159 
160  // This method checks which collection type is set to null, and uses the other one.
162 }
163 
164 
166  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection,
167  const edm::Event* pEvent,
168  const edm::EventSetup* pSetup ) const
169 {
170 
171  // get the Cluster2TPMap or initialize hit associator
173  else initialiseHitAssociator( pEvent );
174 
175  pTrackCollectionHandle_=nullptr;
177  pTrackCollection_=&trackCollection;
178  pTrackingParticleCollection_=&trackingParticleCollection;
179 
180  // This method checks which collection type is set to null, and uses the other one.
182 }
183 
185  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection,
186  const edm::Event* pEvent,
187  const edm::EventSetup* pSetup ) const
188 {
189 
190  // get the Cluster2TPMap or initialize hit associator
192  else initialiseHitAssociator( pEvent );
193 
194  pTrackCollectionHandle_=nullptr;
196  pTrackCollection_=&trackCollection;
197  pTrackingParticleCollection_=&trackingParticleCollection;
198 
199  // This method checks which collection type is set to null, and uses the other one.
201 }
202 
204 {
205  reco::RecoToSimCollection returnValue;
206 
207  size_t collectionSize;
208  // Need to check which pointer is valid to get the collection size
209  if ( pTrackCollection_ ) collectionSize=pTrackCollection_->size();
210  else collectionSize=(*pTrackCollectionHandle_)->size();
211 
212  //std::cout << "#reco Tracks = " << collectionSize << std::endl;
213  for( size_t i=0; i<collectionSize; ++i )
214  {
215  const reco::Track* pTrack; // Get a normal pointer for ease of use.
216  if( pTrackCollection_ ) pTrack=&*(*pTrackCollection_)[i]; // Possibly the most obscure dereference I've ever had to write
217  else pTrack=&(*pTrackCollectionHandle_->product())[i];
218  // std::cout << ">>> recoTrack #index = " << i << " pt = " << pTrack->pt() << std::endl;
219 
220  // The return of this function has first as the index and second as the number of associated hits
221  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs = (useClusterTPAssociation_)
222  ? associateTrackByCluster( pTrack->recHitsBegin(),pTrack->recHitsEnd() )
223  : associateTrack( pTrack->recHitsBegin(), pTrack->recHitsEnd() );
224 
225  // int nt = 0;
226  for (std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
227  {
228  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
229  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
230  size_t numberOfValidTrackHits=pTrack->found();
231 
232  //std::cout << ">>> reco2sim. numberOfSharedHits = " << nt++ << ", " << numberOfSharedHits << std::endl;
233  if (numberOfSharedHits==0) continue; // No point in continuing if there was no association
234 
235  //if electron subtract double counting
236  if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
237  {
238  numberOfSharedHits -= getDoubleCount( pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
239  }
240 
241  double quality;
242  if (absoluteNumberOfHits_ )
243  quality = static_cast<double>(numberOfSharedHits);
244  else if (numberOfValidTrackHits != 0)
245  quality = (static_cast<double>(numberOfSharedHits) / static_cast<double>(numberOfValidTrackHits));
246  else
247  quality = 0;
248  if (quality > cutRecoToSim_ && !( threeHitTracksAreSpecial_ && numberOfValidTrackHits==3 && numberOfSharedHits<3 ) )
249  {
250  if (pTrackCollection_) returnValue.insert( (*pTrackCollection_)[i], std::make_pair( trackingParticleRef, quality ));
251  else returnValue.insert( edm::RefToBase<reco::Track>(*pTrackCollectionHandle_,i), std::make_pair( trackingParticleRef, quality ));
252  }
253  }
254  }
255  return returnValue;
256 }
257 
259 {
260  reco::SimToRecoCollection returnValue;
261 
262  size_t collectionSize;
263  // Need to check which pointer is valid to get the collection size
264  if( pTrackCollection_ ) collectionSize=pTrackCollection_->size();
265  else collectionSize=(*pTrackCollectionHandle_)->size();
266 
267  for( size_t i=0; i<collectionSize; ++i )
268  {
269  const reco::Track* pTrack; // Get a normal pointer for ease of use.
270  if( pTrackCollection_ ) pTrack=&*(*pTrackCollection_)[i]; // Possibly the most obscure dereference I've ever had to write
271  else pTrack=&(*pTrackCollectionHandle_->product())[i];
272 
273  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
274  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs = (useClusterTPAssociation_)
275  ? associateTrackByCluster( pTrack->recHitsBegin(),pTrack->recHitsEnd() )
276  : associateTrack( pTrack->recHitsBegin(),pTrack->recHitsEnd() );
277 
278  // int nt = 0;
279  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
280  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
281  {
282  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
283  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
284  size_t numberOfValidTrackHits=pTrack->found();
285  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
286 
287  //std::cout << ">>> sim2reco. numberOfSharedHits = " << nt++ << ", " << numberOfSharedHits << std::endl;
288  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
289 
290  if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
291  {
292  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
293  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
294  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
295  // hits in the tracker.
296  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
297  }
298 
299 
300  //if electron subtract double counting
301  if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
302  {
303  numberOfSharedHits -= getDoubleCount( pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
304  }
305 
306 
307  double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
308  double quality;
309  if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
310  else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
311  else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
312  else quality=0;
313 
314  if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
315  {
316  if( pTrackCollection_ ) returnValue.insert( trackingParticleRef, std::make_pair( (*pTrackCollection_)[i], quality ) );
317  else returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase<reco::Track>(*pTrackCollectionHandle_,i) , quality ) );
318  }
319  }
320  }
321  return returnValue;
322 
323 }
324 
325 template<typename iter> std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHits::associateTrack( iter begin, iter end ) const
326 {
327  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated hits as "second"
328  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
329 
330  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
331  // 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
332  // number of reco hits. The pair::second entries should add up to the total number of reco hits though.
333  std::vector< std::pair<SimTrackIdentifiers,size_t> > hitIdentifiers=getAllSimTrackIdentifiers(begin, end);
334 
335  // Loop over the TrackingParticles
336  size_t collectionSize;
338  else collectionSize=(*pTrackingParticleCollectionHandle_)->size();
339 
340  for( size_t i=0; i<collectionSize; ++i )
341  {
342  const TrackingParticle* pTrackingParticle; // Convert to raw pointer for ease of use
343  if( pTrackingParticleCollection_ ) pTrackingParticle=&*(*pTrackingParticleCollection_)[i];
344  else pTrackingParticle=&(*pTrackingParticleCollectionHandle_->product())[i];
345 
346  // Ignore TrackingParticles with no hits
347  if( pTrackingParticle->numberOfHits()==0 ) continue;
348 
349  size_t numberOfAssociatedHits=0;
350  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
351  // the number of reco hits associated to that sim track to the total number of associated hits.
352  for( std::vector< std::pair<SimTrackIdentifiers,size_t> >::const_iterator iIdentifierCountPair=hitIdentifiers.begin(); iIdentifierCountPair!=hitIdentifiers.end(); ++iIdentifierCountPair )
353  {
354  if( trackingParticleContainsIdentifier( pTrackingParticle, iIdentifierCountPair->first ) ) numberOfAssociatedHits+=iIdentifierCountPair->second;
355  }
356 
357  if( numberOfAssociatedHits>0 )
358  {
359  if( pTrackingParticleCollection_ ) returnValue.push_back( std::make_pair( (*pTrackingParticleCollection_)[i], numberOfAssociatedHits ) );
360  else returnValue.push_back( std::make_pair( edm::Ref<TrackingParticleCollection>( *pTrackingParticleCollectionHandle_, i ), numberOfAssociatedHits ) );
361  }
362  }
363 
364  return returnValue;
365 }
366 
368 {
369  //get the Cluster2TPList
370  edm::Handle<ClusterTPAssociationList> pCluster2TPListH;
371  pEvent->getByLabel(cluster2TPSrc_, pCluster2TPListH);
372  if (pCluster2TPListH.isValid()) {
373  pCluster2TPList_ = *(pCluster2TPListH.product());
374  //make sure it is properly sorted
376  } else {
377  edm::LogInfo("TrackAssociator") << "ClusterTPAssociationList with label "<<cluster2TPSrc_<<" not found. Using DigiSimLink based associator";
378  initialiseHitAssociator( pEvent );
379  useClusterTPAssociation_ = false;
380  }
381 }
382 
383 template<typename iter> std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHits::associateTrackByCluster(iter begin, iter end) const
384 {
385  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated clusters as "second"
386  // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
387  std::vector<std::pair<edm::Ref<TrackingParticleCollection>, size_t> > returnValue;
388  if (!pCluster2TPList_.size()) return returnValue;
389 
390  // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
391  // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this
392  // vector should be fewer than the number of clusters. The pair::second entries should add up to the total
393  // number of reco clusters though.
394  std::vector<OmniClusterRef> oClusters = getMatchedClusters(begin, end);
395 
396  std::map<TrackingParticleRef, size_t> lmap;
397  for (std::vector<OmniClusterRef>::const_iterator it = oClusters.begin(); it != oClusters.end(); ++it) {
398 
399  std::pair<OmniClusterRef, TrackingParticleRef> clusterTPpairWithDummyTP(*it,TrackingParticleRef());//TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
400  auto range = std::equal_range(pCluster2TPList_.begin(), pCluster2TPList_.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater);
401  if(range.first != range.second) {
402  for(auto ip = range.first; ip != range.second; ++ip) {
403 
404  const TrackingParticleRef trackingParticle = (ip->second);
405 
406  // Ignore TrackingParticles with no hits
407  if (trackingParticle->numberOfHits()==0) continue;
408 
409  /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
410  std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
411  auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
412  if ((tp_range.second-tp_range.first)>1) {
413  edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
414  }
415  if(tp_range.first != tp_range.second) {
416  tp_range.first->second++;
417  } else {
418  returnValue.push_back(tpIntPair);
419  std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
420  }
421  */
422  auto jpos = lmap.find(trackingParticle);
423  if (jpos != lmap.end())
424  ++jpos->second;
425  else
426  lmap.insert(std::make_pair(trackingParticle, 1));
427  }
428  }
429  }
430  // now copy the map to returnValue
431  for (auto ip = lmap.begin(); ip != lmap.end(); ++ip) {
432  returnValue.push_back(std::make_pair(ip->first, ip->second));
433  }
434  return returnValue;
435 }
436 
437 template<typename iter> std::vector<OmniClusterRef> QuickTrackAssociatorByHits::getMatchedClusters(iter begin, iter end) const
438 {
439  std::vector<OmniClusterRef> returnValue;
440  for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
441  const TrackingRecHit* rhit = getHitFromIter(iRecHit);
442  if (rhit->isValid()) {
443  int subdetid = rhit->geographicalId().subdetId();
445  const SiPixelRecHit* pRHit = dynamic_cast<const SiPixelRecHit*>(rhit);
446  if (!pRHit->cluster().isNonnull())
447  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
448  returnValue.push_back(pRHit->omniClusterRef());
449  }
450  else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) {
451  const std::type_info &tid = typeid(*rhit);
452  if (tid == typeid(SiStripMatchedRecHit2D)) {
453  const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast<const SiStripMatchedRecHit2D*>(rhit);
454  if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull())
455  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
456  returnValue.push_back(sMatchedRHit->monoClusterRef());
457  returnValue.push_back(sMatchedRHit->stereoClusterRef());
458  }
459  else if (tid == typeid(SiStripRecHit2D)) {
460  const SiStripRecHit2D* sRHit = dynamic_cast<const SiStripRecHit2D*>(rhit);
461  if (!sRHit->cluster().isNonnull())
462  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
463  returnValue.push_back(sRHit->omniClusterRef());
464  }
465  else if (tid == typeid(SiStripRecHit1D)) {
466  const SiStripRecHit1D* sRHit = dynamic_cast<const SiStripRecHit1D*>(rhit);
467  if (!sRHit->cluster().isNonnull())
468  edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
469  returnValue.push_back(sRHit->omniClusterRef());
470  }
471  else {
472  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid;
473  }
474  }
475  else {
476  edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid;
477  }
478  }
479  }
480  return returnValue;
481 }
482 
483 template<typename iter> std::vector< std::pair<QuickTrackAssociatorByHits::SimTrackIdentifiers,size_t> > QuickTrackAssociatorByHits::getAllSimTrackIdentifiers( iter begin, iter end ) const
484 {
485  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
486  std::vector< std::pair<SimTrackIdentifiers,size_t> > returnValue;
487 
488  std::vector<SimTrackIdentifiers> simTrackIdentifiers;
489  // Loop over all of the rec hits in the track
490  //iter tRHIterBeginEnd = getTRHIterBeginEnd( pTrack );
491  for( iter iRecHit=begin; iRecHit!=end; ++iRecHit )
492  {
493  if( getHitFromIter(iRecHit)->isValid() )
494  {
495  simTrackIdentifiers.clear();
496 
497  // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
498  // have merged (as far as I know).
499  pHitAssociator_->associateHitId( *(getHitFromIter(iRecHit)), simTrackIdentifiers ); // This call fills simTrackIdentifiers
500  // Loop over each identifier, and add it to the return value only if it's not already in there
501  for ( std::vector<SimTrackIdentifiers>::const_iterator iIdentifier = simTrackIdentifiers.begin();
502  iIdentifier != simTrackIdentifiers.end();
503  ++iIdentifier )
504  {
505  std::vector< std::pair<SimTrackIdentifiers,size_t> >::iterator iIdentifierCountPair;
506  for (iIdentifierCountPair=returnValue.begin(); iIdentifierCountPair!=returnValue.end(); ++iIdentifierCountPair)
507  {
508  if (iIdentifierCountPair->first.first==iIdentifier->first && iIdentifierCountPair->first.second==iIdentifier->second )
509  {
510  // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
511  ++iIdentifierCountPair->second;
512  break;
513  }
514  }
515  if( iIdentifierCountPair==returnValue.end() ) returnValue.push_back( std::make_pair(*iIdentifier,1) );
516  // This identifier wasn't found, so add it
517  }
518  }
519  }
520  return returnValue;
521 }
522 
524 {
525  // Loop over all of the g4 tracks in the tracking particle
526  for( std::vector<SimTrack>::const_iterator iSimTrack=pTrackingParticle->g4Track_begin(); iSimTrack!=pTrackingParticle->g4Track_end(); ++iSimTrack )
527  {
528  // And see if the sim track identifiers match
529  if( iSimTrack->eventId()==identifier.second && iSimTrack->trackId()==identifier.first )
530  {
531  return true;
532  }
533  }
534 
535  // If control has made it this far then none of the identifiers were found in
536  // any of the g4 tracks, so return false.
537  return false;
538 }
539 
540 template<typename iter> int QuickTrackAssociatorByHits::getDoubleCount( iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
541 {
542  // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
543  // it makes I'll go through and comment it properly.
544 
545  int doubleCount=0;
546  std::vector<SimHitIdpr> SimTrackIdsDC;
547 
548  for( iter iHit=startIterator; iHit != endIterator; iHit++ )
549  {
550  int idcount=0;
551 
553  std::vector<OmniClusterRef> oClusters = getMatchedClusters(iHit, iHit+1);//only for the cluster being checked
554  for (std::vector<OmniClusterRef>::const_iterator it = oClusters.begin(); it != oClusters.end(); ++it) {
555  std::pair<OmniClusterRef, TrackingParticleRef> clusterTPpairWithDummyTP(*it,TrackingParticleRef());//TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
556  auto range = std::equal_range(pCluster2TPList_.begin(), pCluster2TPList_.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater);
557  if(range.first != range.second) {
558  for(auto ip = range.first; ip != range.second; ++ip) {
559  const TrackingParticleRef trackingParticle = (ip->second);
560  if (associatedTrackingParticle==trackingParticle) {
561  idcount++;
562  }
563  }
564  }
565  }
566  } else {
567  SimTrackIdsDC.clear();
568  pHitAssociator_->associateHitId( *(getHitFromIter(iHit)), SimTrackIdsDC );
569  if( SimTrackIdsDC.size() > 1 )
570  {
571  for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle->g4Track_begin(); g4T != associatedTrackingParticle->g4Track_end(); ++g4T )
572  {
573  if( find( SimTrackIdsDC.begin(), SimTrackIdsDC.end(), SimHitIdpr( ( *g4T).trackId(), SimTrackIdsDC.begin()->second ) )
574  != SimTrackIdsDC.end() )
575  {
576  idcount++;
577  }
578  }
579  }
580  }
581  if( idcount > 1 ) doubleCount+=(idcount - 1);
582  }
583 
584  return doubleCount;
585 }
586 
587 
589 {
590  // The intention of this function was to check whether the hit associator is still valid
591  // (since in general associateSimToReco and associateRecoToSim are called for the same
592  // event). I was doing this by recording the event pointer and checking it hasn't changed
593  // but this doesn't appear to work. Until I find a way of uniquely identifying an event
594  // I'll just create it anew each time.
595 // if( pEventForWhichAssociatorIsValid_==pEvent && pEventForWhichAssociatorIsValid_!=null ) return; // Already set up so no need to do anything
596 
597  // Free up the previous instantiation
598  delete pHitAssociator_;
599 
600  // Create a new instantiation using the new event
603 }
604 
605 
606 
609  edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
610  const edm::Event * pEvent,
611  const edm::EventSetup *setup ) const{
612 
613  edm::LogVerbatim("TrackAssociator") << "Starting TrackAssociatorByHits::associateRecoToSim - #seeds="
614  << pSeedCollectionHandle_->size()<<" #TPs="<<trackingParticleCollectionHandle->size();
615 
616  initialiseHitAssociator( pEvent );
617  pTrackCollectionHandle_=nullptr;
618  pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
619  pTrackCollection_=nullptr;
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 = (useClusterTPAssociation_)
632  ? associateTrackByCluster( pSeed->recHits().first,pSeed->recHits().second )
633  : associateTrack( pSeed->recHits().first,pSeed->recHits().second );
634  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
635  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++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  numberOfSharedHits-=getDoubleCount( pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
647  }
648 
649  double quality;
650  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
651  else if( numberOfValidTrackHits != 0 ) quality=(static_cast<double>(numberOfSharedHits) / static_cast<double>(numberOfValidTrackHits) );
652  else quality=0;
653 
654  if( quality > cutRecoToSim_ && !( threeHitTracksAreSpecial_ && numberOfValidTrackHits==3 && numberOfSharedHits<3 ) )
655  {
656  returnValue.insert( edm::RefToBase<TrajectorySeed>(pSeedCollectionHandle_,i), std::make_pair( trackingParticleRef, quality ));
657  }
658  }
659  }
660 
661  LogTrace("TrackAssociator") << "% of Assoc Seeds=" << ((double)returnValue.size())/((double)pSeedCollectionHandle_->size());
662  returnValue.post_insert();
663  return returnValue;
664 
665 }
666 
667 
670  edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
671  const edm::Event * pEvent,
672  const edm::EventSetup *setup ) const{
673 
674  edm::LogVerbatim("TrackAssociator") << "Starting TrackAssociatorByHits::associateSimToReco - #seeds="
675  <<pSeedCollectionHandle_->size()<<" #TPs="<<trackingParticleCollectionHandle->size();
676 
677  initialiseHitAssociator( pEvent );
678  pTrackCollectionHandle_=nullptr;
679  pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
680  pTrackCollection_=nullptr;
682 
683  reco::SimToRecoCollectionSeed returnValue;
684 
685  size_t collectionSize=pSeedCollectionHandle_->size();
686 
687  for( size_t i=0; i<collectionSize; ++i )
688  {
689  const TrajectorySeed* pSeed=&(*pSeedCollectionHandle_)[i];
690 
691  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
692  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs = (useClusterTPAssociation_)
693  ? associateTrackByCluster( pSeed->recHits().first,pSeed->recHits().second )
694  : associateTrack( pSeed->recHits().first,pSeed->recHits().second );
695  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
696  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
697  {
698  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
699  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
700  size_t numberOfValidTrackHits=pSeed->recHits().second-pSeed->recHits().first;
701  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
702 
703  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
704 
705  //if electron subtract double counting
706  if( abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
707  {
708  numberOfSharedHits-=getDoubleCount( pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
709  }
710 
711  if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
712  {
713  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
714  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
715  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
716  // hits in the tracker.
717  numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
718  }
719 
720  double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
721  double quality;
722  if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
723  else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
724  else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
725  else quality=0;
726 
727  if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
728  {
729  returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase<TrajectorySeed>(pSeedCollectionHandle_,i) , quality ) );
730  }
731  }
732  }
733  return returnValue;
734 
735  LogTrace("TrackAssociator") << "% of Assoc TPs=" << ((double)returnValue.size())/((double)trackingParticleCollectionHandle->size());
736  returnValue.post_insert();
737  return returnValue;
738 }
T getParameter(std::string const &) const
const TrackingRecHit * getHitFromIter(trackingRecHit_iterator iter) const
int i
Definition: DBlmapReader.cc:9
std::vector< std::pair< edm::Ref< TrackingParticleCollection >, size_t > > associateTrack(iter begin, iter end) const
Returns the TrackingParticle that has the most associated hits to the given track.
TrackAssociator that associates by hits a bit quicker than the normal TrackAssociatorByHits class...
static bool clusterTPAssociationListGreater(std::pair< OmniClusterRef, TrackingParticleRef > i, std::pair< OmniClusterRef, TrackingParticleRef > j)
const edm::Event * pEventForWhichAssociatorIsValid_
bool trackingParticleContainsIdentifier(const TrackingParticle *pTrackingParticle, const SimTrackIdentifiers &identifier) const
Returns true if the supplied TrackingParticle has the supplied g4 track identifiers.
ClusterTPAssociationList pCluster2TPList_
g4t_iterator g4Track_begin() const
#define nullptr
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
std::vector< std::pair< edm::Ref< TrackingParticleCollection >, size_t > > associateTrackByCluster(iter begin, iter end) const
bool exists(std::string const &parameterName) const
checks if a parameter exists
QuickTrackAssociatorByHits & operator=(const QuickTrackAssociatorByHits &otherAssociator)
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< SimHitIdpr > associateHitId(const TrackingRecHit &thit)
const edm::RefVector< TrackingParticleCollection > * pTrackingParticleCollection_
Pointer to the TrackingParticle collection handle.
std::pair< uint32_t, EncodedEventId > SimTrackIdentifiers
int getDoubleCount(iter begin, iter end, TrackingParticleRef associatedTrackingParticle) const
This method was copied almost verbatim from the standard TrackAssociatorByHits.
reco::RecoToSimCollection associateRecoToSimImplementation() const
The method that does the work for both overloads of associateRecoToSim.
std::vector< std::pair< SimTrackIdentifiers, size_t > > getAllSimTrackIdentifiers(iter begin, iter end) const
Returns a vector of pairs where first is a SimTrackIdentifiers (see typedef above) and second is the ...
void post_insert()
post insert action
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:142
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:62
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
reco::SimToRecoCollection associateSimToRecoImplementation() const
The method that does the work for both overloads of associateSimToReco.
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
edm::Handle< TrackingParticleCollection > * pTrackingParticleCollectionHandle_
Pointer to the TrackingParticle collection handle.
const edm::RefToBaseVector< reco::Track > * pTrackCollection_
Pointer to the track collection.
#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:99
size_type size() const
Size of the RefVector.
Definition: RefVector.h:89
Monte Carlo truth information used for tracking validation.
void initialiseHitAssociator(const edm::Event *event) const
edm::Handle< edm::View< reco::Track > > * pTrackCollectionHandle_
Pointer to the handle to the track collection.
DetId geographicalId() const
g4t_iterator g4Track_end() const
void prepareCluster2TPMap(const edm::Event *pEvent) const
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
edm::Ref< TrackingParticleCollection > TrackingParticleRef
Pixel Reconstructed Hit.
TrackerHitAssociator * pHitAssociator_
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.
Definition: Track.h:64