19#include <TGeoGlobalMagField.h>
20#include <TGeoManager.h>
21#include <TGeoMaterial.h>
35bool TrackExtrap::sExtrapV2 =
false;
36double TrackExtrap::sSimpleBValue = 0.;
37bool TrackExtrap::sFieldON =
false;
38std::size_t TrackExtrap::sNCallExtrapToZCov = 0;
39std::size_t TrackExtrap::sNCallField = 0;
46 const double x[3] = {50., 50., SSimpleBPosition};
47 double b[3] = {0., 0., 0.};
48 TGeoGlobalMagField::Instance()->Field(
x,
b);
50 sFieldON = (TMath::Abs(sSimpleBValue) > 1.e-10) ?
true :
false;
51 LOG(info) <<
"Track extrapolation with magnetic field " << (sFieldON ?
"ON" :
"OFF");
61 const double correctionFactor = 1.1;
62 if (bendingMomentum == 0.) {
65 return correctionFactor * (-0.0003 * sSimpleBValue * SSimpleBLength * SSimpleBPosition / bendingMomentum);
75 const double correctionFactor = 1.1;
76 if (impactParam == 0.) {
80 return correctionFactor * (-0.0003 * sSimpleBValue * SSimpleBLength * SSimpleBPosition / impactParam);
82 return SMostProbBendingMomentum;
92 if (trackParam.
getZ() == zEnd) {
97 double dZ = zEnd - trackParam.
getZ();
100 trackParam.
setZ(zEnd);
109 if (trackParam.
getZ() == zEnd) {
115 LOG(warning) <<
"Covariance matrix does not exist";
122 double dZ = zEnd - trackParam.
getZ();
125 trackParam.
setZ(zEnd);
128 TMatrixD jacob(5, 5);
134 TMatrixD tmp(trackParam.
getCovariances(), TMatrixD::kMultTranspose, jacob);
135 TMatrixD tmp2(jacob, TMatrixD::kMult, tmp);
139 if (updatePropagator) {
152 }
else if (sExtrapV2) {
153 return extrapToZRungekuttaV2(trackParam, zEnd);
155 return extrapToZRungekutta(trackParam, zEnd);
165 ++sNCallExtrapToZCov;
167 if (trackParam.
getZ() == zEnd) {
178 LOG(warning) <<
"Covariance matrix does not exist";
186 double zBegin = trackParamSave.
getZ();
201 TMatrixD jacob(5, 5);
203 TMatrixD dParam(5, 1);
204 double direction[5] = {-1., -1., 1., 1., -1.};
205 for (
int i = 0;
i < 5;
i++) {
207 if (kParamCov(
i,
i) <= 0.) {
212 for (
int j = 0;
j < 5;
j++) {
214 dParam(
j, 0) = TMath::Sqrt(kParamCov(
i,
i));
215 dParam(
j, 0) *= TMath::Sign(1., direction[
j] * paramSave(
j, 0));
224 trackParamSave.
setZ(zBegin);
228 LOG(warning) <<
"Bad covariance matrix";
233 TMatrixD jacobji(trackParamSave.
getParameters(), TMatrixD::kMinus, extrapParam);
234 jacobji *= 1. / dParam(
i, 0);
235 jacob.SetSub(0,
i, jacobji);
239 TMatrixD tmp(kParamCov, TMatrixD::kMultTranspose, jacob);
240 TMatrixD tmp2(jacob, TMatrixD::kMult, tmp);
244 if (updatePropagator) {
257 if (trackParam.
getZ() == SMIDZ) {
262 if (trackParam.
getZ() < SMuonFilterZBeg) {
263 LOG(warning) <<
"The track already passed the beginning of the muon filter";
271 addMCSEffect(trackParam, -SMuonFilterThickness, SMuonFilterX0);
279 double errXVtx,
double errYVtx,
bool correctForMCS,
bool correctForEnergyLoss)
289 if (trackParam.
getZ() == zVtx) {
294 if (zVtx < SAbsZBeg) {
295 if (zVtx < SAbsZEnd) {
296 LOG(warning) <<
"Ending Z (" << zVtx <<
") downstream the front absorber (zAbsorberEnd = " << SAbsZEnd <<
")";
299 LOG(warning) <<
"Ending Z (" << zVtx <<
") inside the front absorber (" << SAbsZBeg <<
", " << SAbsZEnd <<
")";
305 if (trackParam.
getZ() > SAbsZEnd) {
306 if (trackParam.
getZ() > zVtx) {
307 LOG(warning) <<
"Starting Z (" << trackParam.
getZ() <<
") upstream the vertex (zVtx = " << zVtx <<
")";
309 }
else if (trackParam.
getZ() > SAbsZBeg) {
310 LOG(warning) <<
"Starting Z (" << trackParam.
getZ() <<
") upstream the front absorber (zAbsorberBegin = " << SAbsZBeg <<
")";
313 LOG(warning) <<
"Starting Z (" << trackParam.
getZ() <<
") inside the front absorber (" << SAbsZBeg <<
", " << SAbsZEnd <<
")";
326 double trackXYZIn[3] = {0., 0., 0.};
328 trackXYZIn[2] = SAbsZBeg;
329 trackXYZIn[0] = trackXYZOut[0] + (xVtx - trackXYZOut[0]) / (zVtx - trackXYZOut[2]) * (trackXYZIn[2] - trackXYZOut[2]);
330 trackXYZIn[1] = trackXYZOut[1] + (yVtx - trackXYZOut[1]) / (zVtx - trackXYZOut[2]) * (trackXYZIn[2] - trackXYZOut[2]);
332 TrackParam trackParamIn(trackParam);
333 if (!
extrapToZ(trackParamIn, SAbsZBeg)) {
336 trackXYZIn[0] = trackParamIn.getNonBendingCoor();
337 trackXYZIn[1] = trackParamIn.getBendingCoor();
338 trackXYZIn[2] = trackParamIn.getZ();
340 double pTot = trackParam.
p();
341 double pathLength(0.), f0(0.),
f1(0.),
f2(0.), meanRho(0.), totalELoss(0.), sigmaELoss2(0.);
342 if (!getAbsorberCorrectionParam(trackXYZIn, trackXYZOut, pTot, pathLength, f0, f1, f2, meanRho, totalELoss, sigmaELoss2)) {
348 if (correctForEnergyLoss) {
350 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
351 if (!correctMCSEffectInAbsorber(trackParam, xVtx, yVtx, zVtx, errXVtx, errYVtx, trackXYZIn[2], pathLength, f0, f1, f2)) {
354 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
357 if (!correctMCSEffectInAbsorber(trackParam, xVtx, yVtx, zVtx, errXVtx, errYVtx, trackXYZIn[2], pathLength, f0, f1, f2)) {
362 if (correctForEnergyLoss) {
364 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
365 addMCSEffectInAbsorber(trackParam, -pathLength, f0, f1, f2);
369 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
375 addMCSEffectInAbsorber(trackParam, -pathLength, f0, f1, f2);
386bool TrackExtrap::getAbsorberCorrectionParam(
double trackXYZIn[3],
double trackXYZOut[3],
double pTotal,
387 double& pathLength,
double& f0,
double& f1,
double& f2,
388 double& meanRho,
double& totalELoss,
double& sigmaELoss2)
402 LOG(warning) <<
"geometry is missing";
407 pathLength = TMath::Sqrt((trackXYZOut[0] - trackXYZIn[0]) * (trackXYZOut[0] - trackXYZIn[0]) +
408 (trackXYZOut[1] - trackXYZIn[1]) * (trackXYZOut[1] - trackXYZIn[1]) +
409 (trackXYZOut[2] - trackXYZIn[2]) * (trackXYZOut[2] - trackXYZIn[2]));
410 if (pathLength < TGeoShape::Tolerance()) {
411 LOG(warning) <<
"path length is too small";
414 double b[3] = {(trackXYZOut[0] - trackXYZIn[0]) / pathLength, (trackXYZOut[1] - trackXYZIn[1]) / pathLength, (trackXYZOut[2] - trackXYZIn[2]) / pathLength};
415 TGeoNode* currentnode = gGeoManager->InitTrack(trackXYZIn,
b);
417 LOG(warning) <<
"starting point out of geometry";
422 f0 =
f1 =
f2 = meanRho = totalELoss = 0.;
423 double sigmaELoss(0.);
424 double zB = trackXYZIn[2];
425 double remainingPathLength = pathLength;
429 TGeoMaterial* material = currentnode->GetVolume()->GetMedium()->GetMaterial();
430 double rho = material->GetDensity();
431 double x0 = material->GetRadLen();
432 double atomicZ = material->GetZ();
433 double atomicZoverA(0.);
434 if (material->IsMixture()) {
435 TGeoMixture* mixture =
static_cast<TGeoMixture*
>(material);
437 for (
int iel = 0; iel < mixture->GetNelements(); ++iel) {
438 sum += mixture->GetWmixt()[iel];
439 atomicZoverA += mixture->GetWmixt()[iel] * mixture->GetZmixt()[iel] / mixture->GetAmixt()[iel];
443 atomicZoverA = atomicZ / material->GetA();
447 gGeoManager->FindNextBoundary(remainingPathLength);
448 double localPathLength = gGeoManager->GetStep() + 1.e-6;
450 if (localPathLength >= remainingPathLength) {
451 localPathLength = remainingPathLength;
453 currentnode = gGeoManager->Step();
455 LOG(warning) <<
"navigation failed";
458 if (!gGeoManager->IsEntering()) {
460 gGeoManager->SetStep(0.001);
461 currentnode = gGeoManager->Step();
462 if (!gGeoManager->IsEntering() || !currentnode) {
463 LOG(warning) <<
"navigation failed";
466 localPathLength += 0.001;
471 double zE =
b[2] * localPathLength + zB;
472 double dzB = zB - trackXYZIn[2];
473 double dzE = zE - trackXYZIn[2];
474 f0 += localPathLength /
x0;
475 f1 += (dzE * dzE - dzB * dzB) /
b[2] /
b[2] /
x0 / 2.;
476 f2 += (dzE * dzE * dzE - dzB * dzB * dzB) /
b[2] /
b[2] /
b[2] /
x0 / 3.;
477 meanRho += localPathLength *
rho;
478 totalELoss += betheBloch(pTotal, localPathLength, rho, atomicZ, atomicZoverA);
479 sigmaELoss += energyLossFluctuation(pTotal, localPathLength, rho, atomicZoverA);
483 remainingPathLength -= localPathLength;
484 }
while (remainingPathLength > TGeoShape::Tolerance());
486 meanRho /= pathLength;
487 sigmaELoss2 = sigmaELoss * sigmaELoss;
498 double bendingSlope =
param.getBendingSlope();
499 double nonBendingSlope =
param.getNonBendingSlope();
500 double inverseTotalMomentum2 =
param.getInverseBendingMomentum() *
param.getInverseBendingMomentum() *
501 (1.0 + bendingSlope * bendingSlope) /
502 (1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
504 double pathLength = TMath::Abs(dZ) * TMath::Sqrt(1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
508 double theta02 = 0.0136 / velo * (1 + 0.038 * TMath::Log(pathLength /
x0));
509 return theta02 * theta02 * inverseTotalMomentum2 * pathLength /
x0;
524 double inverseTotalMomentum2 = inverseBendingMomentum * inverseBendingMomentum * (1.0 + bendingSlope * bendingSlope) /
525 (1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
527 double signedPathLength = dZ * TMath::Sqrt(1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
528 double pathLengthOverX0 = (
x0 > 0.) ? TMath::Abs(signedPathLength) /
x0 : TMath::Abs(signedPathLength);
532 double theta02 = 0.0136 / velo * (1 + 0.038 * TMath::Log(pathLengthOverX0));
533 theta02 *= theta02 * inverseTotalMomentum2 * pathLengthOverX0;
535 double varCoor = (
x0 > 0.) ? signedPathLength * signedPathLength * theta02 / 3. : 0.;
536 double varSlop = theta02;
537 double covCorrSlope = (
x0 > 0.) ? signedPathLength * theta02 / 2. : 0.;
542 newParamCov(0, 0) += varCoor;
543 newParamCov(0, 1) += covCorrSlope;
544 newParamCov(1, 0) += covCorrSlope;
545 newParamCov(1, 1) += varSlop;
547 newParamCov(2, 2) += varCoor;
548 newParamCov(2, 3) += covCorrSlope;
549 newParamCov(3, 2) += covCorrSlope;
550 newParamCov(3, 3) += varSlop;
555 double dqPxydSlopeX =
556 inverseBendingMomentum * nonBendingSlope / (1. + nonBendingSlope * nonBendingSlope + bendingSlope * bendingSlope);
557 double dqPxydSlopeY = -inverseBendingMomentum * nonBendingSlope * nonBendingSlope * bendingSlope /
558 (1. + bendingSlope * bendingSlope) /
559 (1. + nonBendingSlope * nonBendingSlope + bendingSlope * bendingSlope);
561 newParamCov(4, 0) += dqPxydSlopeX * covCorrSlope;
562 newParamCov(0, 4) += dqPxydSlopeX * covCorrSlope;
563 newParamCov(4, 1) += dqPxydSlopeX * varSlop;
564 newParamCov(1, 4) += dqPxydSlopeX * varSlop;
565 newParamCov(4, 2) += dqPxydSlopeY * covCorrSlope;
566 newParamCov(2, 4) += dqPxydSlopeY * covCorrSlope;
567 newParamCov(4, 3) += dqPxydSlopeY * varSlop;
568 newParamCov(3, 4) += dqPxydSlopeY * varSlop;
569 newParamCov(4, 4) += (dqPxydSlopeX * dqPxydSlopeX + dqPxydSlopeY * dqPxydSlopeY) * varSlop;
577void TrackExtrap::addMCSEffectInAbsorber(
TrackParam&
param,
double signedPathLength,
double f0,
double f1,
double f2)
583 double bendingSlope =
param.getBendingSlope();
584 double nonBendingSlope =
param.getNonBendingSlope();
585 double inverseBendingMomentum =
param.getInverseBendingMomentum();
586 double alpha2 = 0.0136 * 0.0136 * inverseBendingMomentum * inverseBendingMomentum * (1.0 + bendingSlope * bendingSlope) /
587 (1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
588 double pathLength = TMath::Abs(signedPathLength);
589 double varCoor = alpha2 * (pathLength * pathLength * f0 - 2. * pathLength * f1 + f2);
590 double covCorrSlope = TMath::Sign(1., signedPathLength) * alpha2 * (pathLength * f0 - f1);
591 double varSlop = alpha2 * f0;
594 TMatrixD newParamCov(
param.getCovariances());
596 newParamCov(0, 0) += varCoor;
597 newParamCov(0, 1) += covCorrSlope;
598 newParamCov(1, 0) += covCorrSlope;
599 newParamCov(1, 1) += varSlop;
601 newParamCov(2, 2) += varCoor;
602 newParamCov(2, 3) += covCorrSlope;
603 newParamCov(3, 2) += covCorrSlope;
604 newParamCov(3, 3) += varSlop;
609 double dqPxydSlopeX = inverseBendingMomentum * nonBendingSlope / (1. + nonBendingSlope * nonBendingSlope + bendingSlope * bendingSlope);
610 double dqPxydSlopeY = -inverseBendingMomentum * nonBendingSlope * nonBendingSlope * bendingSlope /
611 (1. + bendingSlope * bendingSlope) / (1. + nonBendingSlope * nonBendingSlope + bendingSlope * bendingSlope);
613 newParamCov(4, 0) += dqPxydSlopeX * covCorrSlope;
614 newParamCov(0, 4) += dqPxydSlopeX * covCorrSlope;
615 newParamCov(4, 1) += dqPxydSlopeX * varSlop;
616 newParamCov(1, 4) += dqPxydSlopeX * varSlop;
617 newParamCov(4, 2) += dqPxydSlopeY * covCorrSlope;
618 newParamCov(2, 4) += dqPxydSlopeY * covCorrSlope;
619 newParamCov(4, 3) += dqPxydSlopeY * varSlop;
620 newParamCov(3, 4) += dqPxydSlopeY * varSlop;
621 newParamCov(4, 4) += (dqPxydSlopeX * dqPxydSlopeX + dqPxydSlopeY * dqPxydSlopeY) * varSlop;
625 param.setCovariances(newParamCov);
629double TrackExtrap::betheBloch(
double pTotal,
double pathLength,
double rho,
double atomicZ,
double atomicZoverA)
635 static constexpr double mK = 0.307075e-3;
636 static constexpr double me = 0.511e-3;
637 static constexpr double x0 = 0.2 * 2.303;
638 static constexpr double x1 = 3. * 2.303;
640 double bg = pTotal / SMuMass;
641 double bg2 = bg * bg;
642 double maxT = 2 * me * bg2;
645 double mI = (atomicZ < 13) ? (12. * atomicZ + 7.) * 1.e-9 : (9.76 * atomicZ + 58.8 * TMath::Power(atomicZ, -0.19)) * 1.e-9;
648 double x = TMath::Log(bg);
649 double lhwI = TMath::Log(28.816 * 1e-9 * TMath::Sqrt(rho * atomicZoverA) / mI);
658 return pathLength *
rho * (
mK * atomicZoverA * (1 +
bg2) / bg2 * (0.5 * TMath::Log(2 * me * bg2 * maxT / (mI * mI)) - bg2 / (1 + bg2) -
d2));
662double TrackExtrap::energyLossFluctuation(
double pTotal,
double pathLength,
double rho,
double atomicZoverA)
667 static constexpr double mK = 0.307075e-3;
669 double p2 = pTotal * pTotal;
670 double beta2 =
p2 / (
p2 + SMuMass * SMuMass);
672 double fwhm = 2. *
mK *
rho * pathLength * atomicZoverA /
beta2;
674 return fwhm / TMath::Sqrt(8. * log(2.));
678bool TrackExtrap::correctMCSEffectInAbsorber(TrackParam&
param,
double xVtx,
double yVtx,
double zVtx,
double errXVtx,
double errYVtx,
679 double absZBeg,
double pathLength,
double f0,
double f1,
double f2)
687 double zB = (
f1 > 0.) ? absZBeg - f2 / f1 : 0.;
690 addMCSEffectInAbsorber(
param, -pathLength, f0, f1, f2);
699 TMatrixD newParam(5, 1);
700 newParam(0, 0) = xVtx;
701 newParam(1, 0) = (
param.getNonBendingCoor() - xVtx) / (zB - zVtx);
702 newParam(2, 0) = yVtx;
703 newParam(3, 0) = (
param.getBendingCoor() - yVtx) / (zB - zVtx);
704 newParam(4, 0) =
param.getCharge() /
param.p() *
705 TMath::Sqrt(1.0 + newParam(1, 0) * newParam(1, 0) + newParam(3, 0) * newParam(3, 0)) /
706 TMath::Sqrt(1.0 + newParam(3, 0) * newParam(3, 0));
709 TMatrixD paramCovP(
param.getCovariances());
710 cov2CovP(
param.getParameters(), paramCovP);
713 TMatrixD paramCovVtx(5, 5);
715 paramCovVtx(0, 0) = errXVtx * errXVtx;
716 paramCovVtx(1, 1) = paramCovP(0, 0);
717 paramCovVtx(2, 2) = errYVtx * errYVtx;
718 paramCovVtx(3, 3) = paramCovP(2, 2);
719 paramCovVtx(4, 4) = paramCovP(4, 4);
720 paramCovVtx(1, 3) = paramCovP(0, 2);
721 paramCovVtx(3, 1) = paramCovP(2, 0);
722 paramCovVtx(1, 4) = paramCovP(0, 4);
723 paramCovVtx(4, 1) = paramCovP(4, 0);
724 paramCovVtx(3, 4) = paramCovP(2, 4);
725 paramCovVtx(4, 3) = paramCovP(4, 2);
728 TMatrixD jacob(5, 5);
730 jacob(1, 0) = -1. / (zB - zVtx);
731 jacob(1, 1) = 1. / (zB - zVtx);
732 jacob(3, 2) = -1. / (zB - zVtx);
733 jacob(3, 3) = 1. / (zB - zVtx);
736 TMatrixD tmp(paramCovVtx, TMatrixD::kMultTranspose, jacob);
737 TMatrixD newParamCov(jacob, TMatrixD::kMult, tmp);
740 covP2Cov(newParam, newParamCov);
743 param.setParameters(newParam);
745 param.setCovariances(newParamCov);
751void TrackExtrap::correctELossEffectInAbsorber(TrackParam&
param,
double eLoss,
double sigmaELoss2)
756 TMatrixD newParamCov(
param.getCovariances());
757 cov2CovP(
param.getParameters(), newParamCov);
760 double p =
param.p();
761 double e = TMath::Sqrt(p * p + SMuMass * SMuMass);
762 double eCorr = e + eLoss;
763 double pCorr = TMath::Sqrt(eCorr * eCorr - SMuMass * SMuMass);
764 double nonBendingSlope =
param.getNonBendingSlope();
765 double bendingSlope =
param.getBendingSlope();
766 param.setInverseBendingMomentum(
param.getCharge() / pCorr *
767 TMath::Sqrt(1.0 + nonBendingSlope * nonBendingSlope + bendingSlope * bendingSlope) /
768 TMath::Sqrt(1.0 + bendingSlope * bendingSlope));
771 newParamCov(4, 4) += eCorr * eCorr / pCorr / pCorr * sigmaELoss2;
774 covP2Cov(
param.getParameters(), newParamCov);
777 param.setCovariances(newParamCov);
781void TrackExtrap::cov2CovP(
const TMatrixD&
param, TMatrixD& cov)
791 TMatrixD jacob(5, 5);
796 jacob(4, 4) = -qPTot /
param(4, 0);
799 TMatrixD tmp(cov, TMatrixD::kMultTranspose, jacob);
800 cov.Mult(jacob, tmp);
804void TrackExtrap::covP2Cov(
const TMatrixD&
param, TMatrixD& covP)
814 TMatrixD jacob(5, 5);
819 jacob(4, 4) = -
param(4, 0) / qPTot;
822 TMatrixD tmp(covP, TMatrixD::kMultTranspose, jacob);
823 covP.Mult(jacob, tmp);
827void TrackExtrap::convertTrackParamForExtrap(TrackParam& trackParam,
double forwardBackward,
double*
v3)
832 v3[0] = trackParam.getNonBendingCoor();
833 v3[1] = trackParam.getBendingCoor();
834 v3[2] = trackParam.getZ();
835 double pYZ = TMath::Abs(1.0 / trackParam.getInverseBendingMomentum());
836 double pZ = pYZ / TMath::Sqrt(1.0 + trackParam.getBendingSlope() * trackParam.getBendingSlope());
837 v3[6] = TMath::Sqrt(pYZ * pYZ + pZ * pZ * trackParam.getNonBendingSlope() * trackParam.getNonBendingSlope());
838 v3[5] = -forwardBackward * pZ /
v3[6];
839 v3[3] = trackParam.getNonBendingSlope() *
v3[5];
840 v3[4] = trackParam.getBendingSlope() *
v3[5];
844void TrackExtrap::recoverTrackParam(
double*
v3,
double charge, TrackParam& trackParam)
849 trackParam.setNonBendingCoor(
v3[0]);
850 trackParam.setBendingCoor(
v3[1]);
851 trackParam.setZ(
v3[2]);
852 double pYZ =
v3[6] * TMath::Sqrt((1. -
v3[3]) * (1. +
v3[3]));
853 trackParam.setInverseBendingMomentum(
charge / pYZ);
854 trackParam.setBendingSlope(
v3[4] /
v3[5]);
855 trackParam.setNonBendingSlope(
v3[3] /
v3[5]);
859bool TrackExtrap::extrapToZRungekutta(TrackParam& trackParam,
double zEnd)
864 if (trackParam.getZ() == zEnd) {
867 double forwardBackward;
868 if (zEnd < trackParam.getZ()) {
869 forwardBackward = 1.0;
871 forwardBackward = -1.0;
875 double chargeExtrap = forwardBackward * TMath::Sign(
double(1.0), trackParam.getInverseBendingMomentum());
876 double v3[7] = {0.}, v3New[7] = {0.};
877 double dZ(0.),
step(0.);
881 double residue = zEnd - trackParam.getZ();
882 while (TMath::Abs(residue) > SRungeKuttaMaxResidue) {
884 dZ = zEnd - trackParam.getZ();
886 step = dZ * TMath::Sqrt(1.0 + trackParam.getBendingSlope() * trackParam.getBendingSlope() +
887 trackParam.getNonBendingSlope() * trackParam.getNonBendingSlope());
888 convertTrackParamForExtrap(trackParam, forwardBackward,
v3);
891 if (++stepNumber > SMaxStepNumber) {
892 LOG(warning) <<
"Too many trials";
895 step = TMath::Abs(step);
896 if (!extrapOneStepRungekutta(chargeExtrap, step,
v3, v3New)) {
899 residue = zEnd - v3New[2];
900 step *= dZ / (v3New[2] - trackParam.getZ());
901 }
while (residue * dZ < 0 && TMath::Abs(residue) > SRungeKuttaMaxResidue);
903 if (v3New[5] *
v3[5] < 0) {
904 LOG(warning) <<
"The track turned around";
908 recoverTrackParam(v3New, chargeExtrap * forwardBackward, trackParam);
912 trackParam.setNonBendingCoor(trackParam.getNonBendingCoor() + residue * trackParam.getNonBendingSlope());
913 trackParam.setBendingCoor(trackParam.getBendingCoor() + residue * trackParam.getBendingSlope());
914 trackParam.setZ(zEnd);
920bool TrackExtrap::extrapToZRungekuttaV2(TrackParam& trackParam,
double zEnd)
926 if (trackParam.getZ() == zEnd) {
930 double residue = zEnd - trackParam.getZ();
931 double forwardBackward = (residue < 0) ? 1. : -1.;
933 convertTrackParamForExtrap(trackParam, forwardBackward,
v3);
934 double charge = TMath::Sign(
double(1.), trackParam.getInverseBendingMomentum());
937 double v3New[7] = {0.};
941 if (++stepNumber > SMaxStepNumber) {
942 LOG(warning) <<
"Too many trials";
947 double slopeX =
v3[3] /
v3[5];
948 double slopeY =
v3[4] /
v3[5];
949 double step = TMath::Abs(residue) * TMath::Sqrt(1.0 + slopeX * slopeX + slopeY * slopeY);
951 if (!extrapOneStepRungekutta(forwardBackward *
charge, step,
v3, v3New)) {
955 if (v3New[5] *
v3[5] < 0) {
956 LOG(warning) <<
"The track turned around";
960 residue = zEnd - v3New[2];
961 if (TMath::Abs(residue) < SRungeKuttaMaxResidueV2) {
965 for (
int i = 0;
i < 7; ++
i) {
970 if (forwardBackward * residue > 0) {
971 forwardBackward = -forwardBackward;
978 recoverTrackParam(v3New,
charge, trackParam);
981 trackParam.setNonBendingCoor(trackParam.getNonBendingCoor() + residue * trackParam.getNonBendingSlope());
982 trackParam.setBendingCoor(trackParam.getBendingCoor() + residue * trackParam.getBendingSlope());
983 trackParam.setZ(zEnd);
989bool TrackExtrap::extrapOneStepRungekutta(
double charge,
double step,
const double* vect,
double* vout)
1014 double h2(0.), h4(0.),
f[4] = {0.};
1015 double xyzt[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
1016 double a(0.),
b(0.),
c(0.), ph(0.), ph2(0.);
1017 double secxs[4] = {0.}, secys[4] = {0.}, seczs[4] = {0.}, hxp[3] = {0.};
1018 double g1(0.), g2(0.), g3(0.), g4(0.), g5(0.), g6(0.), ang2(0.), dxt(0.), dyt(0.), dzt(0.);
1019 double est(0.), at(0.), bt(0.), ct(0.), cba(0.);
1020 double f1(0.),
f2(0.),
f3(0.),
f4(0.),
rho(0.),
tet(0.), hnorm(0.), hp(0.), rho1(0.),
sint(0.), cost(0.);
1030 double maxit = 1992;
1033 const double kdlt = 1e-4;
1034 const double kdlt32 = kdlt / 32.;
1035 const double kthird = 1. / 3.;
1036 const double khalf = 0.5;
1037 const double kec = 2.9979251e-4;
1039 const double kpisqua = 9.86960440109;
1054 for (
int j = 0;
j < 7;
j++) {
1065 if (TMath::Abs(
h) > TMath::Abs(rest)) {
1069 TGeoGlobalMagField::Instance()->Field(vout,
f);
1086 secxs[0] = (
b *
f[2] -
c *
f[1]) * ph2;
1087 secys[0] = (
c *
f[0] -
a *
f[2]) * ph2;
1088 seczs[0] = (
a *
f[1] -
b *
f[0]) * ph2;
1089 ang2 = (secxs[0] * secxs[0] + secys[0] * secys[0] + seczs[0] * seczs[0]);
1090 if (ang2 > kpisqua) {
1094 dxt = h2 *
a + h4 * secxs[0];
1095 dyt = h2 *
b + h4 * secys[0];
1096 dzt = h2 *
c + h4 * seczs[0];
1104 est = TMath::Abs(dxt) + TMath::Abs(dyt) + TMath::Abs(dzt);
1106 if (ncut++ > maxcut) {
1118 TGeoGlobalMagField::Instance()->Field(xyzt,
f);
1125 secxs[1] = (bt *
f[2] - ct *
f[1]) * ph2;
1126 secys[1] = (ct *
f[0] - at *
f[2]) * ph2;
1127 seczs[1] = (at *
f[1] - bt *
f[0]) * ph2;
1131 secxs[2] = (bt *
f[2] - ct *
f[1]) * ph2;
1132 secys[2] = (ct *
f[0] - at *
f[2]) * ph2;
1133 seczs[2] = (at *
f[1] - bt *
f[0]) * ph2;
1134 dxt =
h * (
a + secxs[2]);
1135 dyt =
h * (
b + secys[2]);
1136 dzt =
h * (
c + seczs[2]);
1140 at =
a + 2. * secxs[2];
1141 bt =
b + 2. * secys[2];
1142 ct =
c + 2. * seczs[2];
1144 est = TMath::Abs(dxt) + TMath::Abs(dyt) + TMath::Abs(dzt);
1145 if (est > 2. * TMath::Abs(
h)) {
1146 if (ncut++ > maxcut) {
1158 TGeoGlobalMagField::Instance()->Field(xyzt,
f);
1161 z =
z + (
c + (seczs[0] + seczs[1] + seczs[2]) * kthird) *
h;
1162 y =
y + (
b + (secys[0] + secys[1] + secys[2]) * kthird) *
h;
1163 x =
x + (
a + (secxs[0] + secxs[1] + secxs[2]) * kthird) *
h;
1165 secxs[3] = (bt *
f[2] - ct *
f[1]) * ph2;
1166 secys[3] = (ct *
f[0] - at *
f[2]) * ph2;
1167 seczs[3] = (at *
f[1] - bt *
f[0]) * ph2;
1168 a =
a + (secxs[0] + secxs[3] + 2. * (secxs[1] + secxs[2])) * kthird;
1169 b =
b + (secys[0] + secys[3] + 2. * (secys[1] + secys[2])) * kthird;
1170 c =
c + (seczs[0] + seczs[3] + 2. * (seczs[1] + seczs[2])) * kthird;
1172 est = TMath::Abs(secxs[0] + secxs[3] - (secxs[1] + secxs[2])) +
1173 TMath::Abs(secys[0] + secys[3] - (secys[1] + secys[2])) +
1174 TMath::Abs(seczs[0] + seczs[3] - (seczs[1] + seczs[2]));
1176 if (est > kdlt && TMath::Abs(
h) > 1.e-4) {
1177 if (ncut++ > maxcut) {
1186 if (iter++ > maxit) {
1194 cba = 1. / TMath::Sqrt(
a *
a +
b *
b +
c *
c);
1205 if (rest < 1.e-5 * TMath::Abs(step)) {
1212 LOG(warning) <<
"Ruge-Kutta failed: switch to helix";
1217 f4 = TMath::Sqrt(f1 * f1 + f2 * f2 + f3 * f3);
1219 LOG(warning) <<
"magnetic field at (" << xyzt[0] <<
", " << xyzt[1] <<
", " << xyzt[2] <<
") = " <<
f4 <<
": giving up";
1237 sint = TMath::Sin(tet);
1238 cost = 2. * TMath::Sin(khalf * tet) * TMath::Sin(khalf * tet);
1242 g3 = (
tet -
sint) * hp * rho1;
1247 vout[kix] =
vect[kix] + g1 *
vect[kipx] + g2 * hxp[0] + g3 *
f1;
1248 vout[kiy] =
vect[kiy] + g1 *
vect[kipy] + g2 * hxp[1] + g3 *
f2;
1249 vout[kiz] =
vect[kiz] + g1 *
vect[kipz] + g2 * hxp[2] + g3 *
f3;
1251 vout[kipx] =
vect[kipx] + g4 *
vect[kipx] + g5 * hxp[0] + g6 *
f1;
1252 vout[kipy] =
vect[kipy] + g4 *
vect[kipy] + g5 * hxp[1] + g6 *
f2;
1253 vout[kipz] =
vect[kipz] + g4 *
vect[kipz] + g5 * hxp[2] + g6 *
f3;
1262 LOG(info) <<
"number of times extrapToZCov() is called = " << sNCallExtrapToZCov;
1263 LOG(info) <<
"number of times Field() is called = " << sNCallField;
Definition of the MCH track parameters for internal use.
Class for time synchronization of RawReader instances.
track parameters for internal use
Double_t getInverseBendingMomentum() const
return inverse bending momentum (GeV/c ** -1) times the charge (assumed forward motion)
void setZ(Double_t z)
set Z coordinate (cm)
Bool_t hasCovariances() const
return kTRUE if the covariance matrix exist, kFALSE if not
Double_t getNonBendingCoor() const
return non bending coordinate (cm)
Double_t getZ() const
return Z coordinate (cm)
void addParameters(const TMatrixD ¶meters)
add track parameters
const TMatrixD & getParameters() const
return track parameters
Double_t getNonBendingSlope() const
return non bending slope (cm ** -1)
void setCovariances(const TMatrixD &covariances)
const TMatrixD & getCovariances() const
void setBendingCoor(Double_t bendingCoor)
set bending coordinate (cm)
Double_t getBendingCoor() const
return bending coordinate (cm)
void setParameters(const TMatrixD ¶meters)
set track parameters
void updatePropagator(const TMatrixD &propagator)
Double_t getBendingSlope() const
return bending slope (cm ** -1)
void setNonBendingCoor(Double_t nonBendingCoor)
set non bending coordinate (cm)
float sum(float s, o2::dcs::DataPointValue v)
GLuint GLfloat GLfloat GLfloat x1
GLboolean GLboolean GLboolean b
GLfloat GLfloat GLfloat GLfloat v3
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
value_T gpu::gpustd::array< value_T, 7 > & vect
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"