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