minor updates
[u/mrichter/AliRoot.git] / MUON / AliMUONTrack.cxx
CommitLineData
a9e2aefa 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/*
17$Log$
956019b6 18Revision 1.4 2000/06/30 10:15:48 gosset
19Changes to EventReconstructor...:
20precision fit with multiple Coulomb scattering;
21extrapolation to vertex with Branson correction in absorber (JPC)
22
04b5ea16 23Revision 1.3 2000/06/25 13:23:28 hristov
24stdlib.h needed for non-Linux compilation
25
f6e92cf4 26Revision 1.2 2000/06/15 07:58:48 morsch
27Code from MUON-dev joined
28
a9e2aefa 29Revision 1.1.2.3 2000/06/12 10:11:34 morsch
30Dummy copy constructor and assignment operator added
31
32Revision 1.1.2.2 2000/06/09 12:58:05 gosset
33Removed comment beginnings in Log sections of .cxx files
34Suppressed most violations of coding rules
35
36Revision 1.1.2.1 2000/06/07 14:44:53 gosset
37Addition of files for track reconstruction in C++
38*/
39
40//__________________________________________________________________________
41//
42// Reconstructed track in ALICE dimuon spectrometer
43//__________________________________________________________________________
44
45#include "AliMUONTrack.h"
46
47#include <iostream.h>
48
49#include <TClonesArray.h>
04b5ea16 50#include <TMath.h>
51#include <TMatrix.h>
956019b6 52#include <TVirtualFitter.h>
a9e2aefa 53
54#include "AliMUONEventReconstructor.h"
55#include "AliMUONHitForRec.h"
56#include "AliMUONSegment.h"
57#include "AliMUONTrackHit.h"
58
f6e92cf4 59#include <stdlib.h>
60
04b5ea16 61// Functions to be minimized with Minuit
a9e2aefa 62void TrackChi2(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag);
04b5ea16 63void TrackChi2MCS(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag);
64
65Double_t MultipleScatteringAngle2(AliMUONTrackHit *TrackHit);
a9e2aefa 66
67ClassImp(AliMUONTrack) // Class implementation in ROOT context
68
956019b6 69TVirtualFitter* AliMUONTrack::fgFitter = NULL;
70
a9e2aefa 71 //__________________________________________________________________________
72AliMUONTrack::AliMUONTrack(AliMUONSegment* BegSegment, AliMUONSegment* EndSegment, AliMUONEventReconstructor* EventReconstructor)
73{
74 // Constructor from two Segment's
75 fEventReconstructor = EventReconstructor; // link back to EventReconstructor
76 // memory allocation for the TClonesArray of reconstructed TrackHit's
77 fTrackHitsPtr = new TClonesArray("AliMUONTrackHit", 10);
78 fNTrackHits = 0;
79 AddSegment(BegSegment); // add hits from BegSegment
80 AddSegment(EndSegment); // add hits from EndSegment
81 fTrackHitsPtr->Sort(); // sort TrackHits according to increasing Z
82 SetTrackParamAtVertex(); // set track parameters at vertex
956019b6 83 // set fit conditions
04b5ea16 84 fFitMCS = 0;
956019b6 85 fFitNParam = 3;
86 fFitStart = 1;
a9e2aefa 87 return;
88}
89
90 //__________________________________________________________________________
91AliMUONTrack::AliMUONTrack(AliMUONSegment* Segment, AliMUONHitForRec* HitForRec, AliMUONEventReconstructor* EventReconstructor)
92{
93 // Constructor from one Segment and one HitForRec
94 fEventReconstructor = EventReconstructor; // link back to EventReconstructor
95 // memory allocation for the TClonesArray of reconstructed TrackHit's
96 fTrackHitsPtr = new TClonesArray("AliMUONTrackHit", 10);
97 fNTrackHits = 0;
98 AddSegment(Segment); // add hits from Segment
99 AddHitForRec(HitForRec); // add HitForRec
100 fTrackHitsPtr->Sort(); // sort TrackHits according to increasing Z
101 SetTrackParamAtVertex(); // set track parameters at vertex
956019b6 102 // set fit conditions
04b5ea16 103 fFitMCS = 0;
956019b6 104 fFitNParam = 3;
105 fFitStart = 1;
a9e2aefa 106 return;
107}
108
956019b6 109 //__________________________________________________________________________
a9e2aefa 110AliMUONTrack::AliMUONTrack (const AliMUONTrack& MUONTrack)
111{
112// Dummy copy constructor
113}
114
956019b6 115 //__________________________________________________________________________
a9e2aefa 116AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& MUONTrack)
117{
118// Dummy assignment operator
119 return *this;
120}
121
04b5ea16 122 //__________________________________________________________________________
123void AliMUONTrack::SetFitMCS(Int_t FitMCS)
124{
956019b6 125 // Set multiple Coulomb scattering option for track fit "fFitMCS"
04b5ea16 126 // from "FitMCS" argument: 0 without, 1 with
956019b6 127 if ((FitMCS == 0) || (FitMCS == 1)) fFitMCS = FitMCS;
04b5ea16 128 // better implementation with enum(with, without) ????
956019b6 129 else {
130 cout << "ERROR in AliMUONTrack::SetFitMCS(FitMCS)" << endl;
131 cout << "FitMCS = " << FitMCS << " is neither 0 nor 1" << endl;
132 exit(0);
133 }
134 return;
135}
136
137 //__________________________________________________________________________
138void AliMUONTrack::SetFitNParam(Int_t FitNParam)
139{
140 // Set number of parameters for track fit "fFitNParam" from "FitNParam":
141 // 3 for momentum, 5 for momentum and position
142 if ((FitNParam == 3) || (FitNParam == 5)) fFitNParam = FitNParam;
143 else {
144 cout << "ERROR in AliMUONTrack::SetFitNParam(FitNParam)" << endl;
145 cout << "FitNParam = " << FitNParam << " is neither 3 nor 5" << endl;
146 exit(0);
147 }
148 return;
149}
150
151 //__________________________________________________________________________
152void AliMUONTrack::SetFitStart(Int_t FitStart)
153{
154 // Set multiple Coulomb scattering option for track fit "fFitStart"
155 // from "FitStart" argument: 0 without, 1 with
156 if ((FitStart == 0) || (FitStart == 1)) fFitStart = FitStart;
157 // better implementation with enum(vertex, firstHit) ????
158 else {
159 cout << "ERROR in AliMUONTrack::SetFitStart(FitStart)" << endl;
160 cout << "FitStart = " << FitStart << " is neither 0 nor 1" << endl;
161 exit(0);
162 }
04b5ea16 163 return;
164}
165
956019b6 166 //__________________________________________________________________________
a9e2aefa 167AliMUONTrackParam* AliMUONTrack::GetTrackParamAtFirstHit(void) {
168 // Get pointer to TrackParamAtFirstHit
169 return ((AliMUONTrackHit*) (fTrackHitsPtr->First()))->GetTrackParam();}
a9e2aefa 170
171 //__________________________________________________________________________
172void AliMUONTrack::RecursiveDump(void)
173{
174 // Recursive dump of AliMUONTrack, i.e. with dump of TrackHit's and HitForRec's
175 AliMUONTrackHit *trackHit;
176 AliMUONHitForRec *hitForRec;
177 cout << "Recursive dump of Track: " << this << endl;
178 // Track
179 this->Dump();
180 for (Int_t trackHitIndex = 0; trackHitIndex < fNTrackHits; trackHitIndex++) {
181 trackHit = (AliMUONTrackHit*) ((*fTrackHitsPtr)[trackHitIndex]);
182 // TrackHit
183 cout << "TrackHit: " << trackHit << " (index: " << trackHitIndex << ")" << endl;
184 trackHit->Dump();
185 hitForRec = trackHit->GetHitForRecPtr();
186 // HitForRec
187 cout << "HitForRec: " << hitForRec << endl;
188 hitForRec->Dump();
189 }
190 return;
191}
192
193 //__________________________________________________________________________
956019b6 194void AliMUONTrack::Fit()
a9e2aefa 195{
196 // Fit the current track ("this"),
956019b6 197 // with or without multiple Coulomb scattering according to "fFitMCS",
198 // with the number of parameters given by "fFitNParam"
199 // (3 if one keeps X and Y fixed in "TrackParam", 5 if one lets them vary),
200 // starting, according to "fFitStart",
201 // with track parameters at vertex or at the first TrackHit.
202 // "fFitMCS", "fFitNParam" and "fFitStart" have to be set before
203 // by calling the corresponding Set methods.
a9e2aefa 204 Double_t arg[1], benC, errorParam, invBenP, lower, nonBenC, upper, x, y;
956019b6 205 char parName[50];
206 AliMUONTrackParam *trackParam;
207 // Check if Minuit is initialized...
208 fgFitter = TVirtualFitter::Fitter(this); // add 3 or 5 for the maximum number of parameters ???
209 fgFitter->Clear(); // necessary ???? probably yes
210 // how to reset the printout number at every fit ????
211 // is there any risk to leave it like that ????
a9e2aefa 212 // how to go faster ???? choice of Minuit parameters like EDM ????
04b5ea16 213 // choice of function to be minimized according to fFitMCS
956019b6 214 if (fFitMCS == 0) fgFitter->SetFCN(TrackChi2);
215 else fgFitter->SetFCN(TrackChi2MCS);
216 arg[0] = 1;
217 fgFitter->ExecuteCommand("SET PRINT", arg, 1); // More printing !!!!
218 // Parameters according to "fFitStart"
219 // (should be a function to be used at every place where needed ????)
220 if (fFitStart == 0) trackParam = &fTrackParamAtVertex;
221 else trackParam = this->GetTrackParamAtFirstHit();
222 // set first 3 Minuit parameters
04b5ea16 223 // could be tried with no limits for the search (min=max=0) ????
956019b6 224 fgFitter->SetParameter(0, "InvBenP",
225 trackParam->GetInverseBendingMomentum(),
226 0.003, -0.4, 0.4);
227 fgFitter->SetParameter(1, "BenS",
228 trackParam->GetBendingSlope(),
229 0.001, -0.5, 0.5);
230 fgFitter->SetParameter(2, "NonBenS",
231 trackParam->GetNonBendingSlope(),
232 0.001, -0.5, 0.5);
233 if (fFitNParam == 5) {
234 // set last 2 Minuit parameters (no limits for the search: min=max=0)
235 fgFitter->SetParameter(3, "X",
236 trackParam->GetNonBendingCoor(),
237 0.03, 0.0, 0.0);
238 fgFitter->SetParameter(4, "Y",
239 trackParam->GetBendingCoor(),
240 0.10, 0.0, 0.0);
a9e2aefa 241 }
242 // search without gradient calculation in the function
956019b6 243 fgFitter->ExecuteCommand("SET NOGRADIENT", arg, 0);
a9e2aefa 244 // minimization
956019b6 245 fgFitter->ExecuteCommand("MINIMIZE", arg, 0);
a9e2aefa 246 // exit from Minuit
956019b6 247 fgFitter->ExecuteCommand("EXIT", arg, 0); // necessary ????
248 // get results into "invBenP", "benC", "nonBenC" ("x", "y")
249 fgFitter->GetParameter(0, parName, invBenP, errorParam, lower, upper);
250 fgFitter->GetParameter(1, parName, benC, errorParam, lower, upper);
251 fgFitter->GetParameter(2, parName, nonBenC, errorParam, lower, upper);
252 if (fFitNParam == 5) {
253 fgFitter->GetParameter(3, parName, x, errorParam, lower, upper);
254 fgFitter->GetParameter(4, parName, y, errorParam, lower, upper);
a9e2aefa 255 }
256 // result of the fit into track parameters
956019b6 257 trackParam->SetInverseBendingMomentum(invBenP);
258 trackParam->SetBendingSlope(benC);
259 trackParam->SetNonBendingSlope(nonBenC);
260 if (fFitNParam == 5) {
261 trackParam->SetNonBendingCoor(x);
262 trackParam->SetBendingCoor(y);
a9e2aefa 263 }
a9e2aefa 264}
265
266 //__________________________________________________________________________
267void AliMUONTrack::AddSegment(AliMUONSegment* Segment)
268{
269 // Add Segment
270 AddHitForRec(Segment->GetHitForRec1()); // 1st hit
271 AddHitForRec(Segment->GetHitForRec2()); // 2nd hit
272}
273
274 //__________________________________________________________________________
275void AliMUONTrack::AddHitForRec(AliMUONHitForRec* HitForRec)
276{
277 // Add HitForRec
278 new ((*fTrackHitsPtr)[fNTrackHits]) AliMUONTrackHit(HitForRec);
279 fNTrackHits++;
280}
281
282 //__________________________________________________________________________
283void AliMUONTrack::SetTrackParamAtHit(Int_t indexHit, AliMUONTrackParam *TrackParam)
284{
285 // Set track parameters at TrackHit with index "indexHit"
286 // from the track parameters pointed to by "TrackParam".
287 AliMUONTrackHit* trackHit = (AliMUONTrackHit*) ((*fTrackHitsPtr)[indexHit]);
288 trackHit->SetTrackParam(TrackParam);
289}
290
291 //__________________________________________________________________________
292void AliMUONTrack::SetTrackParamAtVertex()
293{
294 // Set track parameters at vertex.
295 // TrackHit's are assumed to be only in stations(1..) 4 and 5,
296 // and sorted according to increasing Z..
297 // Parameters are calculated from information in HitForRec's
298 // of first and last TrackHit's.
299 AliMUONTrackParam *trackParam =
300 &fTrackParamAtVertex; // pointer to track parameters
301 // Pointer to HitForRec of first TrackHit
302 AliMUONHitForRec *firstHit =
303 ((AliMUONTrackHit*) (fTrackHitsPtr->First()))->GetHitForRecPtr();
304 // Pointer to HitForRec of last TrackHit
305 AliMUONHitForRec *lastHit =
306 ((AliMUONTrackHit*) (fTrackHitsPtr->Last()))->GetHitForRecPtr();
307 // Z difference between first and last hits
308 Double_t deltaZ = firstHit->GetZ() - lastHit->GetZ();
309 // bending slope in stations(1..) 4 and 5
310 Double_t bendingSlope =
311 (firstHit->GetBendingCoor() - lastHit->GetBendingCoor()) / deltaZ;
312 trackParam->SetBendingSlope(bendingSlope);
313 // impact parameter
314 Double_t impactParam =
315 firstHit->GetBendingCoor() - bendingSlope * firstHit->GetZ(); // same if from firstHit and lastHit ????
316 // signed bending momentum
317 Double_t signedBendingMomentum =
318 fEventReconstructor->GetBendingMomentumFromImpactParam(impactParam);
319 trackParam->SetInverseBendingMomentum(1.0 / signedBendingMomentum);
320 // bending slope at vertex
321 trackParam->
322 SetBendingSlope(bendingSlope +
323 impactParam / fEventReconstructor->GetSimpleBPosition());
324 // non bending slope
325 Double_t nonBendingSlope =
326 (firstHit->GetNonBendingCoor() - lastHit->GetNonBendingCoor()) / deltaZ;
327 trackParam->SetNonBendingSlope(nonBendingSlope);
328 // vertex coordinates at (0,0,0)
329 trackParam->SetZ(0.0);
330 trackParam->SetBendingCoor(0.0);
331 trackParam->SetNonBendingCoor(0.0);
332}
333
334 //__________________________________________________________________________
335void TrackChi2(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag)
336{
337 // Return the "Chi2" to be minimized with Minuit for track fitting,
338 // with "NParam" parameters
339 // and their current values in array pointed to by "Param".
340 // Assumes that the track hits are sorted according to increasing Z.
341 // Track parameters at each TrackHit are updated accordingly.
04b5ea16 342 // Multiple Coulomb scattering is not taken into account
956019b6 343 AliMUONTrack *trackBeingFitted;
a9e2aefa 344 AliMUONTrackHit* hit;
345 AliMUONTrackParam param1;
346 Int_t hitNumber;
347 Double_t zHit;
348 Chi2 = 0.0; // initialize Chi2
349 // copy of track parameters to be fitted
956019b6 350 trackBeingFitted = (AliMUONTrack*) AliMUONTrack::Fitter()->GetObjectFit();
351 if (trackBeingFitted->GetFitStart() == 0)
352 param1 = *(trackBeingFitted->GetTrackParamAtVertex());
353 else param1 = *(trackBeingFitted->GetTrackParamAtFirstHit());
a9e2aefa 354 // Minuit parameters to be fitted into this copy
355 param1.SetInverseBendingMomentum(Param[0]);
356 param1.SetBendingSlope(Param[1]);
357 param1.SetNonBendingSlope(Param[2]);
358 if (NParam == 5) {
359 param1.SetNonBendingCoor(Param[3]);
360 param1.SetBendingCoor(Param[4]);
361 }
362 // Follow track through all planes of track hits
363 for (hitNumber = 0; hitNumber < trackBeingFitted->GetNTrackHits(); hitNumber++) {
364 hit = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber];
365 zHit = hit->GetHitForRecPtr()->GetZ();
366 // do something special if 2 hits with same Z ????
367 // security against infinite loop ????
368 (&param1)->ExtrapToZ(zHit); // extrapolation
369 hit->SetTrackParam(&param1);
370 // Increment Chi2
371 // done hit per hit, with hit resolution,
372 // and not with point and angle like in "reco_muon.F" !!!!
373 // Needs to add multiple scattering contribution ????
374 Double_t dX =
375 hit->GetHitForRecPtr()->GetNonBendingCoor() - (&param1)->GetNonBendingCoor();
376 Double_t dY =
377 hit->GetHitForRecPtr()->GetBendingCoor() - (&param1)->GetBendingCoor();
378 Chi2 =
379 Chi2 +
380 dX * dX / hit->GetHitForRecPtr()->GetNonBendingReso2() +
381 dY * dY / hit->GetHitForRecPtr()->GetBendingReso2();
382 }
383}
04b5ea16 384
385 //__________________________________________________________________________
386void TrackChi2MCS(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag)
387{
388 // Return the "Chi2" to be minimized with Minuit for track fitting,
389 // with "NParam" parameters
390 // and their current values in array pointed to by "Param".
391 // Assumes that the track hits are sorted according to increasing Z.
392 // Track parameters at each TrackHit are updated accordingly.
393 // Multiple Coulomb scattering is taken into account with covariance matrix.
956019b6 394 AliMUONTrack *trackBeingFitted;
04b5ea16 395 AliMUONTrackParam param1;
396 Chi2 = 0.0; // initialize Chi2
397 // copy of track parameters to be fitted
956019b6 398 trackBeingFitted = (AliMUONTrack*) AliMUONTrack::Fitter()->GetObjectFit();
399 if (trackBeingFitted->GetFitStart() == 0)
400 param1 = *(trackBeingFitted->GetTrackParamAtVertex());
401 else param1 = *(trackBeingFitted->GetTrackParamAtFirstHit());
04b5ea16 402 // Minuit parameters to be fitted into this copy
403 param1.SetInverseBendingMomentum(Param[0]);
404 param1.SetBendingSlope(Param[1]);
405 param1.SetNonBendingSlope(Param[2]);
406 if (NParam == 5) {
407 param1.SetNonBendingCoor(Param[3]);
408 param1.SetBendingCoor(Param[4]);
409 }
410
956019b6 411 AliMUONTrackHit *hit;
412 Bool_t goodDeterminant;
04b5ea16 413 Int_t hitNumber, hitNumber1, hitNumber2, hitNumber3;
414 Double_t zHit[10], paramBendingCoor[10], paramNonBendingCoor[10], ap[10];
415 Double_t hitBendingCoor[10], hitNonBendingCoor[10];
416 Double_t hitBendingReso2[10], hitNonBendingReso2[10];
956019b6 417 // dimension 10 in parameter ??? related to AliMUONConstants::NTrackingCh() !!!!
04b5ea16 418 Int_t numberOfHit = TMath::Min(trackBeingFitted->GetNTrackHits(), 10);
419 TMatrix *covBending = new TMatrix(numberOfHit, numberOfHit);
420 TMatrix *covNonBending = new TMatrix(numberOfHit, numberOfHit);
421
422 // Predicted coordinates and multiple scattering angles are first calculated
423 for (hitNumber = 0; hitNumber < numberOfHit; hitNumber++) {
424 hit = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber];
425 zHit[hitNumber] = hit->GetHitForRecPtr()->GetZ();
426 // do something special if 2 hits with same Z ????
427 // security against infinite loop ????
428 (&param1)->ExtrapToZ(zHit[hitNumber]); // extrapolation
429 hit->SetTrackParam(&param1);
956019b6 430 paramBendingCoor[hitNumber] = (&param1)->GetBendingCoor();
431 paramNonBendingCoor[hitNumber] = (&param1)->GetNonBendingCoor();
432 hitBendingCoor[hitNumber] = hit->GetHitForRecPtr()->GetBendingCoor();
433 hitNonBendingCoor[hitNumber] = hit->GetHitForRecPtr()->GetNonBendingCoor();
434 hitBendingReso2[hitNumber] = hit->GetHitForRecPtr()->GetBendingReso2();
435 hitNonBendingReso2[hitNumber] = hit->GetHitForRecPtr()->GetNonBendingReso2();
04b5ea16 436 ap[hitNumber] = MultipleScatteringAngle2(hit); // multiple scatt. angle ^2
437 }
438
439 // Calculates the covariance matrix
956019b6 440 // One chamber is taken into account between successive hits.
441 // "ap" should be changed for taking into account the eventual missing hits
442 // by defining an "equivalent" chamber thickness !!!!
04b5ea16 443 for (hitNumber1 = 0; hitNumber1 < numberOfHit; hitNumber1++) {
444 for (hitNumber2 = hitNumber1; hitNumber2 < numberOfHit; hitNumber2++) {
956019b6 445 // initialization to 0 (diagonal plus upper triangular part)
446 (*covBending)(hitNumber2, hitNumber1) = 0.0;
447 // contribution from multiple scattering in bending plane:
448 // loop over upstream hits
449 for (hitNumber3 = 0; hitNumber3 < hitNumber1; hitNumber3++) {
04b5ea16 450 (*covBending)(hitNumber2, hitNumber1) =
451 (*covBending)(hitNumber2, hitNumber1) +
452 ((zHit[hitNumber1] - zHit[hitNumber3]) *
453 (zHit[hitNumber2] - zHit[hitNumber3]) * ap[hitNumber3]);
956019b6 454 }
455 // equal contribution from multiple scattering in non bending plane
04b5ea16 456 (*covNonBending)(hitNumber2, hitNumber1) =
457 (*covBending)(hitNumber2, hitNumber1);
956019b6 458 if (hitNumber1 == hitNumber2) {
459 // Diagonal elements: add contribution from position measurements
460 // in bending plane
461 (*covBending)(hitNumber2, hitNumber1) =
462 (*covBending)(hitNumber2, hitNumber1) + hitBendingReso2[hitNumber1];
463 // and in non bending plane
04b5ea16 464 (*covNonBending)(hitNumber2, hitNumber1) =
956019b6 465 (*covNonBending)(hitNumber2, hitNumber1) + hitNonBendingReso2[hitNumber1];
466 }
467 else {
468 // Non diagonal elements: symmetrization
469 // for bending plane
470 (*covBending)(hitNumber1, hitNumber2) =
471 (*covBending)(hitNumber2, hitNumber1);
472 // and non bending plane
473 (*covNonBending)(hitNumber1, hitNumber2) =
474 (*covNonBending)(hitNumber2, hitNumber1);
475 }
476 } // for (hitNumber2 = hitNumber1;...
477 } // for (hitNumber1 = 0;...
04b5ea16 478
479 // Inverts covariance matrix
956019b6 480 goodDeterminant = kTRUE;
481 // check whether the Invert method returns flag if matrix cannot be inverted,
482 // and do not calculate the Determinant in that case !!!!
04b5ea16 483 if (covBending->Determinant() != 0) {
484 covBending->Invert();
485 } else {
956019b6 486 goodDeterminant = kFALSE;
04b5ea16 487 cout << "Warning in ChiMCS Determinant Bending=0: " << endl;
488 }
956019b6 489 if (covNonBending->Determinant() != 0) {
04b5ea16 490 covNonBending->Invert();
491 } else {
956019b6 492 goodDeterminant = kFALSE;
04b5ea16 493 cout << "Warning in ChiMCS Determinant non Bending=0: " << endl;
494 }
956019b6 495
496 // It would be worth trying to calculate the inverse of the covariance matrix
497 // only once per fit, since it cannot change much in principle,
498 // and it would save a lot of computing time !!!!
04b5ea16 499
500 // Calculates Chi2
956019b6 501 if (goodDeterminant) { // with Multiple Scattering if inversion correct
04b5ea16 502 for (hitNumber1=0; hitNumber1 < numberOfHit ; hitNumber1++){
503 for (hitNumber2=0; hitNumber2 < numberOfHit; hitNumber2++){
504 Chi2 = Chi2 +
505 ((*covBending)(hitNumber2, hitNumber1) *
506 (hitBendingCoor[hitNumber1] - paramBendingCoor[hitNumber1]) *
507 (hitBendingCoor[hitNumber2] - paramBendingCoor[hitNumber2]));
508 Chi2 = Chi2 +
509 ((*covNonBending)(hitNumber2, hitNumber1) *
510 (hitNonBendingCoor[hitNumber1] - paramNonBendingCoor[hitNumber1]) *
511 (hitNonBendingCoor[hitNumber2] - paramNonBendingCoor[hitNumber2]));
512 }
513 }
514 } else { // without Multiple Scattering if inversion impossible
515 for (hitNumber1=0; hitNumber1 < numberOfHit ; hitNumber1++) {
516 Chi2 = Chi2 +
517 ((hitBendingCoor[hitNumber1] - paramBendingCoor[hitNumber1]) *
518 (hitBendingCoor[hitNumber1] - paramBendingCoor[hitNumber1]) /
519 hitBendingReso2[hitNumber1]);
520 Chi2 = Chi2 +
521 ((hitNonBendingCoor[hitNumber1] - paramNonBendingCoor[hitNumber1]) *
522 (hitNonBendingCoor[hitNumber1] - paramNonBendingCoor[hitNumber1]) /
523 hitNonBendingReso2[hitNumber1]);
524 }
525 }
526
527 delete covBending;
528 delete covNonBending;
529}
530
531Double_t MultipleScatteringAngle2(AliMUONTrackHit *TrackHit)
532{
533 // Returns square of multiple Coulomb scattering angle
534 // at TrackHit pointed to by "TrackHit"
535 Double_t slopeBending, slopeNonBending, radiationLength, inverseBendingMomentum2, inverseTotalMomentum2;
536 Double_t varMultipleScatteringAngle;
956019b6 537 AliMUONTrack *trackBeingFitted = (AliMUONTrack*) AliMUONTrack::Fitter()->GetObjectFit();
04b5ea16 538 AliMUONTrackParam *param = TrackHit->GetTrackParam();
956019b6 539 // Better implementation in AliMUONTrack class ????
04b5ea16 540 slopeBending = param->GetBendingSlope();
541 slopeNonBending = param->GetNonBendingSlope();
542 // thickness in radiation length for the current track,
543 // taking local angle into account
544 radiationLength =
545 trackBeingFitted->GetEventReconstructor()->GetChamberThicknessInX0() *
546 TMath::Sqrt(1.0 +
547 slopeBending * slopeBending + slopeNonBending * slopeNonBending);
548 inverseBendingMomentum2 =
549 param->GetInverseBendingMomentum() * param->GetInverseBendingMomentum();
550 inverseTotalMomentum2 =
956019b6 551 inverseBendingMomentum2 * (1.0 + slopeBending * slopeBending) /
04b5ea16 552 (1.0 + slopeBending *slopeBending + slopeNonBending * slopeNonBending);
553 varMultipleScatteringAngle = 0.0136 * (1.0 + 0.038 * TMath::Log(radiationLength));
956019b6 554 // The velocity is assumed to be 1 !!!!
04b5ea16 555 varMultipleScatteringAngle = inverseTotalMomentum2 * radiationLength *
556 varMultipleScatteringAngle * varMultipleScatteringAngle;
557 return varMultipleScatteringAngle;
558}