File indexing completed on 2024-04-06 12:31:36
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "TrackingTools/TrackAssociator/interface/CachedTrajectory.h"
0010
0011 #include "TrackPropagation/SteppingHelixPropagator/interface/SteppingHelixPropagator.h"
0012 #include "DataFormats/GeometrySurface/interface/Plane.h"
0013 #include "Geometry/DTGeometry/interface/DTChamber.h"
0014 #include "Geometry/CSCGeometry/interface/CSCChamber.h"
0015 #include <deque>
0016 #include <algorithm>
0017
0018 std::vector<SteppingHelixStateInfo> propagateThoughFromIP(const SteppingHelixStateInfo& state,
0019 const Propagator* prop,
0020 const FiducialVolume& volume,
0021 int nsteps,
0022 float step,
0023 float minR,
0024 float minZ,
0025 float maxR,
0026 float maxZ) {
0027 CachedTrajectory neckLace;
0028 neckLace.setStateAtIP(state);
0029 neckLace.reset_trajectory();
0030 neckLace.setPropagator(prop);
0031 neckLace.setPropagationStep(0.1);
0032 neckLace.setMinDetectorRadius(minR);
0033 neckLace.setMinDetectorLength(minZ * 2.);
0034 neckLace.setMaxDetectorRadius(maxR);
0035 neckLace.setMaxDetectorLength(maxZ * 2.);
0036
0037
0038 bool isPropagationSuccessful = neckLace.propagateAll(state);
0039
0040 if (!isPropagationSuccessful)
0041 return std::vector<SteppingHelixStateInfo>();
0042
0043 std::vector<SteppingHelixStateInfo> complicatePoints;
0044 neckLace.getTrajectory(complicatePoints, volume, nsteps);
0045
0046 return complicatePoints;
0047 }
0048
0049 CachedTrajectory::CachedTrajectory() : propagator_(nullptr) {
0050 reset_trajectory();
0051 setMaxDetectorRadius();
0052 setMaxDetectorLength();
0053 setMinDetectorRadius();
0054 setMinDetectorLength();
0055 setPropagationStep();
0056 }
0057
0058 void CachedTrajectory::propagateForward(SteppingHelixStateInfo& state, float distance) {
0059
0060
0061 GlobalVector vector(state.momentum().unit());
0062 float r21 = 0;
0063 float r22 = vector.z() / sqrt(1 - pow(vector.x(), 2));
0064 float r23 = -vector.y() / sqrt(1 - pow(vector.x(), 2));
0065 float r31 = vector.x();
0066 float r32 = vector.y();
0067 float r33 = vector.z();
0068 float r11 = r22 * r33 - r23 * r32;
0069 float r12 = r23 * r31;
0070 float r13 = -r22 * r31;
0071
0072 Surface::RotationType rotation(r11, r12, r13, r21, r22, r23, r31, r32, r33);
0073 Plane::PlanePointer target = Plane::build(state.position() + vector * distance, rotation);
0074 propagate(state, *target);
0075 }
0076
0077 void CachedTrajectory::propagate(SteppingHelixStateInfo& state, const Plane& plane) {
0078 if (const SteppingHelixPropagator* shp = dynamic_cast<const SteppingHelixPropagator*>(propagator_)) {
0079 try {
0080 shp->propagate(state, plane, state);
0081 } catch (cms::Exception& ex) {
0082 edm::LogWarning("TrackAssociator") << "Caught exception " << ex.category() << ": " << ex.explainSelf();
0083 edm::LogWarning("TrackAssociator") << "An exception is caught during the track propagation\n"
0084 << state.momentum().x() << ", " << state.momentum().y() << ", "
0085 << state.momentum().z();
0086 state = SteppingHelixStateInfo();
0087 }
0088 } else {
0089 FreeTrajectoryState fts;
0090 state.getFreeState(fts);
0091 TrajectoryStateOnSurface stateOnSurface = propagator_->propagate(fts, plane);
0092 state = SteppingHelixStateInfo(*(stateOnSurface.freeState()));
0093 }
0094 }
0095
0096 void CachedTrajectory::propagate(SteppingHelixStateInfo& state, const Cylinder& cylinder) {
0097 if (const SteppingHelixPropagator* shp = dynamic_cast<const SteppingHelixPropagator*>(propagator_)) {
0098 try {
0099 shp->propagate(state, cylinder, state);
0100 } catch (cms::Exception& ex) {
0101 edm::LogWarning("TrackAssociator") << "Caught exception " << ex.category() << ": " << ex.explainSelf();
0102 edm::LogWarning("TrackAssociator") << "An exception is caught during the track propagation\n"
0103 << state.momentum().x() << ", " << state.momentum().y() << ", "
0104 << state.momentum().z();
0105 state = SteppingHelixStateInfo();
0106 }
0107 } else {
0108 FreeTrajectoryState fts;
0109 state.getFreeState(fts);
0110 TrajectoryStateOnSurface stateOnSurface = propagator_->propagate(fts, cylinder);
0111 state = SteppingHelixStateInfo(*(stateOnSurface.freeState()));
0112 }
0113 }
0114
0115 bool CachedTrajectory::propagateAll(const SteppingHelixStateInfo& initialState) {
0116 if (fullTrajectoryFilled_) {
0117 edm::LogWarning("TrackAssociator")
0118 << "Reseting all trajectories. Please call reset_trajectory() explicitely to avoid this message";
0119 reset_trajectory();
0120 }
0121
0122
0123
0124 reset_trajectory();
0125 if (propagator_ == nullptr)
0126 throw cms::Exception("FatalError") << "Track propagator is not defined\n";
0127 SteppingHelixStateInfo currentState(initialState);
0128 fullTrajectory_.push_back(currentState);
0129
0130 while (currentState.position().perp() < maxRho_ && fabs(currentState.position().z()) < maxZ_) {
0131 LogTrace("TrackAssociator") << "[propagateAll] Propagate outward from (rho, r, z, phi) ("
0132 << currentState.position().perp() << ", " << currentState.position().mag() << ", "
0133 << currentState.position().z() << ", " << currentState.position().phi() << ")";
0134 propagateForward(currentState, step_);
0135 if (!currentState.isValid()) {
0136 LogTrace("TrackAssociator") << "Failed to propagate the track; moving on\n";
0137 break;
0138 }
0139 LogTrace("TrackAssociator") << "\treached (rho, r, z, phi) (" << currentState.position().perp() << ", "
0140 << currentState.position().mag() << ", " << currentState.position().z() << ", "
0141 << currentState.position().phi() << ")";
0142 fullTrajectory_.push_back(currentState);
0143 }
0144
0145 SteppingHelixStateInfo currentState2(initialState);
0146 SteppingHelixStateInfo previousState;
0147 while (currentState2.position().perp() > minRho_ || fabs(currentState2.position().z()) > minZ_) {
0148 previousState = currentState2;
0149 propagateForward(currentState2, -step_);
0150 if (!currentState2.isValid()) {
0151 LogTrace("TrackAssociator") << "Failed to propagate the track; moving on\n";
0152 break;
0153 }
0154 if (previousState.position().perp() - currentState2.position().perp() < 0) {
0155 LogTrace("TrackAssociator")
0156 << "Error: TrackAssociator has propogated the particle past the point of closest approach to IP" << std::endl;
0157 break;
0158 }
0159 LogTrace("TrackAssociator") << "[propagateAll] Propagated inward from (rho, r, z, phi) ("
0160 << previousState.position().perp() << ", " << previousState.position().mag() << ", "
0161 << previousState.position().z() << "," << previousState.position().phi() << ") to ("
0162 << currentState2.position().perp() << ", " << currentState2.position().mag() << ", "
0163 << currentState2.position().z() << ", " << currentState2.position().phi() << ")";
0164 fullTrajectory_.push_front(currentState2);
0165 }
0166
0167
0168
0169
0170
0171
0172
0173 LogTrace("TrackAssociator") << "Done with the track propagation in the detector. Number of steps: "
0174 << fullTrajectory_.size();
0175 fullTrajectoryFilled_ = true;
0176 return !fullTrajectory_.empty();
0177 }
0178
0179 TrajectoryStateOnSurface CachedTrajectory::propagate(const Plane* plane) {
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 const float matchingDistance = 1;
0191
0192 int leftIndex = 0;
0193 int rightIndex = fullTrajectory_.size() - 1;
0194 int closestPointOnLeft = 0;
0195
0196
0197 if (sign(distance(plane, leftIndex)) * sign(distance(plane, rightIndex)) != -1) {
0198 LogTrace("TrackAssociator") << "Track didn't cross the plane:\n\tleft distance: " << distance(plane, leftIndex)
0199 << "\n\tright distance: " << distance(plane, rightIndex);
0200 return TrajectoryStateOnSurface();
0201 }
0202
0203 while (leftIndex + 1 < rightIndex) {
0204 closestPointOnLeft = int((leftIndex + rightIndex) / 2);
0205 float dist = distance(plane, closestPointOnLeft);
0206
0207
0208 if (fabs(dist) < matchingDistance) {
0209
0210 if (closestPointOnLeft > 0 && sign(distance(plane, closestPointOnLeft - 1)) * dist == -1)
0211 closestPointOnLeft--;
0212 break;
0213 }
0214
0215
0216 if (sign(distance(plane, leftIndex) * dist) == -1)
0217 rightIndex = closestPointOnLeft;
0218 else
0219 leftIndex = closestPointOnLeft;
0220
0221
0222
0223
0224
0225 }
0226 LogTrace("TrackAssociator") << "closestPointOnLeft: " << closestPointOnLeft << "\n\ttrajectory point (z,R,eta,phi): "
0227 << fullTrajectory_[closestPointOnLeft].position().z() << ", "
0228 << fullTrajectory_[closestPointOnLeft].position().perp() << " , "
0229 << fullTrajectory_[closestPointOnLeft].position().eta() << " , "
0230 << fullTrajectory_[closestPointOnLeft].position().phi()
0231 << "\n\tplane center (z,R,eta,phi): " << plane->position().z() << ", "
0232 << plane->position().perp() << " , " << plane->position().eta() << " , "
0233 << plane->position().phi();
0234
0235
0236
0237 if (const SteppingHelixPropagator* shp = dynamic_cast<const SteppingHelixPropagator*>(propagator_)) {
0238 SteppingHelixStateInfo state;
0239 try {
0240 shp->propagate(fullTrajectory_[closestPointOnLeft], *plane, state);
0241 } catch (cms::Exception& ex) {
0242 edm::LogWarning("TrackAssociator") << "Caught exception " << ex.category() << ": " << ex.explainSelf();
0243 edm::LogWarning("TrackAssociator") << "An exception is caught during the track propagation\n"
0244 << state.momentum().x() << ", " << state.momentum().y() << ", "
0245 << state.momentum().z();
0246 return TrajectoryStateOnSurface();
0247 }
0248 return state.getStateOnSurface(*plane);
0249 } else {
0250 FreeTrajectoryState fts;
0251 fullTrajectory_[closestPointOnLeft].getFreeState(fts);
0252 return propagator_->propagate(fts, *plane);
0253 }
0254 }
0255
0256 std::pair<float, float> CachedTrajectory::trajectoryDelta(TrajectorType trajectoryType) {
0257
0258
0259
0260
0261
0262
0263
0264 std::pair<float, float> result(0, 0);
0265 if (!stateAtIP_.isValid()) {
0266 edm::LogWarning("TrackAssociator") << "State at IP is not known set. Cannot estimate trajectory change. "
0267 << "Trajectory change is not taken into account in matching";
0268 return result;
0269 }
0270 switch (trajectoryType) {
0271 case IpToEcal:
0272 if (ecalTrajectory_.empty())
0273 edm::LogWarning("TrackAssociator") << "ECAL trajector is empty. Cannot estimate trajectory change. "
0274 << "Trajectory change is not taken into account in matching";
0275 else
0276 return delta(stateAtIP_.momentum().theta(),
0277 ecalTrajectory_.front().position().theta(),
0278 stateAtIP_.momentum().phi(),
0279 ecalTrajectory_.front().position().phi());
0280 break;
0281 case IpToHcal:
0282 if (hcalTrajectory_.empty())
0283 edm::LogWarning("TrackAssociator") << "HCAL trajector is empty. Cannot estimate trajectory change. "
0284 << "Trajectory change is not taken into account in matching";
0285 else
0286 return delta(stateAtIP_.momentum().theta(),
0287 hcalTrajectory_.front().position().theta(),
0288 stateAtIP_.momentum().phi(),
0289 hcalTrajectory_.front().position().phi());
0290 break;
0291 case IpToHO:
0292 if (hoTrajectory_.empty())
0293 edm::LogWarning("TrackAssociator") << "HO trajector is empty. Cannot estimate trajectory change. "
0294 << "Trajectory change is not taken into account in matching";
0295 else
0296 return delta(stateAtIP_.momentum().theta(),
0297 hoTrajectory_.front().position().theta(),
0298 stateAtIP_.momentum().phi(),
0299 hoTrajectory_.front().position().phi());
0300 break;
0301 case FullTrajectory:
0302 if (fullTrajectory_.empty())
0303 edm::LogWarning("TrackAssociator") << "Full trajector is empty. Cannot estimate trajectory change. "
0304 << "Trajectory change is not taken into account in matching";
0305 else
0306 return delta(stateAtIP_.momentum().theta(),
0307 fullTrajectory_.back().position().theta(),
0308 stateAtIP_.momentum().phi(),
0309 fullTrajectory_.back().position().phi());
0310 break;
0311 default:
0312 edm::LogWarning("TrackAssociator")
0313 << "Unkown or not supported trajector type. Cannot estimate trajectory change. "
0314 << "Trajectory change is not taken into account in matching";
0315 }
0316 return result;
0317 }
0318
0319 std::pair<float, float> CachedTrajectory::delta(const double& theta1,
0320 const double& theta2,
0321 const double& phi1,
0322 const double& phi2) {
0323 std::pair<float, float> result(theta2 - theta1, phi2 - phi1);
0324
0325 if (fabs(result.second) > 2 * M_PI - fabs(result.second)) {
0326 if (result.second > 0)
0327 result.second -= 2 * M_PI;
0328 else
0329 result.second += 2 * M_PI;
0330 }
0331 return result;
0332 }
0333
0334 void CachedTrajectory::getTrajectory(std::vector<SteppingHelixStateInfo>& trajectory,
0335 const FiducialVolume& volume,
0336 int steps) {
0337 if (!fullTrajectoryFilled_)
0338 throw cms::Exception("FatalError") << "trajectory is not defined yet. Please use propagateAll first.";
0339 if (fullTrajectory_.empty()) {
0340 LogTrace("TrackAssociator") << "Trajectory is empty. Move on";
0341 return;
0342 }
0343 if (!volume.isValid()) {
0344 LogTrace("TrackAssociator") << "no trajectory is expected to be found since the fiducial volume is not valid";
0345 return;
0346 }
0347 double step = std::max(volume.maxR() - volume.minR(), volume.maxZ() - volume.minZ()) / steps;
0348
0349 int closestPointOnLeft = -1;
0350
0351
0352 if (!((fullTrajectory_.front().position().perp() < volume.maxR() &&
0353 fabs(fullTrajectory_.front().position().z()) < volume.maxZ()) &&
0354 (fullTrajectory_.back().position().perp() > volume.minR() ||
0355 fabs(fullTrajectory_.back().position().z()) > volume.minZ()))) {
0356 LogTrace("TrackAssociator") << "Track didn't cross the region (R1,R2,L1,L2): " << volume.minR() << ", "
0357 << volume.maxR() << ", " << volume.minZ() << ", " << volume.maxZ();
0358 return;
0359 }
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 double dZ(-1.);
0370 double dR(-1.);
0371 int firstPointInside(-1);
0372 for (unsigned int i = 0; i < fullTrajectory_.size(); i++) {
0373
0374
0375
0376 dR = fullTrajectory_[i].position().perp() - volume.minR();
0377 dZ = fabs(fullTrajectory_[i].position().z()) - volume.minZ();
0378 if (dR > 0 || dZ > 0) {
0379 if (i > 0) {
0380 firstPointInside = i;
0381 closestPointOnLeft = i - 1;
0382 } else {
0383 firstPointInside = 0;
0384 closestPointOnLeft = 0;
0385 }
0386 break;
0387 }
0388 }
0389 if (closestPointOnLeft == -1)
0390 throw cms::Exception("FatalError") << "This shouls never happen - internal logic error";
0391
0392 SteppingHelixStateInfo currentState(fullTrajectory_[closestPointOnLeft]);
0393 if (currentState.position().x() * currentState.momentum().x() +
0394 currentState.position().y() * currentState.momentum().y() +
0395 currentState.position().z() * currentState.momentum().z() <
0396 0)
0397 step = -step;
0398
0399
0400
0401 if (firstPointInside != closestPointOnLeft) {
0402 if (dR > 0) {
0403 Cylinder::CylinderPointer barrel =
0404 Cylinder::build(volume.minR(), Cylinder::PositionType(0, 0, 0), Cylinder::RotationType());
0405 propagate(currentState, *barrel);
0406 } else {
0407 Plane::PlanePointer endcap =
0408 Plane::build(Plane::PositionType(0, 0, currentState.position().z() > 0 ? volume.minZ() : -volume.minZ()),
0409 Plane::RotationType());
0410 propagate(currentState, *endcap);
0411 }
0412 if (currentState.isValid())
0413 trajectory.push_back(currentState);
0414 } else
0415 LogTrace("TrackAssociator") << "Weird message\n";
0416
0417 while (currentState.isValid() && currentState.position().perp() < volume.maxR() &&
0418 fabs(currentState.position().z()) < volume.maxZ()) {
0419 propagateForward(currentState, step);
0420 if (!currentState.isValid()) {
0421 LogTrace("TrackAssociator") << "Failed to propagate the track; moving on\n";
0422 break;
0423 }
0424
0425
0426
0427 trajectory.push_back(currentState);
0428 }
0429 }
0430
0431 void CachedTrajectory::reset_trajectory() {
0432 fullTrajectory_.clear();
0433 ecalTrajectory_.clear();
0434 hcalTrajectory_.clear();
0435 hoTrajectory_.clear();
0436 preshowerTrajectory_.clear();
0437 wideEcalTrajectory_.clear();
0438 wideHcalTrajectory_.clear();
0439 wideHOTrajectory_.clear();
0440 fullTrajectoryFilled_ = false;
0441 }
0442
0443 void CachedTrajectory::findEcalTrajectory(const FiducialVolume& volume) {
0444 LogTrace("TrackAssociator") << "getting trajectory in ECAL";
0445 getTrajectory(ecalTrajectory_, volume, 4);
0446 LogTrace("TrackAssociator") << "# of points in ECAL trajectory:" << ecalTrajectory_.size();
0447 }
0448
0449 void CachedTrajectory::findPreshowerTrajectory(const FiducialVolume& volume) {
0450 LogTrace("TrackAssociator") << "getting trajectory in Preshower";
0451 getTrajectory(preshowerTrajectory_, volume, 2);
0452 LogTrace("TrackAssociator") << "# of points in Preshower trajectory:" << preshowerTrajectory_.size();
0453 }
0454
0455 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getEcalTrajectory() const { return ecalTrajectory_; }
0456
0457 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getPreshowerTrajectory() const {
0458 return preshowerTrajectory_;
0459 }
0460
0461 void CachedTrajectory::findHcalTrajectory(const FiducialVolume& volume) {
0462 LogTrace("TrackAssociator") << "getting trajectory in HCAL";
0463 getTrajectory(hcalTrajectory_, volume, 4);
0464 LogTrace("TrackAssociator") << "# of points in HCAL trajectory:" << hcalTrajectory_.size();
0465 }
0466
0467 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getHcalTrajectory() const { return hcalTrajectory_; }
0468
0469 void CachedTrajectory::findHOTrajectory(const FiducialVolume& volume) {
0470 LogTrace("TrackAssociator") << "getting trajectory in HO";
0471 getTrajectory(hoTrajectory_, volume, 2);
0472 LogTrace("TrackAssociator") << "# of points in HO trajectory:" << hoTrajectory_.size();
0473 }
0474
0475 const std::vector<SteppingHelixStateInfo>& CachedTrajectory::getHOTrajectory() const { return hoTrajectory_; }
0476
0477 std::vector<GlobalPoint>* CachedTrajectory::getWideTrajectory(const std::vector<SteppingHelixStateInfo>& states,
0478 WideTrajectoryType wideTrajectoryType) {
0479 std::vector<GlobalPoint>* wideTrajectory = nullptr;
0480 switch (wideTrajectoryType) {
0481 case Ecal:
0482 LogTrace("TrackAssociator") << "Filling ellipses in Ecal trajectory";
0483 wideTrajectory = &wideEcalTrajectory_;
0484 break;
0485 case Hcal:
0486 LogTrace("TrackAssociator") << "Filling ellipses in Hcal trajectory";
0487 wideTrajectory = &wideHcalTrajectory_;
0488 break;
0489 case HO:
0490 LogTrace("TrackAssociator") << "Filling ellipses in HO trajectory";
0491 wideTrajectory = &wideHOTrajectory_;
0492 break;
0493 }
0494 if (!wideTrajectory)
0495 return nullptr;
0496
0497 for (std::vector<SteppingHelixStateInfo>::const_iterator state = states.begin(); state != states.end(); state++) {
0498
0499
0500 GlobalVector vector(state->momentum().unit());
0501 float r21 = 0;
0502 float r22 = vector.z() / sqrt(1 - pow(vector.x(), 2));
0503 float r23 = -vector.y() / sqrt(1 - pow(vector.x(), 2));
0504 float r31 = vector.x();
0505 float r32 = vector.y();
0506 float r33 = vector.z();
0507 float r11 = r22 * r33 - r23 * r32;
0508 float r12 = r23 * r31;
0509 float r13 = -r22 * r31;
0510
0511 Plane::RotationType rotation(r11, r12, r13, r21, r22, r23, r31, r32, r33);
0512 Plane* target = new Plane(state->position(), rotation);
0513
0514 TrajectoryStateOnSurface tsos = state->getStateOnSurface(*target);
0515
0516 if (!tsos.isValid()) {
0517 LogTrace("TrackAssociator") << "[getWideTrajectory] TSOS not valid";
0518 continue;
0519 }
0520 if (!tsos.hasError()) {
0521 LogTrace("TrackAssociator") << "[getWideTrajectory] TSOS does not have Errors";
0522 continue;
0523 }
0524 LocalError localErr = tsos.localError().positionError();
0525 localErr.scale(2);
0526 float xx = localErr.xx();
0527 float xy = localErr.xy();
0528 float yy = localErr.yy();
0529
0530 float denom = yy - xx;
0531 float phi = 0.;
0532 if (xy == 0 && denom == 0)
0533 phi = M_PI_4;
0534 else
0535 phi = 0.5 * atan2(2. * xy, denom);
0536
0537
0538 LocalError rotErr = localErr.rotate(-phi);
0539 float semi1 = sqrt(rotErr.xx());
0540 float semi2 = sqrt(rotErr.yy());
0541
0542
0543
0544
0545
0546
0547
0548
0549 Local2DPoint bounds[4];
0550 bounds[0] = Local2DPoint(semi1 * cos(phi), semi1 * sin(phi));
0551 bounds[1] = Local2DPoint(semi1 * cos(phi + M_PI), semi1 * sin(phi + M_PI));
0552 phi += M_PI_2;
0553 bounds[2] = Local2DPoint(semi2 * cos(phi), semi2 * sin(phi));
0554 bounds[3] = Local2DPoint(semi2 * cos(phi + M_PI), semi2 * sin(phi + M_PI));
0555
0556
0557
0558
0559 wideTrajectory->push_back(state->position());
0560 for (int index = 0; index < 4; ++index)
0561 wideTrajectory->push_back(target->toGlobal(bounds[index]));
0562
0563
0564
0565 }
0566
0567 return wideTrajectory;
0568 }
0569
0570 SteppingHelixStateInfo CachedTrajectory::getStateAtEcal() {
0571 if (ecalTrajectory_.empty())
0572 return SteppingHelixStateInfo();
0573 else
0574 return ecalTrajectory_.front();
0575 }
0576
0577 SteppingHelixStateInfo CachedTrajectory::getStateAtPreshower() {
0578 if (preshowerTrajectory_.empty())
0579 return SteppingHelixStateInfo();
0580 else
0581 return preshowerTrajectory_.front();
0582 }
0583
0584 SteppingHelixStateInfo CachedTrajectory::getStateAtHcal() {
0585 if (hcalTrajectory_.empty())
0586 return SteppingHelixStateInfo();
0587 else
0588 return hcalTrajectory_.front();
0589 }
0590
0591 SteppingHelixStateInfo CachedTrajectory::getStateAtHO() {
0592 if (hoTrajectory_.empty())
0593 return SteppingHelixStateInfo();
0594 else
0595 return hoTrajectory_.front();
0596 }
0597
0598 SteppingHelixStateInfo CachedTrajectory::getInnerState() {
0599 if (fullTrajectory_.empty())
0600 return SteppingHelixStateInfo();
0601 else
0602 return fullTrajectory_.front();
0603 }
0604
0605 SteppingHelixStateInfo CachedTrajectory::getOuterState() {
0606 if (fullTrajectory_.empty())
0607 return SteppingHelixStateInfo();
0608 else
0609 return fullTrajectory_.back();
0610 }