]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrack.cxx
Removing class AliMUONTrackK
[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) ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(fNTrackHits))->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       // compute chi2 of removable hits only
594       if (!trackParamAtHit->IsRemovable()) {
595         trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
596         continue;
597       }
598       
599       discardedHit = trackParamAtHit->GetHitForRecPtr();
600       
601       // Compute residuals
602       dX = discardedHit->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
603       dY = discardedHit->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
604       
605       // Set local chi2
606       trackParamAtHit->SetLocalChi2(dX * dX / discardedHit->GetNonBendingReso2() + dY * dY / discardedHit->GetBendingReso2());
607     
608     trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
609     }
610   
611   }
612   
613   
614   return kTRUE;
615   
616 }
617
618   //__________________________________________________________________________
619 Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
620 {
621   /// Compute the chi2 of the track accounting for multiple scattering or not according to the flag
622   /// - Assume that track parameters at each hit are corrects
623   /// - Assume the hits weights matrices are corrects
624   /// - Return negative value if chi2 computation failed
625   
626   // Check hits (if the first one exist, assume that the other ones exit too!)
627   AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
628   if (!trackParamAtHit->GetHitForRecPtr()) {
629     AliWarning("hit is missing");
630     return -1.;
631   }
632   
633   Double_t chi2 = 0.;
634   
635   if (accountForMCS) {
636     
637     // Check the weight matrices
638     Bool_t weightsAvailable = kTRUE;
639     if (!fHitWeightsNonBending || !fHitWeightsBending) weightsAvailable = kFALSE;
640     else if (fHitWeightsNonBending->GetNrows() != fNTrackHits || fHitWeightsNonBending->GetNcols() != fNTrackHits ||
641              fHitWeightsBending->GetNrows()    != fNTrackHits || fHitWeightsBending->GetNcols()    != fNTrackHits) weightsAvailable = kFALSE;
642     
643     // if weight matrices are not available compute chi2 without MCS
644     if (!weightsAvailable) {
645       AliWarning("hit weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
646       return ComputeGlobalChi2(kFALSE);
647     }
648     
649     // Compute chi2
650     AliMUONHitForRec *hitForRec;
651     Double_t *dX = new Double_t[fNTrackHits];
652     Double_t *dY = new Double_t[fNTrackHits];
653     Int_t hitNumber1, hitNumber2;
654     for (hitNumber1 = 0; hitNumber1 < fNTrackHits ; hitNumber1++) { 
655       trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1);
656       hitForRec = trackParamAtHit->GetHitForRecPtr();
657       dX[hitNumber1] = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
658       dY[hitNumber1] = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
659       for (hitNumber2 = 0; hitNumber2 < hitNumber1; hitNumber2++) {
660         chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber2) + (*fHitWeightsNonBending)(hitNumber2, hitNumber1)) * dX[hitNumber1] * dX[hitNumber2] +
661                 ((*fHitWeightsBending)(hitNumber1, hitNumber2) + (*fHitWeightsBending)(hitNumber2, hitNumber1)) * dY[hitNumber1] * dY[hitNumber2];
662       }
663       chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber1) * dX[hitNumber1] * dX[hitNumber1]) +
664               ((*fHitWeightsBending)(hitNumber1, hitNumber1) * dY[hitNumber1] * dY[hitNumber1]);
665     }
666     delete [] dX;
667     delete [] dY;
668     
669   } else {
670     
671     AliMUONHitForRec *hitForRec;
672     Double_t dX, dY;
673     for (Int_t hitNumber = 0; hitNumber < fNTrackHits ; hitNumber++) { 
674       trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
675       hitForRec = trackParamAtHit->GetHitForRecPtr();
676       dX = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
677       dY = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
678       chi2 += dX * dX / hitForRec->GetNonBendingReso2() + dY * dY / hitForRec->GetBendingReso2();
679     }
680     
681   }
682   
683   return chi2;
684   
685 }
686
687   //__________________________________________________________________________
688 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD* mcsCovariances)
689 {
690   /// Compute the weight matrices of the attached hits, in non bending and bending direction,
691   /// accounting for multiple scattering correlations and hits resolution
692   /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
693   /// - Assume that track parameters at each hit are corrects
694   /// - Return kFALSE if computation failed
695   
696   // Alocate memory
697   if (!fHitWeightsNonBending) fHitWeightsNonBending = new TMatrixD(fNTrackHits,fNTrackHits);
698   if (!fHitWeightsBending) fHitWeightsBending = new TMatrixD(fNTrackHits,fNTrackHits);
699   
700   // Check hits (if the first one exist, assume that the other ones exit too!)
701   if (!((AliMUONTrackParam*) fTrackParamAtHit->First())->GetHitForRecPtr()) {
702     AliWarning("hit is missing");
703     fHitWeightsNonBending->ResizeTo(0,0);
704     fHitWeightsBending->ResizeTo(0,0);
705     return kFALSE;
706   }
707   
708   // Compute weights matrices
709   if (!ComputeHitWeights(*fHitWeightsNonBending, *fHitWeightsBending, mcsCovariances)) return kFALSE;
710   
711   return kTRUE;
712   
713 }
714
715   //__________________________________________________________________________
716 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD& hitWeightsNB, TMatrixD& hitWeightsB, TMatrixD* mcsCovariances, AliMUONHitForRec* discardedHit) const
717 {
718   /// Compute the weight matrices, in non bending and bending direction,
719   /// of the other attached hits assuming the discarded one does not exist
720   /// accounting for multiple scattering correlations and hits resolution
721   /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
722   /// - Return kFALSE if computation failed
723   
724   // Check MCS covariance matrix and recompute it if need
725   Bool_t deleteMCSCov = kFALSE;
726   if (!mcsCovariances) {
727     
728     // build MCS covariance matrix
729     mcsCovariances = new TMatrixD(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
730     deleteMCSCov = kTRUE;
731     ComputeMCSCovariances(*mcsCovariances);
732     
733   } else {
734     
735     // check MCS covariance matrix size
736     if (mcsCovariances->GetNrows() != AliMUONConstants::NTrackingCh() || mcsCovariances->GetNcols() != AliMUONConstants::NTrackingCh()) {
737       ComputeMCSCovariances(*mcsCovariances);
738     }
739     
740   }
741   
742   // Resize the weights matrices; alocate memory
743   if (discardedHit) {
744     hitWeightsNB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
745     hitWeightsB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
746   } else {
747     hitWeightsNB.ResizeTo(fNTrackHits,fNTrackHits);
748     hitWeightsB.ResizeTo(fNTrackHits,fNTrackHits);
749   }
750   
751   // Define variables
752   AliMUONHitForRec *hitForRec1, *hitForRec2;
753   Int_t chamber1, chamber2, currentHitNumber1, currentHitNumber2;
754   
755   // Compute the covariance matrices
756   currentHitNumber1 = 0;
757   for (Int_t hitNumber1 = 0; hitNumber1 < fNTrackHits; hitNumber1++) { 
758     hitForRec1 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1))->GetHitForRecPtr();
759     
760     if (hitForRec1 == discardedHit) continue;
761     
762     chamber1 = hitForRec1->GetChamberNumber();
763     
764     // Loop over next hits
765     currentHitNumber2 = currentHitNumber1;
766     for (Int_t hitNumber2 = hitNumber1; hitNumber2 < fNTrackHits; hitNumber2++) {
767       hitForRec2 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber2))->GetHitForRecPtr();
768       
769       if (hitForRec2 == discardedHit) continue;
770       
771       chamber2 = hitForRec2->GetChamberNumber();
772     
773       // Fill with MCS covariances
774       hitWeightsNB(currentHitNumber1, currentHitNumber2) = (*mcsCovariances)(chamber1,chamber2);
775       
776       // Equal contribution from multiple scattering in non bending and bending directions
777       hitWeightsB(currentHitNumber1, currentHitNumber2) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
778       
779       // Add contribution from hit resolution to diagonal element and symmetrize the matrix
780       if (currentHitNumber1 == currentHitNumber2) {
781         
782         // In non bending plane
783         hitWeightsNB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetNonBendingReso2();
784         // In bending plane
785         hitWeightsB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetBendingReso2();
786         
787       } else {
788         
789         // In non bending plane
790         hitWeightsNB(currentHitNumber2, currentHitNumber1) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
791         // In bending plane
792         hitWeightsB(currentHitNumber2, currentHitNumber1) = hitWeightsB(currentHitNumber1, currentHitNumber2);
793         
794       }
795       
796       currentHitNumber2++;
797     }
798     
799     currentHitNumber1++;
800   }
801     
802   // Inversion of covariance matrices to get the weights
803   if (hitWeightsNB.Determinant() != 0 && hitWeightsB.Determinant() != 0) {
804     hitWeightsNB.Invert();
805     hitWeightsB.Invert();
806   } else {
807     AliWarning(" Determinant = 0");
808     hitWeightsNB.ResizeTo(0,0);
809     hitWeightsB.ResizeTo(0,0);
810     if(deleteMCSCov) delete mcsCovariances;
811     return kFALSE;
812   }
813   
814   if(deleteMCSCov) delete mcsCovariances;
815   
816   return kTRUE;
817   
818 }
819
820   //__________________________________________________________________________
821 void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
822 {
823   /// Compute the multiple scattering covariance matrix
824   /// - Assume that track parameters at each hit are corrects
825   /// - Return kFALSE if computation failed
826   
827   // Make sure the size of the covariance matrix is correct
828   Int_t nChambers = AliMUONConstants::NTrackingCh();
829   mcsCovariances.ResizeTo(nChambers,nChambers);
830   
831   // check for too many track hits
832   if (fNTrackHits > nChambers) {
833     AliWarning("more than 1 hit per chamber!!");
834     mcsCovariances.Zero();
835     return;
836   }
837   
838   // Define variables
839   AliMUONTrackParam* trackParamAtHit;
840   AliMUONHitForRec *hitForRec;
841   AliMUONTrackParam extrapTrackParam;
842   Int_t currentChamber, expectedChamber;
843   Double_t *mcsAngle2 = new Double_t[nChambers];
844   Double_t *zMCS = new Double_t[nChambers];
845   
846   // Compute multiple scattering dispersion angle at each chamber
847   // and save the z position where it is calculated
848   currentChamber = 0;
849   expectedChamber = 0;
850   for (Int_t hitNumber = 0; hitNumber < fNTrackHits; hitNumber++) {
851     trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
852     hitForRec = trackParamAtHit->GetHitForRecPtr();
853     
854     // look for missing chambers if any
855     currentChamber = hitForRec->GetChamberNumber();
856     while (currentChamber > expectedChamber) {
857       
858       // Save the z position where MCS dispersion is calculated
859       zMCS[expectedChamber] = AliMUONConstants::DefaultChamberZ(expectedChamber);
860       
861       // Do not take into account MCS in chambers prior the first hit
862       if (hitNumber > 0) {
863         
864         // Get track parameters at missing chamber z
865         extrapTrackParam = *trackParamAtHit;
866         AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[expectedChamber]);
867         
868         // Save multiple scattering dispersion angle in missing chamber
869         mcsAngle2[expectedChamber] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
870         
871       } else mcsAngle2[expectedChamber] = 0.;
872       
873       expectedChamber++;
874     }
875     
876     // Save z position where MCS dispersion is calculated
877     zMCS[currentChamber] = trackParamAtHit->GetZ();
878     
879     // Save multiple scattering dispersion angle in current chamber
880     mcsAngle2[currentChamber] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtHit,AliMUONConstants::ChamberThicknessInX0(),1.);
881     
882     expectedChamber++;
883   }
884   
885   // complete array of z if last hit is on the last but one chamber
886   if (currentChamber != nChambers-1) zMCS[nChambers-1] = AliMUONConstants::DefaultChamberZ(nChambers-1);
887   
888   
889   // Compute the covariance matrix
890   for (Int_t chamber1 = 0; chamber1 < nChambers; chamber1++) { 
891     
892     for (Int_t chamber2 = chamber1; chamber2 < nChambers; chamber2++) {
893       
894       // Initialization to 0 (diagonal plus upper triangular part)
895       mcsCovariances(chamber1, chamber2) = 0.;
896       
897       // Compute contribution from multiple scattering in upstream chambers
898       for (currentChamber = 0; currentChamber < chamber1; currentChamber++) {   
899         mcsCovariances(chamber1, chamber2) += (zMCS[chamber1] - zMCS[currentChamber]) * (zMCS[chamber2] - zMCS[currentChamber]) * mcsAngle2[currentChamber];
900       }
901       
902       // Symetrize the matrix
903       mcsCovariances(chamber2, chamber1) = mcsCovariances(chamber1, chamber2);
904     }
905     
906   }
907     
908   delete [] mcsAngle2;
909   delete [] zMCS;
910   
911 }
912
913   //__________________________________________________________________________
914 Int_t AliMUONTrack::HitsInCommon(AliMUONTrack* track) const
915 {
916   /// Returns the number of hits in common between the current track ("this")
917   /// and the track pointed to by "track".
918   Int_t hitsInCommon = 0;
919   AliMUONTrackParam *trackParamAtHit1, *trackParamAtHit2;
920   // Loop over hits of first track
921   trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->First();
922   while (trackParamAtHit1) {
923     // Loop over hits of second track
924     trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->First();
925     while (trackParamAtHit2) {
926       // Increment "hitsInCommon" if both TrackParamAtHits point to the same HitForRec
927       if ((trackParamAtHit1->GetHitForRecPtr()) == (trackParamAtHit2->GetHitForRecPtr())) {
928         hitsInCommon++;
929         break;
930       }
931       trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->After(trackParamAtHit2);
932     } // trackParamAtHit2
933     trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->After(trackParamAtHit1);
934   } // trackParamAtHit1
935   return hitsInCommon;
936 }
937
938   //__________________________________________________________________________
939 Double_t AliMUONTrack::GetNormalizedChi2() const
940 {
941   /// return the chi2 value divided by the number of degrees of freedom (or 1.e10 if ndf < 0)
942   
943   Double_t numberOfDegFree = (2. * fNTrackHits - 5.);
944   if (numberOfDegFree > 0.) return fGlobalChi2 / numberOfDegFree;
945   else return 1.e10;
946 }
947
948   //__________________________________________________________________________
949 Bool_t* AliMUONTrack::CompatibleTrack(AliMUONTrack * track, Double_t sigma2Cut) const
950 {
951   /// Return kTRUE/kFALSE for each chamber if hit is compatible or not 
952   TClonesArray *hitArray, *thisHitArray;
953   AliMUONHitForRec *hit, *thisHit;
954   Int_t chamberNumber;
955   Float_t deltaZ;
956   Float_t deltaZMax = 1.; // 1 cm
957   Float_t chi2 = 0;
958   Bool_t *nCompHit = new Bool_t[AliMUONConstants::NTrackingCh()]; 
959
960   for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
961     nCompHit[ch] = kFALSE;
962   }
963
964   thisHitArray = this->GetHitForRecAtHit();
965
966   hitArray =  track->GetHitForRecAtHit();
967
968   for (Int_t iHthis = 0; iHthis < thisHitArray->GetEntriesFast(); iHthis++) {
969     thisHit = (AliMUONHitForRec*) thisHitArray->At(iHthis);
970     chamberNumber = thisHit->GetChamberNumber();
971     if (chamberNumber < 0 || chamberNumber > AliMUONConstants::NTrackingCh()) continue; 
972     nCompHit[chamberNumber] = kFALSE;
973     for (Int_t iH = 0; iH < hitArray->GetEntriesFast(); iH++) {
974       hit = (AliMUONHitForRec*) hitArray->At(iH);
975       deltaZ = TMath::Abs(thisHit->GetZ() - hit->GetZ());
976       chi2 = thisHit->NormalizedChi2WithHitForRec(hit,sigma2Cut); // set cut to 4 sigmas
977       if (chi2 < 3. && deltaZ < deltaZMax) {
978         nCompHit[chamberNumber] = kTRUE;
979         break;
980       }
981     }  
982   }
983   
984   return nCompHit;
985 }
986
987   //__________________________________________________________________________
988 void AliMUONTrack::RecursiveDump(void) const
989 {
990   /// Recursive dump of AliMUONTrack, i.e. with dump of TrackParamAtHit's and attached HitForRec's
991   AliMUONTrackParam *trackParamAtHit;
992   AliMUONHitForRec *hitForRec;
993   cout << "Recursive dump of Track: " << this << endl;
994   // Track
995   this->Dump();
996   for (Int_t trackHitIndex = 0; trackHitIndex < fNTrackHits; trackHitIndex++) {
997     trackParamAtHit = (AliMUONTrackParam*) ((*fTrackParamAtHit)[trackHitIndex]);
998     // TrackHit
999     cout << "TrackParamAtHit: " << trackParamAtHit << " (index: " << trackHitIndex << ")" << endl;
1000     trackParamAtHit->Dump();
1001     hitForRec = trackParamAtHit->GetHitForRecPtr();
1002     // HitForRec
1003     cout << "HitForRec: " << hitForRec << endl;
1004     hitForRec->Dump();
1005   }
1006   return;
1007 }
1008   
1009 //_____________________________________________-
1010 void AliMUONTrack::Print(Option_t*) const
1011 {
1012   /// Printing Track information 
1013
1014   cout << "<AliMUONTrack> No.Clusters=" << setw(2)   << GetNTrackHits() << 
1015       ", Match2Trig=" << setw(1) << GetMatchTrigger()  << 
1016       ", LoTrgNum=" << setw(3) << GetLoTrgNum()  << 
1017     ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) <<  GetChi2MatchTrigger();
1018   cout << Form(" HitTriggerPattern %x",fHitsPatternInTrigCh) << endl;
1019   GetTrackParamAtHit()->First()->Print("FULL");
1020 }
1021
1022 //__________________________________________________________________________
1023 void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt)
1024 {
1025   /// pack the local trigger information and store
1026
1027   if (loCirc < 0 || loCirc > 233) return;
1028
1029   fLocalTrigger = 0;
1030   fLocalTrigger += loCirc;
1031   fLocalTrigger += loStripX << 8;
1032   fLocalTrigger += loStripY << 13;
1033   fLocalTrigger += loDev    << 17;
1034   fLocalTrigger += loLpt    << 22;
1035   fLocalTrigger += loHpt    << 24;
1036
1037 }
1038