CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/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 ")) 
00162             << theDirection <<"\n";
00163           hits.push_back(hitA);
00164           hits.push_back(hitB);
00165         }         
00166       }else if(typeid(*(itm->recHit()->hit())) == typeid(ProjectedSiStripRecHit2D)){
00167         //hits.push_back(itm->recHit()->transientHits()[0]);    //Use 2D SiStripRecHit
00168         if(!itm->recHit()->transientHits()[0]->detUnit()->type().isEndcap()){
00169           hits.push_back(itm->recHit()->transientHits()[0]->transientHits()[0]);        //Use 1D SiStripRecHit
00170         }else{
00171           hits.push_back(itm->recHit()->transientHits()[0]);    //Use 2D SiStripRecHit
00172         }
00173         // ===================================================================================  
00174       }else if(typeid(*(itm->recHit()->hit())) == typeid(SiStripRecHit2D)){
00175         //hits.push_back(itm->recHit());  //Use 2D SiStripRecHit
00176         if(!itm->recHit()->detUnit()->type().isEndcap()){
00177           hits.push_back(itm->recHit()->transientHits()[0]); //Use 1D SiStripRecHit
00178         }else{
00179           hits.push_back(itm->recHit());  //Use 2D SiStripRecHit
00180         }
00181       }else{
00182         hits.push_back(itm->recHit());
00183       }
00184     }//end loop on measurements
00185   }
00186 }
00187 
00188 void Trajectory::validRecHits(ConstRecHitContainer & hits) const {
00189   hits.reserve(foundHits());
00190   for (Trajectory::DataContainer::const_iterator itm
00191          = theData.begin(); itm != theData.end(); itm++)
00192     if ((*itm).recHit()->isValid()) hits.push_back((*itm).recHit());
00193 }
00194 
00195 
00196 PropagationDirection const & Trajectory::direction() const {
00197   if (theDirectionValidity) return theDirection;
00198   else throw cms::Exception("TrackingTools/PatternTools","Trajectory::direction() requested but not set");
00199 }
00200 
00201 void Trajectory::check() const {
00202   if ( theData.empty()) 
00203     throw cms::Exception("TrackingTools/PatternTools","Trajectory::check() - information requested from empty Trajectory");
00204 }
00205 
00206 bool Trajectory::lost( const TransientTrackingRecHit& hit)
00207 {
00208   if ( hit.isValid()) return false;
00209   else {
00210   //     // A DetLayer is always inactive in this logic.
00211   //     // The DetLayer is the Det of an invalid RecHit only if no DetUnit 
00212   //     // is compatible with the predicted state, so we don't really expect
00213   //     // a hit in this case.
00214   
00215     if(hit.geographicalId().rawId() == 0) {return false;}
00216     else{
00217       return hit.getType() == TrackingRecHit::missing;
00218     }
00219   }
00220 }
00221 
00222 bool Trajectory::isBad( const TransientTrackingRecHit& hit)
00223 {
00224   if ( hit.isValid()) return false;
00225   else {
00226     if(hit.geographicalId().rawId() == 0) {return false;}
00227     else{
00228       return hit.getType() == TrackingRecHit::bad;
00229     }
00230   }
00231 }
00232 
00233 TrajectoryStateOnSurface Trajectory::geometricalInnermostState() const {
00234 
00235   check();
00236 
00237   //if trajectory is in one half, return the end closer to origin point
00238   if ( firstMeasurement().updatedState().globalMomentum().perp() > 1.0
00239       && ( firstMeasurement().updatedState().globalPosition().basicVector().dot( firstMeasurement().updatedState().globalMomentum().basicVector() ) *
00240        lastMeasurement().updatedState().globalPosition().basicVector().dot( lastMeasurement().updatedState().globalMomentum().basicVector() )  > 0 ) ) {
00241      return (firstMeasurement().updatedState().globalPosition().mag() < lastMeasurement().updatedState().globalPosition().mag() ) ?
00242             firstMeasurement().updatedState() : lastMeasurement().updatedState();
00243   }
00244 
00245   //more complicated in case of traversing and low-pt trajectories with loops
00246   return closestMeasurement(GlobalPoint(0.0,0.0,0.0)).updatedState();
00247 
00248 }
00249 
00250 
00251 namespace {
00253   struct LessMag {
00254     LessMag(GlobalPoint point) : thePoint(point) {}
00255     bool operator()(const TrajectoryMeasurement& lhs,
00256                     const TrajectoryMeasurement& rhs) const{ 
00257       if (lhs.updatedState().isValid() && rhs.updatedState().isValid())
00258         return (lhs.updatedState().globalPosition() - thePoint).mag2() < (rhs.updatedState().globalPosition() -thePoint).mag2();
00259       else
00260         {
00261           edm::LogError("InvalidStateOnMeasurement")<<"an updated state is not valid. result of LessMag comparator will be wrong.";
00262           return false;
00263         }
00264     }
00265     GlobalPoint thePoint;
00266   };
00267 
00268 }
00269 
00270 TrajectoryMeasurement const & Trajectory::closestMeasurement(GlobalPoint point) const {
00271   check();
00272   vector<TrajectoryMeasurement>::const_iterator iter = std::min_element(measurements().begin(), measurements().end(), LessMag(point) );
00273 
00274   return (*iter);
00275 }
00276 
00277 void Trajectory::reverse() {
00278     // reverse the direction (without changing it if it's not along or opposite)
00279     if (theDirection == alongMomentum)           theDirection = oppositeToMomentum;
00280     else if (theDirection == oppositeToMomentum) theDirection = alongMomentum;
00281     // reverse the order of the hits
00282     std::reverse(theData.begin(), theData.end());
00283 }