CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/SimTracker/TrackAssociation/src/QuickTrackAssociatorByHits.cc

Go to the documentation of this file.
00001 #include <iostream>
00002 #include <fstream>
00003 
00004 #include "SimTracker/TrackAssociation/interface/QuickTrackAssociatorByHits.h"
00005 
00006 #include "SimTracker/TrackerHitAssociation/interface/TrackerHitAssociator.h"
00007 
00008 #include "DataFormats/TrackerRecHit2D/interface/SiPixelRecHit.h"
00009 #include "DataFormats/TrackerRecHit2D/interface/SiStripMatchedRecHit2D.h"
00010 #include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit2D.h"
00011 #include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit1D.h"
00012 #include "DataFormats/SiStripDetId/interface/SiStripDetId.h"
00013 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 #include "DataFormats/Math/interface/deltaR.h"
00016 
00017 QuickTrackAssociatorByHits::QuickTrackAssociatorByHits( const edm::ParameterSet& config )
00018         : pHitAssociator_(NULL), pEventForWhichAssociatorIsValid_(NULL),
00019           absoluteNumberOfHits_( config.getParameter<bool>( "AbsoluteNumberOfHits" ) ),
00020           qualitySimToReco_( config.getParameter<double>( "Quality_SimToReco" ) ),
00021           puritySimToReco_( config.getParameter<double>( "Purity_SimToReco" ) ),
00022           cutRecoToSim_( config.getParameter<double>( "Cut_RecoToSim" ) ),
00023           threeHitTracksAreSpecial_( config.getParameter<bool> ( "ThreeHitTracksAreSpecial" ) ),
00024           useClusterTPAssociation_(config.getParameter<bool>("useClusterTPAssociation")),
00025           cluster2TPSrc_(config.getParameter<edm::InputTag>("cluster2TPSrc"))
00026 {
00027         //
00028         // Check whether the denominator when working out the percentage of shared hits should
00029         // be the number of simulated hits or the number of reconstructed hits.
00030         //
00031         std::string denominatorString=config.getParameter<std::string>("SimToRecoDenominator");
00032         if( denominatorString=="sim" ) simToRecoDenominator_=denomsim;
00033         else if( denominatorString=="reco" ) simToRecoDenominator_=denomreco;
00034         else throw cms::Exception( "QuickTrackAssociatorByHits" ) << "SimToRecoDenominator not specified as sim or reco";
00035 
00036         //
00037         // Set up the parameter set for the hit associator
00038         //
00039         hitAssociatorParameters_.addParameter<bool>( "associatePixel", config.getParameter<bool>("associatePixel") );
00040         hitAssociatorParameters_.addParameter<bool>( "associateStrip", config.getParameter<bool>("associateStrip") );
00041         // This is the important one, it stops the hit associator searching through the list of sim hits.
00042         // I only want to use the hit associator methods that work on the hit IDs (i.e. the uint32_t trackId
00043         // and the EncodedEventId eventId) so I'm not interested in matching that to the PSimHit objects.
00044         hitAssociatorParameters_.addParameter<bool>("associateRecoTracks",true);
00045 
00046         //
00047         // Do some checks on whether UseGrouped or UseSplitting have been set. They're not used
00048         // unlike the standard TrackAssociatorByHits so show a warning.
00049         //
00050         bool useGrouped, useSplitting;
00051         if( config.exists("UseGrouped") ) useGrouped=config.getParameter<bool>("UseGrouped");
00052         else useGrouped=true;
00053 
00054         if( config.exists("UseSplitting") ) useSplitting=config.getParameter<bool>("UseSplitting");
00055         else useSplitting=true;
00056 
00057         // This associator works as though both UseGrouped and UseSplitting were set to true, so show a
00058         // warning if this isn't the case.
00059         if( !(useGrouped && useSplitting) )
00060         {
00061                 edm::LogWarning("QuickTrackAssociatorByHits") << "UseGrouped and/or UseSplitting has been set to false, but this associator ignores that setting.";
00062         }
00063 }
00064 
00065 QuickTrackAssociatorByHits::~QuickTrackAssociatorByHits()
00066 {
00067         delete pHitAssociator_;
00068 }
00069 
00070 QuickTrackAssociatorByHits::QuickTrackAssociatorByHits( const QuickTrackAssociatorByHits& otherAssociator )
00071         : pEventForWhichAssociatorIsValid_(otherAssociator.pEventForWhichAssociatorIsValid_),
00072           hitAssociatorParameters_(otherAssociator.hitAssociatorParameters_),
00073           absoluteNumberOfHits_(otherAssociator.absoluteNumberOfHits_),
00074           qualitySimToReco_(otherAssociator.qualitySimToReco_),
00075           puritySimToReco_(otherAssociator.puritySimToReco_),
00076           cutRecoToSim_(otherAssociator.cutRecoToSim_),
00077           threeHitTracksAreSpecial_(otherAssociator.threeHitTracksAreSpecial_),
00078           simToRecoDenominator_(otherAssociator.simToRecoDenominator_),
00079           pTrackCollectionHandle_(otherAssociator.pTrackCollectionHandle_),
00080           pTrackCollection_(otherAssociator.pTrackCollection_),
00081           pTrackingParticleCollectionHandle_(otherAssociator.pTrackingParticleCollectionHandle_),
00082           pTrackingParticleCollection_(otherAssociator.pTrackingParticleCollection_),
00083           useClusterTPAssociation_(otherAssociator.useClusterTPAssociation_),
00084           cluster2TPSrc_(otherAssociator.cluster2TPSrc_)
00085 {
00086         // No operation other than the initialiser list. That copies everything straight from the other
00087         // associator, except for pHitAssociator_ which needs a deep copy or both instances will try
00088         // and free it on deletion.  If it wasn't for pHitAssociator_ the default copy constructor and
00089         // assignment operator would be sufficient.
00090 
00091         // Actually, need to check the other hit associator isn't null or the pointer dereference would
00092         // probably cause a segmentation fault.
00093         if( otherAssociator.pHitAssociator_ ) pHitAssociator_=new TrackerHitAssociator(*otherAssociator.pHitAssociator_);
00094         else pHitAssociator_=NULL;
00095 }
00096 
00097 QuickTrackAssociatorByHits& QuickTrackAssociatorByHits::operator=( const QuickTrackAssociatorByHits& otherAssociator )
00098 {
00099         // Free up the old pHitAssociator_
00100         delete pHitAssociator_;
00101 
00102         //
00103         // pHitAssociator_ needs to be given a deep copy of the object, but everything else can
00104         // can be shallow copied from the other associator.
00105         //
00106         if( otherAssociator.pHitAssociator_ ) pHitAssociator_=new TrackerHitAssociator(*otherAssociator.pHitAssociator_);
00107         else pHitAssociator_=NULL;
00108         pEventForWhichAssociatorIsValid_=otherAssociator.pEventForWhichAssociatorIsValid_;
00109         hitAssociatorParameters_=otherAssociator.hitAssociatorParameters_;
00110         absoluteNumberOfHits_=otherAssociator.absoluteNumberOfHits_;
00111         qualitySimToReco_=otherAssociator.qualitySimToReco_;
00112         puritySimToReco_=otherAssociator.puritySimToReco_;
00113         cutRecoToSim_=otherAssociator.cutRecoToSim_;
00114         threeHitTracksAreSpecial_=otherAssociator.threeHitTracksAreSpecial_;
00115         useClusterTPAssociation_ = otherAssociator.useClusterTPAssociation_,
00116         cluster2TPSrc_ = otherAssociator.cluster2TPSrc_;
00117         simToRecoDenominator_=otherAssociator.simToRecoDenominator_;
00118         pTrackCollectionHandle_=otherAssociator.pTrackCollectionHandle_;
00119         pTrackCollection_=otherAssociator.pTrackCollection_;
00120         pTrackingParticleCollectionHandle_=otherAssociator.pTrackingParticleCollectionHandle_;
00121         pTrackingParticleCollection_=otherAssociator.pTrackingParticleCollection_;
00122 
00123         return *this;
00124 }
00125 
00126 reco::RecoToSimCollection QuickTrackAssociatorByHits::associateRecoToSim( edm::Handle<edm::View<reco::Track> >& trackCollectionHandle,
00127                                                                               edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
00128                                                                               const edm::Event* pEvent,
00129                                                                               const edm::EventSetup* pSetup ) const
00130 {
00131 
00132         // get the Cluster2TPMap or initialize hit associator
00133         if (useClusterTPAssociation_) prepareCluster2TPMap(pEvent);
00134         else initialiseHitAssociator( pEvent );
00135 
00136         pTrackCollectionHandle_=&trackCollectionHandle;
00137         pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
00138         pTrackCollection_=NULL;
00139         pTrackingParticleCollection_=NULL;
00140 
00141         // This method checks which collection type is set to NULL, and uses the other one.
00142         return associateRecoToSimImplementation();
00143 }
00144 
00145 reco::SimToRecoCollection QuickTrackAssociatorByHits::associateSimToReco( edm::Handle<edm::View<reco::Track> >& trackCollectionHandle,
00146                                                                               edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle,
00147                                                                               const edm::Event * pEvent,
00148                                                                               const edm::EventSetup * pSetup ) const
00149 {
00150 
00151         // get the Cluster2TPMap or initialize hit associator
00152         if (useClusterTPAssociation_) prepareCluster2TPMap(pEvent);
00153         else initialiseHitAssociator( pEvent );
00154 
00155         pTrackCollectionHandle_=&trackCollectionHandle;
00156         pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
00157         pTrackCollection_=NULL;
00158         pTrackingParticleCollection_=NULL;
00159 
00160         // This method checks which collection type is set to NULL, and uses the other one.
00161         return associateSimToRecoImplementation();
00162 }
00163 
00164 
00165 reco::RecoToSimCollection QuickTrackAssociatorByHits::associateRecoToSim(const edm::RefToBaseVector<reco::Track>& trackCollection,
00166                                                                          const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection,
00167                                                                          const edm::Event* pEvent,
00168                                                                          const edm::EventSetup* pSetup ) const
00169 {
00170 
00171   // get the Cluster2TPMap or initialize hit associator
00172   if (useClusterTPAssociation_) prepareCluster2TPMap(pEvent);
00173   else initialiseHitAssociator( pEvent );
00174 
00175   pTrackCollectionHandle_=NULL;
00176   pTrackingParticleCollectionHandle_=NULL;
00177   pTrackCollection_=&trackCollection;
00178   pTrackingParticleCollection_=&trackingParticleCollection;
00179 
00180   // This method checks which collection type is set to NULL, and uses the other one.
00181   return associateRecoToSimImplementation();
00182 }
00183 
00184 reco::SimToRecoCollection QuickTrackAssociatorByHits::associateSimToReco(const edm::RefToBaseVector<reco::Track>& trackCollection,
00185                                                                          const edm::RefVector<TrackingParticleCollection>& trackingParticleCollection,
00186                                                                          const edm::Event* pEvent,
00187                                                                          const edm::EventSetup* pSetup ) const
00188 {
00189 
00190   // get the Cluster2TPMap or initialize hit associator
00191   if (useClusterTPAssociation_) prepareCluster2TPMap(pEvent);
00192   else initialiseHitAssociator( pEvent );
00193 
00194   pTrackCollectionHandle_=NULL;
00195   pTrackingParticleCollectionHandle_=NULL;
00196   pTrackCollection_=&trackCollection;
00197   pTrackingParticleCollection_=&trackingParticleCollection;
00198 
00199   // This method checks which collection type is set to NULL, and uses the other one.
00200   return associateSimToRecoImplementation();
00201 }
00202 
00203 reco::RecoToSimCollection QuickTrackAssociatorByHits::associateRecoToSimImplementation() const
00204 {
00205   reco::RecoToSimCollection returnValue;
00206 
00207   size_t collectionSize;
00208   // Need to check which pointer is valid to get the collection size
00209   if ( pTrackCollection_ ) collectionSize=pTrackCollection_->size();
00210   else collectionSize=(*pTrackCollectionHandle_)->size();
00211 
00212   //std::cout << "#reco Tracks = " << collectionSize << std::endl;
00213   for( size_t i=0; i<collectionSize; ++i )
00214   {
00215     const reco::Track* pTrack; // Get a normal pointer for ease of use.
00216     if( pTrackCollection_ ) pTrack=&*(*pTrackCollection_)[i]; // Possibly the most obscure dereference I've ever had to write
00217     else pTrack=&(*pTrackCollectionHandle_->product())[i];
00218     //    std::cout << ">>> recoTrack #index = " << i << " pt = " << pTrack->pt() << std::endl;
00219 
00220     // The return of this function has first as the index and second as the number of associated hits
00221     std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs = (useClusterTPAssociation_) 
00222       ? associateTrackByCluster( pTrack->recHitsBegin(),pTrack->recHitsEnd() )
00223       : associateTrack( pTrack->recHitsBegin(), pTrack->recHitsEnd() );
00224 
00225     // int nt = 0;
00226     for (std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin(); iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
00227     {
00228       const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
00229       size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
00230       size_t numberOfValidTrackHits=pTrack->found();
00231           
00232       //std::cout << ">>> reco2sim. numberOfSharedHits = " << nt++ << ", " << numberOfSharedHits << std::endl;
00233       if (numberOfSharedHits==0) continue; // No point in continuing if there was no association
00234 
00235       //if electron subtract double counting
00236       if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
00237       {
00238         numberOfSharedHits -= getDoubleCount( pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
00239       }
00240 
00241       double quality;
00242       if (absoluteNumberOfHits_ ) 
00243         quality = static_cast<double>(numberOfSharedHits);
00244       else if (numberOfValidTrackHits != 0) 
00245         quality = (static_cast<double>(numberOfSharedHits) / static_cast<double>(numberOfValidTrackHits));
00246       else 
00247         quality = 0;
00248       if (quality > cutRecoToSim_ && !( threeHitTracksAreSpecial_ && numberOfValidTrackHits==3 && numberOfSharedHits<3 ) )
00249       {
00250         if (pTrackCollection_) returnValue.insert( (*pTrackCollection_)[i], std::make_pair( trackingParticleRef, quality ));
00251         else returnValue.insert( edm::RefToBase<reco::Track>(*pTrackCollectionHandle_,i), std::make_pair( trackingParticleRef, quality ));
00252       }
00253     }
00254   }
00255   return returnValue;
00256 }
00257 
00258 reco::SimToRecoCollection QuickTrackAssociatorByHits::associateSimToRecoImplementation() const
00259 {
00260   reco::SimToRecoCollection returnValue;
00261 
00262         size_t collectionSize;
00263         // Need to check which pointer is valid to get the collection size
00264         if( pTrackCollection_ ) collectionSize=pTrackCollection_->size();
00265         else collectionSize=(*pTrackCollectionHandle_)->size();
00266 
00267         for( size_t i=0; i<collectionSize; ++i )
00268         {
00269                 const reco::Track* pTrack; // Get a normal pointer for ease of use.
00270                 if( pTrackCollection_ ) pTrack=&*(*pTrackCollection_)[i]; // Possibly the most obscure dereference I've ever had to write
00271                 else pTrack=&(*pTrackCollectionHandle_->product())[i];
00272 
00273                 // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
00274                 std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs = (useClusterTPAssociation_) 
00275                 ? associateTrackByCluster( pTrack->recHitsBegin(),pTrack->recHitsEnd() )
00276                 : associateTrack( pTrack->recHitsBegin(),pTrack->recHitsEnd() );
00277 
00278                 // int nt = 0;
00279                 for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
00280                                 iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
00281                 {
00282                         const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
00283                         size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
00284                         size_t numberOfValidTrackHits=pTrack->found();
00285                         size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
00286 
00287                         //std::cout << ">>> sim2reco. numberOfSharedHits = " << nt++ << ", " << numberOfSharedHits << std::endl;
00288                         if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
00289 
00290                         if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
00291                         {
00292                                 // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
00293                                 // various things.  I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
00294                                 // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
00295                                 // hits in the tracker.
00296                                 numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
00297                         }
00298 
00299 
00300                         //if electron subtract double counting
00301                         if (abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
00302                         {
00303                           numberOfSharedHits -= getDoubleCount( pTrack->recHitsBegin(), pTrack->recHitsEnd(), trackingParticleRef );
00304                         }
00305 
00306 
00307                         double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
00308                         double quality;
00309                         if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
00310                         else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
00311                         else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
00312                         else quality=0;
00313 
00314                         if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
00315                         {
00316                                 if( pTrackCollection_ ) returnValue.insert( trackingParticleRef, std::make_pair( (*pTrackCollection_)[i], quality ) );
00317                                 else returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase<reco::Track>(*pTrackCollectionHandle_,i) , quality ) );
00318                         }
00319                 }
00320         }
00321         return returnValue;
00322 
00323 }
00324 
00325 template<typename iter> std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHits::associateTrack( iter begin, iter end ) const
00326 {
00327         // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated hits as "second"
00328         std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > returnValue;
00329 
00330         // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
00331         // 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
00332         // number of reco hits.  The pair::second entries should add up to the total number of reco hits though.
00333         std::vector< std::pair<SimTrackIdentifiers,size_t> > hitIdentifiers=getAllSimTrackIdentifiers(begin, end);
00334 
00335         // Loop over the TrackingParticles
00336         size_t collectionSize;
00337         if( pTrackingParticleCollection_ ) collectionSize=pTrackingParticleCollection_->size();
00338         else collectionSize=(*pTrackingParticleCollectionHandle_)->size();
00339 
00340         for( size_t i=0; i<collectionSize; ++i )
00341         {
00342                 const TrackingParticle* pTrackingParticle; // Convert to raw pointer for ease of use
00343                 if( pTrackingParticleCollection_ ) pTrackingParticle=&*(*pTrackingParticleCollection_)[i];
00344                 else pTrackingParticle=&(*pTrackingParticleCollectionHandle_->product())[i];
00345 
00346                 // Ignore TrackingParticles with no hits
00347                 if( pTrackingParticle->numberOfHits()==0 ) continue;
00348 
00349                 size_t numberOfAssociatedHits=0;
00350                 // Loop over all of the sim track identifiers and see if any of them are part of this TrackingParticle. If they are, add
00351                 // the number of reco hits associated to that sim track to the total number of associated hits.
00352                 for( std::vector< std::pair<SimTrackIdentifiers,size_t> >::const_iterator iIdentifierCountPair=hitIdentifiers.begin(); iIdentifierCountPair!=hitIdentifiers.end(); ++iIdentifierCountPair )
00353                 {
00354                         if( trackingParticleContainsIdentifier( pTrackingParticle, iIdentifierCountPair->first ) ) numberOfAssociatedHits+=iIdentifierCountPair->second;
00355                 }
00356 
00357                 if( numberOfAssociatedHits>0 )
00358                 {
00359                         if( pTrackingParticleCollection_ ) returnValue.push_back( std::make_pair( (*pTrackingParticleCollection_)[i], numberOfAssociatedHits ) );
00360                         else returnValue.push_back( std::make_pair( edm::Ref<TrackingParticleCollection>( *pTrackingParticleCollectionHandle_, i ), numberOfAssociatedHits ) );
00361                 }
00362         }
00363 
00364         return returnValue;
00365 }
00366 
00367 void QuickTrackAssociatorByHits::prepareCluster2TPMap(const edm::Event* pEvent) const
00368 {
00369   //get the Cluster2TPList
00370   edm::Handle<ClusterTPAssociationList> pCluster2TPListH;
00371   pEvent->getByLabel(cluster2TPSrc_, pCluster2TPListH);
00372   if (pCluster2TPListH.isValid()) {
00373     pCluster2TPList_ = *(pCluster2TPListH.product());
00374     //make sure it is properly sorted
00375     std::sort(pCluster2TPList_.begin(), pCluster2TPList_.end(), clusterTPAssociationListGreater);
00376   } else {
00377     edm::LogInfo("TrackAssociator") << "ClusterTPAssociationList with label "<<cluster2TPSrc_<<" not found. Using DigiSimLink based associator";
00378     initialiseHitAssociator( pEvent );
00379     useClusterTPAssociation_ = false;
00380   }
00381 }
00382 
00383 template<typename iter> std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > QuickTrackAssociatorByHits::associateTrackByCluster(iter begin, iter end) const
00384 {
00385   // The pairs in this vector have a Ref to the associated TrackingParticle as "first" and the number of associated clusters as "second"
00386   // Note: typedef edm::Ref<TrackingParticleCollection> TrackingParticleRef;
00387   std::vector<std::pair<edm::Ref<TrackingParticleCollection>, size_t> > returnValue;
00388   if (!pCluster2TPList_.size()) return returnValue;
00389   
00390   // The pairs in this vector have first as the TP, and second the number of reco clusters associated to that TP.
00391   // Most reco clusters will probably have come from the same sim track (i.e TP), so the number of entries in this 
00392   // vector should be fewer than the number of clusters. The pair::second entries should add up to the total 
00393   // number of reco clusters though.
00394   std::vector<OmniClusterRef> oClusters = getMatchedClusters(begin, end);
00395 
00396   std::map<TrackingParticleRef, size_t> lmap; 
00397   for (std::vector<OmniClusterRef>::const_iterator it = oClusters.begin(); it != oClusters.end(); ++it) {
00398 
00399     std::pair<OmniClusterRef, TrackingParticleRef> clusterTPpairWithDummyTP(*it,TrackingParticleRef());//TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
00400     auto range = std::equal_range(pCluster2TPList_.begin(), pCluster2TPList_.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater);
00401     if(range.first != range.second) {
00402       for(auto ip = range.first; ip != range.second; ++ip) {
00403 
00404         const TrackingParticleRef trackingParticle = (ip->second);
00405 
00406         // Ignore TrackingParticles with no hits
00407         if (trackingParticle->numberOfHits()==0) continue;
00408 
00409         /* Alternative implementation to avoid the use of lmap... memory slightly improved but slightly slower...
00410         std::pair<edm::Ref<TrackingParticleCollection>,size_t> tpIntPair(trackingParticle, 1);
00411         auto tp_range = std::equal_range(returnValue.begin(), returnValue.end(), tpIntPair, tpIntPairGreater);
00412         if ((tp_range.second-tp_range.first)>1) {
00413           edm::LogError("TrackAssociator") << ">>> Error in counting TPs!" << " file: " << __FILE__ << " line: " << __LINE__;
00414         }
00415         if(tp_range.first != tp_range.second) {
00416           tp_range.first->second++;
00417         } else {
00418           returnValue.push_back(tpIntPair);
00419           std::sort(returnValue.begin(), returnValue.end(), tpIntPairGreater);
00420         }
00421         */
00422         auto jpos = lmap.find(trackingParticle);     
00423         if (jpos != lmap.end())
00424           ++jpos->second; 
00425         else 
00426           lmap.insert(std::make_pair(trackingParticle, 1));
00427       }
00428     }
00429   }
00430   // now copy the map to returnValue
00431   for (auto ip = lmap.begin(); ip != lmap.end(); ++ip) {
00432     returnValue.push_back(std::make_pair(ip->first, ip->second));
00433   }
00434   return returnValue;
00435 }
00436 
00437 template<typename iter> std::vector<OmniClusterRef> QuickTrackAssociatorByHits::getMatchedClusters(iter begin, iter end) const
00438 {
00439   std::vector<OmniClusterRef> returnValue;
00440   for (iter iRecHit = begin; iRecHit != end; ++iRecHit) {
00441     const TrackingRecHit* rhit = getHitFromIter(iRecHit);
00442     if (rhit->isValid()) {
00443       int subdetid = rhit->geographicalId().subdetId();
00444       if (subdetid==PixelSubdetector::PixelBarrel||subdetid==PixelSubdetector::PixelEndcap) {
00445         const SiPixelRecHit* pRHit = dynamic_cast<const SiPixelRecHit*>(rhit);
00446         if (!pRHit->cluster().isNonnull()) 
00447           edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
00448         returnValue.push_back(pRHit->omniClusterRef());
00449       }
00450       else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) {
00451         const std::type_info &tid = typeid(*rhit);
00452         if (tid == typeid(SiStripMatchedRecHit2D)) {
00453           const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast<const SiStripMatchedRecHit2D*>(rhit);
00454           if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull())  
00455             edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
00456           returnValue.push_back(sMatchedRHit->monoClusterRef()); 
00457           returnValue.push_back(sMatchedRHit->stereoClusterRef()); 
00458         }
00459         else if (tid == typeid(SiStripRecHit2D)) {
00460           const SiStripRecHit2D* sRHit = dynamic_cast<const SiStripRecHit2D*>(rhit);
00461           if (!sRHit->cluster().isNonnull()) 
00462             edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
00463           returnValue.push_back(sRHit->omniClusterRef());
00464         }
00465         else if (tid == typeid(SiStripRecHit1D)) {
00466           const SiStripRecHit1D* sRHit = dynamic_cast<const SiStripRecHit1D*>(rhit);
00467           if (!sRHit->cluster().isNonnull()) 
00468             edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__;
00469           returnValue.push_back(sRHit->omniClusterRef());
00470         }
00471         else {
00472           edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid;
00473         }
00474       }
00475       else {
00476         edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid;
00477       }
00478     }
00479   }
00480   return returnValue;
00481 }
00482 
00483 template<typename iter> std::vector< std::pair<QuickTrackAssociatorByHits::SimTrackIdentifiers,size_t> > QuickTrackAssociatorByHits::getAllSimTrackIdentifiers( iter begin, iter end ) const
00484 {
00485   // The pairs in this vector have first as the sim track identifiers, and second the number of reco hits associated to that sim track.
00486   std::vector< std::pair<SimTrackIdentifiers,size_t> > returnValue;
00487 
00488   std::vector<SimTrackIdentifiers> simTrackIdentifiers;
00489   // Loop over all of the rec hits in the track
00490   //iter tRHIterBeginEnd = getTRHIterBeginEnd( pTrack );
00491   for( iter iRecHit=begin; iRecHit!=end; ++iRecHit )
00492   {
00493     if( getHitFromIter(iRecHit)->isValid() )
00494     {
00495       simTrackIdentifiers.clear();
00496           
00497       // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters
00498       // have merged (as far as I know).
00499       pHitAssociator_->associateHitId( *(getHitFromIter(iRecHit)), simTrackIdentifiers ); // This call fills simTrackIdentifiers
00500       // Loop over each identifier, and add it to the return value only if it's not already in there
00501       for ( std::vector<SimTrackIdentifiers>::const_iterator iIdentifier  = simTrackIdentifiers.begin(); 
00502                                                              iIdentifier != simTrackIdentifiers.end(); 
00503                                                            ++iIdentifier )
00504       {
00505         std::vector< std::pair<SimTrackIdentifiers,size_t> >::iterator iIdentifierCountPair;
00506         for (iIdentifierCountPair=returnValue.begin(); iIdentifierCountPair!=returnValue.end(); ++iIdentifierCountPair)
00507         {
00508           if (iIdentifierCountPair->first.first==iIdentifier->first && iIdentifierCountPair->first.second==iIdentifier->second )
00509           {
00510             // This sim track identifier is already in the list, so increment the count of how many hits it relates to.
00511             ++iIdentifierCountPair->second;
00512             break;
00513           }
00514         }
00515         if( iIdentifierCountPair==returnValue.end() ) returnValue.push_back( std::make_pair(*iIdentifier,1) ); 
00516           // This identifier wasn't found, so add it
00517       }
00518     }
00519   }
00520   return returnValue;
00521 }
00522 
00523 bool QuickTrackAssociatorByHits::trackingParticleContainsIdentifier( const TrackingParticle* pTrackingParticle, const SimTrackIdentifiers& identifier ) const
00524 {
00525   // Loop over all of the g4 tracks in the tracking particle
00526   for( std::vector<SimTrack>::const_iterator iSimTrack=pTrackingParticle->g4Track_begin(); iSimTrack!=pTrackingParticle->g4Track_end(); ++iSimTrack )
00527     {
00528       // And see if the sim track identifiers match
00529       if( iSimTrack->eventId()==identifier.second && iSimTrack->trackId()==identifier.first )
00530         {
00531           return true;
00532         }
00533     }
00534 
00535   // If control has made it this far then none of the identifiers were found in
00536   // any of the g4 tracks, so return false.
00537   return false;
00538 }
00539 
00540 template<typename iter> int QuickTrackAssociatorByHits::getDoubleCount( iter startIterator, iter endIterator, TrackingParticleRef associatedTrackingParticle ) const
00541 {
00542   // This method is largely copied from the standard TrackAssociatorByHits. Once I've tested how much difference
00543   // it makes I'll go through and comment it properly.
00544 
00545   int doubleCount=0;
00546   std::vector<SimHitIdpr> SimTrackIdsDC;
00547 
00548   for( iter iHit=startIterator; iHit != endIterator; iHit++ )
00549     {
00550       int idcount=0;
00551 
00552       if (useClusterTPAssociation_) {
00553         std::vector<OmniClusterRef> oClusters = getMatchedClusters(iHit, iHit+1);//only for the cluster being checked
00554         for (std::vector<OmniClusterRef>::const_iterator it = oClusters.begin(); it != oClusters.end(); ++it) {   
00555           std::pair<OmniClusterRef, TrackingParticleRef> clusterTPpairWithDummyTP(*it,TrackingParticleRef());//TP is dummy: for clusterTPAssociationListGreater sorting only the cluster is needed
00556           auto range = std::equal_range(pCluster2TPList_.begin(), pCluster2TPList_.end(), clusterTPpairWithDummyTP, clusterTPAssociationListGreater);
00557           if(range.first != range.second) {
00558             for(auto ip = range.first; ip != range.second; ++ip) {
00559               const TrackingParticleRef trackingParticle = (ip->second);
00560               if (associatedTrackingParticle==trackingParticle) {
00561                 idcount++;
00562               }
00563             }
00564           }
00565         }
00566       } else {
00567         SimTrackIdsDC.clear();
00568         pHitAssociator_->associateHitId( *(getHitFromIter(iHit)), SimTrackIdsDC );
00569         if( SimTrackIdsDC.size() > 1 )
00570           {
00571             for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle->g4Track_begin(); g4T != associatedTrackingParticle->g4Track_end(); ++g4T )
00572               {
00573                 if( find( SimTrackIdsDC.begin(), SimTrackIdsDC.end(), SimHitIdpr( ( *g4T).trackId(), SimTrackIdsDC.begin()->second ) )
00574                     != SimTrackIdsDC.end() )
00575                   {
00576                     idcount++;
00577                   }
00578               }
00579           }
00580       }
00581       if( idcount > 1 ) doubleCount+=(idcount - 1);
00582     }
00583   
00584   return doubleCount;
00585 }
00586 
00587 
00588 void QuickTrackAssociatorByHits::initialiseHitAssociator( const edm::Event* pEvent ) const
00589 {
00590         // The intention of this function was to check whether the hit associator is still valid
00591         // (since in general associateSimToReco and associateRecoToSim are called for the same
00592         // event). I was doing this by recording the event pointer and checking it hasn't changed
00593         // but this doesn't appear to work. Until I find a way of uniquely identifying an event
00594         // I'll just create it anew each time.
00595 //      if( pEventForWhichAssociatorIsValid_==pEvent && pEventForWhichAssociatorIsValid_!=NULL ) return; // Already set up so no need to do anything
00596 
00597         // Free up the previous instantiation
00598         delete pHitAssociator_;
00599 
00600         // Create a new instantiation using the new event
00601         pHitAssociator_=new TrackerHitAssociator( *pEvent, hitAssociatorParameters_ );
00602         pEventForWhichAssociatorIsValid_=pEvent;
00603 }
00604 
00605 
00606 
00607 reco::RecoToSimCollectionSeed  
00608 QuickTrackAssociatorByHits::associateRecoToSim(edm::Handle<edm::View<TrajectorySeed> >& pSeedCollectionHandle_,
00609                                                edm::Handle<TrackingParticleCollection>&  trackingParticleCollectionHandle,     
00610                                                const edm::Event * pEvent,
00611                                                const edm::EventSetup *setup ) const{
00612 
00613   edm::LogVerbatim("TrackAssociator") << "Starting TrackAssociatorByHits::associateRecoToSim - #seeds="
00614                                       << pSeedCollectionHandle_->size()<<" #TPs="<<trackingParticleCollectionHandle->size();
00615 
00616   initialiseHitAssociator( pEvent );
00617   pTrackCollectionHandle_=NULL;
00618   pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
00619   pTrackCollection_=NULL;
00620   pTrackingParticleCollection_=NULL;
00621 
00622   reco::RecoToSimCollectionSeed  returnValue;
00623 
00624   size_t collectionSize=pSeedCollectionHandle_->size();
00625   
00626   for( size_t i=0; i<collectionSize; ++i )
00627     {
00628       const TrajectorySeed* pSeed = &(*pSeedCollectionHandle_)[i];
00629       
00630       // The return of this function has first as the index and second as the number of associated hits
00631       std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs =  (useClusterTPAssociation_) 
00632         ? associateTrackByCluster( pSeed->recHits().first,pSeed->recHits().second )
00633         : associateTrack( pSeed->recHits().first,pSeed->recHits().second );
00634       for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
00635            iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
00636         {
00637           const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
00638           size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
00639           size_t numberOfValidTrackHits=pSeed->recHits().second-pSeed->recHits().first;
00640           
00641           if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
00642           
00643           //if electron subtract double counting
00644           if( abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
00645             {
00646               numberOfSharedHits-=getDoubleCount( pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
00647             }
00648           
00649           double quality;
00650           if( absoluteNumberOfHits_ ) quality=static_cast<double>( numberOfSharedHits );
00651           else if( numberOfValidTrackHits != 0 ) quality=(static_cast<double>(numberOfSharedHits) / static_cast<double>(numberOfValidTrackHits) );
00652           else quality=0;
00653           
00654           if( quality > cutRecoToSim_ && !( threeHitTracksAreSpecial_ && numberOfValidTrackHits==3 && numberOfSharedHits<3 ) )
00655             {
00656               returnValue.insert( edm::RefToBase<TrajectorySeed>(pSeedCollectionHandle_,i), std::make_pair( trackingParticleRef, quality ));
00657             }
00658         }
00659     }
00660   
00661   LogTrace("TrackAssociator") << "% of Assoc Seeds=" << ((double)returnValue.size())/((double)pSeedCollectionHandle_->size());
00662   returnValue.post_insert();
00663   return returnValue;
00664   
00665 }
00666 
00667 
00668 reco::SimToRecoCollectionSeed
00669 QuickTrackAssociatorByHits::associateSimToReco(edm::Handle<edm::View<TrajectorySeed> >& pSeedCollectionHandle_,
00670                                                edm::Handle<TrackingParticleCollection>& trackingParticleCollectionHandle, 
00671                                                const edm::Event * pEvent,
00672                                                const edm::EventSetup *setup ) const{
00673 
00674   edm::LogVerbatim("TrackAssociator") << "Starting TrackAssociatorByHits::associateSimToReco - #seeds="
00675                                       <<pSeedCollectionHandle_->size()<<" #TPs="<<trackingParticleCollectionHandle->size();
00676 
00677   initialiseHitAssociator( pEvent );
00678   pTrackCollectionHandle_=NULL;
00679   pTrackingParticleCollectionHandle_=&trackingParticleCollectionHandle;
00680   pTrackCollection_=NULL;
00681   pTrackingParticleCollection_=NULL;
00682 
00683   reco::SimToRecoCollectionSeed  returnValue;
00684 
00685   size_t collectionSize=pSeedCollectionHandle_->size();
00686   
00687   for( size_t i=0; i<collectionSize; ++i )
00688     {
00689       const TrajectorySeed* pSeed=&(*pSeedCollectionHandle_)[i];
00690       
00691       // The return of this function has first as an edm:Ref to the associated TrackingParticle, and second as the number of associated hits
00692       std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> > trackingParticleQualityPairs =  (useClusterTPAssociation_) 
00693         ? associateTrackByCluster( pSeed->recHits().first,pSeed->recHits().second )
00694         : associateTrack( pSeed->recHits().first,pSeed->recHits().second );
00695       for( std::vector< std::pair<edm::Ref<TrackingParticleCollection>,size_t> >::const_iterator iTrackingParticleQualityPair=trackingParticleQualityPairs.begin();
00696            iTrackingParticleQualityPair!=trackingParticleQualityPairs.end(); ++iTrackingParticleQualityPair )
00697         {
00698           const edm::Ref<TrackingParticleCollection>& trackingParticleRef=iTrackingParticleQualityPair->first;
00699           size_t numberOfSharedHits=iTrackingParticleQualityPair->second;
00700           size_t numberOfValidTrackHits=pSeed->recHits().second-pSeed->recHits().first;
00701           size_t numberOfSimulatedHits=0; // Set a few lines below, but only if required.
00702           
00703           if( numberOfSharedHits==0 ) continue; // No point in continuing if there was no association
00704 
00705           //if electron subtract double counting
00706           if( abs(trackingParticleRef->pdgId())==11 && (trackingParticleRef->g4Track_end() - trackingParticleRef->g4Track_begin()) > 1 )
00707             {
00708               numberOfSharedHits-=getDoubleCount( pSeed->recHits().first, pSeed->recHits().second, trackingParticleRef );
00709             }
00710           
00711           if( simToRecoDenominator_==denomsim || (numberOfSharedHits<3 && threeHitTracksAreSpecial_) ) // the numberOfSimulatedHits is not always required, so can skip counting in some circumstances
00712             {
00713               // Note that in the standard TrackAssociatorByHits, all of the hits in associatedTrackingParticleHits are checked for
00714               // various things.  I'm not sure what these checks are for but they depend on the UseGrouping and UseSplitting settings.
00715               // This associator works as though both UseGrouping and UseSplitting were set to true, i.e. just counts the number of
00716               // hits in the tracker.
00717               numberOfSimulatedHits=trackingParticleRef->numberOfTrackerHits();
00718             }
00719           
00720           double purity=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfValidTrackHits);
00721           double quality;
00722           if( absoluteNumberOfHits_ ) quality=static_cast<double>(numberOfSharedHits);
00723           else if( simToRecoDenominator_==denomsim && numberOfSimulatedHits != 0 ) quality=static_cast<double>(numberOfSharedHits)/static_cast<double>(numberOfSimulatedHits);
00724           else if( simToRecoDenominator_==denomreco && numberOfValidTrackHits != 0 ) quality=purity;
00725           else quality=0;
00726           
00727           if( quality>qualitySimToReco_ && !( threeHitTracksAreSpecial_ && numberOfSimulatedHits==3 && numberOfSharedHits<3 ) && ( absoluteNumberOfHits_ || (purity>puritySimToReco_) ) )
00728             {
00729               returnValue.insert( trackingParticleRef, std::make_pair( edm::RefToBase<TrajectorySeed>(pSeedCollectionHandle_,i) , quality ) );
00730             }
00731         }
00732     }
00733   return returnValue;
00734   
00735   LogTrace("TrackAssociator") << "% of Assoc TPs=" << ((double)returnValue.size())/((double)trackingParticleCollectionHandle->size());
00736   returnValue.post_insert();
00737   return returnValue;
00738 }