]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONTrackExtrap.cxx
Adding includes required by ROOT
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackExtrap.cxx
CommitLineData
c04e3238 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16/* $Id$ */
17
18///////////////////////////////////////////////////
19//
20// Tools
21// for
22// track
23// extrapolation
24// in
25// ALICE
26// dimuon
27// spectrometer
28//
29///////////////////////////////////////////////////
30
31#include <Riostream.h>
3010c308 32#include <TMath.h>
208f139e 33#include <TMatrixD.h>
c04e3238 34
35#include "AliMUONTrackExtrap.h"
36#include "AliMUONTrackParam.h"
37#include "AliMUONConstants.h"
38#include "AliMagF.h"
39#include "AliLog.h"
40#include "AliTracker.h"
41
42ClassImp(AliMUONTrackExtrap) // Class implementation in ROOT context
43
44const AliMagF* AliMUONTrackExtrap::fgkField = 0x0;
208f139e 45const Int_t AliMUONTrackExtrap::fgkMaxStepNumber = 5000;
46const Double_t AliMUONTrackExtrap::fgkStepLength = 6.;
47
48 //__________________________________________________________________________
49Double_t AliMUONTrackExtrap::GetImpactParamFromBendingMomentum(Double_t bendingMomentum)
50{
51 /// Returns impact parameter at vertex in bending plane (cm),
52 /// from the signed bending momentum "BendingMomentum" in bending plane (GeV/c),
53 /// using simple values for dipole magnetic field.
54 /// The sign of "BendingMomentum" is the sign of the charge.
55
56 if (bendingMomentum == 0.) return 1.e10;
57
58 Double_t simpleBPosition = 0.5 * (AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ());
59 Double_t simpleBLength = 0.5 * (AliMUONConstants::CoilL() + AliMUONConstants::YokeL());
60 Float_t b[3], x[3] = {0.,0.,(Float_t) simpleBPosition};
61 if (fgkField) fgkField->Field(x,b);
62 else {
63 cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
64 exit(-1);
65 }
66 Double_t simpleBValue = (Double_t) b[0];
67
68 return (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / bendingMomentum);
69}
70
71 //__________________________________________________________________________
72Double_t AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(Double_t impactParam)
73{
74 /// Returns signed bending momentum in bending plane (GeV/c),
75 /// the sign being the sign of the charge for particles moving forward in Z,
76 /// from the impact parameter "ImpactParam" at vertex in bending plane (cm),
77 /// using simple values for dipole magnetic field.
78
79 if (impactParam == 0.) return 1.e10;
80
81 Double_t simpleBPosition = 0.5 * (AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ());
82 Double_t simpleBLength = 0.5 * (AliMUONConstants::CoilL() + AliMUONConstants::YokeL());
83 Float_t b[3], x[3] = {0.,0.,(Float_t) simpleBPosition};
84 if (fgkField) fgkField->Field(x,b);
85 else {
86 cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
87 exit(-1);
88 }
89 Double_t simpleBValue = (Double_t) b[0];
90
91 return (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / impactParam);
92}
c04e3238 93
94 //__________________________________________________________________________
95void AliMUONTrackExtrap::ExtrapToZ(AliMUONTrackParam* trackParam, Double_t zEnd)
96{
97 /// Track parameter extrapolation to the plane at "Z".
98 /// On return, the track parameters resulting from the extrapolation are updated in trackParam.
99 if (trackParam->GetZ() == zEnd) return; // nothing to be done if same Z
100 Double_t forwardBackward; // +1 if forward, -1 if backward
101 if (zEnd < trackParam->GetZ()) forwardBackward = 1.0; // spectro. z<0
102 else forwardBackward = -1.0;
dade8580 103 Double_t v3[7], v3New[7]; // 7 in parameter ????
104 Int_t i3, stepNumber;
c04e3238 105 // For safety: return kTRUE or kFALSE ????
106 // Parameter vector for calling EXTRAP_ONESTEP
dade8580 107 ConvertTrackParamForExtrap(trackParam, v3, forwardBackward);
c04e3238 108 // sign of charge (sign of fInverseBendingMomentum if forward motion)
109 // must be changed if backward extrapolation
208f139e 110 Double_t chargeExtrap = forwardBackward * TMath::Sign(Double_t(1.0), trackParam->GetInverseBendingMomentum());
c04e3238 111 // Extrapolation loop
112 stepNumber = 0;
208f139e 113 while (((-forwardBackward * (v3[2] - zEnd)) <= 0.0) && (stepNumber < fgkMaxStepNumber)) { // spectro. z<0
c04e3238 114 stepNumber++;
115 // Option for switching between helix and Runge-Kutta ????
208f139e 116 //ExtrapOneStepRungekutta(chargeExtrap, fgkStepLength, v3, v3New);
117 ExtrapOneStepHelix(chargeExtrap, fgkStepLength, v3, v3New);
dade8580 118 if ((-forwardBackward * (v3New[2] - zEnd)) > 0.0) break; // one is beyond Z spectro. z<0
c04e3238 119 // better use TArray ????
208f139e 120 for (i3 = 0; i3 < 7; i3++) {v3[i3] = v3New[i3];}
c04e3238 121 }
208f139e 122 // check fgkMaxStepNumber ????
c04e3238 123 // Interpolation back to exact Z (2nd order)
124 // should be in function ???? using TArray ????
dade8580 125 Double_t dZ12 = v3New[2] - v3[2]; // 1->2
c04e3238 126 if (TMath::Abs(dZ12) > 0) {
dade8580 127 Double_t dZ1i = zEnd - v3[2]; // 1-i
128 Double_t dZi2 = v3New[2] - zEnd; // i->2
129 Double_t xPrime = (v3New[0] - v3[0]) / dZ12;
130 Double_t xSecond = ((v3New[3] / v3New[5]) - (v3[3] / v3[5])) / dZ12;
131 Double_t yPrime = (v3New[1] - v3[1]) / dZ12;
132 Double_t ySecond = ((v3New[4] / v3New[5]) - (v3[4] / v3[5])) / dZ12;
133 v3[0] = v3[0] + xPrime * dZ1i - 0.5 * xSecond * dZ1i * dZi2; // X
134 v3[1] = v3[1] + yPrime * dZ1i - 0.5 * ySecond * dZ1i * dZi2; // Y
135 v3[2] = zEnd; // Z
c04e3238 136 Double_t xPrimeI = xPrime - 0.5 * xSecond * (dZi2 - dZ1i);
137 Double_t yPrimeI = yPrime - 0.5 * ySecond * (dZi2 - dZ1i);
138 // (PX, PY, PZ)/PTOT assuming forward motion
208f139e 139 v3[5] = 1.0 / TMath::Sqrt(1.0 + xPrimeI * xPrimeI + yPrimeI * yPrimeI); // PZ/PTOT
dade8580 140 v3[3] = xPrimeI * v3[5]; // PX/PTOT
141 v3[4] = yPrimeI * v3[5]; // PY/PTOT
c04e3238 142 } else {
143 cout<<"W-AliMUONTrackExtrap::ExtrapToZ: Extrap. to Z not reached, Z = "<<zEnd<<endl;
144 }
dade8580 145 // Track parameters from 3 parameters,
c04e3238 146 // with charge back for forward motion
dade8580 147 RecoverTrackParam(v3, chargeExtrap * forwardBackward, trackParam);
c04e3238 148}
149
150 //__________________________________________________________________________
dade8580 151void AliMUONTrackExtrap::ConvertTrackParamForExtrap(AliMUONTrackParam* trackParam, Double_t *v3, Double_t forwardBackward)
c04e3238 152{
dade8580 153 /// Set vector of Geant3 parameters pointed to by "v3" from track parameters in trackParam.
c04e3238 154 /// Since AliMUONTrackParam is only geometry, one uses "forwardBackward"
155 /// to know whether the particle is going forward (+1) or backward (-1).
dade8580 156 v3[0] = trackParam->GetNonBendingCoor(); // X
157 v3[1] = trackParam->GetBendingCoor(); // Y
158 v3[2] = trackParam->GetZ(); // Z
c04e3238 159 Double_t pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
160 Double_t pZ = pYZ / TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope());
dade8580 161 v3[6] = TMath::Sqrt(pYZ * pYZ + pZ * pZ * trackParam->GetNonBendingSlope() * trackParam->GetNonBendingSlope()); // PTOT
162 v3[5] = -forwardBackward * pZ / v3[6]; // PZ/PTOT spectro. z<0
163 v3[3] = trackParam->GetNonBendingSlope() * v3[5]; // PX/PTOT
164 v3[4] = trackParam->GetBendingSlope() * v3[5]; // PY/PTOT
c04e3238 165}
166
167 //__________________________________________________________________________
dade8580 168void AliMUONTrackExtrap::RecoverTrackParam(Double_t *v3, Double_t charge, AliMUONTrackParam* trackParam)
c04e3238 169{
dade8580 170 /// Set track parameters in trackParam from Geant3 parameters pointed to by "v3",
c04e3238 171 /// assumed to be calculated for forward motion in Z.
172 /// "InverseBendingMomentum" is signed with "charge".
dade8580 173 trackParam->SetNonBendingCoor(v3[0]); // X
174 trackParam->SetBendingCoor(v3[1]); // Y
175 trackParam->SetZ(v3[2]); // Z
176 Double_t pYZ = v3[6] * TMath::Sqrt(1.0 - v3[3] * v3[3]);
c04e3238 177 trackParam->SetInverseBendingMomentum(charge/pYZ);
dade8580 178 trackParam->SetBendingSlope(v3[4]/v3[5]);
179 trackParam->SetNonBendingSlope(v3[3]/v3[5]);
208f139e 180}
181
182 //__________________________________________________________________________
183void AliMUONTrackExtrap::ExtrapToZCov(AliMUONTrackParam* trackParam, Double_t zEnd)
184{
185 /// Track parameters and their covariances extrapolated to the plane at "zEnd".
186 /// On return, results from the extrapolation are updated in trackParam.
187
188 if (trackParam->GetZ() == zEnd) return; // nothing to be done if same z
189
190 // Save the actual track parameters
191 AliMUONTrackParam trackParamSave(*trackParam);
192 Double_t nonBendingCoor = trackParamSave.GetNonBendingCoor();
193 Double_t nonBendingSlope = trackParamSave.GetNonBendingSlope();
194 Double_t bendingCoor = trackParamSave.GetBendingCoor();
195 Double_t bendingSlope = trackParamSave.GetBendingSlope();
196 Double_t inverseBendingMomentum = trackParamSave.GetInverseBendingMomentum();
197 Double_t zBegin = trackParamSave.GetZ();
198
199 // Extrapolate track parameters to "zEnd"
200 ExtrapToZ(trackParam,zEnd);
201 Double_t extrapNonBendingCoor = trackParam->GetNonBendingCoor();
202 Double_t extrapNonBendingSlope = trackParam->GetNonBendingSlope();
203 Double_t extrapBendingCoor = trackParam->GetBendingCoor();
204 Double_t extrapBendingSlope = trackParam->GetBendingSlope();
205 Double_t extrapInverseBendingMomentum = trackParam->GetInverseBendingMomentum();
206
207 // Get the pointer to the parameter covariance matrix
208 if (!trackParam->CovariancesExist()) {
209 //cout<<"W-AliMUONTrackExtrap::ExtrapToZCov: track parameter covariance matrix does not exist"<<endl;
210 //cout<<" -> nothing to extrapolate !!"<<endl;
211 return;
212 }
213 TMatrixD* paramCov = trackParam->GetCovariances();
214
215 // Calculate the jacobian related to the track parameters extrapolation to "zEnd"
216 TMatrixD jacob(5,5);
217 jacob = 0.;
218 Double_t dParam[5];
219 for (Int_t i=0; i<5; i++) {
220 // Skip jacobian calculation for parameters with no associated error
221 if ((*paramCov)(i,i) == 0.) continue;
222 // Small variation of parameter i only
223 for (Int_t j=0; j<5; j++) {
224 if (j==i) {
225 dParam[j] = TMath::Sqrt((*paramCov)(i,i));
226 if (j == 4) dParam[j] *= TMath::Sign(1.,-inverseBendingMomentum); // variation always in the same direction
227 } else dParam[j] = 0.;
228 }
229 // Set new parameters
230 trackParamSave.SetNonBendingCoor (nonBendingCoor + dParam[0]);
231 trackParamSave.SetNonBendingSlope (nonBendingSlope + dParam[1]);
232 trackParamSave.SetBendingCoor (bendingCoor + dParam[2]);
233 trackParamSave.SetBendingSlope (bendingSlope + dParam[3]);
234 trackParamSave.SetInverseBendingMomentum(inverseBendingMomentum + dParam[4]);
235 trackParamSave.SetZ (zBegin);
236 // Extrapolate new track parameters to "zEnd"
237 ExtrapToZ(&trackParamSave,zEnd);
238 // Calculate the jacobian
239 jacob(0,i) = (trackParamSave.GetNonBendingCoor() - extrapNonBendingCoor ) / dParam[i];
240 jacob(1,i) = (trackParamSave.GetNonBendingSlope() - extrapNonBendingSlope ) / dParam[i];
241 jacob(2,i) = (trackParamSave.GetBendingCoor() - extrapBendingCoor ) / dParam[i];
242 jacob(3,i) = (trackParamSave.GetBendingSlope() - extrapBendingSlope ) / dParam[i];
243 jacob(4,i) = (trackParamSave.GetInverseBendingMomentum() - extrapInverseBendingMomentum) / dParam[i];
244 }
245
246 // Extrapolate track parameter covariances to "zEnd"
247 TMatrixD tmp((*paramCov),TMatrixD::kMultTranspose,jacob);
248 (*paramCov) = TMatrixD(jacob,TMatrixD::kMult,tmp);
249
c04e3238 250}
251
252 //__________________________________________________________________________
253void AliMUONTrackExtrap::ExtrapToStation(AliMUONTrackParam* trackParamIn, Int_t station, AliMUONTrackParam *trackParamOut)
254{
255 /// Track parameters extrapolated from "trackParamIn" to both chambers of the station(0..) "station"
256 /// are returned in the array (dimension 2) of track parameters pointed to by "TrackParamOut"
257 /// (index 0 and 1 for first and second chambers).
258 Double_t extZ[2], z1, z2;
259 Int_t i1 = -1, i2 = -1; // = -1 to avoid compilation warnings
260 // range of station to be checked ????
261 z1 = AliMUONConstants::DefaultChamberZ(2 * station);
262 z2 = AliMUONConstants::DefaultChamberZ(2 * station + 1);
263 // First and second Z to extrapolate at
264 if ((z1 > trackParamIn->GetZ()) && (z2 > trackParamIn->GetZ())) {i1 = 0; i2 = 1;}
265 else if ((z1 < trackParamIn->GetZ()) && (z2 < trackParamIn->GetZ())) {i1 = 1; i2 = 0;}
266 else {
208f139e 267 cout<<"E-AliMUONTrackExtrap::ExtrapToStation: Starting Z ("<<trackParamIn->GetZ()
c04e3238 268 <<") in between z1 ("<<z1<<") and z2 ("<<z2<<") of station(0..)"<<station<<endl;
269 exit(-1);
270 }
271 extZ[i1] = z1;
272 extZ[i2] = z2;
273 // copy of track parameters
274 trackParamOut[i1] = *trackParamIn;
275 // first extrapolation
276 ExtrapToZ(&(trackParamOut[i1]),extZ[0]);
277 trackParamOut[i2] = trackParamOut[i1];
278 // second extrapolation
279 ExtrapToZ(&(trackParamOut[i2]),extZ[1]);
280 return;
208f139e 281}
282
283 //__________________________________________________________________________
284void AliMUONTrackExtrap::ExtrapToVertexUncorrected(AliMUONTrackParam* trackParam, Double_t zVtx)
285{
286 /// Extrapolation to the vertex (at the z position "zVtx") without Branson and Field correction.
287 /// Returns the track parameters resulting from the extrapolation in the current TrackParam.
288 /// Include multiple Coulomb scattering effects in trackParam covariances.
289
290 if (trackParam->GetZ() > zVtx) { // spectro. (z<0)
291 cout<<"W-AliMUONTrackExtrap::ExtrapToVertexUncorrected: Starting Z ("<<trackParam->GetZ()
292 <<") upstream the vertex (zVtx = "<<zVtx<<")"<<endl;
293 exit(-1);
294 }
295
296 if (zVtx < AliMUONConstants::ZAbsorberEnd()) { // spectro. (z<0)
297 cout<<"W-AliMUONTrackExtrap::ExtrapToVertexUncorrected: Ending Z ("<<zVtx
298 <<") downstream the front absorber (zAbsorberEnd = "<<AliMUONConstants::ZAbsorberEnd()<<")"<<endl;
299
300 ExtrapToZCov(trackParam,zVtx);
301 return;
302 }
303
304 // First Extrapolates track parameters upstream to the "Z" end of the front absorber
305 if (trackParam->GetZ() < AliMUONConstants::ZAbsorberEnd()) { // spectro. (z<0)
306 ExtrapToZCov(trackParam,AliMUONConstants::ZAbsorberEnd());
307 } else {
308 cout<<"W-AliMUONTrackExtrap::ExtrapToVertexUncorrected: Starting Z ("<<trackParam->GetZ()
309 <<") upstream or inside the front absorber (zAbsorberEnd = "<<AliMUONConstants::ZAbsorberEnd()<<")"<<endl;
310 }
311
312 // Then go through all the absorber layers
313 Double_t tan3 = TMath::Tan(3./180.*TMath::Pi());
314 Double_t r0Norm, x0, z, zElement, dZ, nonBendingCoor, bendingCoor;
315 for (Int_t iElement=AliMUONConstants::NAbsorberElements()-1; iElement>=0; iElement--) {
316 zElement = AliMUONConstants::ZAbsorberElement(iElement);
317 z = trackParam->GetZ();
318 if (z > zElement) continue; // spectro. (z<0)
319 nonBendingCoor = trackParam->GetNonBendingCoor();
320 bendingCoor = trackParam->GetBendingCoor();
321 r0Norm = nonBendingCoor * nonBendingCoor + bendingCoor * bendingCoor;
322 r0Norm = TMath::Sqrt(r0Norm) / TMath::Abs(trackParam->GetZ()) / tan3;
323 if (r0Norm > 1.) x0 = AliMUONConstants::X0AbsorberOut(iElement); // outer part of the absorber
324 else x0 = AliMUONConstants::X0AbsorberIn(iElement); // inner part of the absorber
325
326 if (zVtx > zElement) {
327 ExtrapToZCov(trackParam,zElement); // extrapolate to absorber element "iElement"
328 dZ = zElement - z;
329 AddMCSEffectInTrackParamCov(trackParam,dZ,x0); // include MCS effect in covariances
330 } else {
331 ExtrapToZCov(trackParam,zVtx); // extrapolate to zVtx
332 dZ = zVtx - z;
333 AddMCSEffectInTrackParamCov(trackParam,dZ,x0); // include MCS effect in covariances
334 break;
335 }
336 }
337
338 // finally go to the vertex
339 ExtrapToZCov(trackParam,zVtx);
340
341}
342
343 //__________________________________________________________________________
344void AliMUONTrackExtrap::AddMCSEffectInTrackParamCov(AliMUONTrackParam *param, Double_t dZ, Double_t x0)
345{
346 /// Add to the track parameter covariances the effects of multiple Coulomb scattering
347 /// through a material of thickness "dZ" and of radiation length "x0"
348 /// assuming linear propagation and using the small angle approximation.
349
350 Double_t bendingSlope = param->GetBendingSlope();
351 Double_t nonBendingSlope = param->GetNonBendingSlope();
352 Double_t inverseTotalMomentum2 = param->GetInverseBendingMomentum() * param->GetInverseBendingMomentum() *
353 (1.0 + bendingSlope * bendingSlope) /
354 (1.0 + bendingSlope *bendingSlope + nonBendingSlope * nonBendingSlope);
355 // Path length in the material
356 Double_t pathLength = TMath::Abs(dZ) * TMath::Sqrt(1.0 + bendingSlope*bendingSlope + nonBendingSlope*nonBendingSlope);
357 Double_t pathLength2 = pathLength * pathLength;
358 // relativistic velocity
359 Double_t velo = 1.;
360 // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory
361 Double_t theta02 = 0.0136 / velo * (1 + 0.038 * TMath::Log(pathLength/x0));
362 theta02 *= theta02 * inverseTotalMomentum2 * pathLength / x0;
363
364 // Add effects of multiple Coulomb scattering in track parameter covariances
365 TMatrixD* paramCov = param->GetCovariances();
366 Double_t varCoor = pathLength2 * theta02 / 3.;
367 Double_t varSlop = theta02;
368 Double_t covCorrSlope = pathLength * theta02 / 2.;
369 // Non bending plane
370 (*paramCov)(0,0) += varCoor; (*paramCov)(0,1) += covCorrSlope;
371 (*paramCov)(1,0) += covCorrSlope; (*paramCov)(1,1) += varSlop;
372 // Bending plane
373 (*paramCov)(2,2) += varCoor; (*paramCov)(2,3) += covCorrSlope;
374 (*paramCov)(3,2) += covCorrSlope; (*paramCov)(3,3) += varSlop;
375
c04e3238 376}
377
378 //__________________________________________________________________________
379void AliMUONTrackExtrap::ExtrapToVertex(AliMUONTrackParam* trackParam, Double_t xVtx, Double_t yVtx, Double_t zVtx)
380{
381 /// Extrapolation to the vertex.
382 /// Returns the track parameters resulting from the extrapolation in the current TrackParam.
383 /// Changes parameters according to Branson correction through the absorber
384
c04e3238 385 // Extrapolates track parameters upstream to the "Z" end of the front absorber
208f139e 386 ExtrapToZ(trackParam,AliMUONConstants::ZAbsorberEnd()); // !!!
c04e3238 387 // Makes Branson correction (multiple scattering + energy loss)
388 BransonCorrection(trackParam,xVtx,yVtx,zVtx);
389 // Makes a simple magnetic field correction through the absorber
208f139e 390 FieldCorrection(trackParam,AliMUONConstants::ZAbsorberEnd());
c04e3238 391}
392
393
394// Keep this version for future developments
395 //__________________________________________________________________________
396// void AliMUONTrackExtrap::BransonCorrection(AliMUONTrackParam* trackParam)
397// {
398// /// Branson correction of track parameters
399// // the entry parameters have to be calculated at the end of the absorber
400// Double_t zEndAbsorber, zBP, xBP, yBP;
401// Double_t pYZ, pX, pY, pZ, pTotal, xEndAbsorber, yEndAbsorber, radiusEndAbsorber2, pT, theta;
402// Int_t sign;
403// // Would it be possible to calculate all that from Geant configuration ????
404// // and to get the Branson parameters from a function in ABSO module ????
405// // with an eventual contribution from other detectors like START ????
406// // Radiation lengths outer part theta > 3 degres
407// static Double_t x01[9] = { 18.8, // C (cm)
408// 10.397, // Concrete (cm)
409// 0.56, // Plomb (cm)
410// 47.26, // Polyethylene (cm)
411// 0.56, // Plomb (cm)
412// 47.26, // Polyethylene (cm)
413// 0.56, // Plomb (cm)
414// 47.26, // Polyethylene (cm)
415// 0.56 }; // Plomb (cm)
416// // inner part theta < 3 degres
417// static Double_t x02[3] = { 18.8, // C (cm)
418// 10.397, // Concrete (cm)
419// 0.35 }; // W (cm)
420// // z positions of the materials inside the absober outer part theta > 3 degres
421// static Double_t z1[10] = { 90, 315, 467, 472, 477, 482, 487, 492, 497, 502 };
422// // inner part theta < 3 degres
423// static Double_t z2[4] = { 90, 315, 467, 503 };
424// static Bool_t first = kTRUE;
425// static Double_t zBP1, zBP2, rLimit;
426// // Calculates z positions of the Branson's planes: zBP1 for outer part and zBP2 for inner part (only at the first call)
427// if (first) {
428// first = kFALSE;
429// Double_t aNBP = 0.0;
430// Double_t aDBP = 0.0;
431// Int_t iBound;
432//
433// for (iBound = 0; iBound < 9; iBound++) {
434// aNBP = aNBP +
435// (z1[iBound+1] * z1[iBound+1] * z1[iBound+1] -
436// z1[iBound] * z1[iBound] * z1[iBound] ) / x01[iBound];
437// aDBP = aDBP +
438// (z1[iBound+1] * z1[iBound+1] - z1[iBound] * z1[iBound] ) / x01[iBound];
439// }
440// zBP1 = (2.0 * aNBP) / (3.0 * aDBP);
441// aNBP = 0.0;
442// aDBP = 0.0;
443// for (iBound = 0; iBound < 3; iBound++) {
444// aNBP = aNBP +
445// (z2[iBound+1] * z2[iBound+1] * z2[iBound+1] -
446// z2[iBound] * z2[iBound ] * z2[iBound] ) / x02[iBound];
447// aDBP = aDBP +
448// (z2[iBound+1] * z2[iBound+1] - z2[iBound] * z2[iBound]) / x02[iBound];
449// }
450// zBP2 = (2.0 * aNBP) / (3.0 * aDBP);
451// rLimit = z2[3] * TMath::Tan(3.0 * (TMath::Pi()) / 180.);
452// }
453//
454// pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
455// sign = 1;
456// if (trackParam->GetInverseBendingMomentum() < 0) sign = -1;
457// pZ = pYZ / (TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope()));
458// pX = pZ * trackParam->GetNonBendingSlope();
459// pY = pZ * trackParam->GetBendingSlope();
460// pTotal = TMath::Sqrt(pYZ *pYZ + pX * pX);
461// xEndAbsorber = trackParam->GetNonBendingCoor();
462// yEndAbsorber = trackParam->GetBendingCoor();
463// radiusEndAbsorber2 = xEndAbsorber * xEndAbsorber + yEndAbsorber * yEndAbsorber;
464//
465// if (radiusEndAbsorber2 > rLimit*rLimit) {
466// zEndAbsorber = z1[9];
467// zBP = zBP1;
468// } else {
469// zEndAbsorber = z2[3];
470// zBP = zBP2;
471// }
472//
473// xBP = xEndAbsorber - (pX / pZ) * (zEndAbsorber - zBP);
474// yBP = yEndAbsorber - (pY / pZ) * (zEndAbsorber - zBP);
475//
476// // new parameters after Branson and energy loss corrections
477// pZ = pTotal * zBP / TMath::Sqrt(xBP * xBP + yBP * yBP + zBP * zBP);
478// pX = pZ * xBP / zBP;
479// pY = pZ * yBP / zBP;
480// trackParam->SetBendingSlope(pY/pZ);
481// trackParam->SetNonBendingSlope(pX/pZ);
482//
483// pT = TMath::Sqrt(pX * pX + pY * pY);
484// theta = TMath::ATan2(pT, pZ);
485// pTotal = TotalMomentumEnergyLoss(rLimit, pTotal, theta, xEndAbsorber, yEndAbsorber);
486//
487// trackParam->SetInverseBendingMomentum((sign / pTotal) *
488// TMath::Sqrt(1.0 +
489// trackParam->GetBendingSlope() * trackParam->GetBendingSlope() +
490// trackParam->GetNonBendingSlope() * trackParam->GetNonBendingSlope()) /
491// TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope()));
492//
493// // vertex position at (0,0,0)
494// // should be taken from vertex measurement ???
495// trackParam->SetBendingCoor(0.);
496// trackParam->SetNonBendingCoor(0.);
497// trackParam->SetZ(0.);
498// }
499
500void AliMUONTrackExtrap::BransonCorrection(AliMUONTrackParam* trackParam, Double_t xVtx, Double_t yVtx, Double_t zVtx)
501{
502 /// Branson correction of track parameters
503 // the entry parameters have to be calculated at the end of the absorber
504 // simplified version: the z positions of Branson's planes are no longer calculated
505 // but are given as inputs. One can use the macros MUONTestAbso.C and DrawTestAbso.C
506 // to test this correction.
507 // Would it be possible to calculate all that from Geant configuration ????
508 // and to get the Branson parameters from a function in ABSO module ????
509 // with an eventual contribution from other detectors like START ????
510 // change to take into account the vertex postition (real, reconstruct,....)
511
512 Double_t zBP, xBP, yBP;
513 Double_t pYZ, pX, pY, pZ, pTotal, xEndAbsorber, yEndAbsorber, radiusEndAbsorber2, pT, theta;
514 Int_t sign;
515 static Bool_t first = kTRUE;
208f139e 516 static Double_t zBP1, zBP2, rLimit, thetaLimit;
c04e3238 517 // zBP1 for outer part and zBP2 for inner part (only at the first call)
518 if (first) {
519 first = kFALSE;
520
c04e3238 521 thetaLimit = 3.0 * (TMath::Pi()) / 180.;
208f139e 522 rLimit = TMath::Abs(AliMUONConstants::ZAbsorberEnd()) * TMath::Tan(thetaLimit);
c04e3238 523 zBP1 = -450; // values close to those calculated with EvalAbso.C
524 zBP2 = -480;
525 }
526
527 pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
528 sign = 1;
529 if (trackParam->GetInverseBendingMomentum() < 0) sign = -1;
530 pZ = trackParam->Pz();
531 pX = trackParam->Px();
532 pY = trackParam->Py();
533 pTotal = TMath::Sqrt(pYZ *pYZ + pX * pX);
534 xEndAbsorber = trackParam->GetNonBendingCoor();
535 yEndAbsorber = trackParam->GetBendingCoor();
536 radiusEndAbsorber2 = xEndAbsorber * xEndAbsorber + yEndAbsorber * yEndAbsorber;
537
538 if (radiusEndAbsorber2 > rLimit*rLimit) {
539 zBP = zBP1;
540 } else {
541 zBP = zBP2;
542 }
543
208f139e 544 xBP = xEndAbsorber - (pX / pZ) * (AliMUONConstants::ZAbsorberEnd() - zBP);
545 yBP = yEndAbsorber - (pY / pZ) * (AliMUONConstants::ZAbsorberEnd() - zBP);
c04e3238 546
547 // new parameters after Branson and energy loss corrections
548// Float_t zSmear = zBP - gRandom->Gaus(0.,2.); // !!! possible smearing of Z vertex position
549
550 Float_t zSmear = zBP ;
551
552 pZ = pTotal * (zSmear-zVtx) / TMath::Sqrt((xBP-xVtx) * (xBP-xVtx) + (yBP-yVtx) * (yBP-yVtx) +( zSmear-zVtx) * (zSmear-zVtx) );
553 pX = pZ * (xBP - xVtx)/ (zSmear-zVtx);
554 pY = pZ * (yBP - yVtx) / (zSmear-zVtx);
555 trackParam->SetBendingSlope(pY/pZ);
556 trackParam->SetNonBendingSlope(pX/pZ);
557
558
559 pT = TMath::Sqrt(pX * pX + pY * pY);
560 theta = TMath::ATan2(pT, TMath::Abs(pZ));
561 pTotal = TotalMomentumEnergyLoss(thetaLimit, pTotal, theta);
562
563 trackParam->SetInverseBendingMomentum((sign / pTotal) *
564 TMath::Sqrt(1.0 +
565 trackParam->GetBendingSlope() * trackParam->GetBendingSlope() +
566 trackParam->GetNonBendingSlope() * trackParam->GetNonBendingSlope()) /
567 TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope()));
568
569 // vertex position at (0,0,0)
570 // should be taken from vertex measurement ???
571
572 trackParam->SetBendingCoor(xVtx);
573 trackParam->SetNonBendingCoor(yVtx);
574 trackParam->SetZ(zVtx);
575
576}
577
578 //__________________________________________________________________________
579Double_t AliMUONTrackExtrap::TotalMomentumEnergyLoss(Double_t thetaLimit, Double_t pTotal, Double_t theta)
580{
581 /// Returns the total momentum corrected from energy loss in the front absorber
582 // One can use the macros MUONTestAbso.C and DrawTestAbso.C
583 // to test this correction.
584 // Momentum energy loss behaviour evaluated with the simulation of single muons (april 2002)
585 Double_t deltaP, pTotalCorrected;
586
587 // Parametrization to be redone according to change of absorber material ????
588 // See remark in function BransonCorrection !!!!
589 // The name is not so good, and there are many arguments !!!!
590 if (theta < thetaLimit ) {
591 if (pTotal < 20) {
592 deltaP = 2.5938 + 0.0570 * pTotal - 0.001151 * pTotal * pTotal;
593 } else {
594 deltaP = 3.0714 + 0.011767 *pTotal;
595 }
596 deltaP *= 0.75; // AZ
597 } else {
598 if (pTotal < 20) {
599 deltaP = 2.1207 + 0.05478 * pTotal - 0.00145079 * pTotal * pTotal;
600 } else {
601 deltaP = 2.6069 + 0.0051705 * pTotal;
602 }
603 deltaP *= 0.9; // AZ
604 }
605 pTotalCorrected = pTotal + deltaP / TMath::Cos(theta);
606 return pTotalCorrected;
607}
608
609 //__________________________________________________________________________
610void AliMUONTrackExtrap::FieldCorrection(AliMUONTrackParam *trackParam, Double_t zEnd)
611{
612 /// Correction of the effect of the magnetic field in the absorber
613 // Assume a constant field along Z axis.
614 Float_t b[3],x[3];
615 Double_t bZ;
616 Double_t pYZ,pX,pY,pZ,pT;
617 Double_t pXNew,pYNew;
618 Double_t c;
619
620 pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
621 c = TMath::Sign(1.0,trackParam->GetInverseBendingMomentum()); // particle charge
622
623 pZ = trackParam->Pz();
624 pX = trackParam->Px();
625 pY = trackParam->Py();
626 pT = TMath::Sqrt(pX*pX+pY*pY);
627
628 if (TMath::Abs(pZ) <= 0) return;
629 x[2] = zEnd/2;
630 x[0] = x[2]*trackParam->GetNonBendingSlope();
631 x[1] = x[2]*trackParam->GetBendingSlope();
632
633 // Take magn. field value at position x.
634 if (fgkField) fgkField->Field(x,b);
635 else {
636 cout<<"F-AliMUONTrackExtrap::FieldCorrection: fgkField = 0x0"<<endl;
637 exit(-1);
638 }
639 bZ = b[2];
640
641 // Transverse momentum rotation
642 // Parameterized with the study of DeltaPhi = phiReco - phiGen as a function of pZ.
643 Double_t phiShift = c*0.436*0.0003*bZ*zEnd/pZ;
644 // Rotate momentum around Z axis.
645 pXNew = pX*TMath::Cos(phiShift) - pY*TMath::Sin(phiShift);
646 pYNew = pX*TMath::Sin(phiShift) + pY*TMath::Cos(phiShift);
647
648 trackParam->SetBendingSlope(pYNew/pZ);
649 trackParam->SetNonBendingSlope(pXNew/pZ);
650
651 trackParam->SetInverseBendingMomentum(c/TMath::Sqrt(pYNew*pYNew+pZ*pZ));
652
653}
654
655 //__________________________________________________________________________
656void AliMUONTrackExtrap::ExtrapOneStepHelix(Double_t charge, Double_t step, Double_t *vect, Double_t *vout)
657{
658/// ******************************************************************
659/// * *
660/// * Performs the tracking of one step in a magnetic field *
661/// * The trajectory is assumed to be a helix in a constant field *
662/// * taken at the mid point of the step. *
663/// * Parameters: *
664/// * input *
665/// * STEP =arc length of the step asked *
666/// * VECT =input vector (position,direction cos and momentum) *
667/// * CHARGE= electric charge of the particle *
668/// * output *
669/// * VOUT = same as VECT after completion of the step *
670/// * *
671/// * ==>Called by : <USER>, GUSWIM *
672/// * Author m.hansroul ********* *
673/// * modified s.egli, s.v.levonian *
674/// * modified v.perevoztchikov
675/// * *
676/// ******************************************************************
677
678// modif: everything in double precision
679
680 Double_t xyz[3], h[4], hxp[3];
681 Double_t h2xy, hp, rho, tet;
682 Double_t sint, sintt, tsint, cos1t;
683 Double_t f1, f2, f3, f4, f5, f6;
684
685 const Int_t kix = 0;
686 const Int_t kiy = 1;
687 const Int_t kiz = 2;
688 const Int_t kipx = 3;
689 const Int_t kipy = 4;
690 const Int_t kipz = 5;
691 const Int_t kipp = 6;
692
693 const Double_t kec = 2.9979251e-4;
694 //
695 // ------------------------------------------------------------------
696 //
697 // units are kgauss,centimeters,gev/c
698 //
699 vout[kipp] = vect[kipp];
700 if (TMath::Abs(charge) < 0.00001) {
701 for (Int_t i = 0; i < 3; i++) {
702 vout[i] = vect[i] + step * vect[i+3];
703 vout[i+3] = vect[i+3];
704 }
705 return;
706 }
707 xyz[0] = vect[kix] + 0.5 * step * vect[kipx];
708 xyz[1] = vect[kiy] + 0.5 * step * vect[kipy];
709 xyz[2] = vect[kiz] + 0.5 * step * vect[kipz];
710
711 //cmodif: call gufld (xyz, h) changed into:
712 GetField (xyz, h);
713
714 h2xy = h[0]*h[0] + h[1]*h[1];
715 h[3] = h[2]*h[2]+ h2xy;
716 if (h[3] < 1.e-12) {
717 for (Int_t i = 0; i < 3; i++) {
718 vout[i] = vect[i] + step * vect[i+3];
719 vout[i+3] = vect[i+3];
720 }
721 return;
722 }
723 if (h2xy < 1.e-12*h[3]) {
724 ExtrapOneStepHelix3(charge*h[2], step, vect, vout);
725 return;
726 }
727 h[3] = TMath::Sqrt(h[3]);
728 h[0] /= h[3];
729 h[1] /= h[3];
730 h[2] /= h[3];
731 h[3] *= kec;
732
733 hxp[0] = h[1]*vect[kipz] - h[2]*vect[kipy];
734 hxp[1] = h[2]*vect[kipx] - h[0]*vect[kipz];
735 hxp[2] = h[0]*vect[kipy] - h[1]*vect[kipx];
736
737 hp = h[0]*vect[kipx] + h[1]*vect[kipy] + h[2]*vect[kipz];
738
739 rho = -charge*h[3]/vect[kipp];
740 tet = rho * step;
741
742 if (TMath::Abs(tet) > 0.15) {
743 sint = TMath::Sin(tet);
744 sintt = (sint/tet);
745 tsint = (tet-sint)/tet;
746 cos1t = 2.*(TMath::Sin(0.5*tet))*(TMath::Sin(0.5*tet))/tet;
747 } else {
748 tsint = tet*tet/36.;
749 sintt = (1. - tsint);
750 sint = tet*sintt;
751 cos1t = 0.5*tet;
752 }
753
754 f1 = step * sintt;
755 f2 = step * cos1t;
756 f3 = step * tsint * hp;
757 f4 = -tet*cos1t;
758 f5 = sint;
759 f6 = tet * cos1t * hp;
760
761 vout[kix] = vect[kix] + f1*vect[kipx] + f2*hxp[0] + f3*h[0];
762 vout[kiy] = vect[kiy] + f1*vect[kipy] + f2*hxp[1] + f3*h[1];
763 vout[kiz] = vect[kiz] + f1*vect[kipz] + f2*hxp[2] + f3*h[2];
764
765 vout[kipx] = vect[kipx] + f4*vect[kipx] + f5*hxp[0] + f6*h[0];
766 vout[kipy] = vect[kipy] + f4*vect[kipy] + f5*hxp[1] + f6*h[1];
767 vout[kipz] = vect[kipz] + f4*vect[kipz] + f5*hxp[2] + f6*h[2];
768
769 return;
770}
771
772 //__________________________________________________________________________
773void AliMUONTrackExtrap::ExtrapOneStepHelix3(Double_t field, Double_t step, Double_t *vect, Double_t *vout)
774{
775/// ******************************************************************
776/// * *
777/// * Tracking routine in a constant field oriented *
778/// * along axis 3 *
779/// * Tracking is performed with a conventional *
780/// * helix step method *
781/// * *
782/// * ==>Called by : <USER>, GUSWIM *
783/// * Authors R.Brun, M.Hansroul ********* *
784/// * Rewritten V.Perevoztchikov
785/// * *
786/// ******************************************************************
787
788 Double_t hxp[3];
789 Double_t h4, hp, rho, tet;
790 Double_t sint, sintt, tsint, cos1t;
791 Double_t f1, f2, f3, f4, f5, f6;
792
793 const Int_t kix = 0;
794 const Int_t kiy = 1;
795 const Int_t kiz = 2;
796 const Int_t kipx = 3;
797 const Int_t kipy = 4;
798 const Int_t kipz = 5;
799 const Int_t kipp = 6;
800
801 const Double_t kec = 2.9979251e-4;
802
803//
804// ------------------------------------------------------------------
805//
806// units are kgauss,centimeters,gev/c
807//
808 vout[kipp] = vect[kipp];
809 h4 = field * kec;
810
811 hxp[0] = - vect[kipy];
812 hxp[1] = + vect[kipx];
813
814 hp = vect[kipz];
815
816 rho = -h4/vect[kipp];
817 tet = rho * step;
818 if (TMath::Abs(tet) > 0.15) {
819 sint = TMath::Sin(tet);
820 sintt = (sint/tet);
821 tsint = (tet-sint)/tet;
822 cos1t = 2.* TMath::Sin(0.5*tet) * TMath::Sin(0.5*tet)/tet;
823 } else {
824 tsint = tet*tet/36.;
825 sintt = (1. - tsint);
826 sint = tet*sintt;
827 cos1t = 0.5*tet;
828 }
829
830 f1 = step * sintt;
831 f2 = step * cos1t;
832 f3 = step * tsint * hp;
833 f4 = -tet*cos1t;
834 f5 = sint;
835 f6 = tet * cos1t * hp;
836
837 vout[kix] = vect[kix] + f1*vect[kipx] + f2*hxp[0];
838 vout[kiy] = vect[kiy] + f1*vect[kipy] + f2*hxp[1];
839 vout[kiz] = vect[kiz] + f1*vect[kipz] + f3;
840
841 vout[kipx] = vect[kipx] + f4*vect[kipx] + f5*hxp[0];
842 vout[kipy] = vect[kipy] + f4*vect[kipy] + f5*hxp[1];
843 vout[kipz] = vect[kipz] + f4*vect[kipz] + f6;
844
845 return;
846}
847 //__________________________________________________________________________
848void AliMUONTrackExtrap::ExtrapOneStepRungekutta(Double_t charge, Double_t step, Double_t* vect, Double_t* vout)
849{
850/// ******************************************************************
851/// * *
852/// * Runge-Kutta method for tracking a particle through a magnetic *
853/// * field. Uses Nystroem algorithm (See Handbook Nat. Bur. of *
854/// * Standards, procedure 25.5.20) *
855/// * *
856/// * Input parameters *
857/// * CHARGE Particle charge *
858/// * STEP Step size *
859/// * VECT Initial co-ords,direction cosines,momentum *
860/// * Output parameters *
861/// * VOUT Output co-ords,direction cosines,momentum *
862/// * User routine called *
863/// * CALL GUFLD(X,F) *
864/// * *
865/// * ==>Called by : <USER>, GUSWIM *
866/// * Authors R.Brun, M.Hansroul ********* *
867/// * V.Perevoztchikov (CUT STEP implementation) *
868/// * *
869/// * *
870/// ******************************************************************
871
872 Double_t h2, h4, f[4];
873 Double_t xyzt[3], a, b, c, ph,ph2;
874 Double_t secxs[4],secys[4],seczs[4],hxp[3];
875 Double_t g1, g2, g3, g4, g5, g6, ang2, dxt, dyt, dzt;
876 Double_t est, at, bt, ct, cba;
877 Double_t f1, f2, f3, f4, rho, tet, hnorm, hp, rho1, sint, cost;
878
879 Double_t x;
880 Double_t y;
881 Double_t z;
882
883 Double_t xt;
884 Double_t yt;
885 Double_t zt;
886
887 Double_t maxit = 1992;
888 Double_t maxcut = 11;
889
890 const Double_t kdlt = 1e-4;
891 const Double_t kdlt32 = kdlt/32.;
892 const Double_t kthird = 1./3.;
893 const Double_t khalf = 0.5;
894 const Double_t kec = 2.9979251e-4;
895
896 const Double_t kpisqua = 9.86960440109;
897 const Int_t kix = 0;
898 const Int_t kiy = 1;
899 const Int_t kiz = 2;
900 const Int_t kipx = 3;
901 const Int_t kipy = 4;
902 const Int_t kipz = 5;
903
904 // *.
905 // *. ------------------------------------------------------------------
906 // *.
907 // * this constant is for units cm,gev/c and kgauss
908 // *
909 Int_t iter = 0;
910 Int_t ncut = 0;
911 for(Int_t j = 0; j < 7; j++)
912 vout[j] = vect[j];
913
914 Double_t pinv = kec * charge / vect[6];
915 Double_t tl = 0.;
916 Double_t h = step;
917 Double_t rest;
918
919
920 do {
921 rest = step - tl;
922 if (TMath::Abs(h) > TMath::Abs(rest)) h = rest;
923 //cmodif: call gufld(vout,f) changed into:
924
925 GetField(vout,f);
926
927 // *
928 // * start of integration
929 // *
930 x = vout[0];
931 y = vout[1];
932 z = vout[2];
933 a = vout[3];
934 b = vout[4];
935 c = vout[5];
936
937 h2 = khalf * h;
938 h4 = khalf * h2;
939 ph = pinv * h;
940 ph2 = khalf * ph;
941 secxs[0] = (b * f[2] - c * f[1]) * ph2;
942 secys[0] = (c * f[0] - a * f[2]) * ph2;
943 seczs[0] = (a * f[1] - b * f[0]) * ph2;
944 ang2 = (secxs[0]*secxs[0] + secys[0]*secys[0] + seczs[0]*seczs[0]);
945 if (ang2 > kpisqua) break;
946
947 dxt = h2 * a + h4 * secxs[0];
948 dyt = h2 * b + h4 * secys[0];
949 dzt = h2 * c + h4 * seczs[0];
950 xt = x + dxt;
951 yt = y + dyt;
952 zt = z + dzt;
953 // *
954 // * second intermediate point
955 // *
956
957 est = TMath::Abs(dxt) + TMath::Abs(dyt) + TMath::Abs(dzt);
958 if (est > h) {
959 if (ncut++ > maxcut) break;
960 h *= khalf;
961 continue;
962 }
963
964 xyzt[0] = xt;
965 xyzt[1] = yt;
966 xyzt[2] = zt;
967
968 //cmodif: call gufld(xyzt,f) changed into:
969 GetField(xyzt,f);
970
971 at = a + secxs[0];
972 bt = b + secys[0];
973 ct = c + seczs[0];
974
975 secxs[1] = (bt * f[2] - ct * f[1]) * ph2;
976 secys[1] = (ct * f[0] - at * f[2]) * ph2;
977 seczs[1] = (at * f[1] - bt * f[0]) * ph2;
978 at = a + secxs[1];
979 bt = b + secys[1];
980 ct = c + seczs[1];
981 secxs[2] = (bt * f[2] - ct * f[1]) * ph2;
982 secys[2] = (ct * f[0] - at * f[2]) * ph2;
983 seczs[2] = (at * f[1] - bt * f[0]) * ph2;
984 dxt = h * (a + secxs[2]);
985 dyt = h * (b + secys[2]);
986 dzt = h * (c + seczs[2]);
987 xt = x + dxt;
988 yt = y + dyt;
989 zt = z + dzt;
990 at = a + 2.*secxs[2];
991 bt = b + 2.*secys[2];
992 ct = c + 2.*seczs[2];
993
994 est = TMath::Abs(dxt)+TMath::Abs(dyt)+TMath::Abs(dzt);
995 if (est > 2.*TMath::Abs(h)) {
996 if (ncut++ > maxcut) break;
997 h *= khalf;
998 continue;
999 }
1000
1001 xyzt[0] = xt;
1002 xyzt[1] = yt;
1003 xyzt[2] = zt;
1004
1005 //cmodif: call gufld(xyzt,f) changed into:
1006 GetField(xyzt,f);
1007
1008 z = z + (c + (seczs[0] + seczs[1] + seczs[2]) * kthird) * h;
1009 y = y + (b + (secys[0] + secys[1] + secys[2]) * kthird) * h;
1010 x = x + (a + (secxs[0] + secxs[1] + secxs[2]) * kthird) * h;
1011
1012 secxs[3] = (bt*f[2] - ct*f[1])* ph2;
1013 secys[3] = (ct*f[0] - at*f[2])* ph2;
1014 seczs[3] = (at*f[1] - bt*f[0])* ph2;
1015 a = a+(secxs[0]+secxs[3]+2. * (secxs[1]+secxs[2])) * kthird;
1016 b = b+(secys[0]+secys[3]+2. * (secys[1]+secys[2])) * kthird;
1017 c = c+(seczs[0]+seczs[3]+2. * (seczs[1]+seczs[2])) * kthird;
1018
1019 est = TMath::Abs(secxs[0]+secxs[3] - (secxs[1]+secxs[2]))
1020 + TMath::Abs(secys[0]+secys[3] - (secys[1]+secys[2]))
1021 + TMath::Abs(seczs[0]+seczs[3] - (seczs[1]+seczs[2]));
1022
1023 if (est > kdlt && TMath::Abs(h) > 1.e-4) {
1024 if (ncut++ > maxcut) break;
1025 h *= khalf;
1026 continue;
1027 }
1028
1029 ncut = 0;
1030 // * if too many iterations, go to helix
1031 if (iter++ > maxit) break;
1032
1033 tl += h;
1034 if (est < kdlt32)
1035 h *= 2.;
1036 cba = 1./ TMath::Sqrt(a*a + b*b + c*c);
1037 vout[0] = x;
1038 vout[1] = y;
1039 vout[2] = z;
1040 vout[3] = cba*a;
1041 vout[4] = cba*b;
1042 vout[5] = cba*c;
1043 rest = step - tl;
1044 if (step < 0.) rest = -rest;
1045 if (rest < 1.e-5*TMath::Abs(step)) return;
1046
1047 } while(1);
1048
1049 // angle too big, use helix
1050
1051 f1 = f[0];
1052 f2 = f[1];
1053 f3 = f[2];
1054 f4 = TMath::Sqrt(f1*f1+f2*f2+f3*f3);
1055 rho = -f4*pinv;
1056 tet = rho * step;
1057
1058 hnorm = 1./f4;
1059 f1 = f1*hnorm;
1060 f2 = f2*hnorm;
1061 f3 = f3*hnorm;
1062
1063 hxp[0] = f2*vect[kipz] - f3*vect[kipy];
1064 hxp[1] = f3*vect[kipx] - f1*vect[kipz];
1065 hxp[2] = f1*vect[kipy] - f2*vect[kipx];
1066
1067 hp = f1*vect[kipx] + f2*vect[kipy] + f3*vect[kipz];
1068
1069 rho1 = 1./rho;
1070 sint = TMath::Sin(tet);
1071 cost = 2.*TMath::Sin(khalf*tet)*TMath::Sin(khalf*tet);
1072
1073 g1 = sint*rho1;
1074 g2 = cost*rho1;
1075 g3 = (tet-sint) * hp*rho1;
1076 g4 = -cost;
1077 g5 = sint;
1078 g6 = cost * hp;
1079
1080 vout[kix] = vect[kix] + g1*vect[kipx] + g2*hxp[0] + g3*f1;
1081 vout[kiy] = vect[kiy] + g1*vect[kipy] + g2*hxp[1] + g3*f2;
1082 vout[kiz] = vect[kiz] + g1*vect[kipz] + g2*hxp[2] + g3*f3;
1083
1084 vout[kipx] = vect[kipx] + g4*vect[kipx] + g5*hxp[0] + g6*f1;
1085 vout[kipy] = vect[kipy] + g4*vect[kipy] + g5*hxp[1] + g6*f2;
1086 vout[kipz] = vect[kipz] + g4*vect[kipz] + g5*hxp[2] + g6*f3;
1087
1088 return;
1089}
1090//___________________________________________________________
1091 void AliMUONTrackExtrap::GetField(Double_t *Position, Double_t *Field)
1092{
1093 /// interface for arguments in double precision (Why ? ChF)
1094 Float_t x[3], b[3];
1095
1096 x[0] = Position[0]; x[1] = Position[1]; x[2] = Position[2];
1097
1098 if (fgkField) fgkField->Field(x,b);
1099 else {
1100 cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
1101 exit(-1);
1102 }
1103
1104 Field[0] = b[0]; Field[1] = b[1]; Field[2] = b[2];
1105
1106 return;
1107}
1108