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 // ---------------------
19 // Class AliMUONTrackK
20 // ---------------------
21 // Reconstructed track in the muons system based on the extended
22 // Kalman filter approach
23 // Author: Alexander Zinchenko, JINR Dubna
25 #include <Riostream.h>
26 #include <TClonesArray.h>
30 #include "AliMUONTrackK.h"
32 #include "AliMUONConstants.h"
34 #include "AliMUONTrackReconstructorK.h"
36 #include "AliMUONSegment.h"
37 #include "AliMUONHitForRec.h"
38 #include "AliMUONRawCluster.h"
39 #include "AliMUONTrackParam.h"
40 #include "AliMUONEventRecoCombi.h"
41 #include "AliMUONDetElement.h"
46 ClassImp(AliMUONTrackK) // Class implementation in ROOT context
49 const Int_t AliMUONTrackK::fgkSize = 5;
50 const Int_t AliMUONTrackK::fgkNSigma = 12;
51 const Double_t AliMUONTrackK::fgkChi2max = 100;
52 const Int_t AliMUONTrackK::fgkTriesMax = 10000;
53 const Double_t AliMUONTrackK::fgkEpsilon = 0.002;
55 void mnvertLocal(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail); // from AliMUONTrack
57 Int_t AliMUONTrackK::fgDebug = -1; //-1;
58 Int_t AliMUONTrackK::fgNOfPoints = 0;
59 AliMUONTrackReconstructorK* AliMUONTrackK::fgTrackReconstructor = NULL;
60 TClonesArray* AliMUONTrackK::fgHitForRec = NULL;
61 AliMUONEventRecoCombi *AliMUONTrackK::fgCombi = NULL;
63 //__________________________________________________________________________
64 AliMUONTrackK::AliMUONTrackK()
91 /// Default constructor
93 fgTrackReconstructor = NULL; // pointer to event reconstructor
94 fgHitForRec = NULL; // pointer to points
95 fgNOfPoints = 0; // number of points
100 //__________________________________________________________________________
101 AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructorK *TrackReconstructor, TClonesArray *hitForRec)
130 if (!TrackReconstructor) return;
131 fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
132 fgHitForRec = hitForRec; // pointer to points
133 fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
135 if (fgTrackReconstructor->GetTrackMethod() == 3) fgCombi = AliMUONEventRecoCombi::Instance();
138 //__________________________________________________________________________
139 AliMUONTrackK::AliMUONTrackK(AliMUONSegment *segment)
140 //: AliMUONTrack(segment, segment, fgTrackReconstructor)
141 : AliMUONTrack(NULL, segment),
142 fStartSegment(segment),
146 fTrackHits(new TObjArray(13)),
152 fTrackPar(new TMatrixD(fgkSize,1)),
153 fTrackParNew(new TMatrixD(fgkSize,1)),
154 fCovariance(new TMatrixD(fgkSize,fgkSize)),
155 fWeight(new TMatrixD(fgkSize,fgkSize)),
156 fParExtrap(new TObjArray(15)),
157 fParFilter(new TObjArray(15)),
159 fCovExtrap(new TObjArray(15)),
160 fCovFilter(new TObjArray(15)),
161 fJacob(new TObjArray(15)),
163 fSteps(new TArrayD(15)),
164 fChi2Array(new TArrayD(13)),
167 /// Constructor from a segment
169 AliMUONHitForRec *hit1, *hit2;
170 AliMUONRawCluster *clus;
171 TClonesArray *rawclusters;
173 // Pointers to hits from the segment
174 hit1 = segment->GetHitForRec1();
175 hit2 = segment->GetHitForRec2();
176 hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
177 hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
178 // check sorting in Z
179 if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
181 hit2 = segment->GetHitForRec1();
184 // Fill array of track parameters
185 if (hit1->GetChamberNumber() > 7) {
186 // last tracking station
187 (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
188 (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
189 fPosition = hit1->GetZ(); // z
190 fTrackHits->Add(hit2); // add hit 2
191 fTrackHits->Add(hit1); // add hit 1
192 //AZ(Z->-Z) fTrackDir = -1;
195 // last but one tracking station
196 (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
197 (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
198 fPosition = hit2->GetZ(); // z
199 fTrackHits->Add(hit1); // add hit 1
200 fTrackHits->Add(hit2); // add hit 2
201 //AZ(Z->-Z) fTrackDir = 1;
204 dZ = hit2->GetZ() - hit1->GetZ();
205 dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
206 dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
207 (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
208 if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
209 (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
210 (*fTrackPar)(2,0) -= TMath::Pi();
211 (*fTrackPar)(4,0) = 1/fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()); // 1/Pt
212 (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
213 // Evaluate covariance (and weight) matrix
216 if (fgDebug < 0 ) return;
217 cout << fgTrackReconstructor->GetNRecTracks()-1 << " " << fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()) << " " << 1/(*fTrackPar)(4,0) << " ";
219 for (Int_t i=0; i<2; i++) {
220 hit1 = (AliMUONHitForRec*) ((*fTrackHits)[i]);
221 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
222 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
223 cout << clus->GetTrack(1);
224 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
225 if (i == 0) cout << " <--> ";
227 cout << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
231 //__________________________________________________________________________
232 AliMUONTrackK::~AliMUONTrackK()
237 //cout << fNmbTrackHits << endl;
238 for (Int_t i = 0; i < fNmbTrackHits; i++) {
239 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
240 hit->SetNTrackHits(hit->GetNTrackHits()-1);
242 delete fTrackHits; // delete the TObjArray of pointers to TrackHit's
246 delete fTrackPar; delete fTrackParNew; delete fCovariance;
250 if (fSteps) delete fSteps;
251 if (fChi2Array) delete fChi2Array;
252 if (fChi2Smooth) delete fChi2Smooth;
253 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
254 // Delete only matrices not shared by several tracks
255 if (!fParExtrap) return;
258 for (Int_t i=0; i<fNSteps; i++) {
259 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
260 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
261 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
263 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
264 fParExtrap->RemoveAt(i);
266 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
267 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
268 id = fParFilter->UncheckedAt(i)->GetUniqueID();
270 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
271 fParFilter->RemoveAt(i);
273 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
274 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
275 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
277 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
278 fCovExtrap->RemoveAt(i);
281 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
282 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
283 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
285 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
286 fCovFilter->RemoveAt(i);
288 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
289 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
290 id = fJacob->UncheckedAt(i)->GetUniqueID();
292 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
297 for (Int_t i=0; i<fNSteps; i++) {
298 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
299 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
300 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
301 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
302 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
303 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
306 fParExtrap->Delete(); fParFilter->Delete();
307 fCovExtrap->Delete(); fCovFilter->Delete();
309 delete fParExtrap; delete fParFilter;
310 delete fCovExtrap; delete fCovFilter;
314 //__________________________________________________________________________
315 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
317 /// Assignment operator
320 if(&source == this) return *this;
322 // base class assignement
323 //AZ TObject::operator=(source);
324 AliMUONTrack::operator=(source);
326 fStartSegment = source.fStartSegment;
327 fNmbTrackHits = source.fNmbTrackHits;
328 fChi2 = source.fChi2;
329 fPosition = source.fPosition;
330 fPositionNew = source.fPositionNew;
331 fTrackDir = source.fTrackDir;
332 fBPFlag = source.fBPFlag;
333 fRecover = source.fRecover;
334 fSkipHit = source.fSkipHit;
337 fTrackHits = new TObjArray(*source.fTrackHits);
338 //source.fTrackHits->Dump();
339 //fTrackHits->Dump();
340 for (Int_t i = 0; i < fNmbTrackHits; i++) {
341 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
342 hit->SetNTrackHits(hit->GetNTrackHits()+1);
345 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
346 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
347 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
348 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
351 fParExtrap = new TObjArray(*source.fParExtrap);
352 fParFilter = new TObjArray(*source.fParFilter);
353 fCovExtrap = new TObjArray(*source.fCovExtrap);
354 fCovFilter = new TObjArray(*source.fCovFilter);
355 fJacob = new TObjArray(*source.fJacob);
356 fSteps = new TArrayD(*source.fSteps);
357 fNSteps = source.fNSteps;
359 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
363 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
364 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
365 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
366 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
367 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
368 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
373 //__________________________________________________________________________
374 void AliMUONTrackK::EvalCovariance(Double_t dZ)
376 /// Evaluate covariance (and weight) matrix for track candidate
377 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
380 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
381 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
383 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
385 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
387 tanA = TMath::Tan((*fTrackPar)(2,0));
388 dAdY = 1/(1+tanA*tanA)/dZ;
389 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
390 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
391 (*fWeight)(2,0) = (*fWeight)(0,2);
393 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
394 tanB = TMath::Tan((*fTrackPar)(3,0));
395 dBdX = 1/(1+tanB*tanB)/rad;
397 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
398 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
399 (*fWeight)(3,1) = (*fWeight)(1,3);
401 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
403 // check whether the Invert method returns flag if matrix cannot be inverted,
404 // and do not calculate the Determinant in that case !!!!
405 if (fWeight->Determinant() != 0) {
406 // fWeight->Invert();
408 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
410 AliWarning(" Determinant fWeight=0:");
415 //__________________________________________________________________________
416 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
418 /// Follows track through detector stations
419 Bool_t miss, success;
420 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
421 Int_t ihit, firstIndx = -1, lastIndx = -1, currIndx = -1, iz0 = -1, iz = -1;
422 Double_t zEnd, dChi2;
423 AliMUONHitForRec *hitAdd, *firstHit = NULL, *lastHit = NULL, *hit;
424 AliMUONRawCluster *clus;
425 TClonesArray *rawclusters;
426 hit = 0; clus = 0; rawclusters = 0;
428 miss = success = kTRUE;
430 //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
431 iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
432 iMin = TMath::Min(ichamEnd,ichamBeg);
433 iMax = TMath::Max(ichamEnd,ichamBeg);
440 if (((AliMUONHitForRec*)fTrackHits->First())->GetChamberNumber() != ichamb) currIndx = 0;
441 } else if (fRecover) {
442 hit = GetHitLastOk();
443 currIndx = fTrackHits->IndexOf(hit);
444 if (currIndx < 0) hit = fStartSegment->GetHitForRec1(); // for station 3
446 ichamb = hit->GetChamberNumber();
447 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
448 // start from the last point or outlier
449 // remove the skipped hit
450 fTrackHits->Remove(fSkipHit); // remove hit
452 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
457 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
458 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetChamberNumber() == 6) ichambOK = 6;
459 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
460 fSkipHit->GetHitNumber() < 0) {
461 iz0 = fgCombi->IZfromHit(fSkipHit);
464 else currIndx = fgHitForRec->IndexOf(fSkipHit);
467 fTrackHits->Compress();
469 } // if (hit == fSkipHit)
470 else if (currIndx < 0) currIndx = fTrackHits->IndexOf(hit);
471 } // else if (fRecover)
473 // Get indices of the 1'st and last hits on the track candidate
474 firstHit = (AliMUONHitForRec*) fTrackHits->First();
475 lastHit = (AliMUONHitForRec*) fTrackHits->Last();
476 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
477 lastHit->GetHitNumber() < 0) iz0 = fgCombi->IZfromHit(lastHit);
479 firstIndx = fgHitForRec->IndexOf(firstHit);
480 lastIndx = fgHitForRec->IndexOf(lastHit);
481 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
485 if (iz0 < 0) iz0 = iFB;
486 while (ichamb >= iMin && ichamb <= iMax) {
487 // Find the closest hit in Z, not belonging to the current plane
490 if (currIndx < fNmbTrackHits) {
491 hitAdd = (AliMUONHitForRec*) fTrackHits->UncheckedAt(currIndx);
492 zEnd = hitAdd->GetZ();
493 //AZ(z->-z) } else zEnd = -9999;
496 //AZ(Z->-Z) zEnd = -9999;
498 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
499 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
500 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
501 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
502 zEnd = hitAdd->GetZ();
508 // Combined cluster / track finder
509 if (zEnd > 999 && iFB < 0 && fgTrackReconstructor->GetTrackMethod() == 3) {
511 AliMUONHitForRec hitTmp;
512 for (iz = iz0 - iFB; iz < fgCombi->Nz(); iz++) {
513 if (TMath::Abs(fgCombi->Z(iz)-fPosition) < 0.5) continue;
514 Int_t *pDEatZ = fgCombi->DEatZ(iz);
515 //cout << iz << " " << fgCombi->Z(iz) << endl;
516 zEnd = fgCombi->Z(iz);
518 AliMUONDetElement *detElem = fgCombi->DetElem(pDEatZ[0]);
520 hitAdd->SetChamberNumber(detElem->Chamber());
521 //hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
526 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
528 // Check if there is a chamber without hits
529 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
530 if (!Back && zEnd<999) currIndx -= iFB;
532 zEnd = AliMUONConstants::DefaultChamberZ(ichamb);
535 ichamb = hitAdd->GetChamberNumber();
539 if (ichamb<iMin || ichamb>iMax) break;
540 // Check for missing station
542 dChamb = TMath::Abs(ichamb-ichambOK);
543 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
544 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
545 if (zEnd > 999) dStatMiss++;
547 //if (dStatMiss == 2 && ichambOK/2 != 3 || dStatMiss > 2) { // AZ - missing st. 3
548 // missing station - abandon track
549 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
551 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
552 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
553 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
554 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
555 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
556 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
559 cout << fNmbTrackHits << endl;
560 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
561 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
562 printf(" * %d %10.4f %10.4f %10.4f",
563 hit->GetChamberNumber(), hit->GetBendingCoor(),
564 hit->GetNonBendingCoor(), hit->GetZ());
566 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
567 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
568 printf("%3d", clus->GetTrack(1)-1);
569 if (clus->GetTrack(2) != 0)
570 printf("%3d \n", clus->GetTrack(2)-1);
575 } // if (fgDebug >= 10)
576 if (fNmbTrackHits>2 && fRecover==0) Recover(); // try to recover track later
578 } // if (dStatMiss > 1)
580 if (endOfProp != 0) break;
582 // propagate to the found Z
584 // Check if track steps into dipole
585 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
586 if (fPosition<zDipole2 && zEnd>zDipole2) {
587 //LinearPropagation(zDipole2-zBeg);
588 ParPropagation(zDipole2);
589 MSThin(1); // multiple scattering in the chamber
590 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
591 fPosition = fPositionNew;
592 *fTrackPar = *fTrackParNew;
593 //MagnetPropagation(zEnd);
594 ParPropagation(zEnd);
595 WeightPropagation(zEnd, kTRUE);
596 fPosition = fPositionNew;
598 // Check if track steps out of dipole
599 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
600 else if (fPosition<zDipole1 && zEnd>zDipole1) {
601 //MagnetPropagation(zDipole1-zBeg);
602 ParPropagation(zDipole1);
603 MSThin(1); // multiple scattering in the chamber
604 WeightPropagation(zDipole1, kTRUE);
605 fPosition = fPositionNew;
606 *fTrackPar = *fTrackParNew;
607 //LinearPropagation(zEnd-zDipole1);
608 ParPropagation(zEnd);
609 WeightPropagation(zEnd, kTRUE);
610 fPosition = fPositionNew;
612 ParPropagation(zEnd);
613 //MSThin(1); // multiple scattering in the chamber
614 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
615 WeightPropagation(zEnd, kTRUE);
616 fPosition = fPositionNew;
620 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
621 // recovered track - remove the hit
623 ichamb = fSkipHit->GetChamberNumber();
624 // remove the skipped hit
625 fTrackHits->Remove(fSkipHit);
627 //AZ fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
630 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
631 //? if (fgTrackReconstructor->GetTrackMethod() != 3) currIndx = fgHitForRec->IndexOf(fSkipHit);
632 currIndx = fgHitForRec->IndexOf(fSkipHit);
636 // backward propagator
638 TMatrixD pointWeight(fgkSize,fgkSize);
639 TMatrixD point(fgkSize,1);
640 TMatrixD trackParTmp = point;
641 point(0,0) = hitAdd->GetBendingCoor();
642 point(1,0) = hitAdd->GetNonBendingCoor();
643 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
644 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
645 TryPoint(point,pointWeight,trackParTmp,dChi2);
646 *fTrackPar = trackParTmp;
647 *fWeight += pointWeight;
648 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
649 fChi2 += dChi2; // Chi2
650 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
651 if (ichamb==ichamEnd) break;
654 // forward propagator
655 if (miss || !FindPoint(ichamb, zEnd, currIndx, iFB, hitAdd, iz)) {
657 *fTrackPar = *fTrackParNew;
660 fTrackHits->Add(hitAdd); // add hit
662 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
664 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
668 if (fgDebug > 0) cout << fNmbTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
669 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
673 //__________________________________________________________________________
674 void AliMUONTrackK::ParPropagation(Double_t zEnd)
676 /// Propagation of track parameters to zEnd
678 Double_t dZ, step, distance, charge;
679 Double_t vGeant3[7], vGeant3New[7];
680 AliMUONTrackParam trackParam;
683 // First step using linear extrapolation
684 dZ = zEnd - fPosition;
685 fPositionNew = fPosition;
686 *fTrackParNew = *fTrackPar;
687 if (dZ == 0) return; //AZ ???
688 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
689 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
690 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
691 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
692 SetGeantParam(vGeant3,iFB);
693 //fTrackParNew->Print();
697 step = TMath::Abs(step);
698 // Propagate parameters
699 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
700 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
701 distance = zEnd - vGeant3New[2];
702 step *= dZ/(vGeant3New[2]-fPositionNew);
704 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
706 GetFromGeantParam(vGeant3New,iFB);
707 //fTrackParNew->Print();
709 // Position adjustment (until within tolerance)
710 while (TMath::Abs(distance) > fgkEpsilon) {
711 dZ = zEnd - fPositionNew;
712 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
713 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
714 step = TMath::Abs(step);
715 SetGeantParam(vGeant3,iFB);
718 // Propagate parameters
719 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
720 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
721 distance = zEnd - vGeant3New[2];
724 if (nTries > fgkTriesMax) AliError(Form(" Too many tries: %d", nTries));
725 } while (distance*iFB < 0);
727 GetFromGeantParam(vGeant3New,iFB);
729 //cout << nTries << endl;
730 //fTrackParNew->Print();
734 //__________________________________________________________________________
735 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
737 /// Propagation of the weight matrix
738 /// W = DtWD, where D is Jacobian
742 TMatrixD jacob(fgkSize,fgkSize);
745 // Save initial and propagated parameters
746 TMatrixD trackPar0 = *fTrackPar;
747 TMatrixD trackParNew0 = *fTrackParNew;
749 // Get covariance matrix
750 *fCovariance = *fWeight;
751 // check whether the Invert method returns flag if matrix cannot be inverted,
752 // and do not calculate the Determinant in that case !!!!
753 if (fCovariance->Determinant() != 0) {
755 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
756 //fCovariance->Print();
758 AliWarning(" Determinant fCovariance=0:");
761 // Loop over parameters to find change of the propagated vs initial ones
762 for (i=0; i<fgkSize; i++) {
763 dPar = TMath::Sqrt((*fCovariance)(i,i));
764 *fTrackPar = trackPar0;
765 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
766 (*fTrackPar)(i,0) += dPar;
767 ParPropagation(zEnd);
768 for (j=0; j<fgkSize; j++) {
769 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
773 //trackParNew0.Print();
774 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
776 TMatrixD jacob0 = jacob;
777 if (jacob.Determinant() != 0) {
780 AliWarning(" Determinant jacob=0:");
782 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
783 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
785 // Restore initial and propagated parameters
786 *fTrackPar = trackPar0;
787 *fTrackParNew = trackParNew0;
790 if (!smooth) return; // do not use smoother
791 if (fTrackDir < 0) return; // only for propagation towards int. point
792 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
793 fParExtrap->Add(tmp);
795 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
796 fParFilter->Add(tmp);
798 *fCovariance = *fWeight;
799 if (fCovariance->Determinant() != 0) {
801 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
803 AliWarning(" Determinant fCovariance=0:");
805 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
806 fCovExtrap->Add(tmp);
808 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
809 fCovFilter->Add(tmp);
811 tmp = new TMatrixD(jacob0); // Jacobian
814 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
815 fSteps->AddAt(fPositionNew,fNSteps++);
816 if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
820 //__________________________________________________________________________
821 Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd, Int_t iz)
823 /// Picks up point within a window for the chamber No ichamb
824 /// Split the track if there are more than 1 hit
825 Int_t ihit, nRecTracks;
826 Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
827 TClonesArray *trackPtr;
828 AliMUONHitForRec *hit, *hitLoop;
829 AliMUONTrackK *trackK;
830 AliMUONDetElement *detElem = NULL;
834 if (fgTrackReconstructor->GetTrackMethod() == 3 && iz >= 0) {
835 // Combined cluster / track finder
836 // Check if extrapolated track passes thru det. elems. at iz
837 Int_t *pDEatZ = fgCombi->DEatZ(iz);
838 Int_t nDetElem = pDEatZ[-1];
839 //cout << fgCombi->Z(iz) << " " << nDetElem << endl;
840 for (Int_t i = 0; i < nDetElem; i++) {
841 detElem = fgCombi->DetElem(pDEatZ[i]);
842 if (detElem->Inside((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPosition)) {
843 detElem->ClusterReco((*fTrackParNew)(1,0), (*fTrackParNew)(0,0));
844 hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
849 if (!ok) return ok; // outside det. elem.
853 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
854 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
855 *fCovariance = *fWeight;
856 // check whether the Invert method returns flag if matrix cannot be inverted,
857 // and do not calculate the Determinant in that case !!!!
858 if (fCovariance->Determinant() != 0) {
860 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
862 AliWarning(" Determinant fCovariance=0:");
864 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
865 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
866 // Loop over all hits and take hits from the chamber
867 TMatrixD pointWeight(fgkSize,fgkSize);
868 TMatrixD saveWeight = pointWeight;
869 TMatrixD pointWeightTmp = pointWeight;
870 TMatrixD point(fgkSize,1);
871 TMatrixD trackPar = point;
872 TMatrixD trackParTmp = point;
873 Int_t nHitsOK = 0, ihitB = currIndx, ihitE = fgNOfPoints, iDhit = iFB;
875 zLast = ((AliMUONHitForRec*)fTrackHits->Last())->GetZ();
876 if (fgTrackReconstructor->GetTrackMethod() == 3 && detElem) {
878 ihitE = detElem->NHitsForRec();
883 for (ihit = ihitB; ihit >= 0 && ihit < ihitE; ihit+=iDhit) {
884 if (fgTrackReconstructor->GetTrackMethod() != 3 || !detElem)
885 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
886 else hit = (AliMUONHitForRec*) detElem->HitsForRec()->UncheckedAt(ihit);
887 if (hit->GetChamberNumber() == ichamb) {
888 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
889 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
890 y = hit->GetBendingCoor();
891 x = hit->GetNonBendingCoor();
892 if (hit->GetBendingReso2() < 0) {
893 // Combined cluster / track finder
894 hit->SetBendingReso2(fgTrackReconstructor->GetBendingResolution()*
895 fgTrackReconstructor->GetBendingResolution());
896 hit->SetNonBendingReso2(fgTrackReconstructor->GetNonBendingResolution()*
897 fgTrackReconstructor->GetNonBendingResolution());
899 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
900 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
902 // windowB = TMath::Min (windowB,5.);
903 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
905 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
906 windowB = TMath::Min (windowB,0.5);
907 windowNonB = TMath::Min (windowNonB,3.);
908 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
909 windowB = TMath::Min (windowB,1.5);
910 windowNonB = TMath::Min (windowNonB,3.);
911 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
912 windowB = TMath::Min (windowB,4.);
913 windowNonB = TMath::Min (windowNonB,6.);
919 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
920 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
921 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
923 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
924 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
928 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
929 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
930 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
931 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
932 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
933 // hit->GetTrackRefSignal() == 1) { // just for test
934 // Vector of measurements and covariance matrix
935 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
936 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
937 // Adjust position: for multiple hits in the chamber or misalignment (Z as a function of X or Y)
938 //AliWarning(Form(" *** adjust %f %f ", zEnd, hit->GetZ()));
940 *fTrackPar = *fTrackParNew;
941 ParPropagation(zEnd);
942 WeightPropagation(zEnd, kTRUE);
943 fPosition = fPositionNew;
944 *fTrackPar = *fTrackParNew;
946 *fCovariance = *fWeight;
947 if (fCovariance->Determinant() != 0) {
949 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
951 AliWarning(" Determinant fCovariance=0:" );
957 pointWeight(0,0) = 1/hit->GetBendingReso2();
958 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
959 TryPoint(point,pointWeight,trackPar,dChi2);
960 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
961 // if (TMath::Sign(1.,(trackPar)(4,0)*(*fTrackPar)(4,0)) < 0) continue; // change of sign
964 //if (nHitsOK > -1) {
966 // Save current members
967 saveWeight = *fWeight;
968 savePosition = fPosition;
969 // temporary storage for the current track
971 trackParTmp = trackPar;
972 pointWeightTmp = pointWeight;
974 if (fgDebug > 0) cout << " Added point: " << x << " " << y << " " << dChi2 << endl;
976 // branching: create a new track
977 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
978 nRecTracks = fgTrackReconstructor->GetNRecTracks();
979 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
981 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
982 if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNmbTrackHits << " " << nRecTracks << endl;
983 trackK->fRecover = 0;
984 *(trackK->fTrackPar) = trackPar;
985 *(trackK->fWeight) += pointWeight;
986 trackK->fChi2 += dChi2;
989 *(trackK->fCovariance) = *(trackK->fWeight);
990 if (trackK->fCovariance->Determinant() != 0) {
992 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
994 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
996 // Add filtered matrices for the smoother
998 if (nHitsOK > 2) { // check for position adjustment
999 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
1000 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
1001 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
1002 RemoveMatrices(trackK);
1003 AliError(Form(" *** Position adjustment 1: %f %f", hit->GetZ(), (*trackK->fSteps)[i]));
1008 AddMatrices (trackK, dChi2, hit);
1010 // Mark hits as being on 2 tracks
1011 for (Int_t i=0; i<fNmbTrackHits; i++) {
1012 hitLoop = (AliMUONHitForRec*) ((*fTrackHits)[i]);
1013 //AZ hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
1016 cout << hitLoop->GetChamberNumber() << " ";
1017 cout << hitLoop->GetBendingCoor() << " ";
1018 cout << hitLoop->GetNonBendingCoor() << " ";
1019 cout << hitLoop->GetZ() << " " << " ";
1020 cout << hitLoop->GetTTRTrack() << endl;
1021 printf(" ** %d %10.4f %10.4f %10.4f\n",
1022 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
1023 hitLoop->GetNonBendingCoor(), hitLoop->GetZ());
1027 trackK->fTrackHits->Add(hit); // add hit
1028 trackK->fNmbTrackHits ++;
1029 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
1032 trackK->fTrackDir = 1;
1033 trackK->fBPFlag = kTRUE;
1038 } else break; // different chamber
1039 } // for (ihit=currIndx;
1042 *fTrackPar = trackParTmp;
1043 *fWeight = saveWeight;
1044 *fWeight += pointWeightTmp;
1045 fChi2 += dChi2Tmp; // Chi2
1046 fPosition = savePosition;
1047 // Add filtered matrices for the smoother
1048 if (fTrackDir > 0) {
1049 for (Int_t i=fNSteps-1; i>=0; i--) {
1050 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
1051 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
1052 RemoveMatrices(this);
1053 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
1056 } // for (Int_t i=fNSteps-1;
1057 AddMatrices (this, dChi2Tmp, hitAdd);
1060 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1061 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1064 } // if (fTrackDir > 0)
1069 //__________________________________________________________________________
1070 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1072 /// Adds a measurement point (modifies track parameters and computes
1075 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1076 TMatrixD wu = *fWeight;
1077 wu += pointWeight; // W+U
1078 trackParTmp = point;
1079 trackParTmp -= *fTrackParNew; // m-p
1080 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1081 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1082 right += right1; // U(m-p) + (W+U)p
1084 // check whether the Invert method returns flag if matrix cannot be inverted,
1085 // and do not calculate the Determinant in that case !!!!
1086 if (wu.Determinant() != 0) {
1088 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1090 AliWarning(" Determinant wu=0:");
1092 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1094 right1 = trackParTmp;
1095 right1 -= point; // p'-m
1096 point = trackParTmp;
1097 point -= *fTrackParNew; // p'-p
1098 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1099 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1101 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1102 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1103 dChi2 += value(0,0);
1107 //__________________________________________________________________________
1108 void AliMUONTrackK::MSThin(Int_t sign)
1110 /// Adds multiple scattering in a thin layer (only angles are affected)
1111 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1113 // check whether the Invert method returns flag if matrix cannot be inverted,
1114 // and do not calculate the Determinant in that case !!!!
1115 if (fWeight->Determinant() != 0) {
1117 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1119 AliWarning(" Determinant fWeight=0:");
1122 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1123 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1124 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1125 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1126 velo = 1; // relativistic
1127 path = TMath::Abs(fgTrackReconstructor->GetChamberThicknessInX0()/cosAlph/cosBeta); // path length
1128 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1130 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1131 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1133 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1137 //__________________________________________________________________________
1138 void AliMUONTrackK::StartBack(void)
1140 /// Starts backpropagator
1144 for (Int_t i=0; i<fgkSize; i++) {
1145 for (Int_t j=0; j<fgkSize; j++) {
1146 if (j==i) (*fWeight)(i,i) /= 100;
1147 //if (j==i) (*fWeight)(i,i) /= fNmbTrackHits*fNmbTrackHits;
1148 else (*fWeight)(j,i) = 0;
1151 // Sort hits on track in descending order in abs(z)
1152 SortHits(0, fTrackHits);
1155 //__________________________________________________________________________
1156 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1158 /// Sort hits in Z if the seed segment in the last but one station
1159 /// (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1161 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1162 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1163 Int_t i = 1, entries = array->GetEntriesFast();
1164 for ( ; i<entries; i++) {
1166 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1168 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1169 if (z < zmax) break;
1171 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1175 for (Int_t j=0; j<=(i-1)/2; j++) {
1176 TObject *hit = array->UncheckedAt(j);
1177 array->AddAt(array->UncheckedAt(i-j),j);
1178 array->AddAt(hit,i-j);
1180 if (fgDebug >= 10) {
1181 for (i=0; i<entries; i++)
1182 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1183 cout << " - Sort" << endl;
1187 //__________________________________________________________________________
1188 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1190 /// Set vector of Geant3 parameters pointed to by "VGeant3"
1191 /// from track parameters
1193 VGeant3[0] = (*fTrackParNew)(1,0); // X
1194 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1195 VGeant3[2] = fPositionNew; // Z
1196 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1197 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1198 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1199 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1202 //__________________________________________________________________________
1203 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1205 /// Get track parameters from vector of Geant3 parameters pointed
1208 fPositionNew = VGeant3[2]; // Z
1209 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1210 (*fTrackParNew)(1,0) = VGeant3[0]; // X
1211 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1212 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1213 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1216 //__________________________________________________________________________
1217 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1219 /// Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1222 AliWarning(Form(" *** Too high Chi2: %f ", fChi2));
1225 if (iChi2 == 0) fChi2 = fNmbTrackHits + (500.-fChi2)/501;
1226 else fChi2 = 500 - (fChi2-fNmbTrackHits)*501;
1229 //__________________________________________________________________________
1230 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1232 /// "Compare" function to sort with decreasing "track quality".
1233 /// Returns +1 (0, -1) if quality of current track
1234 /// is smaller than (equal to, larger than) quality of trackK
1236 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1237 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1241 //__________________________________________________________________________
1242 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1244 /// Check whether or not to keep current track
1245 /// (keep, if it has less than half of common hits with track0)
1246 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1247 AliMUONHitForRec *hit0, *hit1;
1250 nHits0 = track0->fNmbTrackHits;
1251 nTrackHits2 = fNmbTrackHits/2;
1253 for (i=0; i<nHits0; i++) {
1254 // Check if hit belongs to several tracks
1255 hit0 = (AliMUONHitForRec*) (*track0->fTrackHits)[i];
1256 if (hit0->GetNTrackHits() == 1) continue;
1257 for (j=0; j<fNmbTrackHits; j++) {
1258 hit1 = (AliMUONHitForRec*) (*fTrackHits)[j];
1259 if (hit1->GetNTrackHits() == 1) continue;
1262 if (hitsInCommon >= nTrackHits2) return kFALSE;
1270 //__________________________________________________________________________
1271 void AliMUONTrackK::Kill(void)
1273 /// Kill track candidate
1274 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1277 //__________________________________________________________________________
1278 void AliMUONTrackK::FillMUONTrack(void)
1280 /// Compute track parameters at hit positions (as for AliMUONTrack)
1285 // Set track parameters at vertex
1286 AliMUONTrackParam trackParam;
1287 SetTrackParam(&trackParam, fTrackPar, fPosition);
1288 SetTrackParamAtVertex(&trackParam);
1290 // Set track parameters at hits
1291 for (Int_t i = fNmbTrackHits-1; i>=0; i--) {
1292 if ((*fChi2Smooth)[i] < 0) {
1293 // Propagate through last chambers
1294 trackParam.ExtrapToZ(((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1297 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1299 AddTrackParamAtHit(&trackParam,(AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1300 // Fill array of HitForRec's
1301 AddHitForRecAtHit((AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1305 //__________________________________________________________________________
1306 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1308 /// Fill AliMUONTrackParam object
1310 trackParam->SetBendingCoor((*par)(0,0));
1311 trackParam->SetNonBendingCoor((*par)(1,0));
1312 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1313 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1314 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1315 trackParam->SetZ(z);
1318 //__________________________________________________________________________
1319 void AliMUONTrackK::Branson(void)
1321 /// Propagates track to the vertex thru absorber using Branson correction
1322 /// (makes use of the AliMUONTrackParam class)
1324 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1325 AliMUONTrackParam trackParam = AliMUONTrackParam();
1327 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1328 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1329 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1330 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1331 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1332 trackParam->SetZ(fPosition);
1334 SetTrackParam(&trackParam, fTrackPar, fPosition);
1336 trackParam.ExtrapToVertex(Double_t(0.), Double_t(0.), Double_t(0.));
1337 //trackParam.ExtrapToVertex();
1339 (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1340 (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1341 (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1342 (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1343 (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1344 fPosition = trackParam.GetZ();
1345 //delete trackParam;
1346 if (fgDebug > 0) cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1348 // Get covariance matrix
1349 *fCovariance = *fWeight;
1350 if (fCovariance->Determinant() != 0) {
1352 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1354 AliWarning(" Determinant fCovariance=0:");
1358 //__________________________________________________________________________
1359 void AliMUONTrackK::GoToZ(Double_t zEnd)
1361 /// Propagates track to given Z
1363 ParPropagation(zEnd);
1364 MSThin(1); // multiple scattering in the chamber
1365 WeightPropagation(zEnd, kFALSE);
1366 fPosition = fPositionNew;
1367 *fTrackPar = *fTrackParNew;
1370 //__________________________________________________________________________
1371 void AliMUONTrackK::GoToVertex(Int_t iflag)
1374 /// Propagates track to the vertex
1375 /// All material constants are taken from AliRoot
1377 static Double_t x01[5] = { 24.282, // C
1382 // inner part theta < 3 degrees
1383 static Double_t x02[5] = { 30413, // Air
1388 // z positions of the materials inside the absober outer part theta > 3 degres
1389 static Double_t zPos[10] = {-90, -105, -315, -443, -468};
1391 Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
1392 AliMUONHitForRec *hit;
1393 AliMUONRawCluster *clus;
1394 TClonesArray *rawclusters;
1396 // First step to the rear end of the absorber
1397 Double_t zRear = -503;
1399 Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1401 // Go through absorber
1402 pOld = 1/(*fTrackPar)(4,0);
1403 Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1404 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1405 r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
1407 Double_t p0, cos25, cos60;
1408 if (!iflag) goto vertex;
1410 for (Int_t i=4; i>=0; i--) {
1411 ParPropagation(zPos[i]);
1412 WeightPropagation(zPos[i], kFALSE);
1413 dZ = TMath::Abs (fPositionNew-fPosition);
1414 if (r0Norm > 1) x0 = x01[i];
1416 MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
1417 fPosition = fPositionNew;
1418 *fTrackPar = *fTrackParNew;
1419 r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1420 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1421 r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
1423 // Correct momentum for energy losses
1424 pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
1426 cos25 = TMath::Cos(2.5/180*TMath::Pi());
1427 cos60 = TMath::Cos(6.0/180*TMath::Pi());
1428 for (Int_t j=0; j<1; j++) {
1432 deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1434 deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1438 deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1440 deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1448 deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1450 deltaP = 3.0643 + 0.01346*p0;
1456 deltaP = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1458 deltaP = 2.407 + 0.00702*p0;
1467 deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1469 deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1476 deltaP = 2.209 + 0.800e-2*p0;
1478 deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1488 deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1490 deltaP = 3.0714 + 0.011767 * p0;
1495 deltaP = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1497 deltaP = 2.6069 + 0.0051705 * p0;
1503 p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
1505 (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1509 ParPropagation((Double_t)0.);
1510 WeightPropagation((Double_t)0., kFALSE);
1511 fPosition = fPositionNew;
1512 //*fTrackPar = *fTrackParNew;
1513 // Add vertex as a hit
1514 TMatrixD pointWeight(fgkSize,fgkSize);
1515 TMatrixD point(fgkSize,1);
1516 TMatrixD trackParTmp = point;
1517 point(0,0) = 0; // vertex coordinate - should be taken somewhere
1518 point(1,0) = 0; // vertex coordinate - should be taken somewhere
1519 pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1520 pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1521 TryPoint(point,pointWeight,trackParTmp,dChi2);
1522 *fTrackPar = trackParTmp;
1523 *fWeight += pointWeight;
1524 fChi2 += dChi2; // Chi2
1525 if (fgDebug < 0) return; // no output
1527 cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNmbTrackHits << endl;
1528 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1529 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1530 printf ("%5d", hit->GetChamberNumber());
1534 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1535 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1536 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1537 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1538 printf ("%5d", fgHitForRec->IndexOf(hit));
1543 // from raw clusters
1544 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1545 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1546 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1547 Int_t index = -hit->GetHitNumber() / 100000;
1548 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1549 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1551 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1552 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1554 printf ("%5d", clus->GetTrack(1)%10000000);
1557 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1558 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1559 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1560 Int_t index = -hit->GetHitNumber() / 100000;
1561 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1562 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1564 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1565 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1567 if (clus->GetTrack(2) != -1) printf ("%5d", clus->GetTrack(2)%10000000);
1568 else printf ("%5s", " ");
1572 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1573 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1574 cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1575 //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHits)[i1]))) << " ";
1578 for (Int_t i1=0; i1<fNmbTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1580 cout << "---------------------------------------------------" << endl;
1582 // Get covariance matrix
1583 /* Not needed - covariance matrix is not interesting to anybody
1584 *fCovariance = *fWeight;
1585 if (fCovariance->Determinant() != 0) {
1587 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1589 AliWarning(" Determinant fCovariance=0:" );
1594 //__________________________________________________________________________
1595 void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
1597 /// Adds multiple scattering in a thick layer for linear propagation
1599 Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1600 Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1601 Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1603 sinBeta = TMath::Sin((*fTrackPar)(3,0));
1604 Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1605 Double_t momentum = 1/(*fTrackPar)(4,0);
1606 Double_t velo = 1; // relativistic velocity
1607 Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
1609 // Projected scattering angle
1610 Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0));
1611 Double_t theta02 = theta0*theta0;
1612 Double_t dl2 = step*step/2*theta02;
1613 Double_t dl3 = dl2*step*2/3;
1616 Double_t dYdT = 1/cosAlph;
1617 Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1618 Double_t dXdT = tanAlph*tanBeta;
1619 //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1620 Double_t dXdB = 1/cosBeta;
1621 Double_t dAdT = 1/cosBeta;
1622 Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1624 // Get covariance matrix
1625 *fCovariance = *fWeight;
1626 if (fCovariance->Determinant() != 0) {
1627 // fCovariance->Invert();
1629 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1631 AliWarning(" Determinant fCovariance=0:" );
1634 (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1635 (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1636 (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1637 (*fCovariance)(3,3) += theta02*step; // <bb>
1639 (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1640 (*fCovariance)(1,0) = (*fCovariance)(0,1);
1642 (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1643 (*fCovariance)(2,0) = (*fCovariance)(0,2);
1645 (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1646 (*fCovariance)(3,0) = (*fCovariance)(0,3);
1648 (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
1649 (*fCovariance)(2,1) = (*fCovariance)(1,2);
1651 (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1652 (*fCovariance)(3,1) = (*fCovariance)(1,3);
1654 (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1655 (*fCovariance)(3,2) = (*fCovariance)(2,3);
1657 // Get weight matrix
1658 *fWeight = *fCovariance;
1659 if (fWeight->Determinant() != 0) {
1661 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1663 AliWarning(" Determinant fWeight=0:");
1667 //__________________________________________________________________________
1668 Bool_t AliMUONTrackK::Recover(void)
1670 /// Adds new failed track(s) which can be tried to be recovered
1672 TClonesArray *trackPtr;
1673 AliMUONTrackK *trackK;
1675 if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
1676 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1678 // Remove hit with the highest chi2
1681 for (Int_t i=0; i<fNmbTrackHits; i++) {
1682 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1683 printf("%10.4f", chi2);
1686 for (Int_t i=0; i<fNmbTrackHits; i++) {
1687 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
1691 Double_t chi2max = 0;
1693 for (Int_t i=0; i<fNmbTrackHits; i++) {
1694 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1695 if (chi2 < chi2max) continue;
1699 //if (chi2max < 10) return kFALSE; // !!!
1700 //if (chi2max < 25) imax = fNmbTrackHits - 1;
1701 if (chi2max < 15) imax = fNmbTrackHits - 1; // discard the last point
1702 // Check if the outlier is not from the seed segment
1703 AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
1704 if (skipHit == fStartSegment->GetHitForRec1() || skipHit == fStartSegment->GetHitForRec2()) {
1705 //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1706 return kFALSE; // to be changed probably
1709 // Make a copy of track hit collection
1710 TObjArray *hits = new TObjArray(*fTrackHits);
1714 // Hits after the found one will be removed
1715 if (GetStation0() == 3 && skipHit->GetChamberNumber() >= 7) {
1716 SortHits(1, fTrackHits); // unsort hits
1717 imax = fTrackHits->IndexOf(skipHit);
1719 Int_t nTrackHits = fNmbTrackHits;
1720 for (Int_t i=imax+1; i<nTrackHits; i++) {
1721 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
1722 fTrackHits->Remove(hit);
1723 hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit
1727 // Check if the track candidate doesn't exist yet
1728 if (ExistDouble()) { delete hits; return kFALSE; }
1730 //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1733 nRecTracks = fgTrackReconstructor->GetNRecTracks();
1734 skipHit = (AliMUONHitForRec*) ((*fTrackHits)[fNmbTrackHits-1]);
1735 // Remove all saved steps and smoother matrices after the skipped hit
1736 RemoveMatrices(skipHit->GetZ());
1738 //AZ(z->-z) if (skipHit->GetZ() > fStartSegment->GetHitForRec2()->GetZ() || !fNSteps) {
1739 if (TMath::Abs(skipHit->GetZ()) > TMath::Abs(fStartSegment->GetHitForRec2()->GetZ()) || !fNSteps) {
1740 // Propagation toward high Z or skipped hit next to segment -
1741 // start track from segment
1742 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
1743 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1744 trackK->fRecover = 1;
1745 trackK->fSkipHit = skipHit;
1746 trackK->fNmbTrackHits = fNmbTrackHits;
1747 delete trackK->fTrackHits; // not efficient ?
1748 trackK->fTrackHits = new TObjArray(*fTrackHits);
1749 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1753 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1755 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1756 //AZ(z->-z) trackK->fTrackDir = -1;
1757 trackK->fTrackDir = 1;
1758 trackK->fRecover = 1;
1759 trackK->fSkipHit = skipHit;
1760 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1762 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1763 CreateMatrix(trackK->fParFilter);
1765 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1766 trackK->fParFilter->Last()->SetUniqueID(1);
1767 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1768 iD = trackK->fCovFilter->Last()->GetUniqueID();
1770 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1771 CreateMatrix(trackK->fCovFilter);
1773 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1774 trackK->fCovFilter->Last()->SetUniqueID(1);
1775 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1776 if (trackK->fWeight->Determinant() != 0) {
1778 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1780 AliWarning(" Determinant fWeight=0:");
1782 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1784 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1785 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1789 //__________________________________________________________________________
1790 void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1792 /// Adds matrices for the smoother and keep Chi2 for the point
1793 /// Track parameters
1794 //trackK->fParFilter->Last()->Print();
1795 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1797 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1798 CreateMatrix(trackK->fParFilter);
1801 *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1802 trackK->fParFilter->Last()->SetUniqueID(iD);
1804 cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1805 //trackK->fTrackPar->Print();
1806 //trackK->fTrackParNew->Print();
1807 trackK->fParFilter->Last()->Print();
1808 cout << " Add matrices" << endl;
1811 *(trackK->fCovariance) = *(trackK->fWeight);
1812 if (trackK->fCovariance->Determinant() != 0) {
1814 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1816 AliWarning(" Determinant fCovariance=0:");
1818 iD = trackK->fCovFilter->Last()->GetUniqueID();
1820 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1821 CreateMatrix(trackK->fCovFilter);
1824 *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1825 trackK->fCovFilter->Last()->SetUniqueID(iD);
1827 // Save Chi2-increment for point
1828 Int_t indx = trackK->fTrackHits->IndexOf(hitAdd);
1829 if (indx < 0) indx = fNmbTrackHits;
1830 if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10);
1831 trackK->fChi2Array->AddAt(dChi2,indx);
1834 //__________________________________________________________________________
1835 void AliMUONTrackK::CreateMatrix(TObjArray *objArray) const
1837 /// Create new matrix and add it to TObjArray
1839 TMatrixD *matrix = (TMatrixD*) objArray->First();
1840 TMatrixD *tmp = new TMatrixD(*matrix);
1841 objArray->AddAtAndExpand(tmp,objArray->GetLast());
1842 //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1845 //__________________________________________________________________________
1846 void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1848 /// Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1850 for (Int_t i=fNSteps-1; i>=0; i--) {
1851 if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1852 if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1853 RemoveMatrices(this);
1854 } // for (Int_t i=fNSteps-1;
1857 //__________________________________________________________________________
1858 void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1860 /// Remove last saved matrices and steps in the smoother part
1863 Int_t i = trackK->fNSteps;
1866 // Delete only matrices not shared by several tracks
1867 id = trackK->fParExtrap->Last()->GetUniqueID();
1869 trackK->fParExtrap->Last()->SetUniqueID(id-1);
1870 trackK->fParExtrap->RemoveAt(i);
1872 else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1873 id = fParFilter->Last()->GetUniqueID();
1875 trackK->fParFilter->Last()->SetUniqueID(id-1);
1876 trackK->fParFilter->RemoveAt(i);
1878 else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1879 id = trackK->fCovExtrap->Last()->GetUniqueID();
1881 trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1882 trackK->fCovExtrap->RemoveAt(i);
1884 else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1885 id = trackK->fCovFilter->Last()->GetUniqueID();
1887 trackK->fCovFilter->Last()->SetUniqueID(id-1);
1888 trackK->fCovFilter->RemoveAt(i);
1890 else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1891 id = trackK->fJacob->Last()->GetUniqueID();
1893 trackK->fJacob->Last()->SetUniqueID(id-1);
1894 trackK->fJacob->RemoveAt(i);
1896 else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1899 //__________________________________________________________________________
1900 Bool_t AliMUONTrackK::Smooth(void)
1903 Int_t ihit = fNmbTrackHits - 1;
1904 AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1905 fChi2Smooth = new TArrayD(fNmbTrackHits);
1906 fChi2Smooth->Reset(-1);
1908 fParSmooth = new TObjArray(15);
1909 fParSmooth->Clear();
1912 cout << " ******** Enter Smooth " << endl;
1913 cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl;
1915 for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1917 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();}
1919 for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHits)[i])->GetZ() << " ";
1923 // Find last point corresponding to the last hit
1924 Int_t iLast = fNSteps - 1;
1925 for ( ; iLast>=0; iLast--) {
1926 //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ()) break;
1927 if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ())) break;
1930 TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1932 TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1933 TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1934 TMatrixD tmpPar = *fTrackPar;
1935 //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print();
1938 Double_t chi2max = 0;
1939 for (Int_t i=iLast+1; i>0; i--) {
1940 if (i == iLast + 1) goto L33; // temporary fix
1942 // Smoother gain matrix
1943 weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1944 if (weight.Determinant() != 0) {
1946 mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1948 AliWarning(" Determinant weight=0:");
1951 tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
1952 gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
1953 //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
1955 // Smoothed parameter vector
1956 //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
1957 parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
1958 tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
1959 tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
1962 // Smoothed covariance
1963 covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1964 weight = TMatrixD(TMatrixD::kTransposed,gain);
1965 tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
1966 covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
1967 covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
1969 // Check if there was a measurement at given z
1971 for ( ; ihit>=0; ihit--) {
1972 hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1973 if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
1974 //AZ(z->-z) else if (ihit < fNmbTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
1975 else if (ihit < fNmbTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
1977 if (!found) continue; // no measurement - skip the rest
1978 else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
1979 if (ihit == 0) continue; // the first hit - skip the rest
1982 // Smoothed residuals
1984 tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
1985 tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
1987 cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
1988 cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
1990 // Cov. matrix of smoothed residuals
1992 tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
1993 tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
1994 tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
1995 tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
1997 // Calculate Chi2 of smoothed residuals
1998 if (tmp.Determinant() != 0) {
2000 mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2002 AliWarning(" Determinant tmp=0:");
2004 TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
2005 TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
2006 if (fgDebug > 1) chi2.Print();
2007 (*fChi2Smooth)[ihit] = chi2(0,0);
2008 if (chi2(0,0) > chi2max) chi2max = chi2(0,0);
2010 if (chi2(0,0) < 0) {
2012 AliError(Form(" *** chi2 < 0: %d %d ", i, iLast));
2014 // Save smoothed parameters
2015 TMatrixD *par = new TMatrixD(parSmooth);
2016 fParSmooth->AddAtAndExpand(par, ihit);
2018 } // for (Int_t i=iLast+1;
2020 //if (chi2max > 16) {
2021 //if (chi2max > 25) {
2022 //if (chi2max > 50) {
2023 //if (chi2max > 100) {
2024 if (chi2max > fgkChi2max) {
2025 //if (Recover()) DropBranches();
2033 //__________________________________________________________________________
2034 void AliMUONTrackK::Outlier()
2036 /// Adds new track with removed hit having the highest chi2
2039 cout << " ******** Enter Outlier " << endl;
2040 for (Int_t i=0; i<fNmbTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
2042 for (Int_t i=0; i<fNmbTrackHits; i++) {
2043 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
2048 Double_t chi2max = 0;
2050 for (Int_t i=0; i<fNmbTrackHits; i++) {
2051 if ((*fChi2Smooth)[i] < chi2max) continue;
2052 chi2max = (*fChi2Smooth)[i];
2055 // Check if the outlier is not from the seed segment
2056 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
2057 if (hit == fStartSegment->GetHitForRec1() || hit == fStartSegment->GetHitForRec2()) return; // to be changed probably
2059 // Check for missing station
2062 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--;
2063 } else if (imax == fNmbTrackHits-1) {
2064 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2066 else if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2067 if (!ok) { Recover(); return; } // try to recover track
2068 //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; }
2070 // Remove saved steps and smoother matrices after the outlier
2071 RemoveMatrices(hit->GetZ());
2073 // Check for possible double track candidates
2074 //if (ExistDouble(hit)) return;
2076 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2077 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2079 AliMUONTrackK *trackK = 0;
2080 if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2081 // start track from segment
2082 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
2083 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2084 trackK->fRecover = 2;
2085 trackK->fSkipHit = hit;
2086 trackK->fNmbTrackHits = fNmbTrackHits;
2088 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(0);
2089 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2090 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(1);
2091 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2092 delete trackK->fTrackHits; // not efficient ?
2093 trackK->fTrackHits = new TObjArray(*fTrackHits);
2094 for (Int_t i = 0; i < fNmbTrackHits; i++) {
2095 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
2096 hit->SetNTrackHits(hit->GetNTrackHits()+1);
2099 if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHits);
2100 if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2103 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2105 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2106 trackK->fTrackDir = 1;
2107 trackK->fRecover = 2;
2108 trackK->fSkipHit = hit;
2109 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2111 trackK->fParFilter->Last()->SetUniqueID(iD-1);
2112 CreateMatrix(trackK->fParFilter);
2114 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2115 trackK->fParFilter->Last()->SetUniqueID(1);
2116 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2117 iD = trackK->fCovFilter->Last()->GetUniqueID();
2119 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2120 CreateMatrix(trackK->fCovFilter);
2122 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2123 trackK->fCovFilter->Last()->SetUniqueID(1);
2124 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2125 if (trackK->fWeight->Determinant() != 0) {
2127 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2129 AliWarning(" Determinant fWeight=0:");
2131 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2133 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2134 if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2137 //__________________________________________________________________________
2138 Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2140 /// Return Chi2 at point
2141 return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2145 //__________________________________________________________________________
2146 void AliMUONTrackK::Print(FILE *lun) const
2148 /// Print out track information
2151 AliMUONHitForRec *hit = 0;
2152 // from raw clusters
2153 AliMUONRawCluster *clus = 0;
2154 TClonesArray *rawclusters = 0;
2155 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2156 hit = (AliMUONHitForRec*) ((*fTrackHits)[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<fNmbTrackHits; i1++) {
2172 if (GetChi2PerPoint(i1) < -0.1) continue;
2173 hit = (AliMUONHitForRec*) ((*fTrackHits)[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 = fTrackHits;
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->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2209 if (trackK->GetRecover() < 0) continue;
2211 if (trackK->fNmbTrackHits >= imax + 1) {
2212 for (Int_t j=0; j<=imax; j++) {
2213 //if (j != fNmbTrackHits-1 && (*trackK->fTrackHits)[j] != (*fTrackHits)[j]) break;
2214 if ((*trackK->fTrackHits)[j] != (*hits)[j]) break;
2216 if (hits != fTrackHits) {
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->fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2226 else if (imax == trackK->fNmbTrackHits-1) continue;
2227 // else if (imax == trackK->fNmbTrackHits-1) {
2228 //if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(trackK->fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2230 else if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHits->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->fNmbTrackHits == 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*)((*fTrackHits)[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(*fTrackHits);
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->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2291 if (trackK == this) continue;
2292 if (trackK->fNmbTrackHits == fNmbTrackHits || trackK->fNmbTrackHits == fNmbTrackHits-1) {
2293 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2295 if (trackK->fNmbTrackHits == fNmbTrackHits) {
2296 for (Int_t j=0; j<fNmbTrackHits; 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<fNmbTrackHits-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<fNmbTrackHits-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(*fTrackHits);
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->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2344 if (trackK == this) continue;
2345 //AZ if (trackK->GetRecover() < 0) continue; //
2346 if (trackK->fNmbTrackHits >= fNmbTrackHits) {
2347 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
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<fNmbTrackHits; j++) {
2351 //cout << fNmbTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2352 if (j != fNmbTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break;
2353 if (j == fNmbTrackHits-1) {
2354 if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE;
2355 //if (trackK->fNmbTrackHits > fNmbTrackHits &&
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;