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