CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/RecoMuon/CosmicMuonProducer/src/CosmicMuonSmoother.cc

Go to the documentation of this file.
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 // constructor
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 // destructor
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 // fit and smooth trajectory
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 // fit and smooth trajectory 
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 // fit trajectory
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 // fit trajectory
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   //const TransientTrackingRecHit& firsthit = *hits.front();
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 //      return vector<Trajectory>();
00205       continue;
00206     } else if ( (**ihit).isValid() ) {
00207       // update
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 // smooth trajectory
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 // smooth trajectory
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   // first smoothed TrajectoryMeasurement is last fitted
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                    /*avtm.back().layer()*/), 
00304                 avtm.back().estimate());
00305 
00306   } else {
00307     currTsos = predTsos;
00308     myTraj.push(TrajectoryMeasurement(avtm.back().forwardPredictedState(),
00309                    avtm.back().recHit()//,
00310                    /*avtm.back().layer()*/));
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     //  continue;
00344     } else if ( (*itm).recHit()->isValid() ) {
00345       //update
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                      /*(*itm).layer()*/),
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                      /*(*itm).layer()*/));
00386     }
00387   }
00388 
00389   // last smoothed TrajectoryMeasurement is last filtered
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  //    return vector<Trajectory>();
00395       myTraj.push(TrajectoryMeasurement(avtm.front().forwardPredictedState(),
00396                    avtm.front().recHit()));
00397   } else  {
00398     if ( avtm.front().recHit()->isValid() ) {
00399       //update
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                    /*avtm.front().layer()*/),
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 ) { //initialState is the top one
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 ) //top tsos should pointing down
00438        theUtilities->reverseDirection(result,&*theService->magneticField());
00439   } else {
00440      if ( t.firstMeasurement().updatedState().globalPosition().z() * t.lastMeasurement().updatedState().globalPosition().z() >0 ) { //same side
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 { //different sides
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