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.
2 
5 
7  : pHitAssociator_(NULL), pEventForWhichAssociatorIsValid_(NULL),
8  absoluteNumberOfHits_( config.getParameter<bool>( "AbsoluteNumberOfHits" ) ),
9  qualitySimToReco_( config.getParameter<double>( "Quality_SimToReco" ) ),
10  puritySimToReco_( config.getParameter<double>( "Purity_SimToReco" ) ),
11  cutRecoToSim_( config.getParameter<double>( "Cut_RecoToSim" ) ),
12  threeHitTracksAreSpecial_( config.getParameter<bool> ( "ThreeHitTracksAreSpecial" ) )
13 {
14  //
15  // Check whether the denominator when working out the percentage of shared hits should
16  // be the number of simulated hits or the number of reconstructed hits.
17  //
18  std::string denominatorString=config.getParameter<std::string>("SimToRecoDenominator");
19  if( denominatorString=="sim" ) simToRecoDenominator_=denomsim;
20  else if( denominatorString=="reco" ) simToRecoDenominator_=denomreco;
21  else throw cms::Exception( "QuickTrackAssociatorByHits" ) << "SimToRecoDenominator not specified as sim or reco";
22 
23  //
24  // Set up the parameter set for the hit associator
25  //
26  hitAssociatorParameters_.addParameter<bool>( "associatePixel", config.getParameter<bool>("associatePixel") );
27  hitAssociatorParameters_.addParameter<bool>( "associateStrip", config.getParameter<bool>("associateStrip") );
28  // This is the important one, it stops the hit associator searching through the list of sim hits.
29  // I only want to use the hit associator methods that work on the hit IDs (i.e. the uint32_t trackId
30  // and the EncodedEventId eventId) so I'm not interested in matching that to the PSimHit objects.
31  hitAssociatorParameters_.addParameter<bool>("associateRecoTracks",true);
32 
33  //
34  // Do some checks on whether UseGrouped or UseSplitting have been set. They're not used
35  // unlike the standard TrackAssociatorByHits so show a warning.
36  //
37  bool useGrouped, useSplitting;
38  if( config.exists("UseGrouped") ) useGrouped=config.getParameter<bool>("UseGrouped");
39  else useGrouped=true;
40 
41  if( config.exists("UseSplitting") ) useSplitting=config.getParameter<bool>("UseSplitting");
42  else useSplitting=true;
43 
44  // This associator works as though both UseGrouped and UseSplitting were set to true, so show a
45  // warning if this isn't the case.
46  if( !(useGrouped && useSplitting) )
47  {
48  edm::LogWarning("QuickTrackAssociatorByHits") << "UseGrouped and/or UseSplitting has been set to false, but this associator ignores that setting.";
49  }
50 }
51 
53 {
54  delete pHitAssociator_;
55 }
56 
58  : pEventForWhichAssociatorIsValid_(otherAssociator.pEventForWhichAssociatorIsValid_),
59  hitAssociatorParameters_(otherAssociator.hitAssociatorParameters_),
60  absoluteNumberOfHits_(otherAssociator.absoluteNumberOfHits_),
61  qualitySimToReco_(otherAssociator.qualitySimToReco_),
62  puritySimToReco_(otherAssociator.puritySimToReco_),
63  cutRecoToSim_(otherAssociator.cutRecoToSim_),
64  threeHitTracksAreSpecial_(otherAssociator.threeHitTracksAreSpecial_),
65  simToRecoDenominator_(otherAssociator.simToRecoDenominator_),
66  pTrackCollectionHandle_(otherAssociator.pTrackCollectionHandle_),
67  pTrackCollection_(otherAssociator.pTrackCollection_),
68  pTrackingParticleCollectionHandle_(otherAssociator.pTrackingParticleCollectionHandle_),
69  pTrackingParticleCollection_(otherAssociator.pTrackingParticleCollection_)
70 
71 {
72  // No operation other than the initialiser list. That copies everything straight from the other
73  // associator, except for pHitAssociator_ which needs a deep copy or both instances will try
74  // and free it on deletion. If it wasn't for pHitAssociator_ the default copy constructor and
75  // assignment operator would be sufficient.
76 
77  // Actually, need to check the other hit associator isn't null or the pointer dereference would
78  // probably cause a segmentation fault.
79  if( otherAssociator.pHitAssociator_ ) pHitAssociator_=new TrackerHitAssociator(*otherAssociator.pHitAssociator_);
80  else pHitAssociator_=NULL;
81 }
82 
84 {
85  // Free up the old pHitAssociator_
86  delete pHitAssociator_;
87 
88  //
89  // pHitAssociator_ needs to be given a deep copy of the object, but everything else can
90  // can be shallow copied from the other associator.
91  //
92  if( otherAssociator.pHitAssociator_ ) pHitAssociator_=new TrackerHitAssociator(*otherAssociator.pHitAssociator_);
93  else pHitAssociator_=NULL;
97  qualitySimToReco_=otherAssociator.qualitySimToReco_;
98  puritySimToReco_=otherAssociator.puritySimToReco_;
99  cutRecoToSim_=otherAssociator.cutRecoToSim_;
103  pTrackCollection_=otherAssociator.pTrackCollection_;
106 
107  return *this;
108 }
109 
111  edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
112  const edm::Event* pEvent,
113  const edm::EventSetup* pSetup ) const
114 {
115  initialiseHitAssociator( pEvent );
116  pTrackCollectionHandle_=&trackCollectionHandle;
117  pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
120 
121  // This method checks which collection type is set to NULL, and uses the other one.
123 }
124 
126  edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
127  const edm::Event * pEvent,
128  const edm::EventSetup * pSetup ) const
129 {
130  initialiseHitAssociator( pEvent );
131  pTrackCollectionHandle_=&trackCollectionHandle;
132  pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
135 
136  // This method checks which collection type is set to NULL, and uses the other one.
138 }
139 
140 
142  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection,
143  const edm::Event* pEvent,
144  const edm::EventSetup* pSetup ) const
145 {
146  initialiseHitAssociator( pEvent );
149  pTrackCollection_=&trackCollection;
150  pTrackingParticleCollection_=&trackingParticleCollection;
151 
152  // This method checks which collection type is set to NULL, and uses the other one.
154 }
155 
157  const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection,
158  const edm::Event* pEvent,
159  const edm::EventSetup* pSetup ) const
160 {
161  initialiseHitAssociator( pEvent );
164  pTrackCollection_=&trackCollection;
165  pTrackingParticleCollection_=&trackingParticleCollection;
166 
167  // This method checks which collection type is set to NULL, and uses the other one.
169 }
170 
172 {
173  reco::RecoToSimCollection returnValue;
174 
175  size_t collectionSize;
176  // Need to check which pointer is valid to get the collection size
177  if( pTrackCollection_ ) collectionSize=pTrackCollection_->size();
178  else collectionSize=(*pTrackCollectionHandle_)->size();
179 
180  for( size_t i=0; i<collectionSize; ++i )
181  {
182  const reco::Track* pTrack; // Get a normal pointer for ease of use.
183  if( pTrackCollection_ ) pTrack=&*(*pTrackCollection_)[i]; // Possibly the most obscure dereference I've ever had to write
184  else pTrack=&(*pTrackCollectionHandle_->product())[i];
185 
186  // The return of this function has first as the index and second as the number of associated hits
187  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( pTrack );
188  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
189  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
190  {
191  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
192  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
193  size_t numberOfValidTrackHits=pTrack->found();
194 
195  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
196 
197  //if electron subtract double counting
198  if( abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
199  {
200  numberOfSharedHits-=getDoubleCount( pTrack->recHitsBegin(), pTrack->recHitsEnd(), *trackingParticleRef );
201  }
202 
203  double quality;
204  if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
205  else if( numberOfValidTrackHits != 0 ) quality=(static_cast<double>(numberOfSharedHits) / static_cast<double>(numberOfValidTrackHits) );
206  else quality=0;
207 
208  if( quality > cutRecoToSim_ && !( threeHitTracksAreSpecial_ && numberOfValidTrackHits==3 && numberOfSharedHits<3 ) )
209  {
210  if( pTrackCollection_ ) returnValue.insert( (*pTrackCollection_)[i], std::make_pair( trackingParticleRef, quality ));
211  else returnValue.insert( edm::RefToBase<reco::Track>(*pTrackCollectionHandle_,i), std::make_pair( trackingParticleRef, quality ));
212  }
213  }
214  }
215  return returnValue;
216 }
217 
219 {
220  reco::SimToRecoCollection returnValue;
221 
222  size_t collectionSize;
223  // Need to check which pointer is valid to get the collection size
224  if( pTrackCollection_ ) collectionSize=pTrackCollection_->size();
225  else collectionSize=(*pTrackCollectionHandle_)->size();
226 
227  for( size_t i=0; i<collectionSize; ++i )
228  {
229  const reco::Track* pTrack; // Get a normal pointer for ease of use.
230  if( pTrackCollection_ ) pTrack=&*(*pTrackCollection_)[i]; // Possibly the most obscure dereference I've ever had to write
231  else pTrack=&(*pTrackCollectionHandle_->product())[i];
232 
233  // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
234  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs=associateTrack( pTrack );
235  for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
236  iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
237  {
238  const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
239  size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
240  size_t numberOfValidTrackHits=pTrack->found();
241  size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
242 
243  if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
244 
245  if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
246  {
247  // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
248  // various things. I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
249  // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
250  // hits in the tracker.
251  numberOfSimulatedHits=trackingParticleRef->trackPSimHit(DetId::Tracker).size();
252  }
253 
254  double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
255  double quality;
256  if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
257  else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
258  else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
259  else quality=0;
260 
261  if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
262  {
263  if( pTrackCollection_ ) returnValue.insert( trackingParticleRef, std::make_pair( (*pTrackCollection_)[i], quality ) );
264  else returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase<reco::Track>(*pTrackCollectionHandle_,i) , quality ) );
265  }
266  }
267  }
268  return returnValue;
269 
270 }
271 
272 std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHits::associateTrack( const reco::Track* pTrack ) const
273 {
274  // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated hits as "second"
275  std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
276 
277  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
278  // 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
279  // number of reco hits. The pair::second entries should add up to the total number of reco hits though.
280  std::vector< std::pair<SimTrackIdentifiers,size_t> > hitIdentifiers=getAllSimTrackIdentifiers(pTrack);
281 
282  // Loop over the TrackingParticles
283  size_t collectionSize;
285  else collectionSize=(*pTrackingParticleCollectionHandle_)->size();
286 
287  for( size_t i=0; i<collectionSize; ++i )
288  {
289  const TrackingParticle* pTrackingParticle; // Convert to raw pointer for ease of use
290  if( pTrackingParticleCollection_ ) pTrackingParticle=&*(*pTrackingParticleCollection_)[i];
291  else pTrackingParticle=&(*pTrackingParticleCollectionHandle_->product())[i];
292 
293  // Ignore TrackingParticles with no hits
294  if( pTrackingParticle->trackPSimHit().empty() ) continue;
295 
296  size_t numberOfAssociatedHits=0;
297  // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
298  // the number of reco hits associated to that sim track to the total number of associated hits.
299  for( std::vector< std::pair<SimTrackIdentifiers,size_t> >::const_iterator iIdentifierCountPair=hitIdentifiers.begin(); iIdentifierCountPair!=hitIdentifiers.end(); ++iIdentifierCountPair )
300  {
301  if( trackingParticleContainsIdentifier( pTrackingParticle, iIdentifierCountPair->first ) ) numberOfAssociatedHits+=iIdentifierCountPair->second;
302  }
303 
304  if( numberOfAssociatedHits>0 )
305  {
306  if( pTrackingParticleCollection_ ) returnValue.push_back( std::make_pair( (*pTrackingParticleCollection_)[i], numberOfAssociatedHits ) );
307  else returnValue.push_back( std::make_pair( edm::Ref<TrackingParticleCollection>( *pTrackingParticleCollectionHandle_, i ), numberOfAssociatedHits ) );
308  }
309  }
310 
311  return returnValue;
312 }
313 
314 std::vector< std::pair<QuickTrackAssociatorByHits::SimTrackIdentifiers,size_t> > QuickTrackAssociatorByHits::getAllSimTrackIdentifiers( const reco::Track* pTrack ) const
315 {
316  // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
317  std::vector< std::pair<SimTrackIdentifiers,size_t> > returnValue;
318 
319  std::vector<SimTrackIdentifiers> simTrackIdentifiers;
320  // Loop over all of the rec hits in the track
321  for( trackingRecHit_iterator iRecHit=pTrack->recHitsBegin(); iRecHit!=pTrack->recHitsEnd(); ++iRecHit )
322  {
323  if( (*iRecHit)->isValid() )
324  {
325  simTrackIdentifiers.clear();
326 
327  // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
328  // have merged (as far as I know).
329  pHitAssociator_->associateHitId( **iRecHit, simTrackIdentifiers ); // This call fills simTrackIdentifiers
330 
331  // Loop over each identifier, and add it to the return value only if it's not already in there
332  for( std::vector<SimTrackIdentifiers>::const_iterator iIdentifier=simTrackIdentifiers.begin(); iIdentifier!=simTrackIdentifiers.end(); ++iIdentifier )
333  {
334  std::vector< std::pair<SimTrackIdentifiers,size_t> >::iterator iIdentifierCountPair;
335  for( iIdentifierCountPair=returnValue.begin(); iIdentifierCountPair!=returnValue.end(); ++iIdentifierCountPair )
336  {
337  if( iIdentifierCountPair->first.first==iIdentifier->first && iIdentifierCountPair->first.second==iIdentifier->second )
338  {
339  // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
340  ++iIdentifierCountPair->second;
341  break;
342  }
343  }
344  if( iIdentifierCountPair==returnValue.end() ) returnValue.push_back( std::make_pair(*iIdentifier,1) ); // This identifier wasn't found, so add it
345  }
346  }
347  }
348 
349  return returnValue;
350 }
351 
353 {
354  // Loop over all of the g4 tracks in the tracking particle
355  for( std::vector<SimTrack>::const_iterator iSimTrack=pTrackingParticle->g4Track_begin(); iSimTrack!=pTrackingParticle->g4Track_end(); ++iSimTrack )
356  {
357  // And see if the sim track identifiers match
358  if( iSimTrack->eventId()==identifier.second && iSimTrack->trackId()==identifier.first )
359  {
360  return true;
361  }
362  }
363 
364  // If control has made it this far then none of the identifiers were found in
365  // any of the g4 tracks, so return false.
366  return false;
367 }
368 
369 int QuickTrackAssociatorByHits::getDoubleCount( trackingRecHit_iterator startIterator, trackingRecHit_iterator endIterator, const TrackingParticle& associatedTrackingParticle ) const
370 {
371  // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
372  // it makes I'll go through and comment it properly.
373 
374  int doubleCount=0;
375  std::vector<SimHitIdpr> SimTrackIdsDC;
376 
377  for( trackingRecHit_iterator iHit=startIterator; iHit != endIterator; iHit++ )
378  {
379  int idcount=0;
380  SimTrackIdsDC.clear();
381  pHitAssociator_->associateHitId( **iHit, SimTrackIdsDC );
382 
383  if( SimTrackIdsDC.size() > 1 )
384  {
385  for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle.g4Track_begin(); g4T != associatedTrackingParticle.g4Track_end(); ++g4T )
386  {
387  if( find( SimTrackIdsDC.begin(), SimTrackIdsDC.end(), SimHitIdpr( ( *g4T).trackId(), SimTrackIdsDC.begin()->second ) )
388  != SimTrackIdsDC.end() )
389  {
390  idcount++;
391  }
392  }
393  }
394  if( idcount > 1 ) doubleCount+=(idcount - 1);
395  }
396 
397  return doubleCount;
398 }
399 
400 
402 {
403  // The intention of this function was to check whether the hit associator is still valid
404  // (since in general associateSimToReco and associateRecoToSim are called for the same
405  // event). I was doing this by recording the event pointer and checking it hasn't changed
406  // but this doesn't appear to work. Until I find a way of uniquely identifying an event
407  // I'll just create it anew each time.
408 // if( pEventForWhichAssociatorIsValid_==pEvent && pEventForWhichAssociatorIsValid_!=NULL ) return; // Already set up so no need to do anything
409 
410  // Free up the previous instantiation
411  delete pHitAssociator_;
412 
413  // Create a new instantiation using the new event
416 }
417 
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
TrackAssociator that associates by hits a bit quicker than the normal TrackAssociatorByHits class...
int getDoubleCount(trackingRecHit_iterator begin, trackingRecHit_iterator end, const TrackingParticle &associatedTrackingParticle) const
This method was copied almost verbatim from the standard TrackAssociatorByHits.
const std::vector< PSimHit > & trackPSimHit() const
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.
g4t_iterator g4Track_begin() const
bool exists(std::string const &parameterName) const
checks if a parameter exists
#define abs(x)
Definition: mlp_lapack.h:159
#define NULL
Definition: scimark2.h:8
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
reco::RecoToSimCollection associateRecoToSimImplementation() const
The method that does the work for both overloads of associateRecoToSim.
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:145
size_type size() const
trackingRecHit_iterator recHitsBegin() const
Iterator to first hit on the track.
Definition: Track.h:63
std::vector< std::pair< edm::Ref< TrackingParticleCollection >, size_t > > associateTrack(const reco::Track *pTrack) const
Returns the TrackingParticle that has the most associated hits to the given track.
std::vector< SimTrack >::const_iterator g4t_iterator
std::pair< uint32_t, EncodedEventId > SimHitIdpr
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.
T const * product() const
Definition: Handle.h:74
edm::Handle< TrackingParticleCollection > * pTrackingParticleCollectionHandle_
Pointer to the TrackingParticle collection handle.
const edm::RefToBaseVector< reco::Track > * pTrackCollection_
Pointer to the track collection.
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
void initialiseHitAssociator(const edm::Event *event) const
edm::Handle< edm::View< reco::Track > > * pTrackCollectionHandle_
Pointer to the handle to the track collection.
g4t_iterator g4Track_end() const
std::vector< std::pair< SimTrackIdentifiers, size_t > > getAllSimTrackIdentifiers(const reco::Track *pTrack) const
Returns a vector of pairs where first is a SimTrackIdentifiers (see typedef above) and second is the ...
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
compare reco to sim the handle of reco::Track and TrackingParticle collections
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
compare reco to sim the handle of reco::Track and TrackingParticle collections
TrackerHitAssociator * pHitAssociator_
trackingRecHit_iterator recHitsEnd() const
Iterator to last hit on the track.
Definition: Track.h:65