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