CMS 3D CMS Logo

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