1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ///////////////////////////////////////////////////
29 ///////////////////////////////////////////////////
31 #include <Riostream.h>
35 #include "AliMUONTrackExtrap.h"
36 #include "AliMUONTrackParam.h"
37 #include "AliMUONConstants.h"
40 #include "AliTracker.h"
42 ClassImp(AliMUONTrackExtrap) // Class implementation in ROOT context
44 const AliMagF* AliMUONTrackExtrap::fgkField = 0x0;
45 const Bool_t AliMUONTrackExtrap::fgkUseHelix = kFALSE;
46 const Int_t AliMUONTrackExtrap::fgkMaxStepNumber = 5000;
47 const Double_t AliMUONTrackExtrap::fgkHelixStepLength = 6.;
48 const Double_t AliMUONTrackExtrap::fgkRungeKuttaMaxResidue = 0.002;
50 //__________________________________________________________________________
51 Double_t AliMUONTrackExtrap::GetImpactParamFromBendingMomentum(Double_t bendingMomentum)
53 /// Returns impact parameter at vertex in bending plane (cm),
54 /// from the signed bending momentum "BendingMomentum" in bending plane (GeV/c),
55 /// using simple values for dipole magnetic field.
56 /// The sign of "BendingMomentum" is the sign of the charge.
58 if (bendingMomentum == 0.) return 1.e10;
60 Double_t simpleBPosition = 0.5 * (AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ());
61 Double_t simpleBLength = 0.5 * (AliMUONConstants::CoilL() + AliMUONConstants::YokeL());
62 Float_t b[3], x[3] = {0.,0.,(Float_t) simpleBPosition};
63 if (fgkField) fgkField->Field(x,b);
65 cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
68 Double_t simpleBValue = (Double_t) b[0];
70 return (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / bendingMomentum);
73 //__________________________________________________________________________
74 Double_t AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(Double_t impactParam)
76 /// Returns signed bending momentum in bending plane (GeV/c),
77 /// the sign being the sign of the charge for particles moving forward in Z,
78 /// from the impact parameter "ImpactParam" at vertex in bending plane (cm),
79 /// using simple values for dipole magnetic field.
81 if (impactParam == 0.) return 1.e10;
83 Double_t simpleBPosition = 0.5 * (AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ());
84 Double_t simpleBLength = 0.5 * (AliMUONConstants::CoilL() + AliMUONConstants::YokeL());
85 Float_t b[3], x[3] = {0.,0.,(Float_t) simpleBPosition};
86 if (fgkField) fgkField->Field(x,b);
88 cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
91 Double_t simpleBValue = (Double_t) b[0];
93 return (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / impactParam);
96 //__________________________________________________________________________
97 void AliMUONTrackExtrap::ExtrapToZ(AliMUONTrackParam* trackParam, Double_t zEnd)
99 /// Interface to track parameter extrapolation to the plane at "Z" using Helix or Rungekutta algorithm.
100 /// On return, the track parameters resulting from the extrapolation are updated in trackParam.
101 if (fgkUseHelix) AliMUONTrackExtrap::ExtrapToZHelix(trackParam,zEnd);
102 else AliMUONTrackExtrap::ExtrapToZRungekutta(trackParam,zEnd);
105 //__________________________________________________________________________
106 void AliMUONTrackExtrap::ExtrapToZHelix(AliMUONTrackParam* trackParam, Double_t zEnd)
108 /// Track parameter extrapolation to the plane at "Z" using Helix algorithm.
109 /// On return, the track parameters resulting from the extrapolation are updated in trackParam.
110 if (trackParam->GetZ() == zEnd) return; // nothing to be done if same Z
111 Double_t forwardBackward; // +1 if forward, -1 if backward
112 if (zEnd < trackParam->GetZ()) forwardBackward = 1.0; // spectro. z<0
113 else forwardBackward = -1.0;
114 Double_t v3[7], v3New[7]; // 7 in parameter ????
115 Int_t i3, stepNumber;
116 // For safety: return kTRUE or kFALSE ????
117 // Parameter vector for calling EXTRAP_ONESTEP
118 ConvertTrackParamForExtrap(trackParam, forwardBackward, v3);
119 // sign of charge (sign of fInverseBendingMomentum if forward motion)
120 // must be changed if backward extrapolation
121 Double_t chargeExtrap = forwardBackward * TMath::Sign(Double_t(1.0), trackParam->GetInverseBendingMomentum());
122 // Extrapolation loop
124 while (((-forwardBackward * (v3[2] - zEnd)) <= 0.0) && (stepNumber < fgkMaxStepNumber)) { // spectro. z<0
126 ExtrapOneStepHelix(chargeExtrap, fgkHelixStepLength, v3, v3New);
127 if ((-forwardBackward * (v3New[2] - zEnd)) > 0.0) break; // one is beyond Z spectro. z<0
128 // better use TArray ????
129 for (i3 = 0; i3 < 7; i3++) {v3[i3] = v3New[i3];}
131 // check fgkMaxStepNumber ????
132 // Interpolation back to exact Z (2nd order)
133 // should be in function ???? using TArray ????
134 Double_t dZ12 = v3New[2] - v3[2]; // 1->2
135 if (TMath::Abs(dZ12) > 0) {
136 Double_t dZ1i = zEnd - v3[2]; // 1-i
137 Double_t dZi2 = v3New[2] - zEnd; // i->2
138 Double_t xPrime = (v3New[0] - v3[0]) / dZ12;
139 Double_t xSecond = ((v3New[3] / v3New[5]) - (v3[3] / v3[5])) / dZ12;
140 Double_t yPrime = (v3New[1] - v3[1]) / dZ12;
141 Double_t ySecond = ((v3New[4] / v3New[5]) - (v3[4] / v3[5])) / dZ12;
142 v3[0] = v3[0] + xPrime * dZ1i - 0.5 * xSecond * dZ1i * dZi2; // X
143 v3[1] = v3[1] + yPrime * dZ1i - 0.5 * ySecond * dZ1i * dZi2; // Y
145 Double_t xPrimeI = xPrime - 0.5 * xSecond * (dZi2 - dZ1i);
146 Double_t yPrimeI = yPrime - 0.5 * ySecond * (dZi2 - dZ1i);
147 // (PX, PY, PZ)/PTOT assuming forward motion
148 v3[5] = 1.0 / TMath::Sqrt(1.0 + xPrimeI * xPrimeI + yPrimeI * yPrimeI); // PZ/PTOT
149 v3[3] = xPrimeI * v3[5]; // PX/PTOT
150 v3[4] = yPrimeI * v3[5]; // PY/PTOT
152 cout<<"W-AliMUONTrackExtrap::ExtrapToZHelix: Extrap. to Z not reached, Z = "<<zEnd<<endl;
154 // Recover track parameters (charge back for forward motion)
155 RecoverTrackParam(v3, chargeExtrap * forwardBackward, trackParam);
158 //__________________________________________________________________________
159 void AliMUONTrackExtrap::ExtrapToZRungekutta(AliMUONTrackParam* trackParam, Double_t zEnd)
161 /// Track parameter extrapolation to the plane at "Z" using Rungekutta algorithm.
162 /// On return, the track parameters resulting from the extrapolation are updated in trackParam.
163 if (trackParam->GetZ() == zEnd) return; // nothing to be done if same Z
164 Double_t forwardBackward; // +1 if forward, -1 if backward
165 if (zEnd < trackParam->GetZ()) forwardBackward = 1.0; // spectro. z<0
166 else forwardBackward = -1.0;
167 // sign of charge (sign of fInverseBendingMomentum if forward motion)
168 // must be changed if backward extrapolation
169 Double_t chargeExtrap = forwardBackward * TMath::Sign(Double_t(1.0), trackParam->GetInverseBendingMomentum());
170 Double_t v3[7], v3New[7];
172 Int_t stepNumber = 0;
174 // Extrapolation loop (until within tolerance)
175 Double_t residue = zEnd - trackParam->GetZ();
176 while (TMath::Abs(residue) > fgkRungeKuttaMaxResidue && stepNumber <= fgkMaxStepNumber) {
177 dZ = zEnd - trackParam->GetZ();
178 // step lenght assuming linear trajectory
179 step = dZ * TMath::Sqrt(1.0 + trackParam->GetBendingSlope()*trackParam->GetBendingSlope() +
180 trackParam->GetNonBendingSlope()*trackParam->GetNonBendingSlope());
181 ConvertTrackParamForExtrap(trackParam, forwardBackward, v3);
182 do { // reduce step lenght while zEnd oversteped
183 if (stepNumber > fgkMaxStepNumber) {
184 cout<<"W-AliMUONTrackExtrap::ExtrapToZRungekutta: Too many trials: "<<stepNumber<<endl;
188 step = TMath::Abs(step);
189 AliMUONTrackExtrap::ExtrapOneStepRungekutta(chargeExtrap,step,v3,v3New);
190 residue = zEnd - v3New[2];
191 step *= dZ/(v3New[2]-trackParam->GetZ());
192 } while (residue*dZ < 0 && TMath::Abs(residue) > fgkRungeKuttaMaxResidue);
193 RecoverTrackParam(v3New, chargeExtrap * forwardBackward, trackParam);
196 // terminate the extropolation with a straight line up to the exact "zEnd" value
197 trackParam->SetNonBendingCoor(trackParam->GetNonBendingCoor() + residue * trackParam->GetNonBendingSlope());
198 trackParam->SetBendingCoor(trackParam->GetBendingCoor() + residue * trackParam->GetBendingSlope());
199 trackParam->SetZ(zEnd);
202 //__________________________________________________________________________
203 void AliMUONTrackExtrap::ConvertTrackParamForExtrap(AliMUONTrackParam* trackParam, Double_t forwardBackward, Double_t *v3)
205 /// Set vector of Geant3 parameters pointed to by "v3" from track parameters in trackParam.
206 /// Since AliMUONTrackParam is only geometry, one uses "forwardBackward"
207 /// to know whether the particle is going forward (+1) or backward (-1).
208 v3[0] = trackParam->GetNonBendingCoor(); // X
209 v3[1] = trackParam->GetBendingCoor(); // Y
210 v3[2] = trackParam->GetZ(); // Z
211 Double_t pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
212 Double_t pZ = pYZ / TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope());
213 v3[6] = TMath::Sqrt(pYZ * pYZ + pZ * pZ * trackParam->GetNonBendingSlope() * trackParam->GetNonBendingSlope()); // PTOT
214 v3[5] = -forwardBackward * pZ / v3[6]; // PZ/PTOT spectro. z<0
215 v3[3] = trackParam->GetNonBendingSlope() * v3[5]; // PX/PTOT
216 v3[4] = trackParam->GetBendingSlope() * v3[5]; // PY/PTOT
219 //__________________________________________________________________________
220 void AliMUONTrackExtrap::RecoverTrackParam(Double_t *v3, Double_t charge, AliMUONTrackParam* trackParam)
222 /// Set track parameters in trackParam from Geant3 parameters pointed to by "v3",
223 /// assumed to be calculated for forward motion in Z.
224 /// "InverseBendingMomentum" is signed with "charge".
225 trackParam->SetNonBendingCoor(v3[0]); // X
226 trackParam->SetBendingCoor(v3[1]); // Y
227 trackParam->SetZ(v3[2]); // Z
228 Double_t pYZ = v3[6] * TMath::Sqrt(1.0 - v3[3] * v3[3]);
229 trackParam->SetInverseBendingMomentum(charge/pYZ);
230 trackParam->SetBendingSlope(v3[4]/v3[5]);
231 trackParam->SetNonBendingSlope(v3[3]/v3[5]);
234 //__________________________________________________________________________
235 void AliMUONTrackExtrap::ExtrapToZCov(AliMUONTrackParam* trackParam, Double_t zEnd)
237 /// Track parameters and their covariances extrapolated to the plane at "zEnd".
238 /// On return, results from the extrapolation are updated in trackParam.
240 if (trackParam->GetZ() == zEnd) return; // nothing to be done if same z
242 // Save the actual track parameters
243 AliMUONTrackParam trackParamSave(*trackParam);
244 Double_t nonBendingCoor = trackParamSave.GetNonBendingCoor();
245 Double_t nonBendingSlope = trackParamSave.GetNonBendingSlope();
246 Double_t bendingCoor = trackParamSave.GetBendingCoor();
247 Double_t bendingSlope = trackParamSave.GetBendingSlope();
248 Double_t inverseBendingMomentum = trackParamSave.GetInverseBendingMomentum();
249 Double_t zBegin = trackParamSave.GetZ();
251 // Extrapolate track parameters to "zEnd"
252 ExtrapToZ(trackParam,zEnd);
253 Double_t extrapNonBendingCoor = trackParam->GetNonBendingCoor();
254 Double_t extrapNonBendingSlope = trackParam->GetNonBendingSlope();
255 Double_t extrapBendingCoor = trackParam->GetBendingCoor();
256 Double_t extrapBendingSlope = trackParam->GetBendingSlope();
257 Double_t extrapInverseBendingMomentum = trackParam->GetInverseBendingMomentum();
259 // Get the pointer to the parameter covariance matrix
260 if (!trackParam->CovariancesExist()) {
261 //cout<<"W-AliMUONTrackExtrap::ExtrapToZCov: track parameter covariance matrix does not exist"<<endl;
262 //cout<<" -> nothing to extrapolate !!"<<endl;
265 TMatrixD* paramCov = trackParam->GetCovariances();
267 // Calculate the jacobian related to the track parameters extrapolation to "zEnd"
271 for (Int_t i=0; i<5; i++) {
272 // Skip jacobian calculation for parameters with no associated error
273 if ((*paramCov)(i,i) == 0.) continue;
274 // Small variation of parameter i only
275 for (Int_t j=0; j<5; j++) {
277 dParam[j] = TMath::Sqrt((*paramCov)(i,i));
278 if (j == 4) dParam[j] *= TMath::Sign(1.,-inverseBendingMomentum); // variation always in the same direction
279 } else dParam[j] = 0.;
281 // Set new parameters
282 trackParamSave.SetNonBendingCoor (nonBendingCoor + dParam[0]);
283 trackParamSave.SetNonBendingSlope (nonBendingSlope + dParam[1]);
284 trackParamSave.SetBendingCoor (bendingCoor + dParam[2]);
285 trackParamSave.SetBendingSlope (bendingSlope + dParam[3]);
286 trackParamSave.SetInverseBendingMomentum(inverseBendingMomentum + dParam[4]);
287 trackParamSave.SetZ (zBegin);
288 // Extrapolate new track parameters to "zEnd"
289 ExtrapToZ(&trackParamSave,zEnd);
290 // Calculate the jacobian
291 jacob(0,i) = (trackParamSave.GetNonBendingCoor() - extrapNonBendingCoor ) / dParam[i];
292 jacob(1,i) = (trackParamSave.GetNonBendingSlope() - extrapNonBendingSlope ) / dParam[i];
293 jacob(2,i) = (trackParamSave.GetBendingCoor() - extrapBendingCoor ) / dParam[i];
294 jacob(3,i) = (trackParamSave.GetBendingSlope() - extrapBendingSlope ) / dParam[i];
295 jacob(4,i) = (trackParamSave.GetInverseBendingMomentum() - extrapInverseBendingMomentum) / dParam[i];
298 // Extrapolate track parameter covariances to "zEnd"
299 TMatrixD tmp((*paramCov),TMatrixD::kMultTranspose,jacob);
300 (*paramCov) = TMatrixD(jacob,TMatrixD::kMult,tmp);
304 //__________________________________________________________________________
305 void AliMUONTrackExtrap::ExtrapToStation(AliMUONTrackParam* trackParamIn, Int_t station, AliMUONTrackParam *trackParamOut)
307 /// Track parameters extrapolated from "trackParamIn" to both chambers of the station(0..) "station"
308 /// are returned in the array (dimension 2) of track parameters pointed to by "TrackParamOut"
309 /// (index 0 and 1 for first and second chambers).
310 Double_t extZ[2], z1, z2;
311 Int_t i1 = -1, i2 = -1; // = -1 to avoid compilation warnings
312 // range of station to be checked ????
313 z1 = AliMUONConstants::DefaultChamberZ(2 * station);
314 z2 = AliMUONConstants::DefaultChamberZ(2 * station + 1);
315 // First and second Z to extrapolate at
316 if ((z1 > trackParamIn->GetZ()) && (z2 > trackParamIn->GetZ())) {i1 = 0; i2 = 1;}
317 else if ((z1 < trackParamIn->GetZ()) && (z2 < trackParamIn->GetZ())) {i1 = 1; i2 = 0;}
319 cout<<"E-AliMUONTrackExtrap::ExtrapToStation: Starting Z ("<<trackParamIn->GetZ()
320 <<") in between z1 ("<<z1<<") and z2 ("<<z2<<") of station(0..)"<<station<<endl;
325 // copy of track parameters
326 trackParamOut[i1] = *trackParamIn;
327 // first extrapolation
328 ExtrapToZ(&(trackParamOut[i1]),extZ[0]);
329 trackParamOut[i2] = trackParamOut[i1];
330 // second extrapolation
331 ExtrapToZ(&(trackParamOut[i2]),extZ[1]);
335 //__________________________________________________________________________
336 void AliMUONTrackExtrap::ExtrapToVertexUncorrected(AliMUONTrackParam* trackParam, Double_t zVtx)
338 /// Extrapolation to the vertex (at the z position "zVtx") without Branson and Field correction.
339 /// Returns the track parameters resulting from the extrapolation in the current TrackParam.
340 /// Include multiple Coulomb scattering effects in trackParam covariances.
342 if (trackParam->GetZ() > zVtx) { // spectro. (z<0)
343 cout<<"W-AliMUONTrackExtrap::ExtrapToVertexUncorrected: Starting Z ("<<trackParam->GetZ()
344 <<") upstream the vertex (zVtx = "<<zVtx<<")"<<endl;
348 if (zVtx < AliMUONConstants::ZAbsorberEnd()) { // spectro. (z<0)
349 cout<<"W-AliMUONTrackExtrap::ExtrapToVertexUncorrected: Ending Z ("<<zVtx
350 <<") downstream the front absorber (zAbsorberEnd = "<<AliMUONConstants::ZAbsorberEnd()<<")"<<endl;
352 ExtrapToZCov(trackParam,zVtx);
356 // First Extrapolates track parameters upstream to the "Z" end of the front absorber
357 if (trackParam->GetZ() < AliMUONConstants::ZAbsorberEnd()) { // spectro. (z<0)
358 ExtrapToZCov(trackParam,AliMUONConstants::ZAbsorberEnd());
360 cout<<"W-AliMUONTrackExtrap::ExtrapToVertexUncorrected: Starting Z ("<<trackParam->GetZ()
361 <<") upstream or inside the front absorber (zAbsorberEnd = "<<AliMUONConstants::ZAbsorberEnd()<<")"<<endl;
364 // Then go through all the absorber layers
365 Double_t tan3 = TMath::Tan(3./180.*TMath::Pi());
366 Double_t r0Norm, x0, z, zElement, dZ, nonBendingCoor, bendingCoor;
367 for (Int_t iElement=AliMUONConstants::NAbsorberElements()-1; iElement>=0; iElement--) {
368 zElement = AliMUONConstants::ZAbsorberElement(iElement);
369 z = trackParam->GetZ();
370 if (z > zElement) continue; // spectro. (z<0)
371 nonBendingCoor = trackParam->GetNonBendingCoor();
372 bendingCoor = trackParam->GetBendingCoor();
373 r0Norm = nonBendingCoor * nonBendingCoor + bendingCoor * bendingCoor;
374 r0Norm = TMath::Sqrt(r0Norm) / TMath::Abs(trackParam->GetZ()) / tan3;
375 if (r0Norm > 1.) x0 = AliMUONConstants::X0AbsorberOut(iElement); // outer part of the absorber
376 else x0 = AliMUONConstants::X0AbsorberIn(iElement); // inner part of the absorber
378 if (zVtx > zElement) {
379 ExtrapToZCov(trackParam,zElement); // extrapolate to absorber element "iElement"
381 AddMCSEffectInTrackParamCov(trackParam,dZ,x0); // include MCS effect in covariances
383 ExtrapToZCov(trackParam,zVtx); // extrapolate to zVtx
385 AddMCSEffectInTrackParamCov(trackParam,dZ,x0); // include MCS effect in covariances
390 // finally go to the vertex
391 ExtrapToZCov(trackParam,zVtx);
395 //__________________________________________________________________________
396 void AliMUONTrackExtrap::AddMCSEffectInTrackParamCov(AliMUONTrackParam *param, Double_t dZ, Double_t x0)
398 /// Add to the track parameter covariances the effects of multiple Coulomb scattering
399 /// through a material of thickness "dZ" and of radiation length "x0"
400 /// assuming linear propagation and using the small angle approximation.
402 Double_t bendingSlope = param->GetBendingSlope();
403 Double_t nonBendingSlope = param->GetNonBendingSlope();
404 Double_t inverseTotalMomentum2 = param->GetInverseBendingMomentum() * param->GetInverseBendingMomentum() *
405 (1.0 + bendingSlope * bendingSlope) /
406 (1.0 + bendingSlope *bendingSlope + nonBendingSlope * nonBendingSlope);
407 // Path length in the material
408 Double_t pathLength = TMath::Abs(dZ) * TMath::Sqrt(1.0 + bendingSlope*bendingSlope + nonBendingSlope*nonBendingSlope);
409 Double_t pathLength2 = pathLength * pathLength;
410 // relativistic velocity
412 // Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory
413 Double_t theta02 = 0.0136 / velo * (1 + 0.038 * TMath::Log(pathLength/x0));
414 theta02 *= theta02 * inverseTotalMomentum2 * pathLength / x0;
416 // Add effects of multiple Coulomb scattering in track parameter covariances
417 TMatrixD* paramCov = param->GetCovariances();
418 Double_t varCoor = pathLength2 * theta02 / 3.;
419 Double_t varSlop = theta02;
420 Double_t covCorrSlope = pathLength * theta02 / 2.;
422 (*paramCov)(0,0) += varCoor; (*paramCov)(0,1) += covCorrSlope;
423 (*paramCov)(1,0) += covCorrSlope; (*paramCov)(1,1) += varSlop;
425 (*paramCov)(2,2) += varCoor; (*paramCov)(2,3) += covCorrSlope;
426 (*paramCov)(3,2) += covCorrSlope; (*paramCov)(3,3) += varSlop;
430 //__________________________________________________________________________
431 void AliMUONTrackExtrap::ExtrapToVertex(AliMUONTrackParam* trackParam, Double_t xVtx, Double_t yVtx, Double_t zVtx)
433 /// Extrapolation to the vertex.
434 /// Returns the track parameters resulting from the extrapolation in the current TrackParam.
435 /// Changes parameters according to Branson correction through the absorber
437 // Extrapolates track parameters upstream to the "Z" end of the front absorber
438 ExtrapToZ(trackParam,AliMUONConstants::ZAbsorberEnd()); // !!!
439 // Makes Branson correction (multiple scattering + energy loss)
440 BransonCorrection(trackParam,xVtx,yVtx,zVtx);
441 // Makes a simple magnetic field correction through the absorber
442 FieldCorrection(trackParam,AliMUONConstants::ZAbsorberEnd());
446 // Keep this version for future developments
447 //__________________________________________________________________________
448 // void AliMUONTrackExtrap::BransonCorrection(AliMUONTrackParam* trackParam)
450 // /// Branson correction of track parameters
451 // // the entry parameters have to be calculated at the end of the absorber
452 // Double_t zEndAbsorber, zBP, xBP, yBP;
453 // Double_t pYZ, pX, pY, pZ, pTotal, xEndAbsorber, yEndAbsorber, radiusEndAbsorber2, pT, theta;
455 // // Would it be possible to calculate all that from Geant configuration ????
456 // // and to get the Branson parameters from a function in ABSO module ????
457 // // with an eventual contribution from other detectors like START ????
458 // // Radiation lengths outer part theta > 3 degres
459 // static Double_t x01[9] = { 18.8, // C (cm)
460 // 10.397, // Concrete (cm)
461 // 0.56, // Plomb (cm)
462 // 47.26, // Polyethylene (cm)
463 // 0.56, // Plomb (cm)
464 // 47.26, // Polyethylene (cm)
465 // 0.56, // Plomb (cm)
466 // 47.26, // Polyethylene (cm)
467 // 0.56 }; // Plomb (cm)
468 // // inner part theta < 3 degres
469 // static Double_t x02[3] = { 18.8, // C (cm)
470 // 10.397, // Concrete (cm)
472 // // z positions of the materials inside the absober outer part theta > 3 degres
473 // static Double_t z1[10] = { 90, 315, 467, 472, 477, 482, 487, 492, 497, 502 };
474 // // inner part theta < 3 degres
475 // static Double_t z2[4] = { 90, 315, 467, 503 };
476 // static Bool_t first = kTRUE;
477 // static Double_t zBP1, zBP2, rLimit;
478 // // Calculates z positions of the Branson's planes: zBP1 for outer part and zBP2 for inner part (only at the first call)
481 // Double_t aNBP = 0.0;
482 // Double_t aDBP = 0.0;
485 // for (iBound = 0; iBound < 9; iBound++) {
487 // (z1[iBound+1] * z1[iBound+1] * z1[iBound+1] -
488 // z1[iBound] * z1[iBound] * z1[iBound] ) / x01[iBound];
490 // (z1[iBound+1] * z1[iBound+1] - z1[iBound] * z1[iBound] ) / x01[iBound];
492 // zBP1 = (2.0 * aNBP) / (3.0 * aDBP);
495 // for (iBound = 0; iBound < 3; iBound++) {
497 // (z2[iBound+1] * z2[iBound+1] * z2[iBound+1] -
498 // z2[iBound] * z2[iBound ] * z2[iBound] ) / x02[iBound];
500 // (z2[iBound+1] * z2[iBound+1] - z2[iBound] * z2[iBound]) / x02[iBound];
502 // zBP2 = (2.0 * aNBP) / (3.0 * aDBP);
503 // rLimit = z2[3] * TMath::Tan(3.0 * (TMath::Pi()) / 180.);
506 // pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
508 // if (trackParam->GetInverseBendingMomentum() < 0) sign = -1;
509 // pZ = pYZ / (TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope()));
510 // pX = pZ * trackParam->GetNonBendingSlope();
511 // pY = pZ * trackParam->GetBendingSlope();
512 // pTotal = TMath::Sqrt(pYZ *pYZ + pX * pX);
513 // xEndAbsorber = trackParam->GetNonBendingCoor();
514 // yEndAbsorber = trackParam->GetBendingCoor();
515 // radiusEndAbsorber2 = xEndAbsorber * xEndAbsorber + yEndAbsorber * yEndAbsorber;
517 // if (radiusEndAbsorber2 > rLimit*rLimit) {
518 // zEndAbsorber = z1[9];
521 // zEndAbsorber = z2[3];
525 // xBP = xEndAbsorber - (pX / pZ) * (zEndAbsorber - zBP);
526 // yBP = yEndAbsorber - (pY / pZ) * (zEndAbsorber - zBP);
528 // // new parameters after Branson and energy loss corrections
529 // pZ = pTotal * zBP / TMath::Sqrt(xBP * xBP + yBP * yBP + zBP * zBP);
530 // pX = pZ * xBP / zBP;
531 // pY = pZ * yBP / zBP;
532 // trackParam->SetBendingSlope(pY/pZ);
533 // trackParam->SetNonBendingSlope(pX/pZ);
535 // pT = TMath::Sqrt(pX * pX + pY * pY);
536 // theta = TMath::ATan2(pT, pZ);
537 // pTotal = TotalMomentumEnergyLoss(rLimit, pTotal, theta, xEndAbsorber, yEndAbsorber);
539 // trackParam->SetInverseBendingMomentum((sign / pTotal) *
541 // trackParam->GetBendingSlope() * trackParam->GetBendingSlope() +
542 // trackParam->GetNonBendingSlope() * trackParam->GetNonBendingSlope()) /
543 // TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope()));
545 // // vertex position at (0,0,0)
546 // // should be taken from vertex measurement ???
547 // trackParam->SetBendingCoor(0.);
548 // trackParam->SetNonBendingCoor(0.);
549 // trackParam->SetZ(0.);
552 void AliMUONTrackExtrap::BransonCorrection(AliMUONTrackParam* trackParam, Double_t xVtx, Double_t yVtx, Double_t zVtx)
554 /// Branson correction of track parameters
555 // the entry parameters have to be calculated at the end of the absorber
556 // simplified version: the z positions of Branson's planes are no longer calculated
557 // but are given as inputs. One can use the macros MUONTestAbso.C and DrawTestAbso.C
558 // to test this correction.
559 // Would it be possible to calculate all that from Geant configuration ????
560 // and to get the Branson parameters from a function in ABSO module ????
561 // with an eventual contribution from other detectors like START ????
562 // change to take into account the vertex postition (real, reconstruct,....)
564 Double_t zBP, xBP, yBP;
565 Double_t pYZ, pX, pY, pZ, pTotal, xEndAbsorber, yEndAbsorber, radiusEndAbsorber2, pT, theta;
567 static Bool_t first = kTRUE;
568 static Double_t zBP1, zBP2, rLimit, thetaLimit;
569 // zBP1 for outer part and zBP2 for inner part (only at the first call)
573 thetaLimit = 3.0 * (TMath::Pi()) / 180.;
574 rLimit = TMath::Abs(AliMUONConstants::ZAbsorberEnd()) * TMath::Tan(thetaLimit);
575 zBP1 = -450; // values close to those calculated with EvalAbso.C
579 pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
581 if (trackParam->GetInverseBendingMomentum() < 0) sign = -1;
582 pZ = trackParam->Pz();
583 pX = trackParam->Px();
584 pY = trackParam->Py();
585 pTotal = TMath::Sqrt(pYZ *pYZ + pX * pX);
586 xEndAbsorber = trackParam->GetNonBendingCoor();
587 yEndAbsorber = trackParam->GetBendingCoor();
588 radiusEndAbsorber2 = xEndAbsorber * xEndAbsorber + yEndAbsorber * yEndAbsorber;
590 if (radiusEndAbsorber2 > rLimit*rLimit) {
596 xBP = xEndAbsorber - (pX / pZ) * (AliMUONConstants::ZAbsorberEnd() - zBP);
597 yBP = yEndAbsorber - (pY / pZ) * (AliMUONConstants::ZAbsorberEnd() - zBP);
599 // new parameters after Branson and energy loss corrections
600 // Float_t zSmear = zBP - gRandom->Gaus(0.,2.); // !!! possible smearing of Z vertex position
602 Float_t zSmear = zBP ;
604 pZ = pTotal * (zSmear-zVtx) / TMath::Sqrt((xBP-xVtx) * (xBP-xVtx) + (yBP-yVtx) * (yBP-yVtx) +( zSmear-zVtx) * (zSmear-zVtx) );
605 pX = pZ * (xBP - xVtx)/ (zSmear-zVtx);
606 pY = pZ * (yBP - yVtx) / (zSmear-zVtx);
607 trackParam->SetBendingSlope(pY/pZ);
608 trackParam->SetNonBendingSlope(pX/pZ);
611 pT = TMath::Sqrt(pX * pX + pY * pY);
612 theta = TMath::ATan2(pT, TMath::Abs(pZ));
613 pTotal = TotalMomentumEnergyLoss(thetaLimit, pTotal, theta);
615 trackParam->SetInverseBendingMomentum((sign / pTotal) *
617 trackParam->GetBendingSlope() * trackParam->GetBendingSlope() +
618 trackParam->GetNonBendingSlope() * trackParam->GetNonBendingSlope()) /
619 TMath::Sqrt(1.0 + trackParam->GetBendingSlope() * trackParam->GetBendingSlope()));
621 // vertex position at (0,0,0)
622 // should be taken from vertex measurement ???
624 trackParam->SetBendingCoor(xVtx);
625 trackParam->SetNonBendingCoor(yVtx);
626 trackParam->SetZ(zVtx);
630 //__________________________________________________________________________
631 Double_t AliMUONTrackExtrap::TotalMomentumEnergyLoss(Double_t thetaLimit, Double_t pTotal, Double_t theta)
633 /// Returns the total momentum corrected from energy loss in the front absorber
634 // One can use the macros MUONTestAbso.C and DrawTestAbso.C
635 // to test this correction.
636 // Momentum energy loss behaviour evaluated with the simulation of single muons (april 2002)
637 Double_t deltaP, pTotalCorrected;
639 // Parametrization to be redone according to change of absorber material ????
640 // See remark in function BransonCorrection !!!!
641 // The name is not so good, and there are many arguments !!!!
642 if (theta < thetaLimit ) {
644 deltaP = 2.5938 + 0.0570 * pTotal - 0.001151 * pTotal * pTotal;
646 deltaP = 3.0714 + 0.011767 *pTotal;
648 deltaP *= 0.75; // AZ
651 deltaP = 2.1207 + 0.05478 * pTotal - 0.00145079 * pTotal * pTotal;
653 deltaP = 2.6069 + 0.0051705 * pTotal;
657 pTotalCorrected = pTotal + deltaP / TMath::Cos(theta);
658 return pTotalCorrected;
661 //__________________________________________________________________________
662 void AliMUONTrackExtrap::FieldCorrection(AliMUONTrackParam *trackParam, Double_t zEnd)
664 /// Correction of the effect of the magnetic field in the absorber
665 // Assume a constant field along Z axis.
668 Double_t pYZ,pX,pY,pZ,pT;
669 Double_t pXNew,pYNew;
672 pYZ = TMath::Abs(1.0 / trackParam->GetInverseBendingMomentum());
673 c = TMath::Sign(1.0,trackParam->GetInverseBendingMomentum()); // particle charge
675 pZ = trackParam->Pz();
676 pX = trackParam->Px();
677 pY = trackParam->Py();
678 pT = TMath::Sqrt(pX*pX+pY*pY);
680 if (TMath::Abs(pZ) <= 0) return;
682 x[0] = x[2]*trackParam->GetNonBendingSlope();
683 x[1] = x[2]*trackParam->GetBendingSlope();
685 // Take magn. field value at position x.
686 if (fgkField) fgkField->Field(x,b);
688 cout<<"F-AliMUONTrackExtrap::FieldCorrection: fgkField = 0x0"<<endl;
693 // Transverse momentum rotation
694 // Parameterized with the study of DeltaPhi = phiReco - phiGen as a function of pZ.
695 Double_t phiShift = c*0.436*0.0003*bZ*zEnd/pZ;
696 // Rotate momentum around Z axis.
697 pXNew = pX*TMath::Cos(phiShift) - pY*TMath::Sin(phiShift);
698 pYNew = pX*TMath::Sin(phiShift) + pY*TMath::Cos(phiShift);
700 trackParam->SetBendingSlope(pYNew/pZ);
701 trackParam->SetNonBendingSlope(pXNew/pZ);
703 trackParam->SetInverseBendingMomentum(c/TMath::Sqrt(pYNew*pYNew+pZ*pZ));
707 //__________________________________________________________________________
708 void AliMUONTrackExtrap::ExtrapOneStepHelix(Double_t charge, Double_t step, Double_t *vect, Double_t *vout)
710 /// ******************************************************************
712 /// * Performs the tracking of one step in a magnetic field *
713 /// * The trajectory is assumed to be a helix in a constant field *
714 /// * taken at the mid point of the step. *
717 /// * STEP =arc length of the step asked *
718 /// * VECT =input vector (position,direction cos and momentum) *
719 /// * CHARGE= electric charge of the particle *
721 /// * VOUT = same as VECT after completion of the step *
723 /// * ==>Called by : <USER>, GUSWIM *
724 /// * Author m.hansroul ********* *
725 /// * modified s.egli, s.v.levonian *
726 /// * modified v.perevoztchikov
728 /// ******************************************************************
730 // modif: everything in double precision
732 Double_t xyz[3], h[4], hxp[3];
733 Double_t h2xy, hp, rho, tet;
734 Double_t sint, sintt, tsint, cos1t;
735 Double_t f1, f2, f3, f4, f5, f6;
740 const Int_t kipx = 3;
741 const Int_t kipy = 4;
742 const Int_t kipz = 5;
743 const Int_t kipp = 6;
745 const Double_t kec = 2.9979251e-4;
747 // ------------------------------------------------------------------
749 // units are kgauss,centimeters,gev/c
751 vout[kipp] = vect[kipp];
752 if (TMath::Abs(charge) < 0.00001) {
753 for (Int_t i = 0; i < 3; i++) {
754 vout[i] = vect[i] + step * vect[i+3];
755 vout[i+3] = vect[i+3];
759 xyz[0] = vect[kix] + 0.5 * step * vect[kipx];
760 xyz[1] = vect[kiy] + 0.5 * step * vect[kipy];
761 xyz[2] = vect[kiz] + 0.5 * step * vect[kipz];
763 //cmodif: call gufld (xyz, h) changed into:
766 h2xy = h[0]*h[0] + h[1]*h[1];
767 h[3] = h[2]*h[2]+ h2xy;
769 for (Int_t i = 0; i < 3; i++) {
770 vout[i] = vect[i] + step * vect[i+3];
771 vout[i+3] = vect[i+3];
775 if (h2xy < 1.e-12*h[3]) {
776 ExtrapOneStepHelix3(charge*h[2], step, vect, vout);
779 h[3] = TMath::Sqrt(h[3]);
785 hxp[0] = h[1]*vect[kipz] - h[2]*vect[kipy];
786 hxp[1] = h[2]*vect[kipx] - h[0]*vect[kipz];
787 hxp[2] = h[0]*vect[kipy] - h[1]*vect[kipx];
789 hp = h[0]*vect[kipx] + h[1]*vect[kipy] + h[2]*vect[kipz];
791 rho = -charge*h[3]/vect[kipp];
794 if (TMath::Abs(tet) > 0.15) {
795 sint = TMath::Sin(tet);
797 tsint = (tet-sint)/tet;
798 cos1t = 2.*(TMath::Sin(0.5*tet))*(TMath::Sin(0.5*tet))/tet;
801 sintt = (1. - tsint);
808 f3 = step * tsint * hp;
811 f6 = tet * cos1t * hp;
813 vout[kix] = vect[kix] + f1*vect[kipx] + f2*hxp[0] + f3*h[0];
814 vout[kiy] = vect[kiy] + f1*vect[kipy] + f2*hxp[1] + f3*h[1];
815 vout[kiz] = vect[kiz] + f1*vect[kipz] + f2*hxp[2] + f3*h[2];
817 vout[kipx] = vect[kipx] + f4*vect[kipx] + f5*hxp[0] + f6*h[0];
818 vout[kipy] = vect[kipy] + f4*vect[kipy] + f5*hxp[1] + f6*h[1];
819 vout[kipz] = vect[kipz] + f4*vect[kipz] + f5*hxp[2] + f6*h[2];
824 //__________________________________________________________________________
825 void AliMUONTrackExtrap::ExtrapOneStepHelix3(Double_t field, Double_t step, Double_t *vect, Double_t *vout)
827 /// ******************************************************************
829 /// * Tracking routine in a constant field oriented *
831 /// * Tracking is performed with a conventional *
832 /// * helix step method *
834 /// * ==>Called by : <USER>, GUSWIM *
835 /// * Authors R.Brun, M.Hansroul ********* *
836 /// * Rewritten V.Perevoztchikov
838 /// ******************************************************************
841 Double_t h4, hp, rho, tet;
842 Double_t sint, sintt, tsint, cos1t;
843 Double_t f1, f2, f3, f4, f5, f6;
848 const Int_t kipx = 3;
849 const Int_t kipy = 4;
850 const Int_t kipz = 5;
851 const Int_t kipp = 6;
853 const Double_t kec = 2.9979251e-4;
856 // ------------------------------------------------------------------
858 // units are kgauss,centimeters,gev/c
860 vout[kipp] = vect[kipp];
863 hxp[0] = - vect[kipy];
864 hxp[1] = + vect[kipx];
868 rho = -h4/vect[kipp];
870 if (TMath::Abs(tet) > 0.15) {
871 sint = TMath::Sin(tet);
873 tsint = (tet-sint)/tet;
874 cos1t = 2.* TMath::Sin(0.5*tet) * TMath::Sin(0.5*tet)/tet;
877 sintt = (1. - tsint);
884 f3 = step * tsint * hp;
887 f6 = tet * cos1t * hp;
889 vout[kix] = vect[kix] + f1*vect[kipx] + f2*hxp[0];
890 vout[kiy] = vect[kiy] + f1*vect[kipy] + f2*hxp[1];
891 vout[kiz] = vect[kiz] + f1*vect[kipz] + f3;
893 vout[kipx] = vect[kipx] + f4*vect[kipx] + f5*hxp[0];
894 vout[kipy] = vect[kipy] + f4*vect[kipy] + f5*hxp[1];
895 vout[kipz] = vect[kipz] + f4*vect[kipz] + f6;
899 //__________________________________________________________________________
900 void AliMUONTrackExtrap::ExtrapOneStepRungekutta(Double_t charge, Double_t step, Double_t* vect, Double_t* vout)
902 /// ******************************************************************
904 /// * Runge-Kutta method for tracking a particle through a magnetic *
905 /// * field. Uses Nystroem algorithm (See Handbook Nat. Bur. of *
906 /// * Standards, procedure 25.5.20) *
908 /// * Input parameters *
909 /// * CHARGE Particle charge *
910 /// * STEP Step size *
911 /// * VECT Initial co-ords,direction cosines,momentum *
912 /// * Output parameters *
913 /// * VOUT Output co-ords,direction cosines,momentum *
914 /// * User routine called *
915 /// * CALL GUFLD(X,F) *
917 /// * ==>Called by : <USER>, GUSWIM *
918 /// * Authors R.Brun, M.Hansroul ********* *
919 /// * V.Perevoztchikov (CUT STEP implementation) *
922 /// ******************************************************************
924 Double_t h2, h4, f[4];
925 Double_t xyzt[3], a, b, c, ph,ph2;
926 Double_t secxs[4],secys[4],seczs[4],hxp[3];
927 Double_t g1, g2, g3, g4, g5, g6, ang2, dxt, dyt, dzt;
928 Double_t est, at, bt, ct, cba;
929 Double_t f1, f2, f3, f4, rho, tet, hnorm, hp, rho1, sint, cost;
939 Double_t maxit = 1992;
940 Double_t maxcut = 11;
942 const Double_t kdlt = 1e-4;
943 const Double_t kdlt32 = kdlt/32.;
944 const Double_t kthird = 1./3.;
945 const Double_t khalf = 0.5;
946 const Double_t kec = 2.9979251e-4;
948 const Double_t kpisqua = 9.86960440109;
952 const Int_t kipx = 3;
953 const Int_t kipy = 4;
954 const Int_t kipz = 5;
957 // *. ------------------------------------------------------------------
959 // * this constant is for units cm,gev/c and kgauss
963 for(Int_t j = 0; j < 7; j++)
966 Double_t pinv = kec * charge / vect[6];
974 if (TMath::Abs(h) > TMath::Abs(rest)) h = rest;
975 //cmodif: call gufld(vout,f) changed into:
980 // * start of integration
993 secxs[0] = (b * f[2] - c * f[1]) * ph2;
994 secys[0] = (c * f[0] - a * f[2]) * ph2;
995 seczs[0] = (a * f[1] - b * f[0]) * ph2;
996 ang2 = (secxs[0]*secxs[0] + secys[0]*secys[0] + seczs[0]*seczs[0]);
997 if (ang2 > kpisqua) break;
999 dxt = h2 * a + h4 * secxs[0];
1000 dyt = h2 * b + h4 * secys[0];
1001 dzt = h2 * c + h4 * seczs[0];
1006 // * second intermediate point
1009 est = TMath::Abs(dxt) + TMath::Abs(dyt) + TMath::Abs(dzt);
1011 if (ncut++ > maxcut) break;
1020 //cmodif: call gufld(xyzt,f) changed into:
1027 secxs[1] = (bt * f[2] - ct * f[1]) * ph2;
1028 secys[1] = (ct * f[0] - at * f[2]) * ph2;
1029 seczs[1] = (at * f[1] - bt * f[0]) * ph2;
1033 secxs[2] = (bt * f[2] - ct * f[1]) * ph2;
1034 secys[2] = (ct * f[0] - at * f[2]) * ph2;
1035 seczs[2] = (at * f[1] - bt * f[0]) * ph2;
1036 dxt = h * (a + secxs[2]);
1037 dyt = h * (b + secys[2]);
1038 dzt = h * (c + seczs[2]);
1042 at = a + 2.*secxs[2];
1043 bt = b + 2.*secys[2];
1044 ct = c + 2.*seczs[2];
1046 est = TMath::Abs(dxt)+TMath::Abs(dyt)+TMath::Abs(dzt);
1047 if (est > 2.*TMath::Abs(h)) {
1048 if (ncut++ > maxcut) break;
1057 //cmodif: call gufld(xyzt,f) changed into:
1060 z = z + (c + (seczs[0] + seczs[1] + seczs[2]) * kthird) * h;
1061 y = y + (b + (secys[0] + secys[1] + secys[2]) * kthird) * h;
1062 x = x + (a + (secxs[0] + secxs[1] + secxs[2]) * kthird) * h;
1064 secxs[3] = (bt*f[2] - ct*f[1])* ph2;
1065 secys[3] = (ct*f[0] - at*f[2])* ph2;
1066 seczs[3] = (at*f[1] - bt*f[0])* ph2;
1067 a = a+(secxs[0]+secxs[3]+2. * (secxs[1]+secxs[2])) * kthird;
1068 b = b+(secys[0]+secys[3]+2. * (secys[1]+secys[2])) * kthird;
1069 c = c+(seczs[0]+seczs[3]+2. * (seczs[1]+seczs[2])) * kthird;
1071 est = TMath::Abs(secxs[0]+secxs[3] - (secxs[1]+secxs[2]))
1072 + TMath::Abs(secys[0]+secys[3] - (secys[1]+secys[2]))
1073 + TMath::Abs(seczs[0]+seczs[3] - (seczs[1]+seczs[2]));
1075 if (est > kdlt && TMath::Abs(h) > 1.e-4) {
1076 if (ncut++ > maxcut) break;
1082 // * if too many iterations, go to helix
1083 if (iter++ > maxit) break;
1088 cba = 1./ TMath::Sqrt(a*a + b*b + c*c);
1096 if (step < 0.) rest = -rest;
1097 if (rest < 1.e-5*TMath::Abs(step)) return;
1101 // angle too big, use helix
1106 f4 = TMath::Sqrt(f1*f1+f2*f2+f3*f3);
1115 hxp[0] = f2*vect[kipz] - f3*vect[kipy];
1116 hxp[1] = f3*vect[kipx] - f1*vect[kipz];
1117 hxp[2] = f1*vect[kipy] - f2*vect[kipx];
1119 hp = f1*vect[kipx] + f2*vect[kipy] + f3*vect[kipz];
1122 sint = TMath::Sin(tet);
1123 cost = 2.*TMath::Sin(khalf*tet)*TMath::Sin(khalf*tet);
1127 g3 = (tet-sint) * hp*rho1;
1132 vout[kix] = vect[kix] + g1*vect[kipx] + g2*hxp[0] + g3*f1;
1133 vout[kiy] = vect[kiy] + g1*vect[kipy] + g2*hxp[1] + g3*f2;
1134 vout[kiz] = vect[kiz] + g1*vect[kipz] + g2*hxp[2] + g3*f3;
1136 vout[kipx] = vect[kipx] + g4*vect[kipx] + g5*hxp[0] + g6*f1;
1137 vout[kipy] = vect[kipy] + g4*vect[kipy] + g5*hxp[1] + g6*f2;
1138 vout[kipz] = vect[kipz] + g4*vect[kipz] + g5*hxp[2] + g6*f3;
1142 //___________________________________________________________
1143 void AliMUONTrackExtrap::GetField(Double_t *Position, Double_t *Field)
1145 /// interface for arguments in double precision (Why ? ChF)
1148 x[0] = Position[0]; x[1] = Position[1]; x[2] = Position[2];
1150 if (fgkField) fgkField->Field(x,b);
1152 cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
1156 Field[0] = b[0]; Field[1] = b[1]; Field[2] = b[2];