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