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 "AliMUONTrackExtrap.h"
41 #include "AliMUONEventRecoCombi.h"
42 #include "AliMUONDetElement.h"
47 ClassImp(AliMUONTrackK) // Class implementation in ROOT context
50 const Int_t AliMUONTrackK::fgkSize = 5;
51 const Int_t AliMUONTrackK::fgkNSigma = 12;
52 const Double_t AliMUONTrackK::fgkChi2max = 100;
53 const Int_t AliMUONTrackK::fgkTriesMax = 10000;
54 const Double_t AliMUONTrackK::fgkEpsilon = 0.002;
56 void mnvertLocal(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail); // from AliMUONTrack
58 Int_t AliMUONTrackK::fgDebug = -1; //-1;
59 Int_t AliMUONTrackK::fgNOfPoints = 0;
60 AliMUONTrackReconstructorK* AliMUONTrackK::fgTrackReconstructor = NULL;
61 TClonesArray* AliMUONTrackK::fgHitForRec = NULL;
62 AliMUONEventRecoCombi *AliMUONTrackK::fgCombi = NULL;
64 //__________________________________________________________________________
65 AliMUONTrackK::AliMUONTrackK()
92 /// Default constructor
94 fgTrackReconstructor = NULL; // pointer to event reconstructor
95 fgHitForRec = NULL; // pointer to points
96 fgNOfPoints = 0; // number of points
101 //__________________________________________________________________________
102 AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructorK *TrackReconstructor, TClonesArray *hitForRec)
131 if (!TrackReconstructor) return;
132 fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
133 fgHitForRec = hitForRec; // pointer to points
134 fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
136 if (fgTrackReconstructor->GetTrackMethod() == 3) fgCombi = AliMUONEventRecoCombi::Instance();
139 //__________________________________________________________________________
140 AliMUONTrackK::AliMUONTrackK(AliMUONSegment *segment)
141 //: AliMUONTrack(segment, segment, fgTrackReconstructor)
142 : AliMUONTrack(NULL, segment),
143 fStartSegment(segment),
147 fTrackHits(new TObjArray(13)),
153 fTrackPar(new TMatrixD(fgkSize,1)),
154 fTrackParNew(new TMatrixD(fgkSize,1)),
155 fCovariance(new TMatrixD(fgkSize,fgkSize)),
156 fWeight(new TMatrixD(fgkSize,fgkSize)),
157 fParExtrap(new TObjArray(15)),
158 fParFilter(new TObjArray(15)),
160 fCovExtrap(new TObjArray(15)),
161 fCovFilter(new TObjArray(15)),
162 fJacob(new TObjArray(15)),
164 fSteps(new TArrayD(15)),
165 fChi2Array(new TArrayD(13)),
168 /// Constructor from a segment
170 AliMUONHitForRec *hit1, *hit2;
171 AliMUONRawCluster *clus;
172 TClonesArray *rawclusters;
174 // Pointers to hits from the segment
175 hit1 = segment->GetHitForRec1();
176 hit2 = segment->GetHitForRec2();
177 hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
178 hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
179 // check sorting in Z
180 if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
182 hit2 = segment->GetHitForRec1();
185 // Fill array of track parameters
186 if (hit1->GetChamberNumber() > 7) {
187 // last tracking station
188 (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
189 (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
190 fPosition = hit1->GetZ(); // z
191 fTrackHits->Add(hit2); // add hit 2
192 fTrackHits->Add(hit1); // add hit 1
193 //AZ(Z->-Z) fTrackDir = -1;
196 // last but one tracking station
197 (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
198 (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
199 fPosition = hit2->GetZ(); // z
200 fTrackHits->Add(hit1); // add hit 1
201 fTrackHits->Add(hit2); // add hit 2
202 //AZ(Z->-Z) fTrackDir = 1;
205 dZ = hit2->GetZ() - hit1->GetZ();
206 dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
207 dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
208 (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
209 if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
210 (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
211 (*fTrackPar)(2,0) -= TMath::Pi();
212 (*fTrackPar)(4,0) = 1/fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()); // 1/Pt
213 (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
214 // Evaluate covariance (and weight) matrix
217 if (fgDebug < 0 ) return;
218 cout << fgTrackReconstructor->GetNRecTracks()-1 << " " << fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()) << " " << 1/(*fTrackPar)(4,0) << " ";
220 for (Int_t i=0; i<2; i++) {
221 hit1 = (AliMUONHitForRec*) ((*fTrackHits)[i]);
222 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
223 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
224 cout << clus->GetTrack(1);
225 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
226 if (i == 0) cout << " <--> ";
228 cout << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
232 //__________________________________________________________________________
233 AliMUONTrackK::~AliMUONTrackK()
238 //cout << fNmbTrackHits << endl;
239 for (Int_t i = 0; i < fNmbTrackHits; i++) {
240 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
241 hit->SetNTrackHits(hit->GetNTrackHits()-1);
243 delete fTrackHits; // delete the TObjArray of pointers to TrackHit's
247 delete fTrackPar; delete fTrackParNew; delete fCovariance;
251 if (fSteps) delete fSteps;
252 if (fChi2Array) delete fChi2Array;
253 if (fChi2Smooth) delete fChi2Smooth;
254 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
255 // Delete only matrices not shared by several tracks
256 if (!fParExtrap) return;
259 for (Int_t i=0; i<fNSteps; i++) {
260 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
261 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
262 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
264 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
265 fParExtrap->RemoveAt(i);
267 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
268 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
269 id = fParFilter->UncheckedAt(i)->GetUniqueID();
271 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
272 fParFilter->RemoveAt(i);
274 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
275 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
276 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
278 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
279 fCovExtrap->RemoveAt(i);
282 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
283 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
284 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
286 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
287 fCovFilter->RemoveAt(i);
289 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
290 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
291 id = fJacob->UncheckedAt(i)->GetUniqueID();
293 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
298 for (Int_t i=0; i<fNSteps; i++) {
299 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
300 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
301 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
302 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
303 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
304 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
307 fParExtrap->Delete(); fParFilter->Delete();
308 fCovExtrap->Delete(); fCovFilter->Delete();
310 delete fParExtrap; delete fParFilter;
311 delete fCovExtrap; delete fCovFilter;
315 //__________________________________________________________________________
316 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
318 /// Assignment operator
321 if(&source == this) return *this;
323 // base class assignement
324 //AZ TObject::operator=(source);
325 AliMUONTrack::operator=(source);
327 fStartSegment = source.fStartSegment;
328 fNmbTrackHits = source.fNmbTrackHits;
329 fChi2 = source.fChi2;
330 fPosition = source.fPosition;
331 fPositionNew = source.fPositionNew;
332 fTrackDir = source.fTrackDir;
333 fBPFlag = source.fBPFlag;
334 fRecover = source.fRecover;
335 fSkipHit = source.fSkipHit;
338 fTrackHits = new TObjArray(*source.fTrackHits);
339 //source.fTrackHits->Dump();
340 //fTrackHits->Dump();
341 for (Int_t i = 0; i < fNmbTrackHits; i++) {
342 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
343 hit->SetNTrackHits(hit->GetNTrackHits()+1);
346 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
347 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
348 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
349 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
352 fParExtrap = new TObjArray(*source.fParExtrap);
353 fParFilter = new TObjArray(*source.fParFilter);
354 fCovExtrap = new TObjArray(*source.fCovExtrap);
355 fCovFilter = new TObjArray(*source.fCovFilter);
356 fJacob = new TObjArray(*source.fJacob);
357 fSteps = new TArrayD(*source.fSteps);
358 fNSteps = source.fNSteps;
360 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
364 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
365 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
366 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
367 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
368 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
369 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
374 //__________________________________________________________________________
375 void AliMUONTrackK::EvalCovariance(Double_t dZ)
377 /// Evaluate covariance (and weight) matrix for track candidate
378 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
381 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
382 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
384 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
386 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
388 tanA = TMath::Tan((*fTrackPar)(2,0));
389 dAdY = 1/(1+tanA*tanA)/dZ;
390 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
391 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
392 (*fWeight)(2,0) = (*fWeight)(0,2);
394 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
395 tanB = TMath::Tan((*fTrackPar)(3,0));
396 dBdX = 1/(1+tanB*tanB)/rad;
398 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
399 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
400 (*fWeight)(3,1) = (*fWeight)(1,3);
402 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
404 // check whether the Invert method returns flag if matrix cannot be inverted,
405 // and do not calculate the Determinant in that case !!!!
406 if (fWeight->Determinant() != 0) {
407 // fWeight->Invert();
409 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
411 AliWarning(" Determinant fWeight=0:");
416 //__________________________________________________________________________
417 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
419 /// Follows track through detector stations
420 Bool_t miss, success;
421 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
422 Int_t ihit, firstIndx = -1, lastIndx = -1, currIndx = -1, iz0 = -1, iz = -1;
423 Double_t zEnd, dChi2;
424 AliMUONHitForRec *hitAdd, *firstHit = NULL, *lastHit = NULL, *hit;
425 AliMUONRawCluster *clus;
426 TClonesArray *rawclusters;
427 hit = 0; clus = 0; rawclusters = 0;
429 miss = success = kTRUE;
431 //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
432 iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
433 iMin = TMath::Min(ichamEnd,ichamBeg);
434 iMax = TMath::Max(ichamEnd,ichamBeg);
441 if (((AliMUONHitForRec*)fTrackHits->First())->GetChamberNumber() != ichamb) currIndx = 0;
442 } else if (fRecover) {
443 hit = GetHitLastOk();
444 currIndx = fTrackHits->IndexOf(hit);
445 if (currIndx < 0) hit = fStartSegment->GetHitForRec1(); // for station 3
447 ichamb = hit->GetChamberNumber();
448 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
449 // start from the last point or outlier
450 // remove the skipped hit
451 fTrackHits->Remove(fSkipHit); // remove hit
453 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
458 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
459 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetChamberNumber() == 6) ichambOK = 6;
460 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
461 fSkipHit->GetHitNumber() < 0) {
462 iz0 = fgCombi->IZfromHit(fSkipHit);
465 else currIndx = fgHitForRec->IndexOf(fSkipHit);
468 fTrackHits->Compress();
470 } // if (hit == fSkipHit)
471 else if (currIndx < 0) currIndx = fTrackHits->IndexOf(hit);
472 } // else if (fRecover)
474 // Get indices of the 1'st and last hits on the track candidate
475 firstHit = (AliMUONHitForRec*) fTrackHits->First();
476 lastHit = (AliMUONHitForRec*) fTrackHits->Last();
477 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
478 lastHit->GetHitNumber() < 0) iz0 = fgCombi->IZfromHit(lastHit);
480 firstIndx = fgHitForRec->IndexOf(firstHit);
481 lastIndx = fgHitForRec->IndexOf(lastHit);
482 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
486 if (iz0 < 0) iz0 = iFB;
487 while (ichamb >= iMin && ichamb <= iMax) {
488 // Find the closest hit in Z, not belonging to the current plane
491 if (currIndx < fNmbTrackHits) {
492 hitAdd = (AliMUONHitForRec*) fTrackHits->UncheckedAt(currIndx);
493 zEnd = hitAdd->GetZ();
494 //AZ(z->-z) } else zEnd = -9999;
497 //AZ(Z->-Z) zEnd = -9999;
499 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
500 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
501 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
502 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
503 zEnd = hitAdd->GetZ();
509 // Combined cluster / track finder
510 if (zEnd > 999 && iFB < 0 && fgTrackReconstructor->GetTrackMethod() == 3) {
512 AliMUONHitForRec hitTmp;
513 for (iz = iz0 - iFB; iz < fgCombi->Nz(); iz++) {
514 if (TMath::Abs(fgCombi->Z(iz)-fPosition) < 0.5) continue;
515 Int_t *pDEatZ = fgCombi->DEatZ(iz);
516 //cout << iz << " " << fgCombi->Z(iz) << endl;
517 zEnd = fgCombi->Z(iz);
519 AliMUONDetElement *detElem = fgCombi->DetElem(pDEatZ[0]);
521 hitAdd->SetChamberNumber(detElem->Chamber());
522 //hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
527 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
529 // Check if there is a chamber without hits
530 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
531 if (!Back && zEnd<999) currIndx -= iFB;
533 zEnd = AliMUONConstants::DefaultChamberZ(ichamb);
536 ichamb = hitAdd->GetChamberNumber();
540 if (ichamb<iMin || ichamb>iMax) break;
541 // Check for missing station
543 dChamb = TMath::Abs(ichamb-ichambOK);
544 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
545 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
546 if (zEnd > 999) dStatMiss++;
548 //if (dStatMiss == 2 && ichambOK/2 != 3 || dStatMiss > 2) { // AZ - missing st. 3
549 // missing station - abandon track
550 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
552 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
553 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
554 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
555 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
556 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
557 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
560 cout << fNmbTrackHits << endl;
561 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
562 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
563 printf(" * %d %10.4f %10.4f %10.4f",
564 hit->GetChamberNumber(), hit->GetBendingCoor(),
565 hit->GetNonBendingCoor(), hit->GetZ());
567 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
568 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
569 printf("%3d", clus->GetTrack(1)-1);
570 if (clus->GetTrack(2) != 0)
571 printf("%3d \n", clus->GetTrack(2)-1);
576 } // if (fgDebug >= 10)
577 if (fNmbTrackHits>2 && fRecover==0) Recover(); // try to recover track later
579 } // if (dStatMiss > 1)
581 if (endOfProp != 0) break;
583 // propagate to the found Z
585 // Check if track steps into dipole
586 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
587 if (fPosition<zDipole2 && zEnd>zDipole2) {
588 //LinearPropagation(zDipole2-zBeg);
589 ParPropagation(zDipole2);
590 MSThin(1); // multiple scattering in the chamber
591 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
592 fPosition = fPositionNew;
593 *fTrackPar = *fTrackParNew;
594 //MagnetPropagation(zEnd);
595 ParPropagation(zEnd);
596 WeightPropagation(zEnd, kTRUE);
597 fPosition = fPositionNew;
599 // Check if track steps out of dipole
600 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
601 else if (fPosition<zDipole1 && zEnd>zDipole1) {
602 //MagnetPropagation(zDipole1-zBeg);
603 ParPropagation(zDipole1);
604 MSThin(1); // multiple scattering in the chamber
605 WeightPropagation(zDipole1, kTRUE);
606 fPosition = fPositionNew;
607 *fTrackPar = *fTrackParNew;
608 //LinearPropagation(zEnd-zDipole1);
609 ParPropagation(zEnd);
610 WeightPropagation(zEnd, kTRUE);
611 fPosition = fPositionNew;
613 ParPropagation(zEnd);
614 //MSThin(1); // multiple scattering in the chamber
615 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
616 WeightPropagation(zEnd, kTRUE);
617 fPosition = fPositionNew;
621 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
622 // recovered track - remove the hit
624 ichamb = fSkipHit->GetChamberNumber();
625 // remove the skipped hit
626 fTrackHits->Remove(fSkipHit);
628 //AZ fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
631 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
632 //? if (fgTrackReconstructor->GetTrackMethod() != 3) currIndx = fgHitForRec->IndexOf(fSkipHit);
633 currIndx = fgHitForRec->IndexOf(fSkipHit);
637 // backward propagator
639 TMatrixD pointWeight(fgkSize,fgkSize);
640 TMatrixD point(fgkSize,1);
641 TMatrixD trackParTmp = point;
642 point(0,0) = hitAdd->GetBendingCoor();
643 point(1,0) = hitAdd->GetNonBendingCoor();
644 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
645 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
646 TryPoint(point,pointWeight,trackParTmp,dChi2);
647 *fTrackPar = trackParTmp;
648 *fWeight += pointWeight;
649 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
650 fChi2 += dChi2; // Chi2
651 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
652 if (ichamb==ichamEnd) break;
655 // forward propagator
656 if (miss || !FindPoint(ichamb, zEnd, currIndx, iFB, hitAdd, iz)) {
658 *fTrackPar = *fTrackParNew;
661 fTrackHits->Add(hitAdd); // add hit
663 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
665 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
669 if (fgDebug > 0) cout << fNmbTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
670 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
674 //__________________________________________________________________________
675 void AliMUONTrackK::ParPropagation(Double_t zEnd)
677 /// Propagation of track parameters to zEnd
679 Double_t dZ, step, distance, charge;
680 Double_t vGeant3[7], vGeant3New[7];
681 AliMUONTrackParam trackParam;
684 // First step using linear extrapolation
685 dZ = zEnd - fPosition;
686 fPositionNew = fPosition;
687 *fTrackParNew = *fTrackPar;
688 if (dZ == 0) return; //AZ ???
689 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
690 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
691 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
692 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
693 SetGeantParam(vGeant3,iFB);
694 //fTrackParNew->Print();
698 step = TMath::Abs(step);
699 // Propagate parameters
700 AliMUONTrackExtrap::ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
701 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
702 distance = zEnd - vGeant3New[2];
703 step *= dZ/(vGeant3New[2]-fPositionNew);
705 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
707 GetFromGeantParam(vGeant3New,iFB);
708 //fTrackParNew->Print();
710 // Position adjustment (until within tolerance)
711 while (TMath::Abs(distance) > fgkEpsilon) {
712 dZ = zEnd - fPositionNew;
713 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
714 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
715 step = TMath::Abs(step);
716 SetGeantParam(vGeant3,iFB);
719 // Propagate parameters
720 AliMUONTrackExtrap::ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
721 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
722 distance = zEnd - vGeant3New[2];
725 if (nTries > fgkTriesMax) AliError(Form(" Too many tries: %d", nTries));
726 } while (distance*iFB < 0);
728 GetFromGeantParam(vGeant3New,iFB);
730 //cout << nTries << endl;
731 //fTrackParNew->Print();
735 //__________________________________________________________________________
736 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
738 /// Propagation of the weight matrix
739 /// W = DtWD, where D is Jacobian
743 TMatrixD jacob(fgkSize,fgkSize);
746 // Save initial and propagated parameters
747 TMatrixD trackPar0 = *fTrackPar;
748 TMatrixD trackParNew0 = *fTrackParNew;
750 // Get covariance matrix
751 *fCovariance = *fWeight;
752 // check whether the Invert method returns flag if matrix cannot be inverted,
753 // and do not calculate the Determinant in that case !!!!
754 if (fCovariance->Determinant() != 0) {
756 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
757 //fCovariance->Print();
759 AliWarning(" Determinant fCovariance=0:");
762 // Loop over parameters to find change of the propagated vs initial ones
763 for (i=0; i<fgkSize; i++) {
764 dPar = TMath::Sqrt((*fCovariance)(i,i));
765 *fTrackPar = trackPar0;
766 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
767 (*fTrackPar)(i,0) += dPar;
768 ParPropagation(zEnd);
769 for (j=0; j<fgkSize; j++) {
770 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
774 //trackParNew0.Print();
775 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
777 TMatrixD jacob0 = jacob;
778 if (jacob.Determinant() != 0) {
781 AliWarning(" Determinant jacob=0:");
783 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
784 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
786 // Restore initial and propagated parameters
787 *fTrackPar = trackPar0;
788 *fTrackParNew = trackParNew0;
791 if (!smooth) return; // do not use smoother
792 if (fTrackDir < 0) return; // only for propagation towards int. point
793 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
794 fParExtrap->Add(tmp);
796 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
797 fParFilter->Add(tmp);
799 *fCovariance = *fWeight;
800 if (fCovariance->Determinant() != 0) {
802 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
804 AliWarning(" Determinant fCovariance=0:");
806 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
807 fCovExtrap->Add(tmp);
809 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
810 fCovFilter->Add(tmp);
812 tmp = new TMatrixD(jacob0); // Jacobian
815 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
816 fSteps->AddAt(fPositionNew,fNSteps++);
817 if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
821 //__________________________________________________________________________
822 Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd, Int_t iz)
824 /// Picks up point within a window for the chamber No ichamb
825 /// Split the track if there are more than 1 hit
826 Int_t ihit, nRecTracks;
827 Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
828 TClonesArray *trackPtr;
829 AliMUONHitForRec *hit, *hitLoop;
830 AliMUONTrackK *trackK;
831 AliMUONDetElement *detElem = NULL;
835 if (fgTrackReconstructor->GetTrackMethod() == 3 && iz >= 0) {
836 // Combined cluster / track finder
837 // Check if extrapolated track passes thru det. elems. at iz
838 Int_t *pDEatZ = fgCombi->DEatZ(iz);
839 Int_t nDetElem = pDEatZ[-1];
840 //cout << fgCombi->Z(iz) << " " << nDetElem << endl;
841 for (Int_t i = 0; i < nDetElem; i++) {
842 detElem = fgCombi->DetElem(pDEatZ[i]);
843 if (detElem->Inside((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPosition)) {
844 detElem->ClusterReco((*fTrackParNew)(1,0), (*fTrackParNew)(0,0));
845 hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
850 if (!ok) return ok; // outside det. elem.
854 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
855 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
856 *fCovariance = *fWeight;
857 // check whether the Invert method returns flag if matrix cannot be inverted,
858 // and do not calculate the Determinant in that case !!!!
859 if (fCovariance->Determinant() != 0) {
861 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
863 AliWarning(" Determinant fCovariance=0:");
865 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
866 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
867 // Loop over all hits and take hits from the chamber
868 TMatrixD pointWeight(fgkSize,fgkSize);
869 TMatrixD saveWeight = pointWeight;
870 TMatrixD pointWeightTmp = pointWeight;
871 TMatrixD point(fgkSize,1);
872 TMatrixD trackPar = point;
873 TMatrixD trackParTmp = point;
874 Int_t nHitsOK = 0, ihitB = currIndx, ihitE = fgNOfPoints, iDhit = iFB;
876 zLast = ((AliMUONHitForRec*)fTrackHits->Last())->GetZ();
877 if (fgTrackReconstructor->GetTrackMethod() == 3 && detElem) {
879 ihitE = detElem->NHitsForRec();
884 for (ihit = ihitB; ihit >= 0 && ihit < ihitE; ihit+=iDhit) {
885 if (fgTrackReconstructor->GetTrackMethod() != 3 || !detElem)
886 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
887 else hit = (AliMUONHitForRec*) detElem->HitsForRec()->UncheckedAt(ihit);
888 if (hit->GetChamberNumber() == ichamb) {
889 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
890 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
891 y = hit->GetBendingCoor();
892 x = hit->GetNonBendingCoor();
893 if (hit->GetBendingReso2() < 0) {
894 // Combined cluster / track finder
895 hit->SetBendingReso2(fgTrackReconstructor->GetBendingResolution()*
896 fgTrackReconstructor->GetBendingResolution());
897 hit->SetNonBendingReso2(fgTrackReconstructor->GetNonBendingResolution()*
898 fgTrackReconstructor->GetNonBendingResolution());
900 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
901 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
903 // windowB = TMath::Min (windowB,5.);
904 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
906 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
907 windowB = TMath::Min (windowB,0.5);
908 windowNonB = TMath::Min (windowNonB,3.);
909 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
910 windowB = TMath::Min (windowB,1.5);
911 windowNonB = TMath::Min (windowNonB,3.);
912 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
913 windowB = TMath::Min (windowB,4.);
914 windowNonB = TMath::Min (windowNonB,6.);
920 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
921 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
922 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
924 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
925 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
929 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
930 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
931 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
932 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
933 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
934 // hit->GetTrackRefSignal() == 1) { // just for test
935 // Vector of measurements and covariance matrix
936 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
937 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
938 // Adjust position: for multiple hits in the chamber or misalignment (Z as a function of X or Y)
939 //AliWarning(Form(" *** adjust %f %f ", zEnd, hit->GetZ()));
941 *fTrackPar = *fTrackParNew;
942 ParPropagation(zEnd);
943 WeightPropagation(zEnd, kTRUE);
944 fPosition = fPositionNew;
945 *fTrackPar = *fTrackParNew;
947 *fCovariance = *fWeight;
948 if (fCovariance->Determinant() != 0) {
950 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
952 AliWarning(" Determinant fCovariance=0:" );
958 pointWeight(0,0) = 1/hit->GetBendingReso2();
959 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
960 TryPoint(point,pointWeight,trackPar,dChi2);
961 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
962 // if (TMath::Sign(1.,(trackPar)(4,0)*(*fTrackPar)(4,0)) < 0) continue; // change of sign
965 //if (nHitsOK > -1) {
967 // Save current members
968 saveWeight = *fWeight;
969 savePosition = fPosition;
970 // temporary storage for the current track
972 trackParTmp = trackPar;
973 pointWeightTmp = pointWeight;
975 if (fgDebug > 0) cout << " Added point: " << x << " " << y << " " << dChi2 << endl;
977 // branching: create a new track
978 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
979 nRecTracks = fgTrackReconstructor->GetNRecTracks();
980 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
982 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
983 if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNmbTrackHits << " " << nRecTracks << endl;
984 trackK->fRecover = 0;
985 *(trackK->fTrackPar) = trackPar;
986 *(trackK->fWeight) += pointWeight;
987 trackK->fChi2 += dChi2;
990 *(trackK->fCovariance) = *(trackK->fWeight);
991 if (trackK->fCovariance->Determinant() != 0) {
993 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
995 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
997 // Add filtered matrices for the smoother
999 if (nHitsOK > 2) { // check for position adjustment
1000 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
1001 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
1002 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
1003 RemoveMatrices(trackK);
1004 AliError(Form(" *** Position adjustment 1: %f %f", hit->GetZ(), (*trackK->fSteps)[i]));
1009 AddMatrices (trackK, dChi2, hit);
1011 // Mark hits as being on 2 tracks
1012 for (Int_t i=0; i<fNmbTrackHits; i++) {
1013 hitLoop = (AliMUONHitForRec*) ((*fTrackHits)[i]);
1014 //AZ hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
1017 cout << hitLoop->GetChamberNumber() << " ";
1018 cout << hitLoop->GetBendingCoor() << " ";
1019 cout << hitLoop->GetNonBendingCoor() << " ";
1020 cout << hitLoop->GetZ() << " " << " ";
1021 cout << hitLoop->GetTTRTrack() << endl;
1022 printf(" ** %d %10.4f %10.4f %10.4f\n",
1023 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
1024 hitLoop->GetNonBendingCoor(), hitLoop->GetZ());
1028 trackK->fTrackHits->Add(hit); // add hit
1029 trackK->fNmbTrackHits ++;
1030 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
1033 trackK->fTrackDir = 1;
1034 trackK->fBPFlag = kTRUE;
1039 } else break; // different chamber
1040 } // for (ihit=currIndx;
1043 *fTrackPar = trackParTmp;
1044 *fWeight = saveWeight;
1045 *fWeight += pointWeightTmp;
1046 fChi2 += dChi2Tmp; // Chi2
1047 fPosition = savePosition;
1048 // Add filtered matrices for the smoother
1049 if (fTrackDir > 0) {
1050 for (Int_t i=fNSteps-1; i>=0; i--) {
1051 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
1052 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
1053 RemoveMatrices(this);
1054 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
1057 } // for (Int_t i=fNSteps-1;
1058 AddMatrices (this, dChi2Tmp, hitAdd);
1061 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1062 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1065 } // if (fTrackDir > 0)
1070 //__________________________________________________________________________
1071 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1073 /// Adds a measurement point (modifies track parameters and computes
1076 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1077 TMatrixD wu = *fWeight;
1078 wu += pointWeight; // W+U
1079 trackParTmp = point;
1080 trackParTmp -= *fTrackParNew; // m-p
1081 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1082 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1083 right += right1; // U(m-p) + (W+U)p
1085 // check whether the Invert method returns flag if matrix cannot be inverted,
1086 // and do not calculate the Determinant in that case !!!!
1087 if (wu.Determinant() != 0) {
1089 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1091 AliWarning(" Determinant wu=0:");
1093 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1095 right1 = trackParTmp;
1096 right1 -= point; // p'-m
1097 point = trackParTmp;
1098 point -= *fTrackParNew; // p'-p
1099 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1100 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1102 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1103 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1104 dChi2 += value(0,0);
1108 //__________________________________________________________________________
1109 void AliMUONTrackK::MSThin(Int_t sign)
1111 /// Adds multiple scattering in a thin layer (only angles are affected)
1112 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1114 // check whether the Invert method returns flag if matrix cannot be inverted,
1115 // and do not calculate the Determinant in that case !!!!
1116 if (fWeight->Determinant() != 0) {
1118 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1120 AliWarning(" Determinant fWeight=0:");
1123 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1124 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1125 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1126 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1127 velo = 1; // relativistic
1128 path = TMath::Abs(fgTrackReconstructor->GetChamberThicknessInX0()/cosAlph/cosBeta); // path length
1129 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1131 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1132 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1134 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1138 //__________________________________________________________________________
1139 void AliMUONTrackK::StartBack(void)
1141 /// Starts backpropagator
1145 for (Int_t i=0; i<fgkSize; i++) {
1146 for (Int_t j=0; j<fgkSize; j++) {
1147 if (j==i) (*fWeight)(i,i) /= 100;
1148 //if (j==i) (*fWeight)(i,i) /= fNmbTrackHits*fNmbTrackHits;
1149 else (*fWeight)(j,i) = 0;
1152 // Sort hits on track in descending order in abs(z)
1153 SortHits(0, fTrackHits);
1156 //__________________________________________________________________________
1157 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1159 /// Sort hits in Z if the seed segment in the last but one station
1160 /// (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1162 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1163 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1164 Int_t i = 1, entries = array->GetEntriesFast();
1165 for ( ; i<entries; i++) {
1167 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1169 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1170 if (z < zmax) break;
1172 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1176 for (Int_t j=0; j<=(i-1)/2; j++) {
1177 TObject *hit = array->UncheckedAt(j);
1178 array->AddAt(array->UncheckedAt(i-j),j);
1179 array->AddAt(hit,i-j);
1181 if (fgDebug >= 10) {
1182 for (i=0; i<entries; i++)
1183 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1184 cout << " - Sort" << endl;
1188 //__________________________________________________________________________
1189 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1191 /// Set vector of Geant3 parameters pointed to by "VGeant3"
1192 /// from track parameters
1194 VGeant3[0] = (*fTrackParNew)(1,0); // X
1195 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1196 VGeant3[2] = fPositionNew; // Z
1197 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1198 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1199 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1200 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1203 //__________________________________________________________________________
1204 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1206 /// Get track parameters from vector of Geant3 parameters pointed
1209 fPositionNew = VGeant3[2]; // Z
1210 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1211 (*fTrackParNew)(1,0) = VGeant3[0]; // X
1212 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1213 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1214 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1217 //__________________________________________________________________________
1218 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1220 /// Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1223 AliWarning(Form(" *** Too high Chi2: %f ", fChi2));
1226 if (iChi2 == 0) fChi2 = fNmbTrackHits + (500.-fChi2)/501;
1227 else fChi2 = 500 - (fChi2-fNmbTrackHits)*501;
1230 //__________________________________________________________________________
1231 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1233 /// "Compare" function to sort with decreasing "track quality".
1234 /// Returns +1 (0, -1) if quality of current track
1235 /// is smaller than (equal to, larger than) quality of trackK
1237 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1238 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1242 //__________________________________________________________________________
1243 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1245 /// Check whether or not to keep current track
1246 /// (keep, if it has less than half of common hits with track0)
1247 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1248 AliMUONHitForRec *hit0, *hit1;
1251 nHits0 = track0->fNmbTrackHits;
1252 nTrackHits2 = fNmbTrackHits/2;
1254 for (i=0; i<nHits0; i++) {
1255 // Check if hit belongs to several tracks
1256 hit0 = (AliMUONHitForRec*) (*track0->fTrackHits)[i];
1257 if (hit0->GetNTrackHits() == 1) continue;
1258 for (j=0; j<fNmbTrackHits; j++) {
1259 hit1 = (AliMUONHitForRec*) (*fTrackHits)[j];
1260 if (hit1->GetNTrackHits() == 1) continue;
1263 if (hitsInCommon >= nTrackHits2) return kFALSE;
1271 //__________________________________________________________________________
1272 void AliMUONTrackK::Kill(void)
1274 /// Kill track candidate
1275 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1278 //__________________________________________________________________________
1279 void AliMUONTrackK::FillMUONTrack(void)
1281 /// Compute track parameters at hit positions (as for AliMUONTrack)
1286 // Set track parameters at vertex
1287 AliMUONTrackParam trackParam;
1288 SetTrackParam(&trackParam, fTrackPar, fPosition);
1289 SetTrackParamAtVertex(&trackParam);
1291 // Set track parameters at hits
1292 for (Int_t i = fNmbTrackHits-1; i>=0; i--) {
1293 if ((*fChi2Smooth)[i] < 0) {
1294 // Propagate through last chambers
1295 AliMUONTrackExtrap::ExtrapToZ(&trackParam, ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1298 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1300 AddTrackParamAtHit(&trackParam,(AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1301 // Fill array of HitForRec's
1302 AddHitForRecAtHit((AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1306 //__________________________________________________________________________
1307 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1309 /// Fill AliMUONTrackParam object
1311 trackParam->SetBendingCoor((*par)(0,0));
1312 trackParam->SetNonBendingCoor((*par)(1,0));
1313 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1314 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1315 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1316 trackParam->SetZ(z);
1319 //__________________________________________________________________________
1320 void AliMUONTrackK::Branson(void)
1322 /// Propagates track to the vertex thru absorber using Branson correction
1323 /// (makes use of the AliMUONTrackParam class)
1325 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1326 AliMUONTrackParam trackParam = AliMUONTrackParam();
1328 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1329 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1330 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1331 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1332 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1333 trackParam->SetZ(fPosition);
1335 SetTrackParam(&trackParam, fTrackPar, fPosition);
1337 AliMUONTrackExtrap::ExtrapToVertex(&trackParam, Double_t(0.), Double_t(0.), Double_t(0.));
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;