CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/src/RecoParticleFlow/PFTracking/src/PFDisplacedVertexFinder.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFTracking/interface/PFDisplacedVertexFinder.h"
00002 
00003 #include "FWCore/Utilities/interface/Exception.h"
00004 
00005 #include "DataFormats/TrackReco/interface/Track.h"
00006 #include "DataFormats/VertexReco/interface/Vertex.h"
00007 
00008 #include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
00009 #include "RecoVertex/AdaptiveVertexFit/interface/AdaptiveVertexFitter.h"
00010 #include "RecoVertex/KalmanVertexFit/interface/KalmanVertexSmoother.h"
00011 
00012 #include "PhysicsTools/RecoAlgos/plugins/KalmanVertexFitter.h"
00013 
00014 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00015 #include "Geometry/CommonDetUnit/interface/TrackingGeometry.h"
00016 
00017 #include "MagneticField/Engine/interface/MagneticField.h"
00018 
00019 #include "TMath.h"
00020 
00021 using namespace std;
00022 using namespace reco;
00023 
00024 //for debug only 
00025 //#define PFLOW_DEBUG
00026 
00027 PFDisplacedVertexFinder::PFDisplacedVertexFinder() : 
00028   displacedVertexCandidates_( new PFDisplacedVertexCandidateCollection ),
00029   displacedVertices_( new PFDisplacedVertexCollection ),
00030   transvSize_(0.0),
00031   longSize_(0.0),
00032   primaryVertexCut_(0.0),
00033   tobCut_(0.0),
00034   tecCut_(0.0),
00035   minAdaptWeight_(2.0),
00036   debug_(false) {}
00037 
00038 
00039 PFDisplacedVertexFinder::~PFDisplacedVertexFinder() {}
00040 
00041 void
00042 PFDisplacedVertexFinder::setInput(
00043                                   const edm::Handle<reco::PFDisplacedVertexCandidateCollection>& displacedVertexCandidates) {
00044 
00045   if( displacedVertexCandidates_.get() ) {
00046     displacedVertexCandidates_->clear();
00047   }
00048   else 
00049     displacedVertexCandidates_.reset( new PFDisplacedVertexCandidateCollection );
00050 
00051 
00052   if(displacedVertexCandidates.isValid()) {
00053     for(unsigned i=0;i<displacedVertexCandidates->size(); i++) {
00054       PFDisplacedVertexCandidateRef dvcref( displacedVertexCandidates, i); 
00055       displacedVertexCandidates_->push_back( (*dvcref));
00056     }
00057   }
00058 
00059 }
00060 
00061 
00062 // -------- Main function which find vertices -------- //
00063 
00064 void
00065 PFDisplacedVertexFinder::findDisplacedVertices() {
00066 
00067   if (debug_) cout << "========= Start Find Displaced Vertices =========" << endl;
00068 
00069   // The vertexCandidates have not been passed to the event
00070   // So they need to be cleared is they are not empty
00071   if( displacedVertices_.get() ) displacedVertices_->clear();
00072   else 
00073     displacedVertices_.reset( new PFDisplacedVertexCollection );
00074 
00075 
00076   // Prepare the collections
00077   PFDisplacedVertexSeedCollection tempDisplacedVertexSeeds;
00078   tempDisplacedVertexSeeds.reserve(4*displacedVertexCandidates_->size());
00079   PFDisplacedVertexCollection tempDisplacedVertices;
00080   tempDisplacedVertices.reserve(4*displacedVertexCandidates_->size());
00081 
00082   if (debug_) 
00083     cout << "1) Parsing displacedVertexCandidates into displacedVertexSeeds" << endl;
00084 
00085   // 1) Parsing displacedVertexCandidates into displacedVertexSeeds which would
00086   // be later used for vertex fitting
00087 
00088   int i = -1;
00089 
00090   for(IDVC idvc = displacedVertexCandidates_->begin(); 
00091       idvc != displacedVertexCandidates_->end(); idvc++) {
00092 
00093     i++;
00094     if (debug_) {
00095       cout << "Analyse Vertex Candidate " << i << endl;
00096     }
00097     
00098     findSeedsFromCandidate(*idvc, tempDisplacedVertexSeeds);
00099     
00100   }     
00101 
00102   if (debug_) cout << "2) Merging Vertex Seeds" << endl;
00103 
00104   // 2) Some displacedVertexSeeds coming from different displacedVertexCandidates
00105   // may be closed enough to be merged together. bLocked is an array which keeps the
00106   // information about the seeds which are desabled.
00107   vector<bool> bLockedSeeds; 
00108   bLockedSeeds.resize(tempDisplacedVertexSeeds.size());
00109   mergeSeeds(tempDisplacedVertexSeeds, bLockedSeeds);
00110   
00111   if (debug_) cout << "3) Fitting Vertices From Seeds" << endl;
00112 
00113   // 3) Fit displacedVertices from displacedVertexSeeds
00114   for(unsigned idv = 0; idv < tempDisplacedVertexSeeds.size(); idv++){ 
00115     
00116     if (!tempDisplacedVertexSeeds[idv].isEmpty() && !bLockedSeeds[idv]) {
00117       PFDisplacedVertex displacedVertex;  
00118       bLockedSeeds[idv] = fitVertexFromSeed(tempDisplacedVertexSeeds[idv], displacedVertex);
00119       if (!bLockedSeeds[idv])  tempDisplacedVertices.push_back(displacedVertex);
00120     }
00121   }
00122 
00123   if (debug_) cout << "4) Rejecting Bad Vertices and label them" << endl;
00124   
00125   // 4) Reject displaced vertices which may be considered as fakes
00126   vector<bool> bLocked; 
00127   bLocked.resize(tempDisplacedVertices.size());
00128   selectAndLabelVertices(tempDisplacedVertices, bLocked);
00129   
00130   if (debug_) cout << "5) Fill the Displaced Vertices" << endl;
00131 
00132   // 5) Fill the displacedVertex_ which would be transfered to the producer
00133   displacedVertices_->reserve(tempDisplacedVertices.size());
00134 
00135   for(unsigned idv = 0; idv < tempDisplacedVertices.size(); idv++)
00136     if (!bLocked[idv]) displacedVertices_->push_back(tempDisplacedVertices[idv]);
00137 
00138   if (debug_) cout << "========= End Find Displaced Vertices =========" << endl;
00139 
00140 
00141 }
00142 
00143 // -------- Different steps of the finder algorithm -------- //
00144 
00145 
00146 void 
00147 PFDisplacedVertexFinder::findSeedsFromCandidate(PFDisplacedVertexCandidate& vertexCandidate, PFDisplacedVertexSeedCollection& tempDisplacedVertexSeeds){
00148   
00149   const PFDisplacedVertexCandidate::DistMap r2Map = vertexCandidate.r2Map();
00150   bool bNeedNewCandidate = false;
00151 
00152   tempDisplacedVertexSeeds.push_back( PFDisplacedVertexSeed() );
00153 
00154   IDVS idvc_current;
00155 
00156   for (PFDisplacedVertexCandidate::DistMap::const_iterator imap = r2Map.begin();
00157        imap != r2Map.end(); imap++){
00158 
00159     unsigned ie1 = (*imap).second.first;
00160     unsigned ie2 = (*imap).second.second;
00161 
00162     if (debug_) cout << "ie1 = " << ie1 << " ie2 = " << ie2 << " radius = " << sqrt((*imap).first) << endl; 
00163 
00164     GlobalPoint dcaPoint = vertexCandidate.dcaPoint(ie1, ie2);
00165     if (fabs(dcaPoint.x()) > 1e9) continue;
00166 
00167     bNeedNewCandidate = true;
00168     for (idvc_current = tempDisplacedVertexSeeds.begin(); idvc_current != tempDisplacedVertexSeeds.end(); idvc_current++){
00169       if ((*idvc_current).isEmpty()) {
00170         bNeedNewCandidate = false;
00171         break;
00172       }
00173       const GlobalPoint vertexPoint = (*idvc_current).seedPoint();
00174       double Delta_Long = getLongDiff(vertexPoint, dcaPoint);
00175       double Delta_Transv = getTransvDiff(vertexPoint, dcaPoint);
00176       if (Delta_Long > longSize_) continue;
00177       if (Delta_Transv > transvSize_) continue;
00178       bNeedNewCandidate = false;
00179       break;
00180     }
00181     if (bNeedNewCandidate) {    
00182       if (debug_) cout << "create new displaced vertex" << endl;
00183       tempDisplacedVertexSeeds.push_back( PFDisplacedVertexSeed() );      
00184       idvc_current = tempDisplacedVertexSeeds.end();
00185       idvc_current--;
00186       bNeedNewCandidate = false;
00187     }
00188 
00189 
00190     
00191     (*idvc_current).updateSeedPoint(dcaPoint, vertexCandidate.tref(ie1), vertexCandidate.tref(ie2));
00192 
00193 
00194 
00195   }
00196 
00197 
00198 }
00199 
00200 
00201 
00202 
00203 void 
00204 PFDisplacedVertexFinder::mergeSeeds(PFDisplacedVertexSeedCollection& tempDisplacedVertexSeeds, vector<bool>& bLocked){
00205 
00206   // loop over displaced vertex candidates 
00207   // and merge them if they are close to each other
00208   for(unsigned idv_mother = 0;idv_mother < tempDisplacedVertexSeeds.size(); idv_mother++){
00209     if (!bLocked[idv_mother]){
00210 
00211       for (unsigned idv_daughter = idv_mother+1;idv_daughter < tempDisplacedVertexSeeds.size(); idv_daughter++){
00212         
00213         if (!bLocked[idv_daughter]){
00214           if (isCloseTo(tempDisplacedVertexSeeds[idv_mother], tempDisplacedVertexSeeds[idv_daughter])) {
00215         
00216             tempDisplacedVertexSeeds[idv_mother].mergeWith(tempDisplacedVertexSeeds[idv_daughter]);
00217             bLocked[idv_daughter] = true;
00218             if (debug_) cout << "Seeds " << idv_mother << " and " << idv_daughter << " merged" << endl; 
00219           }
00220         }
00221       }
00222     }
00223   }
00224 
00225 }
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 bool
00235 PFDisplacedVertexFinder::fitVertexFromSeed(PFDisplacedVertexSeed& displacedVertexSeed, PFDisplacedVertex& displacedVertex) {
00236 
00237 
00238   if (debug_) cout << "== Start vertexing procedure ==" << endl;
00239 
00240 
00241   // ---- Prepare transient track list ----
00242 
00243   set < TrackBaseRef, PFDisplacedVertexSeed::Compare > tracksToFit = displacedVertexSeed.elements();
00244   GlobalPoint seedPoint = displacedVertexSeed.seedPoint();
00245 
00246   vector<TransientTrack> transTracks;
00247   vector<TransientTrack> transTracksRaw;
00248   vector<TrackBaseRef> transTracksRef;
00249   vector<TrackBaseRef> transTracksRefRaw;
00250 
00251   transTracks.reserve(tracksToFit.size());
00252   transTracksRaw.reserve(tracksToFit.size());
00253   transTracksRef.reserve(tracksToFit.size());
00254   transTracksRefRaw.reserve(tracksToFit.size());
00255 
00256 
00257 
00258   TransientVertex theVertexAdaptiveRaw;
00259   TransientVertex theRecoVertex;
00260 
00261   
00262   // ---- 1) Clean for potentially poor seeds ------- //
00263   // --------------------------------------------- //
00264 
00265   if (tracksToFit.size() < 2) {
00266     if (debug_) cout << "Only one to Fit Track" << endl;
00267     return true;
00268   }
00269 
00270   double rho = sqrt(seedPoint.x()*seedPoint.x()+seedPoint.y()*seedPoint.y());
00271   double z = seedPoint.z();
00272 
00273   if (rho > tobCut_ || fabs(z) > tecCut_) {
00274     if (debug_) cout << "Seed Point out of the tracker rho = " << rho << " z = "<< z << " nTracks = " << tracksToFit.size() << endl;
00275   return true;
00276   }
00277 
00278   if (debug_) displacedVertexSeed.Dump();
00279 
00280   int nStep45 = 0;
00281   int nNotIterative = 0;
00282 
00283   // Fill vectors of TransientTracks and TrackRefs after applying preselection cuts.
00284   for(IEset ie = tracksToFit.begin(); ie !=  tracksToFit.end(); ie++){
00285     TransientTrack tmpTk( *((*ie).get()), magField_, globTkGeomHandle_);
00286     transTracksRaw.push_back( tmpTk );
00287     transTracksRefRaw.push_back( *ie );
00288     if ( (*ie)->algo()-4 > 3 ) nStep45++;
00289     if ( (*ie)->algo()-4 < 0 ||(*ie)->algo()-4 > 5 ) nNotIterative++;
00290   }
00291 
00292   if (rho > 25 && nStep45 + nNotIterative < 1){
00293     if (debug_) cout << "Seed point at rho > 25 cm but no step 4-5 tracks" << endl;
00294     return true;
00295   }
00296 
00297   // ----------------------------------------------- //
00298   // ---- PRESELECT GOOD TRACKS FOR FINAL VERTEX --- //
00299   // ----------------------------------------------- //
00300 
00301 
00302 
00303   // 1)If only two track are found do not prefit
00304 
00305 
00306   if ( transTracksRaw.size() == 2 ){
00307 
00308     if (debug_) cout << "No raw fit done" << endl;
00309     if (switchOff2TrackVertex_) {
00310       if (debug_) 
00311         cout << "Due to probably high pile-up conditions 2 track vertices switched off" << endl;
00312       return true;
00313 
00314     }
00315     GlobalError globalError;
00316 
00317     theVertexAdaptiveRaw = TransientVertex(seedPoint,  globalError, transTracksRaw, 1.);
00318 
00319 
00320 
00321   } else {
00322 
00323 
00324 
00325     if (debug_) cout << "Raw fit done." << endl;
00326     
00327     AdaptiveVertexFitter theAdaptiveFitterRaw(GeometricAnnealing(sigmacut_, t_ini_, ratio_),
00328                                               DefaultLinearizationPointFinder(),
00329                                               KalmanVertexUpdator<5>(), 
00330                                               KalmanVertexTrackCompatibilityEstimator<5>(), 
00331                                               KalmanVertexSmoother() );
00332 
00335 
00336   
00337     if ( transTracksRaw.size() < 1000 && transTracksRaw.size() > 3){
00338 
00339       if (debug_) cout << "First test with KFT" << endl;
00340 
00341       KalmanVertexFitter theKalmanFitter(true);
00342       theVertexAdaptiveRaw = theKalmanFitter.vertex(transTracksRaw, seedPoint);
00343       
00344       if( !theVertexAdaptiveRaw.isValid() || theVertexAdaptiveRaw.totalChiSquared() < 0. ) {
00345         if(debug_) cout << "Prefit failed : valid? " << theVertexAdaptiveRaw.isValid() 
00346                         << " totalChi2 = " << theVertexAdaptiveRaw.totalChiSquared() << endl;
00347         return true;
00348       }
00349 
00350       if (debug_) cout << "We use KFT instead of seed point to set up a point for AVF "
00351                        << " x = " << theVertexAdaptiveRaw.position().x() 
00352                        << " y = " << theVertexAdaptiveRaw.position().y() 
00353                        << " z = " << theVertexAdaptiveRaw.position().z() 
00354                        << endl;
00355 
00356       // To save time: reject the Displaced vertex if it is too close to the beam pipe. 
00357       // Frequently it is very big vertices, with some dosens of tracks
00358 
00359       Vertex vtx =  theVertexAdaptiveRaw;
00360       rho = vtx.position().rho();
00361 
00362       //   cout << "primary vertex cut  = " << primaryVertexCut_ << endl;
00363 
00364       if (rho < primaryVertexCut_ || rho > 100) {
00365         if (debug_) cout << "KFT Vertex geometrically rejected with  tracks #rho = " << rho << endl;
00366         return true;
00367       }
00368 
00369       //     cout << "primary vertex cut  = " << primaryVertexCut_ << " rho = " << rho << endl;
00370 
00371       theVertexAdaptiveRaw = theAdaptiveFitterRaw.vertex(transTracksRaw, theVertexAdaptiveRaw.position());
00372 
00373 
00374     } else {
00375 
00376 
00377       theVertexAdaptiveRaw = theAdaptiveFitterRaw.vertex(transTracksRaw, seedPoint);
00378 
00379     }
00380 
00381     if( !theVertexAdaptiveRaw.isValid() || theVertexAdaptiveRaw.totalChiSquared() < 0. ) {
00382       if(debug_) cout << "Fit failed : valid? " << theVertexAdaptiveRaw.isValid() 
00383                       << " totalChi2 = " << theVertexAdaptiveRaw.totalChiSquared() << endl;
00384       return true;
00385     }  
00386 
00387     // To save time: reject the Displaced vertex if it is too close to the beam pipe. 
00388     // Frequently it is very big vertices, with some dosens of tracks
00389 
00390     Vertex vtx =  theVertexAdaptiveRaw;
00391     rho = vtx.position().rho();
00392 
00393     if (rho < primaryVertexCut_)  {
00394       if (debug_) cout << "Vertex " << " geometrically rejected with " <<  transTracksRaw.size() << " tracks #rho = " << rho << endl;
00395       return true;
00396     }
00397 
00398 
00399   }
00400 
00401 
00402  
00403   // ---- Remove tracks with small weight or 
00404   //      big first (last) hit_to_vertex distance 
00405   //      and then refit                          ---- //
00406   
00407 
00408   
00409   for (unsigned i = 0; i < transTracksRaw.size(); i++) {
00410 
00411     if (debug_) cout << "Raw Weight track " << i << " = " << theVertexAdaptiveRaw.trackWeight(transTracksRaw[i]) << endl;
00412 
00413     if (theVertexAdaptiveRaw.trackWeight(transTracksRaw[i]) > minAdaptWeight_){
00414 
00415       PFTrackHitFullInfo pattern = hitPattern_.analyze(tkerGeomHandle_, transTracksRefRaw[i], theVertexAdaptiveRaw);
00416 
00417       PFDisplacedVertex::VertexTrackType vertexTrackType = getVertexTrackType(pattern);
00418 
00419       if (vertexTrackType != PFDisplacedVertex::T_NOT_FROM_VERTEX){
00420 
00421         bool bGoodTrack = helper_.isTrackSelected(transTracksRaw[i].track(), vertexTrackType);
00422 
00423         if (bGoodTrack){
00424           transTracks.push_back(transTracksRaw[i]);
00425           transTracksRef.push_back(transTracksRefRaw[i]);
00426         } else {
00427           if (debug_)
00428             cout << "Track rejected nChi2 = " << transTracksRaw[i].track().normalizedChi2()
00429                  << " pt = " <<  transTracksRaw[i].track().pt()
00430                  << " dxy (wrt (0,0,0)) = " << transTracksRaw[i].track().dxy()
00431                  << " nHits = " << transTracksRaw[i].track().numberOfValidHits()
00432                  << " nOuterHits = " << transTracksRaw[i].track().trackerExpectedHitsOuter().numberOfHits() << endl;
00433         } 
00434       } else {
00435         
00436         if (debug_){ 
00437           cout << "Remove track because too far away from the vertex:" << endl;
00438         }
00439         
00440       }
00441       
00442     }
00443    
00444   }
00445 
00446 
00447 
00448   if (debug_) cout << "All Tracks " << transTracksRaw.size() 
00449                    << " with good weight " << transTracks.size() << endl;
00450 
00451 
00452   // ---- Refit ---- //
00453   FitterType vtxFitter = F_NOTDEFINED;
00454 
00455   if (transTracks.size() < 2) return true;
00456   else if (transTracks.size() == 2){
00457     
00458     if (switchOff2TrackVertex_) {
00459       if (debug_) 
00460         cout << "Due to probably high pile-up conditions 2 track vertices switched off" << endl;
00461       return true;
00462     }
00463     vtxFitter = F_KALMAN;
00464   }
00465   else if (transTracks.size() > 2 && transTracksRaw.size() > transTracks.size()) 
00466     vtxFitter = F_ADAPTIVE;
00467   else if (transTracks.size() > 2 && transTracksRaw.size() == transTracks.size())  
00468     vtxFitter = F_DONOTREFIT;
00469   else return true;
00470 
00471   if (debug_) cout << "Vertex Fitter " << vtxFitter << endl;
00472 
00473   if(vtxFitter == F_KALMAN){
00474 
00475     KalmanVertexFitter theKalmanFitter(true);
00476     theRecoVertex = theKalmanFitter.vertex(transTracks, seedPoint);
00477 
00478   } else if(vtxFitter == F_ADAPTIVE){
00479 
00480     AdaptiveVertexFitter theAdaptiveFitter( 
00481                                          GeometricAnnealing(sigmacut_, t_ini_, ratio_),
00482                                          DefaultLinearizationPointFinder(),
00483                                          KalmanVertexUpdator<5>(), 
00484                                          KalmanVertexTrackCompatibilityEstimator<5>(), 
00485                                          KalmanVertexSmoother() );
00486 
00487     theRecoVertex = theAdaptiveFitter.vertex(transTracks, seedPoint);
00488 
00489   } else if (vtxFitter == F_DONOTREFIT) {
00490     theRecoVertex = theVertexAdaptiveRaw;
00491   } else {
00492     return true;
00493   }
00494 
00495 
00496   // ---- Check if the fitted vertex is valid ---- //
00497 
00498   if( !theRecoVertex.isValid() || theRecoVertex.totalChiSquared() < 0. ) {
00499     if (debug_) cout << "Refit failed : valid? " << theRecoVertex.isValid() 
00500          << " totalChi2 = " << theRecoVertex.totalChiSquared() << endl;
00501     return true;
00502   }
00503 
00504   // ---- Create vertex ---- //
00505 
00506   Vertex theRecoVtx = theRecoVertex;
00507 
00508   double chi2 = theRecoVtx.chi2();
00509   double ndf =  theRecoVtx.ndof();
00510 
00511     
00512   if (chi2 > TMath::ChisquareQuantile(0.95, ndf)) {
00513     if (debug_) 
00514       cout << "Rejected because of chi2 = " << chi2 << " ndf = " << ndf << " confid. level: " << TMath::ChisquareQuantile(0.95, ndf) << endl;
00515     return true;
00516   }
00517   
00518 
00519 
00520   // ---- Create and fill vector of refitted TransientTracks ---- //
00521 
00522   // -----------------------------------------------//
00523   // ---- Prepare and Fill the Displaced Vertex ----//
00524   // -----------------------------------------------//
00525   
00526 
00527   displacedVertex = (PFDisplacedVertex) theRecoVtx;
00528   displacedVertex.removeTracks();
00529   
00530   for(unsigned i = 0; i < transTracks.size();i++) {
00531     
00532     PFTrackHitFullInfo pattern = hitPattern_.analyze(tkerGeomHandle_, transTracksRef[i], theRecoVertex);
00533 
00534     PFDisplacedVertex::VertexTrackType vertexTrackType = getVertexTrackType(pattern);
00535 
00536     Track refittedTrack;
00537     float weight =  theRecoVertex.trackWeight(transTracks[i]);
00538 
00539 
00540     if (weight < minAdaptWeight_) continue;
00541 
00542     try{
00543       refittedTrack =  theRecoVertex.refittedTrack(transTracks[i]).track();
00544     }catch( cms::Exception& exception ){
00545       continue;
00546     }
00547 
00548     if (debug_){
00549       cout << "Vertex Track Type = " << vertexTrackType << endl;
00550 
00551       cout << "nHitBeforeVertex = " << pattern.first.first 
00552            << " nHitAfterVertex = " << pattern.second.first
00553            << " nMissHitBeforeVertex = " << pattern.first.second
00554            << " nMissHitAfterVertex = " << pattern.second.second
00555            << " Weight = " << weight << endl;
00556     }
00557 
00558     displacedVertex.addElement(transTracksRef[i], 
00559                                refittedTrack, 
00560                                pattern, vertexTrackType, weight);
00561 
00562   }
00563 
00564   displacedVertex.setPrimaryDirection(helper_.primaryVertex());
00565   displacedVertex.calcKinematics();
00566 
00567 
00568   
00569   if (debug_) cout << "== End vertexing procedure ==" << endl;
00570 
00571   return false;
00572 
00573 }
00574 
00575 
00576 
00577 
00578 
00579 
00580 void 
00581 PFDisplacedVertexFinder::selectAndLabelVertices(PFDisplacedVertexCollection& tempDisplacedVertices, vector <bool>& bLocked){
00582 
00583   if (debug_) cout << " 4.1) Reject vertices " << endl;
00584 
00585   for(unsigned idv = 0; idv < tempDisplacedVertices.size(); idv++){
00586 
00587 
00588     // ---- We accept a vertex only if it is not in TOB in the barrel 
00589     //      and not in TEC in the end caps
00590     //      and not too much before the first pixel layer            ---- //
00591 
00592     const float rho =  tempDisplacedVertices[idv].position().rho();
00593     const float z =  tempDisplacedVertices[idv].position().z();
00594         
00595     if (rho > tobCut_ || rho < primaryVertexCut_ || fabs(z) > tecCut_)  {
00596       if (debug_) cout << "Vertex " << idv  
00597                        << " geometrically rejected #rho = " << rho 
00598                        << " z = " << z << endl;
00599          
00600       bLocked[idv] = true;
00601 
00602       continue;
00603     }
00604 
00605     unsigned nPrimary =  tempDisplacedVertices[idv].nPrimaryTracks();
00606     unsigned nMerged =  tempDisplacedVertices[idv].nMergedTracks();
00607     unsigned nSecondary =  tempDisplacedVertices[idv].nSecondaryTracks();      
00608 
00609     if (nPrimary + nMerged > 1) {
00610       bLocked[idv] = true;
00611       if (debug_) cout << "Vertex " << idv
00612                        << " rejected because two primary or merged tracks" << endl;
00613       
00614 
00615     }
00616 
00617     if (nPrimary + nMerged + nSecondary < 2){
00618       bLocked[idv] = true;
00619       if (debug_) cout << "Vertex " << idv
00620                        << " rejected because only one track related to the vertex" << endl;
00621     }
00622 
00623 
00624   }
00625 
00626   
00627   if (debug_) cout << " 4.2) Check for common vertices" << endl;
00628   
00629   // ---- Among the remaining vertex we shall remove one 
00630   //      of those which have two common tracks          ---- //
00631 
00632   for(unsigned idv_mother = 0; idv_mother < tempDisplacedVertices.size(); idv_mother++){
00633     for(unsigned idv_daughter = idv_mother+1; 
00634         idv_daughter < tempDisplacedVertices.size(); idv_daughter++){
00635 
00636       if(!bLocked[idv_daughter] && !bLocked[idv_mother]){
00637 
00638         const unsigned commonTrks = commonTracks(tempDisplacedVertices[idv_daughter], tempDisplacedVertices[idv_mother]);
00639 
00640         if (commonTrks > 1) {
00641 
00642           if (debug_) cout << "Vertices " << idv_daughter << " and " << idv_mother
00643                            << " has many common tracks" << endl;
00644 
00645           // We keep the vertex vertex which contains the most of the tracks
00646 
00647           const int mother_size = tempDisplacedVertices[idv_mother].nTracks();
00648           const int daughter_size = tempDisplacedVertices[idv_daughter].nTracks();
00649           
00650           if (mother_size > daughter_size) bLocked[idv_daughter] = true;
00651           else if (mother_size < daughter_size) bLocked[idv_mother] = true;
00652           else {
00653 
00654             // If they have the same size we keep the vertex with the best normalised chi2
00655 
00656             const float mother_normChi2 = tempDisplacedVertices[idv_mother].normalizedChi2();
00657             const float daughter_normChi2 = tempDisplacedVertices[idv_daughter].normalizedChi2();
00658             if (mother_normChi2 < daughter_normChi2) bLocked[idv_daughter] = true;
00659             else bLocked[idv_mother] = true;
00660           }
00661           
00662         }
00663       }
00664     }
00665   }
00666   
00667   for(unsigned idv = 0; idv < tempDisplacedVertices.size(); idv++)
00668     if ( !bLocked[idv] ) bLocked[idv] = rejectAndLabelVertex(tempDisplacedVertices[idv]);
00669   
00670 
00671 }
00672 
00673 bool
00674 PFDisplacedVertexFinder::rejectAndLabelVertex(PFDisplacedVertex& dv){
00675 
00676   PFDisplacedVertex::VertexType vertexType = helper_.identifyVertex(dv);
00677   dv.setVertexType(vertexType);
00678     
00679   return dv.isFake();
00680 
00681 }
00682 
00683 
00685 
00686 bool 
00687 PFDisplacedVertexFinder::isCloseTo(const PFDisplacedVertexSeed& dv1, const PFDisplacedVertexSeed& dv2) const {
00688 
00689   const GlobalPoint vP1 = dv1.seedPoint();
00690   const GlobalPoint vP2 = dv2.seedPoint();
00691 
00692   double Delta_Long = getLongDiff(vP1, vP2);
00693   if (Delta_Long > longSize_) return false;
00694   double Delta_Transv = getTransvDiff(vP1, vP2);
00695   if (Delta_Transv > transvSize_) return false;
00696   //  if (Delta_Long < longSize_ && Delta_Transv < transvSize_) isCloseTo = true;
00697 
00698   return true;
00699 
00700 }
00701 
00702 
00703 double  
00704 PFDisplacedVertexFinder::getLongDiff(const GlobalPoint& Ref, const GlobalPoint& ToProject) const {
00705 
00706   Basic3DVector<double>vRef(Ref);
00707   Basic3DVector<double>vToProject(ToProject);
00708   return fabs((vRef.dot(vToProject)-vRef.mag2())/vRef.mag());
00709 
00710 }
00711 
00712 double  
00713 PFDisplacedVertexFinder::getLongProj(const GlobalPoint& Ref, const GlobalVector& ToProject) const {
00714 
00715   Basic3DVector<double>vRef(Ref);
00716   Basic3DVector<double>vToProject(ToProject);
00717   return (vRef.dot(vToProject))/vRef.mag();
00718 
00719 
00720 }
00721 
00722 
00723 double  
00724 PFDisplacedVertexFinder::getTransvDiff(const GlobalPoint& Ref, const GlobalPoint& ToProject) const {
00725 
00726   Basic3DVector<double>vRef(Ref);
00727   Basic3DVector<double>vToProject(ToProject);
00728   return fabs(vRef.cross(vToProject).mag()/vRef.mag());
00729 
00730 }
00731 
00732 
00733 reco::PFDisplacedVertex::VertexTrackType
00734 PFDisplacedVertexFinder::getVertexTrackType(PFTrackHitFullInfo& pairTrackHitInfo) const {
00735 
00736   unsigned int nHitBeforeVertex = pairTrackHitInfo.first.first;
00737   unsigned int nHitAfterVertex = pairTrackHitInfo.second.first;
00738 
00739   unsigned int nMissHitBeforeVertex = pairTrackHitInfo.first.second;
00740   unsigned int nMissHitAfterVertex = pairTrackHitInfo.second.second;
00741 
00742   // For the moment those definitions are given apriori a more general study would be useful to refine those criteria
00743 
00744   if (nHitBeforeVertex <= 1 && nHitAfterVertex >= 3 && nMissHitAfterVertex <= 1)
00745     return PFDisplacedVertex::T_FROM_VERTEX;
00746   else if (nHitBeforeVertex >= 3 && nHitAfterVertex <= 1 && nMissHitBeforeVertex <= 1)
00747     return PFDisplacedVertex::T_TO_VERTEX;
00748   else if ((nHitBeforeVertex >= 2 && nHitAfterVertex >= 3) 
00749            || 
00750            (nHitBeforeVertex >= 3 && nHitAfterVertex >= 2))
00751     return PFDisplacedVertex::T_MERGED;
00752   else 
00753     return PFDisplacedVertex::T_NOT_FROM_VERTEX;
00754 }
00755 
00756 
00757 unsigned PFDisplacedVertexFinder::commonTracks(const PFDisplacedVertex& v1, const PFDisplacedVertex& v2) const { 
00758 
00759   vector<Track> vt1 = v1.refittedTracks();
00760   vector<Track> vt2 = v2.refittedTracks();
00761 
00762   unsigned commonTracks = 0;
00763 
00764   for ( unsigned il1 = 0; il1 < vt1.size(); il1++){
00765     unsigned il1_idx = v1.originalTrack(vt1[il1]).key();
00766     
00767     for ( unsigned il2 = 0; il2 < vt2.size(); il2++)
00768       if (il1_idx == v2.originalTrack(vt2[il2]).key()) {commonTracks++; break;}
00769     
00770   }
00771 
00772   return commonTracks;
00773 
00774 }
00775 
00776 std::ostream& operator<<(std::ostream& out, const PFDisplacedVertexFinder& a) {
00777 
00778   if(! out) return out;
00779   out << setprecision(3) << setw(5) << endl;
00780   out << "" << endl;
00781   out << " ====================================== " << endl;  
00782   out << " ====== Displaced Vertex Finder ======= " << endl;
00783   out << " ====================================== " << endl;  
00784   out << " " << endl;  
00785 
00786   a.helper_.Dump();
00787   out << "" << endl 
00788       << " Adaptive Vertex Fitter parameters are :"<< endl 
00789       << " sigmacut = " << a.sigmacut_ << " T_ini = " 
00790       << a.t_ini_ << " ratio = " << a.ratio_ << endl << endl; 
00791 
00792   const std::auto_ptr< reco::PFDisplacedVertexCollection >& displacedVertices_
00793     = a.displacedVertices(); 
00794 
00795 
00796   if(!displacedVertices_.get() ) {
00797     out<<"displacedVertex already transfered"<<endl;
00798   }
00799   else{
00800 
00801     out<<"Number of displacedVertices found : "<< displacedVertices_->size()<<endl<<endl;
00802 
00803     int i = -1;
00804 
00805     for(PFDisplacedVertexFinder::IDV idv = displacedVertices_->begin(); 
00806         idv != displacedVertices_->end(); idv++){
00807       i++;
00808       out << i << " "; idv->Dump(); out << "" << endl;
00809     }
00810   }
00811  
00812   return out;
00813 }