00001 #include "RecoVertex/AdaptiveVertexFinder/interface/AdaptiveVertexReconstructor.h"
00002 #include "RecoVertex/VertexTools/interface/GeometricAnnealing.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00005 #include "RecoVertex/VertexTools/interface/DummyVertexSmoother.h"
00006 #include "RecoVertex/KalmanVertexFit/interface/KalmanVertexSmoother.h"
00007 #include <algorithm>
00008
00009 using namespace std;
00010
00011 TransientVertex AdaptiveVertexReconstructor::cleanUp ( const TransientVertex & old ) const
00012 {
00013 vector < reco::TransientTrack > trks = old.originalTracks();
00014 vector < reco::TransientTrack > newtrks;
00015 TransientVertex::TransientTrackToFloatMap mp;
00016 static const float minweight = 1.e-8;
00017 for ( vector< reco::TransientTrack >::const_iterator i=trks.begin();
00018 i!=trks.end() ; ++i )
00019 {
00020 if ( old.trackWeight ( *i ) > minweight )
00021 {
00022 newtrks.push_back ( *i );
00023 mp[*i]=old.trackWeight ( *i );
00024 }
00025 }
00026
00027 TransientVertex ret;
00028
00029 if ( old.hasPrior() )
00030 {
00031 VertexState priorstate ( old.priorPosition(), old.priorError() );
00032 ret=TransientVertex ( priorstate, old.vertexState(), newtrks,
00033 old.totalChiSquared(), old.degreesOfFreedom() );
00034 } else {
00035 ret=TransientVertex ( old.vertexState(), newtrks,
00036 old.totalChiSquared(), old.degreesOfFreedom() );
00037 }
00038 ret.weightMap ( mp );
00039
00040 if ( old.hasRefittedTracks() )
00041 {
00042
00043 vector < reco::TransientTrack > newrfs;
00044 vector < reco::TransientTrack > oldrfs=old.refittedTracks();
00045 vector < reco::TransientTrack >::const_iterator origtrkiter=trks.begin();
00046 for ( vector< reco::TransientTrack >::const_iterator i=oldrfs.begin(); i!=oldrfs.end() ; ++i )
00047 {
00048 if ( old.trackWeight ( *origtrkiter ) > minweight )
00049 {
00050 newrfs.push_back ( *i );
00051 }
00052 origtrkiter++;
00053 }
00054 if ( newrfs.size() ) ret.refittedTracks ( newrfs );
00055 }
00056
00057 if ( ret.refittedTracks().size() > ret.originalTracks().size() )
00058 {
00059 edm::LogError("AdaptiveVertexReconstructor" )
00060 << "More refitted tracks than original tracks!";
00061 }
00062
00063 return ret;
00064 }
00065
00066 void AdaptiveVertexReconstructor::erase (
00067 const TransientVertex & newvtx,
00068 set < reco::TransientTrack > & remainingtrks,
00069 float w ) const
00070 {
00071
00072
00073
00074
00075 const vector < reco::TransientTrack > & origtrks = newvtx.originalTracks();
00076 for ( vector< reco::TransientTrack >::const_iterator i=origtrks.begin();
00077 i!=origtrks.end(); ++i )
00078 {
00079 double weight = newvtx.trackWeight ( *i );
00080 if ( weight > w )
00081 {
00082 remainingtrks.erase ( *i );
00083 };
00084 };
00085 }
00086
00087 AdaptiveVertexReconstructor::AdaptiveVertexReconstructor(
00088 float primcut, float seccut, float min_weight, bool smoothing ) :
00089 thePrimaryFitter ( 0 ), theSecondaryFitter ( 0 ),
00090 theMinWeight( min_weight ), theWeightThreshold ( 0.001 )
00091 {
00092 setupFitters ( primcut, 256., 0.25, seccut, 256., 0.25, smoothing );
00093 }
00094
00095 AdaptiveVertexReconstructor::~AdaptiveVertexReconstructor()
00096 {
00097 if ( thePrimaryFitter ) delete thePrimaryFitter;
00098 if ( theSecondaryFitter ) delete theSecondaryFitter;
00099 }
00100
00101 void AdaptiveVertexReconstructor::setupFitters ( float primcut,
00102 float primT, float primr, float seccut, float secT,
00103 float secr, bool smoothing )
00104 {
00105 VertexSmoother<5> * smoother ;
00106 if ( smoothing )
00107 {
00108 smoother = new KalmanVertexSmoother();
00109 } else {
00110 smoother = new DummyVertexSmoother<5>();
00111 }
00112
00113 if ( thePrimaryFitter ) delete thePrimaryFitter;
00114 if ( theSecondaryFitter ) delete theSecondaryFitter;
00115
00116
00117
00118
00119
00120 thePrimaryFitter = new AdaptiveVertexFitter ( GeometricAnnealing ( primcut, primT, primr ), DefaultLinearizationPointFinder(),
00121 KalmanVertexUpdator<5>(), KalmanVertexTrackCompatibilityEstimator<5>(), *smoother );
00122 thePrimaryFitter->setWeightThreshold ( theWeightThreshold );
00123
00124 theSecondaryFitter = new AdaptiveVertexFitter ( GeometricAnnealing ( seccut, secT, secr ), DefaultLinearizationPointFinder(),
00125 KalmanVertexUpdator<5>(),
00126 KalmanVertexTrackCompatibilityEstimator<5>(), *smoother );
00127 theSecondaryFitter->setWeightThreshold ( 0. );
00128
00129
00130
00131 delete smoother;
00132 }
00133
00134 AdaptiveVertexReconstructor::AdaptiveVertexReconstructor( const edm::ParameterSet & m )
00135 : thePrimaryFitter(0), theSecondaryFitter(0), theMinWeight(0.5), theWeightThreshold ( 0.001 )
00136 {
00137 float primcut = 2.0;
00138 float seccut = 6.0;
00139 bool smoothing=false;
00140
00141
00142 float primT = 256.;
00143 float primr = 0.25;
00144 float secT = 256.;
00145 float secr = 0.25;
00146
00147 try {
00148 primcut = m.getParameter<double>("primcut");
00149 primT = m.getParameter<double>("primT");
00150 primr = m.getParameter<double>("primr");
00151 seccut = m.getParameter<double>("seccut");
00152 secT = m.getParameter<double>("secT");
00153 secr = m.getParameter<double>("secr");
00154 theMinWeight = m.getParameter<double>("minweight");
00155 theWeightThreshold = m.getParameter<double>("weightthreshold");
00156 smoothing = m.getParameter<bool>("smoothing");
00157 } catch ( edm::Exception & e ) {
00158 edm::LogError ("AdaptiveVertexReconstructor") << e.what();
00159 }
00160
00161 setupFitters ( primcut, primT, primr, seccut, secT, secr, smoothing );
00162 }
00163
00164 vector<TransientVertex>
00165 AdaptiveVertexReconstructor::vertices(const vector<reco::TransientTrack> & t,
00166 const reco::BeamSpot & s ) const
00167 {
00168 return vertices ( vector<reco::TransientTrack>(), t, s, false, true );
00169 }
00170
00171 vector<TransientVertex>
00172 AdaptiveVertexReconstructor::vertices(const vector<reco::TransientTrack> & primaries,
00173 const vector<reco::TransientTrack > & tracks, const reco::BeamSpot & s ) const
00174 {
00175 return vertices ( primaries, tracks, s, true, true );
00176 }
00177
00178
00179 vector<TransientVertex> AdaptiveVertexReconstructor::vertices (
00180 const vector<reco::TransientTrack> & tracks ) const
00181 {
00182 return vertices ( vector<reco::TransientTrack>(), tracks, reco::BeamSpot(),
00183 false, false );
00184 }
00185
00186 vector<TransientVertex> AdaptiveVertexReconstructor::vertices (
00187 const vector<reco::TransientTrack> & primaries,
00188 const vector<reco::TransientTrack> & tracks,
00189 const reco::BeamSpot & s, bool has_primaries, bool usespot ) const
00190 {
00191 vector < TransientVertex > ret;
00192 set < reco::TransientTrack > remainingtrks;
00193
00194 copy(tracks.begin(), tracks.end(),
00195 inserter(remainingtrks, remainingtrks.begin()));
00196
00197 int ctr=0;
00198 unsigned int n_tracks = remainingtrks.size();
00199
00200
00201 try {
00202 while ( remainingtrks.size() > 1 )
00203 {
00204
00205
00206
00207
00208 ctr++;
00209 const AdaptiveVertexFitter * fitter = theSecondaryFitter;
00210 if ( ret.size() == 0 )
00211 {
00212 fitter = thePrimaryFitter;
00213 };
00214 vector < reco::TransientTrack > fittrks;
00215 fittrks.reserve ( remainingtrks.size() );
00216
00217 copy(remainingtrks.begin(), remainingtrks.end(), back_inserter(fittrks));
00218
00219 TransientVertex tmpvtx;
00220 if ( (ret.size() == 0) && has_primaries )
00221 {
00222
00223 copy ( primaries.begin(), primaries.end(), back_inserter(fittrks) );
00224 }
00225 if ( (ret.size() == 0) && usespot )
00226 {
00227 tmpvtx=fitter->vertex ( fittrks, s );
00228 } else {
00229 tmpvtx=fitter->vertex ( fittrks );
00230 }
00231 TransientVertex newvtx = cleanUp ( tmpvtx );
00232 ret.push_back ( newvtx );
00233 erase ( newvtx, remainingtrks, theMinWeight );
00234 if ( n_tracks == remainingtrks.size() )
00235 {
00236 if ( usespot )
00237 {
00238
00239 usespot=false;
00240 LogDebug("AdaptiveVertexReconstructor")
00241 << "no tracks in vertex. trying again without beamspot constraint!";
00242 continue;
00243 }
00244 LogDebug("AdaptiveVertexReconstructor") << "all tracks (" << n_tracks
00245 << ") would be recycled for next fit. Trying with low threshold!";
00246 erase ( newvtx, remainingtrks, 1.e-5 );
00247 if ( n_tracks == remainingtrks.size() )
00248 {
00249 LogDebug("AdaptiveVertexReconstructor") << "low threshold didnt help! "
00250 << "Discontinue procedure!";
00251 break;
00252 }
00253 };
00254
00255
00256 n_tracks = remainingtrks.size();
00257 };
00258 } catch ( VertexException & v ) {
00259
00260
00261 };
00262
00263 return cleanUpVertices ( ret );
00264 }
00265
00266 vector<TransientVertex> AdaptiveVertexReconstructor::cleanUpVertices (
00267 const vector < TransientVertex > & old ) const
00268 {
00269 vector < TransientVertex > ret;
00270 for ( vector< TransientVertex >::const_iterator i=old.begin(); i!=old.end() ; ++i )
00271 {
00272 if (!(i->hasTrackWeight()))
00273 {
00274 ret.push_back ( *i );
00275 continue;
00276 }
00277
00278
00279
00280 int nsig=0;
00281 TransientVertex::TransientTrackToFloatMap wm = i->weightMap();
00282 for ( TransientVertex::TransientTrackToFloatMap::const_iterator w=wm.begin(); w!=wm.end() ; ++w )
00283 {
00284 if (w->second > theWeightThreshold) nsig++;
00285 }
00286 if ( nsig > 1 ) ret.push_back ( *i );
00287 }
00288
00289 return ret;
00290 }