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/VertexPrimitives/interface/VertexException.h"
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008
00009 #include <algorithm>
00010
00011 using namespace edm;
00012
00013
00014 #ifdef STORE_WEIGHTS
00015 #include <dataharvester/Writer.h>
00016 #endif
00017
00018 using namespace std;
00019
00020 namespace {
00021 struct CompareTwoTracks {
00022 int operator() ( const reco::TransientTrack & a, const reco::TransientTrack & b ) {
00023 return ( a.impactPointState().globalMomentum().perp() >
00024 b.impactPointState().globalMomentum().perp() ) ;
00025 };
00026 };
00027
00028 typedef AdaptiveVertexFitter::RefCountedVertexTrack RefCountedVertexTrack;
00029
00030 GlobalError fitError()
00031 {
00032 static GlobalError err;
00033 static bool once=true;
00034 if (once)
00035 {
00036
00037 static const float initialError = 10000;
00038 AlgebraicSymMatrix33 ret;
00039 ret(0,0)=initialError;
00040 ret(1,1)=initialError;
00041 ret(2,2)=initialError;
00042 err=GlobalError ( ret );
00043 once=false;
00044 }
00045 return err;
00046 }
00047
00048 GlobalError linPointError()
00049 {
00050 static GlobalError err;
00051 static bool once=true;
00052 if (once)
00053 {
00054
00055
00056 AlgebraicSymMatrix33 ret;
00057 ret(0,0)=.3; ret(1,1)=.3; ret(2,2)=3.;
00058
00059 err=GlobalError ( ret );
00060 once=false;
00061 }
00062 return err;
00063 }
00064
00065 struct DistanceToRefPoint {
00066 DistanceToRefPoint ( const GlobalPoint & ref ) : theRef ( ref ) {}
00067
00068 bool operator() ( const RefCountedVertexTrack & v1, const RefCountedVertexTrack & v2 )
00069 {
00070 return ( distance ( v1 ) < distance ( v2 ) );
00071 }
00072
00073 float distance ( const RefCountedVertexTrack & v1 )
00074 {
00075 return ( v1->linearizedTrack()->track().initialFreeState().position() - theRef ).mag2();
00076 }
00077
00078 private:
00079 GlobalPoint theRef;
00080 };
00081
00082 #ifdef STORE_WEIGHTS
00083 map < RefCountedLinearizedTrackState, int > ids;
00084 int iter=0;
00085
00086 int getId ( const RefCountedLinearizedTrackState & r )
00087 {
00088 static int ctr=1;
00089 if ( ids.count(r) == 0 )
00090 {
00091 ids[r]=ctr++;
00092 }
00093 return ids[r];
00094 }
00095 #endif
00096 }
00097
00098 AdaptiveVertexFitter::AdaptiveVertexFitter(
00099 const AnnealingSchedule & ann,
00100 const LinearizationPointFinder & linP,
00101 const VertexUpdator<5> & updator,
00102 const VertexTrackCompatibilityEstimator<5> & crit,
00103 const VertexSmoother<5> & smoother,
00104 const AbstractLTSFactory<5> & ltsf ) :
00105 theNr(0),
00106 theLinP(linP.clone()), theUpdator( updator.clone()),
00107 theSmoother ( smoother.clone() ), theAssProbComputer( ann.clone() ),
00108 theComp ( crit.clone() ), theLinTrkFactory ( ltsf.clone() ),
00109 gsfIntermediarySmoothing_(false)
00110 {
00111 setParameters();
00112 }
00113
00114 void AdaptiveVertexFitter::setWeightThreshold ( float w )
00115 {
00116 theWeightThreshold=w;
00117 }
00118
00119 AdaptiveVertexFitter::AdaptiveVertexFitter
00120 (const AdaptiveVertexFitter & o ) :
00121 theMaxShift ( o.theMaxShift ), theMaxLPShift ( o.theMaxLPShift ),
00122 theMaxStep ( o.theMaxStep ), theWeightThreshold ( o.theWeightThreshold ),
00123 theNr ( o.theNr ),
00124 theLinP ( o.theLinP->clone() ), theUpdator ( o.theUpdator->clone() ),
00125 theSmoother ( o.theSmoother->clone() ),
00126 theAssProbComputer ( o.theAssProbComputer->clone() ),
00127 theComp ( o.theComp->clone() ),
00128 theLinTrkFactory ( o.theLinTrkFactory->clone() ),
00129 gsfIntermediarySmoothing_(o.gsfIntermediarySmoothing_)
00130 {}
00131
00132 AdaptiveVertexFitter::~AdaptiveVertexFitter()
00133 {
00134 delete theLinP;
00135 delete theUpdator;
00136 delete theSmoother;
00137 delete theAssProbComputer;
00138 delete theComp;
00139 delete theLinTrkFactory;
00140 }
00141
00142 void AdaptiveVertexFitter::setParameters( double maxshift, double maxlpshift,
00143 unsigned maxstep, double weightthreshold )
00144 {
00145 theMaxShift = maxshift;
00146 theMaxLPShift = maxlpshift;
00147 theMaxStep = maxstep;
00148 theWeightThreshold=weightthreshold;
00149 }
00150
00151
00152 void AdaptiveVertexFitter::setParameters ( const edm::ParameterSet & s )
00153 {
00154 setParameters ( s.getParameter<double>("maxshift"),
00155 s.getParameter<double>("maxlpshift"),
00156 s.getParameter<int>("maxstep"),
00157 s.getParameter<double>("weightthreshold") );
00158 }
00159
00160 CachingVertex<5>
00161 AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & unstracks) const
00162 {
00163 if ( unstracks.size() < 2 )
00164 {
00165 LogError("RecoVertex|AdaptiveVertexFitter")
00166 << "Supplied fewer than two tracks. Vertex is invalid.";
00167 return CachingVertex<5>();
00168 };
00169 vector < reco::TransientTrack > tracks = unstracks;
00170 sort ( tracks.begin(), tracks.end(), CompareTwoTracks() );
00171
00172 GlobalPoint linP = theLinP->getLinearizationPoint(tracks);
00173
00174 VertexState lseed (linP, linPointError() );
00175 vector<RefCountedVertexTrack> vtContainer = linearizeTracks(tracks, lseed);
00176
00177 VertexState seed (linP, fitError() );
00178 return fit(vtContainer, seed, false);
00179 }
00180
00181 CachingVertex<5>
00182 AdaptiveVertexFitter::vertex(const vector<RefCountedVertexTrack> & tracks) const
00183 {
00184 if ( tracks.size() < 2 )
00185 {
00186 LogError("RecoVertex|AdaptiveVertexFitter")
00187 << "Supplied fewer than two tracks. Vertex is invalid.";
00188 return CachingVertex<5>();
00189 };
00190
00191 GlobalPoint linP = tracks[0]->linearizedTrack()->linearizationPoint();
00192 VertexState seed (linP, fitError() );
00193 return fit(tracks, seed, false);
00194 }
00195
00196 CachingVertex<5>
00197 AdaptiveVertexFitter::vertex(const vector<RefCountedVertexTrack> & tracks, const reco::BeamSpot & spot ) const
00198 {
00199 if ( tracks.size() < 1 )
00200 {
00201 LogError("RecoVertex|AdaptiveVertexFitter")
00202 << "Supplied no tracks. Vertex is invalid.";
00203 return CachingVertex<5>();
00204 };
00205 VertexState beamSpotState(spot);
00206 return fit(tracks, beamSpotState, true );
00207 }
00208
00209
00210
00214 CachingVertex<5>
00215 AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & tracks,
00216 const GlobalPoint& linPoint) const
00217 {
00218 if ( tracks.size() < 2 )
00219 {
00220 LogError("RecoVertex|AdaptiveVertexFitter")
00221 << "Supplied fewer than two tracks. Vertex is invalid.";
00222 return CachingVertex<5>();
00223 };
00224
00225 VertexState seed (linPoint, linPointError() );
00226 vector<RefCountedVertexTrack> vtContainer = linearizeTracks(tracks, seed);
00227 VertexState fitseed (linPoint, fitError() );
00228 return fit(vtContainer, fitseed, false);
00229 }
00230
00231
00236 CachingVertex<5>
00237 AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & unstracks,
00238 const reco::BeamSpot& beamSpot) const
00239 {
00240 if ( unstracks.size() < 1 )
00241 {
00242 LogError("RecoVertex|AdaptiveVertexFitter")
00243 << "Supplied no tracks. Vertex is invalid.";
00244 return CachingVertex<5>();
00245 };
00246
00247 VertexState beamSpotState(beamSpot);
00248 vector<RefCountedVertexTrack> vtContainer;
00249
00250 vector < reco::TransientTrack > tracks = unstracks;
00251 sort ( tracks.begin(), tracks.end(), CompareTwoTracks() );
00252
00253 if (tracks.size() > 1) {
00254
00255 GlobalPoint linP = theLinP->getLinearizationPoint(tracks);
00256 VertexState lpState(linP, linPointError() );
00257 vtContainer = linearizeTracks(tracks, lpState);
00258 } else {
00259
00260 vtContainer = linearizeTracks(tracks, beamSpotState);
00261 }
00262
00263 return fit(vtContainer, beamSpotState, true);
00264 }
00265
00266
00272 CachingVertex<5> AdaptiveVertexFitter::vertex(const vector<reco::TransientTrack> & tracks,
00273 const GlobalPoint& priorPos,
00274 const GlobalError& priorError) const
00275
00276 {
00277 if ( tracks.size() < 1 )
00278 {
00279 LogError("RecoVertex|AdaptiveVertexFitter")
00280 << "Supplied no tracks. Vertex is invalid.";
00281 return CachingVertex<5>();
00282 };
00283 VertexState seed (priorPos, priorError);
00284 vector<RefCountedVertexTrack> vtContainer = linearizeTracks(tracks, seed);
00285 return fit( vtContainer, seed, true );
00286 }
00287
00288
00293 CachingVertex<5> AdaptiveVertexFitter::vertex(
00294 const vector<RefCountedVertexTrack> & tracks,
00295 const GlobalPoint& priorPos,
00296 const GlobalError& priorError) const
00297 {
00298 if ( tracks.size() < 1 )
00299 {
00300 LogError("RecoVertex|AdaptiveVertexFitter")
00301 << "Supplied no tracks. Vertex is invalid.";
00302 return CachingVertex<5>();
00303 };
00304 VertexState seed (priorPos, priorError);
00305 return fit(tracks, seed, true);
00306 }
00307
00308
00316 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00317 AdaptiveVertexFitter::linearizeTracks(const vector<reco::TransientTrack> & tracks,
00318 const VertexState & seed ) const
00319 {
00320 const GlobalPoint & linP ( seed.position() );
00321 vector<RefCountedLinearizedTrackState> lTracks;
00322 for(vector<reco::TransientTrack>::const_iterator i = tracks.begin();
00323 i != tracks.end(); ++i )
00324 {
00325 try {
00326 RefCountedLinearizedTrackState lTrData
00327 = theLinTrkFactory->linearizedTrackState(linP, *i);
00328 lTracks.push_back(lTrData);
00329 } catch ( exception & e ) {
00330 LogWarning("RecoVertex/AdaptiveVertexFitter")
00331 << "Exception " << e.what() << " in ::linearizeTracks."
00332 << "Your future vertex has just lost a track.";
00333 };
00334 }
00335 return weightTracks(lTracks, seed );
00336 }
00337
00343 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00344 AdaptiveVertexFitter::reLinearizeTracks(
00345 const vector<RefCountedVertexTrack> & tracks,
00346 const CachingVertex<5> & vertex ) const
00347 {
00348 VertexState seed = vertex.vertexState();
00349 GlobalPoint linP = seed.position();
00350 vector<RefCountedLinearizedTrackState> lTracks;
00351 for(vector<RefCountedVertexTrack>::const_iterator i = tracks.begin();
00352 i != tracks.end(); i++)
00353 {
00354 try {
00355 RefCountedLinearizedTrackState lTrData
00356 = theLinTrkFactory->linearizedTrackState( linP, (**i).linearizedTrack()->track() );
00357
00358
00359
00360
00361 lTracks.push_back(lTrData);
00362 } catch ( exception & e ) {
00363 LogWarning("RecoVertex/AdaptiveVertexFitter")
00364 << "Exception " << e.what() << " in ::relinearizeTracks. "
00365 << "Will not relinearize this track.";
00366 lTracks.push_back ( (**i).linearizedTrack() );
00367 };
00368 };
00369 return reWeightTracks(lTracks, vertex );
00370 }
00371
00372 AdaptiveVertexFitter * AdaptiveVertexFitter::clone() const
00373 {
00374 return new AdaptiveVertexFitter( * this );
00375 }
00376
00377 double AdaptiveVertexFitter::getWeight ( float chi2 ) const
00378 {
00379 double weight = theAssProbComputer->weight(chi2);
00380
00381 if ( weight > 1.0 )
00382 {
00383 LogWarning("RecoVertex/AdaptiveVertexFitter") << "Weight " << weight << " > 1.0!";
00384 weight=1.0;
00385 };
00386
00387 if ( weight < 1e-20 )
00388 {
00389
00390 weight=1e-20;
00391 };
00392 return weight;
00393 }
00394
00395 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00396 AdaptiveVertexFitter::reWeightTracks(
00397 const vector<RefCountedLinearizedTrackState> & lTracks,
00398 const CachingVertex<5> & vertex ) const
00399 {
00400 VertexState seed = vertex.vertexState();
00401 theNr++;
00402
00403
00404 vector<RefCountedVertexTrack> finalTracks;
00405 VertexTrackFactory<5> vTrackFactory;
00406 #ifdef STORE_WEIGHTS
00407 iter++;
00408 #endif
00409 for(vector<RefCountedLinearizedTrackState>::const_iterator i
00410 = lTracks.begin(); i != lTracks.end(); i++)
00411 {
00412 double weight=0.;
00413 pair<bool, double> chi2Res = theComp->estimate ( vertex, *i );
00414 if (!chi2Res.first) {
00415 cout << "[AdaptiveVertexFitter] aie... vertex candidate is at " << vertex.position() << endl;
00416 LogWarning("AdaptiveVertexFitter" ) << "When reweighting, chi2<0. Will add this track with w=0.";
00417
00418 }else {
00419 weight = getWeight ( chi2Res.second );
00420 }
00421
00422 RefCountedVertexTrack vTrData
00423 = vTrackFactory.vertexTrack(*i, seed, weight );
00424
00425 #ifdef STORE_WEIGHTS
00426 map < string, dataharvester::MultiType > m;
00427 m["chi2"]=chi2;
00428 m["w"]=theAssProbComputer->weight(chi2);
00429 m["T"]=theAssProbComputer->currentTemp();
00430 m["n"]=iter;
00431 m["pos"]="reweight";
00432 m["id"]=getId ( *i );
00433 dataharvester::Writer::file("w.txt").save ( m );
00434 #endif
00435
00436 finalTracks.push_back(vTrData);
00437 }
00438 sort ( finalTracks.begin(), finalTracks.end(),
00439 DistanceToRefPoint ( vertex.position() ) );
00440 return finalTracks;
00441 }
00442
00443 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00444 AdaptiveVertexFitter::weightTracks(
00445 const vector<RefCountedLinearizedTrackState> & lTracks,
00446 const VertexState & seed ) const
00447 {
00448 theNr++;
00449 CachingVertex<5> seedvtx ( seed, vector<RefCountedVertexTrack> (), 0. );
00452 theAssProbComputer->resetAnnealing();
00453
00454 vector<RefCountedVertexTrack> finalTracks;
00455 VertexTrackFactory<5> vTrackFactory;
00456 #ifdef STORE_WEIGHTS
00457 iter++;
00458 #endif
00459 for(vector<RefCountedLinearizedTrackState>::const_iterator i
00460 = lTracks.begin(); i != lTracks.end(); i++)
00461 {
00462
00463 double weight = 0.;
00464 pair<bool, double> chi2Res = theComp->estimate ( seedvtx, *i );
00465 if (!chi2Res.first) {
00466 cout << "[AdaptiveVertexFitter] Aiee! " << endl;
00467 LogWarning ("AdaptiveVertexFitter" ) << "When weighting a track, chi2 calculation failed;"
00468 << " will add with w=0.";
00469 } else {
00470 weight = getWeight ( chi2Res.second );
00471 }
00472 RefCountedVertexTrack vTrData
00473 = vTrackFactory.vertexTrack(*i, seed, weight );
00474 #ifdef STORE_WEIGHTS
00475 map < string, dataharvester::MultiType > m;
00476 m["chi2"]=chi2;
00477 m["w"]=theAssProbComputer->weight(chi2);
00478 m["T"]=theAssProbComputer->currentTemp();
00479 m["n"]=iter;
00480 m["id"]=getId ( *i );
00481 m["pos"]="weight";
00482 dataharvester::Writer::file("w.txt").save ( m );
00483 #endif
00484 finalTracks.push_back(vTrData);
00485 }
00486 return finalTracks;
00487 }
00488
00494 vector<AdaptiveVertexFitter::RefCountedVertexTrack>
00495 AdaptiveVertexFitter::reWeightTracks(
00496 const vector<RefCountedVertexTrack> & tracks,
00497 const CachingVertex<5> & seed) const
00498 {
00499 vector<RefCountedLinearizedTrackState> lTracks;
00500 for(vector<RefCountedVertexTrack>::const_iterator i = tracks.begin();
00501 i != tracks.end(); i++)
00502 {
00503 lTracks.push_back((**i).linearizedTrack());
00504 }
00505
00506 return reWeightTracks(lTracks, seed);
00507 }
00508
00509
00510
00511
00512
00513
00514 CachingVertex<5>
00515 AdaptiveVertexFitter::fit( const vector<RefCountedVertexTrack> & tracks,
00516 const VertexState & priorSeed,
00517 bool withPrior) const
00518 {
00519 theAssProbComputer->resetAnnealing();
00520
00521 vector<RefCountedVertexTrack> initialTracks;
00522 GlobalPoint priorVertexPosition = priorSeed.position();
00523 GlobalError priorVertexError = priorSeed.error();
00524
00525 CachingVertex<5> returnVertex( priorVertexPosition,priorVertexError,
00526 initialTracks,0);
00527 if (withPrior)
00528 {
00529 returnVertex = CachingVertex<5>(priorVertexPosition,priorVertexError,
00530 priorVertexPosition,priorVertexError,initialTracks,0);
00531 }
00532
00533
00534
00535 vector<RefCountedVertexTrack> globalVTracks ( tracks.size() );
00536
00537 partial_sort_copy ( tracks.begin(), tracks.end(),
00538 globalVTracks.begin(), globalVTracks.end(), DistanceToRefPoint ( priorSeed.position() ) );
00539
00540
00541 int lpStep = 0; int step = 0;
00542
00543 CachingVertex<5> initialVertex = returnVertex;
00544
00545 GlobalPoint newPosition = priorVertexPosition;
00546 GlobalPoint previousPosition = newPosition;
00547
00548 int ns_trks=0;
00549
00550
00551 do {
00552 ns_trks=0;
00553 CachingVertex<5> fVertex = initialVertex;
00554 if ((previousPosition - newPosition).transverse() > theMaxLPShift)
00555 {
00556
00557
00558 if (gsfIntermediarySmoothing_) returnVertex = theSmoother->smooth(returnVertex);
00559 globalVTracks = reLinearizeTracks( globalVTracks, returnVertex );
00560 lpStep++;
00561 } else if (step) {
00562
00563 if (gsfIntermediarySmoothing_) returnVertex = theSmoother->smooth(returnVertex);
00564 globalVTracks = reWeightTracks( globalVTracks, returnVertex );
00565 }
00566
00567 CachingVertex<5> nVertex;
00568 for(vector<RefCountedVertexTrack>::const_iterator i
00569 = globalVTracks.begin(); i != globalVTracks.end(); i++)
00570 {
00571 if ((**i).weight() > 0.) nVertex = theUpdator->add( fVertex, *i );
00572 else nVertex = fVertex;
00573 if (nVertex.isValid()) {
00574 if ( (**i).weight() >= theWeightThreshold )
00575 {
00576 ns_trks++;
00577 };
00578
00579 if ( fabs ( nVertex.position().z() ) > 10000. ||
00580 nVertex.position().perp()>120.)
00581 {
00582
00583 LogWarning ("AdaptiveVertexFitter" ) << "Vertex candidate just took off to " << nVertex.position()
00584 << "! Will discard this update!";
00585
00586
00587
00588
00589
00590
00591
00592 } else {
00593 fVertex = nVertex;
00594 }
00595 } else {
00596 LogWarning("RecoVertex/AdaptiveVertexFitter")
00597 << "The updator returned an invalid vertex when adding track "
00598 << i-globalVTracks.begin()
00599 << ".\n Your vertex might just have lost one good track.";
00600 };
00601 }
00602 previousPosition = newPosition;
00603 newPosition = fVertex.position();
00604 returnVertex = fVertex;
00605 theAssProbComputer->anneal();
00606 step++;
00607 if ( step >= theMaxStep ) break;
00608
00609 } while (
00610
00611
00612
00613 ( ((previousPosition - newPosition).mag() > theMaxShift) ||
00614 (!(theAssProbComputer->isAnnealed()) ) ) ) ;
00615
00616 if ( theWeightThreshold > 0. && ns_trks < 2 && !withPrior )
00617 {
00618 LogDebug("AdaptiveVertexFitter")
00619 << "fewer than two significant tracks (w>" << theWeightThreshold << ")."
00620 << " Fitted vertex is invalid.";
00621 return CachingVertex<5>();
00622 }
00623
00624 #ifdef STORE_WEIGHTS
00625 map < string, dataharvester::MultiType > m;
00626 m["chi2"]=chi2;
00627 m["w"]=theAssProbComputer->weight(chi2);
00628 m["T"]=theAssProbComputer->currentTemp();
00629 m["n"]=iter;
00630 m["id"]=getId ( *i );
00631 m["pos"]="final";
00632 dataharvester::Writer::file("w.txt").save ( m );
00633 #endif
00634 return theSmoother->smooth( returnVertex );
00635 }