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 "AliMUONHitForRec.h"
37 #include "AliMUONObjectPair.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);
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(AliMUONObjectPair *segment)
141 : AliMUONTrack(NULL,NULL),
142 fStartSegment(new AliMUONObjectPair(*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
168 Double_t dX, dY, dZ, bendingSlope, bendingImpact;
169 AliMUONHitForRec *hit1, *hit2;
170 AliMUONRawCluster *clus;
171 TClonesArray *rawclusters;
173 // Pointers to hits from the segment
174 hit1 = (AliMUONHitForRec*) segment->First();
175 hit2 = (AliMUONHitForRec*) segment->Second();
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 = (AliMUONHitForRec*) segment->First();
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 bendingSlope = (hit2->GetBendingCoor() - hit1->GetBendingCoor()) / dZ;
208 bendingImpact = hit1->GetBendingCoor() - hit1->GetZ() * bendingSlope;
209 (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
210 if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
211 (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
212 (*fTrackPar)(2,0) -= TMath::Pi();
213 (*fTrackPar)(4,0) = 1./AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact); // 1/Pt
214 (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
215 // Evaluate covariance (and weight) matrix
218 if (fgDebug < 0 ) return;
219 cout << fgTrackReconstructor->GetNRecTracks()-1 << " "
220 << AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact)
221 << " " << 1/(*fTrackPar)(4,0) << " ";
223 for (Int_t i=0; i<2; i++) {
224 hit1 = (AliMUONHitForRec*) ((*fTrackHits)[i]);
225 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
226 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
227 cout << clus->GetTrack(1);
228 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
229 if (i == 0) cout << " <--> ";
231 cout << " @ " << hit1->GetChamberNumber() << endl;
235 //__________________________________________________________________________
236 AliMUONTrackK::~AliMUONTrackK()
241 delete fStartSegment;
246 //cout << fNmbTrackHits << endl;
247 for (Int_t i = 0; i < fNmbTrackHits; i++) {
248 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
249 hit->SetNTrackHits(hit->GetNTrackHits()-1);
251 delete fTrackHits; // delete the TObjArray of pointers to TrackHit's
255 delete fTrackPar; delete fTrackParNew; delete fCovariance;
259 if (fSteps) delete fSteps;
260 if (fChi2Array) delete fChi2Array;
261 if (fChi2Smooth) delete fChi2Smooth;
262 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
263 // Delete only matrices not shared by several tracks
264 if (!fParExtrap) return;
267 for (Int_t i=0; i<fNSteps; i++) {
268 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
269 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
270 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
272 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
273 fParExtrap->RemoveAt(i);
275 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
276 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
277 id = fParFilter->UncheckedAt(i)->GetUniqueID();
279 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
280 fParFilter->RemoveAt(i);
282 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
283 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
284 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
286 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
287 fCovExtrap->RemoveAt(i);
290 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
291 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
292 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
294 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
295 fCovFilter->RemoveAt(i);
297 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
298 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
299 id = fJacob->UncheckedAt(i)->GetUniqueID();
301 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
306 for (Int_t i=0; i<fNSteps; i++) {
307 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
308 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
309 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
310 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
311 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
312 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
315 fParExtrap->Delete(); fParFilter->Delete();
316 fCovExtrap->Delete(); fCovFilter->Delete();
318 delete fParExtrap; delete fParFilter;
319 delete fCovExtrap; delete fCovFilter;
323 //__________________________________________________________________________
324 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
326 /// Assignment operator
329 if(&source == this) return *this;
331 // base class assignement
332 //AZ TObject::operator=(source);
333 AliMUONTrack::operator=(source);
335 if (fStartSegment) delete fStartSegment;
336 if (source.fStartSegment) fStartSegment = new AliMUONObjectPair(*(source.fStartSegment));
337 else fStartSegment = 0x0;
339 fNmbTrackHits = source.fNmbTrackHits;
340 fChi2 = source.fChi2;
341 fPosition = source.fPosition;
342 fPositionNew = source.fPositionNew;
343 fTrackDir = source.fTrackDir;
344 fBPFlag = source.fBPFlag;
345 fRecover = source.fRecover;
346 fSkipHit = source.fSkipHit;
349 fTrackHits = new TObjArray(*source.fTrackHits);
350 //source.fTrackHits->Dump();
351 //fTrackHits->Dump();
352 for (Int_t i = 0; i < fNmbTrackHits; i++) {
353 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
354 hit->SetNTrackHits(hit->GetNTrackHits()+1);
357 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
358 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
359 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
360 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
363 fParExtrap = new TObjArray(*source.fParExtrap);
364 fParFilter = new TObjArray(*source.fParFilter);
365 fCovExtrap = new TObjArray(*source.fCovExtrap);
366 fCovFilter = new TObjArray(*source.fCovFilter);
367 fJacob = new TObjArray(*source.fJacob);
368 fSteps = new TArrayD(*source.fSteps);
369 fNSteps = source.fNSteps;
371 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
375 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
376 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
377 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
378 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
379 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
380 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
385 //__________________________________________________________________________
386 void AliMUONTrackK::EvalCovariance(Double_t dZ)
388 /// Evaluate covariance (and weight) matrix for track candidate
389 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
392 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
393 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
395 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
397 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
399 tanA = TMath::Tan((*fTrackPar)(2,0));
400 dAdY = 1/(1+tanA*tanA)/dZ;
401 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
402 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
403 (*fWeight)(2,0) = (*fWeight)(0,2);
405 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
406 tanB = TMath::Tan((*fTrackPar)(3,0));
407 dBdX = 1/(1+tanB*tanB)/rad;
409 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
410 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
411 (*fWeight)(3,1) = (*fWeight)(1,3);
413 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
415 // check whether the Invert method returns flag if matrix cannot be inverted,
416 // and do not calculate the Determinant in that case !!!!
417 if (fWeight->Determinant() != 0) {
418 // fWeight->Invert();
420 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
422 AliWarning(" Determinant fWeight=0:");
427 //__________________________________________________________________________
428 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
430 /// Follows track through detector stations
431 Bool_t miss, success;
432 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
433 Int_t ihit, firstIndx = -1, lastIndx = -1, currIndx = -1, iz0 = -1, iz = -1;
434 Double_t zEnd, dChi2;
435 AliMUONHitForRec *hitAdd, *firstHit = NULL, *lastHit = NULL, *hit;
436 AliMUONRawCluster *clus;
437 TClonesArray *rawclusters;
438 hit = 0; clus = 0; rawclusters = 0;
440 miss = success = kTRUE;
442 //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
443 iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
444 iMin = TMath::Min(ichamEnd,ichamBeg);
445 iMax = TMath::Max(ichamEnd,ichamBeg);
452 if (((AliMUONHitForRec*)fTrackHits->First())->GetChamberNumber() != ichamb) currIndx = 0;
453 } else if (fRecover) {
454 hit = GetHitLastOk();
455 currIndx = fTrackHits->IndexOf(hit);
456 if (currIndx < 0) hit = (AliMUONHitForRec*) fStartSegment->First(); // for station 3
458 ichamb = hit->GetChamberNumber();
459 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
460 // start from the last point or outlier
461 // remove the skipped hit
462 fTrackHits->Remove(fSkipHit); // remove hit
464 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
469 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
470 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetChamberNumber() == 6) ichambOK = 6;
471 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
472 fSkipHit->GetHitNumber() < 0) {
473 iz0 = fgCombi->IZfromHit(fSkipHit);
476 else currIndx = fgHitForRec->IndexOf(fSkipHit);
479 fTrackHits->Compress();
481 } // if (hit == fSkipHit)
482 else if (currIndx < 0) currIndx = fTrackHits->IndexOf(hit);
483 } // else if (fRecover)
485 // Get indices of the 1'st and last hits on the track candidate
486 firstHit = (AliMUONHitForRec*) fTrackHits->First();
487 lastHit = (AliMUONHitForRec*) fTrackHits->Last();
488 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
489 lastHit->GetHitNumber() < 0) iz0 = fgCombi->IZfromHit(lastHit);
491 firstIndx = fgHitForRec->IndexOf(firstHit);
492 lastIndx = fgHitForRec->IndexOf(lastHit);
493 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
497 if (iz0 < 0) iz0 = iFB;
498 while (ichamb >= iMin && ichamb <= iMax) {
499 // Find the closest hit in Z, not belonging to the current plane
502 if (currIndx < fNmbTrackHits) {
503 hitAdd = (AliMUONHitForRec*) fTrackHits->UncheckedAt(currIndx);
504 zEnd = hitAdd->GetZ();
505 //AZ(z->-z) } else zEnd = -9999;
508 //AZ(Z->-Z) zEnd = -9999;
510 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
511 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
512 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
513 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
514 zEnd = hitAdd->GetZ();
520 // Combined cluster / track finder
521 if (zEnd > 999 && iFB < 0 && fgTrackReconstructor->GetTrackMethod() == 3) {
523 AliMUONHitForRec hitTmp;
524 for (iz = iz0 - iFB; iz < fgCombi->Nz(); iz++) {
525 if (TMath::Abs(fgCombi->Z(iz)-fPosition) < 0.5) continue;
526 Int_t *pDEatZ = fgCombi->DEatZ(iz);
527 //cout << iz << " " << fgCombi->Z(iz) << endl;
528 zEnd = fgCombi->Z(iz);
530 AliMUONDetElement *detElem = fgCombi->DetElem(pDEatZ[0]);
532 hitAdd->SetChamberNumber(detElem->Chamber());
533 //hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
538 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
540 // Check if there is a chamber without hits
541 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
542 if (!Back && zEnd<999) currIndx -= iFB;
544 zEnd = AliMUONConstants::DefaultChamberZ(ichamb);
547 ichamb = hitAdd->GetChamberNumber();
551 if (ichamb<iMin || ichamb>iMax) break;
552 // Check for missing station
554 dChamb = TMath::Abs(ichamb-ichambOK);
555 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
556 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
557 if (zEnd > 999) dStatMiss++;
559 //if (dStatMiss == 2 && ichambOK/2 != 3 || dStatMiss > 2) { // AZ - missing st. 3
560 // missing station - abandon track
561 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
563 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
564 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
565 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
566 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
567 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
568 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
571 cout << fNmbTrackHits << endl;
572 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
573 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
574 printf(" * %d %10.4f %10.4f %10.4f",
575 hit->GetChamberNumber(), hit->GetBendingCoor(),
576 hit->GetNonBendingCoor(), hit->GetZ());
578 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
579 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
580 printf("%3d", clus->GetTrack(1)-1);
581 if (clus->GetTrack(2) != 0)
582 printf("%3d \n", clus->GetTrack(2)-1);
587 } // if (fgDebug >= 10)
588 if (fNmbTrackHits>2 && fRecover==0) Recover(); // try to recover track later
590 } // if (dStatMiss > 1)
592 if (endOfProp != 0) break;
594 // propagate to the found Z
596 // Check if track steps into dipole
597 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
598 if (fPosition<zDipole2 && zEnd>zDipole2) {
599 //LinearPropagation(zDipole2-zBeg);
600 ParPropagation(zDipole2);
601 MSThin(1); // multiple scattering in the chamber
602 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
603 fPosition = fPositionNew;
604 *fTrackPar = *fTrackParNew;
605 //MagnetPropagation(zEnd);
606 ParPropagation(zEnd);
607 WeightPropagation(zEnd, kTRUE);
608 fPosition = fPositionNew;
610 // Check if track steps out of dipole
611 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
612 else if (fPosition<zDipole1 && zEnd>zDipole1) {
613 //MagnetPropagation(zDipole1-zBeg);
614 ParPropagation(zDipole1);
615 MSThin(1); // multiple scattering in the chamber
616 WeightPropagation(zDipole1, kTRUE);
617 fPosition = fPositionNew;
618 *fTrackPar = *fTrackParNew;
619 //LinearPropagation(zEnd-zDipole1);
620 ParPropagation(zEnd);
621 WeightPropagation(zEnd, kTRUE);
622 fPosition = fPositionNew;
624 ParPropagation(zEnd);
625 //MSThin(1); // multiple scattering in the chamber
626 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
627 WeightPropagation(zEnd, kTRUE);
628 fPosition = fPositionNew;
632 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
633 // recovered track - remove the hit
635 ichamb = fSkipHit->GetChamberNumber();
636 // remove the skipped hit
637 fTrackHits->Remove(fSkipHit);
639 //AZ fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
642 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
643 //? if (fgTrackReconstructor->GetTrackMethod() != 3) currIndx = fgHitForRec->IndexOf(fSkipHit);
644 currIndx = fgHitForRec->IndexOf(fSkipHit);
648 // backward propagator
650 TMatrixD pointWeight(fgkSize,fgkSize);
651 TMatrixD point(fgkSize,1);
652 TMatrixD trackParTmp = point;
653 point(0,0) = hitAdd->GetBendingCoor();
654 point(1,0) = hitAdd->GetNonBendingCoor();
655 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
656 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
657 TryPoint(point,pointWeight,trackParTmp,dChi2);
658 *fTrackPar = trackParTmp;
659 *fWeight += pointWeight;
660 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
661 fChi2 += dChi2; // Chi2
662 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
663 if (ichamb==ichamEnd) break;
666 // forward propagator
667 if (miss || !FindPoint(ichamb, zEnd, currIndx, iFB, hitAdd, iz)) {
669 *fTrackPar = *fTrackParNew;
672 fTrackHits->Add(hitAdd); // add hit
674 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
676 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
680 if (fgDebug > 0) cout << fNmbTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
681 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
682 if (GetRecover() < 0) success = kFALSE;
686 //__________________________________________________________________________
687 void AliMUONTrackK::ParPropagation(Double_t zEnd)
689 /// Propagation of track parameters to zEnd
691 Double_t dZ, step, distance, charge;
692 Double_t vGeant3[7], vGeant3New[7];
693 AliMUONTrackParam trackParam;
696 // First step using linear extrapolation
697 dZ = zEnd - fPosition;
698 fPositionNew = fPosition;
699 *fTrackParNew = *fTrackPar;
700 if (dZ == 0) return; //AZ ???
701 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
702 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
703 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
704 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
705 SetGeantParam(vGeant3,iFB);
706 //fTrackParNew->Print();
710 step = TMath::Abs(step);
711 // Propagate parameters
712 AliMUONTrackExtrap::ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
713 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
714 distance = zEnd - vGeant3New[2];
715 step *= dZ/(vGeant3New[2]-fPositionNew);
717 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
719 GetFromGeantParam(vGeant3New,iFB);
720 //fTrackParNew->Print();
722 // Position adjustment (until within tolerance)
723 while (TMath::Abs(distance) > fgkEpsilon) {
724 dZ = zEnd - fPositionNew;
725 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
726 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
727 step = TMath::Abs(step);
728 SetGeantParam(vGeant3,iFB);
731 // Propagate parameters
732 AliMUONTrackExtrap::ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
733 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
734 distance = zEnd - vGeant3New[2];
737 if (nTries > fgkTriesMax) AliError(Form(" Too many tries: %d", nTries));
738 } while (distance*iFB < 0);
740 GetFromGeantParam(vGeant3New,iFB);
742 //cout << nTries << endl;
743 //fTrackParNew->Print();
747 //__________________________________________________________________________
748 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
750 /// Propagation of the weight matrix
751 /// W = DtWD, where D is Jacobian
755 TMatrixD jacob(fgkSize,fgkSize);
758 // Save initial and propagated parameters
759 TMatrixD trackPar0 = *fTrackPar;
760 TMatrixD trackParNew0 = *fTrackParNew;
762 // Get covariance matrix
763 *fCovariance = *fWeight;
764 // check whether the Invert method returns flag if matrix cannot be inverted,
765 // and do not calculate the Determinant in that case !!!!
766 if (fCovariance->Determinant() != 0) {
768 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
769 //fCovariance->Print();
771 AliWarning(" Determinant fCovariance=0:");
774 // Loop over parameters to find change of the propagated vs initial ones
775 for (i=0; i<fgkSize; i++) {
776 dPar = TMath::Sqrt((*fCovariance)(i,i));
777 *fTrackPar = trackPar0;
778 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
779 (*fTrackPar)(i,0) += dPar;
780 ParPropagation(zEnd);
781 for (j=0; j<fgkSize; j++) {
782 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
786 //trackParNew0.Print();
787 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
789 TMatrixD jacob0 = jacob;
790 if (jacob.Determinant() != 0) {
793 AliWarning(" Determinant jacob=0:");
795 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
796 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
798 // Restore initial and propagated parameters
799 *fTrackPar = trackPar0;
800 *fTrackParNew = trackParNew0;
803 if (!smooth) return; // do not use smoother
804 if (fTrackDir < 0) return; // only for propagation towards int. point
805 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
806 fParExtrap->Add(tmp);
808 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
809 fParFilter->Add(tmp);
811 *fCovariance = *fWeight;
812 if (fCovariance->Determinant() != 0) {
814 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
816 AliWarning(" Determinant fCovariance=0:");
818 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
819 fCovExtrap->Add(tmp);
821 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
822 fCovFilter->Add(tmp);
824 tmp = new TMatrixD(jacob0); // Jacobian
827 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
828 fSteps->AddAt(fPositionNew,fNSteps++);
829 if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
833 //__________________________________________________________________________
834 Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd, Int_t iz)
836 /// Picks up point within a window for the chamber No ichamb
837 /// Split the track if there are more than 1 hit
838 Int_t ihit, nRecTracks;
839 Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
840 TClonesArray *trackPtr;
841 AliMUONHitForRec *hit, *hitLoop;
842 AliMUONTrackK *trackK;
843 AliMUONDetElement *detElem = NULL;
847 if (fgTrackReconstructor->GetTrackMethod() == 3 && iz >= 0) {
848 // Combined cluster / track finder
849 // Check if extrapolated track passes thru det. elems. at iz
850 Int_t *pDEatZ = fgCombi->DEatZ(iz);
851 Int_t nDetElem = pDEatZ[-1];
852 //cout << fgCombi->Z(iz) << " " << nDetElem << endl;
853 for (Int_t i = 0; i < nDetElem; i++) {
854 detElem = fgCombi->DetElem(pDEatZ[i]);
855 if (detElem->Inside((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPosition)) {
856 detElem->ClusterReco((*fTrackParNew)(1,0), (*fTrackParNew)(0,0));
857 hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
862 if (!ok) return ok; // outside det. elem.
866 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
867 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
868 *fCovariance = *fWeight;
869 // check whether the Invert method returns flag if matrix cannot be inverted,
870 // and do not calculate the Determinant in that case !!!!
871 if (fCovariance->Determinant() != 0) {
873 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
875 AliWarning(" Determinant fCovariance=0:");
877 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
878 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
879 // Loop over all hits and take hits from the chamber
880 TMatrixD pointWeight(fgkSize,fgkSize);
881 TMatrixD saveWeight = pointWeight;
882 TMatrixD pointWeightTmp = pointWeight;
883 TMatrixD point(fgkSize,1);
884 TMatrixD trackPar = point;
885 TMatrixD trackParTmp = point;
886 Int_t nHitsOK = 0, ihitB = currIndx, ihitE = fgNOfPoints, iDhit = iFB;
888 zLast = ((AliMUONHitForRec*)fTrackHits->Last())->GetZ();
889 if (fgTrackReconstructor->GetTrackMethod() == 3 && detElem) {
891 ihitE = detElem->NHitsForRec();
895 TArrayD branchChi2(20);
896 for (ihit = ihitB; ihit >= 0 && ihit < ihitE; ihit+=iDhit) {
897 if (fgTrackReconstructor->GetTrackMethod() != 3 || !detElem)
898 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
899 else hit = (AliMUONHitForRec*) detElem->HitsForRec()->UncheckedAt(ihit);
900 if (hit->GetChamberNumber() == ichamb) {
901 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
902 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
903 y = hit->GetBendingCoor();
904 x = hit->GetNonBendingCoor();
905 if (hit->GetBendingReso2() < 0) {
906 // Combined cluster / track finder
907 hit->SetBendingReso2(fgTrackReconstructor->GetBendingResolution()*
908 fgTrackReconstructor->GetBendingResolution());
909 hit->SetNonBendingReso2(fgTrackReconstructor->GetNonBendingResolution()*
910 fgTrackReconstructor->GetNonBendingResolution());
912 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
913 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
915 // windowB = TMath::Min (windowB,5.);
916 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
918 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
919 windowB = TMath::Min (windowB,0.5);
920 windowNonB = TMath::Min (windowNonB,3.);
921 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
922 windowB = TMath::Min (windowB,1.5);
923 windowNonB = TMath::Min (windowNonB,3.);
924 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
925 windowB = TMath::Min (windowB,4.);
926 windowNonB = TMath::Min (windowNonB,6.);
932 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
933 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
934 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
936 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
937 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
941 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
942 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
943 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
944 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
945 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
946 // hit->GetTrackRefSignal() == 1) { // just for test
947 // Vector of measurements and covariance matrix
948 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
949 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
950 // Adjust position: for multiple hits in the chamber or misalignment (Z as a function of X or Y)
951 //AliWarning(Form(" *** adjust %f %f ", zEnd, hit->GetZ()));
953 *fTrackPar = *fTrackParNew;
954 ParPropagation(zEnd);
955 WeightPropagation(zEnd, kTRUE);
956 fPosition = fPositionNew;
957 *fTrackPar = *fTrackParNew;
959 *fCovariance = *fWeight;
960 if (fCovariance->Determinant() != 0) {
962 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
964 AliWarning(" Determinant fCovariance=0:" );
970 pointWeight(0,0) = 1/hit->GetBendingReso2();
971 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
972 TryPoint(point,pointWeight,trackPar,dChi2);
973 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
974 // if (TMath::Sign(1.,(trackPar)(4,0)*(*fTrackPar)(4,0)) < 0) continue; // change of sign
977 //if (nHitsOK > -1) {
979 // Save current members
980 saveWeight = *fWeight;
981 savePosition = fPosition;
982 // temporary storage for the current track
984 trackParTmp = trackPar;
985 pointWeightTmp = pointWeight;
987 if (fgDebug > 0) cout << " Added point: " << x << " " << y << " " << dChi2 << endl;
988 branchChi2[0] = dChi2;
990 // branching: create a new track
991 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
992 nRecTracks = fgTrackReconstructor->GetNRecTracks();
993 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
995 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
996 if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNmbTrackHits << " " << nRecTracks << endl;
997 trackK->fRecover = 0;
998 *(trackK->fTrackPar) = trackPar;
999 *(trackK->fWeight) += pointWeight;
1000 trackK->fChi2 += dChi2;
1003 *(trackK->fCovariance) = *(trackK->fWeight);
1004 if (trackK->fCovariance->Determinant() != 0) {
1006 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1008 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
1010 // Add filtered matrices for the smoother
1011 if (fTrackDir > 0) {
1012 if (nHitsOK > 2) { // check for position adjustment
1013 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
1014 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
1015 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
1016 RemoveMatrices(trackK);
1017 AliError(Form(" *** Position adjustment 1: %f %f", hit->GetZ(), (*trackK->fSteps)[i]));
1022 AddMatrices (trackK, dChi2, hit);
1024 // Mark hits as being on 2 tracks
1025 for (Int_t i=0; i<fNmbTrackHits; i++) {
1026 hitLoop = (AliMUONHitForRec*) ((*fTrackHits)[i]);
1027 //AZ hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
1030 cout << hitLoop->GetChamberNumber() << " ";
1031 cout << hitLoop->GetBendingCoor() << " ";
1032 cout << hitLoop->GetNonBendingCoor() << " ";
1033 cout << hitLoop->GetZ() << " " << " ";
1034 cout << hitLoop->GetTTRTrack() << endl;
1035 printf(" ** %d %10.4f %10.4f %10.4f\n",
1036 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
1037 hitLoop->GetNonBendingCoor(), hitLoop->GetZ());
1041 trackK->fTrackHits->Add(hit); // add hit
1042 trackK->fNmbTrackHits ++;
1043 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
1046 trackK->fTrackDir = 1;
1047 trackK->fBPFlag = kTRUE;
1049 if (nHitsOK > branchChi2.GetSize()) branchChi2.Set(branchChi2.GetSize()+10);
1050 branchChi2[nHitsOK-1] = dChi2;
1054 } else break; // different chamber
1055 } // for (ihit=currIndx;
1058 *fTrackPar = trackParTmp;
1059 *fWeight = saveWeight;
1060 *fWeight += pointWeightTmp;
1061 fChi2 += dChi2Tmp; // Chi2
1062 fPosition = savePosition;
1063 // Add filtered matrices for the smoother
1064 if (fTrackDir > 0) {
1065 for (Int_t i=fNSteps-1; i>=0; i--) {
1066 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
1067 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
1068 RemoveMatrices(this);
1069 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
1072 } // for (Int_t i=fNSteps-1;
1073 AddMatrices (this, dChi2Tmp, hitAdd);
1076 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1077 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1080 } // if (fTrackDir > 0)
1081 // Check for maximum number of branches - exclude excessive
1082 if (nHitsOK > 1) CheckBranches(branchChi2, nHitsOK);
1087 //__________________________________________________________________________
1088 void AliMUONTrackK::CheckBranches(TArrayD &branchChi2, Int_t nBranch)
1090 /// Check for maximum number of branches - exclude excessive
1092 Int_t nBranchMax = 5;
1093 if (nBranch <= nBranchMax) return;
1095 Double_t *chi2 = branchChi2.GetArray();
1096 Int_t *indx = new Int_t [nBranch];
1097 TMath::Sort (nBranch, chi2, indx, kFALSE);
1098 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1099 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
1100 Int_t ibeg = nRecTracks - nBranch;
1102 // Discard excessive branches with higher Chi2 contribution
1103 for (Int_t i = nBranchMax; i < nBranch; ++i) {
1105 // Discard current track
1109 Int_t j = ibeg + indx[i];
1110 AliMUONTrackK *trackK = (AliMUONTrackK*) trackPtr->UncheckedAt(j);
1111 trackK->SetRecover(-1);
1116 //__________________________________________________________________________
1117 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1119 /// Adds a measurement point (modifies track parameters and computes
1122 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1123 TMatrixD wu = *fWeight;
1124 wu += pointWeight; // W+U
1125 trackParTmp = point;
1126 trackParTmp -= *fTrackParNew; // m-p
1127 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1128 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1129 right += right1; // U(m-p) + (W+U)p
1131 // check whether the Invert method returns flag if matrix cannot be inverted,
1132 // and do not calculate the Determinant in that case !!!!
1133 if (wu.Determinant() != 0) {
1135 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1137 AliWarning(" Determinant wu=0:");
1139 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1141 right1 = trackParTmp;
1142 right1 -= point; // p'-m
1143 point = trackParTmp;
1144 point -= *fTrackParNew; // p'-p
1145 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1146 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1148 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1149 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1150 dChi2 += value(0,0);
1154 //__________________________________________________________________________
1155 void AliMUONTrackK::MSThin(Int_t sign)
1157 /// Adds multiple scattering in a thin layer (only angles are affected)
1158 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1160 // check whether the Invert method returns flag if matrix cannot be inverted,
1161 // and do not calculate the Determinant in that case !!!!
1162 if (fWeight->Determinant() != 0) {
1164 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1166 AliWarning(" Determinant fWeight=0:");
1169 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1170 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1171 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1172 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1173 velo = 1; // relativistic
1174 path = TMath::Abs(AliMUONConstants::ChamberThicknessInX0()/cosAlph/cosBeta); // path length
1175 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1177 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1178 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1180 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1184 //__________________________________________________________________________
1185 void AliMUONTrackK::StartBack(void)
1187 /// Starts backpropagator
1191 for (Int_t i=0; i<fgkSize; i++) {
1192 for (Int_t j=0; j<fgkSize; j++) {
1193 if (j==i) (*fWeight)(i,i) /= 100;
1194 //if (j==i) (*fWeight)(i,i) /= fNmbTrackHits*fNmbTrackHits;
1195 else (*fWeight)(j,i) = 0;
1198 // Sort hits on track in descending order in abs(z)
1199 SortHits(0, fTrackHits);
1202 //__________________________________________________________________________
1203 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1205 /// Sort hits in Z if the seed segment is in the last but one station
1206 /// (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1208 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1209 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1210 Int_t i = 1, entries = array->GetEntriesFast();
1211 for ( ; i<entries; i++) {
1213 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1215 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1216 if (z < zmax) break;
1218 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1222 for (Int_t j=0; j<=(i-1)/2; j++) {
1223 TObject *hit = array->UncheckedAt(j);
1224 array->AddAt(array->UncheckedAt(i-j),j);
1225 array->AddAt(hit,i-j);
1227 if (fgDebug >= 10) {
1228 for (i=0; i<entries; i++)
1229 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1230 cout << " - Sort" << endl;
1234 //__________________________________________________________________________
1235 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1237 /// Set vector of Geant3 parameters pointed to by "VGeant3"
1238 /// from track parameters
1240 VGeant3[0] = (*fTrackParNew)(1,0); // X
1241 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1242 VGeant3[2] = fPositionNew; // Z
1243 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1244 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1245 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1246 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1249 //__________________________________________________________________________
1250 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1252 /// Get track parameters from vector of Geant3 parameters pointed
1255 fPositionNew = VGeant3[2]; // Z
1256 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1257 (*fTrackParNew)(1,0) = VGeant3[0]; // X
1258 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1259 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1260 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1263 //__________________________________________________________________________
1264 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1266 /// Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1269 AliWarning(Form(" *** Too high Chi2: %f ", fChi2));
1272 if (iChi2 == 0) fChi2 = fNmbTrackHits + (500.-fChi2)/501;
1273 else fChi2 = 500 - (fChi2-fNmbTrackHits)*501;
1276 //__________________________________________________________________________
1277 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1279 /// "Compare" function to sort with decreasing "track quality".
1280 /// Returns +1 (0, -1) if quality of current track
1281 /// is smaller than (equal to, larger than) quality of trackK
1283 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1284 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1288 //__________________________________________________________________________
1289 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1291 /// Check whether or not to keep current track
1292 /// (keep, if it has less than half of common hits with track0)
1293 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1294 AliMUONHitForRec *hit0, *hit1;
1297 nHits0 = track0->fNmbTrackHits;
1298 nTrackHits2 = fNmbTrackHits/2;
1300 for (i=0; i<nHits0; i++) {
1301 // Check if hit belongs to several tracks
1302 hit0 = (AliMUONHitForRec*) (*track0->fTrackHits)[i];
1303 if (hit0->GetNTrackHits() == 1) continue;
1304 for (j=0; j<fNmbTrackHits; j++) {
1305 hit1 = (AliMUONHitForRec*) (*fTrackHits)[j];
1306 if (hit1->GetNTrackHits() == 1) continue;
1309 if (hitsInCommon >= nTrackHits2) return kFALSE;
1317 //__________________________________________________________________________
1318 void AliMUONTrackK::Kill(void)
1320 /// Kill track candidate
1321 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1324 //__________________________________________________________________________
1325 void AliMUONTrackK::FillMUONTrack(void)
1327 /// Compute track parameters at hit positions (as for AliMUONTrack)
1332 // Set track parameters at vertex
1333 AliMUONTrackParam trackParam;
1334 SetTrackParam(&trackParam, fTrackPar, fPosition);
1335 SetTrackParamAtVertex(&trackParam);
1337 // Set track parameters at hits
1338 for (Int_t i = fNmbTrackHits-1; i>=0; i--) {
1339 if ((*fChi2Smooth)[i] < 0) {
1340 // Propagate through last chambers
1341 AliMUONTrackExtrap::ExtrapToZ(&trackParam, ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1344 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1346 AddTrackParamAtHit(&trackParam,(AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1347 // Fill array of HitForRec's
1348 AddHitForRecAtHit((AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1352 //__________________________________________________________________________
1353 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1355 /// Fill AliMUONTrackParam object
1357 trackParam->SetBendingCoor((*par)(0,0));
1358 trackParam->SetNonBendingCoor((*par)(1,0));
1359 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1360 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1361 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1362 trackParam->SetZ(z);
1365 //__________________________________________________________________________
1366 void AliMUONTrackK::Branson(void)
1368 /// Propagates track to the vertex thru absorber using Branson correction
1369 /// (makes use of the AliMUONTrackParam class)
1371 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1372 AliMUONTrackParam trackParam = AliMUONTrackParam();
1374 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1375 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1376 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1377 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1378 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1379 trackParam->SetZ(fPosition);
1381 SetTrackParam(&trackParam, fTrackPar, fPosition);
1383 AliMUONTrackExtrap::ExtrapToVertex(&trackParam, Double_t(0.), Double_t(0.), Double_t(0.));
1385 (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1386 (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1387 (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1388 (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1389 (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1390 fPosition = trackParam.GetZ();
1391 //delete trackParam;
1392 if (fgDebug > 0) cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1394 // Get covariance matrix
1395 *fCovariance = *fWeight;
1396 if (fCovariance->Determinant() != 0) {
1398 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1400 AliWarning(" Determinant fCovariance=0:");
1404 //__________________________________________________________________________
1405 void AliMUONTrackK::GoToZ(Double_t zEnd)
1407 /// Propagates track to given Z
1409 ParPropagation(zEnd);
1410 MSThin(1); // multiple scattering in the chamber
1411 WeightPropagation(zEnd, kFALSE);
1412 fPosition = fPositionNew;
1413 *fTrackPar = *fTrackParNew;
1416 //__________________________________________________________________________
1417 void AliMUONTrackK::GoToVertex(Int_t iflag)
1420 /// Propagates track to the vertex
1421 /// All material constants are taken from AliRoot
1423 static Double_t x01[5] = { 24.282, // C
1428 // inner part theta < 3 degrees
1429 static Double_t x02[5] = { 30413, // Air
1434 // z positions of the materials inside the absober outer part theta > 3 degres
1435 static Double_t zPos[10] = {-90, -105, -315, -443, -468};
1437 Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
1438 AliMUONHitForRec *hit;
1439 AliMUONRawCluster *clus;
1440 TClonesArray *rawclusters;
1442 // First step to the rear end of the absorber
1443 Double_t zRear = -503;
1445 Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1447 // Go through absorber
1448 pOld = 1/(*fTrackPar)(4,0);
1449 Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1450 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1451 r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
1453 Double_t p0, cos25, cos60;
1454 if (!iflag) goto vertex;
1456 for (Int_t i=4; i>=0; i--) {
1457 ParPropagation(zPos[i]);
1458 WeightPropagation(zPos[i], kFALSE);
1459 dZ = TMath::Abs (fPositionNew-fPosition);
1460 if (r0Norm > 1) x0 = x01[i];
1462 MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
1463 fPosition = fPositionNew;
1464 *fTrackPar = *fTrackParNew;
1465 r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1466 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1467 r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
1469 // Correct momentum for energy losses
1470 pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
1472 cos25 = TMath::Cos(2.5/180*TMath::Pi());
1473 cos60 = TMath::Cos(6.0/180*TMath::Pi());
1474 for (Int_t j=0; j<1; j++) {
1478 deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1480 deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1484 deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1486 deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1494 deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1496 deltaP = 3.0643 + 0.01346*p0;
1502 deltaP = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1504 deltaP = 2.407 + 0.00702*p0;
1513 deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1515 deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1522 deltaP = 2.209 + 0.800e-2*p0;
1524 deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1534 deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1536 deltaP = 3.0714 + 0.011767 * p0;
1541 deltaP = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1543 deltaP = 2.6069 + 0.0051705 * p0;
1549 p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
1551 (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1555 ParPropagation((Double_t)0.);
1556 WeightPropagation((Double_t)0., kFALSE);
1557 fPosition = fPositionNew;
1558 //*fTrackPar = *fTrackParNew;
1559 // Add vertex as a hit
1560 TMatrixD pointWeight(fgkSize,fgkSize);
1561 TMatrixD point(fgkSize,1);
1562 TMatrixD trackParTmp = point;
1563 point(0,0) = 0; // vertex coordinate - should be taken somewhere
1564 point(1,0) = 0; // vertex coordinate - should be taken somewhere
1565 pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1566 pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1567 TryPoint(point,pointWeight,trackParTmp,dChi2);
1568 *fTrackPar = trackParTmp;
1569 *fWeight += pointWeight;
1570 fChi2 += dChi2; // Chi2
1571 if (fgDebug < 0) return; // no output
1573 cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNmbTrackHits << endl;
1574 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1575 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1576 printf ("%5d", hit->GetChamberNumber());
1580 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1581 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1582 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1583 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1584 printf ("%5d", fgHitForRec->IndexOf(hit));
1589 // from raw clusters
1590 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1591 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1592 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1593 Int_t index = -hit->GetHitNumber() / 100000;
1594 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1595 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1597 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1598 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1600 printf ("%5d", clus->GetTrack(1)%10000000);
1603 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1604 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1605 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1606 Int_t index = -hit->GetHitNumber() / 100000;
1607 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1608 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1610 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1611 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1613 if (clus->GetTrack(2) != -1) printf ("%5d", clus->GetTrack(2)%10000000);
1614 else printf ("%5s", " ");
1618 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1619 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1620 cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1621 //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHits)[i1]))) << " ";
1624 for (Int_t i1=0; i1<fNmbTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1626 cout << "---------------------------------------------------" << endl;
1628 // Get covariance matrix
1629 /* Not needed - covariance matrix is not interesting to anybody
1630 *fCovariance = *fWeight;
1631 if (fCovariance->Determinant() != 0) {
1633 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1635 AliWarning(" Determinant fCovariance=0:" );
1640 //__________________________________________________________________________
1641 void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
1643 /// Adds multiple scattering in a thick layer for linear propagation
1645 Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1646 Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1647 Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1649 sinBeta = TMath::Sin((*fTrackPar)(3,0));
1650 Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1651 Double_t momentum = 1/(*fTrackPar)(4,0);
1652 Double_t velo = 1; // relativistic velocity
1653 Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
1655 // Projected scattering angle
1656 Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0));
1657 Double_t theta02 = theta0*theta0;
1658 Double_t dl2 = step*step/2*theta02;
1659 Double_t dl3 = dl2*step*2/3;
1662 Double_t dYdT = 1/cosAlph;
1663 Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1664 Double_t dXdT = tanAlph*tanBeta;
1665 //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1666 Double_t dXdB = 1/cosBeta;
1667 Double_t dAdT = 1/cosBeta;
1668 Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1670 // Get covariance matrix
1671 *fCovariance = *fWeight;
1672 if (fCovariance->Determinant() != 0) {
1673 // fCovariance->Invert();
1675 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1677 AliWarning(" Determinant fCovariance=0:" );
1680 (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1681 (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1682 (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1683 (*fCovariance)(3,3) += theta02*step; // <bb>
1685 (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1686 (*fCovariance)(1,0) = (*fCovariance)(0,1);
1688 (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1689 (*fCovariance)(2,0) = (*fCovariance)(0,2);
1691 (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1692 (*fCovariance)(3,0) = (*fCovariance)(0,3);
1694 (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
1695 (*fCovariance)(2,1) = (*fCovariance)(1,2);
1697 (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1698 (*fCovariance)(3,1) = (*fCovariance)(1,3);
1700 (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1701 (*fCovariance)(3,2) = (*fCovariance)(2,3);
1703 // Get weight matrix
1704 *fWeight = *fCovariance;
1705 if (fWeight->Determinant() != 0) {
1707 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1709 AliWarning(" Determinant fWeight=0:");
1713 //__________________________________________________________________________
1714 Bool_t AliMUONTrackK::Recover(void)
1716 /// Adds new failed track(s) which can be tried to be recovered
1718 TClonesArray *trackPtr;
1719 AliMUONTrackK *trackK;
1721 if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
1722 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1724 // Remove hit with the highest chi2
1727 for (Int_t i=0; i<fNmbTrackHits; i++) {
1728 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1729 printf("%10.4f", chi2);
1732 for (Int_t i=0; i<fNmbTrackHits; i++) {
1733 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
1737 Double_t chi2max = 0;
1739 for (Int_t i=0; i<fNmbTrackHits; i++) {
1740 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1741 if (chi2 < chi2max) continue;
1745 //if (chi2max < 10) return kFALSE; // !!!
1746 //if (chi2max < 25) imax = fNmbTrackHits - 1;
1747 if (chi2max < 15) imax = fNmbTrackHits - 1; // discard the last point
1748 // Check if the outlier is not from the seed segment
1749 AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
1750 if (skipHit == (AliMUONHitForRec*) fStartSegment->First() || skipHit == (AliMUONHitForRec*) fStartSegment->Second()) {
1751 //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1752 return kFALSE; // to be changed probably
1755 // Make a copy of track hit collection
1756 TObjArray *hits = new TObjArray(*fTrackHits);
1760 // Hits after the found one will be removed
1761 if (GetStation0() == 3 && skipHit->GetChamberNumber() >= 7) {
1762 SortHits(1, fTrackHits); // unsort hits
1763 imax = fTrackHits->IndexOf(skipHit);
1765 Int_t nTrackHits = fNmbTrackHits;
1766 for (Int_t i=imax+1; i<nTrackHits; i++) {
1767 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
1768 fTrackHits->Remove(hit);
1769 hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit
1773 // Check if the track candidate doesn't exist yet
1774 if (ExistDouble()) { delete hits; return kFALSE; }
1776 //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1779 nRecTracks = fgTrackReconstructor->GetNRecTracks();
1780 skipHit = (AliMUONHitForRec*) ((*fTrackHits)[fNmbTrackHits-1]);
1781 // Remove all saved steps and smoother matrices after the skipped hit
1782 RemoveMatrices(skipHit->GetZ());
1784 //AZ(z->-z) if (skipHit->GetZ() > ((AliMUONHitForRec*) fStartSegment->Second())->GetZ() || !fNSteps) {
1785 if (TMath::Abs(skipHit->GetZ()) > TMath::Abs( ((AliMUONHitForRec*) fStartSegment->Second())->GetZ()) || !fNSteps) {
1786 // Propagation toward high Z or skipped hit next to segment -
1787 // start track from segment
1788 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
1789 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1790 trackK->fRecover = 1;
1791 trackK->fSkipHit = skipHit;
1792 trackK->fNmbTrackHits = fNmbTrackHits;
1793 delete trackK->fTrackHits; // not efficient ?
1794 trackK->fTrackHits = new TObjArray(*fTrackHits);
1795 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1799 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1801 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1802 //AZ(z->-z) trackK->fTrackDir = -1;
1803 trackK->fTrackDir = 1;
1804 trackK->fRecover = 1;
1805 trackK->fSkipHit = skipHit;
1806 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1808 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1809 CreateMatrix(trackK->fParFilter);
1811 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1812 trackK->fParFilter->Last()->SetUniqueID(1);
1813 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1814 iD = trackK->fCovFilter->Last()->GetUniqueID();
1816 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1817 CreateMatrix(trackK->fCovFilter);
1819 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1820 trackK->fCovFilter->Last()->SetUniqueID(1);
1821 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1822 if (trackK->fWeight->Determinant() != 0) {
1824 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1826 AliWarning(" Determinant fWeight=0:");
1828 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1830 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1831 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1835 //__________________________________________________________________________
1836 void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1838 /// Adds matrices for the smoother and keep Chi2 for the point
1839 /// Track parameters
1840 //trackK->fParFilter->Last()->Print();
1841 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1843 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1844 CreateMatrix(trackK->fParFilter);
1847 *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1848 trackK->fParFilter->Last()->SetUniqueID(iD);
1850 cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1851 //trackK->fTrackPar->Print();
1852 //trackK->fTrackParNew->Print();
1853 trackK->fParFilter->Last()->Print();
1854 cout << " Add matrices" << endl;
1857 *(trackK->fCovariance) = *(trackK->fWeight);
1858 if (trackK->fCovariance->Determinant() != 0) {
1860 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1862 AliWarning(" Determinant fCovariance=0:");
1864 iD = trackK->fCovFilter->Last()->GetUniqueID();
1866 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1867 CreateMatrix(trackK->fCovFilter);
1870 *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1871 trackK->fCovFilter->Last()->SetUniqueID(iD);
1873 // Save Chi2-increment for point
1874 Int_t indx = trackK->fTrackHits->IndexOf(hitAdd);
1875 if (indx < 0) indx = fNmbTrackHits;
1876 if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10);
1877 trackK->fChi2Array->AddAt(dChi2,indx);
1880 //__________________________________________________________________________
1881 void AliMUONTrackK::CreateMatrix(TObjArray *objArray) const
1883 /// Create new matrix and add it to TObjArray
1885 TMatrixD *matrix = (TMatrixD*) objArray->First();
1886 TMatrixD *tmp = new TMatrixD(*matrix);
1887 objArray->AddAtAndExpand(tmp,objArray->GetLast());
1888 //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1891 //__________________________________________________________________________
1892 void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1894 /// Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1896 for (Int_t i=fNSteps-1; i>=0; i--) {
1897 if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1898 if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1899 RemoveMatrices(this);
1900 } // for (Int_t i=fNSteps-1;
1903 //__________________________________________________________________________
1904 void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1906 /// Remove last saved matrices and steps in the smoother part
1909 Int_t i = trackK->fNSteps;
1912 // Delete only matrices not shared by several tracks
1913 id = trackK->fParExtrap->Last()->GetUniqueID();
1915 trackK->fParExtrap->Last()->SetUniqueID(id-1);
1916 trackK->fParExtrap->RemoveAt(i);
1918 else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1919 id = fParFilter->Last()->GetUniqueID();
1921 trackK->fParFilter->Last()->SetUniqueID(id-1);
1922 trackK->fParFilter->RemoveAt(i);
1924 else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1925 id = trackK->fCovExtrap->Last()->GetUniqueID();
1927 trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1928 trackK->fCovExtrap->RemoveAt(i);
1930 else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1931 id = trackK->fCovFilter->Last()->GetUniqueID();
1933 trackK->fCovFilter->Last()->SetUniqueID(id-1);
1934 trackK->fCovFilter->RemoveAt(i);
1936 else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1937 id = trackK->fJacob->Last()->GetUniqueID();
1939 trackK->fJacob->Last()->SetUniqueID(id-1);
1940 trackK->fJacob->RemoveAt(i);
1942 else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1945 //__________________________________________________________________________
1946 Bool_t AliMUONTrackK::Smooth(void)
1949 Int_t ihit = fNmbTrackHits - 1;
1950 AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1951 fChi2Smooth = new TArrayD(fNmbTrackHits);
1952 fChi2Smooth->Reset(-1);
1954 fParSmooth = new TObjArray(15);
1955 fParSmooth->Clear();
1958 cout << " ******** Enter Smooth " << endl;
1959 cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl;
1961 for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1963 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();}
1965 for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHits)[i])->GetZ() << " ";
1969 // Find last point corresponding to the last hit
1970 Int_t iLast = fNSteps - 1;
1971 for ( ; iLast>=0; iLast--) {
1972 //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ()) break;
1973 if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ())) break;
1976 TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1978 TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1979 TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1980 TMatrixD tmpPar = *fTrackPar;
1981 //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print();
1984 Double_t chi2max = 0;
1985 for (Int_t i=iLast+1; i>0; i--) {
1986 if (i == iLast + 1) goto L33; // temporary fix
1988 // Smoother gain matrix
1989 weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1990 if (weight.Determinant() != 0) {
1992 mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1994 AliWarning(" Determinant weight=0:");
1997 tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
1998 gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
1999 //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
2001 // Smoothed parameter vector
2002 //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
2003 parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
2004 tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
2005 tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
2008 // Smoothed covariance
2009 covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
2010 weight = TMatrixD(TMatrixD::kTransposed,gain);
2011 tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
2012 covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
2013 covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
2015 // Check if there was a measurement at given z
2017 for ( ; ihit>=0; ihit--) {
2018 hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
2019 if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
2020 //AZ(z->-z) else if (ihit < fNmbTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
2021 else if (ihit < fNmbTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
2023 if (!found) continue; // no measurement - skip the rest
2024 else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
2025 if (ihit == 0) continue; // the first hit - skip the rest
2028 // Smoothed residuals
2030 tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
2031 tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
2033 cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
2034 cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
2036 // Cov. matrix of smoothed residuals
2038 tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
2039 tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
2040 tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
2041 tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
2043 // Calculate Chi2 of smoothed residuals
2044 if (tmp.Determinant() != 0) {
2046 mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2048 AliWarning(" Determinant tmp=0:");
2050 TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
2051 TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
2052 if (fgDebug > 1) chi2.Print();
2053 (*fChi2Smooth)[ihit] = chi2(0,0);
2054 if (chi2(0,0) > chi2max) chi2max = chi2(0,0);
2056 if (chi2(0,0) < 0) {
2058 AliError(Form(" *** chi2 < 0: %d %d ", i, iLast));
2060 // Save smoothed parameters
2061 TMatrixD *par = new TMatrixD(parSmooth);
2062 fParSmooth->AddAtAndExpand(par, ihit);
2064 } // for (Int_t i=iLast+1;
2066 //if (chi2max > 16) {
2067 //if (chi2max > 25) {
2068 //if (chi2max > 50) {
2069 //if (chi2max > 100) {
2070 if (chi2max > fgkChi2max) {
2071 //if (Recover()) DropBranches();
2079 //__________________________________________________________________________
2080 void AliMUONTrackK::Outlier()
2082 /// Adds new track with removed hit having the highest chi2
2085 cout << " ******** Enter Outlier " << endl;
2086 for (Int_t i=0; i<fNmbTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
2088 for (Int_t i=0; i<fNmbTrackHits; i++) {
2089 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
2094 Double_t chi2max = 0;
2096 for (Int_t i=0; i<fNmbTrackHits; i++) {
2097 if ((*fChi2Smooth)[i] < chi2max) continue;
2098 chi2max = (*fChi2Smooth)[i];
2101 // Check if the outlier is not from the seed segment
2102 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
2103 if (hit == (AliMUONHitForRec*) fStartSegment->First() || hit == (AliMUONHitForRec*) fStartSegment->Second()) return; // to be changed probably
2105 // Check for missing station
2108 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--;
2109 } else if (imax == fNmbTrackHits-1) {
2110 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2112 else if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2113 if (!ok) { Recover(); return; } // try to recover track
2114 //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; }
2116 // Remove saved steps and smoother matrices after the outlier
2117 RemoveMatrices(hit->GetZ());
2119 // Check for possible double track candidates
2120 //if (ExistDouble(hit)) return;
2122 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2123 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2125 AliMUONTrackK *trackK = 0;
2126 if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2127 // start track from segment
2128 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
2129 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2130 trackK->fRecover = 2;
2131 trackK->fSkipHit = hit;
2132 trackK->fNmbTrackHits = fNmbTrackHits;
2134 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(0);
2135 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2136 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(1);
2137 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2138 delete trackK->fTrackHits; // not efficient ?
2139 trackK->fTrackHits = new TObjArray(*fTrackHits);
2140 for (Int_t i = 0; i < fNmbTrackHits; i++) {
2141 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
2142 hit->SetNTrackHits(hit->GetNTrackHits()+1);
2145 if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHits);
2146 if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2149 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2151 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2152 trackK->fTrackDir = 1;
2153 trackK->fRecover = 2;
2154 trackK->fSkipHit = hit;
2155 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2157 trackK->fParFilter->Last()->SetUniqueID(iD-1);
2158 CreateMatrix(trackK->fParFilter);
2160 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2161 trackK->fParFilter->Last()->SetUniqueID(1);
2162 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2163 iD = trackK->fCovFilter->Last()->GetUniqueID();
2165 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2166 CreateMatrix(trackK->fCovFilter);
2168 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2169 trackK->fCovFilter->Last()->SetUniqueID(1);
2170 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2171 if (trackK->fWeight->Determinant() != 0) {
2173 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2175 AliWarning(" Determinant fWeight=0:");
2177 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2179 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2180 if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2183 //__________________________________________________________________________
2184 Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2186 /// Return Chi2 at point
2187 return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2191 //__________________________________________________________________________
2192 void AliMUONTrackK::Print(FILE *lun) const
2194 /// Print out track information
2197 AliMUONHitForRec *hit = 0;
2198 // from raw clusters
2199 AliMUONRawCluster *clus = 0;
2200 TClonesArray *rawclusters = 0;
2201 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2202 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2203 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2204 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2205 if (TMath::Abs(clus->GetTrack(1)-1) < 2) {
2206 if (clus->GetTrack(2)) flag = 2;
2209 if (clus->GetTrack(2) && TMath::Abs(clus->GetTrack(2)-1) < 2) {
2216 Int_t sig[2]={1,1}, tid[2]={0};
2217 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2218 if (GetChi2PerPoint(i1) < -0.1) continue;
2219 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2220 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2221 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2222 for (Int_t j=0; j<2; j++) {
2223 tid[j] = clus->GetTrack(j+1) - 1;
2224 if (clus->GetTrack(j+1) < 0) { sig[j] = 0; tid[j] = 999; }
2226 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(i1));
2227 if (!(clus->GetTrack(2))) fprintf(lun, "%3d %3d", sig[0], tid[0]); // simple cluster
2228 else { // track overlap
2229 fprintf(lun, "%3d %3d", TMath::Max(sig[0],sig[1]), TMath::Min(tid[0],tid[1]));
2230 //if (tid[0] < 2) flag *= 2;
2231 //else if (tid[1] < 2) flag *= 3;
2233 fprintf (lun, "%3d \n", flag);
2238 //__________________________________________________________________________
2239 void AliMUONTrackK::DropBranches(Int_t imax, TObjArray *hits)
2241 /// Drop branches downstream of the skipped hit
2243 TClonesArray *trackPtr;
2244 AliMUONTrackK *trackK;
2246 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2247 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2248 Int_t icand = trackPtr->IndexOf(this);
2249 if (!hits) hits = fTrackHits;
2251 // Check if the track candidate doesn't exist yet
2252 for (Int_t i=icand+1; i<nRecTracks; i++) {
2253 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2254 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2255 if (trackK->GetRecover() < 0) continue;
2257 if (trackK->fNmbTrackHits >= imax + 1) {
2258 for (Int_t j=0; j<=imax; j++) {
2259 //if (j != fNmbTrackHits-1 && (*trackK->fTrackHits)[j] != (*fTrackHits)[j]) break;
2260 if ((*trackK->fTrackHits)[j] != (*hits)[j]) break;
2262 if (hits != fTrackHits) {
2263 // Drop all branches downstream the hit (for Recover)
2264 trackK->SetRecover(-1);
2265 if (fgDebug >= 0 )cout << " Recover " << i << endl;
2268 // Check if the removal of the hit breaks the track
2271 if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2272 else if (imax == trackK->fNmbTrackHits-1) continue;
2273 // else if (imax == trackK->fNmbTrackHits-1) {
2274 //if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(trackK->fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2276 else if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2277 if (!ok) trackK->SetRecover(-1);
2279 } // for (Int_t j=0;
2281 } // for (Int_t i=0;
2284 //__________________________________________________________________________
2285 void AliMUONTrackK::DropBranches(AliMUONObjectPair *segment)
2287 /// Drop all candidates with the same seed segment
2289 TClonesArray *trackPtr;
2290 AliMUONTrackK *trackK;
2291 AliMUONObjectPair *trackKSegment;
2293 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2294 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2295 Int_t icand = trackPtr->IndexOf(this);
2297 for (Int_t i=icand+1; i<nRecTracks; i++) {
2298 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2299 trackKSegment = trackK->fStartSegment;
2300 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2301 if (trackK->GetRecover() < 0) continue;
2302 if (trackKSegment->First() == segment->First() &&
2303 trackKSegment->Second() == segment->Second()) trackK->SetRecover(-1);
2305 if (fgDebug >= 0) cout << " Drop segment " << endl;
2308 //__________________________________________________________________________
2309 AliMUONHitForRec* AliMUONTrackK::GetHitLastOk(void)
2311 /// Return the hit where track stopped
2313 if (!fNSteps) return (AliMUONHitForRec*)((*fTrackHits)[1]);
2317 //__________________________________________________________________________
2318 Int_t AliMUONTrackK::GetStation0(void)
2320 /// Return seed station number
2321 return ((AliMUONHitForRec*) fStartSegment->First())->GetChamberNumber() / 2;
2324 //__________________________________________________________________________
2325 Bool_t AliMUONTrackK::ExistDouble(AliMUONHitForRec *hit)
2327 /// Check if the track will make a double after outlier removal
2329 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2330 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2331 TObjArray *hitArray = new TObjArray(*fTrackHits);
2332 TObjArray *hitArray1 = new TObjArray(*hitArray);
2333 hitArray1->Remove(hit);
2334 hitArray1->Compress();
2336 Bool_t same = kFALSE;
2337 for (Int_t i=0; i<nRecTracks; i++) {
2338 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2339 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2340 if (trackK == this) continue;
2341 if (trackK->fNmbTrackHits == fNmbTrackHits || trackK->fNmbTrackHits == fNmbTrackHits-1) {
2342 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2344 if (trackK->fNmbTrackHits == fNmbTrackHits) {
2345 for (Int_t j=0; j<fNmbTrackHits; j++) {
2346 if (hits->UncheckedAt(j) != hitArray->UncheckedAt(j)) { same = kFALSE; break; }
2348 if (same) { delete hits; break; }
2349 if (trackK->fSkipHit) {
2350 TObjArray *hits1 = new TObjArray(*hits);
2351 if (hits1->Remove(trackK->fSkipHit) > 0) {
2354 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2355 if (hits1->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2357 if (same) { delete hits1; break; }
2362 // Check with removed outlier
2364 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2365 if (hits->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2367 if (same) { delete hits; break; }
2371 } // for (Int_t i=0; i<nRecTracks;
2372 delete hitArray; delete hitArray1;
2373 if (same && fgDebug >= 0) cout << " Same" << endl;
2377 //__________________________________________________________________________
2378 Bool_t AliMUONTrackK::ExistDouble(void)
2380 /// Check if the track will make a double after recovery
2382 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2383 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2385 TObjArray *hitArray = new TObjArray(*fTrackHits);
2386 if (GetStation0() == 3) SortHits(0, hitArray); // sort
2387 //if (GetStation0() == 3) SortHits(1, hitArray); // unsort
2389 Bool_t same = kFALSE;
2390 for (Int_t i=0; i<nRecTracks; i++) {
2391 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2392 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2393 if (trackK == this) continue;
2394 //AZ if (trackK->GetRecover() < 0) continue; //
2395 if (trackK->fNmbTrackHits >= fNmbTrackHits) {
2396 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2397 if (trackK->GetStation0() == 3) SortHits(0, hits); // sort
2398 //if (trackK->GetStation0() == 3) SortHits(1, hits); // unsort
2399 for (Int_t j=0; j<fNmbTrackHits; j++) {
2400 //cout << fNmbTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2401 if (j != fNmbTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break;
2402 if (j == fNmbTrackHits-1) {
2403 if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE;
2404 //if (trackK->fNmbTrackHits > fNmbTrackHits &&
2405 //if (trackK->fSkipHit) cout << ((AliMUONHitForRec*)((*hitArray)[j]))->GetZ() << " " << trackK->fSkipHit->GetZ() << endl;
2407 } // for (Int_t j=0;
2411 } // for (Int_t i=0;
2416 //______________________________________________________________________________
2417 void mnvertLocal(Double_t *a, Int_t l, Int_t, Int_t n, Int_t &ifail)
2419 ///*-*-*-*-*-*-*-*-*-*-*-*Inverts a symmetric matrix*-*-*-*-*-*-*-*-*-*-*-*-*
2420 ///*-* ==========================
2421 ///*-* inverts a symmetric matrix. matrix is first scaled to
2422 ///*-* have all ones on the diagonal (equivalent to change of units)
2423 ///*-* but no pivoting is done since matrix is positive-definite.
2424 ///*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
2426 // taken from TMinuit package of Root (l>=n)
2427 // fVERTs, fVERTq and fVERTpp changed to localVERTs, localVERTq and localVERTpp
2428 // Double_t localVERTs[n], localVERTq[n], localVERTpp[n];
2429 Double_t * localVERTs = new Double_t[n];
2430 Double_t * localVERTq = new Double_t[n];
2431 Double_t * localVERTpp = new Double_t[n];
2432 // fMaxint changed to localMaxint
2433 Int_t localMaxint = n;
2435 /* System generated locals */
2438 /* Local variables */
2440 Int_t i, j, k, kp1, km1;
2442 /* Parameter adjustments */
2448 if (n < 1) goto L100;
2449 if (n > localMaxint) goto L100;
2450 //*-*- scale matrix by sqrt of diag elements
2451 for (i = 1; i <= n; ++i) {
2453 if (si <= 0) goto L100;
2454 localVERTs[i-1] = 1 / TMath::Sqrt(si);
2456 for (i = 1; i <= n; ++i) {
2457 for (j = 1; j <= n; ++j) {
2458 a[i + j*l] = a[i + j*l]*localVERTs[i-1]*localVERTs[j-1];
2461 //*-*- . . . start main loop . . . .
2462 for (i = 1; i <= n; ++i) {
2464 //*-*- preparation for elimination step1
2465 if (a[k + k*l] != 0) localVERTq[k-1] = 1 / a[k + k*l];
2467 localVERTpp[k-1] = 1;
2471 if (km1 < 0) goto L100;
2472 else if (km1 == 0) goto L50;
2475 for (j = 1; j <= km1; ++j) {
2476 localVERTpp[j-1] = a[j + k*l];
2477 localVERTq[j-1] = a[j + k*l]*localVERTq[k-1];
2481 if (k - n < 0) goto L51;
2482 else if (k - n == 0) goto L60;
2485 for (j = kp1; j <= n; ++j) {
2486 localVERTpp[j-1] = a[k + j*l];
2487 localVERTq[j-1] = -a[k + j*l]*localVERTq[k-1];
2490 //*-*- elimination proper
2492 for (j = 1; j <= n; ++j) {
2493 for (k = j; k <= n; ++k) { a[j + k*l] += localVERTpp[j-1]*localVERTq[k-1]; }
2496 //*-*- elements of left diagonal and unscaling
2497 for (j = 1; j <= n; ++j) {
2498 for (k = 1; k <= j; ++k) {
2499 a[k + j*l] = a[k + j*l]*localVERTs[k-1]*localVERTs[j-1];
2500 a[j + k*l] = a[k + j*l];
2503 delete [] localVERTs;
2504 delete [] localVERTq;
2505 delete [] localVERTpp;
2507 //*-*- failure return
2509 delete [] localVERTs;
2510 delete [] localVERTq;
2511 delete [] localVERTpp;