00001
00015 #include "RecoMuon/CosmicMuonProducer/interface/CosmicMuonSmoother.h"
00016
00017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00018 #include "TrackingTools/KalmanUpdators/interface/KFUpdator.h"
00019 #include "TrackingTools/KalmanUpdators/interface/Chi2MeasurementEstimator.h"
00020 #include "TrackingTools/TrackFitters/interface/TrajectoryStateWithArbitraryError.h"
00021 #include "TrackingTools/TrackFitters/interface/TrajectoryStateCombiner.h"
00022 #include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHit.h"
00023 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00024 #include "DataFormats/GeometrySurface/interface/PlaneBuilder.h"
00025
00026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00027
00028 using namespace edm;
00029 using namespace std;
00030
00031
00032
00033
00034 CosmicMuonSmoother::CosmicMuonSmoother(const ParameterSet& par, const MuonServiceProxy *service) : theService(service) {
00035
00036 theUpdator = new KFUpdator;
00037 theUtilities = new CosmicMuonUtilities;
00038 theEstimator = new Chi2MeasurementEstimator(200.0);
00039 thePropagatorAlongName = par.getParameter<string>("PropagatorAlong");
00040 thePropagatorOppositeName = par.getParameter<string>("PropagatorOpposite");
00041 theErrorRescaling = par.getParameter<double>("RescalingFactor");
00042
00043 category_ = "Muon|RecoMuon|CosmicMuon|CosmicMuonSmoother";
00044 }
00045
00046
00047
00048
00049 CosmicMuonSmoother::~CosmicMuonSmoother() {
00050
00051 if ( theUpdator ) delete theUpdator;
00052 if ( theUtilities ) delete theUtilities;
00053 if ( theEstimator ) delete theEstimator;
00054
00055 }
00056
00057
00058
00059
00060
00061 Trajectory CosmicMuonSmoother::trajectory(const Trajectory& t) const {
00062 std::vector<Trajectory> && fitted = fit(t);
00063 if (fitted.empty()) return Trajectory();
00064 std::vector<Trajectory> && smoothed = smooth(fitted);
00065 return smoothed.empty() ? Trajectory() : smoothed.front();
00066 }
00067
00068
00069
00070
00071 std::vector<Trajectory> CosmicMuonSmoother::trajectories(const TrajectorySeed& seed,
00072 const ConstRecHitContainer& hits,
00073 const TrajectoryStateOnSurface& firstPredTsos) const {
00074
00075 if ( hits.empty() ||!firstPredTsos.isValid() ) return vector<Trajectory>();
00076
00077 LogTrace(category_)<< "trajectory begin (seed hits tsos)";
00078
00079 TrajectoryStateOnSurface firstTsos = firstPredTsos;
00080 firstTsos.rescaleError(theErrorRescaling);
00081
00082 LogTrace(category_)<< "first TSOS: "<<firstTsos;
00083
00084 vector<Trajectory> fitted = fit(seed, hits, firstTsos);
00085 LogTrace(category_)<< "fitted: "<<fitted.size();
00086 vector<Trajectory> smoothed = smooth(fitted);
00087 LogTrace(category_)<< "smoothed: "<<smoothed.size();
00088
00089 return smoothed;
00090
00091 }
00092
00093
00094
00095
00096 vector<Trajectory> CosmicMuonSmoother::fit(const Trajectory& t) const {
00097
00098 if ( t.empty() ) return vector<Trajectory>();
00099
00100 LogTrace(category_)<< "fit begin (trajectory) ";
00101
00102 TrajectoryStateOnSurface firstTsos = initialState(t);
00103 if ( !firstTsos.isValid() ) {
00104 LogTrace(category_)<< "Error: firstTsos invalid. ";
00105 return vector<Trajectory>();
00106 }
00107
00108 LogTrace(category_)<< "firstTsos: "<<firstTsos;
00109
00110 ConstRecHitContainer hits = t.recHits();
00111 LogTrace(category_)<< "hits: "<<hits.size();
00112 LogTrace(category_)<<"hit front" <<hits.front()->globalPosition()<< " hit back"
00113 <<hits.back()->globalPosition();
00114
00115 sortHitsAlongMom(hits, firstTsos);
00116
00117 LogTrace(category_)<<"after sorting hit front" <<hits.front()->globalPosition()<< " hit back"
00118 <<hits.back()->globalPosition();
00119
00120 return fit(t.seed(), hits, firstTsos);
00121
00122 }
00123
00124
00125
00126
00127
00128 vector<Trajectory> CosmicMuonSmoother::fit(const TrajectorySeed& seed,
00129 const ConstRecHitContainer& hits,
00130 const TrajectoryStateOnSurface& firstPredTsos) const {
00131
00132 LogTrace(category_)<< "fit begin (seed, hit, tsos).";
00133
00134 if ( hits.empty() ) {
00135 LogTrace(category_)<< "Error: empty hits container.";
00136 return vector<Trajectory>();
00137 }
00138
00139 Trajectory myTraj(seed, alongMomentum);
00140
00141 TrajectoryStateOnSurface predTsos(firstPredTsos);
00142 LogTrace(category_)<< "first pred TSOS: "<<predTsos;
00143
00144 if ( !predTsos.isValid() ) {
00145 LogTrace(category_)<< "Error: firstTsos invalid.";
00146 return vector<Trajectory>();
00147 }
00148 TrajectoryStateOnSurface currTsos;
00149
00150 if ( hits.front()->isValid() ) {
00151
00152 TransientTrackingRecHit::RecHitPointer preciseHit = hits.front()->clone(predTsos);
00153 LogTrace(category_)<<"first hit is at det "<< hits.front()->det()->surface().position();
00154
00155 currTsos = theUpdator->update(predTsos, *preciseHit);
00156 if (!currTsos.isValid()){
00157 edm::LogWarning(category_)
00158 <<"an updated state is not valid. killing the trajectory.";
00159 return vector<Trajectory>();
00160 }
00161 myTraj.push(TrajectoryMeasurement(predTsos, currTsos, hits.front(),
00162 theEstimator->estimate(predTsos, *hits.front()).second));
00163 if ( currTsos.isValid() ) LogTrace(category_)<< "first curr TSOS: "<<currTsos;
00164
00165 } else {
00166
00167 currTsos = predTsos;
00168 myTraj.push(TrajectoryMeasurement(predTsos, hits.front()));
00169 }
00170
00171
00172 for ( ConstRecHitContainer::const_iterator ihit = hits.begin() + 1;
00173 ihit != hits.end(); ++ihit ) {
00174
00175 if ( !(**ihit).isValid() ) {
00176 LogTrace(category_)<< "Error: invalid hit.";
00177 continue;
00178 }
00179 if (currTsos.isValid()) {
00180 LogTrace(category_)<<"current pos "<<currTsos.globalPosition()
00181 <<"mom "<<currTsos.globalMomentum();
00182 } else {
00183 LogTrace(category_)<<"current state invalid";
00184 }
00185
00186 predTsos = propagatorAlong()->propagate(currTsos, (**ihit).det()->surface());
00187 LogTrace(category_)<<"predicted state propagate directly "<<predTsos.isValid();
00188
00189 if ( !predTsos.isValid() ) {
00190 LogTrace(category_)<<"step-propagating from "<<currTsos.globalPosition() <<" to position: "<<(*ihit)->globalPosition();
00191 predTsos = theUtilities->stepPropagate(currTsos, (*ihit), *propagatorAlong());
00192 }
00193 if ( !predTsos.isValid() && (fabs(theService->magneticField()->inTesla(GlobalPoint(0,0,0)).z()) < 0.01) && (theService->propagator("StraightLinePropagator").isValid() ) ) {
00194 LogTrace(category_)<<"straight-line propagating from "<<currTsos.globalPosition() <<" to position: "<<(*ihit)->globalPosition();
00195 predTsos = theService->propagator("StraightLinePropagator")->propagate(currTsos, (**ihit).det()->surface());
00196 }
00197 if (predTsos.isValid()) {
00198 LogTrace(category_)<<"predicted pos "<<predTsos.globalPosition()
00199 <<"mom "<<predTsos.globalMomentum();
00200 } else {
00201 LogTrace(category_)<<"predicted state invalid";
00202 }
00203 if ( !predTsos.isValid() ) {
00204 LogTrace(category_)<< "Error: predTsos is still invalid forward fit.";
00205
00206 continue;
00207 } else if ( (**ihit).isValid() ) {
00208
00209 TransientTrackingRecHit::RecHitPointer preciseHit = (**ihit).clone(predTsos);
00210
00211 if ( !preciseHit->isValid() ) {
00212 currTsos = predTsos;
00213 myTraj.push(TrajectoryMeasurement(predTsos, *ihit));
00214 } else {
00215 currTsos = theUpdator->update(predTsos, *preciseHit);
00216 if (!currTsos.isValid()){
00217 edm::LogWarning(category_)
00218 <<"an updated state is not valid. killing the trajectory.";
00219 return vector<Trajectory>();
00220 }
00221 myTraj.push(TrajectoryMeasurement(predTsos, currTsos, preciseHit,
00222 theEstimator->estimate(predTsos, *preciseHit).second));
00223 }
00224 } else {
00225 currTsos = predTsos;
00226 myTraj.push(TrajectoryMeasurement(predTsos, *ihit));
00227 }
00228
00229 }
00230
00231 std::vector<TrajectoryMeasurement> mytms = myTraj.measurements();
00232 LogTrace(category_)<<"fit result "<<mytms.size();
00233 for (std::vector<TrajectoryMeasurement>::const_iterator itm = mytms.begin();
00234 itm != mytms.end(); ++itm ) {
00235 LogTrace(category_)<<"updated pos "<<itm->updatedState().globalPosition()
00236 <<"mom "<<itm->updatedState().globalMomentum();
00237 }
00238
00239
00240 return vector<Trajectory>(1, myTraj);
00241
00242 }
00243
00244
00245
00246
00247
00248 vector<Trajectory> CosmicMuonSmoother::smooth(const vector<Trajectory>& tc) const {
00249
00250 vector<Trajectory> result;
00251
00252 for ( vector<Trajectory>::const_iterator it = tc.begin(); it != tc.end(); ++it ) {
00253 vector<Trajectory> smoothed = smooth(*it);
00254 result.insert(result.end(), smoothed.begin(), smoothed.end());
00255 }
00256
00257 return result;
00258
00259 }
00260
00261
00262
00263
00264
00265 vector<Trajectory> CosmicMuonSmoother::smooth(const Trajectory& t) const {
00266
00267 if ( t.empty() ) {
00268 LogTrace(category_)<< "Error: smooth: empty trajectory.";
00269 return vector<Trajectory>();
00270 }
00271
00272 Trajectory myTraj(t.seed(), oppositeToMomentum);
00273
00274 vector<TrajectoryMeasurement> avtm = t.measurements();
00275
00276 if ( avtm.size() < 2 ) {
00277 LogTrace(category_)<< "Error: smooth: too little TM. ";
00278 return vector<Trajectory>();
00279 }
00280
00281 TrajectoryStateOnSurface predTsos = avtm.back().forwardPredictedState();
00282 predTsos.rescaleError(theErrorRescaling);
00283
00284 if ( !predTsos.isValid() ) {
00285 LogTrace(category_)<< "Error: smooth: first TSOS from back invalid. ";
00286 return vector<Trajectory>();
00287 }
00288
00289 TrajectoryStateOnSurface currTsos;
00290
00291
00292 if ( avtm.back().recHit()->isValid() ) {
00293 currTsos = theUpdator->update(predTsos, (*avtm.back().recHit()));
00294 if (!currTsos.isValid()){
00295 edm::LogWarning(category_)
00296 <<"an updated state is not valid. killing the trajectory.";
00297 return vector<Trajectory>();
00298 }
00299 myTraj.push(TrajectoryMeasurement(avtm.back().forwardPredictedState(),
00300 predTsos,
00301 avtm.back().updatedState(),
00302 avtm.back().recHit(),
00303 avtm.back().estimate()
00304 ),
00305 avtm.back().estimate());
00306
00307 } else {
00308 currTsos = predTsos;
00309 myTraj.push(TrajectoryMeasurement(avtm.back().forwardPredictedState(),
00310 avtm.back().recHit()
00311 ));
00312
00313 }
00314
00315 TrajectoryStateCombiner combiner;
00316
00317
00318 for ( vector<TrajectoryMeasurement>::reverse_iterator itm = avtm.rbegin() + 1;
00319 itm != avtm.rend() - 1; ++itm ) {
00320
00321 if (currTsos.isValid()) {
00322 LogTrace(category_)<<"current pos "<<currTsos.globalPosition()
00323 <<"mom "<<currTsos.globalMomentum();
00324 } else {
00325 LogTrace(category_)<<"current state invalid";
00326 }
00327
00328 predTsos = propagatorOpposite()->propagate(currTsos,(*itm).recHit()->det()->surface());
00329
00330 if ( !predTsos.isValid() ) {
00331 LogTrace(category_)<<"step-propagating from "<<currTsos.globalPosition() <<" to position: "<<(*itm).recHit()->globalPosition();
00332 predTsos = theUtilities->stepPropagate(currTsos, (*itm).recHit(), *propagatorOpposite());
00333 }
00334 if (predTsos.isValid()) {
00335 LogTrace(category_)<<"predicted pos "<<predTsos.globalPosition()
00336 <<"mom "<<predTsos.globalMomentum();
00337 } else {
00338 LogTrace(category_)<<"predicted state invalid";
00339 }
00340
00341 if ( !predTsos.isValid() ) {
00342 LogTrace(category_)<< "Error: predTsos is still invalid backward smooth.";
00343 return vector<Trajectory>();
00344
00345 } else if ( (*itm).recHit()->isValid() ) {
00346
00347 currTsos = theUpdator->update(predTsos, (*(*itm).recHit()));
00348 if (!currTsos.isValid()){
00349 edm::LogWarning(category_)
00350 <<"an updated state is not valid. killing the trajectory.";
00351 return vector<Trajectory>();
00352 }
00353 TrajectoryStateOnSurface combTsos = combiner(predTsos, (*itm).forwardPredictedState());
00354 if ( !combTsos.isValid() ) {
00355 LogTrace(category_)<< "Error: smooth: combining pred TSOS failed. ";
00356 return vector<Trajectory>();
00357 }
00358
00359 TrajectoryStateOnSurface smooTsos = combiner((*itm).updatedState(), predTsos);
00360
00361 if ( !smooTsos.isValid() ) {
00362 LogTrace(category_)<< "Error: smooth: combining smooth TSOS failed. ";
00363 return vector<Trajectory>();
00364 }
00365
00366 myTraj.push(TrajectoryMeasurement((*itm).forwardPredictedState(),
00367 predTsos,
00368 smooTsos,
00369 (*itm).recHit(),
00370 theEstimator->estimate(combTsos, (*(*itm).recHit())).second
00371 ),
00372 (*itm).estimate());
00373 } else {
00374 currTsos = predTsos;
00375 TrajectoryStateOnSurface combTsos = combiner(predTsos, (*itm).forwardPredictedState());
00376
00377 if ( !combTsos.isValid() ) {
00378 LogTrace(category_)<< "Error: smooth: combining TSOS failed. ";
00379 return vector<Trajectory>();
00380 }
00381
00382 myTraj.push(TrajectoryMeasurement((*itm).forwardPredictedState(),
00383 predTsos,
00384 combTsos,
00385 (*itm).recHit()
00386 ));
00387 }
00388 }
00389
00390
00391 predTsos = propagatorOpposite()->propagate(currTsos, avtm.front().recHit()->det()->surface());
00392
00393 if ( !predTsos.isValid() ){
00394 LogTrace(category_)<< "Error: last predict TSOS failed, use original one. ";
00395
00396 myTraj.push(TrajectoryMeasurement(avtm.front().forwardPredictedState(),
00397 avtm.front().recHit()));
00398 } else {
00399 if ( avtm.front().recHit()->isValid() ) {
00400
00401 currTsos = theUpdator->update(predTsos, (*avtm.front().recHit()));
00402 if (currTsos.isValid())
00403 myTraj.push(TrajectoryMeasurement(avtm.front().forwardPredictedState(),
00404 predTsos,
00405 currTsos,
00406 avtm.front().recHit(),
00407 theEstimator->estimate(predTsos, (*avtm.front().recHit())).second
00408 ),
00409 avtm.front().estimate());
00410 }
00411 }
00412 LogTrace(category_)<< "myTraj foundHits. "<<myTraj.foundHits();
00413
00414 if (myTraj.foundHits() >= 3)
00415 return vector<Trajectory>(1, myTraj);
00416 else {
00417 LogTrace(category_)<< "Error: smooth: No enough hits in trajctory. ";
00418 return vector<Trajectory>();
00419 }
00420
00421 }
00422
00423 TrajectoryStateOnSurface CosmicMuonSmoother::initialState(const Trajectory& t) const {
00424 if ( t.empty() ) return TrajectoryStateOnSurface();
00425
00426 if ( !t.firstMeasurement().updatedState().isValid() || !t.lastMeasurement().updatedState().isValid() ) return TrajectoryStateOnSurface();
00427
00428 TrajectoryStateOnSurface result;
00429
00430 bool beamhaloFlag = ( t.firstMeasurement().updatedState().globalMomentum().eta() > 4.0 || t.lastMeasurement().updatedState().globalMomentum().eta() > 4.0 );
00431
00432 if ( !beamhaloFlag ) {
00433 if (t.firstMeasurement().updatedState().globalPosition().y() > t.lastMeasurement().updatedState().globalPosition().y()) {
00434 result = t.firstMeasurement().updatedState();
00435 } else {
00436 result = t.lastMeasurement().updatedState();
00437 }
00438 if (result.globalMomentum().y()> 1.0 )
00439 theUtilities->reverseDirection(result,&*theService->magneticField());
00440 } else {
00441 if ( t.firstMeasurement().updatedState().globalPosition().z() * t.lastMeasurement().updatedState().globalPosition().z() >0 ) {
00442 if ( fabs(t.firstMeasurement().updatedState().globalPosition().z()) > fabs(t.lastMeasurement().updatedState().globalPosition().z()) ) {
00443 result = t.firstMeasurement().updatedState();
00444 } else {
00445 result = t.lastMeasurement().updatedState();
00446 }
00447 } else {
00448
00449 if ( fabs(t.firstMeasurement().updatedState().globalPosition().eta()) > fabs(t.lastMeasurement().updatedState().globalPosition().eta()) ) {
00450 result = t.firstMeasurement().updatedState();
00451 } else {
00452 result = t.lastMeasurement().updatedState();
00453 }
00454 }
00455
00456 }
00457
00458 return result;
00459
00460 }
00461
00462 void CosmicMuonSmoother::sortHitsAlongMom(ConstRecHitContainer& hits, const TrajectoryStateOnSurface& tsos) const {
00463
00464 if (hits.size() < 2) return;
00465 float dis1 = (hits.front()->globalPosition() - tsos.globalPosition()).mag();
00466 float dis2 = (hits.back()->globalPosition() - tsos.globalPosition()).mag();
00467
00468 if ( dis1 > dis2 )
00469 std::reverse(hits.begin(),hits.end());
00470
00471 return;
00472 }
00473