00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "TrackingTools/TrackAssociator/interface/CachedTrajectory.h"
00011
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
00031
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
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
00153
00154
00155
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
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 const float matchingDistance = 1;
00180
00181 int leftIndex = 0;
00182 int rightIndex = fullTrajectory_.size()-1;
00183 int closestPointOnLeft = 0;
00184
00185
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
00196
00197 if (fabs(dist)<matchingDistance) {
00198
00199 if (closestPointOnLeft>0 && sign( distance(plane, closestPointOnLeft-1) ) * dist == -1)
00200 closestPointOnLeft--;
00201 break;
00202 }
00203
00204
00205 if (sign( distance(plane, leftIndex) * dist ) == -1)
00206 rightIndex = closestPointOnLeft;
00207 else
00208 leftIndex = closestPointOnLeft;
00209
00210
00211
00212
00213
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
00229
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
00256
00257
00258
00259
00260
00261
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
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
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
00348
00349
00350
00351
00352
00353
00354
00355 double dZ(-1.);
00356 double dR(-1.);
00357 int firstPointInside(-1);
00358 for(unsigned int i=0; i<fullTrajectory_.size(); i++) {
00359
00360
00361
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
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
00410
00411
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 );
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
00491
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);
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);
00528 phi_temp = phi;
00529
00530
00531 LocalError rotErr = localErr.rotate(-phi);
00532 float semi1 = sqrt(rotErr.xx());
00533 float semi2 = sqrt(rotErr.yy());
00534
00535
00536
00537
00538
00539
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;
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
00550
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
00557
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