CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/TrackingTools/PatternTools/src/Trajectory.cc

Go to the documentation of this file.
00001 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00002 #include "boost/intrusive_ptr.hpp" 
00003 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h" 
00004 #include "FWCore/Utilities/interface/Exception.h"
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006 
00007 #include "DataFormats/TrackerRecHit2D/interface/SiStripMatchedRecHit2D.h"
00008 #include "DataFormats/TrackerRecHit2D/interface/ProjectedSiStripRecHit2D.h"
00009 #include <Geometry/CommonDetUnit/interface/GeomDetUnit.h>
00010 #include <Geometry/CommonDetUnit/interface/GeomDetType.h>
00011 
00012 
00013 #include <algorithm>
00014 
00015 using namespace std;
00016 
00017 void Trajectory::pop() {
00018   if (!empty()) {
00019     if(theData.back().recHit()->isValid()) {
00020       theNumberOfFoundHits--;
00021       theChiSquared -= theData.back().estimate();
00022     }
00023     else if(lost(* (theData.back().recHit()) )) {
00024       theNumberOfLostHits--;
00025     }
00026     else if(isBad(* (theData.back().recHit()) ) && theData.back().recHit()->geographicalId().det()==DetId::Muon ) {
00027       theChiSquaredBad -= theData.back().estimate();
00028     }
00029 
00030     theData.pop_back();
00031   }
00032 }
00033 
00034 
00035 void Trajectory::push( const TrajectoryMeasurement& tm) {
00036   push( tm, tm.estimate());
00037 }
00038 
00039 void Trajectory::push( const TrajectoryMeasurement& tm, double chi2Increment)
00040 {
00041   theData.push_back(tm);
00042   if ( tm.recHit()->isValid()) {
00043     theChiSquared += chi2Increment;
00044     theNumberOfFoundHits++;
00045   }
00046   // else if (lost( tm.recHit()) && !inactive(tm.recHit().det())) theNumberOfLostHits++;
00047   else if (lost( *(tm.recHit()) ) ) {
00048     theNumberOfLostHits++;
00049   }
00050  
00051   else if (isBad( *(tm.recHit()) ) && tm.recHit()->geographicalId().det()==DetId::Muon ) {
00052     theChiSquaredBad += chi2Increment;
00053   }
00054  
00055   // in case of a Trajectory constructed without direction, 
00056   // determine direction from the radii of the first two measurements
00057 
00058   if ( !theDirectionValidity && theData.size() >= 2) {
00059     if (theData[0].updatedState().globalPosition().perp() <
00060         theData.back().updatedState().globalPosition().perp())
00061       theDirection = alongMomentum;
00062     else theDirection = oppositeToMomentum;
00063     theDirectionValidity = true;
00064   }
00065 }
00066 
00067 Trajectory::RecHitContainer Trajectory::recHits(bool splitting) const {
00068   RecHitContainer hits;
00069   recHitsV(hits,splitting);
00070   return hits;
00071 }
00072 
00073 
00074 int Trajectory::ndof(bool bon) const {
00075   const Trajectory::RecHitContainer transRecHits = recHits();
00076   
00077   int dof = 0;
00078   int dofBad = 0;
00079   
00080   for(Trajectory::RecHitContainer::const_iterator rechit = transRecHits.begin();
00081       rechit != transRecHits.end(); ++rechit) {
00082     if((*rechit)->isValid())
00083       dof += (*rechit)->dimension();
00084     else if( isBad(**rechit) && (*rechit)->geographicalId().det()==DetId::Muon )
00085       dofBad += (*rechit)->dimension();
00086   }
00087 
00088   // If dof!=0 (there is at least 1 valid hit),
00089   //    return ndof=ndof(fit)
00090   // If dof=0 (all rec hits are invalid, only for STA trajectories),
00091   //    return ndof=ndof(invalid hits)
00092   if(dof) {
00093     int constr = bon ? 5 : 4;
00094     return std::max(dof - constr, 0);
00095   }
00096   else {
00097     // A STA can have < 5 (invalid) hits
00098     // if this is the case ==> ndof = 1
00099     // (to avoid divisions by 0)
00100     int constr = bon ? 5 : 4;
00101     return std::max(dofBad - constr, 1);
00102   }
00103 }
00104 
00105 
00106 
00107 void Trajectory::recHitsV(ConstRecHitContainer & hits,bool splitting) const {
00108   hits.reserve(theData.size());
00109   if(!splitting){  
00110     for (Trajectory::DataContainer::const_iterator itm
00111            = theData.begin(); itm != theData.end(); itm++){    
00112       hits.push_back((*itm).recHit());
00113     }
00114   }else{    
00115     for (Trajectory::DataContainer::const_iterator itm
00116            = theData.begin(); itm != theData.end(); itm++){    
00117 
00118       // ====== WARNING: this is a temporary solution =========
00119       //        all this part of code should be implemented internally 
00120       //        in the TrackingRecHit classes. The concrete types of rechit 
00121       //        should be transparent to the Trajectory class
00122 
00123       if( typeid(*(itm->recHit()->hit())) == typeid(SiStripMatchedRecHit2D)){
00124         LocalPoint firstLocalPos = 
00125           itm->updatedState().surface().toLocal(itm->recHit()->transientHits()[0]->globalPosition());
00126         
00127         LocalPoint secondLocalPos = 
00128           itm->updatedState().surface().toLocal(itm->recHit()->transientHits()[1]->globalPosition());
00129         
00130         LocalVector Delta = secondLocalPos - firstLocalPos;
00131         float scalar  = Delta.z() * (itm->updatedState().localDirection().z());
00132         
00133 
00134         TransientTrackingRecHit::ConstRecHitPointer hitA, hitB;
00135 
00136         // Get 2D strip Hits from a matched Hit.
00137         //hitA = itm->recHit()->transientHits()[0];
00138         //hitB = itm->recHit()->transientHits()[1];
00139 
00140         // Get 2D strip Hits from a matched Hit. Then get the 1D hit from the 2D hit
00141         if(!itm->recHit()->transientHits()[0]->detUnit()->type().isEndcap()){
00142           hitA = itm->recHit()->transientHits()[0]->transientHits()[0];
00143           hitB = itm->recHit()->transientHits()[1]->transientHits()[0];
00144         }else{ //don't use 1D hit in the endcap yet
00145           hitA = itm->recHit()->transientHits()[0];
00146           hitB = itm->recHit()->transientHits()[1];
00147         }
00148 
00149         if( (scalar>=0 && direction()==alongMomentum) ||
00150             (scalar<0 && direction()==oppositeToMomentum)){
00151           hits.push_back(hitA);
00152           hits.push_back(hitB);
00153         }else if( (scalar>=0 && direction()== oppositeToMomentum) ||
00154                   (scalar<0 && direction()== alongMomentum)){
00155           hits.push_back(hitB);
00156           hits.push_back(hitA);
00157         }else {
00158           //throw cms::Exception("Error in Trajectory::recHitsV(). Direction is not defined");  
00159           edm::LogError("Trajectory_recHitsV_UndefinedTrackDirection") << 
00160                 "Error in Trajectory::recHitsV: scalar = " << scalar << 
00161                 ", direction = " << (direction()==alongMomentum ? "along" : (direction()==oppositeToMomentum ? "opposite" : "undefined")) << "\n";
00162           hits.push_back(hitA);
00163           hits.push_back(hitB);
00164         }         
00165       }else if(typeid(*(itm->recHit()->hit())) == typeid(ProjectedSiStripRecHit2D)){
00166         //hits.push_back(itm->recHit()->transientHits()[0]);    //Use 2D SiStripRecHit
00167         if(!itm->recHit()->transientHits()[0]->detUnit()->type().isEndcap()){
00168           hits.push_back(itm->recHit()->transientHits()[0]->transientHits()[0]);        //Use 1D SiStripRecHit
00169         }else{
00170           hits.push_back(itm->recHit()->transientHits()[0]);    //Use 2D SiStripRecHit
00171         }
00172         // ===================================================================================  
00173       }else if(typeid(*(itm->recHit()->hit())) == typeid(SiStripRecHit2D)){
00174         //hits.push_back(itm->recHit());  //Use 2D SiStripRecHit
00175         if(!itm->recHit()->detUnit()->type().isEndcap()){
00176           hits.push_back(itm->recHit()->transientHits()[0]); //Use 1D SiStripRecHit
00177         }else{
00178           hits.push_back(itm->recHit());  //Use 2D SiStripRecHit
00179         }
00180       }else{
00181         hits.push_back(itm->recHit());
00182       }
00183     }//end loop on measurements
00184   }
00185 }
00186 
00187 void Trajectory::validRecHits(ConstRecHitContainer & hits) const {
00188   hits.reserve(foundHits());
00189   for (Trajectory::DataContainer::const_iterator itm
00190          = theData.begin(); itm != theData.end(); itm++)
00191     if ((*itm).recHit()->isValid()) hits.push_back((*itm).recHit());
00192 }
00193 
00194 
00195 PropagationDirection const & Trajectory::direction() const {
00196   if (theDirectionValidity) return theDirection;
00197   else throw cms::Exception("TrackingTools/PatternTools","Trajectory::direction() requested but not set");
00198 }
00199 
00200 void Trajectory::check() const {
00201   if ( theData.empty()) 
00202     throw cms::Exception("TrackingTools/PatternTools","Trajectory::check() - information requested from empty Trajectory");
00203 }
00204 
00205 bool Trajectory::lost( const TransientTrackingRecHit& hit)
00206 {
00207   if ( hit.isValid()) return false;
00208   else {
00209   //     // A DetLayer is always inactive in this logic.
00210   //     // The DetLayer is the Det of an invalid RecHit only if no DetUnit 
00211   //     // is compatible with the predicted state, so we don't really expect
00212   //     // a hit in this case.
00213   
00214     if(hit.geographicalId().rawId() == 0) {return false;}
00215     else{
00216       return hit.getType() == TrackingRecHit::missing;
00217     }
00218   }
00219 }
00220 
00221 bool Trajectory::isBad( const TransientTrackingRecHit& hit)
00222 {
00223   if ( hit.isValid()) return false;
00224   else {
00225     if(hit.geographicalId().rawId() == 0) {return false;}
00226     else{
00227       return hit.getType() == TrackingRecHit::bad;
00228     }
00229   }
00230 }
00231 
00232 TrajectoryStateOnSurface Trajectory::geometricalInnermostState() const {
00233 
00234   check();
00235 
00236   //if trajectory is in one half, return the end closer to origin point
00237   if ( firstMeasurement().updatedState().globalMomentum().perp() > 1.0
00238       && ( firstMeasurement().updatedState().globalPosition().basicVector().dot( firstMeasurement().updatedState().globalMomentum().basicVector() ) *
00239        lastMeasurement().updatedState().globalPosition().basicVector().dot( lastMeasurement().updatedState().globalMomentum().basicVector() )  > 0 ) ) {
00240      return (firstMeasurement().updatedState().globalPosition().mag() < lastMeasurement().updatedState().globalPosition().mag() ) ?
00241             firstMeasurement().updatedState() : lastMeasurement().updatedState();
00242   }
00243 
00244   //more complicated in case of traversing and low-pt trajectories with loops
00245   return closestMeasurement(GlobalPoint(0.0,0.0,0.0)).updatedState();
00246 
00247 }
00248 
00249 
00250 namespace {
00252   struct LessMag {
00253     LessMag(GlobalPoint point) : thePoint(point) {}
00254     bool operator()(const TrajectoryMeasurement& lhs,
00255                     const TrajectoryMeasurement& rhs) const{ 
00256       if (lhs.updatedState().isValid() && rhs.updatedState().isValid())
00257         return (lhs.updatedState().globalPosition() - thePoint).mag2() < (rhs.updatedState().globalPosition() -thePoint).mag2();
00258       else
00259         {
00260           edm::LogError("InvalidStateOnMeasurement")<<"an updated state is not valid. result of LessMag comparator will be wrong.";
00261           return false;
00262         }
00263     }
00264     GlobalPoint thePoint;
00265   };
00266 
00267 }
00268 
00269 TrajectoryMeasurement const & Trajectory::closestMeasurement(GlobalPoint point) const {
00270   check();
00271   vector<TrajectoryMeasurement>::const_iterator iter = std::min_element(measurements().begin(), measurements().end(), LessMag(point) );
00272 
00273   return (*iter);
00274 }
00275 
00276 void Trajectory::reverse() {
00277     // reverse the direction (without changing it if it's not along or opposite)
00278     if (theDirection == alongMomentum)           theDirection = oppositeToMomentum;
00279     else if (theDirection == oppositeToMomentum) theDirection = alongMomentum;
00280     // reverse the order of the hits
00281     std::reverse(theData.begin(), theData.end());
00282 }