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
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>();
00108 };
00109
00110 GlobalPoint linP(0.,0.,0.);
00111 linP = theLinP->getLinearizationPoint(tracks);
00112
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>();
00128 };
00129
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>();
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>();
00164 };
00165
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>();
00187 };
00188
00189 VertexState beamSpotState(beamSpot);
00190 vector<RefCountedVertexTrack> vtContainer;
00191
00192 if (tracks.size() > 1) {
00193
00194 GlobalPoint linP(0.,0.,0.);
00195 linP = theLinP->getLinearizationPoint(tracks);
00196 AlgebraicSymMatrix we(3,1);
00197
00198
00199 GlobalError error(we*10000);
00200 VertexState lpState(linP, error);
00201 vtContainer = linearizeTracks(tracks, lpState);
00202 } else {
00203
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>();
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>();
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
00306
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
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
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
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;
00489
00490
00491 do {
00492 ns_trks=0;
00493 CachingVertex<5> fVertex = initialVertex;
00494 if ((previousPosition - newPosition).transverse() > theMaxLPShift)
00495 {
00496
00497
00498 globalVTracks = reLinearizeTracks( globalVTracks,
00499 returnVertex );
00500 lpStep++;
00501 } else if (step) {
00502
00503 globalVTracks = reWeightTracks( globalVTracks,
00504 returnVertex );
00505 }
00506
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
00539
00540
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>();
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 }