CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/TrackingTools/TrackAssociator/src/CachedTrajectory.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    TrackAssociator
00004 // Class:      CachedTrajectory
00005 // 
00006 // $Id: CachedTrajectory.cc,v 1.24 2010/10/03 17:25:10 elmer Exp $
00007 //
00008 //
00009 
00010 #include "TrackingTools/TrackAssociator/interface/CachedTrajectory.h"
00011 // #include "Utilities/Timing/interface/TimerStack.h"
00012 #include "TrackPropagation/SteppingHelixPropagator/interface/SteppingHelixPropagator.h"
00013 #include "DataFormats/GeometrySurface/interface/Plane.h"
00014 #include "Geometry/DTGeometry/interface/DTChamber.h"
00015 #include "Geometry/CSCGeometry/interface/CSCChamber.h"
00016 #include <deque>
00017 #include <algorithm>
00018 
00019 CachedTrajectory::CachedTrajectory():propagator_(0){
00020    reset_trajectory();
00021    setMaxDetectorRadius();
00022    setMaxDetectorLength();
00023    setMinDetectorRadius();
00024    setMinDetectorLength();
00025    setPropagationStep();
00026 }
00027 
00028 void CachedTrajectory::propagateForward(SteppingHelixStateInfo& state, float distance)
00029 {
00030    // defined a normal plane wrt the particle trajectory direction
00031    // let's hope that I computed the rotation matrix correctly.
00032    GlobalVector vector(state.momentum().unit());
00033    float r21 = 0;
00034    float r22 = vector.z()/sqrt(1-pow(vector.x(),2));
00035    float r23 = -vector.y()/sqrt(1-pow(vector.x(),2));
00036    float r31 = vector.x();
00037    float r32 = vector.y();
00038    float r33 = vector.z();
00039    float r11 = r22*r33-r23*r32;
00040    float r12 = r23*r31;
00041    float r13 = -r22*r31;
00042    
00043    Surface::RotationType rotation(r11, r12, r13,
00044                                   r21, r22, r23,
00045                                   r31, r32, r33);
00046    Plane::PlanePointer target = Plane::build(state.position()+vector*distance, rotation);
00047    propagate(state, *target);
00048 }
00049 
00050 void CachedTrajectory::propagate(SteppingHelixStateInfo& state, const Plane& plane)
00051 {
00052    if( const SteppingHelixPropagator* shp = dynamic_cast<const SteppingHelixPropagator*>(propagator_) )
00053      {
00054         try {
00055            state = shp->propagate(state, plane);
00056         }
00057         catch(cms::Exception &ex){
00058            edm::LogWarning("TrackAssociator") << 
00059                 "Caught exception " << ex.category() << ": " << ex.explainSelf();
00060            edm::LogWarning("TrackAssociator") << "An exception is caught during the track propagation\n"
00061              << state.momentum().x() << ", " << state.momentum().y() << ", " << state.momentum().z();
00062            state = SteppingHelixStateInfo();
00063         }
00064      }
00065    else
00066      {
00067         FreeTrajectoryState fts;
00068         state.getFreeState( fts );
00069         TrajectoryStateOnSurface stateOnSurface = propagator_->propagate(fts, plane);
00070         state = SteppingHelixStateInfo( *(stateOnSurface.freeState()) );
00071      }
00072 }
00073 
00074 void CachedTrajectory::propagate(SteppingHelixStateInfo& state, const Cylinder& cylinder)
00075 {
00076    if( const SteppingHelixPropagator* shp = dynamic_cast<const SteppingHelixPropagator*>(propagator_) )
00077      {
00078         try {
00079            state = shp->propagate(state, cylinder);
00080         }
00081         catch(cms::Exception &ex){
00082            edm::LogWarning("TrackAssociator") << 
00083                 "Caught exception " << ex.category() << ": " << ex.explainSelf();
00084            edm::LogWarning("TrackAssociator") << "An exception is caught during the track propagation\n"
00085              << state.momentum().x() << ", " << state.momentum().y() << ", " << state.momentum().z();
00086            state = SteppingHelixStateInfo();
00087         }
00088      }
00089    else
00090      {
00091         FreeTrajectoryState fts;
00092         state.getFreeState( fts );
00093         TrajectoryStateOnSurface stateOnSurface = propagator_->propagate(fts, cylinder);
00094         state = SteppingHelixStateInfo( *(stateOnSurface.freeState()) );
00095      }
00096 }
00097 
00098 bool CachedTrajectory::propagateAll(const SteppingHelixStateInfo& initialState)
00099 {
00100    if ( fullTrajectoryFilled_ ) {
00101       edm::LogWarning("TrackAssociator") << "Reseting all trajectories. Please call reset_trajectory() explicitely to avoid this message";
00102       reset_trajectory();
00103    }
00104         
00105 //   TimerStack timers(TimerStack::Disableable);
00106 
00107    reset_trajectory();
00108    if (propagator_==0) throw cms::Exception("FatalError") << "Track propagator is not defined\n";
00109    SteppingHelixStateInfo currentState(initialState);
00110    fullTrajectory_.push_back(currentState);
00111 
00112    while (currentState.position().perp()<maxRho_ && fabs(currentState.position().z())<maxZ_ ){
00113       LogTrace("TrackAssociator") << "[propagateAll] Propagate outward from (rho, r, z, phi) (" << 
00114         currentState.position().perp() << ", " << currentState.position().mag() << ", " <<
00115         currentState.position().z() << ", " << currentState.position().phi() << ")";
00116       propagateForward(currentState,step_);
00117      if (! currentState.isValid() ) {
00118        LogTrace("TrackAssociator") << "Failed to propagate the track; moving on\n";
00119        break;
00120      }
00121       LogTrace("TrackAssociator") << "\treached (rho, r, z, phi) (" << 
00122         currentState.position().perp() << ", " << currentState.position().mag() << ", " <<
00123         currentState.position().z() << ", " << currentState.position().phi() << ")";
00124      fullTrajectory_.push_back(currentState);
00125    }
00126 
00127 
00128    SteppingHelixStateInfo currentState2(initialState);
00129    SteppingHelixStateInfo previousState;
00130    while (currentState2.position().perp()>minRho_ || fabs(currentState2.position().z())>minZ_) {
00131       previousState=currentState2;
00132       propagateForward(currentState2,-step_);
00133       if (! currentState2.isValid() ) {
00134          LogTrace("TrackAssociator") << "Failed to propagate the track; moving on\n";
00135          break;
00136       }
00137       if(previousState.position().perp()- currentState2.position().perp() < 0) { 
00138          LogTrace("TrackAssociator") << "Error: TrackAssociator has propogated the particle past the point of closest approach to IP" << std::endl;
00139          break;
00140       }
00141       LogTrace("TrackAssociator") << "[propagateAll] Propagated inward from (rho, r, z, phi) (" << 
00142         previousState.position().perp() << ", " << previousState.position().mag() << ", " <<
00143         previousState.position().z() << "," << previousState.position().phi() << ") to (" << 
00144         currentState2.position().perp() << ", " << currentState2.position().mag() << ", " <<
00145         currentState2.position().z() << ", " << currentState2.position().phi() << ")";
00146       fullTrajectory_.push_front(currentState2);
00147    }
00148 
00149 
00150 
00151 
00152    // LogTrace("TrackAssociator") << "fullTrajectory_ has " << fullTrajectory_.size() << " states with (R, z):\n";
00153    // for(unsigned int i=0; i<fullTrajectory_.size(); i++) {
00154    //  LogTrace("TrackAssociator") << "state " << i << ": (" << fullTrajectory_[i].position().perp() << ", "
00155    //    << fullTrajectory_[i].position().z() << ")\n";
00156    // }
00157 
00158 
00159 
00160 
00161 
00162    LogTrace("TrackAssociator") << "Done with the track propagation in the detector. Number of steps: " << fullTrajectory_.size();
00163    fullTrajectoryFilled_ = true;
00164    return ! fullTrajectory_.empty();
00165 }
00166 
00167 TrajectoryStateOnSurface CachedTrajectory::propagate(const Plane* plane)
00168 {
00169    // TimerStack timers(TimerStack::Disableable);
00170    // timers.benchmark("CachedTrajectory::propagate::benchmark");
00171    // timers.push("CachedTrajectory::propagate",TimerStack::FastMonitoring);
00172    // timers.push("CachedTrajectory::propagate::findClosestPoint",TimerStack::FastMonitoring);
00173 
00174    // Assume that all points along the trajectory are equally spread out.
00175    // For simplication assume that the trajectory is just a straight
00176    // line and find a point closest to the target plane. Propagate to
00177    // the plane from the point.
00178    
00179    const float matchingDistance = 1;
00180    // find the closest point to the plane
00181    int leftIndex = 0;
00182    int rightIndex = fullTrajectory_.size()-1;
00183    int closestPointOnLeft = 0;
00184    
00185    // check whether the trajectory crossed the plane (signs should be different)
00186    if ( sign( distance(plane, leftIndex) ) * sign( distance(plane, rightIndex) ) != -1 ) {
00187       LogTrace("TrackAssociator") << "Track didn't cross the plane:\n\tleft distance: "<<distance(plane, leftIndex)
00188         <<"\n\tright distance: " << distance(plane, rightIndex);
00189      return TrajectoryStateOnSurface();
00190    }
00191    
00192    while (leftIndex + 1 < rightIndex) {
00193       closestPointOnLeft = int((leftIndex+rightIndex)/2);
00194       float dist = distance(plane,closestPointOnLeft);
00195       // LogTrace("TrackAssociator") << "Closest point on left: " << closestPointOnLeft << "\n"
00196       //    << "Distance to the plane: " << dist;
00197       if (fabs(dist)<matchingDistance) {
00198          // found close match, verify that we are on the left side
00199          if (closestPointOnLeft>0 && sign( distance(plane, closestPointOnLeft-1) ) * dist == -1)
00200            closestPointOnLeft--;
00201          break; 
00202       }
00203       
00204       // check where is the plane
00205       if (sign( distance(plane, leftIndex) * dist ) == -1)
00206         rightIndex = closestPointOnLeft;
00207       else
00208         leftIndex = closestPointOnLeft;
00209       
00210       // LogTrace("TrackAssociator") << "Distance on left: " << distance(plane, leftIndex) << "\n"
00211       //        << "Distance to closest point: " <<  distance(plane, closestPointOnLeft) << "\n"
00212       //        << "Left index: " << leftIndex << "\n"
00213       //        << "Right index: " << rightIndex;
00214       
00215    }
00216       LogTrace("TrackAssociator") << "closestPointOnLeft: " << closestPointOnLeft 
00217         << "\n\ttrajectory point (z,R,eta,phi): " 
00218         << fullTrajectory_[closestPointOnLeft].position().z() << ", "
00219         << fullTrajectory_[closestPointOnLeft].position().perp() << " , "       
00220         << fullTrajectory_[closestPointOnLeft].position().eta() << " , " 
00221         << fullTrajectory_[closestPointOnLeft].position().phi()
00222         << "\n\tplane center (z,R,eta,phi): " 
00223         << plane->position().z() << ", "
00224         << plane->position().perp() << " , "    
00225         << plane->position().eta() << " , " 
00226         << plane->position().phi();
00227      
00228    // propagate to the plane
00229    // timers.pop_and_push("CachedTrajectory::propagate::localPropagation",TimerStack::FastMonitoring);
00230    if (const SteppingHelixPropagator* shp = dynamic_cast<const SteppingHelixPropagator*>(propagator_))
00231      {
00232         SteppingHelixStateInfo state;
00233         try { 
00234            state = shp->propagate(fullTrajectory_[closestPointOnLeft], *plane);
00235         }
00236         catch(cms::Exception &ex){
00237            edm::LogWarning("TrackAssociator") << 
00238                 "Caught exception " << ex.category() << ": " << ex.explainSelf();
00239            edm::LogWarning("TrackAssociator") << "An exception is caught during the track propagation\n"
00240              << state.momentum().x() << ", " << state.momentum().y() << ", " << state.momentum().z();
00241            return TrajectoryStateOnSurface();
00242         }
00243         return state.getStateOnSurface(*plane);
00244      }
00245    else
00246      {
00247         FreeTrajectoryState fts;
00248         fullTrajectory_[closestPointOnLeft].getFreeState(fts);
00249         return propagator_->propagate(fts, *plane);
00250      }
00251 }
00252 
00253 std::pair<float,float> CachedTrajectory::trajectoryDelta( TrajectorType trajectoryType )
00254 {
00255    // MEaning of trajectory change depends on its usage. In most cases we measure 
00256    // change in a trajectory as difference between final track position and initial 
00257    // direction. In some cases such as change of trajectory in the muon detector we 
00258    // might want to compare theta-phi of two points or even find local maximum and
00259    // mimimum. In general it's not essential what defenition of the trajectory change
00260    // is used since we use these numbers only as a rough estimate on how much wider
00261    // we should make the preselection region.
00262    std::pair<float,float> result(0,0);
00263    if ( ! stateAtIP_.isValid() ) { 
00264       edm::LogWarning("TrackAssociator") << "State at IP is not known set. Cannot estimate trajectory change. " <<
00265         "Trajectory change is not taken into account in matching";
00266       return result;
00267    }
00268    switch (trajectoryType) {
00269     case IpToEcal:
00270       if ( ecalTrajectory_.empty() )
00271         edm::LogWarning("TrackAssociator") << "ECAL trajector is empty. Cannot estimate trajectory change. " <<
00272         "Trajectory change is not taken into account in matching";
00273       else return delta( stateAtIP_.momentum().theta(), ecalTrajectory_.front().position().theta(), 
00274                          stateAtIP_.momentum().phi(), ecalTrajectory_.front().position().phi() );
00275       break;
00276     case IpToHcal:
00277       if ( hcalTrajectory_.empty() )
00278         edm::LogWarning("TrackAssociator") << "HCAL trajector is empty. Cannot estimate trajectory change. " <<
00279         "Trajectory change is not taken into account in matching";
00280       else return delta( stateAtIP_.momentum().theta(), hcalTrajectory_.front().position().theta(), 
00281                          stateAtIP_.momentum().phi(),   hcalTrajectory_.front().position().phi() );
00282       break;
00283     case IpToHO:
00284       if ( hoTrajectory_.empty() )
00285         edm::LogWarning("TrackAssociator") << "HO trajector is empty. Cannot estimate trajectory change. " <<
00286         "Trajectory change is not taken into account in matching";
00287       else return delta( stateAtIP_.momentum().theta(), hoTrajectory_.front().position().theta(), 
00288                          stateAtIP_.momentum().phi(),   hoTrajectory_.front().position().phi() );
00289       break;
00290     case FullTrajectory:
00291       if ( fullTrajectory_.empty() )
00292         edm::LogWarning("TrackAssociator") << "Full trajector is empty. Cannot estimate trajectory change. " <<
00293         "Trajectory change is not taken into account in matching";
00294       else  return delta( stateAtIP_.momentum().theta(), fullTrajectory_.back().position().theta(), 
00295                           stateAtIP_.momentum().phi(),   fullTrajectory_.back().position().phi() );
00296       break;
00297     default:
00298       edm::LogWarning("TrackAssociator") << "Unkown or not supported trajector type. Cannot estimate trajectory change. " <<
00299         "Trajectory change is not taken into account in matching";
00300    }
00301    return result;
00302 }
00303 
00304 std::pair<float,float> CachedTrajectory::delta(const double& theta1,
00305                                                const double& theta2,
00306                                                const double& phi1,
00307                                                const double& phi2)
00308 {
00309    std::pair<float,float> result(theta2 - theta1, phi2 - phi1 );
00310    // this won't work for loopers, since deltaPhi cannot be larger than Pi.
00311    if ( fabs(result.second) > 2*M_PI-fabs(result.second) ) {
00312       if (result.second>0) 
00313         result.second -= 2*M_PI;
00314       else
00315         result.second += 2*M_PI;
00316    }
00317    return result;
00318 }
00319         
00320 void CachedTrajectory::getTrajectory(std::vector<SteppingHelixStateInfo>& trajectory,
00321                                      const FiducialVolume& volume,
00322                                      int steps)
00323 {
00324    if ( ! fullTrajectoryFilled_ ) throw cms::Exception("FatalError") << "trajectory is not defined yet. Please use propagateAll first.";
00325    if ( fullTrajectory_.empty() ) {
00326       LogTrace("TrackAssociator") << "Trajectory is empty. Move on";
00327       return;
00328    }
00329    if ( ! volume.isValid() ) {
00330       LogTrace("TrackAssociator") << "no trajectory is expected to be found since the fiducial volume is not valid";
00331       return;
00332    }
00333    double step = std::max(volume.maxR()-volume.minR(),volume.maxZ()-volume.minZ())/steps;
00334    
00335    int closestPointOnLeft = -1;
00336    
00337    // check whether the trajectory crossed the region
00338    if ( ! 
00339         ( ( fullTrajectory_.front().position().perp() < volume.maxR() && fabs(fullTrajectory_.front().position().z()) < volume.maxZ() ) &&
00340           ( fullTrajectory_.back().position().perp() > volume.minR() || fabs(fullTrajectory_.back().position().z()) > volume.minZ() ) ))
00341      {
00342         LogTrace("TrackAssociator") << "Track didn't cross the region (R1,R2,L1,L2): " << volume.minR() << ", " << volume.maxR() <<
00343           ", " << volume.minZ() << ", " << volume.maxZ();
00344         return;
00345      }
00346    
00347    // get distance along momentum to the surface.
00348    
00349    // the following code can be made faster, but it'll hardly be a significant improvement
00350    // simplifications:
00351    //   1) direct loop over stored trajectory points instead of some sort 
00352    //      of fast root search (Newton method)
00353    //   2) propagate from the closest point outside the region with the 
00354    //      requested step ignoring stored trajectory points.
00355    double dZ(-1.);
00356    double dR(-1.);
00357    int firstPointInside(-1);
00358    for(unsigned int i=0; i<fullTrajectory_.size(); i++) {
00359       // LogTrace("TrackAssociator") << "Trajectory info (i,perp,r1,r2,z,z1,z2): " << i << ", " << fullTrajectory_[i].position().perp() <<
00360       //        ", " << volume.minR() << ", " << volume.maxR() << ", " << fullTrajectory_[i].position().z() << ", " << volume.minZ() << ", " << 
00361       //        volume.maxZ() << ", " << closestPointOnLeft;
00362       dR = fullTrajectory_[i].position().perp()-volume.minR();
00363       dZ = fabs(fullTrajectory_[i].position().z()) - volume.minZ();
00364       if ( dR> 0  || dZ >0 )
00365         {
00366            if (i>0) {
00367               firstPointInside = i;
00368               closestPointOnLeft = i - 1;
00369            } else {
00370               firstPointInside = 0;
00371               closestPointOnLeft = 0;
00372            }
00373            break;
00374         }
00375    }
00376    if (closestPointOnLeft == -1) throw cms::Exception("FatalError") << "This shouls never happen - internal logic error";
00377    
00378    SteppingHelixStateInfo currentState(fullTrajectory_[closestPointOnLeft]);
00379    if ( currentState.position().x()*currentState.momentum().x() +
00380         currentState.position().y()*currentState.momentum().y() +
00381         currentState.position().z()*currentState.momentum().z() < 0 )
00382      step = -step;
00383    
00384    // propagate to the inner surface of the active volume
00385 
00386    if (firstPointInside != closestPointOnLeft) {
00387       if ( dR > 0 ) {
00388          Cylinder::CylinderPointer barrel = Cylinder::build( Cylinder::PositionType (0, 0, 0), Cylinder::RotationType (), volume.minR());
00389          propagate(currentState, *barrel);
00390       } else {
00391          Plane::PlanePointer endcap = Plane::build( Plane::PositionType (0, 0, 
00392                                                                          currentState.position().z()>0?volume.minZ():-volume.minZ()), 
00393                                                     Plane::RotationType () );
00394          propagate(currentState, *endcap);
00395       }
00396       if ( currentState.isValid() ) trajectory.push_back(currentState);
00397    } else
00398      LogTrace("TrackAssociator") << "Weird message\n";
00399 
00400    while (currentState.isValid() &&
00401           currentState.position().perp()    < volume.maxR() && 
00402           fabs(currentState.position().z()) < volume.maxZ() )
00403      {
00404         propagateForward(currentState,step);
00405         if (! currentState.isValid() ) {
00406            LogTrace("TrackAssociator") << "Failed to propagate the track; moving on\n";
00407            break;
00408         }
00409         // LogTrace("TrackAssociator") << "New state (perp, z): " << currentState.position().perp() << ", " << currentState.position().z();
00410         //if ( ( currentState.position().perp() < volume.maxR() && fabs(currentState.position().z()) < volume.maxZ() ) &&
00411         //     ( currentState.position().perp()-volume.minR() > 0  || fabs(currentState.position().z()) - volume.minZ() >0 ) )
00412         trajectory.push_back(currentState);
00413      }
00414 }
00415 
00416 void CachedTrajectory::reset_trajectory() { 
00417    fullTrajectory_.clear();
00418    ecalTrajectory_.clear();
00419    hcalTrajectory_.clear();
00420    hoTrajectory_.clear();
00421    preshowerTrajectory_.clear();
00422    wideEcalTrajectory_.clear();   
00423    wideHcalTrajectory_.clear();
00424    wideHOTrajectory_.clear();
00425    fullTrajectoryFilled_ = false;
00426 }
00427 
00428 void CachedTrajectory::findEcalTrajectory( const FiducialVolume& volume ) {
00429    LogTrace("TrackAssociator") << "getting trajectory in ECAL";
00430    getTrajectory(ecalTrajectory_, volume, 4 );
00431    LogTrace("TrackAssociator") << "# of points in ECAL trajectory:" << ecalTrajectory_.size();
00432 }
00433 
00434 void CachedTrajectory::findPreshowerTrajectory( const FiducialVolume& volume ) {
00435    LogTrace("TrackAssociator") << "getting trajectory in Preshower";
00436    getTrajectory(preshowerTrajectory_, volume, 2 );
00437    LogTrace("TrackAssociator") << "# of points in Preshower trajectory:" << preshowerTrajectory_.size();
00438 }
00439 
00440 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getEcalTrajectory() {
00441    return ecalTrajectory_;
00442 }
00443 
00444 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getPreshowerTrajectory() {
00445    return preshowerTrajectory_;
00446 }
00447 
00448 void CachedTrajectory::findHcalTrajectory( const FiducialVolume& volume ) {
00449    LogTrace("TrackAssociator") << "getting trajectory in HCAL";
00450    getTrajectory(hcalTrajectory_, volume, 4 ); // more steps to account for different depth
00451    LogTrace("TrackAssociator") << "# of points in HCAL trajectory:" << hcalTrajectory_.size();
00452 }
00453 
00454 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getHcalTrajectory() {
00455    return hcalTrajectory_;
00456 }
00457 
00458 void CachedTrajectory::findHOTrajectory( const FiducialVolume& volume ) {
00459    LogTrace("TrackAssociator") << "getting trajectory in HO";
00460    getTrajectory(hoTrajectory_, volume, 2 );
00461    LogTrace("TrackAssociator") << "# of points in HO trajectory:" << hoTrajectory_.size();
00462 }
00463 
00464 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getHOTrajectory() {
00465    return hoTrajectory_;
00466 }
00467    
00468 std::vector<GlobalPoint>*
00469 CachedTrajectory::getWideTrajectory(const std::vector<SteppingHelixStateInfo>& states, 
00470                                     WideTrajectoryType wideTrajectoryType) {
00471    std::vector<GlobalPoint>* wideTrajectory = 0;
00472    switch (wideTrajectoryType) {
00473     case Ecal:
00474        LogTrace("TrackAssociator") << "Filling ellipses in Ecal trajectory";
00475        wideTrajectory = &wideEcalTrajectory_;
00476        break;
00477     case Hcal:
00478        LogTrace("TrackAssociator") << "Filling ellipses in Hcal trajectory";
00479       wideTrajectory = &wideHcalTrajectory_;
00480       break;
00481     case HO:
00482        LogTrace("TrackAssociator") << "Filling ellipses in HO trajectory";
00483        wideTrajectory = &wideHOTrajectory_;
00484        break;
00485    }
00486    if(!wideTrajectory) return 0;
00487 
00488    for(std::vector<SteppingHelixStateInfo>::const_iterator state= states.begin();
00489        state != states.end(); state++) {
00490       // defined a normal plane wrt the particle trajectory direction
00491       // let's hope that I computed the rotation matrix correctly.
00492       GlobalVector vector(state->momentum().unit());
00493       float r21 = 0;
00494       float r22 = vector.z()/sqrt(1-pow(vector.x(),2));
00495       float r23 = -vector.y()/sqrt(1-pow(vector.x(),2));
00496       float r31 = vector.x();
00497       float r32 = vector.y();
00498       float r33 = vector.z();
00499       float r11 = r22*r33-r23*r32;
00500       float r12 = r23*r31;
00501       float r13 = -r22*r31;
00502    
00503       Plane::RotationType rotation(r11, r12, r13,
00504                                    r21, r22, r23,
00505                                    r31, r32, r33);
00506       Plane* target = new Plane(state->position(), rotation);
00507 
00508       TrajectoryStateOnSurface tsos = state->getStateOnSurface(*target);
00509 
00510       if (!tsos.isValid()) {
00511          LogTrace("TrackAssociator") << "[getWideTrajectory] TSOS not valid";
00512          continue;
00513       }
00514       if (!tsos.hasError()) {
00515          LogTrace("TrackAssociator") << "[getWideTrajectory] TSOS does not have Errors";
00516          continue;
00517       }
00518       LocalError localErr = tsos.localError().positionError();
00519       localErr.scale(2); // get the 2 sigma ellipse
00520       float xx = localErr.xx();
00521       float xy = localErr.xy();
00522       float yy = localErr.yy();
00523 
00524       float denom = yy - xx;
00525       float phi = 0., phi_temp=0.;
00526       if(xy == 0 && denom==0) phi = M_PI_4;
00527       else phi = 0.5 * atan2(2.*xy,denom); // angle of MAJOR axis
00528       phi_temp = phi;
00529       // Unrotate the error ellipse to get the semimajor and minor axes. Then place points on
00530       // the endpoints of semiminor an seminajor axes on original(rotated) error ellipse.
00531       LocalError rotErr = localErr.rotate(-phi); // xy covariance of rotErr should be zero
00532       float semi1 = sqrt(rotErr.xx());
00533       float semi2 = sqrt(rotErr.yy());
00534       
00535       // Just use one point if the ellipse is small
00536       // if(semi1 < 0.1 && semi2 < 0.1) {
00537       //   LogTrace("TrackAssociator") << "[getWideTrajectory] Error ellipse is small, using one trajectory point";
00538       //   wideTrajectory->push_back(state->position());
00539       //   continue;
00540       // }
00541 
00542       Local2DPoint bounds[4];
00543       bounds[0] = Local2DPoint(semi1*cos(phi),         semi1*sin(phi));
00544       bounds[1] = Local2DPoint(semi1*cos(phi+M_PI),    semi1*sin(phi+M_PI));
00545       phi += M_PI_2; // add pi/2 for the semi2 axis
00546       bounds[2] = Local2DPoint(semi2*cos(phi),         semi2*sin(phi));
00547       bounds[3] = Local2DPoint(semi2*cos(phi+M_PI),    semi2*sin(phi+M_PI));
00548 
00549       // LogTrace("TrackAssociator") << "Axes " << semi1 <<","<< semi2 <<"   phi "<< phi;
00550       // LogTrace("TrackAssociator") << "Local error ellipse: " << bounds[0] << bounds[1] << bounds[2] << bounds[3];
00551 
00552       wideTrajectory->push_back(state->position());
00553       for(int index=0; index<4; ++index)
00554          wideTrajectory->push_back(target->toGlobal(bounds[index]));
00555 
00556       //LogTrace("TrackAssociator") <<"Global error ellipse: (" << target->toGlobal(bounds[0]) <<","<< target->toGlobal(bounds[1])
00557       //         <<","<< target->toGlobal(bounds[2]) <<","<< target->toGlobal(bounds[3]) <<","<<state->position() <<")";
00558    }
00559 
00560    return wideTrajectory;
00561 }
00562 
00563 SteppingHelixStateInfo CachedTrajectory::getStateAtEcal()
00564 {
00565    if ( ecalTrajectory_.empty() )
00566      return SteppingHelixStateInfo();
00567    else 
00568      return ecalTrajectory_.front();
00569 }
00570 
00571 SteppingHelixStateInfo CachedTrajectory::getStateAtPreshower()
00572 {
00573    if ( preshowerTrajectory_.empty() )
00574      return SteppingHelixStateInfo();
00575    else 
00576      return preshowerTrajectory_.front();
00577 }
00578 
00579 SteppingHelixStateInfo CachedTrajectory::getStateAtHcal()
00580 {
00581    if ( hcalTrajectory_.empty() )
00582      return SteppingHelixStateInfo();
00583    else 
00584      return hcalTrajectory_.front();
00585 }
00586 
00587 SteppingHelixStateInfo CachedTrajectory::getStateAtHO()
00588 {
00589    if ( hoTrajectory_.empty() )
00590      return SteppingHelixStateInfo();
00591    else 
00592      return hoTrajectory_.front();
00593 }
00594 
00595 
00596 SteppingHelixStateInfo CachedTrajectory::getInnerState() {
00597   if(fullTrajectory_.empty() )
00598     return SteppingHelixStateInfo();
00599   else
00600     return fullTrajectory_.front();
00601 }
00602 
00603 
00604 SteppingHelixStateInfo CachedTrajectory::getOuterState() {
00605   if(fullTrajectory_.empty() )
00606     return SteppingHelixStateInfo();
00607   else
00608     return fullTrajectory_.back();
00609 }
00610