Project
Loading...
Searching...
No Matches
TrackExtrap.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
18
19#include <TGeoGlobalMagField.h>
20#include <TGeoManager.h>
21#include <TGeoMaterial.h>
22#include <TGeoNode.h>
23#include <TGeoShape.h>
24#include <TMath.h>
25
26#include "Framework/Logger.h"
27
29
30namespace o2
31{
32namespace mch
33{
34
35bool TrackExtrap::sExtrapV2 = false;
36double TrackExtrap::sSimpleBValue = 0.;
37bool TrackExtrap::sFieldON = false;
38std::size_t TrackExtrap::sNCallExtrapToZCov = 0;
39std::size_t TrackExtrap::sNCallField = 0;
40
41//__________________________________________________________________________
43{
46 const double x[3] = {50., 50., SSimpleBPosition};
47 double b[3] = {0., 0., 0.};
48 TGeoGlobalMagField::Instance()->Field(x, b);
49 sSimpleBValue = b[0];
50 sFieldON = (TMath::Abs(sSimpleBValue) > 1.e-10) ? true : false;
51 LOG(info) << "Track extrapolation with magnetic field " << (sFieldON ? "ON" : "OFF");
52}
53
54//__________________________________________________________________________
56{
61 const double correctionFactor = 1.1; // impact parameter is 10% underestimated
62 if (bendingMomentum == 0.) {
63 return 1.e10;
64 }
65 return correctionFactor * (-0.0003 * sSimpleBValue * SSimpleBLength * SSimpleBPosition / bendingMomentum);
66}
67
68//__________________________________________________________________________
70{
75 const double correctionFactor = 1.1; // bending momentum is 10% underestimated
76 if (impactParam == 0.) {
77 return 1.e10;
78 }
79 if (sFieldON) {
80 return correctionFactor * (-0.0003 * sSimpleBValue * SSimpleBLength * SSimpleBPosition / impactParam);
81 } else {
82 return SMostProbBendingMomentum;
83 }
84}
85
86//__________________________________________________________________________
87void TrackExtrap::linearExtrapToZ(TrackParam& trackParam, double zEnd)
88{
91
92 if (trackParam.getZ() == zEnd) {
93 return; // nothing to be done if same z
94 }
95
96 // Compute track parameters
97 double dZ = zEnd - trackParam.getZ();
98 trackParam.setNonBendingCoor(trackParam.getNonBendingCoor() + trackParam.getNonBendingSlope() * dZ);
99 trackParam.setBendingCoor(trackParam.getBendingCoor() + trackParam.getBendingSlope() * dZ);
100 trackParam.setZ(zEnd);
101}
102
103//__________________________________________________________________________
104void TrackExtrap::linearExtrapToZCov(TrackParam& trackParam, double zEnd, bool updatePropagator)
105{
108
109 if (trackParam.getZ() == zEnd) {
110 return; // nothing to be done if same z
111 }
112
113 // No need to propagate the covariance matrix if it does not exist
114 if (!trackParam.hasCovariances()) {
115 LOG(warning) << "Covariance matrix does not exist";
116 // Extrapolate linearly track parameters to "zEnd"
117 linearExtrapToZ(trackParam, zEnd);
118 return;
119 }
120
121 // Compute track parameters
122 double dZ = zEnd - trackParam.getZ();
123 trackParam.setNonBendingCoor(trackParam.getNonBendingCoor() + trackParam.getNonBendingSlope() * dZ);
124 trackParam.setBendingCoor(trackParam.getBendingCoor() + trackParam.getBendingSlope() * dZ);
125 trackParam.setZ(zEnd);
126
127 // Calculate the jacobian related to the track parameters linear extrapolation to "zEnd"
128 TMatrixD jacob(5, 5);
129 jacob.UnitMatrix();
130 jacob(0, 1) = dZ;
131 jacob(2, 3) = dZ;
132
133 // Extrapolate track parameter covariances to "zEnd"
134 TMatrixD tmp(trackParam.getCovariances(), TMatrixD::kMultTranspose, jacob);
135 TMatrixD tmp2(jacob, TMatrixD::kMult, tmp);
136 trackParam.setCovariances(tmp2);
137
138 // Update the propagator if required
139 if (updatePropagator) {
140 trackParam.updatePropagator(jacob);
141 }
142}
143
144//__________________________________________________________________________
145bool TrackExtrap::extrapToZ(TrackParam& trackParam, double zEnd)
146{
149 if (!sFieldON) {
150 linearExtrapToZ(trackParam, zEnd);
151 return true;
152 } else if (sExtrapV2) {
153 return extrapToZRungekuttaV2(trackParam, zEnd);
154 } else {
155 return extrapToZRungekutta(trackParam, zEnd);
156 }
157}
158
159//__________________________________________________________________________
160bool TrackExtrap::extrapToZCov(TrackParam& trackParam, double zEnd, bool updatePropagator)
161{
164
165 ++sNCallExtrapToZCov;
166
167 if (trackParam.getZ() == zEnd) {
168 return true; // nothing to be done if same z
169 }
170
171 if (!sFieldON) { // linear extrapolation if no magnetic field
172 linearExtrapToZCov(trackParam, zEnd, updatePropagator);
173 return true;
174 }
175
176 // No need to propagate the covariance matrix if it does not exist
177 if (!trackParam.hasCovariances()) {
178 LOG(warning) << "Covariance matrix does not exist";
179 // Extrapolate track parameters to "zEnd"
180 return extrapToZ(trackParam, zEnd);
181 }
182
183 // Save the actual track parameters
184 TrackParam trackParamSave(trackParam);
185 TMatrixD paramSave(trackParamSave.getParameters());
186 double zBegin = trackParamSave.getZ();
187
188 // Get reference to the parameter covariance matrix
189 const TMatrixD& kParamCov = trackParam.getCovariances();
190
191 // Extrapolate track parameters to "zEnd"
192 // Do not update the covariance matrix if the extrapolation failed
193 if (!extrapToZ(trackParam, zEnd)) {
194 return false;
195 }
196
197 // Get reference to the extrapolated parameters
198 const TMatrixD& extrapParam = trackParam.getParameters();
199
200 // Calculate the jacobian related to the track parameters extrapolation to "zEnd"
201 TMatrixD jacob(5, 5);
202 jacob.Zero();
203 TMatrixD dParam(5, 1);
204 double direction[5] = {-1., -1., 1., 1., -1.};
205 for (int i = 0; i < 5; i++) {
206 // Skip jacobian calculation for parameters with no associated error
207 if (kParamCov(i, i) <= 0.) {
208 continue;
209 }
210
211 // Small variation of parameter i only
212 for (int j = 0; j < 5; j++) {
213 if (j == i) {
214 dParam(j, 0) = TMath::Sqrt(kParamCov(i, i));
215 dParam(j, 0) *= TMath::Sign(1., direction[j] * paramSave(j, 0)); // variation always in the same direction
216 } else {
217 dParam(j, 0) = 0.;
218 }
219 }
220
221 // Set new parameters
222 trackParamSave.setParameters(paramSave);
223 trackParamSave.addParameters(dParam);
224 trackParamSave.setZ(zBegin);
225
226 // Extrapolate new track parameters to "zEnd"
227 if (!extrapToZ(trackParamSave, zEnd)) {
228 LOG(warning) << "Bad covariance matrix";
229 return false;
230 }
231
232 // Calculate the jacobian
233 TMatrixD jacobji(trackParamSave.getParameters(), TMatrixD::kMinus, extrapParam);
234 jacobji *= 1. / dParam(i, 0);
235 jacob.SetSub(0, i, jacobji);
236 }
237
238 // Extrapolate track parameter covariances to "zEnd"
239 TMatrixD tmp(kParamCov, TMatrixD::kMultTranspose, jacob);
240 TMatrixD tmp2(jacob, TMatrixD::kMult, tmp);
241 trackParam.setCovariances(tmp2);
242
243 // Update the propagator if required
244 if (updatePropagator) {
245 trackParam.updatePropagator(jacob);
246 }
247
248 return true;
249}
250
251//__________________________________________________________________________
253{
256
257 if (trackParam.getZ() == SMIDZ) {
258 return true; // nothing to be done
259 }
260
261 // check the track position with respect to the muon filter (spectro z<0)
262 if (trackParam.getZ() < SMuonFilterZBeg) {
263 LOG(warning) << "The track already passed the beginning of the muon filter";
264 return false;
265 }
266
267 // propagate through the muon filter and add MCS effets
268 if (!extrapToZCov(trackParam, SMuonFilterZEnd)) {
269 return false;
270 }
271 addMCSEffect(trackParam, -SMuonFilterThickness, SMuonFilterX0);
272
273 // propagate to the first MID chamber
274 return extrapToZCov(trackParam, SMIDZ);
275}
276
277//__________________________________________________________________________
278bool TrackExtrap::extrapToVertex(TrackParam& trackParam, double xVtx, double yVtx, double zVtx,
279 double errXVtx, double errYVtx, bool correctForMCS, bool correctForEnergyLoss)
280{
288
289 if (trackParam.getZ() == zVtx) {
290 return true; // nothing to be done if already at vertex
291 }
292
293 // Check the vertex position with respect to the absorber (spectro z<0)
294 if (zVtx < SAbsZBeg) {
295 if (zVtx < SAbsZEnd) {
296 LOG(warning) << "Ending Z (" << zVtx << ") downstream the front absorber (zAbsorberEnd = " << SAbsZEnd << ")";
297 return false;
298 } else {
299 LOG(warning) << "Ending Z (" << zVtx << ") inside the front absorber (" << SAbsZBeg << ", " << SAbsZEnd << ")";
300 return false;
301 }
302 }
303
304 // Check the track position with respect to the vertex and the absorber (spectro z<0)
305 if (trackParam.getZ() > SAbsZEnd) {
306 if (trackParam.getZ() > zVtx) {
307 LOG(warning) << "Starting Z (" << trackParam.getZ() << ") upstream the vertex (zVtx = " << zVtx << ")";
308 return false;
309 } else if (trackParam.getZ() > SAbsZBeg) {
310 LOG(warning) << "Starting Z (" << trackParam.getZ() << ") upstream the front absorber (zAbsorberBegin = " << SAbsZBeg << ")";
311 return false;
312 } else {
313 LOG(warning) << "Starting Z (" << trackParam.getZ() << ") inside the front absorber (" << SAbsZBeg << ", " << SAbsZEnd << ")";
314 return false;
315 }
316 }
317
318 // Extrapolate track parameters (and covariances if any) to the end of the absorber
319 if ((trackParam.hasCovariances() && !extrapToZCov(trackParam, SAbsZEnd)) ||
320 (!trackParam.hasCovariances() && !extrapToZ(trackParam, SAbsZEnd))) {
321 return false;
322 }
323
324 // Get absorber correction parameters assuming linear propagation in absorber
325 double trackXYZOut[3] = {trackParam.getNonBendingCoor(), trackParam.getBendingCoor(), trackParam.getZ()};
326 double trackXYZIn[3] = {0., 0., 0.};
327 if (correctForMCS) { // assume linear propagation to the vertex
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]);
331 } else { // or standard propagation without vertex constraint
332 TrackParam trackParamIn(trackParam);
333 if (!extrapToZ(trackParamIn, SAbsZBeg)) {
334 return false;
335 }
336 trackXYZIn[0] = trackParamIn.getNonBendingCoor();
337 trackXYZIn[1] = trackParamIn.getBendingCoor();
338 trackXYZIn[2] = trackParamIn.getZ();
339 }
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)) {
343 return false;
344 }
345
346 // Compute track parameters and covariances at vertex according to correctForMCS and correctForEnergyLoss flags
347 if (correctForMCS) {
348 if (correctForEnergyLoss) {
349 // Correct for multiple scattering and energy loss
350 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
351 if (!correctMCSEffectInAbsorber(trackParam, xVtx, yVtx, zVtx, errXVtx, errYVtx, trackXYZIn[2], pathLength, f0, f1, f2)) {
352 return false;
353 }
354 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
355 } else {
356 // Correct for multiple scattering
357 if (!correctMCSEffectInAbsorber(trackParam, xVtx, yVtx, zVtx, errXVtx, errYVtx, trackXYZIn[2], pathLength, f0, f1, f2)) {
358 return false;
359 }
360 }
361 } else {
362 if (correctForEnergyLoss) {
363 // Correct for energy loss add multiple scattering dispersion in covariance matrix
364 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
365 addMCSEffectInAbsorber(trackParam, -pathLength, f0, f1, f2); // (spectro. (z<0))
366 if (!extrapToZCov(trackParam, trackXYZIn[2])) {
367 return false;
368 }
369 correctELossEffectInAbsorber(trackParam, 0.5 * totalELoss, 0.5 * sigmaELoss2);
370 if (!extrapToZCov(trackParam, zVtx)) {
371 return false;
372 }
373 } else {
374 // add multiple scattering dispersion in covariance matrix
375 addMCSEffectInAbsorber(trackParam, -pathLength, f0, f1, f2); // (spectro. (z<0))
376 if (!extrapToZCov(trackParam, zVtx)) {
377 return false;
378 }
379 }
380 }
381
382 return true;
383}
384
385//__________________________________________________________________________
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)
389{
399
400 // Check whether the geometry is available
401 if (!gGeoManager) {
402 LOG(warning) << "geometry is missing";
403 return false;
404 }
405
406 // Initialize starting point and direction
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";
412 return false;
413 }
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);
416 if (!currentnode) {
417 LOG(warning) << "starting point out of geometry";
418 return false;
419 }
420
421 // loop over absorber slices and calculate absorber's parameters
422 f0 = f1 = f2 = meanRho = totalELoss = 0.;
423 double sigmaELoss(0.);
424 double zB = trackXYZIn[2];
425 double remainingPathLength = pathLength;
426 do {
427
428 // Get material properties
429 TGeoMaterial* material = currentnode->GetVolume()->GetMedium()->GetMaterial();
430 double rho = material->GetDensity(); // material density (g/cm3)
431 double x0 = material->GetRadLen(); // radiation-length (cm-1)
432 double atomicZ = material->GetZ(); // Z of material
433 double atomicZoverA(0.); // Z/A of material
434 if (material->IsMixture()) {
435 TGeoMixture* mixture = static_cast<TGeoMixture*>(material);
436 double sum(0.);
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];
440 }
441 atomicZoverA /= sum;
442 } else {
443 atomicZoverA = atomicZ / material->GetA();
444 }
445
446 // Get path length within this material
447 gGeoManager->FindNextBoundary(remainingPathLength);
448 double localPathLength = gGeoManager->GetStep() + 1.e-6;
449 // Check if boundary within remaining path length. If so, make sure to cross the boundary to prepare the next step
450 if (localPathLength >= remainingPathLength) {
451 localPathLength = remainingPathLength;
452 } else {
453 currentnode = gGeoManager->Step();
454 if (!currentnode) {
455 LOG(warning) << "navigation failed";
456 return false;
457 }
458 if (!gGeoManager->IsEntering()) {
459 // make another small step to try to enter in new absorber slice
460 gGeoManager->SetStep(0.001);
461 currentnode = gGeoManager->Step();
462 if (!gGeoManager->IsEntering() || !currentnode) {
463 LOG(warning) << "navigation failed";
464 return false;
465 }
466 localPathLength += 0.001;
467 }
468 }
469
470 // calculate absorber's parameters
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);
480
481 // prepare next step
482 zB = zE;
483 remainingPathLength -= localPathLength;
484 } while (remainingPathLength > TGeoShape::Tolerance());
485
486 meanRho /= pathLength;
487 sigmaELoss2 = sigmaELoss * sigmaELoss;
488
489 return true;
490}
491
492//__________________________________________________________________________
493double TrackExtrap::getMCSAngle2(const TrackParam& param, double dZ, double x0)
494{
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);
503 // Path length in the material
504 double pathLength = TMath::Abs(dZ) * TMath::Sqrt(1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
505 // relativistic velocity
506 double velo = 1.;
507 // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory
508 double theta02 = 0.0136 / velo * (1 + 0.038 * TMath::Log(pathLength / x0));
509 return theta02 * theta02 * inverseTotalMomentum2 * pathLength / x0;
510}
511
512//__________________________________________________________________________
513void TrackExtrap::addMCSEffect(TrackParam& trackParam, double dZ, double x0)
514{
520
521 double bendingSlope = trackParam.getBendingSlope();
522 double nonBendingSlope = trackParam.getNonBendingSlope();
523 double inverseBendingMomentum = trackParam.getInverseBendingMomentum();
524 double inverseTotalMomentum2 = inverseBendingMomentum * inverseBendingMomentum * (1.0 + bendingSlope * bendingSlope) /
525 (1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
526 // Path length in the material
527 double signedPathLength = dZ * TMath::Sqrt(1.0 + bendingSlope * bendingSlope + nonBendingSlope * nonBendingSlope);
528 double pathLengthOverX0 = (x0 > 0.) ? TMath::Abs(signedPathLength) / x0 : TMath::Abs(signedPathLength);
529 // relativistic velocity
530 double velo = 1.;
531 // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory
532 double theta02 = 0.0136 / velo * (1 + 0.038 * TMath::Log(pathLengthOverX0));
533 theta02 *= theta02 * inverseTotalMomentum2 * pathLengthOverX0;
534
535 double varCoor = (x0 > 0.) ? signedPathLength * signedPathLength * theta02 / 3. : 0.;
536 double varSlop = theta02;
537 double covCorrSlope = (x0 > 0.) ? signedPathLength * theta02 / 2. : 0.;
538
539 // Set MCS covariance matrix
540 TMatrixD newParamCov(trackParam.getCovariances());
541 // Non bending plane
542 newParamCov(0, 0) += varCoor;
543 newParamCov(0, 1) += covCorrSlope;
544 newParamCov(1, 0) += covCorrSlope;
545 newParamCov(1, 1) += varSlop;
546 // Bending plane
547 newParamCov(2, 2) += varCoor;
548 newParamCov(2, 3) += covCorrSlope;
549 newParamCov(3, 2) += covCorrSlope;
550 newParamCov(3, 3) += varSlop;
551
552 // Set momentum related covariances if B!=0
553 if (sFieldON) {
554 // compute derivative d(q/Pxy) / dSlopeX and d(q/Pxy) / dSlopeY
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);
560 // Inverse bending momentum (due to dependences with bending and non bending slopes)
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;
570 }
571
572 // Set new covariances
573 trackParam.setCovariances(newParamCov);
574}
575
576//__________________________________________________________________________
577void TrackExtrap::addMCSEffectInAbsorber(TrackParam& param, double signedPathLength, double f0, double f1, double f2)
578{
581
582 // absorber related covariance parameters
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); // velocity = 1
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;
592
593 // Set MCS covariance matrix
594 TMatrixD newParamCov(param.getCovariances());
595 // Non bending plane
596 newParamCov(0, 0) += varCoor;
597 newParamCov(0, 1) += covCorrSlope;
598 newParamCov(1, 0) += covCorrSlope;
599 newParamCov(1, 1) += varSlop;
600 // Bending plane
601 newParamCov(2, 2) += varCoor;
602 newParamCov(2, 3) += covCorrSlope;
603 newParamCov(3, 2) += covCorrSlope;
604 newParamCov(3, 3) += varSlop;
605
606 // Set momentum related covariances if B!=0
607 if (sFieldON) {
608 // compute derivative d(q/Pxy) / dSlopeX and d(q/Pxy) / dSlopeY
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);
612 // Inverse bending momentum (due to dependences with bending and non bending slopes)
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;
622 }
623
624 // Set new covariances
625 param.setCovariances(newParamCov);
626}
627
628//__________________________________________________________________________
629double TrackExtrap::betheBloch(double pTotal, double pathLength, double rho, double atomicZ, double atomicZoverA)
630{
634
635 static constexpr double mK = 0.307075e-3; // [GeV*cm^2/g]
636 static constexpr double me = 0.511e-3; // [GeV/c^2]
637 static constexpr double x0 = 0.2 * 2.303; // density effect first junction point * 2.303
638 static constexpr double x1 = 3. * 2.303; // density effect second junction point * 2.303
639
640 double bg = pTotal / SMuMass; // beta*gamma
641 double bg2 = bg * bg;
642 double maxT = 2 * me * bg2; // neglecting the electron mass
643
644 // mean exitation energy (GeV)
645 double mI = (atomicZ < 13) ? (12. * atomicZ + 7.) * 1.e-9 : (9.76 * atomicZ + 58.8 * TMath::Power(atomicZ, -0.19)) * 1.e-9;
646
647 // density effect
648 double x = TMath::Log(bg);
649 double lhwI = TMath::Log(28.816 * 1e-9 * TMath::Sqrt(rho * atomicZoverA) / mI);
650 double d2(0.);
651 if (x > x1) {
652 d2 = lhwI + x - 0.5;
653 } else if (x > x0) {
654 double r = (x1 - x) / (x1 - x0);
655 d2 = lhwI + x - 0.5 + (0.5 - lhwI - x0) * r * r * r;
656 }
657
658 return pathLength * rho * (mK * atomicZoverA * (1 + bg2) / bg2 * (0.5 * TMath::Log(2 * me * bg2 * maxT / (mI * mI)) - bg2 / (1 + bg2) - d2));
659}
660
661//__________________________________________________________________________
662double TrackExtrap::energyLossFluctuation(double pTotal, double pathLength, double rho, double atomicZoverA)
663{
666
667 static constexpr double mK = 0.307075e-3; // GeV.g^-1.cm^2
668
669 double p2 = pTotal * pTotal;
670 double beta2 = p2 / (p2 + SMuMass * SMuMass);
671
672 double fwhm = 2. * mK * rho * pathLength * atomicZoverA / beta2; // FWHM of the energy loss Landau distribution
673
674 return fwhm / TMath::Sqrt(8. * log(2.)); // gaussian: fwmh = 2 * srqt(2*ln(2)) * sigma (i.e. fwmh = 2.35 * sigma)
675}
676
677//__________________________________________________________________________
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)
680{
685
686 // Position of the Branson plane (spectro. (z<0))
687 double zB = (f1 > 0.) ? absZBeg - f2 / f1 : 0.;
688
689 // Add MCS effects to current parameter covariances (spectro. (z<0))
690 addMCSEffectInAbsorber(param, -pathLength, f0, f1, f2);
691
692 // Get track parameters and covariances in the Branson plane corrected for magnetic field effect
693 if (!extrapToZCov(param, zVtx)) {
694 return false;
695 }
697
698 // compute track parameters at vertex
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));
707
708 // Get covariances in (X, SlopeX, Y, SlopeY, q*PTot) coordinate system
709 TMatrixD paramCovP(param.getCovariances());
710 cov2CovP(param.getParameters(), paramCovP);
711
712 // Get the covariance matrix in the (XVtx, X, YVtx, Y, q*PTot) coordinate system
713 TMatrixD paramCovVtx(5, 5);
714 paramCovVtx.Zero();
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);
726
727 // Jacobian of the transformation (XVtx, X, YVtx, Y, q*PTot) -> (XVtx, SlopeXVtx, YVtx, SlopeYVtx, q*PTotVtx)
728 TMatrixD jacob(5, 5);
729 jacob.UnitMatrix();
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);
734
735 // Compute covariances at vertex in the (XVtx, SlopeXVtx, YVtx, SlopeYVtx, q*PTotVtx) coordinate system
736 TMatrixD tmp(paramCovVtx, TMatrixD::kMultTranspose, jacob);
737 TMatrixD newParamCov(jacob, TMatrixD::kMult, tmp);
738
739 // Compute covariances at vertex in the (XVtx, SlopeXVtx, YVtx, SlopeYVtx, q/PyzVtx) coordinate system
740 covP2Cov(newParam, newParamCov);
741
742 // Set parameters and covariances at vertex
743 param.setParameters(newParam);
744 param.setZ(zVtx);
745 param.setCovariances(newParamCov);
746
747 return true;
748}
749
750//__________________________________________________________________________
751void TrackExtrap::correctELossEffectInAbsorber(TrackParam& param, double eLoss, double sigmaELoss2)
752{
754
755 // Get parameter covariances in (X, SlopeX, Y, SlopeY, q*PTot) coordinate system
756 TMatrixD newParamCov(param.getCovariances());
757 cov2CovP(param.getParameters(), newParamCov);
758
759 // Compute new parameters corrected for energy loss
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));
769
770 // Add effects of energy loss fluctuation to covariances
771 newParamCov(4, 4) += eCorr * eCorr / pCorr / pCorr * sigmaELoss2;
772
773 // Get new parameter covariances in (X, SlopeX, Y, SlopeY, q/Pyz) coordinate system
774 covP2Cov(param.getParameters(), newParamCov);
775
776 // Set new parameter covariances
777 param.setCovariances(newParamCov);
778}
779
780//__________________________________________________________________________
781void TrackExtrap::cov2CovP(const TMatrixD& param, TMatrixD& cov)
782{
785
786 // charge * total momentum
787 double qPTot = TMath::Sqrt(1. + param(1, 0) * param(1, 0) + param(3, 0) * param(3, 0)) /
788 TMath::Sqrt(1. + param(3, 0) * param(3, 0)) / param(4, 0);
789
790 // Jacobian of the opposite transformation
791 TMatrixD jacob(5, 5);
792 jacob.UnitMatrix();
793 jacob(4, 1) = qPTot * param(1, 0) / (1. + param(1, 0) * param(1, 0) + param(3, 0) * param(3, 0));
794 jacob(4, 3) = -qPTot * param(1, 0) * param(1, 0) * param(3, 0) /
795 (1. + param(3, 0) * param(3, 0)) / (1. + param(1, 0) * param(1, 0) + param(3, 0) * param(3, 0));
796 jacob(4, 4) = -qPTot / param(4, 0);
797
798 // compute covariances in new coordinate system
799 TMatrixD tmp(cov, TMatrixD::kMultTranspose, jacob);
800 cov.Mult(jacob, tmp);
801}
802
803//__________________________________________________________________________
804void TrackExtrap::covP2Cov(const TMatrixD& param, TMatrixD& covP)
805{
808
809 // charge * total momentum
810 double qPTot = TMath::Sqrt(1. + param(1, 0) * param(1, 0) + param(3, 0) * param(3, 0)) /
811 TMath::Sqrt(1. + param(3, 0) * param(3, 0)) / param(4, 0);
812
813 // Jacobian of the transformation
814 TMatrixD jacob(5, 5);
815 jacob.UnitMatrix();
816 jacob(4, 1) = param(4, 0) * param(1, 0) / (1. + param(1, 0) * param(1, 0) + param(3, 0) * param(3, 0));
817 jacob(4, 3) = -param(4, 0) * param(1, 0) * param(1, 0) * param(3, 0) /
818 (1. + param(3, 0) * param(3, 0)) / (1. + param(1, 0) * param(1, 0) + param(3, 0) * param(3, 0));
819 jacob(4, 4) = -param(4, 0) / qPTot;
820
821 // compute covariances in new coordinate system
822 TMatrixD tmp(covP, TMatrixD::kMultTranspose, jacob);
823 covP.Mult(jacob, tmp);
824}
825
826//__________________________________________________________________________
827void TrackExtrap::convertTrackParamForExtrap(TrackParam& trackParam, double forwardBackward, double* v3)
828{
832 v3[0] = trackParam.getNonBendingCoor(); // X
833 v3[1] = trackParam.getBendingCoor(); // Y
834 v3[2] = trackParam.getZ(); // Z
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()); // P
838 v3[5] = -forwardBackward * pZ / v3[6]; // PZ/P spectro. z<0
839 v3[3] = trackParam.getNonBendingSlope() * v3[5]; // PX/P
840 v3[4] = trackParam.getBendingSlope() * v3[5]; // PY/P
841}
842
843//__________________________________________________________________________
844void TrackExtrap::recoverTrackParam(double* v3, double charge, TrackParam& trackParam)
845{
849 trackParam.setNonBendingCoor(v3[0]); // X
850 trackParam.setBendingCoor(v3[1]); // Y
851 trackParam.setZ(v3[2]); // Z
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]);
856}
857
858//__________________________________________________________________________
859bool TrackExtrap::extrapToZRungekutta(TrackParam& trackParam, double zEnd)
860{
864 if (trackParam.getZ() == zEnd) {
865 return true; // nothing to be done if same Z
866 }
867 double forwardBackward; // +1 if forward, -1 if backward
868 if (zEnd < trackParam.getZ()) {
869 forwardBackward = 1.0; // spectro. z<0
870 } else {
871 forwardBackward = -1.0;
872 }
873 // sign of charge (sign of fInverseBendingMomentum if forward motion)
874 // must be changed if backward extrapolation
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.);
878 int stepNumber = 0;
879
880 // Extrapolation loop (until within tolerance or the track turn around)
881 double residue = zEnd - trackParam.getZ();
882 while (TMath::Abs(residue) > SRungeKuttaMaxResidue) {
883
884 dZ = zEnd - trackParam.getZ();
885 // step length assuming linear trajectory
886 step = dZ * TMath::Sqrt(1.0 + trackParam.getBendingSlope() * trackParam.getBendingSlope() +
887 trackParam.getNonBendingSlope() * trackParam.getNonBendingSlope());
888 convertTrackParamForExtrap(trackParam, forwardBackward, v3);
889
890 do { // reduce step length while zEnd overstepped
891 if (++stepNumber > SMaxStepNumber) {
892 LOG(warning) << "Too many trials";
893 return false;
894 }
895 step = TMath::Abs(step);
896 if (!extrapOneStepRungekutta(chargeExtrap, step, v3, v3New)) {
897 return false;
898 }
899 residue = zEnd - v3New[2];
900 step *= dZ / (v3New[2] - trackParam.getZ());
901 } while (residue * dZ < 0 && TMath::Abs(residue) > SRungeKuttaMaxResidue);
902
903 if (v3New[5] * v3[5] < 0) { // the track turned around
904 LOG(warning) << "The track turned around";
905 return false;
906 }
907
908 recoverTrackParam(v3New, chargeExtrap * forwardBackward, trackParam);
909 }
910
911 // terminate the extropolation with a straight line up to the exact "zEnd" value
912 trackParam.setNonBendingCoor(trackParam.getNonBendingCoor() + residue * trackParam.getNonBendingSlope());
913 trackParam.setBendingCoor(trackParam.getBendingCoor() + residue * trackParam.getBendingSlope());
914 trackParam.setZ(zEnd);
915
916 return true;
917}
918
919//__________________________________________________________________________
920bool TrackExtrap::extrapToZRungekuttaV2(TrackParam& trackParam, double zEnd)
921{
925
926 if (trackParam.getZ() == zEnd) {
927 return true; // nothing to be done if same Z
928 }
929
930 double residue = zEnd - trackParam.getZ();
931 double forwardBackward = (residue < 0) ? 1. : -1.; // +1 if forward, -1 if backward
932 double v3[7] = {0.};
933 convertTrackParamForExtrap(trackParam, forwardBackward, v3);
934 double charge = TMath::Sign(double(1.), trackParam.getInverseBendingMomentum());
935
936 // Extrapolation loop (until within tolerance or the track turn around)
937 double v3New[7] = {0.};
938 int stepNumber = 0;
939 while (true) {
940
941 if (++stepNumber > SMaxStepNumber) {
942 LOG(warning) << "Too many trials";
943 return false;
944 }
945
946 // step length assuming linear trajectory
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);
950
951 if (!extrapOneStepRungekutta(forwardBackward * charge, step, v3, v3New)) {
952 return false;
953 }
954
955 if (v3New[5] * v3[5] < 0) {
956 LOG(warning) << "The track turned around";
957 return false;
958 }
959
960 residue = zEnd - v3New[2];
961 if (TMath::Abs(residue) < SRungeKuttaMaxResidueV2) {
962 break;
963 }
964
965 for (int i = 0; i < 7; ++i) {
966 v3[i] = v3New[i];
967 }
968
969 // invert the sens of propagation if the track went too far
970 if (forwardBackward * residue > 0) {
971 forwardBackward = -forwardBackward;
972 v3[3] = -v3[3];
973 v3[4] = -v3[4];
974 v3[5] = -v3[5];
975 }
976 }
977
978 recoverTrackParam(v3New, charge, trackParam);
979
980 // terminate the extrapolation with a straight line up to the exact "zEnd" value
981 trackParam.setNonBendingCoor(trackParam.getNonBendingCoor() + residue * trackParam.getNonBendingSlope());
982 trackParam.setBendingCoor(trackParam.getBendingCoor() + residue * trackParam.getBendingSlope());
983 trackParam.setZ(zEnd);
984
985 return true;
986}
987
988//__________________________________________________________________________
989bool TrackExtrap::extrapOneStepRungekutta(double charge, double step, const double* vect, double* vout)
990{
1013
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.);
1021
1022 double x(0.);
1023 double y(0.);
1024 double z(0.);
1025
1026 double xt(0.);
1027 double yt(0.);
1028 double zt(0.);
1029
1030 double maxit = 1992;
1031 double maxcut = 11;
1032
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;
1038
1039 const double kpisqua = 9.86960440109;
1040 const int kix = 0;
1041 const int kiy = 1;
1042 const int kiz = 2;
1043 const int kipx = 3;
1044 const int kipy = 4;
1045 const int kipz = 5;
1046
1047 // *.
1048 // *. ------------------------------------------------------------------
1049 // *.
1050 // * this constant is for units cm,gev/c and kgauss
1051 // *
1052 int iter = 0;
1053 int ncut = 0;
1054 for (int j = 0; j < 7; j++) {
1055 vout[j] = vect[j];
1056 }
1057
1058 double pinv = kec * charge / vect[6];
1059 double tl = 0.;
1060 double h = step;
1061 double rest(0.);
1062
1063 do {
1064 rest = step - tl;
1065 if (TMath::Abs(h) > TMath::Abs(rest)) {
1066 h = rest;
1067 }
1068 // cmodif: call gufld(vout,f) changed into:
1069 TGeoGlobalMagField::Instance()->Field(vout, f);
1070 ++sNCallField;
1071
1072 // *
1073 // * start of integration
1074 // *
1075 x = vout[0];
1076 y = vout[1];
1077 z = vout[2];
1078 a = vout[3];
1079 b = vout[4];
1080 c = vout[5];
1081
1082 h2 = khalf * h;
1083 h4 = khalf * h2;
1084 ph = pinv * h;
1085 ph2 = khalf * ph;
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) {
1091 break;
1092 }
1093
1094 dxt = h2 * a + h4 * secxs[0];
1095 dyt = h2 * b + h4 * secys[0];
1096 dzt = h2 * c + h4 * seczs[0];
1097 xt = x + dxt;
1098 yt = y + dyt;
1099 zt = z + dzt;
1100 // *
1101 // * second intermediate point
1102 // *
1103
1104 est = TMath::Abs(dxt) + TMath::Abs(dyt) + TMath::Abs(dzt);
1105 if (est > h) {
1106 if (ncut++ > maxcut) {
1107 break;
1108 }
1109 h *= khalf;
1110 continue;
1111 }
1112
1113 xyzt[0] = xt;
1114 xyzt[1] = yt;
1115 xyzt[2] = zt;
1116
1117 // cmodif: call gufld(xyzt,f) changed into:
1118 TGeoGlobalMagField::Instance()->Field(xyzt, f);
1119 ++sNCallField;
1120
1121 at = a + secxs[0];
1122 bt = b + secys[0];
1123 ct = c + seczs[0];
1124
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;
1128 at = a + secxs[1];
1129 bt = b + secys[1];
1130 ct = c + seczs[1];
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]);
1137 xt = x + dxt;
1138 yt = y + dyt;
1139 zt = z + dzt;
1140 at = a + 2. * secxs[2];
1141 bt = b + 2. * secys[2];
1142 ct = c + 2. * seczs[2];
1143
1144 est = TMath::Abs(dxt) + TMath::Abs(dyt) + TMath::Abs(dzt);
1145 if (est > 2. * TMath::Abs(h)) {
1146 if (ncut++ > maxcut) {
1147 break;
1148 }
1149 h *= khalf;
1150 continue;
1151 }
1152
1153 xyzt[0] = xt;
1154 xyzt[1] = yt;
1155 xyzt[2] = zt;
1156
1157 // cmodif: call gufld(xyzt,f) changed into:
1158 TGeoGlobalMagField::Instance()->Field(xyzt, f);
1159 ++sNCallField;
1160
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;
1164
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;
1171
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]));
1175
1176 if (est > kdlt && TMath::Abs(h) > 1.e-4) {
1177 if (ncut++ > maxcut) {
1178 break;
1179 }
1180 h *= khalf;
1181 continue;
1182 }
1183
1184 ncut = 0;
1185 // * if too many iterations, go to helix
1186 if (iter++ > maxit) {
1187 break;
1188 }
1189
1190 tl += h;
1191 if (est < kdlt32) {
1192 h *= 2.;
1193 }
1194 cba = 1. / TMath::Sqrt(a * a + b * b + c * c);
1195 vout[0] = x;
1196 vout[1] = y;
1197 vout[2] = z;
1198 vout[3] = cba * a;
1199 vout[4] = cba * b;
1200 vout[5] = cba * c;
1201 rest = step - tl;
1202 if (step < 0.) {
1203 rest = -rest;
1204 }
1205 if (rest < 1.e-5 * TMath::Abs(step)) {
1206 return true;
1207 }
1208
1209 } while (1);
1210
1211 // angle too big, use helix
1212 LOG(warning) << "Ruge-Kutta failed: switch to helix";
1213
1214 f1 = f[0];
1215 f2 = f[1];
1216 f3 = f[2];
1217 f4 = TMath::Sqrt(f1 * f1 + f2 * f2 + f3 * f3);
1218 if (f4 < 1.e-10) {
1219 LOG(warning) << "magnetic field at (" << xyzt[0] << ", " << xyzt[1] << ", " << xyzt[2] << ") = " << f4 << ": giving up";
1220 return false;
1221 }
1222 rho = -f4 * pinv;
1223 tet = rho * step;
1224
1225 hnorm = 1. / f4;
1226 f1 = f1 * hnorm;
1227 f2 = f2 * hnorm;
1228 f3 = f3 * hnorm;
1229
1230 hxp[0] = f2 * vect[kipz] - f3 * vect[kipy];
1231 hxp[1] = f3 * vect[kipx] - f1 * vect[kipz];
1232 hxp[2] = f1 * vect[kipy] - f2 * vect[kipx];
1233
1234 hp = f1 * vect[kipx] + f2 * vect[kipy] + f3 * vect[kipz];
1235
1236 rho1 = 1. / rho;
1237 sint = TMath::Sin(tet);
1238 cost = 2. * TMath::Sin(khalf * tet) * TMath::Sin(khalf * tet);
1239
1240 g1 = sint * rho1;
1241 g2 = cost * rho1;
1242 g3 = (tet - sint) * hp * rho1;
1243 g4 = -cost;
1244 g5 = sint;
1245 g6 = cost * hp;
1246
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;
1250
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;
1254
1255 return true;
1256}
1257
1258//__________________________________________________________________________
1260{
1262 LOG(info) << "number of times extrapToZCov() is called = " << sNCallExtrapToZCov;
1263 LOG(info) << "number of times Field() is called = " << sNCallField;
1264}
1265
1266} // namespace mch
1267} // namespace o2
int16_t charge
Definition RawEventData.h:5
int32_t i
constexpr int p2()
uint32_t j
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Definition of tools for track extrapolation.
Definition of the MCH track parameters for internal use.
Class for time synchronization of RawReader instances.
static bool extrapToZ(TrackParam &trackParam, double zEnd)
static void addMCSEffect(TrackParam &trackParam, double dZ, double x0)
static void setField()
static bool extrapToVertex(TrackParam &trackParam, double xVtx, double yVtx, double zVtx, double errXVtx, double errYVtx)
Definition TrackExtrap.h:61
static void linearExtrapToZ(TrackParam &trackParam, double zEnd)
static double getMCSAngle2(const TrackParam &param, double dZ, double x0)
static bool extrapToZCov(TrackParam &trackParam, double zEnd, bool updatePropagator=false)
static double getBendingMomentumFromImpactParam(double impactParam)
static bool extrapToMID(TrackParam &trackParam)
static double getImpactParamFromBendingMomentum(double bendingMomentum)
static void printNCalls()
static void linearExtrapToZCov(TrackParam &trackParam, double zEnd, bool updatePropagator=false)
track parameters for internal use
Definition TrackParam.h:34
Double_t getInverseBendingMomentum() const
return inverse bending momentum (GeV/c ** -1) times the charge (assumed forward motion)
Definition TrackParam.h:67
void setZ(Double_t z)
set Z coordinate (cm)
Definition TrackParam.h:49
Bool_t hasCovariances() const
return kTRUE if the covariance matrix exist, kFALSE if not
Definition TrackParam.h:95
Double_t getNonBendingCoor() const
return non bending coordinate (cm)
Definition TrackParam.h:51
Double_t getZ() const
return Z coordinate (cm)
Definition TrackParam.h:47
void addParameters(const TMatrixD &parameters)
add track parameters
Definition TrackParam.h:87
const TMatrixD & getParameters() const
return track parameters
Definition TrackParam.h:81
Double_t getNonBendingSlope() const
return non bending slope (cm ** -1)
Definition TrackParam.h:55
void setCovariances(const TMatrixD &covariances)
const TMatrixD & getCovariances() const
void setBendingCoor(Double_t bendingCoor)
set bending coordinate (cm)
Definition TrackParam.h:61
Double_t getBendingCoor() const
return bending coordinate (cm)
Definition TrackParam.h:59
void setParameters(const TMatrixD &parameters)
set track parameters
Definition TrackParam.h:83
void updatePropagator(const TMatrixD &propagator)
Double_t p() const
Double_t getBendingSlope() const
return bending slope (cm ** -1)
Definition TrackParam.h:63
void setNonBendingCoor(Double_t nonBendingCoor)
set non bending coordinate (cm)
Definition TrackParam.h:53
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLuint GLfloat x0
Definition glcorearb.h:5034
GLboolean r
Definition glcorearb.h:1233
GLfloat GLfloat GLfloat GLfloat v3
Definition glcorearb.h:814
GLenum GLfloat param
Definition glcorearb.h:271
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
value_T f3
Definition TrackUtils.h:93
value_T sint
Definition TrackUtils.h:77
kp1 *kp2 *value_T bg2
Definition TrackUtils.h:131
value_T f4
Definition TrackUtils.h:94
value_T step
Definition TrackUtils.h:42
value_T f1
Definition TrackUtils.h:91
value_T d2
Definition TrackUtils.h:135
value_T gpu::gpustd::array< value_T, 7 > & vect
Definition TrackUtils.h:42
kp1 *kp2 *value_T beta2
Definition TrackUtils.h:131
constexpr value_T mK
Definition TrackUtils.h:127
value_T rho
Definition TrackUtils.h:36
value_T f2
Definition TrackUtils.h:92
value_T tet
Definition TrackUtils.h:75
const value_T lhwI
Definition TrackUtils.h:137
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"