]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrack.cxx
Take into account new class AliAODTracklets.
[u/mrichter/AliRoot.git] / MUON / AliMUONTrack.cxx
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 // Reconstructed track
21 // in
22 // ALICE
23 // dimuon
24 // spectrometer
25 //
26 ///////////////////////////////////////////////////
27
28 #include "AliMUONTrack.h"
29
30 #include "AliMUONTrackParam.h" 
31 #include "AliMUONHitForRec.h" 
32 #include "AliMUONObjectPair.h" 
33 #include "AliMUONConstants.h"
34 #include "AliMUONTrackExtrap.h" 
35
36 #include "AliLog.h"
37
38 #include <TMath.h>
39 #include <TMatrixD.h>
40
41 #include <Riostream.h>
42
43 /// \cond CLASSIMP
44 ClassImp(AliMUONTrack) // Class implementation in ROOT context
45 /// \endcond
46
47 //__________________________________________________________________________
48 AliMUONTrack::AliMUONTrack()
49   : TObject(),
50     fTrackParamAtVertex(),
51     fTrackParamAtHit(0x0),
52     fHitForRecAtHit(0x0),
53     fNTrackHits(0),
54     fFitWithVertex(kFALSE),
55     fVertex(0x0),
56     fFitWithMCS(kFALSE),
57     fHitWeightsNonBending(0x0),
58     fHitWeightsBending(0x0),
59     fGlobalChi2(-1.),
60     fImproved(kFALSE),
61     fMatchTrigger(-1),
62     floTrgNum(-1),
63     fChi2MatchTrigger(0.),
64     fTrackID(0),
65     fHitsPatternInTrigCh(0),
66     fLocalTrigger(234)
67 {
68   /// Default constructor
69 }
70
71   //__________________________________________________________________________
72 AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment)
73   : TObject(),
74     fTrackParamAtVertex(),
75     fTrackParamAtHit(0x0),
76     fHitForRecAtHit(0x0),
77     fNTrackHits(0),
78     fFitWithVertex(kFALSE),
79     fVertex(0x0),
80     fFitWithMCS(kFALSE),
81     fHitWeightsNonBending(0x0),
82     fHitWeightsBending(0x0),
83     fGlobalChi2(0.),
84     fImproved(kFALSE),
85     fMatchTrigger(-1),
86     floTrgNum(-1),    
87     fChi2MatchTrigger(0.),
88     fTrackID(0),
89     fHitsPatternInTrigCh(0),
90     fLocalTrigger(234)
91 {
92   /// Constructor from thw hitForRec's
93
94   fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);
95   fTrackParamAtHit->SetOwner(kTRUE);
96   fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10);
97   fHitForRecAtHit->SetOwner(kTRUE);
98   
99   if (!segment) return; //AZ
100   
101   // Pointers to hits from the segment
102   AliMUONHitForRec* hit1 = (AliMUONHitForRec*) segment->First();
103   AliMUONHitForRec* hit2 = (AliMUONHitForRec*) segment->Second();
104   
105   // check sorting in -Z (spectro z<0)
106   if (hit1->GetZ() < hit2->GetZ()) {
107     hit1 = hit2;
108     hit2 = (AliMUONHitForRec*) segment->First();
109   }
110   
111   // order the hits into the track according to the station the segment belong to
112   //(the hit first attached is the one from which we will start the tracking procedure)
113   if (hit1->GetChamberNumber() == 8) {
114     AddTrackParamAtHit(0,hit1);
115     AddTrackParamAtHit(0,hit2);
116   } else {
117     AddTrackParamAtHit(0,hit2);
118     AddTrackParamAtHit(0,hit1);
119   }
120   
121   AliMUONTrackParam* trackParamAtFirstHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
122   AliMUONHitForRec* firstHit = trackParamAtFirstHit->GetHitForRecPtr();
123   AliMUONTrackParam* trackParamAtLastHit = (AliMUONTrackParam*) fTrackParamAtHit->Last();
124   AliMUONHitForRec* lastHit = trackParamAtLastHit->GetHitForRecPtr();
125   
126   
127   // Compute track parameters
128   Double_t dZ = firstHit->GetZ() - lastHit->GetZ();
129   // Non bending plane
130   Double_t nonBendingCoor1 = firstHit->GetNonBendingCoor();
131   Double_t nonBendingCoor2 = lastHit->GetNonBendingCoor();
132   Double_t nonBendingSlope = (nonBendingCoor1 - nonBendingCoor2) / dZ;
133   // Bending plane
134   Double_t bendingCoor1 = firstHit->GetBendingCoor();
135   Double_t bendingCoor2 = lastHit->GetBendingCoor();
136   Double_t bendingSlope = (bendingCoor1 - bendingCoor2) / dZ;
137   // Inverse bending momentum
138   Double_t bendingImpact = bendingCoor1 - firstHit->GetZ() * bendingSlope;
139   Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
140   
141   
142   // Set track parameters at first hit
143   trackParamAtFirstHit->SetNonBendingCoor(nonBendingCoor1);
144   trackParamAtFirstHit->SetNonBendingSlope(nonBendingSlope);
145   trackParamAtFirstHit->SetBendingCoor(bendingCoor1);
146   trackParamAtFirstHit->SetBendingSlope(bendingSlope);
147   trackParamAtFirstHit->SetInverseBendingMomentum(inverseBendingMomentum);
148   
149   
150   // Set track parameters at last hit
151   trackParamAtLastHit->SetNonBendingCoor(nonBendingCoor2);
152   trackParamAtLastHit->SetNonBendingSlope(nonBendingSlope);
153   trackParamAtLastHit->SetBendingCoor(bendingCoor2);
154   trackParamAtLastHit->SetBendingSlope(bendingSlope);
155   trackParamAtLastHit->SetInverseBendingMomentum(inverseBendingMomentum);
156   
157   
158   // Compute and set track parameters covariances at first hit
159   TMatrixD paramCov1(5,5);
160   paramCov1.Zero();
161   // Non bending plane
162   paramCov1(0,0) = firstHit->GetNonBendingReso2();
163   paramCov1(0,1) = firstHit->GetNonBendingReso2() / dZ;
164   paramCov1(1,0) = paramCov1(0,1);
165   paramCov1(1,1) = ( firstHit->GetNonBendingReso2() + lastHit->GetNonBendingReso2() ) / dZ / dZ;
166   // Bending plane
167   paramCov1(2,2) = firstHit->GetBendingReso2();
168   paramCov1(2,3) = firstHit->GetBendingReso2() / dZ;
169   paramCov1(3,2) = paramCov1(2,3);
170   paramCov1(3,3) = ( firstHit->GetBendingReso2() + lastHit->GetBendingReso2() ) / dZ / dZ;
171   // Inverse bending momentum (50% error)
172   paramCov1(4,4) = 0.5*inverseBendingMomentum * 0.5*inverseBendingMomentum;
173   // Set covariances
174   trackParamAtFirstHit->SetCovariances(paramCov1);
175   
176   
177   // Compute and set track parameters covariances at last hit (as if the first hit did not exist)
178   TMatrixD paramCov2(5,5);
179   paramCov2.Zero();
180   // Non bending plane
181   paramCov2(0,0) = paramCov1(0,0);
182   paramCov2(1,1) = 100.*paramCov1(1,1);
183   // Bending plane
184   paramCov2(2,2) = paramCov1(2,2);
185   paramCov2(3,3) = 100.*paramCov1(3,3);
186   // Inverse bending momentum
187   paramCov2(4,4) = paramCov1(4,4);
188   // Set covariances
189   trackParamAtLastHit->SetCovariances(paramCov2);
190   
191   
192   // Flag first hit as being removable
193   trackParamAtFirstHit->SetRemovable(kTRUE);
194   
195   // Flag last hit as being removable
196   trackParamAtLastHit->SetRemovable(kTRUE);
197   
198 }
199
200   //__________________________________________________________________________
201 AliMUONTrack::AliMUONTrack (const AliMUONTrack& track)
202   : TObject(track),
203     fTrackParamAtVertex(track.fTrackParamAtVertex),
204     fTrackParamAtHit(0x0),
205     fHitForRecAtHit(0x0),
206     fNTrackHits(track.fNTrackHits),
207     fFitWithVertex(track.fFitWithVertex),
208     fVertex(0x0),
209     fFitWithMCS(track.fFitWithMCS),
210     fHitWeightsNonBending(0x0),
211     fHitWeightsBending(0x0),
212     fGlobalChi2(track.fGlobalChi2),
213     fImproved(track.fImproved),
214     fMatchTrigger(track.fMatchTrigger),
215     floTrgNum(track.floTrgNum),    
216     fChi2MatchTrigger(track.fChi2MatchTrigger),
217     fTrackID(track.fTrackID),
218     fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
219     fLocalTrigger(track.fLocalTrigger)
220 {
221   ///copy constructor
222   Int_t maxIndex = 0;
223   
224   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
225   if (track.fTrackParamAtHit) {
226     maxIndex = (track.fTrackParamAtHit)->GetEntriesFast();
227     fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",maxIndex);
228     for (Int_t index = 0; index < maxIndex; index++) {
229       new ((*fTrackParamAtHit)[index]) AliMUONTrackParam(*(AliMUONTrackParam*)track.fTrackParamAtHit->At(index));
230     }
231   }
232   
233   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
234   if (track.fHitForRecAtHit) {
235     maxIndex = (track.fHitForRecAtHit)->GetEntriesFast();
236     fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",maxIndex);
237     for (Int_t index = 0; index < maxIndex; index++) {
238       new ((*fHitForRecAtHit)[index]) AliMUONHitForRec(*(AliMUONHitForRec*)track.fHitForRecAtHit->At(index));
239     }
240   }
241   
242   // copy vertex used during the tracking procedure if any
243   if (track.fVertex) fVertex = new AliMUONHitForRec(*(track.fVertex));
244   
245   // copy hit weights matrices if any
246   if (track.fHitWeightsNonBending) fHitWeightsNonBending = new TMatrixD(*(track.fHitWeightsNonBending));
247   if (track.fHitWeightsBending) fHitWeightsBending = new TMatrixD(*(track.fHitWeightsBending));
248   
249 }
250
251   //__________________________________________________________________________
252 AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& track)
253 {
254   /// Asignment operator
255   // check assignement to self
256   if (this == &track)
257     return *this;
258
259   // base class assignement
260   TObject::operator=(track);
261
262   fTrackParamAtVertex = track.fTrackParamAtVertex;
263
264   Int_t maxIndex = 0;
265   
266   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
267   if (track.fTrackParamAtHit) {
268     if (fTrackParamAtHit) fTrackParamAtHit->Clear();
269     else fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);
270     maxIndex = (track.fTrackParamAtHit)->GetEntriesFast();
271     for (Int_t index = 0; index < maxIndex; index++) {
272       new ((*fTrackParamAtHit)[fTrackParamAtHit->GetEntriesFast()])
273         AliMUONTrackParam(*(AliMUONTrackParam*)(track.fTrackParamAtHit)->At(index));
274     }
275   } else if (fTrackParamAtHit) {
276     delete fTrackParamAtHit;
277     fTrackParamAtHit = 0x0;
278   }
279
280   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
281   if (track.fHitForRecAtHit) {
282     if (fHitForRecAtHit) fHitForRecAtHit->Clear();
283     else fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10);
284     maxIndex = (track.fHitForRecAtHit)->GetEntriesFast();
285     for (Int_t index = 0; index < maxIndex; index++) {
286       new ((*fHitForRecAtHit)[fHitForRecAtHit->GetEntriesFast()])
287         AliMUONHitForRec(*(AliMUONHitForRec*)(track.fHitForRecAtHit)->At(index));
288     }
289   } else if (fHitForRecAtHit) {
290     delete fHitForRecAtHit;
291     fHitForRecAtHit = 0x0;
292   }
293   
294   // copy vertex used during the tracking procedure if any.
295   if (track.fVertex) {
296     if (fVertex) *fVertex = *(track.fVertex);
297     else fVertex = new AliMUONHitForRec(*(track.fVertex));
298   } else if (fVertex) {
299     delete fVertex;
300     fVertex = 0x0;
301   }
302   
303   // copy hit weights matrix if any
304   if (track.fHitWeightsNonBending) {
305     if (fHitWeightsNonBending) {
306       fHitWeightsNonBending->ResizeTo(*(track.fHitWeightsNonBending));
307       *fHitWeightsNonBending = *(track.fHitWeightsNonBending);
308     } else fHitWeightsNonBending = new TMatrixD(*(track.fHitWeightsNonBending));
309   } else if (fHitWeightsNonBending) {
310     delete fHitWeightsNonBending;
311     fHitWeightsNonBending = 0x0;
312   }
313   
314   // copy hit weights matrix if any
315   if (track.fHitWeightsBending) {
316     if (fHitWeightsBending) {
317       fHitWeightsBending->ResizeTo(*(track.fHitWeightsBending));
318       *fHitWeightsBending = *(track.fHitWeightsBending);
319     } else fHitWeightsBending = new TMatrixD(*(track.fHitWeightsBending));
320   } else if (fHitWeightsBending) {
321     delete fHitWeightsBending;
322     fHitWeightsBending = 0x0;
323   }
324   
325   fNTrackHits         =  track.fNTrackHits;
326   fFitWithVertex      =  track.fFitWithVertex;
327   fFitWithMCS         =  track.fFitWithMCS;
328   fGlobalChi2         =  track.fGlobalChi2;
329   fImproved           =  track.fImproved;
330   fMatchTrigger       =  track.fMatchTrigger;
331   floTrgNum           =  track.floTrgNum;
332   fChi2MatchTrigger   =  track.fChi2MatchTrigger;
333   fTrackID            =  track.fTrackID; 
334   fHitsPatternInTrigCh = track.fHitsPatternInTrigCh;
335   fLocalTrigger        = track.fLocalTrigger;
336
337   return *this;
338 }
339
340   //__________________________________________________________________________
341 AliMUONTrack::~AliMUONTrack()
342 {
343   /// Destructor
344   delete fTrackParamAtHit;
345   delete fHitForRecAtHit;
346   delete fVertex;
347   delete fHitWeightsNonBending;
348   delete fHitWeightsBending;
349 }
350
351   //__________________________________________________________________________
352 void AliMUONTrack::Clear(Option_t* opt)
353 {
354   /// Clear arrays
355   if ( fTrackParamAtHit ) fTrackParamAtHit->Clear(opt);
356   if ( fHitForRecAtHit ) fHitForRecAtHit->Clear(opt);
357   delete fVertex; fVertex = 0x0;
358   delete fHitWeightsNonBending; fHitWeightsNonBending = 0x0;
359   delete fHitWeightsBending; fHitWeightsBending = 0x0;
360 }
361
362   //__________________________________________________________________________
363 void AliMUONTrack::AddTrackParamAtHit(const AliMUONTrackParam *trackParam, AliMUONHitForRec *hitForRec)
364 {
365   /// Add TrackParamAtHit if "trackParam" != NULL
366   /// else create empty TrackParamAtHit and set the z position to the one of "hitForRec" if any
367   /// Update link to HitForRec if "hitForRec" != NULL
368   if (!fTrackParamAtHit) {
369     fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);  
370     fNTrackHits = 0;
371   }
372   AliMUONTrackParam* trackParamAtHit;
373   if (trackParam) {
374     trackParamAtHit = new ((*fTrackParamAtHit)[fNTrackHits]) AliMUONTrackParam(*trackParam);
375     if (hitForRec) {
376       if (hitForRec->GetZ() != trackParam->GetZ())
377         AliWarning("Added track parameters at a different z position than the one of the attached hit");
378     }
379   } else {
380     trackParamAtHit = new ((*fTrackParamAtHit)[fNTrackHits]) AliMUONTrackParam();
381     if (hitForRec) trackParamAtHit->SetZ(hitForRec->GetZ());
382   }
383   if (hitForRec) trackParamAtHit->SetHitForRecPtr(hitForRec);
384   fNTrackHits++;
385 }
386
387   //__________________________________________________________________________
388 void AliMUONTrack::RemoveTrackParamAtHit(AliMUONTrackParam *trackParam)
389 {
390   /// Remove trackParam from the array of TrackParamAtHit
391   if (!fTrackParamAtHit) {
392     AliWarning("array fTrackParamAtHit does not exist");
393     return;
394   }
395   
396   if (!fTrackParamAtHit->Remove(trackParam)) {
397     AliWarning("object to remove does not exist in array fTrackParamAtHit");
398     return;
399   }
400   
401   fTrackParamAtHit->Compress();
402   fNTrackHits--;
403 }
404
405   //__________________________________________________________________________
406 void AliMUONTrack::AddHitForRecAtHit(const AliMUONHitForRec *hitForRec) 
407 {
408   /// Add hitForRec to the array of hitForRec at hit
409   if (!fHitForRecAtHit)
410     fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10); 
411   
412   if (!hitForRec)
413     AliFatal("AliMUONTrack::AddHitForRecAtHit: hitForRec == NULL");
414   
415   new ((*fHitForRecAtHit)[fHitForRecAtHit->GetEntriesFast()]) AliMUONHitForRec(*hitForRec);
416 }
417
418   //__________________________________________________________________________
419 void AliMUONTrack::UpdateTrackParamAtHit()
420 {
421   /// Update track parameters at each attached hit
422   
423   if (fNTrackHits == 0) {
424     AliWarning("no hit attached to the track");
425     return;
426   }
427   
428   Double_t z;
429   AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtHit->First();
430   AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(startingTrackParam);
431   while (trackParamAtHit) {
432     
433     // save current z
434     z = trackParamAtHit->GetZ();
435     
436     // reset track parameters and their covariances
437     trackParamAtHit->SetParameters(startingTrackParam->GetParameters());
438     trackParamAtHit->SetZ(startingTrackParam->GetZ());
439     
440     // extrapolation to the given z
441     AliMUONTrackExtrap::ExtrapToZ(trackParamAtHit, z);
442     
443     // prepare next step
444     startingTrackParam = trackParamAtHit;
445     trackParamAtHit = (AliMUONTrackParam*) (fTrackParamAtHit->After(trackParamAtHit));
446   }
447
448 }
449
450   //__________________________________________________________________________
451 void AliMUONTrack::UpdateCovTrackParamAtHit()
452 {
453   /// Update track parameters and their covariances at each attached hit
454   
455   if (fNTrackHits == 0) {
456     AliWarning("no hit attached to the track");
457     return;
458   }
459   
460   Double_t z;
461   AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtHit->First();
462   AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(startingTrackParam);
463   while (trackParamAtHit) {
464     
465     // save current z
466     z = trackParamAtHit->GetZ();
467     
468     // reset track parameters and their covariances
469     trackParamAtHit->SetParameters(startingTrackParam->GetParameters());
470     trackParamAtHit->SetZ(startingTrackParam->GetZ());
471     trackParamAtHit->SetCovariances(startingTrackParam->GetCovariances());
472     
473     // extrapolation to the given z
474     AliMUONTrackExtrap::ExtrapToZCov(trackParamAtHit, z);
475     
476     // prepare next step
477     startingTrackParam = trackParamAtHit;
478     trackParamAtHit = (AliMUONTrackParam*) (fTrackParamAtHit->After(trackParamAtHit));
479   }
480
481 }
482
483   //__________________________________________________________________________
484 void AliMUONTrack::SetVertex(const AliMUONHitForRec* vertex)
485 {
486   /// Set the vertex used during the tracking procedure
487   if (!fVertex) fVertex = new AliMUONHitForRec(*vertex);
488   else *fVertex = *vertex;
489 }
490
491
492   //__________________________________________________________________________
493 Bool_t AliMUONTrack::ComputeLocalChi2(Bool_t accountForMCS)
494 {
495   /// Compute the removable hit contribution to the chi2 of the track
496   /// accounting for multiple scattering or not according to the flag
497   /// - Also recompute the weight matrices of the attached hits if accountForMCS=kTRUE
498   /// - Assume that track parameters at each hit are corrects
499   /// - Return kFALSE if computation failed
500   
501   // Check hits (if the first one exist, assume that the other ones exit too!)
502   AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
503   if (!trackParamAtHit->GetHitForRecPtr()) {
504     AliWarning("hit is missing");
505     return kFALSE;
506   }
507   
508   if (accountForMCS) { // Compute local chi2 taking into account multiple scattering effects
509       
510     // Compute MCS covariance matrix only once
511     TMatrixD mcsCovariances(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
512     ComputeMCSCovariances(mcsCovariances);
513     
514     // Make sure hit weights are consistent with following calculations
515     if (!ComputeHitWeights(&mcsCovariances)) {
516       AliWarning("cannot take into account the multiple scattering effects");
517       return ComputeLocalChi2(kFALSE);
518     }
519     
520     // Compute chi2 of the track
521     Double_t globalChi2 = ComputeGlobalChi2(kTRUE);
522     if (globalChi2 < 0.) return kFALSE;
523     
524     // Loop over removable hits and compute their local chi2
525     AliMUONTrackParam* trackParamAtHit1;
526     AliMUONHitForRec *hitForRec, *discardedHit;
527     Int_t hitNumber1, hitNumber2, currentHitNumber1, currentHitNumber2;
528     TMatrixD hitWeightsNB(fNTrackHits-1,fNTrackHits-1);
529     TMatrixD hitWeightsB(fNTrackHits-1,fNTrackHits-1);
530     Double_t *dX = new Double_t[fNTrackHits-1];
531     Double_t *dY = new Double_t[fNTrackHits-1];
532     Double_t globalChi2b;
533     while (trackParamAtHit) {
534       
535       discardedHit = trackParamAtHit->GetHitForRecPtr();
536       
537       // Recompute hit weights without the current hit
538       if (!ComputeHitWeights(hitWeightsNB, hitWeightsB, &mcsCovariances, discardedHit)) {
539         AliWarning("cannot take into account the multiple scattering effects");
540         ComputeLocalChi2(kFALSE);
541       }
542       
543       // Compute track chi2 without the current hit
544       globalChi2b = 0.;
545       currentHitNumber1 = 0;
546       for (hitNumber1 = 0; hitNumber1 < fNTrackHits ; hitNumber1++) { 
547         trackParamAtHit1 = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1);
548         hitForRec = trackParamAtHit1->GetHitForRecPtr();
549         
550         if (hitForRec == discardedHit) continue;
551         
552         // Compute and save residuals
553         dX[currentHitNumber1] = hitForRec->GetNonBendingCoor() - trackParamAtHit1->GetNonBendingCoor();
554         dY[currentHitNumber1] = hitForRec->GetBendingCoor() - trackParamAtHit1->GetBendingCoor();
555         
556         currentHitNumber2 = 0;
557         for (hitNumber2 = 0; hitNumber2 < hitNumber1; hitNumber2++) {
558           hitForRec = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber2))->GetHitForRecPtr();
559           
560           if (hitForRec == discardedHit) continue;
561           
562           // Add contribution from covariances
563           globalChi2b += (hitWeightsNB(currentHitNumber1, currentHitNumber2) +
564                           hitWeightsNB(currentHitNumber2, currentHitNumber1)) * dX[currentHitNumber1] * dX[currentHitNumber2] +
565                          (hitWeightsB(currentHitNumber1, currentHitNumber2) +
566                           hitWeightsB(currentHitNumber2, currentHitNumber1)) * dY[currentHitNumber1] * dY[currentHitNumber2];
567           
568           currentHitNumber2++;
569         }
570         
571         // Add contribution from variances
572         globalChi2b += hitWeightsNB(currentHitNumber1, currentHitNumber1) * dX[currentHitNumber1] * dX[currentHitNumber1] +
573                        hitWeightsB(currentHitNumber1, currentHitNumber1) * dY[currentHitNumber1] * dY[currentHitNumber1];
574         
575         currentHitNumber1++;
576       }
577
578       // Set local chi2
579       trackParamAtHit->SetLocalChi2(globalChi2 - globalChi2b);
580       
581       trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
582     }
583     
584     delete [] dX;
585     delete [] dY;
586     
587   } else { // without multiple scattering effects
588     
589     AliMUONHitForRec *discardedHit;
590     Double_t dX, dY;
591     while (trackParamAtHit) {
592       
593       discardedHit = trackParamAtHit->GetHitForRecPtr();
594       
595       // Compute residuals
596       dX = discardedHit->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
597       dY = discardedHit->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
598       
599       // Set local chi2
600       trackParamAtHit->SetLocalChi2(dX * dX / discardedHit->GetNonBendingReso2() + dY * dY / discardedHit->GetBendingReso2());
601     
602     trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
603     }
604   
605   }
606   
607   
608   return kTRUE;
609   
610 }
611
612   //__________________________________________________________________________
613 Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
614 {
615   /// Compute the chi2 of the track accounting for multiple scattering or not according to the flag
616   /// - Assume that track parameters at each hit are corrects
617   /// - Assume the hits weights matrices are corrects
618   /// - Return negative value if chi2 computation failed
619   
620   // Check hits (if the first one exist, assume that the other ones exit too!)
621   AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
622   if (!trackParamAtHit->GetHitForRecPtr()) {
623     AliWarning("hit is missing");
624     return -1.;
625   }
626   
627   Double_t chi2 = 0.;
628   
629   if (accountForMCS) {
630     
631     // Check the weight matrices
632     Bool_t weightsAvailable = kTRUE;
633     if (!fHitWeightsNonBending || !fHitWeightsBending) weightsAvailable = kFALSE;
634     else if (fHitWeightsNonBending->GetNrows() != fNTrackHits || fHitWeightsNonBending->GetNcols() != fNTrackHits ||
635              fHitWeightsBending->GetNrows()    != fNTrackHits || fHitWeightsBending->GetNcols()    != fNTrackHits) weightsAvailable = kFALSE;
636     
637     // if weight matrices are not available compute chi2 without MCS
638     if (!weightsAvailable) {
639       AliWarning("hit weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
640       return ComputeGlobalChi2(kFALSE);
641     }
642     
643     // Compute chi2
644     AliMUONHitForRec *hitForRec;
645     Double_t *dX = new Double_t[fNTrackHits];
646     Double_t *dY = new Double_t[fNTrackHits];
647     Int_t hitNumber1, hitNumber2;
648     for (hitNumber1 = 0; hitNumber1 < fNTrackHits ; hitNumber1++) { 
649       trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1);
650       hitForRec = trackParamAtHit->GetHitForRecPtr();
651       dX[hitNumber1] = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
652       dY[hitNumber1] = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
653       for (hitNumber2 = 0; hitNumber2 < hitNumber1; hitNumber2++) {
654         chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber2) + (*fHitWeightsNonBending)(hitNumber2, hitNumber1)) * dX[hitNumber1] * dX[hitNumber2] +
655                 ((*fHitWeightsBending)(hitNumber1, hitNumber2) + (*fHitWeightsBending)(hitNumber2, hitNumber1)) * dY[hitNumber1] * dY[hitNumber2];
656       }
657       chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber1) * dX[hitNumber1] * dX[hitNumber1]) +
658               ((*fHitWeightsBending)(hitNumber1, hitNumber1) * dY[hitNumber1] * dY[hitNumber1]);
659     }
660     delete [] dX;
661     delete [] dY;
662     
663   } else {
664     
665     AliMUONHitForRec *hitForRec;
666     Double_t dX, dY;
667     for (Int_t hitNumber = 0; hitNumber < fNTrackHits ; hitNumber++) { 
668       trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
669       hitForRec = trackParamAtHit->GetHitForRecPtr();
670       dX = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
671       dY = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
672       chi2 += dX * dX / hitForRec->GetNonBendingReso2() + dY * dY / hitForRec->GetBendingReso2();
673     }
674     
675   }
676   
677   return chi2;
678   
679 }
680
681   //__________________________________________________________________________
682 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD* mcsCovariances)
683 {
684   /// Compute the weight matrices of the attached hits, in non bending and bending direction,
685   /// accounting for multiple scattering correlations and hits resolution
686   /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
687   /// - Assume that track parameters at each hit are corrects
688   /// - Return kFALSE if computation failed
689   
690   // Alocate memory
691   if (!fHitWeightsNonBending) fHitWeightsNonBending = new TMatrixD(fNTrackHits,fNTrackHits);
692   if (!fHitWeightsBending) fHitWeightsBending = new TMatrixD(fNTrackHits,fNTrackHits);
693   
694   // Check hits (if the first one exist, assume that the other ones exit too!)
695   if (!((AliMUONTrackParam*) fTrackParamAtHit->First())->GetHitForRecPtr()) {
696     AliWarning("hit is missing");
697     fHitWeightsNonBending->ResizeTo(0,0);
698     fHitWeightsBending->ResizeTo(0,0);
699     return kFALSE;
700   }
701   
702   // Compute weights matrices
703   if (!ComputeHitWeights(*fHitWeightsNonBending, *fHitWeightsBending, mcsCovariances)) return kFALSE;
704   
705   return kTRUE;
706   
707 }
708
709   //__________________________________________________________________________
710 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD& hitWeightsNB, TMatrixD& hitWeightsB, TMatrixD* mcsCovariances, AliMUONHitForRec* discardedHit) const
711 {
712   /// Compute the weight matrices, in non bending and bending direction,
713   /// of the other attached hits assuming the discarded one does not exist
714   /// accounting for multiple scattering correlations and hits resolution
715   /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
716   /// - Return kFALSE if computation failed
717   
718   // Check MCS covariance matrix and recompute it if need
719   Bool_t deleteMCSCov = kFALSE;
720   if (!mcsCovariances) {
721     
722     // build MCS covariance matrix
723     mcsCovariances = new TMatrixD(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
724     deleteMCSCov = kTRUE;
725     ComputeMCSCovariances(*mcsCovariances);
726     
727   } else {
728     
729     // check MCS covariance matrix size
730     if (mcsCovariances->GetNrows() != AliMUONConstants::NTrackingCh() || mcsCovariances->GetNcols() != AliMUONConstants::NTrackingCh()) {
731       ComputeMCSCovariances(*mcsCovariances);
732     }
733     
734   }
735   
736   // Resize the weights matrices; alocate memory
737   if (discardedHit) {
738     hitWeightsNB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
739     hitWeightsB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
740   } else {
741     hitWeightsNB.ResizeTo(fNTrackHits,fNTrackHits);
742     hitWeightsB.ResizeTo(fNTrackHits,fNTrackHits);
743   }
744   
745   // Define variables
746   AliMUONHitForRec *hitForRec1, *hitForRec2;
747   Int_t chamber1, chamber2, currentHitNumber1, currentHitNumber2;
748   
749   // Compute the covariance matrices
750   currentHitNumber1 = 0;
751   for (Int_t hitNumber1 = 0; hitNumber1 < fNTrackHits; hitNumber1++) { 
752     hitForRec1 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1))->GetHitForRecPtr();
753     
754     if (hitForRec1 == discardedHit) continue;
755     
756     chamber1 = hitForRec1->GetChamberNumber();
757     
758     // Loop over next hits
759     currentHitNumber2 = currentHitNumber1;
760     for (Int_t hitNumber2 = hitNumber1; hitNumber2 < fNTrackHits; hitNumber2++) {
761       hitForRec2 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber2))->GetHitForRecPtr();
762       
763       if (hitForRec2 == discardedHit) continue;
764       
765       chamber2 = hitForRec2->GetChamberNumber();
766     
767       // Fill with MCS covariances
768       hitWeightsNB(currentHitNumber1, currentHitNumber2) = (*mcsCovariances)(chamber1,chamber2);
769       
770       // Equal contribution from multiple scattering in non bending and bending directions
771       hitWeightsB(currentHitNumber1, currentHitNumber2) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
772       
773       // Add contribution from hit resolution to diagonal element and symmetrize the matrix
774       if (currentHitNumber1 == currentHitNumber2) {
775         
776         // In non bending plane
777         hitWeightsNB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetNonBendingReso2();
778         // In bending plane
779         hitWeightsB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetBendingReso2();
780         
781       } else {
782         
783         // In non bending plane
784         hitWeightsNB(currentHitNumber2, currentHitNumber1) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
785         // In bending plane
786         hitWeightsB(currentHitNumber2, currentHitNumber1) = hitWeightsB(currentHitNumber1, currentHitNumber2);
787         
788       }
789       
790       currentHitNumber2++;
791     }
792     
793     currentHitNumber1++;
794   }
795     
796   // Inversion of covariance matrices to get the weights
797   if (hitWeightsNB.Determinant() != 0 && hitWeightsB.Determinant() != 0) {
798     hitWeightsNB.Invert();
799     hitWeightsB.Invert();
800   } else {
801     AliWarning(" Determinant = 0");
802     hitWeightsNB.ResizeTo(0,0);
803     hitWeightsB.ResizeTo(0,0);
804     if(deleteMCSCov) delete mcsCovariances;
805     return kFALSE;
806   }
807   
808   if(deleteMCSCov) delete mcsCovariances;
809   
810   return kTRUE;
811   
812 }
813
814   //__________________________________________________________________________
815 void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
816 {
817   /// Compute the multiple scattering covariance matrix
818   /// - Assume that track parameters at each hit are corrects
819   /// - Return kFALSE if computation failed
820   
821   // Make sure the size of the covariance matrix is correct
822   Int_t nChambers = AliMUONConstants::NTrackingCh();
823   mcsCovariances.ResizeTo(nChambers,nChambers);
824   
825   // check for too many track hits
826   if (fNTrackHits > nChambers) {
827     AliWarning("more than 1 hit per chamber!!");
828     mcsCovariances.Zero();
829     return;
830   }
831   
832   // Define variables
833   AliMUONTrackParam* trackParamAtHit;
834   AliMUONHitForRec *hitForRec;
835   AliMUONTrackParam extrapTrackParam;
836   Int_t currentChamber, expectedChamber;
837   Double_t *mcsAngle2 = new Double_t[nChambers];
838   Double_t *zMCS = new Double_t[nChambers];
839   
840   // Compute multiple scattering dispersion angle at each chamber
841   // and save the z position where it is calculated
842   currentChamber = 0;
843   expectedChamber = 0;
844   for (Int_t hitNumber = 0; hitNumber < fNTrackHits; hitNumber++) {
845     trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
846     hitForRec = trackParamAtHit->GetHitForRecPtr();
847     
848     // look for missing chambers if any
849     currentChamber = hitForRec->GetChamberNumber();
850     while (currentChamber > expectedChamber) {
851       
852       // Save the z position where MCS dispersion is calculated
853       zMCS[expectedChamber] = AliMUONConstants::DefaultChamberZ(expectedChamber);
854       
855       // Do not take into account MCS in chambers prior the first hit
856       if (hitNumber > 0) {
857         
858         // Get track parameters at missing chamber z
859         extrapTrackParam = *trackParamAtHit;
860         AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[expectedChamber]);
861         
862         // Save multiple scattering dispersion angle in missing chamber
863         mcsAngle2[expectedChamber] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
864         
865       } else mcsAngle2[expectedChamber] = 0.;
866       
867       expectedChamber++;
868     }
869     
870     // Save z position where MCS dispersion is calculated
871     zMCS[currentChamber] = trackParamAtHit->GetZ();
872     
873     // Save multiple scattering dispersion angle in current chamber
874     mcsAngle2[currentChamber] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtHit,AliMUONConstants::ChamberThicknessInX0(),1.);
875     
876     expectedChamber++;
877   }
878   
879   // complete array of z if last hit is on the last but one chamber
880   if (currentChamber != nChambers-1) zMCS[nChambers-1] = AliMUONConstants::DefaultChamberZ(nChambers-1);
881   
882   
883   // Compute the covariance matrix
884   for (Int_t chamber1 = 0; chamber1 < nChambers; chamber1++) { 
885     
886     for (Int_t chamber2 = chamber1; chamber2 < nChambers; chamber2++) {
887       
888       // Initialization to 0 (diagonal plus upper triangular part)
889       mcsCovariances(chamber1, chamber2) = 0.;
890       
891       // Compute contribution from multiple scattering in upstream chambers
892       for (currentChamber = 0; currentChamber < chamber1; currentChamber++) {   
893         mcsCovariances(chamber1, chamber2) += (zMCS[chamber1] - zMCS[currentChamber]) * (zMCS[chamber2] - zMCS[currentChamber]) * mcsAngle2[currentChamber];
894       }
895       
896       // Symetrize the matrix
897       mcsCovariances(chamber2, chamber1) = mcsCovariances(chamber1, chamber2);
898     }
899     
900   }
901     
902   delete [] mcsAngle2;
903   delete [] zMCS;
904   
905 }
906
907   //__________________________________________________________________________
908 Int_t AliMUONTrack::HitsInCommon(AliMUONTrack* track) const
909 {
910   /// Returns the number of hits in common between the current track ("this")
911   /// and the track pointed to by "track".
912   Int_t hitsInCommon = 0;
913   AliMUONTrackParam *trackParamAtHit1, *trackParamAtHit2;
914   // Loop over hits of first track
915   trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->First();
916   while (trackParamAtHit1) {
917     // Loop over hits of second track
918     trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->First();
919     while (trackParamAtHit2) {
920       // Increment "hitsInCommon" if both TrackParamAtHits point to the same HitForRec
921       if ((trackParamAtHit1->GetHitForRecPtr()) == (trackParamAtHit2->GetHitForRecPtr())) {
922         hitsInCommon++;
923         break;
924       }
925       trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->After(trackParamAtHit2);
926     } // trackParamAtHit2
927     trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->After(trackParamAtHit1);
928   } // trackParamAtHit1
929   return hitsInCommon;
930 }
931
932   //__________________________________________________________________________
933 Double_t AliMUONTrack::GetNormalizedChi2() const
934 {
935   /// return the chi2 value divided by the number of degrees of freedom (or 1.e10 if ndf < 0)
936   
937   Double_t numberOfDegFree = (2. * fNTrackHits - 5.);
938   if (numberOfDegFree > 0.) return fGlobalChi2 / numberOfDegFree;
939   else return 1.e10;
940 }
941
942   //__________________________________________________________________________
943 Bool_t* AliMUONTrack::CompatibleTrack(AliMUONTrack * track, Double_t sigma2Cut) const
944 {
945   /// Return kTRUE/kFALSE for each chamber if hit is compatible or not 
946   TClonesArray *hitArray, *thisHitArray;
947   AliMUONHitForRec *hit, *thisHit;
948   Int_t chamberNumber;
949   Float_t deltaZ;
950   Float_t deltaZMax = 1.; // 1 cm
951   Float_t chi2 = 0;
952   Bool_t *nCompHit = new Bool_t[AliMUONConstants::NTrackingCh()]; 
953
954   for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
955     nCompHit[ch] = kFALSE;
956   }
957
958   thisHitArray = this->GetHitForRecAtHit();
959
960   hitArray =  track->GetHitForRecAtHit();
961
962   for (Int_t iHthis = 0; iHthis < thisHitArray->GetEntriesFast(); iHthis++) {
963     thisHit = (AliMUONHitForRec*) thisHitArray->At(iHthis);
964     chamberNumber = thisHit->GetChamberNumber();
965     if (chamberNumber < 0 || chamberNumber > AliMUONConstants::NTrackingCh()) continue; 
966     nCompHit[chamberNumber] = kFALSE;
967     for (Int_t iH = 0; iH < hitArray->GetEntriesFast(); iH++) {
968       hit = (AliMUONHitForRec*) hitArray->At(iH);
969       deltaZ = TMath::Abs(thisHit->GetZ() - hit->GetZ());
970       chi2 = thisHit->NormalizedChi2WithHitForRec(hit,sigma2Cut); // set cut to 4 sigmas
971       if (chi2 < 3. && deltaZ < deltaZMax) {
972         nCompHit[chamberNumber] = kTRUE;
973         break;
974       }
975     }  
976   }
977   
978   return nCompHit;
979 }
980
981   //__________________________________________________________________________
982 void AliMUONTrack::RecursiveDump(void) const
983 {
984   /// Recursive dump of AliMUONTrack, i.e. with dump of TrackParamAtHit's and attached HitForRec's
985   AliMUONTrackParam *trackParamAtHit;
986   AliMUONHitForRec *hitForRec;
987   cout << "Recursive dump of Track: " << this << endl;
988   // Track
989   this->Dump();
990   for (Int_t trackHitIndex = 0; trackHitIndex < fNTrackHits; trackHitIndex++) {
991     trackParamAtHit = (AliMUONTrackParam*) ((*fTrackParamAtHit)[trackHitIndex]);
992     // TrackHit
993     cout << "TrackParamAtHit: " << trackParamAtHit << " (index: " << trackHitIndex << ")" << endl;
994     trackParamAtHit->Dump();
995     hitForRec = trackParamAtHit->GetHitForRecPtr();
996     // HitForRec
997     cout << "HitForRec: " << hitForRec << endl;
998     hitForRec->Dump();
999   }
1000   return;
1001 }
1002   
1003 //_____________________________________________-
1004 void AliMUONTrack::Print(Option_t*) const
1005 {
1006   /// Printing Track information 
1007
1008   cout << "<AliMUONTrack> No.Clusters=" << setw(2)   << GetNTrackHits() << 
1009       ", Match2Trig=" << setw(1) << GetMatchTrigger()  << 
1010       ", LoTrgNum=" << setw(3) << GetLoTrgNum()  << 
1011     ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) <<  GetChi2MatchTrigger();
1012   cout << Form(" HitTriggerPattern %x",fHitsPatternInTrigCh) << endl;
1013   GetTrackParamAtHit()->First()->Print("FULL");
1014 }
1015
1016 //__________________________________________________________________________
1017 void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt)
1018 {
1019   /// pack the local trigger information and store
1020
1021   if (loCirc < 0 || loCirc > 233) return;
1022
1023   fLocalTrigger = 0;
1024   fLocalTrigger += loCirc;
1025   fLocalTrigger += loStripX << 8;
1026   fLocalTrigger += loStripY << 13;
1027   fLocalTrigger += loDev    << 17;
1028   fLocalTrigger += loLpt    << 22;
1029   fLocalTrigger += loHpt    << 24;
1030
1031 }
1032