CMS 3D CMS Logo

TrimmedVertexFinder.cc

Go to the documentation of this file.
00001 #include "RecoVertex/TrimmedKalmanVertexFinder/interface/TrimmedVertexFinder.h"
00002 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
00003 #include "RecoVertex/VertexTools/interface/PerigeeLinearizedTrackState.h"
00004 #include "FWCore/Utilities/interface/Exception.h"
00005 
00006 using namespace reco;
00007 
00008 TrimmedVertexFinder::TrimmedVertexFinder(
00009   const VertexFitter<5> * vf, const VertexUpdator<5> * vu, 
00010   const VertexTrackCompatibilityEstimator<5> * ve)
00011   : theFitter(vf->clone()), theUpdator(vu->clone()), 
00012     theEstimator(ve->clone()), theMinProb(0.05)
00013 {}
00014 
00015     
00016 TrimmedVertexFinder::TrimmedVertexFinder(
00017 const TrimmedVertexFinder & other) 
00018   : theFitter(other.theFitter->clone()), 
00019   theUpdator(other.theUpdator->clone()), 
00020   theEstimator(other.theEstimator->clone()), 
00021   theMinProb(other.theMinProb)
00022 {}
00023 
00024 
00025 TrimmedVertexFinder::~TrimmedVertexFinder() {
00026   delete theFitter;
00027   delete theUpdator;
00028   delete theEstimator;
00029 }
00030 
00031 
00032 vector<TransientVertex> 
00033 TrimmedVertexFinder::vertices(vector<TransientTrack> & tks) 
00034   const
00035 {
00036   vector<TransientVertex> all;
00037   if (tks.size() < 2) return all;
00038 
00039   // prepare vertex tracks and initial vertex
00040   CachingVertex<5> vtx = theFitter->vertex(tks);
00041   if (!vtx.isValid()) {
00042     cout << "TrimmedVertexFinder::WARNING: initial vertex invalid"
00043          << endl << "vertex finding stops here." << endl;
00044     return all;
00045   }
00046 
00047   vector<RefCountedVertexTrack> selected = vtx.tracks();
00048 
00049   // reject incompatible tracks starting from the worst
00050   vector<RefCountedVertexTrack> remain;
00051   bool found = false;
00052   while (!found && selected.size() >= 2) {
00053 
00054     // find track with worst compatibility
00055     vector<RefCountedVertexTrack>::iterator iWorst = theWorst(vtx, 
00056                                                               selected, 
00057                                                               theMinProb);
00058     
00059     if (iWorst != selected.end()) {
00060       // reject track
00061       remain.push_back(*iWorst);
00062       selected.erase(iWorst);
00063       
00064       if (selected.size() == 1) {
00065         // not enough tracks to build new vertices
00066         remain.push_back(selected.front());
00067       }
00068       else {
00069         // removing track from vertex
00070         // need to redo the vertex fit instead of removing the track;
00071         // successive removals lead to numerical problems
00072         // this is however quick since intermediate quantities are cached
00073         // in the RefCountedVertexTracks
00074         vtx = theFitter->vertex(selected);
00075         if (!vtx.isValid()) {
00076           cout << "TrimmedVertexFinder::WARNING: current vertex invalid"
00077                << endl << "vertex finding stops here." << endl;
00078           return all;
00079         }
00080 
00081         // ref-counted tracks may have changed during the fit
00082         // if the linearization point has moved too much
00083         selected = vtx.tracks();
00084       }
00085       
00086     } else {
00087       // no incompatible track remains, make vertex
00088       found = true;
00089       int n_tracks_in_vertex = selected.size();
00090 
00091       // now return all tracks with weight < 0.5 to 'remain'.
00092       for ( vector< RefCountedVertexTrack >::const_iterator t=selected.begin();
00093           t!=selected.end() ; ++t )
00094       {
00095         if ( (**t).weight() < 0.5 )
00096         {
00097           /*
00098           cout << "[TrimmedVertexFinder] recycling track with weight "
00099                << (**t).weight() << endl;*/
00100           remain.push_back ( *t );
00101           n_tracks_in_vertex--; // one 'good' track less in the vertex
00102         };
00103       };
00104 
00105       if ( n_tracks_in_vertex > 1 ) {
00106         all.push_back(vtx);
00107       }
00108       else {
00109         cout << "[TrimmedVertexFinder] ERROR: found vertex ";
00110         cout << "has less than 2 tracks " << endl;
00111       }
00112     }
00113   }
00114 
00115   // modify list of incompatible tracks
00116   tks.clear();
00117   for (vector<RefCountedVertexTrack>::const_iterator i = remain.begin(); 
00118        i != remain.end(); i++) {
00119     const PerigeeLinearizedTrackState* plts = 
00120       dynamic_cast<const PerigeeLinearizedTrackState*>
00121       ((**i).linearizedTrack().get());
00122     if (plts == 0) {
00123       throw cms::Exception("TrimmedVertexFinder: can't take track from non-perigee track state");
00124     }
00125 
00126     tks.push_back(plts->track());
00127   }
00128 
00129   // return 0 or 1 vertex
00130   return all;
00131 }
00132 
00133 
00134 vector<TrimmedVertexFinder::RefCountedVertexTrack>::iterator 
00135 TrimmedVertexFinder::theWorst(const CachingVertex<5> & vtx, 
00136   vector<RefCountedVertexTrack> & vtxTracks, float cut) const
00137 {
00138 
00139   //  cout << "Cut is now " << cut << endl;
00140 
00141   // find track with worst compatibility
00142   vector<RefCountedVertexTrack>::iterator iWorst = vtxTracks.end();
00143   float worseChi2 = 0.;
00144   for (vector<RefCountedVertexTrack>::iterator itr = vtxTracks.begin();
00145        itr != vtxTracks.end(); itr++) {
00146 
00147     float chi2 = 0;
00148     try {
00149       // remove track from vertex
00150       CachingVertex<5> newV = theUpdator->remove(vtx, *itr);
00151       // compute compatibility
00152       chi2 = theEstimator->estimate(newV, *itr);
00153     }
00154     catch ( cms::Exception & e) {
00155       // problematic track, remove it from vertex
00156       cout << "[TrimmedVertexFinder] warning: "
00157            << "exception caught for this track, causing its rejection:" 
00158            << e.what() << endl;
00159       iWorst = itr;
00160       break;
00161     }
00162 
00163     // compute number of degrees of freedom
00164     if ( chi2 > 0. ) {
00165       // we want to keep negative chi squares, and avoid calling
00166       // ChiSquaredProbability with a negative chi2.
00167       int ndf = 2;
00168       if (vtx.tracks().size() == 2) ndf = 1;
00169 
00170       float prob = ChiSquaredProbability(chi2, ndf);
00171       if (prob < cut && chi2 >= worseChi2) {
00172         // small inconsistency: sorting on chi2, not on chi2 probability
00173         // because large chi2 are not rounded off while small probabilities 
00174         // are rounded off to 0....
00175         // should not matter since at a given iteration 
00176         // all track chi2 increments have the same ndf
00177         iWorst = itr;
00178         worseChi2 = chi2;
00179       }
00180     }
00181   }
00182 
00183   return iWorst;
00184 }

Generated on Tue Jun 9 17:46:12 2009 for CMSSW by  doxygen 1.5.4