CMS 3D CMS Logo

AdaptiveVertexFitter.cc

Go to the documentation of this file.
00001 #include "RecoVertex/AdaptiveVertexFit/interface/AdaptiveVertexFitter.h"
00002 #include "DataFormats/GeometryCommonDetAlgo/interface/GlobalError.h"
00003 #include "RecoVertex/VertexTools/interface/AnnealingSchedule.h"
00004 #include "RecoVertex/VertexTools/interface/GeometricAnnealing.h"
00005 #include "RecoVertex/VertexTools/interface/VertexTrackFactory.h"
00006 #include "RecoVertex/AdaptiveVertexFit/interface/KalmanChiSquare.h"
00007 #include "RecoVertex/VertexPrimitives/interface/VertexException.h"
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 
00010 #include <algorithm>
00011 
00012 using namespace edm;
00013 
00014 // #define STORE_WEIGHTS
00015 #ifdef STORE_WEIGHTS
00016 #include <dataharvester/Writer.h>
00017 #endif
00018 
00019 using namespace std;
00020 
00021 namespace {
00022   static const float initialError = 10000;
00023 
00024   #ifdef STORE_WEIGHTS
00025   map < RefCountedLinearizedTrackState, int > ids;
00026   int iter=0;
00027 
00028   int getId ( const RefCountedLinearizedTrackState & r )
00029   {
00030     static int ctr=1;
00031     if ( ids.count(r) == 0 )
00032     {
00033       ids[r]=ctr++;
00034     }
00035     return ids[r];
00036   }
00037   #endif
00038 }
00039 
00040 AdaptiveVertexFitter::AdaptiveVertexFitter(
00041       const AnnealingSchedule & ann,
00042       const LinearizationPointFinder & linP,
00043       const VertexUpdator<5> & updator,
00044       const VertexTrackCompatibilityEstimator<5> & crit,
00045       const VertexSmoother<5> & smoother,
00046       const AbstractLTSFactory<5> & ltsf ) :
00047     theNr(0),
00048     theLinP(linP.clone()), theUpdator( updator.clone()),
00049     theSmoother ( smoother.clone() ), theAssProbComputer( ann.clone() ),
00050     theComp ( crit.clone() ), theLinTrkFactory ( ltsf.clone() )
00051 {
00052   setParameters();
00053 }
00054 
00055 void AdaptiveVertexFitter::setWeightThreshold ( float w )
00056 {
00057   theWeightThreshold=w;
00058 }
00059 
00060 AdaptiveVertexFitter::AdaptiveVertexFitter
00061                         (const AdaptiveVertexFitter & o ) :
00062     theMaxShift ( o.theMaxShift ), theMaxLPShift ( o.theMaxLPShift ),
00063     theMaxStep ( o.theMaxStep ), theWeightThreshold ( o.theWeightThreshold ),
00064     theNr ( o.theNr ),
00065     theLinP ( o.theLinP->clone() ), theUpdator ( o.theUpdator->clone() ),
00066     theSmoother ( o.theSmoother->clone() ),
00067     theAssProbComputer ( o.theAssProbComputer->clone() ),
00068     theComp ( o.theComp->clone() ),
00069     theLinTrkFactory ( o.theLinTrkFactory->clone() )
00070 {}
00071 
00072 AdaptiveVertexFitter::~AdaptiveVertexFitter()
00073 {
00074   delete theLinP;
00075   delete theUpdator;
00076   delete theSmoother;
00077   delete theAssProbComputer;
00078   delete theComp;
00079   delete theLinTrkFactory;
00080 }
00081 
00082 void AdaptiveVertexFitter::setParameters( double maxshift, double maxlpshift, 
00083                                           unsigned maxstep, double weightthreshold )
00084 {
00085   theMaxShift = maxshift;
00086   theMaxLPShift = maxlpshift;
00087   theMaxStep = maxstep;
00088   theWeightThreshold=weightthreshold;
00089 }
00090 
00091 
00092 void AdaptiveVertexFitter::setParameters ( const edm::ParameterSet & s )
00093 {
00094     setParameters ( s.getParameter<double>("maxshift"),
00095                     s.getParameter<double>("maxlpshift"),
00096                     s.getParameter<int>("maxstep"),
00097                     s.getParameter<double>("weightthreshold") );
00098 }
00099 
00100 CachingVertex<5>
00101 AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & tracks) const
00102 {
00103   if ( tracks.size() < 2 )
00104   {
00105     LogError("RecoVertex/AdaptiveVertexFitter")
00106       << "Supplied fewer than two tracks. Vertex is invalid.";
00107     return CachingVertex<5>(); // return invalid vertex
00108   };
00109   // Linearization Point
00110   GlobalPoint linP(0.,0.,0.);
00111     linP = theLinP->getLinearizationPoint(tracks);
00112   // Initial vertex seed, with a very large error matrix
00113   AlgebraicSymMatrix we(3,1);
00114   GlobalError error( we * initialError );
00115   VertexState seed (linP, error);
00116   vector<RefCountedVertexTrack> vtContainer = linearizeTracks(tracks, seed);
00117   return fit(vtContainer, seed, false);
00118 }
00119 
00120 CachingVertex<5>
00121 AdaptiveVertexFitter::vertex(const vector<RefCountedVertexTrack> & tracks) const
00122 {
00123   if ( tracks.size() < 2 )
00124   {
00125     LogError("RecoVertex/AdaptiveVertexFitter")
00126       << "Supplied fewer than two tracks. Vertex is invalid.";
00127     return CachingVertex<5>(); // return invalid vertex
00128   };
00129   // Initial vertex seed, with a very small weight matrix
00130   GlobalPoint linP = tracks[0]->linearizedTrack()->linearizationPoint();
00131   AlgebraicSymMatrix we(3,1);
00132   GlobalError error( we * initialError );
00133   VertexState seed (linP, error);
00134   return fit(tracks, seed, false);
00135 }
00136 
00137 CachingVertex<5>
00138 AdaptiveVertexFitter::vertex(const vector<RefCountedVertexTrack> & tracks, const reco::BeamSpot & spot ) const
00139 {
00140   if ( tracks.size() < 1 )
00141   {
00142     LogError("RecoVertex/AdaptiveVertexFitter")
00143       << "Supplied no tracks. Vertex is invalid.";
00144     return CachingVertex<5>(); // return invalid vertex
00145   };
00146   VertexState beamSpotState(spot);
00147   return fit(tracks, beamSpotState, true );
00148 }
00149 
00150 
00151 
00155 CachingVertex<5>
00156 AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & tracks,
00157                   const GlobalPoint& linPoint) const
00158 {
00159   if ( tracks.size() < 2 )
00160   {
00161     LogError("RecoVertex/AdaptiveVertexFitter")
00162       << "Supplied fewer than two tracks. Vertex is invalid.";
00163     return CachingVertex<5>(); // return invalid vertex
00164   };
00165   // Initial vertex seed, with a very large error matrix
00166   AlgebraicSymMatrix we(3,1);
00167   GlobalError error( we * initialError );
00168   VertexState seed (linPoint, error);
00169   vector<RefCountedVertexTrack> vtContainer = linearizeTracks(tracks, seed);
00170   return fit(vtContainer, seed, false);
00171 }
00172 
00173 
00178 CachingVertex<5> 
00179 AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & tracks,
00180                                const reco::BeamSpot& beamSpot) const
00181 {
00182   if ( tracks.size() < 1 )
00183   {
00184     LogError("RecoVertex/AdaptiveVertexFitter")
00185       << "Supplied no tracks. Vertex is invalid.";
00186     return CachingVertex<5>(); // return invalid vertex
00187   };
00188 
00189   VertexState beamSpotState(beamSpot);
00190   vector<RefCountedVertexTrack> vtContainer;
00191 
00192   if (tracks.size() > 1) {
00193     // Linearization Point search if there are more than 1 track
00194     GlobalPoint linP(0.,0.,0.);
00195       linP = theLinP->getLinearizationPoint(tracks);
00196     AlgebraicSymMatrix we(3,1);
00197     // AlgebraicSymMatrix33 we;
00198     // we(0,0)=1; we(1,1)=1; we(2,2);
00199     GlobalError error(we*10000);
00200     VertexState lpState(linP, error);
00201     vtContainer = linearizeTracks(tracks, lpState);
00202   } else {
00203     // otherwise take the beamspot position.
00204     vtContainer = linearizeTracks(tracks, beamSpotState);
00205   }
00206 
00207   return fit(vtContainer, beamSpotState, true);
00208 }
00209 
00210 
00216 CachingVertex<5> AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & tracks,
00217                   const GlobalPoint& priorPos,
00218                   const GlobalError& priorError) const
00219 
00220 {
00221   if ( tracks.size() < 1 )
00222   {
00223     LogError("RecoVertex/AdaptiveVertexFitter")
00224       << "Supplied no tracks. Vertex is invalid.";
00225     return CachingVertex<5>(); // return invalid vertex
00226   };
00227   VertexState seed (priorPos, priorError);
00228   vector<RefCountedVertexTrack> vtContainer = linearizeTracks(tracks, seed);
00229   return fit( vtContainer, seed, true );
00230 }
00231 
00232 
00237 CachingVertex<5> AdaptiveVertexFitter::vertex(
00238                 const vector<RefCountedVertexTrack> & tracks,
00239                   const GlobalPoint& priorPos,
00240                   const GlobalError& priorError) const
00241 {
00242   if ( tracks.size() < 1 )
00243   {
00244     LogError("RecoVertex/AdaptiveVertexFitter")
00245       << "Supplied no tracks. Vertex is invalid.";
00246     return CachingVertex<5>(); // return invalid vertex
00247   };
00248   VertexState seed (priorPos, priorError);
00249   return fit(tracks, seed, true);
00250 }
00251 
00252 
00260 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00261 AdaptiveVertexFitter::linearizeTracks(const vector<reco::TransientTrack> & tracks,
00262                                       const VertexState & seed ) const
00263 {
00264   GlobalPoint linP = seed.position();
00265   vector<RefCountedLinearizedTrackState> lTracks;
00266   for(vector<reco::TransientTrack>::const_iterator i = tracks.begin();
00267       i != tracks.end(); ++i )
00268   {
00269     try {
00270       RefCountedLinearizedTrackState lTrData
00271         = theLinTrkFactory->linearizedTrackState(linP, *i);
00272       lTracks.push_back(lTrData);
00273     } catch ( exception & e ) {
00274       LogWarning("RecoVertex/AdaptiveVertexFitter") 
00275         << "Exception " << e.what() << " in ::linearizeTracks."
00276         << "Your future vertex has just lost a track.";
00277     };
00278   }
00279   AlgebraicSymMatrix we(3,0);
00280   GlobalError nullError( we );
00281   VertexState initialSeed (linP, nullError);
00282   return weightTracks(lTracks, initialSeed);
00283 }
00284 
00290 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00291 AdaptiveVertexFitter::reLinearizeTracks(
00292                                 const vector<RefCountedVertexTrack> & tracks,
00293                                 const CachingVertex<5> & vertex ) const
00294 {
00295   VertexState seed = vertex.vertexState();
00296   GlobalPoint linP = seed.position();
00297   vector<RefCountedLinearizedTrackState> lTracks;
00298   for(vector<RefCountedVertexTrack>::const_iterator i = tracks.begin();
00299     i != tracks.end(); i++)
00300   {
00301     try {
00302       RefCountedLinearizedTrackState lTrData
00303         = theLinTrkFactory->linearizedTrackState( linP, (**i).linearizedTrack()->track() );
00304       /*
00305       RefCountedLinearizedTrackState lTrData =
00306               (**i).linearizedTrack()->stateWithNewLinearizationPoint(linP);
00307               */
00308       lTracks.push_back(lTrData);
00309     } catch ( exception & e ) {
00310       LogWarning("RecoVertex/AdaptiveVertexFitter") 
00311         << "Exception " << e.what() << " in ::relinearizeTracks. "
00312         << "Will not relinearize this track.";
00313       lTracks.push_back ( (**i).linearizedTrack() );
00314     };
00315   };
00316   return reWeightTracks(lTracks, vertex );
00317 }
00318 
00319 AdaptiveVertexFitter * AdaptiveVertexFitter::clone() const
00320 {
00321   return new AdaptiveVertexFitter( * this );
00322 }
00323 
00324 float AdaptiveVertexFitter::getWeight ( float chi2 ) const
00325 {
00326   float weight = theAssProbComputer->weight(chi2);
00327 
00328   if ( weight > 1.0 )
00329   {
00330     LogWarning("RecoVertex/AdaptiveVertexFitter") << "Weight " << weight << " > 1.0!";
00331     weight=1.0;
00332   };
00333 
00334   if ( weight < 0.0 )
00335   {
00336     LogWarning("RecoVertex/AdaptiveVertexFitter") << "Weight " << weight << " < 0.0!";
00337     weight=0.0;
00338   };
00339   return weight;
00340 }
00341 
00342 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00343 AdaptiveVertexFitter::reWeightTracks(
00344                     const vector<RefCountedLinearizedTrackState> & lTracks,
00345                     const CachingVertex<5> & vertex ) const
00346 {
00347   VertexState seed = vertex.vertexState();
00348   theNr++;
00349   // GlobalPoint pos = seed.position();
00350 
00351   vector<RefCountedVertexTrack> finalTracks;
00352   VertexTrackFactory<5> vTrackFactory;
00353   #ifdef STORE_WEIGHTS
00354   iter++;
00355   #endif
00356   for(vector<RefCountedLinearizedTrackState>::const_iterator i
00357         = lTracks.begin(); i != lTracks.end(); i++)
00358   {
00359     float weight=0.;
00360     try {
00361       float chi2 = theComp->estimate ( vertex, *i );
00362       weight=getWeight ( chi2 );
00363     } catch ( cms::Exception & c ) {
00364       cout << "[AdaptiveVertexFitter] Aiee! " << c.what() << endl;
00365       LogWarning("AdaptiveVertexFitter" ) << "When reweighting, a track threw \"" 
00366                                           << c.what() << "\". Will add this track with w=0.";
00367     }
00368     
00369     RefCountedVertexTrack vTrData
00370        = vTrackFactory.vertexTrack(*i, seed, weight );
00371 
00372     #ifdef STORE_WEIGHTS
00373     map < string, dataharvester::MultiType > m;
00374     m["chi2"]=chi2;
00375     m["w"]=theAssProbComputer->weight(chi2);
00376     m["T"]=theAssProbComputer->currentTemp();
00377     m["n"]=iter;
00378     m["pos"]="reweight";
00379     m["id"]=getId ( *i );
00380     dataharvester::Writer::file("w.txt").save ( m );
00381     #endif
00382 
00383     finalTracks.push_back(vTrData);
00384   }
00385   return finalTracks;
00386 }
00387 
00388 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00389 AdaptiveVertexFitter::weightTracks(
00390                     const vector<RefCountedLinearizedTrackState> & lTracks,
00391                     const VertexState & seed ) const
00392 {
00393   theNr++;
00394   GlobalPoint pos = seed.position();
00397   theAssProbComputer->resetAnnealing();
00398 
00399   vector<RefCountedVertexTrack> finalTracks;
00400   VertexTrackFactory<5> vTrackFactory;
00401   KalmanChiSquare computer;
00402   #ifdef STORE_WEIGHTS
00403   iter++;
00404   #endif
00405   for(vector<RefCountedLinearizedTrackState>::const_iterator i
00406         = lTracks.begin(); i != lTracks.end(); i++)
00407   {
00408     float weight = 0.;
00409     try {
00410       float chi2 = computer.estimate ( pos, *i );
00411       weight = getWeight ( chi2 );
00412     } catch ( cms::Exception & c ) {
00413       cout << "[AdaptiveVertexFitter] Aiee! " << c.what() << endl;
00414       LogWarning ("AdaptiveVertexFitter" ) << "When weighting a track, track threw \"" << c.what()
00415                                            << " will add with w=0.";
00416     }
00417 
00418     RefCountedVertexTrack vTrData
00419        = vTrackFactory.vertexTrack(*i, seed, weight );
00420     #ifdef STORE_WEIGHTS
00421     map < string, dataharvester::MultiType > m;
00422     m["chi2"]=chi2;
00423     m["w"]=theAssProbComputer->weight(chi2);
00424     m["T"]=theAssProbComputer->currentTemp();
00425     m["n"]=iter;
00426     m["id"]=getId ( *i );
00427     m["pos"]="weight";
00428     dataharvester::Writer::file("w.txt").save ( m );
00429     #endif
00430     finalTracks.push_back(vTrData);
00431   }
00432   return finalTracks;
00433 }
00434 
00440 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00441 AdaptiveVertexFitter::reWeightTracks(
00442                             const vector<RefCountedVertexTrack> & tracks,
00443                             const CachingVertex<5> & seed) const
00444 {
00445   vector<RefCountedLinearizedTrackState> lTracks;
00446   for(vector<RefCountedVertexTrack>::const_iterator i = tracks.begin();
00447     i != tracks.end(); i++)
00448   {
00449     lTracks.push_back((**i).linearizedTrack());
00450   }
00451 
00452   return reWeightTracks(lTracks, seed);
00453 }
00454 
00455 
00456 /*
00457  * The method where the vertex fit is actually done!
00458  */
00459 
00460 CachingVertex<5>
00461 AdaptiveVertexFitter::fit(const vector<RefCountedVertexTrack> & tracks,
00462                           const VertexState & priorSeed,
00463                           bool withPrior) const
00464 {
00465   theAssProbComputer->resetAnnealing();
00466   vector<RefCountedVertexTrack> initialTracks;
00467   GlobalPoint priorVertexPosition = priorSeed.position();
00468   GlobalError priorVertexError = priorSeed.error();
00469 
00470   CachingVertex<5> returnVertex( priorVertexPosition,priorVertexError,
00471                               initialTracks,0);
00472   if (withPrior)
00473   {
00474     returnVertex = CachingVertex<5>(priorVertexPosition,priorVertexError,
00475                     priorVertexPosition,priorVertexError,initialTracks,0);
00476   }
00477 
00478   vector<RefCountedVertexTrack> globalVTracks = tracks;
00479 
00480   // main loop through all the VTracks
00481   int lpStep = 0; int step = 0;
00482 
00483   CachingVertex<5> initialVertex = returnVertex;
00484 
00485   GlobalPoint newPosition = priorVertexPosition;
00486   GlobalPoint previousPosition = newPosition;
00487 
00488   int ns_trks=0; // number of significant tracks.
00489   // If we have only two significant tracks, we return an invalid vertex
00490 
00491   do {
00492     ns_trks=0;
00493     CachingVertex<5> fVertex = initialVertex;
00494     if ((previousPosition - newPosition).transverse() > theMaxLPShift)
00495     {
00496       // relinearize and reweight.
00497       // (reLinearizeTracks also reweights tracks)
00498       globalVTracks = reLinearizeTracks( globalVTracks,
00499                              returnVertex );
00500       lpStep++;
00501     } else if (step) {
00502       // reweight, if it is not the first step
00503       globalVTracks = reWeightTracks( globalVTracks,
00504                                       returnVertex );
00505     }
00506     // update sequentially the vertex estimate
00507     CachingVertex<5> nVertex;
00508     for(vector<RefCountedVertexTrack>::const_iterator i
00509           = globalVTracks.begin(); i != globalVTracks.end(); i++)
00510     {
00511       try {
00512         nVertex = theUpdator->add( fVertex, *i );
00513       } catch ( cms::Exception & c ) {
00514         edm::LogWarning("AdaptiveVertexFitter" ) << "when updating, received " << c.what()
00515                                                  << " final result might miss the info of a track.";
00516       }
00517       if (nVertex.isValid()) {
00518         if ( (**i).weight() >= theWeightThreshold )
00519         {
00520           ns_trks++;
00521         };
00522         fVertex = nVertex;
00523       } else {
00524         LogWarning("RecoVertex/AdaptiveVertexFitter") 
00525           << "The updator returned an invalid vertex when adding track "
00526           << i-globalVTracks.begin() <<endl
00527           << "Your vertex might just have lost one good track.";
00528       };
00529     }
00530     previousPosition = newPosition;
00531     newPosition = fVertex.position();
00532     returnVertex = fVertex;
00533     theAssProbComputer->anneal();
00534     step++;
00535     if ( step >= theMaxStep ) break;
00536 
00537   } while (
00538       // repeat as long as
00539       // - vertex moved too much or
00540       // - we're not yet annealed
00541          ( ((previousPosition - newPosition).mag() > theMaxShift) ||
00542            (!(theAssProbComputer->isAnnealed()) ) ) ) ;
00543 
00544   if ( theWeightThreshold > 0. &&  ns_trks < 2 && !withPrior ) 
00545   {
00546     LogDebug("RecoVertex/AdaptiveVertexFitter") 
00547       << "fewer than two significant tracks (w>" << theWeightThreshold << ")."
00548       << " Fitted vertex is invalid.";
00549     return CachingVertex<5>(); // return invalid vertex
00550   }
00551 
00552   #ifdef STORE_WEIGHTS
00553   map < string, dataharvester::MultiType > m;
00554   m["chi2"]=chi2;
00555   m["w"]=theAssProbComputer->weight(chi2);
00556   m["T"]=theAssProbComputer->currentTemp();
00557   m["n"]=iter;
00558   m["id"]=getId ( *i );
00559   m["pos"]="final";
00560   dataharvester::Writer::file("w.txt").save ( m );
00561   #endif
00562   return theSmoother->smooth( returnVertex );
00563 }

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