1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 #include <Riostream.h>
19 #include <TClonesArray.h>
23 #include "AliMUONTrackK.h"
26 #include "AliMUONTrackReconstructor.h"
28 #include "AliMUONSegment.h"
29 #include "AliMUONHitForRec.h"
30 #include "AliMUONRawCluster.h"
31 #include "AliMUONTrackParam.h"
32 #include "AliMUONEventRecoCombi.h"
33 #include "AliMUONDetElement.h"
37 const Int_t AliMUONTrackK::fgkSize = 5;
38 const Int_t AliMUONTrackK::fgkNSigma = 12;
39 const Double_t AliMUONTrackK::fgkChi2max = 100;
40 const Int_t AliMUONTrackK::fgkTriesMax = 10000;
41 const Double_t AliMUONTrackK::fgkEpsilon = 0.002;
43 void mnvertLocal(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail); // from AliMUONTrack
45 Int_t AliMUONTrackK::fgDebug = -1; //-1;
46 Int_t AliMUONTrackK::fgNOfPoints = 0;
47 AliMUONTrackReconstructor* AliMUONTrackK::fgTrackReconstructor = NULL;
48 TClonesArray* AliMUONTrackK::fgHitForRec = NULL;
49 AliMUONEventRecoCombi *AliMUONTrackK::fgCombi = NULL;
51 ClassImp(AliMUONTrackK) // Class implementation in ROOT context
53 //__________________________________________________________________________
54 AliMUONTrackK::AliMUONTrackK()
58 // Default constructor
60 fgTrackReconstructor = NULL; // pointer to event reconstructor
61 fgHitForRec = NULL; // pointer to points
62 fgNOfPoints = 0; // number of points
67 fTrackPar = fTrackParNew = NULL;
68 fCovariance = fWeight = NULL;
70 fParExtrap = fParFilter = fParSmooth = NULL;
71 fCovExtrap = fCovFilter = NULL;
73 fSteps = NULL; fNSteps = 0;
80 //__________________________________________________________________________
81 AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructor *TrackReconstructor, TClonesArray *hitForRec)
86 if (!TrackReconstructor) return;
87 fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
88 fgHitForRec = hitForRec; // pointer to points
89 fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
91 if (fgTrackReconstructor->GetTrackMethod() == 3) fgCombi = AliMUONEventRecoCombi::Instance();
97 fTrackPar = fTrackParNew = NULL;
98 fCovariance = fWeight = NULL;
100 fParExtrap = fParFilter = fParSmooth = NULL;
101 fCovExtrap = fCovFilter = NULL;
103 fSteps = NULL; fNSteps = 0;
108 //__________________________________________________________________________
109 AliMUONTrackK::AliMUONTrackK(AliMUONSegment *segment)
110 : AliMUONTrack(segment, segment, fgTrackReconstructor)
112 // Constructor from a segment
114 AliMUONHitForRec *hit1, *hit2;
115 AliMUONRawCluster *clus;
116 TClonesArray *rawclusters;
118 fStartSegment = segment;
121 // Pointers to hits from the segment
122 hit1 = segment->GetHitForRec1();
123 hit2 = segment->GetHitForRec2();
124 hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
125 hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
126 // check sorting in Z
127 if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
129 hit2 = segment->GetHitForRec1();
131 // memory allocation for the TObjArray of pointers to reconstructed TrackHit's
132 fTrackHitsPtr = new TObjArray(13);
136 fTrackPar = new TMatrixD(fgkSize,1); // track parameters
137 fTrackParNew = new TMatrixD(fgkSize,1); // track parameters
138 fCovariance = new TMatrixD(fgkSize,fgkSize); // covariance matrix
139 fWeight = new TMatrixD(fgkSize,fgkSize); // weight matrix (inverse of covariance)
141 // Fill array of track parameters
142 if (hit1->GetChamberNumber() > 7) {
143 // last tracking station
144 (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
145 (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
146 fPosition = hit1->GetZ(); // z
147 fTrackHitsPtr->Add(hit2); // add hit 2
148 fTrackHitsPtr->Add(hit1); // add hit 1
149 //AZ(Z->-Z) fTrackDir = -1;
152 // last but one tracking station
153 (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
154 (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
155 fPosition = hit2->GetZ(); // z
156 fTrackHitsPtr->Add(hit1); // add hit 1
157 fTrackHitsPtr->Add(hit2); // add hit 2
158 //AZ(Z->-Z) fTrackDir = 1;
161 dZ = hit2->GetZ() - hit1->GetZ();
162 dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
163 dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
164 (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
165 if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
166 (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
167 (*fTrackPar)(2,0) -= TMath::Pi();
168 (*fTrackPar)(4,0) = 1/fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()); // 1/Pt
169 (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
170 // Evaluate covariance (and weight) matrix
174 fParExtrap = new TObjArray(15);
175 fParFilter = new TObjArray(15);
176 fCovExtrap = new TObjArray(15);
177 fCovFilter = new TObjArray(15);
178 fJacob = new TObjArray(15);
179 fSteps = new TArrayD(15);
181 fChi2Array = new TArrayD(13);
185 if (fgDebug < 0 ) return;
186 cout << fgTrackReconstructor->GetNRecTracks()-1 << " " << fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()) << " " << 1/(*fTrackPar)(4,0) << " ";
187 if (fgTrackReconstructor->GetRecTrackRefHits()) {
188 // from track ref. hits
189 cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[0]))->GetTTRTrack() << "<-->" << ((AliMUONHitForRec*)((*fTrackHitsPtr)[1]))->GetTTRTrack() << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
192 for (Int_t i=0; i<2; i++) {
193 hit1 = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i]);
194 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
195 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
196 cout << clus->GetTrack(1);
197 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
198 if (i == 0) cout << " <--> ";
200 cout << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
204 //__________________________________________________________________________
205 AliMUONTrackK::~AliMUONTrackK()
210 delete fTrackHitsPtr; // delete the TObjArray of pointers to TrackHit's
211 fTrackHitsPtr = NULL;
214 delete fTrackPar; delete fTrackParNew; delete fCovariance;
218 if (fSteps) delete fSteps;
219 if (fChi2Array) delete fChi2Array;
220 if (fChi2Smooth) delete fChi2Smooth;
221 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
222 // Delete only matrices not shared by several tracks
223 if (!fParExtrap) return;
226 for (Int_t i=0; i<fNSteps; i++) {
227 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
228 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
229 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
231 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
232 fParExtrap->RemoveAt(i);
234 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
235 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
236 id = fParFilter->UncheckedAt(i)->GetUniqueID();
238 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
239 fParFilter->RemoveAt(i);
241 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
242 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
243 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
245 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
246 fCovExtrap->RemoveAt(i);
249 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
250 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
251 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
253 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
254 fCovFilter->RemoveAt(i);
256 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
257 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
258 id = fJacob->UncheckedAt(i)->GetUniqueID();
260 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
265 for (Int_t i=0; i<fNSteps; i++) {
266 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
267 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
268 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
269 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
270 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
271 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
274 fParExtrap->Delete(); fParFilter->Delete();
275 fCovExtrap->Delete(); fCovFilter->Delete();
277 delete fParExtrap; delete fParFilter;
278 delete fCovExtrap; delete fCovFilter;
282 //__________________________________________________________________________
283 AliMUONTrackK::AliMUONTrackK (const AliMUONTrackK& source)
284 : AliMUONTrack(source)
286 // Protected copy constructor
287 AliFatal("Not implemented.");
290 //__________________________________________________________________________
291 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
293 // Assignment operator
295 if(&source == this) return *this;
297 // base class assignement
298 //AZ TObject::operator=(source);
299 AliMUONTrack::operator=(source);
301 fStartSegment = source.fStartSegment;
302 fNTrackHits = source.fNTrackHits;
303 fChi2 = source.fChi2;
304 fPosition = source.fPosition;
305 fPositionNew = source.fPositionNew;
306 fTrackDir = source.fTrackDir;
307 fBPFlag = source.fBPFlag;
308 fRecover = source.fRecover;
309 fSkipHit = source.fSkipHit;
312 fTrackHitsPtr = new TObjArray(*source.fTrackHitsPtr);
313 //source.fTrackHitsPtr->Dump();
314 //fTrackHitsPtr->Dump();
316 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
317 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
318 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
319 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
322 fParExtrap = new TObjArray(*source.fParExtrap);
323 fParFilter = new TObjArray(*source.fParFilter);
324 fCovExtrap = new TObjArray(*source.fCovExtrap);
325 fCovFilter = new TObjArray(*source.fCovFilter);
326 fJacob = new TObjArray(*source.fJacob);
327 fSteps = new TArrayD(*source.fSteps);
328 fNSteps = source.fNSteps;
330 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
334 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
335 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
336 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
337 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
338 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
339 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
344 //__________________________________________________________________________
345 void AliMUONTrackK::EvalCovariance(Double_t dZ)
347 // Evaluate covariance (and weight) matrix for track candidate
348 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
351 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
352 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
354 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
356 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
358 tanA = TMath::Tan((*fTrackPar)(2,0));
359 dAdY = 1/(1+tanA*tanA)/dZ;
360 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
361 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
362 (*fWeight)(2,0) = (*fWeight)(0,2);
364 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
365 tanB = TMath::Tan((*fTrackPar)(3,0));
366 dBdX = 1/(1+tanB*tanB)/rad;
368 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
369 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
370 (*fWeight)(3,1) = (*fWeight)(1,3);
372 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
374 // check whether the Invert method returns flag if matrix cannot be inverted,
375 // and do not calculate the Determinant in that case !!!!
376 if (fWeight->Determinant() != 0) {
377 // fWeight->Invert();
379 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
381 AliWarning(" Determinant fWeight=0:");
386 //__________________________________________________________________________
387 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
389 // Follows track through detector stations
390 Bool_t miss, success;
391 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
392 Int_t ihit, firstIndx = -1, lastIndx = -1, currIndx = -1, iz0 = -1, iz = -1;
393 Double_t zEnd, dChi2;
394 AliMUONHitForRec *hitAdd, *firstHit = NULL, *lastHit = NULL, *hit;
395 AliMUONRawCluster *clus;
396 TClonesArray *rawclusters;
397 hit = 0; clus = 0; rawclusters = 0;
399 miss = success = kTRUE;
401 //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
402 iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
403 iMin = TMath::Min(ichamEnd,ichamBeg);
404 iMax = TMath::Max(ichamEnd,ichamBeg);
411 if (((AliMUONHitForRec*)fTrackHitsPtr->First())->GetChamberNumber() != ichamb) currIndx = 0;
412 } else if (fRecover) {
413 hit = GetHitLastOk();
414 currIndx = fTrackHitsPtr->IndexOf(hit);
415 if (currIndx < 0) hit = fStartSegment->GetHitForRec1(); // for station 3
417 ichamb = hit->GetChamberNumber();
418 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
419 // start from the last point or outlier
420 // remove the skipped hit
421 fTrackHitsPtr->Remove(fSkipHit); // remove hit
423 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
428 ichambOK = ((AliMUONHitForRec*)((*fTrackHitsPtr)[fNTrackHits-1]))->GetChamberNumber();
429 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHitsPtr)[0]))->GetChamberNumber() == 6) ichambOK = 6;
430 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
431 fSkipHit->GetHitNumber() < 0) {
432 iz0 = fgCombi->IZfromHit(fSkipHit);
435 else currIndx = fgHitForRec->IndexOf(fSkipHit);
438 fTrackHitsPtr->Compress();
440 } // if (hit == fSkipHit)
441 else if (currIndx < 0) currIndx = fTrackHitsPtr->IndexOf(hit);
442 } // else if (fRecover)
444 // Get indices of the 1'st and last hits on the track candidate
445 firstHit = (AliMUONHitForRec*) fTrackHitsPtr->First();
446 lastHit = (AliMUONHitForRec*) fTrackHitsPtr->Last();
447 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
448 lastHit->GetHitNumber() < 0) iz0 = fgCombi->IZfromHit(lastHit);
450 firstIndx = fgHitForRec->IndexOf(firstHit);
451 lastIndx = fgHitForRec->IndexOf(lastHit);
452 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
456 if (iz0 < 0) iz0 = iFB;
457 while (ichamb >= iMin && ichamb <= iMax) {
458 // Find the closest hit in Z, not belonging to the current plane
461 if (currIndx < fNTrackHits) {
462 hitAdd = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(currIndx);
463 zEnd = hitAdd->GetZ();
464 //AZ(z->-z) } else zEnd = -9999;
467 //AZ(Z->-Z) zEnd = -9999;
469 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
470 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
471 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
472 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
473 zEnd = hitAdd->GetZ();
479 // Combined cluster / track finder
480 if (zEnd > 999 && iFB < 0 && fgTrackReconstructor->GetTrackMethod() == 3) {
482 AliMUONHitForRec hitTmp;
483 for (iz = iz0 - iFB; iz < fgCombi->Nz(); iz++) {
484 if (TMath::Abs(fgCombi->Z(iz)-fPosition) < 0.5) continue;
485 Int_t *pDEatZ = fgCombi->DEatZ(iz);
486 //cout << iz << " " << fgCombi->Z(iz) << endl;
487 zEnd = fgCombi->Z(iz);
489 AliMUONDetElement *detElem = fgCombi->DetElem(pDEatZ[0]);
491 hitAdd->SetChamberNumber(detElem->Chamber());
492 //hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
497 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
499 // Check if there is a chamber without hits
500 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
501 if (!Back && zEnd<999) currIndx -= iFB;
503 zEnd = AliMUONConstants::DefaultChamberZ(ichamb);
506 ichamb = hitAdd->GetChamberNumber();
510 if (ichamb<iMin || ichamb>iMax) break;
511 // Check for missing station
513 dChamb = TMath::Abs(ichamb-ichambOK);
514 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
515 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
516 if (zEnd > 999) dStatMiss++;
518 // missing station - abandon track
519 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
521 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
522 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
523 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
524 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
525 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
526 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
529 cout << fNTrackHits << endl;
530 for (Int_t i1=0; i1<fNTrackHits; i1++) {
531 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
532 printf(" * %d %10.4f %10.4f %10.4f",
533 hit->GetChamberNumber(), hit->GetBendingCoor(),
534 hit->GetNonBendingCoor(), hit->GetZ());
535 if (fgTrackReconstructor->GetRecTrackRefHits()) {
536 // from track ref. hits
537 printf(" %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack());
540 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
541 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
542 printf("%3d", clus->GetTrack(1)-1);
543 if (clus->GetTrack(2) != 0) printf("%3d \n", clus->GetTrack(2)-1);
547 } // if (fgDebug >= 10)
548 if (fNTrackHits>2 && fRecover==0) Recover(); // try to recover track later
550 } // if (dStatMiss > 1)
552 if (endOfProp != 0) break;
554 // propagate to the found Z
556 // Check if track steps into dipole
557 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
558 if (fPosition<zDipole2 && zEnd>zDipole2) {
559 //LinearPropagation(zDipole2-zBeg);
560 ParPropagation(zDipole2);
561 MSThin(1); // multiple scattering in the chamber
562 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
563 fPosition = fPositionNew;
564 *fTrackPar = *fTrackParNew;
565 //MagnetPropagation(zEnd);
566 ParPropagation(zEnd);
567 WeightPropagation(zEnd, kTRUE);
568 fPosition = fPositionNew;
570 // Check if track steps out of dipole
571 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
572 else if (fPosition<zDipole1 && zEnd>zDipole1) {
573 //MagnetPropagation(zDipole1-zBeg);
574 ParPropagation(zDipole1);
575 MSThin(1); // multiple scattering in the chamber
576 WeightPropagation(zDipole1, kTRUE);
577 fPosition = fPositionNew;
578 *fTrackPar = *fTrackParNew;
579 //LinearPropagation(zEnd-zDipole1);
580 ParPropagation(zEnd);
581 WeightPropagation(zEnd, kTRUE);
582 fPosition = fPositionNew;
584 ParPropagation(zEnd);
585 //MSThin(1); // multiple scattering in the chamber
586 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
587 WeightPropagation(zEnd, kTRUE);
588 fPosition = fPositionNew;
592 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
593 // recovered track - remove the hit
595 ichamb = fSkipHit->GetChamberNumber();
596 // remove the skipped hit
597 fTrackHitsPtr->Remove(fSkipHit);
599 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
602 ichambOK = ((AliMUONHitForRec*)((*fTrackHitsPtr)[fNTrackHits-1]))->GetChamberNumber();
603 //? if (fgTrackReconstructor->GetTrackMethod() != 3) currIndx = fgHitForRec->IndexOf(fSkipHit);
604 currIndx = fgHitForRec->IndexOf(fSkipHit);
608 // backward propagator
610 TMatrixD pointWeight(fgkSize,fgkSize);
611 TMatrixD point(fgkSize,1);
612 TMatrixD trackParTmp = point;
613 point(0,0) = hitAdd->GetBendingCoor();
614 point(1,0) = hitAdd->GetNonBendingCoor();
615 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
616 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
617 TryPoint(point,pointWeight,trackParTmp,dChi2);
618 *fTrackPar = trackParTmp;
619 *fWeight += pointWeight;
620 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
621 fChi2 += dChi2; // Chi2
622 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
623 if (ichamb==ichamEnd) break;
626 // forward propagator
627 if (miss || !FindPoint(ichamb, zEnd, currIndx, iFB, hitAdd, iz)) {
629 *fTrackPar = *fTrackParNew;
632 fTrackHitsPtr->Add(hitAdd); // add hit
634 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
636 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
640 if (fgDebug > 0) cout << fNTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
641 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
645 //__________________________________________________________________________
646 void AliMUONTrackK::ParPropagation(Double_t zEnd)
648 // Propagation of track parameters to zEnd
650 Double_t dZ, step, distance, charge;
651 Double_t vGeant3[7], vGeant3New[7];
652 AliMUONTrackParam trackParam;
655 // First step using linear extrapolation
656 dZ = zEnd - fPosition;
657 fPositionNew = fPosition;
658 *fTrackParNew = *fTrackPar;
659 if (dZ == 0) return; //AZ ???
660 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
661 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
662 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
663 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
664 SetGeantParam(vGeant3,iFB);
665 //fTrackParNew->Print();
669 step = TMath::Abs(step);
670 // Propagate parameters
671 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
672 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
673 distance = zEnd - vGeant3New[2];
674 step *= dZ/(vGeant3New[2]-fPositionNew);
676 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
678 GetFromGeantParam(vGeant3New,iFB);
679 //fTrackParNew->Print();
681 // Position adjustment (until within tolerance)
682 while (TMath::Abs(distance) > fgkEpsilon) {
683 dZ = zEnd - fPositionNew;
684 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
685 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
686 step = TMath::Abs(step);
687 SetGeantParam(vGeant3,iFB);
690 // Propagate parameters
691 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
692 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
693 distance = zEnd - vGeant3New[2];
696 if (nTries > fgkTriesMax) AliError(Form(" Too many tries: %d", nTries));
697 } while (distance*iFB < 0);
699 GetFromGeantParam(vGeant3New,iFB);
701 //cout << nTries << endl;
702 //fTrackParNew->Print();
706 //__________________________________________________________________________
707 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
709 // Propagation of the weight matrix
710 // W = DtWD, where D is Jacobian
714 TMatrixD jacob(fgkSize,fgkSize);
717 // Save initial and propagated parameters
718 TMatrixD trackPar0 = *fTrackPar;
719 TMatrixD trackParNew0 = *fTrackParNew;
721 // Get covariance matrix
722 *fCovariance = *fWeight;
723 // check whether the Invert method returns flag if matrix cannot be inverted,
724 // and do not calculate the Determinant in that case !!!!
725 if (fCovariance->Determinant() != 0) {
727 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
728 //fCovariance->Print();
730 AliWarning(" Determinant fCovariance=0:");
733 // Loop over parameters to find change of the propagated vs initial ones
734 for (i=0; i<fgkSize; i++) {
735 dPar = TMath::Sqrt((*fCovariance)(i,i));
736 *fTrackPar = trackPar0;
737 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
738 (*fTrackPar)(i,0) += dPar;
739 ParPropagation(zEnd);
740 for (j=0; j<fgkSize; j++) {
741 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
745 //trackParNew0.Print();
746 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
748 TMatrixD jacob0 = jacob;
749 if (jacob.Determinant() != 0) {
752 AliWarning(" Determinant jacob=0:");
754 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
755 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
757 // Restore initial and propagated parameters
758 *fTrackPar = trackPar0;
759 *fTrackParNew = trackParNew0;
762 if (!smooth) return; // do not use smoother
763 if (fTrackDir < 0) return; // only for propagation towards int. point
764 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
765 fParExtrap->Add(tmp);
767 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
768 fParFilter->Add(tmp);
770 *fCovariance = *fWeight;
771 if (fCovariance->Determinant() != 0) {
773 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
775 AliWarning(" Determinant fCovariance=0:");
777 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
778 fCovExtrap->Add(tmp);
780 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
781 fCovFilter->Add(tmp);
783 tmp = new TMatrixD(jacob0); // Jacobian
786 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
787 fSteps->AddAt(fPositionNew,fNSteps++);
788 if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
792 //__________________________________________________________________________
793 Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd, Int_t iz)
795 // Picks up point within a window for the chamber No ichamb
796 // Split the track if there are more than 1 hit
797 Int_t ihit, nRecTracks;
798 Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
799 TClonesArray *trackPtr;
800 AliMUONHitForRec *hit, *hitLoop;
801 AliMUONTrackK *trackK;
802 AliMUONDetElement *detElem = NULL;
806 if (fgTrackReconstructor->GetTrackMethod() == 3 && iz >= 0) {
807 // Combined cluster / track finder
808 // Check if extrapolated track passes thru det. elems. at iz
809 Int_t *pDEatZ = fgCombi->DEatZ(iz);
810 Int_t nDetElem = pDEatZ[-1];
811 //cout << fgCombi->Z(iz) << " " << nDetElem << endl;
812 for (Int_t i = 0; i < nDetElem; i++) {
813 detElem = fgCombi->DetElem(pDEatZ[i]);
814 if (detElem->Inside((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPosition)) {
815 detElem->ClusterReco((*fTrackParNew)(1,0), (*fTrackParNew)(0,0));
816 hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
821 if (!ok) return ok; // outside det. elem.
825 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
826 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
827 *fCovariance = *fWeight;
828 // check whether the Invert method returns flag if matrix cannot be inverted,
829 // and do not calculate the Determinant in that case !!!!
830 if (fCovariance->Determinant() != 0) {
832 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
834 AliWarning(" Determinant fCovariance=0:");
836 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
837 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
838 // Loop over all hits and take hits from the chamber
839 TMatrixD pointWeight(fgkSize,fgkSize);
840 TMatrixD saveWeight = pointWeight;
841 TMatrixD pointWeightTmp = pointWeight;
842 TMatrixD point(fgkSize,1);
843 TMatrixD trackPar = point;
844 TMatrixD trackParTmp = point;
845 Int_t nHitsOK = 0, ihitB = currIndx, ihitE = fgNOfPoints, iDhit = iFB;
847 zLast = ((AliMUONHitForRec*)fTrackHitsPtr->Last())->GetZ();
848 if (fgTrackReconstructor->GetTrackMethod() == 3 && detElem) {
850 ihitE = detElem->NHitsForRec();
855 for (ihit = ihitB; ihit >= 0 && ihit < ihitE; ihit+=iDhit) {
856 if (fgTrackReconstructor->GetTrackMethod() != 3 || !detElem)
857 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
858 else hit = (AliMUONHitForRec*) detElem->HitsForRec()->UncheckedAt(ihit);
859 if (hit->GetChamberNumber() == ichamb) {
860 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
861 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
862 y = hit->GetBendingCoor();
863 x = hit->GetNonBendingCoor();
864 if (hit->GetBendingReso2() < 0) {
865 // Combined cluster / track finder
866 hit->SetBendingReso2(fgTrackReconstructor->GetBendingResolution()*
867 fgTrackReconstructor->GetBendingResolution());
868 hit->SetNonBendingReso2(fgTrackReconstructor->GetNonBendingResolution()*
869 fgTrackReconstructor->GetNonBendingResolution());
871 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
872 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
874 // windowB = TMath::Min (windowB,5.);
875 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
877 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
878 windowB = TMath::Min (windowB,0.5);
879 windowNonB = TMath::Min (windowNonB,3.);
880 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
881 windowB = TMath::Min (windowB,1.5);
882 windowNonB = TMath::Min (windowNonB,3.);
883 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
884 windowB = TMath::Min (windowB,4.);
885 windowNonB = TMath::Min (windowNonB,6.);
891 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
892 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
893 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
895 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
896 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
900 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
901 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
902 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
903 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
904 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
905 // hit->GetTrackRefSignal() == 1) { // just for test
906 // Vector of measurements and covariance matrix
907 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
908 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
909 // Adjust position: for multiple hits in the chamber or misalignment (Z as a function of X or Y)
910 //AliWarning(Form(" *** adjust %f %f ", zEnd, hit->GetZ()));
912 *fTrackPar = *fTrackParNew;
913 ParPropagation(zEnd);
914 WeightPropagation(zEnd, kTRUE);
915 fPosition = fPositionNew;
916 *fTrackPar = *fTrackParNew;
918 *fCovariance = *fWeight;
919 if (fCovariance->Determinant() != 0) {
921 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
923 AliWarning(" Determinant fCovariance=0:" );
929 pointWeight(0,0) = 1/hit->GetBendingReso2();
930 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
931 TryPoint(point,pointWeight,trackPar,dChi2);
932 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
933 // if (TMath::Sign(1.,(trackPar)(4,0)*(*fTrackPar)(4,0)) < 0) continue; // change of sign
936 //if (nHitsOK > -1) {
938 // Save current members
939 saveWeight = *fWeight;
940 savePosition = fPosition;
941 // temporary storage for the current track
943 trackParTmp = trackPar;
944 pointWeightTmp = pointWeight;
946 if (fgDebug > 0) cout << " Added point: " << x << " " << y << " " << dChi2 << endl;
948 // branching: create a new track
949 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
950 nRecTracks = fgTrackReconstructor->GetNRecTracks();
951 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
953 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
954 if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNTrackHits << " " << nRecTracks << endl;
955 trackK->fRecover = 0;
956 *(trackK->fTrackPar) = trackPar;
957 *(trackK->fWeight) += pointWeight;
958 trackK->fChi2 += dChi2;
961 *(trackK->fCovariance) = *(trackK->fWeight);
962 if (trackK->fCovariance->Determinant() != 0) {
964 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
966 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
968 // Add filtered matrices for the smoother
970 if (nHitsOK > 2) { // check for position adjustment
971 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
972 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
973 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
974 RemoveMatrices(trackK);
975 AliError(Form(" *** Position adjustment 1: %f %f", hit->GetZ(), (*trackK->fSteps)[i]));
980 AddMatrices (trackK, dChi2, hit);
982 // Mark hits as being on 2 tracks
983 for (Int_t i=0; i<fNTrackHits; i++) {
984 hitLoop = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i]);
985 hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
988 cout << hitLoop->GetChamberNumber() << " ";
989 cout << hitLoop->GetBendingCoor() << " ";
990 cout << hitLoop->GetNonBendingCoor() << " ";
991 cout << hitLoop->GetZ() << " " << " ";
992 cout << hitLoop->GetTrackRefSignal() << " " << " ";
993 cout << hitLoop->GetTTRTrack() << endl;
994 printf(" ** %d %10.4f %10.4f %10.4f %d %d \n",
995 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
996 hitLoop->GetNonBendingCoor(), hitLoop->GetZ(),
997 hitLoop->GetTrackRefSignal(), hitLoop->GetTTRTrack());
1001 trackK->fTrackHitsPtr->Add(hit); // add hit
1002 trackK->fNTrackHits ++;
1003 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
1006 trackK->fTrackDir = 1;
1007 trackK->fBPFlag = kTRUE;
1012 } else break; // different chamber
1013 } // for (ihit=currIndx;
1016 *fTrackPar = trackParTmp;
1017 *fWeight = saveWeight;
1018 *fWeight += pointWeightTmp;
1019 fChi2 += dChi2Tmp; // Chi2
1020 fPosition = savePosition;
1021 // Add filtered matrices for the smoother
1022 if (fTrackDir > 0) {
1023 for (Int_t i=fNSteps-1; i>=0; i--) {
1024 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
1025 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
1026 RemoveMatrices(this);
1027 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
1030 } // for (Int_t i=fNSteps-1;
1031 AddMatrices (this, dChi2Tmp, hitAdd);
1034 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1035 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1038 } // if (fTrackDir > 0)
1043 //__________________________________________________________________________
1044 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1046 // Adds a measurement point (modifies track parameters and computes
1049 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1050 TMatrixD wu = *fWeight;
1051 wu += pointWeight; // W+U
1052 trackParTmp = point;
1053 trackParTmp -= *fTrackParNew; // m-p
1054 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1055 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1056 right += right1; // U(m-p) + (W+U)p
1058 // check whether the Invert method returns flag if matrix cannot be inverted,
1059 // and do not calculate the Determinant in that case !!!!
1060 if (wu.Determinant() != 0) {
1062 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1064 AliWarning(" Determinant wu=0:");
1066 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1068 right1 = trackParTmp;
1069 right1 -= point; // p'-m
1070 point = trackParTmp;
1071 point -= *fTrackParNew; // p'-p
1072 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1073 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1075 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1076 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1077 dChi2 += value(0,0);
1081 //__________________________________________________________________________
1082 void AliMUONTrackK::MSThin(Int_t sign)
1084 // Adds multiple scattering in a thin layer (only angles are affected)
1085 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1087 // check whether the Invert method returns flag if matrix cannot be inverted,
1088 // and do not calculate the Determinant in that case !!!!
1089 if (fWeight->Determinant() != 0) {
1091 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1093 AliWarning(" Determinant fWeight=0:");
1096 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1097 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1098 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1099 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1100 velo = 1; // relativistic
1101 path = TMath::Abs(fgTrackReconstructor->GetChamberThicknessInX0()/cosAlph/cosBeta); // path length
1102 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1104 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1105 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1107 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1111 //__________________________________________________________________________
1112 void AliMUONTrackK::StartBack(void)
1114 // Starts backpropagator
1118 for (Int_t i=0; i<fgkSize; i++) {
1119 for (Int_t j=0; j<fgkSize; j++) {
1120 if (j==i) (*fWeight)(i,i) /= 100;
1121 //if (j==i) (*fWeight)(i,i) /= fNTrackHits*fNTrackHits;
1122 else (*fWeight)(j,i) = 0;
1125 // Sort hits on track in descending order in abs(z)
1126 SortHits(0, fTrackHitsPtr);
1129 //__________________________________________________________________________
1130 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1132 // Sort hits in Z if the seed segment in the last but one station
1133 // (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1135 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1136 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1137 Int_t i = 1, entries = array->GetEntriesFast();
1138 for ( ; i<entries; i++) {
1140 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1142 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1143 if (z < zmax) break;
1145 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1149 for (Int_t j=0; j<=(i-1)/2; j++) {
1150 TObject *hit = array->UncheckedAt(j);
1151 array->AddAt(array->UncheckedAt(i-j),j);
1152 array->AddAt(hit,i-j);
1154 if (fgDebug >= 10) {
1155 for (i=0; i<entries; i++)
1156 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1157 cout << " - Sort" << endl;
1161 //__________________________________________________________________________
1162 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1164 // Set vector of Geant3 parameters pointed to by "VGeant3"
1165 // from track parameters
1167 VGeant3[0] = (*fTrackParNew)(1,0); // X
1168 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1169 VGeant3[2] = fPositionNew; // Z
1170 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1171 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1172 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1173 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1176 //__________________________________________________________________________
1177 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1179 // Get track parameters from vector of Geant3 parameters pointed
1182 fPositionNew = VGeant3[2]; // Z
1183 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1184 (*fTrackParNew)(1,0) = VGeant3[0]; // X
1185 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1186 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1187 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1190 //__________________________________________________________________________
1191 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1193 // Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1196 AliWarning(Form(" *** Too high Chi2: %f ", fChi2));
1199 if (iChi2 == 0) fChi2 = fNTrackHits + (500.-fChi2)/501;
1200 else fChi2 = 500 - (fChi2-fNTrackHits)*501;
1203 //__________________________________________________________________________
1204 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1206 // "Compare" function to sort with decreasing "track quality".
1207 // Returns +1 (0, -1) if quality of current track
1208 // is smaller than (equal to, larger than) quality of trackK
1210 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1211 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1215 //__________________________________________________________________________
1216 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1218 // Check whether or not to keep current track
1219 // (keep, if it has less than half of common hits with track0)
1220 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1221 AliMUONHitForRec *hit0, *hit1;
1224 nHits0 = track0->fNTrackHits;
1225 nTrackHits2 = fNTrackHits/2;
1227 for (i=0; i<nHits0; i++) {
1228 // Check if hit belongs to several tracks
1229 hit0 = (AliMUONHitForRec*) (*track0->fTrackHitsPtr)[i];
1230 if (hit0->GetNTrackHits() == 1) continue;
1231 for (j=0; j<fNTrackHits; j++) {
1232 hit1 = (AliMUONHitForRec*) (*fTrackHitsPtr)[j];
1233 if (hit1->GetNTrackHits() == 1) continue;
1236 if (hitsInCommon >= nTrackHits2) return kFALSE;
1244 //__________________________________________________________________________
1245 void AliMUONTrackK::Kill(void)
1247 // Kill track candidate
1249 AliMUONHitForRec *hit;
1251 if (fTrackHitsPtr) {
1252 // Remove track mark from hits
1253 for (i=0; i<fNTrackHits; i++) {
1254 hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[i];
1255 hit->SetNTrackHits(hit->GetNTrackHits()-1);
1258 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1261 //__________________________________________________________________________
1262 void AliMUONTrackK::FillMUONTrack(void)
1264 // Compute track parameters at hit positions (as for AliMUONTrack)
1266 // Set number of hits per track
1267 ((AliMUONTrack*)this)->SetNTrackHits(fNTrackHits);
1269 // Set track parameters at vertex
1270 AliMUONTrackParam trackParam;
1271 SetTrackParam(&trackParam, fTrackPar, fPosition);
1272 ((AliMUONTrack*)this)->SetTrackParamAtVertex(&trackParam);
1274 // Set track parameters at hits
1275 for (Int_t i = fNTrackHits-1; i>=0; i--) {
1276 if ((*fChi2Smooth)[i] < 0) {
1277 // Propagate through last chambers
1278 trackParam.ExtrapToZ(((AliMUONHitForRec*)((*fTrackHitsPtr)[i]))->GetZ());
1281 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHitsPtr)[i]))->GetZ());
1283 ((AliMUONTrack*)this)->AddTrackParamAtHit(&trackParam);
1284 // Fill array of HitForRec's
1285 ((AliMUONTrack*)this)->AddHitForRecAtHit((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i));
1289 //__________________________________________________________________________
1290 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1292 // Fill AliMUONTrackParam object
1294 trackParam->SetBendingCoor((*par)(0,0));
1295 trackParam->SetNonBendingCoor((*par)(1,0));
1296 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1297 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1298 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1299 trackParam->SetZ(z);
1302 //__________________________________________________________________________
1303 void AliMUONTrackK::Branson(void)
1305 // Propagates track to the vertex thru absorber using Branson correction
1306 // (makes use of the AliMUONTrackParam class)
1308 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1309 AliMUONTrackParam trackParam = AliMUONTrackParam();
1311 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1312 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1313 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1314 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1315 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1316 trackParam->SetZ(fPosition);
1318 SetTrackParam(&trackParam, fTrackPar, fPosition);
1320 trackParam.ExtrapToVertex(Double_t(0.), Double_t(0.), Double_t(0.));
1321 //trackParam.ExtrapToVertex();
1323 (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1324 (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1325 (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1326 (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1327 (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1328 fPosition = trackParam.GetZ();
1329 //delete trackParam;
1330 if (fgDebug > 0) cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1332 // Get covariance matrix
1333 *fCovariance = *fWeight;
1334 if (fCovariance->Determinant() != 0) {
1336 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1338 AliWarning(" Determinant fCovariance=0:");
1342 //__________________________________________________________________________
1343 void AliMUONTrackK::GoToZ(Double_t zEnd)
1345 // Propagates track to given Z
1347 ParPropagation(zEnd);
1348 MSThin(1); // multiple scattering in the chamber
1349 WeightPropagation(zEnd, kFALSE);
1350 fPosition = fPositionNew;
1351 *fTrackPar = *fTrackParNew;
1354 //__________________________________________________________________________
1355 void AliMUONTrackK::GoToVertex(Int_t iflag)
1358 // Propagates track to the vertex
1359 // All material constants are taken from AliRoot
1361 static Double_t x01[5] = { 24.282, // C
1366 // inner part theta < 3 degrees
1367 static Double_t x02[5] = { 30413, // Air
1372 // z positions of the materials inside the absober outer part theta > 3 degres
1373 static Double_t zPos[10] = {-90, -105, -315, -443, -468};
1375 Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
1376 AliMUONHitForRec *hit;
1377 AliMUONRawCluster *clus;
1378 TClonesArray *rawclusters;
1380 // First step to the rear end of the absorber
1381 Double_t zRear = -503;
1383 Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1385 // Go through absorber
1386 pOld = 1/(*fTrackPar)(4,0);
1387 Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1388 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1389 r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
1391 Double_t p0, cos25, cos60;
1392 if (!iflag) goto vertex;
1394 for (Int_t i=4; i>=0; i--) {
1395 ParPropagation(zPos[i]);
1396 WeightPropagation(zPos[i], kFALSE);
1397 dZ = TMath::Abs (fPositionNew-fPosition);
1398 if (r0Norm > 1) x0 = x01[i];
1400 MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
1401 fPosition = fPositionNew;
1402 *fTrackPar = *fTrackParNew;
1403 r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1404 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1405 r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
1407 // Correct momentum for energy losses
1408 pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
1410 cos25 = TMath::Cos(2.5/180*TMath::Pi());
1411 cos60 = TMath::Cos(6.0/180*TMath::Pi());
1412 for (Int_t j=0; j<1; j++) {
1416 deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1418 deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1422 deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1424 deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1432 deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1434 deltaP = 3.0643 + 0.01346*p0;
1440 deltaP = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1442 deltaP = 2.407 + 0.00702*p0;
1451 deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1453 deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1460 deltaP = 2.209 + 0.800e-2*p0;
1462 deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1472 deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1474 deltaP = 3.0714 + 0.011767 * p0;
1479 deltaP = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1481 deltaP = 2.6069 + 0.0051705 * p0;
1487 p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
1489 (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1493 ParPropagation((Double_t)0.);
1494 WeightPropagation((Double_t)0., kFALSE);
1495 fPosition = fPositionNew;
1496 //*fTrackPar = *fTrackParNew;
1497 // Add vertex as a hit
1498 TMatrixD pointWeight(fgkSize,fgkSize);
1499 TMatrixD point(fgkSize,1);
1500 TMatrixD trackParTmp = point;
1501 point(0,0) = 0; // vertex coordinate - should be taken somewhere
1502 point(1,0) = 0; // vertex coordinate - should be taken somewhere
1503 pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1504 pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1505 TryPoint(point,pointWeight,trackParTmp,dChi2);
1506 *fTrackPar = trackParTmp;
1507 *fWeight += pointWeight;
1508 fChi2 += dChi2; // Chi2
1509 if (fgDebug < 0) return; // no output
1511 cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNTrackHits << endl;
1512 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1513 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1514 printf ("%4d", hit->GetChamberNumber());
1518 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1519 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1520 //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetHitNumber() << " ";
1521 //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetZ() << " ";
1522 printf ("%4d", fgHitForRec->IndexOf(hit));
1526 if (fgTrackReconstructor->GetRecTrackRefHits()) {
1527 // from track ref. hits
1528 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1529 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1530 cout << hit->GetTTRTrack() + hit->GetTrackRefSignal()*10000 << " ";
1533 // from raw clusters
1534 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1535 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1536 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1537 Int_t index = -hit->GetHitNumber() / 100000;
1538 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1539 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1541 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1542 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1544 printf ("%4d", clus->GetTrack(1));
1547 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1548 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1549 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1550 Int_t index = -hit->GetHitNumber() / 100000;
1551 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1552 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1554 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1555 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1557 if (clus->GetTrack(2) != -1) printf ("%4d", clus->GetTrack(2));
1558 else printf ("%4s", " ");
1562 for (Int_t i1=0; i1<fNTrackHits; i1++) {
1563 //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetHitNumber() << " ";
1564 cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetZ() << " ";
1565 //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))) << " ";
1568 for (Int_t i1=0; i1<fNTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1570 cout << "---------------------------------------------------" << endl;
1572 // Get covariance matrix
1573 /* Not needed - covariance matrix is not interesting to anybody
1574 *fCovariance = *fWeight;
1575 if (fCovariance->Determinant() != 0) {
1577 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1579 AliWarning(" Determinant fCovariance=0:" );
1584 //__________________________________________________________________________
1585 void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
1587 // Adds multiple scattering in a thick layer for linear propagation
1589 Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1590 Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1591 Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1593 sinBeta = TMath::Sin((*fTrackPar)(3,0));
1594 Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1595 Double_t momentum = 1/(*fTrackPar)(4,0);
1596 Double_t velo = 1; // relativistic velocity
1597 Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
1599 // Projected scattering angle
1600 Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0));
1601 Double_t theta02 = theta0*theta0;
1602 Double_t dl2 = step*step/2*theta02;
1603 Double_t dl3 = dl2*step*2/3;
1606 Double_t dYdT = 1/cosAlph;
1607 Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1608 Double_t dXdT = tanAlph*tanBeta;
1609 //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1610 Double_t dXdB = 1/cosBeta;
1611 Double_t dAdT = 1/cosBeta;
1612 Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1614 // Get covariance matrix
1615 *fCovariance = *fWeight;
1616 if (fCovariance->Determinant() != 0) {
1617 // fCovariance->Invert();
1619 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1621 AliWarning(" Determinant fCovariance=0:" );
1624 (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1625 (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1626 (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1627 (*fCovariance)(3,3) += theta02*step; // <bb>
1629 (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1630 (*fCovariance)(1,0) = (*fCovariance)(0,1);
1632 (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1633 (*fCovariance)(2,0) = (*fCovariance)(0,2);
1635 (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1636 (*fCovariance)(3,0) = (*fCovariance)(0,3);
1638 (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
1639 (*fCovariance)(2,1) = (*fCovariance)(1,2);
1641 (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1642 (*fCovariance)(3,1) = (*fCovariance)(1,3);
1644 (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1645 (*fCovariance)(3,2) = (*fCovariance)(2,3);
1647 // Get weight matrix
1648 *fWeight = *fCovariance;
1649 if (fWeight->Determinant() != 0) {
1651 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1653 AliWarning(" Determinant fWeight=0:");
1657 //__________________________________________________________________________
1658 Bool_t AliMUONTrackK::Recover(void)
1660 // Adds new failed track(s) which can be tried to be recovered
1662 TClonesArray *trackPtr;
1663 AliMUONTrackK *trackK;
1665 if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
1666 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1668 // Remove hit with the highest chi2
1671 for (Int_t i=0; i<fNTrackHits; i++) {
1672 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1673 printf("%10.4f", chi2);
1676 for (Int_t i=0; i<fNTrackHits; i++) {
1677 printf("%10d", ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i))->GetChamberNumber());
1681 Double_t chi2max = 0;
1683 for (Int_t i=0; i<fNTrackHits; i++) {
1684 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1685 if (chi2 < chi2max) continue;
1689 //if (chi2max < 10) return kFALSE; // !!!
1690 //if (chi2max < 25) imax = fNTrackHits - 1;
1691 if (chi2max < 15) imax = fNTrackHits - 1; // discard the last point
1692 // Check if the outlier is not from the seed segment
1693 AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(imax);
1694 if (skipHit == fStartSegment->GetHitForRec1() || skipHit == fStartSegment->GetHitForRec2()) {
1695 //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1696 return kFALSE; // to be changed probably
1699 // Make a copy of track hit collection
1700 TObjArray *hits = new TObjArray(*fTrackHitsPtr);
1704 // Hits after the found one will be removed
1705 if (GetStation0() == 3 && skipHit->GetChamberNumber() >= 7) {
1706 SortHits(1, fTrackHitsPtr); // unsort hits
1707 imax = fTrackHitsPtr->IndexOf(skipHit);
1709 Int_t nTrackHits = fNTrackHits;
1710 for (Int_t i=imax+1; i<nTrackHits; i++) {
1711 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(i);
1712 fTrackHitsPtr->Remove(hit);
1713 hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit
1717 // Check if the track candidate doesn't exist yet
1718 if (ExistDouble()) { delete hits; return kFALSE; }
1720 //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1723 nRecTracks = fgTrackReconstructor->GetNRecTracks();
1724 skipHit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[fNTrackHits-1]);
1725 // Remove all saved steps and smoother matrices after the skipped hit
1726 RemoveMatrices(skipHit->GetZ());
1728 //AZ(z->-z) if (skipHit->GetZ() > fStartSegment->GetHitForRec2()->GetZ() || !fNSteps) {
1729 if (TMath::Abs(skipHit->GetZ()) > TMath::Abs(fStartSegment->GetHitForRec2()->GetZ()) || !fNSteps) {
1730 // Propagation toward high Z or skipped hit next to segment -
1731 // start track from segment
1732 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
1733 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1734 trackK->fRecover = 1;
1735 trackK->fSkipHit = skipHit;
1736 trackK->fNTrackHits = fNTrackHits;
1737 delete trackK->fTrackHitsPtr; // not efficient ?
1738 trackK->fTrackHitsPtr = new TObjArray(*fTrackHitsPtr);
1739 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1743 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1745 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1746 //AZ(z->-z) trackK->fTrackDir = -1;
1747 trackK->fTrackDir = 1;
1748 trackK->fRecover = 1;
1749 trackK->fSkipHit = skipHit;
1750 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1752 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1753 CreateMatrix(trackK->fParFilter);
1755 trackK->fParFilter->Last()->SetUniqueID(iD);
1757 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1758 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1759 iD = trackK->fCovFilter->Last()->GetUniqueID();
1761 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1762 CreateMatrix(trackK->fCovFilter);
1764 trackK->fCovFilter->Last()->SetUniqueID(iD);
1766 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1767 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1768 if (trackK->fWeight->Determinant() != 0) {
1770 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1772 AliWarning(" Determinant fWeight=0:");
1774 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1776 for (Int_t i=0; i<fNTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1777 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1781 //__________________________________________________________________________
1782 void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1784 // Adds matrices for the smoother and keep Chi2 for the point
1786 //trackK->fParFilter->Last()->Print();
1787 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1789 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1790 CreateMatrix(trackK->fParFilter);
1793 *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1794 trackK->fParFilter->Last()->SetUniqueID(iD);
1796 cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1797 //trackK->fTrackPar->Print();
1798 //trackK->fTrackParNew->Print();
1799 trackK->fParFilter->Last()->Print();
1800 cout << " Add matrices" << endl;
1803 *(trackK->fCovariance) = *(trackK->fWeight);
1804 if (trackK->fCovariance->Determinant() != 0) {
1806 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1808 AliWarning(" Determinant fCovariance=0:");
1810 iD = trackK->fCovFilter->Last()->GetUniqueID();
1812 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1813 CreateMatrix(trackK->fCovFilter);
1816 *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1817 trackK->fCovFilter->Last()->SetUniqueID(iD);
1819 // Save Chi2-increment for point
1820 Int_t indx = trackK->fTrackHitsPtr->IndexOf(hitAdd);
1821 if (indx < 0) indx = fNTrackHits;
1822 if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10);
1823 trackK->fChi2Array->AddAt(dChi2,indx);
1826 //__________________________________________________________________________
1827 void AliMUONTrackK::CreateMatrix(TObjArray *objArray)
1829 // Create new matrix and add it to TObjArray
1831 TMatrixD *matrix = (TMatrixD*) objArray->First();
1832 TMatrixD *tmp = new TMatrixD(*matrix);
1833 objArray->AddAtAndExpand(tmp,objArray->GetLast());
1834 //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1837 //__________________________________________________________________________
1838 void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1840 // Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1842 for (Int_t i=fNSteps-1; i>=0; i--) {
1843 if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1844 if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1845 RemoveMatrices(this);
1846 } // for (Int_t i=fNSteps-1;
1849 //__________________________________________________________________________
1850 void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1852 // Remove last saved matrices and steps in the smoother part
1855 Int_t i = trackK->fNSteps;
1858 // Delete only matrices not shared by several tracks
1859 id = trackK->fParExtrap->Last()->GetUniqueID();
1861 trackK->fParExtrap->Last()->SetUniqueID(id-1);
1862 trackK->fParExtrap->RemoveAt(i);
1864 else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1865 id = fParFilter->Last()->GetUniqueID();
1867 trackK->fParFilter->Last()->SetUniqueID(id-1);
1868 trackK->fParFilter->RemoveAt(i);
1870 else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1871 id = trackK->fCovExtrap->Last()->GetUniqueID();
1873 trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1874 trackK->fCovExtrap->RemoveAt(i);
1876 else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1877 id = trackK->fCovFilter->Last()->GetUniqueID();
1879 trackK->fCovFilter->Last()->SetUniqueID(id-1);
1880 trackK->fCovFilter->RemoveAt(i);
1882 else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1883 id = trackK->fJacob->Last()->GetUniqueID();
1885 trackK->fJacob->Last()->SetUniqueID(id-1);
1886 trackK->fJacob->RemoveAt(i);
1888 else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1891 //__________________________________________________________________________
1892 Bool_t AliMUONTrackK::Smooth(void)
1895 Int_t ihit = fNTrackHits - 1;
1896 AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[ihit];
1897 fChi2Smooth = new TArrayD(fNTrackHits);
1898 fChi2Smooth->Reset(-1);
1900 fParSmooth = new TObjArray(15);
1901 fParSmooth->Clear();
1904 cout << " ******** Enter Smooth " << endl;
1905 cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl;
1907 for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1909 for (Int_t i=fNSteps-1; i>=0; i--) {cout << i << " " << (*fSteps)[i]; ((TMatrixD*)fParFilter->UncheckedAt(i))->Print(); ((TMatrixD*)fParExtrap->UncheckedAt(i))->Print(); ((TMatrixD*)fJacob->UncheckedAt(i))->Print();}
1911 for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHitsPtr)[i])->GetZ() << " ";
1915 // Find last point corresponding to the last hit
1916 Int_t iLast = fNSteps - 1;
1917 for ( ; iLast>=0; iLast--) {
1918 //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHitsPtr)[fNTrackHits-1])->GetZ()) break;
1919 if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHitsPtr)[fNTrackHits-1])->GetZ())) break;
1922 TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1924 TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1925 TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1926 TMatrixD tmpPar = *fTrackPar;
1927 //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print();
1930 Double_t chi2max = 0;
1931 for (Int_t i=iLast+1; i>0; i--) {
1932 if (i == iLast + 1) goto L33; // temporary fix
1934 // Smoother gain matrix
1935 weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1936 if (weight.Determinant() != 0) {
1938 mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1940 AliWarning(" Determinant weight=0:");
1943 tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
1944 gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
1945 //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
1947 // Smoothed parameter vector
1948 //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
1949 parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
1950 tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
1951 tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
1954 // Smoothed covariance
1955 covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1956 weight = TMatrixD(TMatrixD::kTransposed,gain);
1957 tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
1958 covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
1959 covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
1961 // Check if there was a measurement at given z
1963 for ( ; ihit>=0; ihit--) {
1964 hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[ihit];
1965 if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
1966 //AZ(z->-z) else if (ihit < fNTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
1967 else if (ihit < fNTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
1969 if (!found) continue; // no measurement - skip the rest
1970 else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
1971 if (ihit == 0) continue; // the first hit - skip the rest
1974 // Smoothed residuals
1976 tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
1977 tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
1979 cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
1980 cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
1982 // Cov. matrix of smoothed residuals
1984 tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
1985 tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
1986 tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
1987 tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
1989 // Calculate Chi2 of smoothed residuals
1990 if (tmp.Determinant() != 0) {
1992 mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1994 AliWarning(" Determinant tmp=0:");
1996 TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
1997 TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
1998 if (fgDebug > 1) chi2.Print();
1999 (*fChi2Smooth)[ihit] = chi2(0,0);
2000 if (chi2(0,0) > chi2max) chi2max = chi2(0,0);
2002 if (chi2(0,0) < 0) {
2004 AliError(Form(" *** chi2 < 0: %d %d ", i, iLast));
2006 // Save smoothed parameters
2007 TMatrixD *par = new TMatrixD(parSmooth);
2008 fParSmooth->AddAtAndExpand(par, ihit);
2010 } // for (Int_t i=iLast+1;
2012 //if (chi2max > 16) {
2013 //if (chi2max > 25) {
2014 //if (chi2max > 50) {
2015 //if (chi2max > 100) {
2016 if (chi2max > fgkChi2max) {
2017 //if (Recover()) DropBranches();
2025 //__________________________________________________________________________
2026 void AliMUONTrackK::Outlier()
2028 // Adds new track with removed hit having the highest chi2
2031 cout << " ******** Enter Outlier " << endl;
2032 for (Int_t i=0; i<fNTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
2034 for (Int_t i=0; i<fNTrackHits; i++) {
2035 printf("%10d", ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i))->GetChamberNumber());
2040 Double_t chi2max = 0;
2042 for (Int_t i=0; i<fNTrackHits; i++) {
2043 if ((*fChi2Smooth)[i] < chi2max) continue;
2044 chi2max = (*fChi2Smooth)[i];
2047 // Check if the outlier is not from the seed segment
2048 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(imax);
2049 if (hit == fStartSegment->GetHitForRec1() || hit == fStartSegment->GetHitForRec2()) return; // to be changed probably
2051 // Check for missing station
2054 if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(1))->GetChamberNumber() < 8) ok--;
2055 } else if (imax == fNTrackHits-1) {
2056 if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(fNTrackHits-2))->GetChamberNumber() > 1) ok--;
2058 else if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2059 if (!ok) { Recover(); return; } // try to recover track
2060 //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; }
2062 // Remove saved steps and smoother matrices after the outlier
2063 RemoveMatrices(hit->GetZ());
2065 // Check for possible double track candidates
2066 //if (ExistDouble(hit)) return;
2068 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2069 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2071 AliMUONTrackK *trackK = 0;
2072 if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2073 // start track from segment
2074 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
2075 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2076 trackK->fRecover = 2;
2077 trackK->fSkipHit = hit;
2078 trackK->fNTrackHits = fNTrackHits;
2079 delete trackK->fTrackHitsPtr; // not efficient ?
2080 trackK->fTrackHitsPtr = new TObjArray(*fTrackHitsPtr);
2081 if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHitsPtr);
2082 if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2085 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2087 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2088 trackK->fTrackDir = 1;
2089 trackK->fRecover = 2;
2090 trackK->fSkipHit = hit;
2091 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2093 trackK->fParFilter->Last()->SetUniqueID(iD-1);
2094 CreateMatrix(trackK->fParFilter);
2096 trackK->fParFilter->Last()->SetUniqueID(iD);
2098 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2099 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2100 iD = trackK->fCovFilter->Last()->GetUniqueID();
2102 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2103 CreateMatrix(trackK->fCovFilter);
2105 trackK->fCovFilter->Last()->SetUniqueID(iD);
2107 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2108 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2109 if (trackK->fWeight->Determinant() != 0) {
2111 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2113 AliWarning(" Determinant fWeight=0:");
2115 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2117 for (Int_t i=0; i<fNTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2118 if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2121 //__________________________________________________________________________
2122 Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2124 // Return Chi2 at point
2125 return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2129 //__________________________________________________________________________
2130 void AliMUONTrackK::Print(FILE *lun) const
2132 // Print out track information
2135 AliMUONHitForRec *hit = 0;
2136 if (fgTrackReconstructor->GetRecTrackRefHits()) {
2137 // from track ref. hits
2138 for (Int_t j=0; j<fNTrackHits; j++) {
2139 hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(j);
2140 if (hit->GetTTRTrack() > 1) { flag = 0; break; }
2142 for (Int_t j=0; j<fNTrackHits; j++) {
2143 printf("%10.4f", GetChi2PerPoint(j));
2144 if (GetChi2PerPoint(j) > -0.1) {
2145 hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(j);
2146 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(j));
2147 fprintf(lun, "%3d %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack(), flag);
2152 // from raw clusters
2153 AliMUONRawCluster *clus = 0;
2154 TClonesArray *rawclusters = 0;
2155 for (Int_t i1=0; i1<fNTrackHits; i1++) {
2156 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
2157 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2158 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2159 if (TMath::Abs(clus->GetTrack(1)-1) < 2) {
2160 if (clus->GetTrack(2)) flag = 2;
2163 if (clus->GetTrack(2) && TMath::Abs(clus->GetTrack(2)-1) < 2) {
2170 Int_t sig[2]={1,1}, tid[2]={0};
2171 for (Int_t i1=0; i1<fNTrackHits; i1++) {
2172 if (GetChi2PerPoint(i1) < -0.1) continue;
2173 hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
2174 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2175 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2176 for (Int_t j=0; j<2; j++) {
2177 tid[j] = clus->GetTrack(j+1) - 1;
2178 if (clus->GetTrack(j+1) < 0) { sig[j] = 0; tid[j] = 999; }
2180 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(i1));
2181 if (!(clus->GetTrack(2))) fprintf(lun, "%3d %3d", sig[0], tid[0]); // simple cluster
2182 else { // track overlap
2183 fprintf(lun, "%3d %3d", TMath::Max(sig[0],sig[1]), TMath::Min(tid[0],tid[1]));
2184 //if (tid[0] < 2) flag *= 2;
2185 //else if (tid[1] < 2) flag *= 3;
2187 fprintf (lun, "%3d \n", flag);
2192 //__________________________________________________________________________
2193 void AliMUONTrackK::DropBranches(Int_t imax, TObjArray *hits)
2195 // Drop branches downstream of the skipped hit
2197 TClonesArray *trackPtr;
2198 AliMUONTrackK *trackK;
2200 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2201 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2202 Int_t icand = trackPtr->IndexOf(this);
2203 if (!hits) hits = fTrackHitsPtr;
2205 // Check if the track candidate doesn't exist yet
2206 for (Int_t i=icand+1; i<nRecTracks; i++) {
2207 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2208 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2209 if (trackK->GetRecover() < 0) continue;
2211 if (trackK->fNTrackHits >= imax + 1) {
2212 for (Int_t j=0; j<=imax; j++) {
2213 //if (j != fNTrackHits-1 && (*trackK->fTrackHitsPtr)[j] != (*fTrackHitsPtr)[j]) break;
2214 if ((*trackK->fTrackHitsPtr)[j] != (*hits)[j]) break;
2216 if (hits != fTrackHitsPtr) {
2217 // Drop all branches downstream the hit (for Recover)
2218 trackK->SetRecover(-1);
2219 if (fgDebug >= 0 )cout << " Recover " << i << endl;
2222 // Check if the removal of the hit breaks the track
2225 if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2226 else if (imax == trackK->fNTrackHits-1) continue;
2227 // else if (imax == trackK->fNTrackHits-1) {
2228 //if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(trackK->fNTrackHits-2))->GetChamberNumber() > 1) ok--;
2230 else if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2231 if (!ok) trackK->SetRecover(-1);
2233 } // for (Int_t j=0;
2235 } // for (Int_t i=0;
2238 //__________________________________________________________________________
2239 void AliMUONTrackK::DropBranches(AliMUONSegment *segment)
2241 // Drop all candidates with the same seed segment
2243 TClonesArray *trackPtr;
2244 AliMUONTrackK *trackK;
2246 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2247 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2248 Int_t icand = trackPtr->IndexOf(this);
2250 for (Int_t i=icand+1; i<nRecTracks; i++) {
2251 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2252 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2253 if (trackK->GetRecover() < 0) continue;
2254 if (trackK->fStartSegment == segment) trackK->SetRecover(-1);
2256 if (fgDebug >= 0) cout << " Drop segment " << endl;
2259 //__________________________________________________________________________
2260 AliMUONHitForRec* AliMUONTrackK::GetHitLastOk(void)
2262 // Return the hit where track stopped
2264 if (!fNSteps) return (AliMUONHitForRec*)((*fTrackHitsPtr)[1]);
2268 //__________________________________________________________________________
2269 Int_t AliMUONTrackK::GetStation0(void)
2271 // Return seed station number
2272 return fStartSegment->GetHitForRec1()->GetChamberNumber() / 2;
2275 //__________________________________________________________________________
2276 Bool_t AliMUONTrackK::ExistDouble(AliMUONHitForRec *hit)
2278 // Check if the track will make a double after outlier removal
2280 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2281 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2282 TObjArray *hitArray = new TObjArray(*fTrackHitsPtr);
2283 TObjArray *hitArray1 = new TObjArray(*hitArray);
2284 hitArray1->Remove(hit);
2285 hitArray1->Compress();
2287 Bool_t same = kFALSE;
2288 for (Int_t i=0; i<nRecTracks; i++) {
2289 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2290 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2291 if (trackK == this) continue;
2292 if (trackK->fNTrackHits == fNTrackHits || trackK->fNTrackHits == fNTrackHits-1) {
2293 TObjArray *hits = new TObjArray(*trackK->fTrackHitsPtr);
2295 if (trackK->fNTrackHits == fNTrackHits) {
2296 for (Int_t j=0; j<fNTrackHits; j++) {
2297 if (hits->UncheckedAt(j) != hitArray->UncheckedAt(j)) { same = kFALSE; break; }
2299 if (same) { delete hits; break; }
2300 if (trackK->fSkipHit) {
2301 TObjArray *hits1 = new TObjArray(*hits);
2302 if (hits1->Remove(trackK->fSkipHit) > 0) {
2305 for (Int_t j=0; j<fNTrackHits-1; j++) {
2306 if (hits1->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2308 if (same) { delete hits1; break; }
2313 // Check with removed outlier
2315 for (Int_t j=0; j<fNTrackHits-1; j++) {
2316 if (hits->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2318 if (same) { delete hits; break; }
2322 } // for (Int_t i=0; i<nRecTracks;
2323 delete hitArray; delete hitArray1;
2324 if (same && fgDebug >= 0) cout << " Same" << endl;
2328 //__________________________________________________________________________
2329 Bool_t AliMUONTrackK::ExistDouble(void)
2331 // Check if the track will make a double after recovery
2333 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2334 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2336 TObjArray *hitArray = new TObjArray(*fTrackHitsPtr);
2337 if (GetStation0() == 3) SortHits(0, hitArray); // sort
2338 //if (GetStation0() == 3) SortHits(1, hitArray); // unsort
2340 Bool_t same = kFALSE;
2341 for (Int_t i=0; i<nRecTracks; i++) {
2342 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2343 if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2344 if (trackK == this) continue;
2345 //AZ if (trackK->GetRecover() < 0) continue; //
2346 if (trackK->fNTrackHits >= fNTrackHits) {
2347 TObjArray *hits = new TObjArray(*trackK->fTrackHitsPtr);
2348 if (trackK->GetStation0() == 3) SortHits(0, hits); // sort
2349 //if (trackK->GetStation0() == 3) SortHits(1, hits); // unsort
2350 for (Int_t j=0; j<fNTrackHits; j++) {
2351 //cout << fNTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2352 if (j != fNTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break;
2353 if (j == fNTrackHits-1) {
2354 if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE;
2355 //if (trackK->fNTrackHits > fNTrackHits &&
2356 //if (trackK->fSkipHit) cout << ((AliMUONHitForRec*)((*hitArray)[j]))->GetZ() << " " << trackK->fSkipHit->GetZ() << endl;
2358 } // for (Int_t j=0;
2362 } // for (Int_t i=0;