From Laurent:
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackK.cxx
CommitLineData
83dbc640 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
b035a148 16/* $Id$ */
83dbc640 17
b035a148 18#include <stdlib.h> // for exit()
83dbc640 19#include <Riostream.h>
20#include <TClonesArray.h>
b035a148 21#include <TArrayD.h>
83dbc640 22#include <TMatrixD.h>
83dbc640 23
30178c30 24#include "AliMUONTrackK.h"
83dbc640 25#include "AliCallf77.h"
26#include "AliMUON.h"
27#include "AliMUONChamber.h"
29f1b13a 28#include "AliMUONTrackReconstructor.h"
ef3eee8c 29#include "AliMagF.h"
83dbc640 30#include "AliMUONSegment.h"
31#include "AliMUONHitForRec.h"
32#include "AliMUONRawCluster.h"
33#include "AliMUONTrackParam.h"
34#include "AliRun.h"
8c343c7c 35#include "AliLog.h"
83dbc640 36
343146bf 37const Int_t AliMUONTrackK::fgkSize = 5;
b21aa6eb 38const Int_t AliMUONTrackK::fgkNSigma = 12;
39const Double_t AliMUONTrackK::fgkChi2max = 100;
343146bf 40const Int_t AliMUONTrackK::fgkTriesMax = 10000;
41const Double_t AliMUONTrackK::fgkEpsilon = 0.002;
42
b21aa6eb 43void mnvertLocal(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail); // from AliMUONTrack
44//void mnvertLocalK(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail);
83dbc640 45
46ClassImp(AliMUONTrackK) // Class implementation in ROOT context
47
b035a148 48Int_t AliMUONTrackK::fgDebug = -1;
83dbc640 49Int_t AliMUONTrackK::fgNOfPoints = 0;
50AliMUON* AliMUONTrackK::fgMUON = NULL;
29f1b13a 51AliMUONTrackReconstructor* AliMUONTrackK::fgTrackReconstructor = NULL;
83dbc640 52TClonesArray* AliMUONTrackK::fgHitForRec = NULL;
b035a148 53//FILE *lun1 = fopen("window.dat","w");
83dbc640 54
55 //__________________________________________________________________________
56AliMUONTrackK::AliMUONTrackK()
b035a148 57 //AZ: TObject()
58 : AliMUONTrack()
83dbc640 59{
60 // Default constructor
61
b21aa6eb 62 fgTrackReconstructor = NULL; // pointer to event reconstructor
83dbc640 63 fgMUON = NULL; // pointer to Muon module
64 fgHitForRec = NULL; // pointer to points
65 fgNOfPoints = 0; // number of points
66
67 fStartSegment = NULL;
68 fTrackHitsPtr = NULL;
69 fNTrackHits = 0;
b035a148 70 fTrackPar = fTrackParNew = NULL;
71 fCovariance = fWeight = NULL;
83dbc640 72 fSkipHit = NULL;
b035a148 73 fParExtrap = fParFilter = fParSmooth = NULL;
74 fCovExtrap = fCovFilter = NULL;
75 fJacob = NULL;
76 fSteps = NULL; fNSteps = 0;
77 fChi2Array = NULL;
78 fChi2Smooth = NULL;
83dbc640 79
80 return;
81}
82
83 //__________________________________________________________________________
29f1b13a 84AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructor *TrackReconstructor, TClonesArray *hitForRec)
b035a148 85 //AZ: TObject()
86 : AliMUONTrack()
83dbc640 87{
88 // Constructor
89
29f1b13a 90 if (!TrackReconstructor) return;
b21aa6eb 91 fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
83dbc640 92 fgMUON = (AliMUON*) gAlice->GetModule("MUON"); // pointer to Muon module
93 fgHitForRec = hitForRec; // pointer to points
94 fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
95
96 fStartSegment = NULL;
97 fTrackHitsPtr = NULL;
98 fNTrackHits = 0;
99 fChi2 = 0;
b035a148 100 fTrackPar = fTrackParNew = NULL;
101 fCovariance = fWeight = NULL;
83dbc640 102 fSkipHit = NULL;
b035a148 103 fParExtrap = fParFilter = fParSmooth = NULL;
104 fCovExtrap = fCovFilter = NULL;
105 fJacob = NULL;
106 fSteps = NULL; fNSteps = 0;
107 fChi2Array = NULL;
108 fChi2Smooth = NULL;
83dbc640 109}
110
111 //__________________________________________________________________________
112AliMUONTrackK::AliMUONTrackK(AliMUONSegment *segment)
b035a148 113 //AZ: TObject()
29f1b13a 114 : AliMUONTrack(segment, segment, fgTrackReconstructor)
83dbc640 115{
116 // Constructor from a segment
117 Double_t dX, dY, dZ;
118 AliMUONHitForRec *hit1, *hit2;
119 AliMUONRawCluster *clus;
120 TClonesArray *rawclusters;
121
122 fStartSegment = segment;
123 fRecover = 0;
b035a148 124 fSkipHit = NULL;
83dbc640 125 // Pointers to hits from the segment
126 hit1 = segment->GetHitForRec1();
127 hit2 = segment->GetHitForRec2();
128 hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
129 hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
130 // check sorting in Z
b035a148 131 if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
83dbc640 132 hit1 = hit2;
133 hit2 = segment->GetHitForRec1();
134 }
135 // memory allocation for the TObjArray of pointers to reconstructed TrackHit's
b035a148 136 fTrackHitsPtr = new TObjArray(13);
83dbc640 137 fNTrackHits = 2;
138 fChi2 = 0;
139 fBPFlag = kFALSE;
343146bf 140 fTrackPar = new TMatrixD(fgkSize,1); // track parameters
141 fTrackParNew = new TMatrixD(fgkSize,1); // track parameters
142 fCovariance = new TMatrixD(fgkSize,fgkSize); // covariance matrix
143 fWeight = new TMatrixD(fgkSize,fgkSize); // weight matrix (inverse of covariance)
83dbc640 144
145 // Fill array of track parameters
146 if (hit1->GetChamberNumber() > 7) {
147 // last tracking station
148 (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
149 (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
150 fPosition = hit1->GetZ(); // z
b035a148 151 fTrackHitsPtr->Add(hit2); // add hit 2
152 fTrackHitsPtr->Add(hit1); // add hit 1
153 //AZ(Z->-Z) fTrackDir = -1;
154 fTrackDir = 1;
83dbc640 155 } else {
156 // last but one tracking station
157 (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
158 (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
159 fPosition = hit2->GetZ(); // z
b035a148 160 fTrackHitsPtr->Add(hit1); // add hit 1
161 fTrackHitsPtr->Add(hit2); // add hit 2
162 //AZ(Z->-Z) fTrackDir = 1;
163 fTrackDir = -1;
83dbc640 164 }
165 dZ = hit2->GetZ() - hit1->GetZ();
166 dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
167 dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
168 (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
b21aa6eb 169 if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
170 (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
171 (*fTrackPar)(2,0) -= TMath::Pi();
29f1b13a 172 (*fTrackPar)(4,0) = 1/fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()); // 1/Pt
83dbc640 173 (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
b035a148 174 // Evaluate covariance (and weight) matrix
175 EvalCovariance(dZ);
176
177 // For smoother
178 fParExtrap = new TObjArray(15);
179 fParFilter = new TObjArray(15);
180 fCovExtrap = new TObjArray(15);
181 fCovFilter = new TObjArray(15);
182 fJacob = new TObjArray(15);
183 fSteps = new TArrayD(15);
184 fNSteps = 0;
185 fChi2Array = new TArrayD(13);
186 fChi2Smooth = NULL;
187 fParSmooth = NULL;
188
189 if (fgDebug < 0 ) return;
29f1b13a 190 cout << fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()) << " " << 1/(*fTrackPar)(4,0) << " ";
191 if (fgTrackReconstructor->GetRecTrackRefHits()) {
29fc2c86 192 // from track ref. hits
193 cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[0]))->GetTTRTrack() << "<-->" << ((AliMUONHitForRec*)((*fTrackHitsPtr)[1]))->GetTTRTrack() << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
83dbc640 194 } else {
195 // from raw clusters
196 for (Int_t i=0; i<2; i++) {
197 hit1 = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i]);
29f1b13a 198 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
83dbc640 199 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
b21aa6eb 200 cout << clus->GetTrack(1);
201 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
83dbc640 202 if (i == 0) cout << " <--> ";
203 }
b035a148 204 cout << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
83dbc640 205 }
83dbc640 206}
207
208 //__________________________________________________________________________
209AliMUONTrackK::~AliMUONTrackK()
210{
211 // Destructor
212
213 if (fTrackHitsPtr) {
214 delete fTrackHitsPtr; // delete the TObjArray of pointers to TrackHit's
215 fTrackHitsPtr = NULL;
216 }
b035a148 217 if (fTrackPar) {
218 delete fTrackPar; delete fTrackParNew; delete fCovariance;
219 delete fWeight;
220 }
221
222 if (fSteps) delete fSteps;
223 if (fChi2Array) delete fChi2Array;
224 if (fChi2Smooth) delete fChi2Smooth;
225 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
226 // Delete only matrices not shared by several tracks
227 if (!fParExtrap) return;
228
229 Int_t id = 0;
230 for (Int_t i=0; i<fNSteps; i++) {
231 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
232 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
233 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
234 if (id > 1) {
235 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
236 fParExtrap->RemoveAt(i);
237 }
238 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
239 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
240 id = fParFilter->UncheckedAt(i)->GetUniqueID();
241 if (id > 1) {
242 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
243 fParFilter->RemoveAt(i);
244 }
245 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
246 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
247 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
248 if (id > 1) {
249 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
250 fCovExtrap->RemoveAt(i);
251 }
252
253 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
254 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
255 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
256 if (id > 1) {
257 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
258 fCovFilter->RemoveAt(i);
259 }
260 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
261 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
262 id = fJacob->UncheckedAt(i)->GetUniqueID();
263 if (id > 1) {
264 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
265 fJacob->RemoveAt(i);
266 }
267 }
268 /*
269 for (Int_t i=0; i<fNSteps; i++) {
270 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
271 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
272 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
273 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
274 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
275 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
276 }
277 */
278 fParExtrap->Delete(); fParFilter->Delete();
279 fCovExtrap->Delete(); fCovFilter->Delete();
280 fJacob->Delete();
281 delete fParExtrap; delete fParFilter;
282 delete fCovExtrap; delete fCovFilter;
283 delete fJacob;
83dbc640 284}
285
286 //__________________________________________________________________________
30178c30 287AliMUONTrackK::AliMUONTrackK (const AliMUONTrackK& source)
b035a148 288 //AZ: TObject(source)
289 : AliMUONTrack(source)
83dbc640 290{
30178c30 291// Protected copy constructor
8c343c7c 292 AliFatal("Not implemented.");
83dbc640 293}
294
295 //__________________________________________________________________________
296AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
297{
298 // Assignment operator
299 // Members
300 if(&source == this) return *this;
30178c30 301
302 // base class assignement
b035a148 303 //AZ TObject::operator=(source);
304 AliMUONTrack::operator=(source);
30178c30 305
83dbc640 306 fStartSegment = source.fStartSegment;
307 fNTrackHits = source.fNTrackHits;
308 fChi2 = source.fChi2;
309 fPosition = source.fPosition;
310 fPositionNew = source.fPositionNew;
311 fTrackDir = source.fTrackDir;
312 fBPFlag = source.fBPFlag;
313 fRecover = source.fRecover;
314 fSkipHit = source.fSkipHit;
315
316 // Pointers
317 fTrackHitsPtr = new TObjArray(*source.fTrackHitsPtr);
318 //source.fTrackHitsPtr->Dump();
319 //fTrackHitsPtr->Dump();
320
321 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
322 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
323 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
324 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
325
b035a148 326 // For smoother
327 fParExtrap = new TObjArray(*source.fParExtrap);
328 fParFilter = new TObjArray(*source.fParFilter);
329 fCovExtrap = new TObjArray(*source.fCovExtrap);
330 fCovFilter = new TObjArray(*source.fCovFilter);
331 fJacob = new TObjArray(*source.fJacob);
332 fSteps = new TArrayD(*source.fSteps);
333 fNSteps = source.fNSteps;
334 fChi2Array = NULL;
335 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
336 fChi2Smooth = NULL;
337 fParSmooth = NULL;
338
339 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
340 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
341 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
342 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
343 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
344 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
345 }
83dbc640 346 return *this;
347}
348
349 //__________________________________________________________________________
350void AliMUONTrackK::EvalCovariance(Double_t dZ)
351{
352 // Evaluate covariance (and weight) matrix for track candidate
353 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
354
b21aa6eb 355 dZ = -dZ;
29f1b13a 356 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
357 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
83dbc640 358
359 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
360
361 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
362
363 tanA = TMath::Tan((*fTrackPar)(2,0));
364 dAdY = 1/(1+tanA*tanA)/dZ;
365 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
366 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
367 (*fWeight)(2,0) = (*fWeight)(0,2);
368
369 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
370 tanB = TMath::Tan((*fTrackPar)(3,0));
371 dBdX = 1/(1+tanB*tanB)/rad;
372 dBdY = 0; // neglect
373 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
374 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
375 (*fWeight)(3,1) = (*fWeight)(1,3);
376
377 //(*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.2)*((*fTrackPar)(4,0)*0.2); // error 20%
378 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
379
380 // check whether the Invert method returns flag if matrix cannot be inverted,
381 // and do not calculate the Determinant in that case !!!!
382 if (fWeight->Determinant() != 0) {
83dbc640 383 // fWeight->Invert();
b21aa6eb 384 Int_t ifail;
385 //mnvertLocalK(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifailWeight);
386 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 387 } else {
8c343c7c 388 AliWarning(" Determinant fWeight=0:");
83dbc640 389 }
390 return;
391}
392
393 //__________________________________________________________________________
394Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
395{
396 // Follows track through detector stations
397 Bool_t miss, success;
b035a148 398 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
399 Int_t ihit, firstIndx, lastIndx, currIndx;
83dbc640 400 Double_t zEnd, dChi2;
401 AliMUONHitForRec *hitAdd, *firstHit, *lastHit, *hit;
402 AliMUONRawCluster *clus;
403 TClonesArray *rawclusters;
404 hit = 0; clus = 0; rawclusters = 0;
405
b035a148 406 miss = success = kTRUE;
83dbc640 407 Int_t endOfProp = 0;
b035a148 408 iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
83dbc640 409 iMin = TMath::Min(ichamEnd,ichamBeg);
410 iMax = TMath::Max(ichamEnd,ichamBeg);
411 ichamb = ichamBeg;
412 ichambOK = ichamb;
413
83dbc640 414 if (Back) {
415 // backpropagation
b035a148 416 currIndx = 1;
417 if (((AliMUONHitForRec*)fTrackHitsPtr->First())->GetChamberNumber() != ichamb) currIndx = 0;
418 } else if (fRecover) {
419 hit = GetHitLastOk();
420 currIndx = fTrackHitsPtr->IndexOf(hit);
421 if (currIndx < 0) hit = fStartSegment->GetHitForRec1(); // for station 3
422 Back = kTRUE;
423 ichamb = hit->GetChamberNumber();
424 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
425 // start from the last point or outlier
426 // remove the skipped hit
427 fTrackHitsPtr->Remove(fSkipHit); // remove hit
428 fNTrackHits --;
429 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
430 if (fRecover == 1) {
431 // recovery
432 Back = kFALSE;
433 fRecover = 0;
434 ichambOK = ((AliMUONHitForRec*)((*fTrackHitsPtr)[fNTrackHits-1]))->GetChamberNumber();
435 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHitsPtr)[0]))->GetChamberNumber() == 6) ichambOK = 6;
436 currIndx = fgHitForRec->IndexOf(fSkipHit);
437 } else {
438 // outlier
439 fTrackHitsPtr->Compress();
440 }
441 } // if (hit == fSkipHit)
442 else if (currIndx < 0) currIndx = fTrackHitsPtr->IndexOf(hit);
443 } // else if (fRecover)
444 else {
445 // Get indices of the 1'st and last hits on the track candidate
446 firstHit = (AliMUONHitForRec*) fTrackHitsPtr->First();
447 lastHit = (AliMUONHitForRec*) fTrackHitsPtr->Last();
448 firstIndx = fgHitForRec->IndexOf(firstHit);
449 lastIndx = fgHitForRec->IndexOf(lastHit);
450 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
83dbc640 451 }
452
453 while (ichamb>=iMin && ichamb<=iMax) {
454 // Find the closest hit in Z, not belonging to the current plane
455 if (Back) {
456 // backpropagation
b035a148 457 if (currIndx < fNTrackHits) {
458 hitAdd = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(currIndx);
459 zEnd = hitAdd->GetZ();
460 //AZ(z->-z) } else zEnd = -9999;
461 } else zEnd = 9999;
83dbc640 462 } else {
b035a148 463 //AZ(Z->-Z) zEnd = -9999;
464 zEnd = 9999;
83dbc640 465 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
466 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
467 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
468 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
469 zEnd = hitAdd->GetZ();
470 currIndx = ihit;
471 break;
472 }
473 }
474 }
b035a148 475 //AZ(Z->-Z) if (zEnd<-999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
476 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
83dbc640 477 else {
b035a148 478 // Check if there is a chamber without hits
479 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
480 if (!Back && zEnd<999) currIndx -= iFB;
83dbc640 481 ichamb += iFB;
482 zEnd = (&(fgMUON->Chamber(ichamb)))->Z();
483 miss = kTRUE;
484 } else {
485 ichamb = hitAdd->GetChamberNumber();
486 miss = kFALSE;
487 }
488 }
489 if (ichamb<iMin || ichamb>iMax) break;
490 // Check for missing station
491 if (!Back) {
492 dChamb = TMath::Abs(ichamb-ichambOK);
b035a148 493 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
494 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
495 if (zEnd > 999) dStatMiss++;
496 if (dStatMiss > 1) {
497 // missing station - abandon track
498 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
499 if (fgDebug >= 10) {
83dbc640 500 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
501 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
502 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
503 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
504 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
29fc2c86 505 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
83dbc640 506 }
b035a148 507 cout << endl;
83dbc640 508 cout << fNTrackHits << endl;
509 for (Int_t i1=0; i1<fNTrackHits; i1++) {
510 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
511 printf(" * %d %10.4f %10.4f %10.4f",
b035a148 512 hit->GetChamberNumber(), hit->GetBendingCoor(),
83dbc640 513 hit->GetNonBendingCoor(), hit->GetZ());
29f1b13a 514 if (fgTrackReconstructor->GetRecTrackRefHits()) {
29fc2c86 515 // from track ref. hits
516 printf(" %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack());
83dbc640 517 } else {
518 // from raw clusters
29f1b13a 519 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
83dbc640 520 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
b035a148 521 printf("%3d", clus->GetTrack(1)-1);
522 if (clus->GetTrack(2) != 0) printf("%3d \n", clus->GetTrack(2)-1);
83dbc640 523 else printf("\n");
524 }
525 }
b035a148 526 } // if (fgDebug >= 10)
527 if (fNTrackHits>2 && fRecover==0) Recover(); // try to recover track later
528 return kFALSE;
529 } // if (dStatMiss > 1)
530 } // if (!Back)
83dbc640 531 if (endOfProp != 0) break;
532
533 // propagate to the found Z
534
535 // Check if track steps into dipole
b035a148 536 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
537 if (fPosition<zDipole2 && zEnd>zDipole2) {
83dbc640 538 //LinearPropagation(zDipole2-zBeg);
539 ParPropagation(zDipole2);
540 MSThin(1); // multiple scattering in the chamber
b035a148 541 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
83dbc640 542 fPosition = fPositionNew;
543 *fTrackPar = *fTrackParNew;
544 //MagnetPropagation(zEnd);
545 ParPropagation(zEnd);
b035a148 546 WeightPropagation(zEnd, kTRUE);
83dbc640 547 fPosition = fPositionNew;
548 }
549 // Check if track steps out of dipole
b035a148 550 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
551 else if (fPosition<zDipole1 && zEnd>zDipole1) {
83dbc640 552 //MagnetPropagation(zDipole1-zBeg);
553 ParPropagation(zDipole1);
554 MSThin(1); // multiple scattering in the chamber
b035a148 555 WeightPropagation(zDipole1, kTRUE);
83dbc640 556 fPosition = fPositionNew;
557 *fTrackPar = *fTrackParNew;
558 //LinearPropagation(zEnd-zDipole1);
559 ParPropagation(zEnd);
b035a148 560 WeightPropagation(zEnd, kTRUE);
83dbc640 561 fPosition = fPositionNew;
562 } else {
563 ParPropagation(zEnd);
564 //MSThin(1); // multiple scattering in the chamber
565 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
b035a148 566 WeightPropagation(zEnd, kTRUE);
83dbc640 567 fPosition = fPositionNew;
568 }
569
570 // Add measurement
571 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
572 // recovered track - remove the hit
573 miss = kTRUE;
b035a148 574 ichamb = fSkipHit->GetChamberNumber();
575 // remove the skipped hit
576 fTrackHitsPtr->Remove(fSkipHit);
577 fNTrackHits --;
578 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
83dbc640 579 Back = kFALSE;
b035a148 580 fRecover =0;
83dbc640 581 ichambOK = ((AliMUONHitForRec*)((*fTrackHitsPtr)[fNTrackHits-1]))->GetChamberNumber();
582 currIndx = fgHitForRec->IndexOf(fSkipHit);
583 }
584
585 if (Back && !miss) {
586 // backward propagator
b035a148 587 if (currIndx) {
588 TMatrixD pointWeight(fgkSize,fgkSize);
589 TMatrixD point(fgkSize,1);
590 TMatrixD trackParTmp = point;
591 point(0,0) = hitAdd->GetBendingCoor();
592 point(1,0) = hitAdd->GetNonBendingCoor();
593 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
594 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
595 TryPoint(point,pointWeight,trackParTmp,dChi2);
596 *fTrackPar = trackParTmp;
597 *fWeight += pointWeight;
598 //AZ(z->-z) if (fTrackDir < 0) AddMatrices (this, dChi2, hitAdd);
599 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
600 fChi2 += dChi2; // Chi2
601 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
83dbc640 602 if (ichamb==ichamEnd) break;
b035a148 603 currIndx ++;
83dbc640 604 } else {
605 // forward propagator
606 if (miss || !FindPoint(ichamb,zEnd,currIndx,iFB,hitAdd)) {
607 // missing point
608 *fTrackPar = *fTrackParNew;
609 } else {
610 //add point
b035a148 611 fTrackHitsPtr->Add(hitAdd); // add hit
83dbc640 612 fNTrackHits ++;
613 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
614 ichambOK = ichamb;
615 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
616 }
617 }
618 } // while
b035a148 619 if (fgDebug > 0) cout << fNTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
29f1b13a 620 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
83dbc640 621 return success;
622}
623
624 //__________________________________________________________________________
625void AliMUONTrackK::ParPropagation(Double_t zEnd)
626{
627 // Propagation of track parameters to zEnd
628 Int_t iFB, nTries;
629 Double_t dZ, step, distance, charge;
630 Double_t vGeant3[7], vGeant3New[7];
b21aa6eb 631 AliMUONTrackParam trackParam;
632
83dbc640 633 nTries = 0;
634 // First step using linear extrapolation
635 dZ = zEnd - fPosition;
83dbc640 636 fPositionNew = fPosition;
637 *fTrackParNew = *fTrackPar;
b035a148 638 if (dZ == 0) return; //AZ ???
639 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
640 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
641 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
642 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
83dbc640 643 SetGeantParam(vGeant3,iFB);
b21aa6eb 644 //fTrackParNew->Print();
83dbc640 645
646 // Check if overstep
647 do {
648 step = TMath::Abs(step);
649 // Propagate parameters
b21aa6eb 650 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
651 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
83dbc640 652 distance = zEnd - vGeant3New[2];
653 step *= dZ/(vGeant3New[2]-fPositionNew);
654 nTries ++;
343146bf 655 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
83dbc640 656
657 GetFromGeantParam(vGeant3New,iFB);
b21aa6eb 658 //fTrackParNew->Print();
83dbc640 659
b035a148 660 // Position adjustment (until within tolerance)
343146bf 661 while (TMath::Abs(distance) > fgkEpsilon) {
83dbc640 662 dZ = zEnd - fPositionNew;
663 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
664 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
665 step = TMath::Abs(step);
666 SetGeantParam(vGeant3,iFB);
667 do {
668 // binary search
669 // Propagate parameters
b21aa6eb 670 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
671 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
83dbc640 672 distance = zEnd - vGeant3New[2];
673 step /= 2;
674 nTries ++;
343146bf 675 if (nTries > fgkTriesMax) {
83dbc640 676 cout << " ***** ParPropagation: too many tries " << nTries << endl;
b035a148 677 AliFatal("Too many tries.");
83dbc640 678 }
679 } while (distance*iFB < 0);
680
681 GetFromGeantParam(vGeant3New,iFB);
682 }
683 //cout << nTries << endl;
b21aa6eb 684 //fTrackParNew->Print();
83dbc640 685 return;
686}
687/*
688 //__________________________________________________________________________
689void AliMUONTrackK::WeightPropagation(void)
690{
691 // Propagation of the weight matrix
692 // W = DtWD, where D is Jacobian
693
694 // !!! not implemented TMatrixD weight1(*fJacob,TMatrixD::kAtBA,*fWeight); // DtWD
695 TMatrixD weight1(*fWeight,TMatrixD::kMult,*fJacob); // WD
696 *fWeight = TMatrixD(*fJacob,TMatrixD::kTransposeMult,weight1); // DtWD
697 return;
698}
699*/
700 //__________________________________________________________________________
b035a148 701void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
83dbc640 702{
703 // Propagation of the weight matrix
704 // W = DtWD, where D is Jacobian
705 Int_t i, j;
706 Double_t dPar;
707
30178c30 708 TMatrixD jacob(fgkSize,fgkSize);
709 jacob = 0;
83dbc640 710
711 // Save initial and propagated parameters
712 TMatrixD trackPar0 = *fTrackPar;
713 TMatrixD trackParNew0 = *fTrackParNew;
83dbc640 714
715 // Get covariance matrix
716 *fCovariance = *fWeight;
717 // check whether the Invert method returns flag if matrix cannot be inverted,
718 // and do not calculate the Determinant in that case !!!!
719 if (fCovariance->Determinant() != 0) {
720 // fCovariance->Invert();
b21aa6eb 721 Int_t ifail;
722 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
723 //fCovariance->Print();
83dbc640 724 } else {
8c343c7c 725 AliWarning(" Determinant fCovariance=0:");
83dbc640 726 }
727
b21aa6eb 728 // Loop over parameters to find change of the propagated vs initial ones
343146bf 729 for (i=0; i<fgkSize; i++) {
83dbc640 730 dPar = TMath::Sqrt((*fCovariance)(i,i));
b21aa6eb 731 *fTrackPar = trackPar0;
732 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
83dbc640 733 (*fTrackPar)(i,0) += dPar;
734 ParPropagation(zEnd);
343146bf 735 for (j=0; j<fgkSize; j++) {
b21aa6eb 736 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
83dbc640 737 }
738 }
739
83dbc640 740 //trackParNew0.Print();
30178c30 741 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
83dbc640 742 //par1.Print();
b21aa6eb 743 TMatrixD jacob0 = jacob;
30178c30 744 if (jacob.Determinant() != 0) {
b21aa6eb 745 jacob.Invert();
83dbc640 746 } else {
b21aa6eb 747 AliWarning(" Determinant jacob=0:");
83dbc640 748 }
30178c30 749 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
750 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
83dbc640 751
752 // Restore initial and propagated parameters
753 *fTrackPar = trackPar0;
754 *fTrackParNew = trackParNew0;
b035a148 755
756 // Save for smoother
757 if (!smooth) return; // do not use smoother
758 //AZ(z->-z) if (fTrackDir > 0) return; // only for propagation towards int. point
759 if (fTrackDir < 0) return; // only for propagation towards int. point
760 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
761 fParExtrap->Add(tmp);
762 tmp->SetUniqueID(1);
763 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
764 fParFilter->Add(tmp);
765 tmp->SetUniqueID(1);
766 *fCovariance = *fWeight;
767 if (fCovariance->Determinant() != 0) {
b21aa6eb 768 Int_t ifail;
769 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
b035a148 770 } else {
771 AliWarning(" Determinant fCovariance=0:");
772 }
773 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
774 fCovExtrap->Add(tmp);
775 tmp->SetUniqueID(1);
776 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
777 fCovFilter->Add(tmp);
778 tmp->SetUniqueID(1);
b21aa6eb 779 tmp = new TMatrixD(jacob0); // Jacobian
b035a148 780 fJacob->Add(tmp);
781 tmp->SetUniqueID(1);
782 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
783 fSteps->AddAt(fPositionNew,fNSteps++);
784 if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
83dbc640 785 return;
786}
787
788 //__________________________________________________________________________
789Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd)
790{
791 // Picks up point within a window for the chamber No ichamb
792 // Split the track if there are more than 1 hit
793 Int_t ihit, nRecTracks;
30178c30 794 Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
83dbc640 795 TClonesArray *trackPtr;
796 AliMUONHitForRec *hit, *hitLoop;
797 AliMUONTrackK *trackK;
798
30178c30 799 Bool_t ok = kFALSE;
29f1b13a 800 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
801 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
83dbc640 802 *fCovariance = *fWeight;
803 // check whether the Invert method returns flag if matrix cannot be inverted,
804 // and do not calculate the Determinant in that case !!!!
805 if (fCovariance->Determinant() != 0) {
806 // fCovariance->Invert();
b21aa6eb 807 Int_t ifail;
808 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 809 } else {
b21aa6eb 810 AliWarning(" Determinant fCovariance=0:");
83dbc640 811 }
30178c30 812 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
813 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
83dbc640 814 // Loop over all hits and take hits from the chamber
343146bf 815 TMatrixD pointWeight(fgkSize,fgkSize);
83dbc640 816 TMatrixD saveWeight = pointWeight;
817 TMatrixD pointWeightTmp = pointWeight;
343146bf 818 TMatrixD point(fgkSize,1);
83dbc640 819 TMatrixD trackPar = point;
820 TMatrixD trackParTmp = point;
821 Int_t nHitsOK = 0;
b035a148 822 Double_t zLast;
823 zLast = ((AliMUONHitForRec*)fTrackHitsPtr->Last())->GetZ();
83dbc640 824
825 for (ihit=currIndx; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
826 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
827 if (hit->GetChamberNumber() == ichamb) {
828 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
829 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
b21aa6eb 830 //if (TMath::Abs(hit->GetZ()-zEnd) > 0.1) {
831 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
83dbc640 832 // adjust position: for multiple hits in the chamber
833 // (mostly (only?) for GEANT hits)
b21aa6eb 834 cout << " ******* adjust " << zEnd << " " << hit->GetZ() << endl;
83dbc640 835 zEnd = hit->GetZ();
836 *fTrackPar = *fTrackParNew;
837 ParPropagation(zEnd);
b035a148 838 WeightPropagation(zEnd, kTRUE);
83dbc640 839 fPosition = fPositionNew;
840 *fTrackPar = *fTrackParNew;
841 // Get covariance
842 *fCovariance = *fWeight;
843 if (fCovariance->Determinant() != 0) {
b21aa6eb 844 Int_t ifail;
845 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 846 } else {
b21aa6eb 847 AliWarning(" Determinant fCovariance=0:" );
83dbc640 848 }
849 }
850 y = hit->GetBendingCoor();
851 x = hit->GetNonBendingCoor();
30178c30 852 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
853 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
b035a148 854
b21aa6eb 855 // windowB = TMath::Min (windowB,5.);
856 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
b035a148 857 /*
858 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
859 windowB = TMath::Min (windowB,0.5);
860 windowNonB = TMath::Min (windowNonB,3.);
861 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
862 windowB = TMath::Min (windowB,1.5);
863 windowNonB = TMath::Min (windowNonB,3.);
864 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
865 windowB = TMath::Min (windowB,4.);
866 windowNonB = TMath::Min (windowNonB,6.);
867 }
868 */
869
870 // Test
871 /*
872 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
873 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
874 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
875 } else {
876 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
877 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
878 }
879 */
880
881 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
30178c30 882 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
883 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
b035a148 884 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
885 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
29fc2c86 886 // hit->GetTrackRefSignal() == 1) { // just for test
83dbc640 887 // Vector of measurements and covariance matrix
b21aa6eb 888 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
83dbc640 889 point.Zero();
890 point(0,0) = y;
891 point(1,0) = x;
892 pointWeight(0,0) = 1/hit->GetBendingReso2();
893 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
894 TryPoint(point,pointWeight,trackPar,dChi2);
29f1b13a 895 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
30178c30 896 ok = kTRUE;
83dbc640 897 nHitsOK++;
898 //if (nHitsOK > -1) {
899 if (nHitsOK == 1) {
900 // Save current members
901 saveWeight = *fWeight;
902 savePosition = fPosition;
903 // temporary storage for the current track
904 dChi2Tmp = dChi2;
905 trackParTmp = trackPar;
906 pointWeightTmp = pointWeight;
907 hitAdd = hit;
908 } else {
909 // branching: create a new track
29f1b13a 910 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
911 nRecTracks = fgTrackReconstructor->GetNRecTracks();
b035a148 912 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
83dbc640 913 *trackK = *this;
29f1b13a 914 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
29fc2c86 915 if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNTrackHits << " " << nRecTracks << endl;
83dbc640 916 trackK->fRecover = 0;
917 *(trackK->fTrackPar) = trackPar;
918 *(trackK->fWeight) += pointWeight;
919 trackK->fChi2 += dChi2;
b035a148 920 // Check
921 /*
922 *(trackK->fCovariance) = *(trackK->fWeight);
923 if (trackK->fCovariance->Determinant() != 0) {
b21aa6eb 924 Int_t ifail;
925 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
b035a148 926 }
927 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
928 */
929 // Add filtered matrices for the smoother
930 //AZ(z->-z) if (fTrackDir < 0) {
931 if (fTrackDir > 0) {
932 if (nHitsOK > 2) { // check for position adjustment
933 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
934 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
935 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
936 RemoveMatrices(trackK);
937 cout << " *** Position adjustment 1 " << hit->GetZ() << " "
938 << (*trackK->fSteps)[i] << endl;
b21aa6eb 939 AliFatal(" Position adjustment 1.");
b035a148 940 }
941 else break;
942 }
943 }
944 AddMatrices (trackK, dChi2, hit);
945 }
83dbc640 946 // Mark hits as being on 2 tracks
947 for (Int_t i=0; i<fNTrackHits; i++) {
948 hitLoop = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i]);
949 hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
b035a148 950 if (fgDebug >=10) {
951 cout << " ** ";
952 cout << hitLoop->GetChamberNumber() << " ";
953 cout << hitLoop->GetBendingCoor() << " ";
954 cout << hitLoop->GetNonBendingCoor() << " ";
955 cout << hitLoop->GetZ() << " " << " ";
29fc2c86 956 cout << hitLoop->GetTrackRefSignal() << " " << " ";
957 cout << hitLoop->GetTTRTrack() << endl;
b035a148 958 printf(" ** %d %10.4f %10.4f %10.4f %d %d \n",
959 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
960 hitLoop->GetNonBendingCoor(), hitLoop->GetZ(),
29fc2c86 961 hitLoop->GetTrackRefSignal(), hitLoop->GetTTRTrack());
b035a148 962 }
83dbc640 963 }
964 //add point
b035a148 965 trackK->fTrackHitsPtr->Add(hit); // add hit
83dbc640 966 trackK->fNTrackHits ++;
967 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
968 if (ichamb == 9) {
969 // the last chamber
b035a148 970 //AZ(z->-z) trackK->fTrackDir = -1;
971 trackK->fTrackDir = 1;
83dbc640 972 trackK->fBPFlag = kTRUE;
973 }
974 }
975 }
976 }
977 } else break; // different chamber
978 } // for (ihit=currIndx;
30178c30 979 if (ok) {
b035a148 980 // Restore members
83dbc640 981 *fTrackPar = trackParTmp;
982 *fWeight = saveWeight;
983 *fWeight += pointWeightTmp;
984 fChi2 += dChi2Tmp; // Chi2
83dbc640 985 fPosition = savePosition;
b035a148 986 // Add filtered matrices for the smoother
987 //AZ(z->-z) if (fTrackDir < 0) {
988 if (fTrackDir > 0) {
989 for (Int_t i=fNSteps-1; i>=0; i--) {
990 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
991 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
992 RemoveMatrices(this);
b21aa6eb 993 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
b035a148 994 }
995 else break;
996 } // for (Int_t i=fNSteps-1;
997 AddMatrices (this, dChi2Tmp, hitAdd);
998 /*
999 if (nHitsOK > 1) {
1000 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1001 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1002 }
1003 */
1004 } // if (fTrackDir > 0)
83dbc640 1005 }
30178c30 1006 return ok;
83dbc640 1007}
1008
1009 //__________________________________________________________________________
1010void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1011{
1012 // Adds a measurement point (modifies track parameters and computes
1013 // change of Chi2)
1014
1015 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1016 TMatrixD wu = *fWeight;
1017 wu += pointWeight; // W+U
1018 trackParTmp = point;
1019 trackParTmp -= *fTrackParNew; // m-p
1020 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1021 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1022 right += right1; // U(m-p) + (W+U)p
1023
1024 // check whether the Invert method returns flag if matrix cannot be inverted,
1025 // and do not calculate the Determinant in that case !!!!
1026 if (wu.Determinant() != 0) {
83dbc640 1027 // wu.Invert();
b21aa6eb 1028 Int_t ifail;
1029 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1030 } else {
b21aa6eb 1031 AliWarning(" Determinant wu=0:");
83dbc640 1032 }
1033 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1034
1035 right1 = trackParTmp;
1036 right1 -= point; // p'-m
1037 point = trackParTmp;
1038 point -= *fTrackParNew; // p'-p
1039 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1040 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1041 dChi2 = value(0,0);
1042 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1043 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1044 dChi2 += value(0,0);
1045 return;
1046}
1047
1048 //__________________________________________________________________________
1049void AliMUONTrackK::MSThin(Int_t sign)
1050{
1051 // Adds multiple scattering in a thin layer (only angles are affected)
1052 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1053
1054 // check whether the Invert method returns flag if matrix cannot be inverted,
1055 // and do not calculate the Determinant in that case !!!!
1056 if (fWeight->Determinant() != 0) {
1057 //fWeight->Invert(); // covariance
1058
b21aa6eb 1059 Int_t ifail;
1060 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1061 } else {
b21aa6eb 1062 AliWarning(" Determinant fWeight=0:");
83dbc640 1063 }
1064
1065 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1066 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1067 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1068 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1069 velo = 1; // relativistic
29f1b13a 1070 path = TMath::Abs(fgTrackReconstructor->GetChamberThicknessInX0()/cosAlph/cosBeta); // path length
83dbc640 1071 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1072
1073 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1074 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1075 //fWeight->Invert(); // weight
1076
b21aa6eb 1077 Int_t ifail;
1078 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1079 return;
1080}
b035a148 1081
83dbc640 1082 //__________________________________________________________________________
1083void AliMUONTrackK::StartBack(void)
1084{
1085 // Starts backpropagator
1086
1087 fBPFlag = kTRUE;
1088 fChi2 = 0;
343146bf 1089 for (Int_t i=0; i<fgkSize; i++) {
1090 for (Int_t j=0; j<fgkSize; j++) {
83dbc640 1091 if (j==i) (*fWeight)(i,i) /= 100;
1092 //if (j==i) (*fWeight)(i,i) /= fNTrackHits*fNTrackHits;
1093 else (*fWeight)(j,i) = 0;
1094 }
1095 }
b035a148 1096 // Sort hits on track in descending order in abs(z)
1097 SortHits(0, fTrackHitsPtr);
1098}
1099
1100 //__________________________________________________________________________
1101void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1102{
1103 // Sort hits in Z if the seed segment in the last but one station
1104 // (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1105
1106 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1107 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1108 Int_t i = 1, entries = array->GetEntriesFast();
1109 for ( ; i<entries; i++) {
1110 if (iflag) {
1111 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1112 } else {
1113 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1114 if (z < zmax) break;
1115 zmax = z;
1116 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1117 }
1118 }
1119 if (!iflag) i--;
1120 for (Int_t j=0; j<=(i-1)/2; j++) {
1121 TObject *hit = array->UncheckedAt(j);
1122 array->AddAt(array->UncheckedAt(i-j),j);
1123 array->AddAt(hit,i-j);
1124 }
1125 if (fgDebug >= 10) {
1126 for (i=0; i<entries; i++)
1127 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1128 cout << " - Sort" << endl;
1129 }
83dbc640 1130}
1131
1132 //__________________________________________________________________________
1133void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1134{
1135 // Set vector of Geant3 parameters pointed to by "VGeant3"
1136 // from track parameters
1137
1138 VGeant3[0] = (*fTrackParNew)(1,0); // X
1139 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1140 VGeant3[2] = fPositionNew; // Z
b21aa6eb 1141 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1142 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
83dbc640 1143 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1144 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1145}
1146
1147 //__________________________________________________________________________
1148void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1149{
1150 // Get track parameters from vector of Geant3 parameters pointed
1151 // to by "VGeant3"
1152
1153 fPositionNew = VGeant3[2]; // Z
1154 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1155 (*fTrackParNew)(1,0) = VGeant3[0]; // X
b21aa6eb 1156 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1157 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
83dbc640 1158 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1159}
1160
1161 //__________________________________________________________________________
1162void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1163{
1164 // Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1165
b035a148 1166 if (fChi2 > 500) {
83dbc640 1167 cout << " ***** Too high Chi2: " << fChi2 << endl;
b035a148 1168 fChi2 = 500;
83dbc640 1169 }
b035a148 1170 if (iChi2 == 0) fChi2 = fNTrackHits + (500.-fChi2)/501;
1171 else fChi2 = 500 - (fChi2-fNTrackHits)*501;
83dbc640 1172}
1173
1174 //__________________________________________________________________________
1175Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1176{
1177 // "Compare" function to sort with decreasing "track quality".
1178 // Returns +1 (0, -1) if quality of current track
1179 // is smaller than (equal to, larger than) quality of trackK
1180
1181 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1182 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1183 else return(-1);
1184}
1185
1186 //__________________________________________________________________________
30178c30 1187Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
83dbc640 1188{
1189 // Check whether or not to keep current track
1190 // (keep, if it has less than half of common hits with track0)
1191 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1192 AliMUONHitForRec *hit0, *hit1;
1193
1194 hitsInCommon = 0;
1195 nHits0 = track0->fNTrackHits;
1196 nTrackHits2 = fNTrackHits/2;
1197
1198 for (i=0; i<nHits0; i++) {
1199 // Check if hit belongs to several tracks
1200 hit0 = (AliMUONHitForRec*) (*track0->fTrackHitsPtr)[i];
1201 if (hit0->GetNTrackHits() == 1) continue;
1202 for (j=0; j<fNTrackHits; j++) {
1203 hit1 = (AliMUONHitForRec*) (*fTrackHitsPtr)[j];
1204 if (hit1->GetNTrackHits() == 1) continue;
1205 if (hit0 == hit1) {
1206 hitsInCommon++;
1207 if (hitsInCommon >= nTrackHits2) return kFALSE;
1208 break;
1209 }
1210 } // for (j=0;
1211 } // for (i=0;
1212 return kTRUE;
1213}
1214
1215 //__________________________________________________________________________
1216void AliMUONTrackK::Kill(void)
1217{
1218 // Kill track candidate
1219 Int_t i;
1220 AliMUONHitForRec *hit;
1221
1222 if (fTrackHitsPtr) {
1223 // Remove track mark from hits
1224 for (i=0; i<fNTrackHits; i++) {
1225 hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[i];
1226 hit->SetNTrackHits(hit->GetNTrackHits()-1);
1227 }
1228 }
29f1b13a 1229 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
83dbc640 1230}
1231
1232 //__________________________________________________________________________
b035a148 1233void AliMUONTrackK::FillMUONTrack(void)
1234{
1235 // Compute track parameters at hit positions (as for AliMUONTrack)
1236
1237 // Set number of hits per track
1238 ((AliMUONTrack*)this)->SetNTrackHits(fNTrackHits);
1239
1240 // Set track parameters at vertex
1241 AliMUONTrackParam trackParam;
1242 SetTrackParam(&trackParam, fTrackPar, fPosition);
1243 ((AliMUONTrack*)this)->SetTrackParamAtVertex(&trackParam);
1244
1245 // Set track parameters at hits
1246 for (Int_t i = fNTrackHits-1; i>=0; i--) {
1247 if ((*fChi2Smooth)[i] < 0) {
1248 // Propagate through last chambers
1249 trackParam.ExtrapToZ(((AliMUONHitForRec*)((*fTrackHitsPtr)[i]))->GetZ());
1250 } else {
1251 // Take saved info
1252 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHitsPtr)[i]))->GetZ());
1253 }
1254 ((AliMUONTrack*)this)->AddTrackParamAtHit(&trackParam);
b21aa6eb 1255 // Fill array of HitForRec's
1256 ((AliMUONTrack*)this)->AddHitForRecAtHit((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i));
b035a148 1257 }
1258}
1259
1260 //__________________________________________________________________________
1261void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1262{
1263 // Fill AliMUONTrackParam object
1264
1265 trackParam->SetBendingCoor((*par)(0,0));
1266 trackParam->SetNonBendingCoor((*par)(1,0));
1267 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1268 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1269 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1270 trackParam->SetZ(z);
1271}
1272
1273 //__________________________________________________________________________
83dbc640 1274void AliMUONTrackK::Branson(void)
1275{
1276 // Propagates track to the vertex thru absorber using Branson correction
1277 // (makes use of the AliMUONTrackParam class)
1278
b21aa6eb 1279 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1280 AliMUONTrackParam trackParam = AliMUONTrackParam();
b035a148 1281 /*
83dbc640 1282 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1283 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1284 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1285 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1286 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1287 trackParam->SetZ(fPosition);
b035a148 1288 */
b21aa6eb 1289 SetTrackParam(&trackParam, fTrackPar, fPosition);
83dbc640 1290
b21aa6eb 1291 trackParam.ExtrapToVertex(Double_t(0.), Double_t(0.), Double_t(0.));
1292 //trackParam.ExtrapToVertex();
83dbc640 1293
b21aa6eb 1294 (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1295 (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1296 (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1297 (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1298 (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1299 fPosition = trackParam.GetZ();
1300 //delete trackParam;
83dbc640 1301 cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1302
1303 // Get covariance matrix
1304 *fCovariance = *fWeight;
1305 if (fCovariance->Determinant() != 0) {
b21aa6eb 1306 Int_t ifail;
1307 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1308 } else {
b21aa6eb 1309 AliWarning(" Determinant fCovariance=0:");
83dbc640 1310 }
1311}
1312
1313 //__________________________________________________________________________
1314void AliMUONTrackK::GoToZ(Double_t zEnd)
1315{
1316 // Propagates track to given Z
1317
1318 ParPropagation(zEnd);
1319 MSThin(1); // multiple scattering in the chamber
b035a148 1320 WeightPropagation(zEnd, kFALSE);
83dbc640 1321 fPosition = fPositionNew;
1322 *fTrackPar = *fTrackParNew;
1323}
1324
1325 //__________________________________________________________________________
b035a148 1326void AliMUONTrackK::GoToVertex(Int_t iflag)
83dbc640 1327{
1328 // Version 3.08
1329 // Propagates track to the vertex
1330 // All material constants are taken from AliRoot
1331
1332 static Double_t x01[5] = { 24.282, // C
1333 24.282, // C
1334 11.274, // Concrete
1335 1.758, // Fe
1336 1.758}; // Fe (cm)
1337 // inner part theta < 3 degrees
1338 static Double_t x02[5] = { 30413, // Air
1339 24.282, // C
1340 11.274, // Concrete
1341 1.758, // Fe
1342 0.369}; // W (cm)
1343 // z positions of the materials inside the absober outer part theta > 3 degres
b035a148 1344 static Double_t zPos[10] = {-90, -105, -315, -443, -468};
83dbc640 1345
30178c30 1346 Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
83dbc640 1347 AliMUONHitForRec *hit;
1348 AliMUONRawCluster *clus;
1349 TClonesArray *rawclusters;
1350
1351 // First step to the rear end of the absorber
b035a148 1352 //AZ(z->-z) Double_t zRear = 503;
1353 Double_t zRear = -503;
83dbc640 1354 GoToZ(zRear);
1355 Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1356
1357 // Go through absorber
1358 pOld = 1/(*fTrackPar)(4,0);
1359 Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1360 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
b035a148 1361 r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
83dbc640 1362 r0Norm = r0Rear;
b035a148 1363 Double_t p0, cos25, cos60;
1364 if (!iflag) goto vertex;
1365
83dbc640 1366 for (Int_t i=4; i>=0; i--) {
1367 ParPropagation(zPos[i]);
b035a148 1368 WeightPropagation(zPos[i], kFALSE);
83dbc640 1369 dZ = TMath::Abs (fPositionNew-fPosition);
30178c30 1370 if (r0Norm > 1) x0 = x01[i];
1371 else x0 = x02[i];
1372 MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
83dbc640 1373 fPosition = fPositionNew;
1374 *fTrackPar = *fTrackParNew;
1375 r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1376 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
b035a148 1377 r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
83dbc640 1378 }
1379 // Correct momentum for energy losses
1380 pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
b035a148 1381 p0 = pTotal;
1382 cos25 = TMath::Cos(2.5/180*TMath::Pi());
1383 cos60 = TMath::Cos(6.0/180*TMath::Pi());
1384 for (Int_t j=0; j<1; j++) {
83dbc640 1385 /*
1386 if (r0Rear > 1) {
1387 if (p0 < 20) {
1388 deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1389 } else {
1390 deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1391 }
1392 } else {
1393 if (p0 < 20) {
1394 deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1395 } else {
1396 deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1397 }
1398 }
1399 */
b035a148 1400 /*
83dbc640 1401 if (r0Rear < 1) {
1402 //W
1403 if (p0<15) {
1404 deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1405 } else {
1406 deltaP = 3.0643 + 0.01346*p0;
1407 }
b035a148 1408 deltaP *= 0.95;
83dbc640 1409 } else {
1410 //Pb
1411 if (p0<15) {
1412 deltaP = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1413 } else {
1414 deltaP = 2.407 + 0.00702*p0;
1415 }
b035a148 1416 deltaP *= 0.95;
1417 }
1418 */
1419 /*
1420 if (r0Rear < 1) {
1421 //W
1422 if (p0<18) {
1423 deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1424 } else {
1425 deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1426 }
1427 //deltaP += 0.2;
1428 deltaP *= cos25;
1429 } else {
1430 //Pb
1431 if (p0<18) {
1432 deltaP = 2.209 + 0.800e-2*p0;
1433 } else {
1434 deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1435 }
1436 //deltaP += 0.2;
1437 deltaP *= cos60;
1438 }
1439 deltaP *= 1.1;
1440 */
1441 //*
1442 if (r0Rear < 1) {
1443 if (p0 < 20) {
1444 deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1445 } else {
1446 deltaP = 3.0714 + 0.011767 * p0;
1447 }
1448 } else {
1449 if (p0 < 20) {
1450 deltaP = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1451 } else {
1452 deltaP = 2.6069 + 0.0051705 * p0;
1453 }
83dbc640 1454 }
b035a148 1455 deltaP *= 0.9;
1456 //*/
83dbc640 1457
b035a148 1458 p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
83dbc640 1459 }
1460 (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1461
1462 // Go to the vertex
b035a148 1463vertex:
83dbc640 1464 ParPropagation((Double_t)0.);
b035a148 1465 WeightPropagation((Double_t)0., kFALSE);
83dbc640 1466 fPosition = fPositionNew;
1467 //*fTrackPar = *fTrackParNew;
1468 // Add vertex as a hit
343146bf 1469 TMatrixD pointWeight(fgkSize,fgkSize);
1470 TMatrixD point(fgkSize,1);
83dbc640 1471 TMatrixD trackParTmp = point;
1472 point(0,0) = 0; // vertex coordinate - should be taken somewhere
1473 point(1,0) = 0; // vertex coordinate - should be taken somewhere
1474 pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1475 pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1476 TryPoint(point,pointWeight,trackParTmp,dChi2);
1477 *fTrackPar = trackParTmp;
1478 *fWeight += pointWeight;
1479 fChi2 += dChi2; // Chi2
b035a148 1480 if (fgDebug < 0) return; // no output
1481
83dbc640 1482 cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNTrackHits << endl;
1483 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1484 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1485 printf ("%4d", hit->GetChamberNumber());
83dbc640 1486 }
1487 cout << endl;
b035a148 1488 if (fgDebug > 0) {
1489 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1490 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1491 //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetHitNumber() << " ";
1492 //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetZ() << " ";
1493 printf ("%4d", fgHitForRec->IndexOf(hit));
1494 }
1495 cout << endl;
83dbc640 1496 }
29f1b13a 1497 if (fgTrackReconstructor->GetRecTrackRefHits()) {
29fc2c86 1498 // from track ref. hits
83dbc640 1499 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1500 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
29fc2c86 1501 cout << hit->GetTTRTrack() + hit->GetTrackRefSignal()*10000 << " ";
83dbc640 1502 }
1503 } else {
1504 // from raw clusters
1505 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1506 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
29f1b13a 1507 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
83dbc640 1508 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
b21aa6eb 1509 printf ("%4d", clus->GetTrack(1));
83dbc640 1510 }
1511 cout << endl;
1512 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1513 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
29f1b13a 1514 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
83dbc640 1515 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
b21aa6eb 1516 if (clus->GetTrack(2) != -1) printf ("%4d", clus->GetTrack(2));
83dbc640 1517 else printf ("%4s", " ");
83dbc640 1518 }
1519 }
1520 cout << endl;
1521 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1522 //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetHitNumber() << " ";
1523 cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetZ() << " ";
1524 //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))) << " ";
1525 }
1526 cout << endl;
b035a148 1527 for (Int_t i1=0; i1<fNTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1528 cout << endl;
83dbc640 1529 cout << "---------------------------------------------------" << endl;
1530
1531 // Get covariance matrix
b035a148 1532 /* Not needed - covariance matrix is not interesting to anybody
83dbc640 1533 *fCovariance = *fWeight;
1534 if (fCovariance->Determinant() != 0) {
1535 // fCovariance->Invert();
b21aa6eb 1536 Int_t ifail;
1537 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1538 } else {
b21aa6eb 1539 AliWarning(" Determinant fCovariance=0:" );
83dbc640 1540 }
b035a148 1541 */
83dbc640 1542}
1543
1544 //__________________________________________________________________________
30178c30 1545void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
83dbc640 1546{
1547 // Adds multiple scattering in a thick layer for linear propagation
1548
1549 Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1550 Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1551 Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1552 Double_t sinBeta;
1553 sinBeta = TMath::Sin((*fTrackPar)(3,0));
1554 Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1555 Double_t momentum = 1/(*fTrackPar)(4,0);
1556 Double_t velo = 1; // relativistic velocity
b035a148 1557 Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
83dbc640 1558
1559 // Projected scattering angle
30178c30 1560 Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0));
83dbc640 1561 Double_t theta02 = theta0*theta0;
1562 Double_t dl2 = step*step/2*theta02;
1563 Double_t dl3 = dl2*step*2/3;
1564
1565 //Derivatives
1566 Double_t dYdT = 1/cosAlph;
1567 Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1568 Double_t dXdT = tanAlph*tanBeta;
1569 //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1570 Double_t dXdB = 1/cosBeta;
1571 Double_t dAdT = 1/cosBeta;
1572 Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1573
1574 // Get covariance matrix
1575 *fCovariance = *fWeight;
1576 if (fCovariance->Determinant() != 0) {
1577 // fCovariance->Invert();
b21aa6eb 1578 Int_t ifail;
1579 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1580 } else {
b21aa6eb 1581 AliWarning(" Determinant fCovariance=0:" );
83dbc640 1582 }
1583
1584 (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1585 (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1586 (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1587 (*fCovariance)(3,3) += theta02*step; // <bb>
1588
1589 (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1590 (*fCovariance)(1,0) = (*fCovariance)(0,1);
1591
1592 (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1593 (*fCovariance)(2,0) = (*fCovariance)(0,2);
1594
1595 (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1596 (*fCovariance)(3,0) = (*fCovariance)(0,3);
1597
b21aa6eb 1598 (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
83dbc640 1599 (*fCovariance)(2,1) = (*fCovariance)(1,2);
1600
1601 (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1602 (*fCovariance)(3,1) = (*fCovariance)(1,3);
1603
1604 (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1605 (*fCovariance)(3,2) = (*fCovariance)(2,3);
1606
1607 // Get weight matrix
1608 *fWeight = *fCovariance;
1609 if (fWeight->Determinant() != 0) {
1610 // fWeight->Invert();
b21aa6eb 1611 Int_t ifail;
1612 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1613 } else {
b21aa6eb 1614 AliWarning(" Determinant fWeight=0:");
83dbc640 1615 }
1616}
1617
1618 //__________________________________________________________________________
b035a148 1619Bool_t AliMUONTrackK::Recover(void)
83dbc640 1620{
1621 // Adds new failed track(s) which can be tried to be recovered
b035a148 1622 Int_t nRecTracks;
83dbc640 1623 TClonesArray *trackPtr;
1624 AliMUONTrackK *trackK;
1625
b035a148 1626 if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
29f1b13a 1627 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
83dbc640 1628
b035a148 1629 // Remove hit with the highest chi2
1630 Double_t chi2 = 0;
1631 if (fgDebug > 0) {
1632 for (Int_t i=0; i<fNTrackHits; i++) {
1633 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1634 printf("%10.4f", chi2);
1635 }
1636 printf("\n");
1637 for (Int_t i=0; i<fNTrackHits; i++) {
1638 printf("%10d", ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i))->GetChamberNumber());
1639 }
1640 printf("\n");
1641 }
1642 Double_t chi2_max = 0;
1643 Int_t imax = 0;
1644 for (Int_t i=0; i<fNTrackHits; i++) {
1645 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1646 if (chi2 < chi2_max) continue;
1647 chi2_max = chi2;
1648 imax = i;
1649 }
1650 //if (chi2_max < 10) return kFALSE; // !!!
1651 //if (chi2_max < 25) imax = fNTrackHits - 1;
1652 if (chi2_max < 15) imax = fNTrackHits - 1; // discard the last point
1653 // Check if the outlier is not from the seed segment
1654 AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(imax);
1655 if (skipHit == fStartSegment->GetHitForRec1() || skipHit == fStartSegment->GetHitForRec2()) {
1656 //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1657 return kFALSE; // to be changed probably
1658 }
1659
1660 // Make a copy of track hit collection
1661 TObjArray *hits = new TObjArray(*fTrackHitsPtr);
1662 Int_t imax0;
1663 imax0 = imax;
1664
1665 // Hits after the found one will be removed
1666 if (GetStation0() == 3 && skipHit->GetChamberNumber() > 7) {
1667 SortHits(1, fTrackHitsPtr); // unsort hits
1668 imax = fTrackHitsPtr->IndexOf(skipHit);
1669 }
1670 Int_t nTrackHits = fNTrackHits;
1671 for (Int_t i=imax+1; i<nTrackHits; i++) {
1672 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(i);
1673 fTrackHitsPtr->Remove(hit);
1674 hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit
1675 fNTrackHits--;
1676 }
83dbc640 1677
1678 // Check if the track candidate doesn't exist yet
b035a148 1679 if (ExistDouble()) { delete hits; return kFALSE; }
1680
1681 //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1682 delete hits;
83dbc640 1683
29f1b13a 1684 nRecTracks = fgTrackReconstructor->GetNRecTracks();
b035a148 1685 skipHit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[fNTrackHits-1]);
1686 // Remove all saved steps and smoother matrices after the skipped hit
1687 RemoveMatrices(skipHit->GetZ());
1688
1689 //AZ(z->-z) if (skipHit->GetZ() > fStartSegment->GetHitForRec2()->GetZ() || !fNSteps) {
1690 if (TMath::Abs(skipHit->GetZ()) > TMath::Abs(fStartSegment->GetHitForRec2()->GetZ()) || !fNSteps) {
1691 // Propagation toward high Z or skipped hit next to segment -
1692 // start track from segment
1693 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
29f1b13a 1694 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
b035a148 1695 trackK->fRecover = 1;
1696 trackK->fSkipHit = skipHit;
1697 trackK->fNTrackHits = fNTrackHits;
1698 delete trackK->fTrackHitsPtr; // not efficient ?
1699 trackK->fTrackHitsPtr = new TObjArray(*fTrackHitsPtr);
1700 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1701 return kTRUE;
1702 }
1703
1704 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1705 *trackK = *this;
29f1b13a 1706 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
b035a148 1707 //AZ(z->-z) trackK->fTrackDir = -1;
1708 trackK->fTrackDir = 1;
83dbc640 1709 trackK->fRecover = 1;
b035a148 1710 trackK->fSkipHit = skipHit;
1711 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1712 if (iD > 1) {
1713 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1714 CreateMatrix(trackK->fParFilter);
1715 iD = 1;
1716 trackK->fParFilter->Last()->SetUniqueID(iD);
1717 }
1718 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1719 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1720 iD = trackK->fCovFilter->Last()->GetUniqueID();
1721 if (iD > 1) {
1722 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1723 CreateMatrix(trackK->fCovFilter);
1724 iD = 1;
1725 trackK->fCovFilter->Last()->SetUniqueID(iD);
1726 }
1727 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1728 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1729 if (trackK->fWeight->Determinant() != 0) {
b21aa6eb 1730 Int_t ifail;
1731 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
83dbc640 1732 } else {
b21aa6eb 1733 AliWarning(" Determinant fWeight=0:");
83dbc640 1734 }
b035a148 1735 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1736 trackK->fChi2 = 0;
1737 for (Int_t i=0; i<fNTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1738 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1739 return kTRUE;
1740}
83dbc640 1741
b035a148 1742 //__________________________________________________________________________
1743void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1744{
1745 // Adds matrices for the smoother and keep Chi2 for the point
1746 // Track parameters
1747 //trackK->fParFilter->Last()->Print();
1748 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1749 if (iD > 1) {
1750 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1751 CreateMatrix(trackK->fParFilter);
1752 iD = 1;
1753 }
1754 *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1755 trackK->fParFilter->Last()->SetUniqueID(iD);
1756 if (fgDebug > 1) {
1757 cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1758 //trackK->fTrackPar->Print();
1759 //trackK->fTrackParNew->Print();
1760 trackK->fParFilter->Last()->Print();
1761 cout << " Add matrices" << endl;
1762 }
1763 // Covariance
1764 *(trackK->fCovariance) = *(trackK->fWeight);
1765 if (trackK->fCovariance->Determinant() != 0) {
b21aa6eb 1766 Int_t ifail;
1767 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
b035a148 1768 } else {
b21aa6eb 1769 AliWarning(" Determinant fCovariance=0:");
b035a148 1770 }
1771 iD = trackK->fCovFilter->Last()->GetUniqueID();
1772 if (iD > 1) {
1773 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1774 CreateMatrix(trackK->fCovFilter);
1775 iD = 1;
1776 }
1777 *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1778 trackK->fCovFilter->Last()->SetUniqueID(iD);
1779
1780 // Save Chi2-increment for point
1781 Int_t indx = trackK->fTrackHitsPtr->IndexOf(hitAdd);
1782 if (indx < 0) indx = fNTrackHits;
1783 if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10);
1784 trackK->fChi2Array->AddAt(dChi2,indx);
1785}
1786
1787 //__________________________________________________________________________
1788void AliMUONTrackK::CreateMatrix(TObjArray *objArray)
1789{
1790 // Create new matrix and add it to TObjArray
1791
1792 TMatrixD *matrix = (TMatrixD*) objArray->First();
1793 TMatrixD *tmp = new TMatrixD(*matrix);
b21aa6eb 1794 objArray->AddAtAndExpand(tmp,objArray->GetLast());
b035a148 1795 //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1796}
1797
1798 //__________________________________________________________________________
1799void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1800{
1801 // Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1802
1803 for (Int_t i=fNSteps-1; i>=0; i--) {
1804 if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1805 if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1806 RemoveMatrices(this);
1807 } // for (Int_t i=fNSteps-1;
83dbc640 1808}
1809
b035a148 1810 //__________________________________________________________________________
1811void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1812{
1813 // Remove last saved matrices and steps in the smoother part
1814
1815 trackK->fNSteps--;
1816 Int_t i = trackK->fNSteps;
1817
1818 Int_t id = 0;
1819 // Delete only matrices not shared by several tracks
1820 id = trackK->fParExtrap->Last()->GetUniqueID();
1821 if (id > 1) {
1822 trackK->fParExtrap->Last()->SetUniqueID(id-1);
1823 trackK->fParExtrap->RemoveAt(i);
1824 }
1825 else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1826 id = fParFilter->Last()->GetUniqueID();
1827 if (id > 1) {
1828 trackK->fParFilter->Last()->SetUniqueID(id-1);
1829 trackK->fParFilter->RemoveAt(i);
1830 }
1831 else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1832 id = trackK->fCovExtrap->Last()->GetUniqueID();
1833 if (id > 1) {
1834 trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1835 trackK->fCovExtrap->RemoveAt(i);
1836 }
1837 else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1838 id = trackK->fCovFilter->Last()->GetUniqueID();
1839 if (id > 1) {
1840 trackK->fCovFilter->Last()->SetUniqueID(id-1);
1841 trackK->fCovFilter->RemoveAt(i);
1842 }
1843 else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1844 id = trackK->fJacob->Last()->GetUniqueID();
1845 if (id > 1) {
1846 trackK->fJacob->Last()->SetUniqueID(id-1);
1847 trackK->fJacob->RemoveAt(i);
1848 }
1849 else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1850}
1851
1852 //__________________________________________________________________________
b035a148 1853Bool_t AliMUONTrackK::Smooth(void)
1854{
1855 // Apply smoother
1856 Int_t ihit = fNTrackHits - 1;
1857 AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[ihit];
1858 fChi2Smooth = new TArrayD(fNTrackHits);
1859 fChi2Smooth->Reset(-1);
1860 fChi2 = 0;
1861 fParSmooth = new TObjArray(15);
1862 fParSmooth->Clear();
1863
1864 if (fgDebug > 0) {
1865 cout << " ******** Enter Smooth " << endl;
1866 cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl;
1867 /*
1868 for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1869 cout << endl;
b21aa6eb 1870 for (Int_t i=fNSteps-1; i>=0; i--) {cout << i << " " << (*fSteps)[i]; ((TMatrixD*)fParFilter->UncheckedAt(i))->Print(); ((TMatrixD*)fParExtrap->UncheckedAt(i))->Print(); ((TMatrixD*)fJacob->UncheckedAt(i))->Print();}
b035a148 1871 */
1872 for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHitsPtr)[i])->GetZ() << " ";
1873 cout << endl;
1874 }
1875
1876 // Find last point corresponding to the last hit
1877 Int_t iLast = fNSteps - 1;
1878 for ( ; iLast>=0; iLast--) {
1879 //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHitsPtr)[fNTrackHits-1])->GetZ()) break;
1880 if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHitsPtr)[fNTrackHits-1])->GetZ())) break;
1881 }
1882
1883 TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1884 //parSmooth.Dump();
1885 TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1886 TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1887 TMatrixD tmpPar = *fTrackPar;
1888 //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print();
1889
1890 Bool_t found;
1891 Double_t chi2_max = 0;
1892 for (Int_t i=iLast+1; i>0; i--) {
1893 if (i == iLast + 1) goto L33; // temporary fix
1894
1895 // Smoother gain matrix
1896 weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1897 if (weight.Determinant() != 0) {
b21aa6eb 1898 Int_t ifail;
1899 mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
b035a148 1900 } else {
b21aa6eb 1901 AliWarning(" Determinant weight=0:");
b035a148 1902 }
1903 // Fk'Wkk+1
1904 tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
1905 gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
1906 //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
1907
1908 // Smoothed parameter vector
1909 //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
1910 parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
1911 tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
1912 tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
1913 parSmooth = tmpPar;
1914
1915 // Smoothed covariance
1916 covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1917 weight = TMatrixD(TMatrixD::kTransposed,gain);
1918 tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
1919 covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
1920 covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
1921
1922 // Check if there was a measurement at given z
1923 found = kFALSE;
1924 for ( ; ihit>=0; ihit--) {
1925 hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[ihit];
1926 if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
1927 //AZ(z->-z) else if (ihit < fNTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
1928 else if (ihit < fNTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
1929 }
1930 if (!found) continue; // no measurement - skip the rest
1931 else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
1932 if (ihit == 0) continue; // the first hit - skip the rest
1933
1934L33:
1935 // Smoothed residuals
1936 tmpPar = 0;
1937 tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
1938 tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
1939 if (fgDebug > 1) {
1940 cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
1941 cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
1942 }
1943 // Cov. matrix of smoothed residuals
1944 tmp = 0;
1945 tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
1946 tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
1947 tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
1948 tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
1949
1950 // Calculate Chi2 of smoothed residuals
1951 if (tmp.Determinant() != 0) {
b21aa6eb 1952 Int_t ifail;
1953 mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
b035a148 1954 } else {
b21aa6eb 1955 AliWarning(" Determinant tmp=0:");
b035a148 1956 }
1957 TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
1958 TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
1959 if (fgDebug > 1) chi2.Print();
1960 (*fChi2Smooth)[ihit] = chi2(0,0);
1961 if (chi2(0,0) > chi2_max) chi2_max = chi2(0,0);
1962 fChi2 += chi2(0,0);
1963 if (chi2(0,0) < 0) {
b21aa6eb 1964 chi2.Print(); cout << " chi2 < 0 " << i << " " << iLast << endl;
1965 //AliFatal("chi2 < 0.");
b035a148 1966 }
1967 // Save smoothed parameters
1968 TMatrixD *par = new TMatrixD(parSmooth);
b21aa6eb 1969 fParSmooth->AddAtAndExpand(par, ihit);
b035a148 1970
1971 } // for (Int_t i=iLast+1;
1972
1973 //if (chi2_max > 16) {
1974 //if (chi2_max > 25) {
1975 //if (chi2_max > 50) {
1976 //if (chi2_max > 100) {
1977 if (chi2_max > fgkChi2max) {
1978 //if (Recover()) DropBranches();
1979 //Recover();
1980 Outlier();
1981 return kFALSE;
1982 }
1983 return kTRUE;
1984}
1985
1986 //__________________________________________________________________________
1987void AliMUONTrackK::Outlier()
1988{
1989 // Adds new track with removed hit having the highest chi2
1990
1991 if (fgDebug > 0) {
1992 cout << " ******** Enter Outlier " << endl;
1993 for (Int_t i=0; i<fNTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
1994 printf("\n");
1995 for (Int_t i=0; i<fNTrackHits; i++) {
1996 printf("%10d", ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i))->GetChamberNumber());
1997 }
1998 printf("\n");
1999 }
2000
2001 Double_t chi2_max = 0;
2002 Int_t imax = 0;
2003 for (Int_t i=0; i<fNTrackHits; i++) {
2004 if ((*fChi2Smooth)[i] < chi2_max) continue;
2005 chi2_max = (*fChi2Smooth)[i];
2006 imax = i;
2007 }
2008 // Check if the outlier is not from the seed segment
2009 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(imax);
2010 if (hit == fStartSegment->GetHitForRec1() || hit == fStartSegment->GetHitForRec2()) return; // to be changed probably
2011
2012 // Check for missing station
2013 Int_t ok = 1;
2014 if (imax == 0) {
2015 if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(1))->GetChamberNumber() < 8) ok--;
2016 } else if (imax == fNTrackHits-1) {
2017 if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(fNTrackHits-2))->GetChamberNumber() > 1) ok--;
2018 }
2019 else if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2020 if (!ok) { Recover(); return; } // try to recover track
2021 //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; }
2022
2023 // Remove saved steps and smoother matrices after the outlier
2024 RemoveMatrices(hit->GetZ());
2025
2026 // Check for possible double track candidates
2027 //if (ExistDouble(hit)) return;
2028
29f1b13a 2029 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2030 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
b035a148 2031
2032 AliMUONTrackK *trackK = 0;
2033 if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2034 // start track from segment
2035 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
29f1b13a 2036 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
b035a148 2037 trackK->fRecover = 2;
2038 trackK->fSkipHit = hit;
2039 trackK->fNTrackHits = fNTrackHits;
2040 delete trackK->fTrackHitsPtr; // not efficient ?
2041 trackK->fTrackHitsPtr = new TObjArray(*fTrackHitsPtr);
2042 if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHitsPtr);
2043 if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2044 return;
2045 }
2046 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2047 *trackK = *this;
29f1b13a 2048 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
b035a148 2049 //AZ(z->-z) trackK->fTrackDir = -1;
2050 trackK->fTrackDir = 1;
2051 trackK->fRecover = 2;
2052 trackK->fSkipHit = hit;
2053 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2054 if (iD > 1) {
2055 trackK->fParFilter->Last()->SetUniqueID(iD-1);
2056 CreateMatrix(trackK->fParFilter);
2057 iD = 1;
2058 trackK->fParFilter->Last()->SetUniqueID(iD);
2059 }
2060 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2061 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2062 iD = trackK->fCovFilter->Last()->GetUniqueID();
2063 if (iD > 1) {
2064 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2065 CreateMatrix(trackK->fCovFilter);
2066 iD = 1;
2067 trackK->fCovFilter->Last()->SetUniqueID(iD);
2068 }
2069 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2070 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2071 if (trackK->fWeight->Determinant() != 0) {
b21aa6eb 2072 Int_t ifail;
2073 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
b035a148 2074 } else {
b21aa6eb 2075 AliWarning(" Determinant fWeight=0:");
b035a148 2076 }
2077 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2078 trackK->fChi2 = 0;
2079 for (Int_t i=0; i<fNTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2080 if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2081}
2082
2083 //__________________________________________________________________________
2084Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2085{
2086 // Return Chi2 at point
2087 return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2088 //return 0.;
2089}
2090
2091 //__________________________________________________________________________
2092void AliMUONTrackK::Print(FILE *lun) const
2093{
2094 // Print out track information
2095
2096 Int_t flag = 1;
2097 AliMUONHitForRec *hit = 0;
29f1b13a 2098 if (fgTrackReconstructor->GetRecTrackRefHits()) {
29fc2c86 2099 // from track ref. hits
b035a148 2100 for (Int_t j=0; j<fNTrackHits; j++) {
2101 hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(j);
29fc2c86 2102 if (hit->GetTTRTrack() > 1) { flag = 0; break; }
b035a148 2103 }
2104 for (Int_t j=0; j<fNTrackHits; j++) {
2105 printf("%10.4f", GetChi2PerPoint(j));
2106 if (GetChi2PerPoint(j) > -0.1) {
2107 hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(j);
2108 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(j));
29fc2c86 2109 fprintf(lun, "%3d %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack(), flag);
b035a148 2110 }
2111 }
2112 printf("\n");
2113 } else {
2114 // from raw clusters
2115 AliMUONRawCluster *clus = 0;
2116 TClonesArray *rawclusters = 0;
2117 for (Int_t i1=0; i1<fNTrackHits; i1++) {
2118 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
29f1b13a 2119 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
b035a148 2120 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2121 if (TMath::Abs(clus->GetTrack(1)-1) < 2) {
2122 if (clus->GetTrack(2)) flag = 2;
2123 continue;
2124 }
2125 if (clus->GetTrack(2) && TMath::Abs(clus->GetTrack(2)-1) < 2) {
2126 flag = 3;
2127 continue;
2128 }
2129 flag = 0;
2130 break;
2131 }
2132 Int_t sig[2]={1,1}, tid[2]={0};
2133 for (Int_t i1=0; i1<fNTrackHits; i1++) {
2134 if (GetChi2PerPoint(i1) < -0.1) continue;
2135 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
29f1b13a 2136 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
b035a148 2137 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2138 for (Int_t j=0; j<2; j++) {
2139 tid[j] = clus->GetTrack(j+1) - 1;
2140 if (clus->GetTrack(j+1) < 0) { sig[j] = 0; tid[j] = 999; }
2141 }
2142 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(i1));
2143 if (!(clus->GetTrack(2))) fprintf(lun, "%3d %3d", sig[0], tid[0]); // simple cluster
2144 else { // track overlap
2145 fprintf(lun, "%3d %3d", TMath::Max(sig[0],sig[1]), TMath::Min(tid[0],tid[1]));
2146 //if (tid[0] < 2) flag *= 2;
2147 //else if (tid[1] < 2) flag *= 3;
2148 }
2149 fprintf (lun, "%3d \n", flag);
2150 }
2151 }
2152}
2153
2154 //__________________________________________________________________________
2155void AliMUONTrackK::DropBranches(Int_t imax, TObjArray *hits)
2156{
2157 // Drop branches downstream of the skipped hit
2158 Int_t nRecTracks;
2159 TClonesArray *trackPtr;
2160 AliMUONTrackK *trackK;
2161
29f1b13a 2162 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2163 nRecTracks = fgTrackReconstructor->GetNRecTracks();
b035a148 2164 Int_t icand = trackPtr->IndexOf(this);
2165 if (!hits) hits = fTrackHitsPtr;
2166
2167 // Check if the track candidate doesn't exist yet
2168 for (Int_t i=icand+1; i<nRecTracks; i++) {
2169 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2170 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2171 if (trackK->GetRecover() < 0) continue;
2172
2173 if (trackK->fNTrackHits >= imax + 1) {
2174 for (Int_t j=0; j<=imax; j++) {
2175 //if (j != fNTrackHits-1 && (*trackK->fTrackHitsPtr)[j] != (*fTrackHitsPtr)[j]) break;
2176 if ((*trackK->fTrackHitsPtr)[j] != (*hits)[j]) break;
2177 if (j == imax) {
2178 if (hits != fTrackHitsPtr) {
2179 // Drop all branches downstream the hit (for Recover)
2180 trackK->SetRecover(-1);
2181 if (fgDebug >= 0 )cout << " Recover " << i << endl;
2182 continue;
2183 }
2184 // Check if the removal of the hit breaks the track
2185 Int_t ok = 1;
2186 if (imax == 0) {
2187 if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2188 else if (imax == trackK->fNTrackHits-1) continue;
2189 // else if (imax == trackK->fNTrackHits-1) {
2190 //if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(trackK->fNTrackHits-2))->GetChamberNumber() > 1) ok--;
2191 //}
2192 else if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2193 if (!ok) trackK->SetRecover(-1);
2194 }
2195 } // for (Int_t j=0;
2196 }
2197 } // for (Int_t i=0;
2198}
2199
2200 //__________________________________________________________________________
2201void AliMUONTrackK::DropBranches(AliMUONSegment *segment)
2202{
2203 // Drop all candidates with the same seed segment
2204 Int_t nRecTracks;
2205 TClonesArray *trackPtr;
2206 AliMUONTrackK *trackK;
2207
29f1b13a 2208 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2209 nRecTracks = fgTrackReconstructor->GetNRecTracks();
b035a148 2210 Int_t icand = trackPtr->IndexOf(this);
2211
2212 for (Int_t i=icand+1; i<nRecTracks; i++) {
2213 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2214 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2215 if (trackK->GetRecover() < 0) continue;
2216 if (trackK->fStartSegment == segment) trackK->SetRecover(-1);
2217 }
2218 if (fgDebug >= 0) cout << " Drop segment " << endl;
2219}
2220
2221 //__________________________________________________________________________
2222AliMUONHitForRec* AliMUONTrackK::GetHitLastOk(void)
2223{
2224 // Return the hit where track stopped
2225
2226 if (!fNSteps) return (AliMUONHitForRec*)((*fTrackHitsPtr)[1]);
2227 return fSkipHit;
2228}
2229
2230 //__________________________________________________________________________
2231Int_t AliMUONTrackK::GetStation0(void)
2232{
2233 // Return seed station number
2234 return fStartSegment->GetHitForRec1()->GetChamberNumber() / 2;
2235}
2236
2237 //__________________________________________________________________________
2238Bool_t AliMUONTrackK::ExistDouble(AliMUONHitForRec *hit)
2239{
2240 // Check if the track will make a double after outlier removal
2241
29f1b13a 2242 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2243 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
b035a148 2244 TObjArray *hitArray = new TObjArray(*fTrackHitsPtr);
2245 TObjArray *hitArray1 = new TObjArray(*hitArray);
2246 hitArray1->Remove(hit);
2247 hitArray1->Compress();
2248
2249 Bool_t same = kFALSE;
2250 for (Int_t i=0; i<nRecTracks; i++) {
2251 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2252 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2253 if (trackK == this) continue;
2254 if (trackK->fNTrackHits == fNTrackHits || trackK->fNTrackHits == fNTrackHits-1) {
2255 TObjArray *hits = new TObjArray(*trackK->fTrackHitsPtr);
2256 same = kTRUE;
2257 if (trackK->fNTrackHits == fNTrackHits) {
2258 for (Int_t j=0; j<fNTrackHits; j++) {
2259 if (hits->UncheckedAt(j) != hitArray->UncheckedAt(j)) { same = kFALSE; break; }
2260 }
2261 if (same) { delete hits; break; }
2262 if (trackK->fSkipHit) {
2263 TObjArray *hits1 = new TObjArray(*hits);
2264 if (hits1->Remove(trackK->fSkipHit) > 0) {
2265 hits1->Compress();
2266 same = kTRUE;
2267 for (Int_t j=0; j<fNTrackHits-1; j++) {
2268 if (hits1->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2269 }
2270 if (same) { delete hits1; break; }
2271 }
2272 delete hits1;
2273 }
2274 } else {
2275 // Check with removed outlier
2276 same = kTRUE;
2277 for (Int_t j=0; j<fNTrackHits-1; j++) {
2278 if (hits->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2279 }
2280 if (same) { delete hits; break; }
2281 }
2282 delete hits;
2283 }
2284 } // for (Int_t i=0; i<nRecTracks;
2285 delete hitArray; delete hitArray1;
2286 if (same && fgDebug >= 0) cout << " Same" << endl;
2287 return same;
2288}
2289
2290 //__________________________________________________________________________
2291Bool_t AliMUONTrackK::ExistDouble(void)
2292{
2293 // Check if the track will make a double after recovery
2294
29f1b13a 2295 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2296 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
b035a148 2297
2298 TObjArray *hitArray = new TObjArray(*fTrackHitsPtr);
2299 if (GetStation0() == 3) SortHits(0, hitArray); // sort
2300 //if (GetStation0() == 3) SortHits(1, hitArray); // unsort
2301
2302 Bool_t same = kFALSE;
2303 for (Int_t i=0; i<nRecTracks; i++) {
2304 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2305 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2306 if (trackK == this) continue;
2307 //AZ if (trackK->GetRecover() < 0) continue; //
2308 if (trackK->fNTrackHits >= fNTrackHits) {
2309 TObjArray *hits = new TObjArray(*trackK->fTrackHitsPtr);
2310 if (trackK->GetStation0() == 3) SortHits(0, hits); // sort
2311 //if (trackK->GetStation0() == 3) SortHits(1, hits); // unsort
2312 for (Int_t j=0; j<fNTrackHits; j++) {
2313 //cout << fNTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2314 if (j != fNTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break;
2315 if (j == fNTrackHits-1) {
2316 if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE;
2317 //if (trackK->fNTrackHits > fNTrackHits &&
2318 //if (trackK->fSkipHit) cout << ((AliMUONHitForRec*)((*hitArray)[j]))->GetZ() << " " << trackK->fSkipHit->GetZ() << endl;
2319 }
2320 } // for (Int_t j=0;
2321 delete hits;
2322 if (same) break;
2323 }
2324 } // for (Int_t i=0;
2325 delete hitArray;
2326 return same;
2327}