CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/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] && isCloseTo(tempDisplacedVertexSeeds[idv_mother], tempDisplacedVertexSeeds[idv_daughter])) {
00214         
00215           tempDisplacedVertexSeeds[idv_mother].mergeWith(tempDisplacedVertexSeeds[idv_daughter]);
00216           bLocked[idv_daughter] = true;
00217           if (debug_) cout << "Seeds " << idv_mother << " and " << idv_daughter << " merged" << endl; 
00218         
00219         }
00220       }
00221     }
00222   }
00223 
00224 }
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 bool
00234 PFDisplacedVertexFinder::fitVertexFromSeed(PFDisplacedVertexSeed& displacedVertexSeed, PFDisplacedVertex& displacedVertex) {
00235 
00236 
00237   if (debug_) cout << "== Start vertexing procedure ==" << endl;
00238 
00239 
00240   // ---- Prepare transient track list ----
00241 
00242   set < TrackBaseRef, PFDisplacedVertexSeed::Compare > tracksToFit = displacedVertexSeed.elements();
00243   GlobalPoint seedPoint = displacedVertexSeed.seedPoint();
00244 
00245   vector<TransientTrack> transTracks;
00246   vector<TransientTrack> transTracksRaw;
00247   vector<TrackBaseRef> transTracksRef;
00248   vector<TrackBaseRef> transTracksRefRaw;
00249 
00250   transTracks.reserve(tracksToFit.size());
00251   transTracksRaw.reserve(tracksToFit.size());
00252   transTracksRef.reserve(tracksToFit.size());
00253   transTracksRefRaw.reserve(tracksToFit.size());
00254 
00255 
00256 
00257   TransientVertex theVertexAdaptiveRaw;
00258   TransientVertex theRecoVertex;
00259 
00260   
00261   // ---- 1) Clean for potentially poor seeds ------- //
00262   // --------------------------------------------- //
00263 
00264   if (tracksToFit.size() < 2) {
00265     if (debug_) cout << "Only one to Fit Track" << endl;
00266     return true;
00267   }
00268 
00269   double rho = sqrt(seedPoint.x()*seedPoint.x()+seedPoint.y()*seedPoint.y());
00270   double z = seedPoint.z();
00271 
00272   if (rho > tobCut_ || fabs(z) > tecCut_) {
00273     if (debug_) cout << "Seed Point out of the tracker rho = " << rho << " z = "<< z << " nTracks = " << tracksToFit.size() << endl;
00274   return true;
00275   }
00276 
00277   if (debug_) displacedVertexSeed.Dump();
00278 
00279   int nStep45 = 0;
00280   int nNotIterative = 0;
00281 
00282   // Fill vectors of TransientTracks and TrackRefs after applying preselection cuts.
00283   for(IEset ie = tracksToFit.begin(); ie !=  tracksToFit.end(); ie++){
00284     TransientTrack tmpTk( *((*ie).get()), magField_, globTkGeomHandle_);
00285     transTracksRaw.push_back( tmpTk );
00286     transTracksRefRaw.push_back( *ie );
00287     if ( (*ie)->algo()-4 > 3 ) nStep45++;
00288     if ( (*ie)->algo()-4 < 0 ||(*ie)->algo()-4 > 5 ) nNotIterative++;
00289   }
00290 
00291   if (rho > 25 && nStep45 + nNotIterative < 1){
00292     if (debug_) cout << "Seed point at rho > 25 cm but no step 4-5 tracks" << endl;
00293     return true;
00294   }
00295 
00296   // ----------------------------------------------- //
00297   // ---- PRESELECT GOOD TRACKS FOR FINAL VERTEX --- //
00298   // ----------------------------------------------- //
00299 
00300 
00301 
00302   // 1)If only two track are found do not prefit
00303 
00304 
00305   if ( transTracksRaw.size() == 2 ){
00306 
00307     if (debug_) cout << "No raw fit done" << endl;
00308 
00309     GlobalError globalError;
00310 
00311     theVertexAdaptiveRaw = TransientVertex(seedPoint,  globalError, transTracksRaw, 1.);
00312 
00313 
00314 
00315   } else {
00316 
00317 
00318 
00319     if (debug_) cout << "Raw fit done." << endl;
00320     
00321     AdaptiveVertexFitter theAdaptiveFitterRaw(GeometricAnnealing(sigmacut_, t_ini_, ratio_),
00322                                               DefaultLinearizationPointFinder(),
00323                                               KalmanVertexUpdator<5>(), 
00324                                               KalmanVertexTrackCompatibilityEstimator<5>(), 
00325                                               KalmanVertexSmoother() );
00326 
00329 
00330   
00331     if ( transTracksRaw.size() < 10 ){
00332 
00333       if (debug_) cout << "First test with KFT" << endl;
00334 
00335       KalmanVertexFitter theKalmanFitter(true);
00336       theVertexAdaptiveRaw = theKalmanFitter.vertex(transTracksRaw, seedPoint);
00337       
00338       if( !theVertexAdaptiveRaw.isValid() || theVertexAdaptiveRaw.totalChiSquared() < 0. ) {
00339         if(debug_) cout << "Prefit failed : valid? " << theVertexAdaptiveRaw.isValid() 
00340                         << " totalChi2 = " << theVertexAdaptiveRaw.totalChiSquared() << endl;
00341         return true;
00342       }
00343 
00344       if (debug_) cout << "We use KFT instead of seed point to set up a point for AVF "
00345                        << " x = " << theVertexAdaptiveRaw.position().x() 
00346                        << " y = " << theVertexAdaptiveRaw.position().y() 
00347                        << " z = " << theVertexAdaptiveRaw.position().z() 
00348                        << endl;
00349 
00350       // To save time: reject the Displaced vertex if it is too close to the beam pipe. 
00351       // Frequently it is very big vertices, with some dosens of tracks
00352 
00353       Vertex vtx =  theVertexAdaptiveRaw;
00354       rho = vtx.position().rho();
00355 
00356       if (rho < primaryVertexCut_) {
00357         if (debug_) cout << "KFT Vertex geometrically rejected with  tracks #rho = " << rho << endl;
00358         return true;
00359       }
00360 
00361 
00362       theVertexAdaptiveRaw = theAdaptiveFitterRaw.vertex(transTracksRaw, theVertexAdaptiveRaw.position());
00363 
00364 
00365     } else {
00366 
00367 
00368       theVertexAdaptiveRaw = theAdaptiveFitterRaw.vertex(transTracksRaw, seedPoint);
00369 
00370     }
00371 
00372     if( !theVertexAdaptiveRaw.isValid() || theVertexAdaptiveRaw.totalChiSquared() < 0. ) {
00373       if(debug_) cout << "Fit failed : valid? " << theVertexAdaptiveRaw.isValid() 
00374                       << " totalChi2 = " << theVertexAdaptiveRaw.totalChiSquared() << endl;
00375       return true;
00376     }  
00377 
00378     // To save time: reject the Displaced vertex if it is too close to the beam pipe. 
00379     // Frequently it is very big vertices, with some dosens of tracks
00380 
00381     Vertex vtx =  theVertexAdaptiveRaw;
00382     rho = vtx.position().rho();
00383 
00384     if (rho < primaryVertexCut_)  {
00385       if (debug_) cout << "Vertex " << " geometrically rejected with " <<  transTracksRaw.size() << " tracks #rho = " << rho << endl;
00386       return true;
00387     }
00388 
00389 
00390   }
00391 
00392 
00393  
00394   // ---- Remove tracks with small weight or 
00395   //      big first (last) hit_to_vertex distance 
00396   //      and then refit                          ---- //
00397   
00398 
00399   
00400   for (unsigned i = 0; i < transTracksRaw.size(); i++) {
00401 
00402     if (debug_) cout << "Raw Weight track " << i << " = " << theVertexAdaptiveRaw.trackWeight(transTracksRaw[i]) << endl;
00403 
00404     if (theVertexAdaptiveRaw.trackWeight(transTracksRaw[i]) > minAdaptWeight_){
00405 
00406       PFTrackHitFullInfo pattern = hitPattern_.analyze(tkerGeomHandle_, transTracksRefRaw[i], theVertexAdaptiveRaw);
00407 
00408       PFDisplacedVertex::VertexTrackType vertexTrackType = getVertexTrackType(pattern);
00409 
00410       if (vertexTrackType != PFDisplacedVertex::T_NOT_FROM_VERTEX){
00411 
00412         bool bGoodTrack = helper_.isTrackSelected(transTracksRaw[i].track(), vertexTrackType);
00413 
00414         if (bGoodTrack){
00415           transTracks.push_back(transTracksRaw[i]);
00416           transTracksRef.push_back(transTracksRefRaw[i]);
00417         } else {
00418           if (debug_)
00419             cout << "Track rejected nChi2 = " << transTracksRaw[i].track().normalizedChi2()
00420                  << " pt = " <<  transTracksRaw[i].track().pt()
00421                  << " dxy (wrt (0,0,0)) = " << transTracksRaw[i].track().dxy()
00422                  << " nHits = " << transTracksRaw[i].track().numberOfValidHits()
00423                  << " nOuterHits = " << transTracksRaw[i].track().trackerExpectedHitsOuter().numberOfHits() << endl;
00424         } 
00425       } else {
00426         
00427         if (debug_){ 
00428           cout << "Remove track because too far away from the vertex:" << endl;
00429         }
00430         
00431       }
00432       
00433     }
00434    
00435   }
00436 
00437 
00438 
00439   if (debug_) cout << "All Tracks " << transTracksRaw.size() 
00440                    << " with good weight " << transTracks.size() << endl;
00441 
00442 
00443   // ---- Refit ---- //
00444   FitterType vtxFitter = F_NOTDEFINED;
00445 
00446   if (transTracks.size() < 2) return true;
00447   else if (transTracks.size() == 2) 
00448     vtxFitter = F_KALMAN;
00449   else if (transTracks.size() > 2 && transTracksRaw.size() > transTracks.size()) 
00450     vtxFitter = F_ADAPTIVE;
00451   else if (transTracks.size() > 2 && transTracksRaw.size() == transTracks.size())  
00452     vtxFitter = F_DONOTREFIT;
00453   else return true;
00454 
00455   if (debug_) cout << "Vertex Fitter " << vtxFitter << endl;
00456 
00457   if(vtxFitter == F_KALMAN){
00458 
00459     KalmanVertexFitter theKalmanFitter(true);
00460     theRecoVertex = theKalmanFitter.vertex(transTracks, seedPoint);
00461 
00462   } else if(vtxFitter == F_ADAPTIVE){
00463 
00464     AdaptiveVertexFitter theAdaptiveFitter( 
00465                                          GeometricAnnealing(sigmacut_, t_ini_, ratio_),
00466                                          DefaultLinearizationPointFinder(),
00467                                          KalmanVertexUpdator<5>(), 
00468                                          KalmanVertexTrackCompatibilityEstimator<5>(), 
00469                                          KalmanVertexSmoother() );
00470 
00471     theRecoVertex = theAdaptiveFitter.vertex(transTracks, seedPoint);
00472 
00473   } else if (vtxFitter == F_DONOTREFIT) {
00474     theRecoVertex = theVertexAdaptiveRaw;
00475   } else {
00476     return true;
00477   }
00478 
00479 
00480   // ---- Check if the fitted vertex is valid ---- //
00481 
00482   if( !theRecoVertex.isValid() || theRecoVertex.totalChiSquared() < 0. ) {
00483     if (debug_) cout << "Refit failed : valid? " << theRecoVertex.isValid() 
00484          << " totalChi2 = " << theRecoVertex.totalChiSquared() << endl;
00485     return true;
00486   }
00487 
00488   // ---- Create vertex ---- //
00489 
00490   Vertex theRecoVtx = theRecoVertex;
00491 
00492   double chi2 = theRecoVtx.chi2();
00493   double ndf =  theRecoVtx.ndof();
00494 
00495     
00496   if (chi2 > TMath::ChisquareQuantile(0.95, ndf)) {
00497     if (debug_) 
00498       cout << "Rejected because of chi2 = " << chi2 << " ndf = " << ndf << " confid. level: " << TMath::ChisquareQuantile(0.95, ndf) << endl;
00499     return true;
00500   }
00501   
00502 
00503 
00504   // ---- Create and fill vector of refitted TransientTracks ---- //
00505 
00506   // -----------------------------------------------//
00507   // ---- Prepare and Fill the Displaced Vertex ----//
00508   // -----------------------------------------------//
00509   
00510 
00511   displacedVertex = (PFDisplacedVertex) theRecoVtx;
00512   displacedVertex.removeTracks();
00513   
00514   for(unsigned i = 0; i < transTracks.size();i++) {
00515     
00516     PFTrackHitFullInfo pattern = hitPattern_.analyze(tkerGeomHandle_, transTracksRef[i], theRecoVertex);
00517 
00518     PFDisplacedVertex::VertexTrackType vertexTrackType = getVertexTrackType(pattern);
00519 
00520     Track refittedTrack;
00521     float weight =  theRecoVertex.trackWeight(transTracks[i]);
00522 
00523 
00524     if (weight < minAdaptWeight_) continue;
00525 
00526     try{
00527       refittedTrack =  theRecoVertex.refittedTrack(transTracks[i]).track();
00528     }catch( cms::Exception& exception ){
00529       continue;
00530     }
00531 
00532     if (debug_){
00533       cout << "Vertex Track Type = " << vertexTrackType << endl;
00534 
00535       cout << "nHitBeforeVertex = " << pattern.first.first 
00536            << " nHitAfterVertex = " << pattern.second.first
00537            << " nMissHitBeforeVertex = " << pattern.first.second
00538            << " nMissHitAfterVertex = " << pattern.second.second
00539            << " Weight = " << weight << endl;
00540     }
00541 
00542     displacedVertex.addElement(transTracksRef[i], 
00543                                refittedTrack, 
00544                                pattern, vertexTrackType, weight);
00545 
00546   }
00547 
00548   displacedVertex.setPrimaryDirection(helper_.primaryVertex());
00549   displacedVertex.calcKinematics();
00550 
00551 
00552   
00553   if (debug_) cout << "== End vertexing procedure ==" << endl;
00554 
00555   return false;
00556 
00557 }
00558 
00559 
00560 
00561 
00562 
00563 
00564 void 
00565 PFDisplacedVertexFinder::selectAndLabelVertices(PFDisplacedVertexCollection& tempDisplacedVertices, vector <bool>& bLocked){
00566 
00567   if (debug_) cout << " 4.1) Reject vertices " << endl;
00568 
00569   for(unsigned idv = 0; idv < tempDisplacedVertices.size(); idv++){
00570 
00571 
00572     // ---- We accept a vertex only if it is not in TOB in the barrel 
00573     //      and not in TEC in the end caps
00574     //      and not too much before the first pixel layer            ---- //
00575 
00576     const float rho =  tempDisplacedVertices[idv].position().rho();
00577     const float z =  tempDisplacedVertices[idv].position().z();
00578         
00579     if (rho > tobCut_ || rho < primaryVertexCut_ || fabs(z) > tecCut_)  {
00580       if (debug_) cout << "Vertex " << idv  
00581                        << " geometrically rejected #rho = " << rho 
00582                        << " z = " << z << endl;
00583          
00584       bLocked[idv] = true;
00585 
00586       continue;
00587     }
00588 
00589     unsigned nPrimary =  tempDisplacedVertices[idv].nPrimaryTracks();
00590     unsigned nMerged =  tempDisplacedVertices[idv].nMergedTracks();
00591     unsigned nSecondary =  tempDisplacedVertices[idv].nSecondaryTracks();      
00592 
00593     if (nPrimary + nMerged > 1) {
00594       bLocked[idv] = true;
00595       if (debug_) cout << "Vertex " << idv
00596                        << " rejected because two primary or merged tracks" << endl;
00597       
00598 
00599     }
00600 
00601     if (nPrimary + nMerged + nSecondary < 2){
00602       bLocked[idv] = true;
00603       if (debug_) cout << "Vertex " << idv
00604                        << " rejected because only one track related to the vertex" << endl;
00605     }
00606 
00607 
00608   }
00609 
00610   
00611   if (debug_) cout << " 4.2) Check for common vertices" << endl;
00612   
00613   // ---- Among the remaining vertex we shall remove one 
00614   //      of those which have two common tracks          ---- //
00615 
00616   for(unsigned idv_mother = 0; idv_mother < tempDisplacedVertices.size(); idv_mother++){
00617     for(unsigned idv_daughter = idv_mother+1; 
00618         idv_daughter < tempDisplacedVertices.size(); idv_daughter++){
00619 
00620       if(!bLocked[idv_daughter] && !bLocked[idv_mother]){
00621 
00622         const unsigned commonTrks = commonTracks(tempDisplacedVertices[idv_daughter], tempDisplacedVertices[idv_mother]);
00623 
00624         if (commonTrks > 1) {
00625 
00626           if (debug_) cout << "Vertices " << idv_daughter << " and " << idv_mother
00627                            << " has many common tracks" << endl;
00628 
00629           // We keep the vertex vertex which contains the most of the tracks
00630 
00631           const int mother_size = tempDisplacedVertices[idv_mother].nTracks();
00632           const int daughter_size = tempDisplacedVertices[idv_daughter].nTracks();
00633           
00634           if (mother_size > daughter_size) bLocked[idv_daughter] = true;
00635           else if (mother_size < daughter_size) bLocked[idv_mother] = true;
00636           else {
00637 
00638             // If they have the same size we keep the vertex with the best normalised chi2
00639 
00640             const float mother_normChi2 = tempDisplacedVertices[idv_mother].normalizedChi2();
00641             const float daughter_normChi2 = tempDisplacedVertices[idv_daughter].normalizedChi2();
00642             if (mother_normChi2 < daughter_normChi2) bLocked[idv_daughter] = true;
00643             else bLocked[idv_mother] = true;
00644           }
00645           
00646         }
00647       }
00648     }
00649   }
00650   
00651   for(unsigned idv = 0; idv < tempDisplacedVertices.size(); idv++)
00652     if ( !bLocked[idv] ) bLocked[idv] = rejectAndLabelVertex(tempDisplacedVertices[idv]);
00653   
00654 
00655 }
00656 
00657 bool
00658 PFDisplacedVertexFinder::rejectAndLabelVertex(PFDisplacedVertex& dv){
00659 
00660   PFDisplacedVertex::VertexType vertexType = helper_.identifyVertex(dv);
00661   dv.setVertexType(vertexType);
00662     
00663   return dv.isFake();
00664 
00665 }
00666 
00667 
00669 
00670 bool 
00671 PFDisplacedVertexFinder::isCloseTo(const PFDisplacedVertexSeed& dv1, const PFDisplacedVertexSeed& dv2) const {
00672 
00673   bool isCloseTo = false;
00674 
00675   const GlobalPoint vP1 = dv1.seedPoint();
00676   const GlobalPoint vP2 = dv2.seedPoint();
00677 
00678   double Delta_Long = getLongDiff(vP1, vP2);
00679   double Delta_Transv = getTransvDiff(vP1, vP2);
00680   if (Delta_Long < longSize_ && Delta_Transv < transvSize_) isCloseTo = true;
00681 
00682   return isCloseTo;
00683 
00684 }
00685 
00686 
00687 double  
00688 PFDisplacedVertexFinder::getLongDiff(const GlobalPoint& Ref, const GlobalPoint& ToProject) const {
00689 
00690   Basic3DVector<double>vRef(Ref);
00691   Basic3DVector<double>vToProject(ToProject);
00692   return fabs((vRef.dot(vToProject)-vRef.mag2())/vRef.mag());
00693 
00694 }
00695 
00696 double  
00697 PFDisplacedVertexFinder::getLongProj(const GlobalPoint& Ref, const GlobalVector& ToProject) const {
00698 
00699   Basic3DVector<double>vRef(Ref);
00700   Basic3DVector<double>vToProject(ToProject);
00701   return (vRef.dot(vToProject))/vRef.mag();
00702 
00703 
00704 }
00705 
00706 
00707 double  
00708 PFDisplacedVertexFinder::getTransvDiff(const GlobalPoint& Ref, const GlobalPoint& ToProject) const {
00709 
00710   Basic3DVector<double>vRef(Ref);
00711   Basic3DVector<double>vToProject(ToProject);
00712   return fabs(vRef.cross(vToProject).mag()/vRef.mag());
00713 
00714 }
00715 
00716 
00717 reco::PFDisplacedVertex::VertexTrackType
00718 PFDisplacedVertexFinder::getVertexTrackType(PFTrackHitFullInfo& pairTrackHitInfo) const {
00719 
00720   unsigned int nHitBeforeVertex = pairTrackHitInfo.first.first;
00721   unsigned int nHitAfterVertex = pairTrackHitInfo.second.first;
00722 
00723   unsigned int nMissHitBeforeVertex = pairTrackHitInfo.first.second;
00724   unsigned int nMissHitAfterVertex = pairTrackHitInfo.second.second;
00725 
00726   // For the moment those definitions are given apriori a more general study would be useful to refine those criteria
00727 
00728   if (nHitBeforeVertex <= 1 && nHitAfterVertex >= 3 && nMissHitAfterVertex <= 1)
00729     return PFDisplacedVertex::T_FROM_VERTEX;
00730   else if (nHitBeforeVertex >= 3 && nHitAfterVertex <= 1 && nMissHitBeforeVertex <= 1)
00731     return PFDisplacedVertex::T_TO_VERTEX;
00732   else if ((nHitBeforeVertex >= 2 && nHitAfterVertex >= 3) 
00733            || 
00734            (nHitBeforeVertex >= 3 && nHitAfterVertex >= 2))
00735     return PFDisplacedVertex::T_MERGED;
00736   else 
00737     return PFDisplacedVertex::T_NOT_FROM_VERTEX;
00738 }
00739 
00740 
00741 unsigned PFDisplacedVertexFinder::commonTracks(const PFDisplacedVertex& v1, const PFDisplacedVertex& v2) const { 
00742 
00743   vector<Track> vt1 = v1.refittedTracks();
00744   vector<Track> vt2 = v2.refittedTracks();
00745 
00746   unsigned commonTracks = 0;
00747 
00748   for ( unsigned il1 = 0; il1 < vt1.size(); il1++){
00749     unsigned il1_idx = v1.originalTrack(vt1[il1]).key();
00750     
00751     for ( unsigned il2 = 0; il2 < vt2.size(); il2++)
00752       if (il1_idx == v2.originalTrack(vt2[il2]).key()) {commonTracks++; break;}
00753     
00754   }
00755 
00756   return commonTracks;
00757 
00758 }
00759 
00760 std::ostream& operator<<(std::ostream& out, const PFDisplacedVertexFinder& a) {
00761 
00762   if(! out) return out;
00763   out << setprecision(3) << setw(5) << endl;
00764   out << "" << endl;
00765   out << " ====================================== " << endl;  
00766   out << " ====== Displaced Vertex Finder ======= " << endl;
00767   out << " ====================================== " << endl;  
00768   out << " " << endl;  
00769 
00770   a.helper_.Dump();
00771   out << "" << endl 
00772       << " Adaptive Vertex Fitter parameters are :"<< endl 
00773       << " sigmacut = " << a.sigmacut_ << " T_ini = " 
00774       << a.t_ini_ << " ratio = " << a.ratio_ << endl << endl; 
00775 
00776   const std::auto_ptr< reco::PFDisplacedVertexCollection >& displacedVertices_
00777     = a.displacedVertices(); 
00778 
00779 
00780   if(!displacedVertices_.get() ) {
00781     out<<"displacedVertex already transfered"<<endl;
00782   }
00783   else{
00784 
00785     out<<"Number of displacedVertices found : "<< displacedVertices_->size()<<endl<<endl;
00786 
00787     int i = -1;
00788 
00789     for(PFDisplacedVertexFinder::IDV idv = displacedVertices_->begin(); 
00790         idv != displacedVertices_->end(); idv++){
00791       i++;
00792       out << i << " "; idv->Dump(); out << "" << endl;
00793     }
00794   }
00795  
00796   return out;
00797 }