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 "AliMUONTrackK.h"
27 #include "AliMUONConstants.h"
29 #include "AliMUONTrackReconstructorK.h"
30 #include "AliMUONHitForRec.h"
31 #include "AliMUONObjectPair.h"
32 #include "AliMUONRawCluster.h"
33 #include "AliMUONTrackParam.h"
34 #include "AliMUONTrackExtrap.h"
35 #include "AliMUONEventRecoCombi.h"
36 #include "AliMUONDetElement.h"
41 #include <Riostream.h>
42 #include <TClonesArray.h>
46 ClassImp(AliMUONTrackK) // Class implementation in ROOT context
49 const Int_t AliMUONTrackK::fgkSize = 5;
50 const Int_t AliMUONTrackK::fgkNSigma = 12;
51 const Double_t AliMUONTrackK::fgkChi2max = 100;
52 const Int_t AliMUONTrackK::fgkTriesMax = 10000;
53 const Double_t AliMUONTrackK::fgkEpsilon = 0.002;
55 void mnvertLocal(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail);
57 Int_t AliMUONTrackK::fgDebug = -1; //-1;
58 Int_t AliMUONTrackK::fgNOfPoints = 0;
59 AliMUONTrackReconstructorK* AliMUONTrackK::fgTrackReconstructor = NULL;
60 TClonesArray* AliMUONTrackK::fgHitForRec = NULL;
61 AliMUONEventRecoCombi *AliMUONTrackK::fgCombi = NULL;
63 //__________________________________________________________________________
64 AliMUONTrackK::AliMUONTrackK()
91 /// Default constructor
93 fgTrackReconstructor = NULL; // pointer to event reconstructor
94 fgHitForRec = NULL; // pointer to points
95 fgNOfPoints = 0; // number of points
100 //__________________________________________________________________________
101 AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructorK *TrackReconstructor, TClonesArray *hitForRec)
130 if (!TrackReconstructor) return;
131 fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
132 fgHitForRec = hitForRec; // pointer to points
133 fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
135 if (fgTrackReconstructor->GetTrackMethod() == 3) fgCombi = AliMUONEventRecoCombi::Instance();
138 //__________________________________________________________________________
139 AliMUONTrackK::AliMUONTrackK(AliMUONObjectPair *segment)
140 : AliMUONTrack(NULL,NULL),
141 fStartSegment(new AliMUONObjectPair(*segment)),
145 fTrackHits(new TObjArray(13)),
151 fTrackPar(new TMatrixD(fgkSize,1)),
152 fTrackParNew(new TMatrixD(fgkSize,1)),
153 fCovariance(new TMatrixD(fgkSize,fgkSize)),
154 fWeight(new TMatrixD(fgkSize,fgkSize)),
155 fParExtrap(new TObjArray(15)),
156 fParFilter(new TObjArray(15)),
158 fCovExtrap(new TObjArray(15)),
159 fCovFilter(new TObjArray(15)),
160 fJacob(new TObjArray(15)),
162 fSteps(new TArrayD(15)),
163 fChi2Array(new TArrayD(13)),
166 /// Constructor from a segment
167 Double_t dX, dY, dZ, bendingSlope, bendingImpact;
168 AliMUONHitForRec *hit1, *hit2;
169 AliMUONRawCluster *clus;
170 TClonesArray *rawclusters;
172 // Pointers to hits from the segment
173 hit1 = (AliMUONHitForRec*) segment->First();
174 hit2 = (AliMUONHitForRec*) segment->Second();
175 hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
176 hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
177 // check sorting in Z
178 if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
180 hit2 = (AliMUONHitForRec*) segment->First();
183 // Fill array of track parameters
184 if (hit1->GetChamberNumber() > 7) {
185 // last tracking station
186 (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
187 (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
188 fPosition = hit1->GetZ(); // z
189 fTrackHits->Add(hit2); // add hit 2
190 fTrackHits->Add(hit1); // add hit 1
191 //AZ(Z->-Z) fTrackDir = -1;
194 // last but one tracking station
195 (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
196 (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
197 fPosition = hit2->GetZ(); // z
198 fTrackHits->Add(hit1); // add hit 1
199 fTrackHits->Add(hit2); // add hit 2
200 //AZ(Z->-Z) fTrackDir = 1;
203 dZ = hit2->GetZ() - hit1->GetZ();
204 dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
205 dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
206 bendingSlope = (hit2->GetBendingCoor() - hit1->GetBendingCoor()) / dZ;
207 bendingImpact = hit1->GetBendingCoor() - hit1->GetZ() * bendingSlope;
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./AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact); // 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 << " "
219 << AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact)
220 << " " << 1/(*fTrackPar)(4,0) << " ";
222 for (Int_t i=0; i<2; i++) {
223 hit1 = (AliMUONHitForRec*) ((*fTrackHits)[i]);
224 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
225 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
226 cout << clus->GetTrack(1);
227 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
228 if (i == 0) cout << " <--> ";
230 cout << " @ " << hit1->GetChamberNumber() << endl;
234 //__________________________________________________________________________
235 AliMUONTrackK::~AliMUONTrackK()
240 delete fStartSegment;
245 //cout << fNmbTrackHits << endl;
246 for (Int_t i = 0; i < fNmbTrackHits; i++) {
247 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
248 hit->SetNTrackHits(hit->GetNTrackHits()-1);
250 delete fTrackHits; // delete the TObjArray of pointers to TrackHit's
254 delete fTrackPar; delete fTrackParNew; delete fCovariance;
258 if (fSteps) delete fSteps;
259 if (fChi2Array) delete fChi2Array;
260 if (fChi2Smooth) delete fChi2Smooth;
261 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
262 // Delete only matrices not shared by several tracks
263 if (!fParExtrap) return;
266 for (Int_t i=0; i<fNSteps; i++) {
267 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
268 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
269 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
271 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
272 fParExtrap->RemoveAt(i);
274 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
275 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
276 id = fParFilter->UncheckedAt(i)->GetUniqueID();
278 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
279 fParFilter->RemoveAt(i);
281 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
282 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
283 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
285 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
286 fCovExtrap->RemoveAt(i);
289 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
290 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
291 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
293 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
294 fCovFilter->RemoveAt(i);
296 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
297 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
298 id = fJacob->UncheckedAt(i)->GetUniqueID();
300 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
305 for (Int_t i=0; i<fNSteps; i++) {
306 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
307 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
308 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
309 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
310 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
311 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
314 fParExtrap->Delete(); fParFilter->Delete();
315 fCovExtrap->Delete(); fCovFilter->Delete();
317 delete fParExtrap; delete fParFilter;
318 delete fCovExtrap; delete fCovFilter;
322 //__________________________________________________________________________
323 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
325 /// Assignment operator
328 if(&source == this) return *this;
330 // base class assignement
331 //AZ TObject::operator=(source);
332 AliMUONTrack::operator=(source);
334 if (fStartSegment) delete fStartSegment;
335 if (source.fStartSegment) fStartSegment = new AliMUONObjectPair(*(source.fStartSegment));
336 else fStartSegment = 0x0;
338 fNmbTrackHits = source.fNmbTrackHits;
339 fChi2 = source.fChi2;
340 fPosition = source.fPosition;
341 fPositionNew = source.fPositionNew;
342 fTrackDir = source.fTrackDir;
343 fBPFlag = source.fBPFlag;
344 fRecover = source.fRecover;
345 fSkipHit = source.fSkipHit;
348 fTrackHits = new TObjArray(*source.fTrackHits);
349 //source.fTrackHits->Dump();
350 //fTrackHits->Dump();
351 for (Int_t i = 0; i < fNmbTrackHits; i++) {
352 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
353 hit->SetNTrackHits(hit->GetNTrackHits()+1);
356 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
357 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
358 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
359 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
362 fParExtrap = new TObjArray(*source.fParExtrap);
363 fParFilter = new TObjArray(*source.fParFilter);
364 fCovExtrap = new TObjArray(*source.fCovExtrap);
365 fCovFilter = new TObjArray(*source.fCovFilter);
366 fJacob = new TObjArray(*source.fJacob);
367 fSteps = new TArrayD(*source.fSteps);
368 fNSteps = source.fNSteps;
370 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
374 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
375 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
376 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
377 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
378 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
379 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
384 //__________________________________________________________________________
385 void AliMUONTrackK::EvalCovariance(Double_t dZ)
387 /// Evaluate covariance (and weight) matrix for track candidate
388 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
391 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
392 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
394 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
396 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
398 tanA = TMath::Tan((*fTrackPar)(2,0));
399 dAdY = 1/(1+tanA*tanA)/dZ;
400 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
401 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
402 (*fWeight)(2,0) = (*fWeight)(0,2);
404 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
405 tanB = TMath::Tan((*fTrackPar)(3,0));
406 dBdX = 1/(1+tanB*tanB)/rad;
408 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
409 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
410 (*fWeight)(3,1) = (*fWeight)(1,3);
412 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
414 // check whether the Invert method returns flag if matrix cannot be inverted,
415 // and do not calculate the Determinant in that case !!!!
416 if (fWeight->Determinant() != 0) {
417 // fWeight->Invert();
419 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
421 AliWarning(" Determinant fWeight=0:");
426 //__________________________________________________________________________
427 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
429 /// Follows track through detector stations
430 Bool_t miss, success;
431 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
432 Int_t ihit, firstIndx = -1, lastIndx = -1, currIndx = -1, iz0 = -1, iz = -1;
433 Double_t zEnd, dChi2;
434 AliMUONHitForRec *hitAdd, *firstHit = NULL, *lastHit = NULL, *hit;
435 AliMUONRawCluster *clus;
436 TClonesArray *rawclusters;
437 hit = 0; clus = 0; rawclusters = 0;
439 miss = success = kTRUE;
441 //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
442 iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
443 iMin = TMath::Min(ichamEnd,ichamBeg);
444 iMax = TMath::Max(ichamEnd,ichamBeg);
451 if (((AliMUONHitForRec*)fTrackHits->First())->GetChamberNumber() != ichamb) currIndx = 0;
452 } else if (fRecover) {
453 hit = GetHitLastOk();
454 currIndx = fTrackHits->IndexOf(hit);
455 if (currIndx < 0) hit = (AliMUONHitForRec*) fStartSegment->First(); // for station 3
457 ichamb = hit->GetChamberNumber();
458 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
459 // start from the last point or outlier
460 // remove the skipped hit
461 fTrackHits->Remove(fSkipHit); // remove hit
463 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
468 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
469 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetChamberNumber() == 6) ichambOK = 6;
470 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
471 fSkipHit->GetHitNumber() < 0) {
472 iz0 = fgCombi->IZfromHit(fSkipHit);
475 else currIndx = fgHitForRec->IndexOf(fSkipHit);
478 fTrackHits->Compress();
480 } // if (hit == fSkipHit)
481 else if (currIndx < 0) currIndx = fTrackHits->IndexOf(hit);
482 } // else if (fRecover)
484 // Get indices of the 1'st and last hits on the track candidate
485 firstHit = (AliMUONHitForRec*) fTrackHits->First();
486 lastHit = (AliMUONHitForRec*) fTrackHits->Last();
487 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
488 lastHit->GetHitNumber() < 0) iz0 = fgCombi->IZfromHit(lastHit);
490 firstIndx = fgHitForRec->IndexOf(firstHit);
491 lastIndx = fgHitForRec->IndexOf(lastHit);
492 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
496 if (iz0 < 0) iz0 = iFB;
497 while (ichamb >= iMin && ichamb <= iMax) {
498 // Find the closest hit in Z, not belonging to the current plane
501 if (currIndx < fNmbTrackHits) {
502 hitAdd = (AliMUONHitForRec*) fTrackHits->UncheckedAt(currIndx);
503 zEnd = hitAdd->GetZ();
504 //AZ(z->-z) } else zEnd = -9999;
507 //AZ(Z->-Z) zEnd = -9999;
509 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
510 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
511 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
512 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
513 zEnd = hitAdd->GetZ();
519 // Combined cluster / track finder
520 if (zEnd > 999 && iFB < 0 && fgTrackReconstructor->GetTrackMethod() == 3) {
522 AliMUONHitForRec hitTmp;
523 for (iz = iz0 - iFB; iz < fgCombi->Nz(); iz++) {
524 if (TMath::Abs(fgCombi->Z(iz)-fPosition) < 0.5) continue;
525 Int_t *pDEatZ = fgCombi->DEatZ(iz);
526 //cout << iz << " " << fgCombi->Z(iz) << endl;
527 zEnd = fgCombi->Z(iz);
529 AliMUONDetElement *detElem = fgCombi->DetElem(pDEatZ[0]);
531 hitAdd->SetChamberNumber(detElem->Chamber());
532 //hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
537 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
539 // Check if there is a chamber without hits
540 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
541 if (!Back && zEnd<999) currIndx -= iFB;
543 zEnd = AliMUONConstants::DefaultChamberZ(ichamb);
546 ichamb = hitAdd->GetChamberNumber();
550 if (ichamb<iMin || ichamb>iMax) break;
551 // Check for missing station
553 dChamb = TMath::Abs(ichamb-ichambOK);
554 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
555 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
556 if (zEnd > 999) dStatMiss++;
558 //if (dStatMiss == 2 && ichambOK/2 != 3 || dStatMiss > 2) { // AZ - missing st. 3
559 // missing station - abandon track
560 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
562 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
563 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
564 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
565 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
566 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
567 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
570 cout << fNmbTrackHits << endl;
571 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
572 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
573 printf(" * %d %10.4f %10.4f %10.4f",
574 hit->GetChamberNumber(), hit->GetBendingCoor(),
575 hit->GetNonBendingCoor(), hit->GetZ());
577 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
578 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
579 printf("%3d", clus->GetTrack(1)-1);
580 if (clus->GetTrack(2) != 0)
581 printf("%3d \n", clus->GetTrack(2)-1);
586 } // if (fgDebug >= 10)
587 if (fNmbTrackHits>2 && fRecover==0) Recover(); // try to recover track later
589 } // if (dStatMiss > 1)
591 if (endOfProp != 0) break;
593 // propagate to the found Z
595 // Check if track steps into dipole
596 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
597 if (fPosition<zDipole2 && zEnd>zDipole2) {
598 //LinearPropagation(zDipole2-zBeg);
599 ParPropagation(zDipole2);
600 MSThin(1); // multiple scattering in the chamber
601 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
602 fPosition = fPositionNew;
603 *fTrackPar = *fTrackParNew;
604 //MagnetPropagation(zEnd);
605 ParPropagation(zEnd);
606 WeightPropagation(zEnd, kTRUE);
607 fPosition = fPositionNew;
609 // Check if track steps out of dipole
610 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
611 else if (fPosition<zDipole1 && zEnd>zDipole1) {
612 //MagnetPropagation(zDipole1-zBeg);
613 ParPropagation(zDipole1);
614 MSThin(1); // multiple scattering in the chamber
615 WeightPropagation(zDipole1, kTRUE);
616 fPosition = fPositionNew;
617 *fTrackPar = *fTrackParNew;
618 //LinearPropagation(zEnd-zDipole1);
619 ParPropagation(zEnd);
620 WeightPropagation(zEnd, kTRUE);
621 fPosition = fPositionNew;
623 ParPropagation(zEnd);
624 //MSThin(1); // multiple scattering in the chamber
625 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
626 WeightPropagation(zEnd, kTRUE);
627 fPosition = fPositionNew;
631 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
632 // recovered track - remove the hit
634 ichamb = fSkipHit->GetChamberNumber();
635 // remove the skipped hit
636 fTrackHits->Remove(fSkipHit);
638 //AZ fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
641 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
642 //? if (fgTrackReconstructor->GetTrackMethod() != 3) currIndx = fgHitForRec->IndexOf(fSkipHit);
643 currIndx = fgHitForRec->IndexOf(fSkipHit);
647 // backward propagator
649 TMatrixD pointWeight(fgkSize,fgkSize);
650 TMatrixD point(fgkSize,1);
651 TMatrixD trackParTmp = point;
652 point(0,0) = hitAdd->GetBendingCoor();
653 point(1,0) = hitAdd->GetNonBendingCoor();
654 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
655 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
656 TryPoint(point,pointWeight,trackParTmp,dChi2);
657 *fTrackPar = trackParTmp;
658 *fWeight += pointWeight;
659 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
660 fChi2 += dChi2; // Chi2
661 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
662 if (ichamb==ichamEnd) break;
665 // forward propagator
666 if (miss || !FindPoint(ichamb, zEnd, currIndx, iFB, hitAdd, iz)) {
668 *fTrackPar = *fTrackParNew;
671 fTrackHits->Add(hitAdd); // add hit
673 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
675 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
679 if (fgDebug > 0) cout << fNmbTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
680 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
681 if (GetRecover() < 0) success = kFALSE;
685 //__________________________________________________________________________
686 void AliMUONTrackK::ParPropagation(Double_t zEnd)
688 /// Propagation of track parameters to zEnd
690 Double_t dZ, step, distance, charge;
691 Double_t vGeant3[7], vGeant3New[7];
692 AliMUONTrackParam trackParam;
695 // First step using linear extrapolation
696 dZ = zEnd - fPosition;
697 fPositionNew = fPosition;
698 *fTrackParNew = *fTrackPar;
699 if (dZ == 0) return; //AZ ???
700 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
701 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
702 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
703 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
704 SetGeantParam(vGeant3,iFB);
705 //fTrackParNew->Print();
709 step = TMath::Abs(step);
710 // Propagate parameters
711 AliMUONTrackExtrap::ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
712 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
713 distance = zEnd - vGeant3New[2];
714 step *= dZ/(vGeant3New[2]-fPositionNew);
716 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
718 GetFromGeantParam(vGeant3New,iFB);
719 //fTrackParNew->Print();
721 // Position adjustment (until within tolerance)
722 while (TMath::Abs(distance) > fgkEpsilon) {
723 dZ = zEnd - fPositionNew;
724 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
725 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
726 step = TMath::Abs(step);
727 SetGeantParam(vGeant3,iFB);
730 // Propagate parameters
731 AliMUONTrackExtrap::ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
732 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
733 distance = zEnd - vGeant3New[2];
736 if (nTries > fgkTriesMax) AliError(Form(" Too many tries: %d", nTries));
737 } while (distance*iFB < 0);
739 GetFromGeantParam(vGeant3New,iFB);
741 //cout << nTries << endl;
742 //fTrackParNew->Print();
746 //__________________________________________________________________________
747 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
749 /// Propagation of the weight matrix
750 /// W = DtWD, where D is Jacobian
754 TMatrixD jacob(fgkSize,fgkSize);
757 // Save initial and propagated parameters
758 TMatrixD trackPar0 = *fTrackPar;
759 TMatrixD trackParNew0 = *fTrackParNew;
761 // Get covariance matrix
762 *fCovariance = *fWeight;
763 // check whether the Invert method returns flag if matrix cannot be inverted,
764 // and do not calculate the Determinant in that case !!!!
765 if (fCovariance->Determinant() != 0) {
767 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
768 //fCovariance->Print();
770 AliWarning(" Determinant fCovariance=0:");
773 // Loop over parameters to find change of the propagated vs initial ones
774 for (i=0; i<fgkSize; i++) {
775 dPar = TMath::Sqrt((*fCovariance)(i,i));
776 *fTrackPar = trackPar0;
777 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
778 (*fTrackPar)(i,0) += dPar;
779 ParPropagation(zEnd);
780 for (j=0; j<fgkSize; j++) {
781 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
785 //trackParNew0.Print();
786 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
788 TMatrixD jacob0 = jacob;
789 if (jacob.Determinant() != 0) {
792 AliWarning(" Determinant jacob=0:");
794 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
795 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
797 // Restore initial and propagated parameters
798 *fTrackPar = trackPar0;
799 *fTrackParNew = trackParNew0;
802 if (!smooth) return; // do not use smoother
803 if (fTrackDir < 0) return; // only for propagation towards int. point
804 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
805 fParExtrap->Add(tmp);
807 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
808 fParFilter->Add(tmp);
810 *fCovariance = *fWeight;
811 if (fCovariance->Determinant() != 0) {
813 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
815 AliWarning(" Determinant fCovariance=0:");
817 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
818 fCovExtrap->Add(tmp);
820 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
821 fCovFilter->Add(tmp);
823 tmp = new TMatrixD(jacob0); // Jacobian
826 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
827 fSteps->AddAt(fPositionNew,fNSteps++);
828 if (fgDebug > 0) printf(" WeightPropagation %d %.3f %.3f %.3f \n", fNSteps,
829 (*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPositionNew);
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;
845 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
846 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
847 *fCovariance = *fWeight;
848 // check whether the Invert method returns flag if matrix cannot be inverted,
849 // and do not calculate the Determinant in that case !!!!
850 if (fCovariance->Determinant() != 0) {
852 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
854 AliWarning(" Determinant fCovariance=0:");
856 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
857 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
860 if (fgTrackReconstructor->GetTrackMethod() == 3 && iz >= 0) {
861 // Combined cluster / track finder
862 // Check if extrapolated track passes thru det. elems. at iz
863 Int_t *pDEatZ = fgCombi->DEatZ(iz);
864 Int_t nDetElem = pDEatZ[-1];
865 //cout << fgCombi->Z(iz) << " " << nDetElem << endl;
866 windowB = fgkNSigma * TMath::Sqrt((*fCovariance)(0,0));
867 windowNonB = fgkNSigma * TMath::Sqrt((*fCovariance)(1,1));
868 if (fgkNSigma > 6) windowB = TMath::Min (windowB, 5.);
869 windowB = TMath::Max (windowB, 2.);
870 windowNonB = TMath::Max (windowNonB, 2.);
871 for (Int_t i = 0; i < nDetElem; i++) {
872 detElem = fgCombi->DetElem(pDEatZ[i]);
873 if (detElem->Inside((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPosition, windowNonB, windowB)) {
874 detElem->ClusterReco((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), windowNonB, windowB);
875 hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
880 if (!ok) return ok; // outside det. elem.
884 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
885 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
886 *fCovariance = *fWeight;
887 // check whether the Invert method returns flag if matrix cannot be inverted,
888 // and do not calculate the Determinant in that case !!!!
889 if (fCovariance->Determinant() != 0) {
891 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
893 AliWarning(" Determinant fCovariance=0:");
895 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
896 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
897 // Loop over all hits and take hits from the chamber
898 TMatrixD pointWeight(fgkSize,fgkSize);
899 TMatrixD saveWeight = pointWeight;
900 TMatrixD pointWeightTmp = pointWeight;
901 TMatrixD point(fgkSize,1);
902 TMatrixD trackPar = point;
903 TMatrixD trackParTmp = point;
904 Int_t nHitsOK = 0, ihitB = currIndx, ihitE = fgNOfPoints, iDhit = iFB;
906 zLast = ((AliMUONHitForRec*)fTrackHits->Last())->GetZ();
907 if (fgTrackReconstructor->GetTrackMethod() == 3 && detElem) {
909 ihitE = detElem->NHitsForRec();
913 TArrayD branchChi2(20);
914 for (ihit = ihitB; ihit >= 0 && ihit < ihitE; ihit+=iDhit) {
915 if (fgTrackReconstructor->GetTrackMethod() != 3 || !detElem)
916 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
917 else hit = (AliMUONHitForRec*) detElem->HitsForRec()->UncheckedAt(ihit);
918 if (hit->GetChamberNumber() == ichamb) {
919 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
920 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
921 y = hit->GetBendingCoor();
922 x = hit->GetNonBendingCoor();
923 if (hit->GetBendingReso2() < 0) {
924 // Combined cluster / track finder
925 hit->SetBendingReso2(fgTrackReconstructor->GetBendingResolution()*
926 fgTrackReconstructor->GetBendingResolution());
927 hit->SetNonBendingReso2(fgTrackReconstructor->GetNonBendingResolution()*
928 fgTrackReconstructor->GetNonBendingResolution());
930 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
931 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
933 // windowB = TMath::Min (windowB,5.);
934 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
936 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
937 windowB = TMath::Min (windowB,0.5);
938 windowNonB = TMath::Min (windowNonB,3.);
939 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
940 windowB = TMath::Min (windowB,1.5);
941 windowNonB = TMath::Min (windowNonB,3.);
942 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
943 windowB = TMath::Min (windowB,4.);
944 windowNonB = TMath::Min (windowNonB,6.);
950 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
951 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
952 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
954 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
955 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
959 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
960 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
961 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
962 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
963 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
964 // hit->GetTrackRefSignal() == 1) { // just for test
965 // Vector of measurements and covariance matrix
966 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
967 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
968 // Adjust position: for multiple hits in the chamber or misalignment (Z as a function of X or Y)
969 //AliWarning(Form(" *** adjust %f %f ", zEnd, hit->GetZ()));
971 *fTrackPar = *fTrackParNew;
972 ParPropagation(zEnd);
973 WeightPropagation(zEnd, kTRUE);
974 fPosition = fPositionNew;
975 *fTrackPar = *fTrackParNew;
977 *fCovariance = *fWeight;
978 if (fCovariance->Determinant() != 0) {
980 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
982 AliWarning(" Determinant fCovariance=0:" );
988 pointWeight(0,0) = 1/hit->GetBendingReso2();
989 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
990 TryPoint(point,pointWeight,trackPar,dChi2);
991 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
992 // if (TMath::Sign(1.,(trackPar)(4,0)*(*fTrackPar)(4,0)) < 0) continue; // change of sign
995 //if (nHitsOK > -1) {
997 // Save current members
998 saveWeight = *fWeight;
999 savePosition = fPosition;
1000 // temporary storage for the current track
1002 trackParTmp = trackPar;
1003 pointWeightTmp = pointWeight;
1005 if (fgDebug > 0) printf(" Added point (ch, x, y, Chi2): %d %.3f %.3f %.3f\n", ichamb, x, y, dChi2);
1006 branchChi2[0] = dChi2;
1008 // branching: create a new track
1009 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1010 nRecTracks = fgTrackReconstructor->GetNRecTracks();
1011 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1013 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1014 if (fgDebug > 0) printf(" ******** New track (ch, hit, x, y, mom, Chi2, nhits, cand): %d %d %.3f %.3f %.3f %.3f %d %d\n", ichamb, hit->GetTTRTrack(), hit->GetNonBendingCoor(), hit->GetBendingCoor(), 1/(trackPar)(4,0), dChi2, fNmbTrackHits, nRecTracks);
1015 trackK->fRecover = 0;
1016 *(trackK->fTrackPar) = trackPar;
1017 *(trackK->fWeight) += pointWeight;
1018 trackK->fChi2 += dChi2;
1021 *(trackK->fCovariance) = *(trackK->fWeight);
1022 if (trackK->fCovariance->Determinant() != 0) {
1024 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1026 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
1028 // Add filtered matrices for the smoother
1029 if (fTrackDir > 0) {
1030 if (nHitsOK > 2) { // check for position adjustment
1031 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
1032 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
1033 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
1034 RemoveMatrices(trackK);
1035 AliError(Form(" *** Position adjustment 1: %f %f", hit->GetZ(), (*trackK->fSteps)[i]));
1040 AddMatrices (trackK, dChi2, hit);
1042 // Mark hits as being on 2 tracks
1043 for (Int_t i=0; i<fNmbTrackHits; i++) {
1044 hitLoop = (AliMUONHitForRec*) ((*fTrackHits)[i]);
1045 //AZ hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
1048 cout << hitLoop->GetChamberNumber() << " ";
1049 cout << hitLoop->GetBendingCoor() << " ";
1050 cout << hitLoop->GetNonBendingCoor() << " ";
1051 cout << hitLoop->GetZ() << " " << " ";
1052 cout << hitLoop->GetTTRTrack() << endl;
1053 printf(" ** %d %10.4f %10.4f %10.4f\n",
1054 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
1055 hitLoop->GetNonBendingCoor(), hitLoop->GetZ());
1059 trackK->fTrackHits->Add(hit); // add hit
1060 trackK->fNmbTrackHits ++;
1061 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
1064 trackK->fTrackDir = 1;
1065 trackK->fBPFlag = kTRUE;
1067 if (nHitsOK > branchChi2.GetSize()) branchChi2.Set(branchChi2.GetSize()+10);
1068 branchChi2[nHitsOK-1] = dChi2;
1072 } else break; // different chamber
1073 } // for (ihit=currIndx;
1076 *fTrackPar = trackParTmp;
1077 *fWeight = saveWeight;
1078 *fWeight += pointWeightTmp;
1079 fChi2 += dChi2Tmp; // Chi2
1080 fPosition = savePosition;
1081 // Add filtered matrices for the smoother
1082 if (fTrackDir > 0) {
1083 for (Int_t i=fNSteps-1; i>=0; i--) {
1084 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
1085 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
1086 RemoveMatrices(this);
1087 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
1090 } // for (Int_t i=fNSteps-1;
1091 AddMatrices (this, dChi2Tmp, hitAdd);
1094 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1095 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1098 } // if (fTrackDir > 0)
1099 // Check for maximum number of branches - exclude excessive
1100 if (nHitsOK > 1) CheckBranches(branchChi2, nHitsOK);
1105 //__________________________________________________________________________
1106 void AliMUONTrackK::CheckBranches(TArrayD &branchChi2, Int_t nBranch)
1108 /// Check for maximum number of branches - exclude excessive
1110 Int_t nBranchMax = 5;
1111 if (nBranch <= nBranchMax) return;
1113 Double_t *chi2 = branchChi2.GetArray();
1114 Int_t *indx = new Int_t [nBranch];
1115 TMath::Sort (nBranch, chi2, indx, kFALSE);
1116 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1117 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
1118 Int_t ibeg = nRecTracks - nBranch;
1120 // Discard excessive branches with higher Chi2 contribution
1121 for (Int_t i = nBranchMax; i < nBranch; ++i) {
1123 // Discard current track
1127 Int_t j = ibeg + indx[i];
1128 AliMUONTrackK *trackK = (AliMUONTrackK*) trackPtr->UncheckedAt(j);
1129 trackK->SetRecover(-1);
1134 //__________________________________________________________________________
1135 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1137 /// Adds a measurement point (modifies track parameters and computes
1140 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1141 TMatrixD wu = *fWeight;
1142 wu += pointWeight; // W+U
1143 trackParTmp = point;
1144 trackParTmp -= *fTrackParNew; // m-p
1145 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1146 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1147 right += right1; // U(m-p) + (W+U)p
1149 // check whether the Invert method returns flag if matrix cannot be inverted,
1150 // and do not calculate the Determinant in that case !!!!
1151 if (wu.Determinant() != 0) {
1153 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1155 AliWarning(" Determinant wu=0:");
1157 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1159 right1 = trackParTmp;
1160 right1 -= point; // p'-m
1161 point = trackParTmp;
1162 point -= *fTrackParNew; // p'-p
1163 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1164 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1166 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1167 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1168 dChi2 += value(0,0);
1172 //__________________________________________________________________________
1173 void AliMUONTrackK::MSThin(Int_t sign)
1175 /// Adds multiple scattering in a thin layer (only angles are affected)
1176 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1178 // check whether the Invert method returns flag if matrix cannot be inverted,
1179 // and do not calculate the Determinant in that case !!!!
1180 if (fWeight->Determinant() != 0) {
1182 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1184 AliWarning(" Determinant fWeight=0:");
1187 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1188 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1189 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1190 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1191 velo = 1; // relativistic
1192 path = TMath::Abs(AliMUONConstants::ChamberThicknessInX0()/cosAlph/cosBeta); // path length
1193 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1195 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1196 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1198 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1202 //__________________________________________________________________________
1203 void AliMUONTrackK::StartBack(void)
1205 /// Starts backpropagator
1209 for (Int_t i=0; i<fgkSize; i++) {
1210 for (Int_t j=0; j<fgkSize; j++) {
1211 if (j==i) (*fWeight)(i,i) /= 100;
1212 //if (j==i) (*fWeight)(i,i) /= fNmbTrackHits*fNmbTrackHits;
1213 else (*fWeight)(j,i) = 0;
1216 // Sort hits on track in descending order in abs(z)
1217 SortHits(0, fTrackHits);
1220 //__________________________________________________________________________
1221 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1223 /// Sort hits in Z if the seed segment is in the last but one station
1224 /// (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1226 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1227 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1228 Int_t i = 1, entries = array->GetEntriesFast();
1229 for ( ; i<entries; i++) {
1231 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1233 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1234 if (z < zmax) break;
1236 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1240 for (Int_t j=0; j<=(i-1)/2; j++) {
1241 TObject *hit = array->UncheckedAt(j);
1242 array->AddAt(array->UncheckedAt(i-j),j);
1243 array->AddAt(hit,i-j);
1245 if (fgDebug >= 10) {
1246 for (i=0; i<entries; i++)
1247 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1248 cout << " - Sort" << endl;
1252 //__________________________________________________________________________
1253 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1255 /// Set vector of Geant3 parameters pointed to by "VGeant3"
1256 /// from track parameters
1258 VGeant3[0] = (*fTrackParNew)(1,0); // X
1259 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1260 VGeant3[2] = fPositionNew; // Z
1261 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1262 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1263 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1264 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1267 //__________________________________________________________________________
1268 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1270 /// Get track parameters from vector of Geant3 parameters pointed
1273 fPositionNew = VGeant3[2]; // Z
1274 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1275 (*fTrackParNew)(1,0) = VGeant3[0]; // X
1276 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1277 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1278 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1281 //__________________________________________________________________________
1282 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1284 /// Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1287 AliWarning(Form(" *** Too high Chi2: %f ", fChi2));
1290 if (iChi2 == 0) fChi2 = fNmbTrackHits + (500.-fChi2)/501;
1291 else fChi2 = 500 - (fChi2-fNmbTrackHits)*501;
1294 //__________________________________________________________________________
1295 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1297 /// "Compare" function to sort with decreasing "track quality".
1298 /// Returns +1 (0, -1) if quality of current track
1299 /// is smaller than (equal to, larger than) quality of trackK
1301 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1302 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1306 //__________________________________________________________________________
1307 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1309 /// Check whether or not to keep current track
1310 /// (keep, if it has less than half of common hits with track0)
1311 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1312 AliMUONHitForRec *hit0, *hit1;
1315 nHits0 = track0->fNmbTrackHits;
1316 nTrackHits2 = fNmbTrackHits/2;
1318 for (i=0; i<nHits0; i++) {
1319 // Check if hit belongs to several tracks
1320 hit0 = (AliMUONHitForRec*) (*track0->fTrackHits)[i];
1321 if (hit0->GetNTrackHits() == 1) continue;
1322 for (j=0; j<fNmbTrackHits; j++) {
1323 hit1 = (AliMUONHitForRec*) (*fTrackHits)[j];
1324 if (hit1->GetNTrackHits() == 1) continue;
1327 if (hitsInCommon >= nTrackHits2) return kFALSE;
1335 //__________________________________________________________________________
1336 void AliMUONTrackK::Kill(void)
1338 /// Kill track candidate
1339 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1342 //__________________________________________________________________________
1343 void AliMUONTrackK::FillMUONTrack(void)
1345 /// Compute track parameters at hit positions (as for AliMUONTrack)
1350 // Set track parameters at vertex
1351 AliMUONTrackParam trackParam;
1352 SetTrackParam(&trackParam, fTrackPar, fPosition);
1353 SetTrackParamAtVertex(&trackParam);
1355 // Set track parameters at hits
1356 for (Int_t i = fNmbTrackHits-1; i>=0; i--) {
1357 if ((*fChi2Smooth)[i] < 0) {
1358 // Propagate through last chambers
1359 AliMUONTrackExtrap::ExtrapToZ(&trackParam, ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1362 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1364 AddTrackParamAtHit(&trackParam,(AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1365 // Fill array of HitForRec's
1366 AddHitForRecAtHit((AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1370 //__________________________________________________________________________
1371 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1373 /// Fill AliMUONTrackParam object
1375 trackParam->SetBendingCoor((*par)(0,0));
1376 trackParam->SetNonBendingCoor((*par)(1,0));
1377 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1378 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1379 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1380 trackParam->SetZ(z);
1383 //__________________________________________________________________________
1384 void AliMUONTrackK::Branson(void)
1386 /// Propagates track to the vertex thru absorber using Branson correction
1387 /// (makes use of the AliMUONTrackParam class)
1389 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1390 AliMUONTrackParam trackParam = AliMUONTrackParam();
1392 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1393 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1394 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1395 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1396 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1397 trackParam->SetZ(fPosition);
1399 SetTrackParam(&trackParam, fTrackPar, fPosition);
1401 AliMUONTrackExtrap::ExtrapToVertex(&trackParam, Double_t(0.), Double_t(0.), Double_t(0.));
1403 (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1404 (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1405 (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1406 (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1407 (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1408 fPosition = trackParam.GetZ();
1409 //delete trackParam;
1410 if (fgDebug > 0) cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1412 // Get covariance matrix
1413 *fCovariance = *fWeight;
1414 if (fCovariance->Determinant() != 0) {
1416 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1418 AliWarning(" Determinant fCovariance=0:");
1422 //__________________________________________________________________________
1423 void AliMUONTrackK::GoToZ(Double_t zEnd)
1425 /// Propagates track to given Z
1427 ParPropagation(zEnd);
1428 MSThin(1); // multiple scattering in the chamber
1429 WeightPropagation(zEnd, kFALSE);
1430 fPosition = fPositionNew;
1431 *fTrackPar = *fTrackParNew;
1434 //__________________________________________________________________________
1435 void AliMUONTrackK::GoToVertex(Int_t iflag)
1438 /// Propagates track to the vertex
1439 /// All material constants are taken from AliRoot
1441 static Double_t x01[5] = { 24.282, // C
1446 // inner part theta < 3 degrees
1447 static Double_t x02[5] = { 30413, // Air
1452 // z positions of the materials inside the absober outer part theta > 3 degres
1453 static Double_t zPos[10] = {-90, -105, -315, -443, -468};
1455 Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
1456 AliMUONHitForRec *hit;
1457 AliMUONRawCluster *clus;
1458 TClonesArray *rawclusters;
1460 // First step to the rear end of the absorber
1461 Double_t zRear = -503;
1463 Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1465 // Go through absorber
1466 pOld = 1/(*fTrackPar)(4,0);
1467 Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1468 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1469 r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
1471 Double_t p0, cos25, cos60;
1472 if (!iflag) goto vertex;
1474 for (Int_t i=4; i>=0; i--) {
1475 ParPropagation(zPos[i]);
1476 WeightPropagation(zPos[i], kFALSE);
1477 dZ = TMath::Abs (fPositionNew-fPosition);
1478 if (r0Norm > 1) x0 = x01[i];
1480 MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
1481 fPosition = fPositionNew;
1482 *fTrackPar = *fTrackParNew;
1483 r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1484 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1485 r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
1487 // Correct momentum for energy losses
1488 pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
1490 cos25 = TMath::Cos(2.5/180*TMath::Pi());
1491 cos60 = TMath::Cos(6.0/180*TMath::Pi());
1492 for (Int_t j=0; j<1; j++) {
1496 deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1498 deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1502 deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1504 deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1512 deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1514 deltaP = 3.0643 + 0.01346*p0;
1520 deltaP = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1522 deltaP = 2.407 + 0.00702*p0;
1531 deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1533 deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1540 deltaP = 2.209 + 0.800e-2*p0;
1542 deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1552 deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1554 deltaP = 3.0714 + 0.011767 * p0;
1559 deltaP = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1561 deltaP = 2.6069 + 0.0051705 * p0;
1567 p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
1569 (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1573 ParPropagation((Double_t)0.);
1574 WeightPropagation((Double_t)0., kFALSE);
1575 fPosition = fPositionNew;
1576 //*fTrackPar = *fTrackParNew;
1577 // Add vertex as a hit
1578 TMatrixD pointWeight(fgkSize,fgkSize);
1579 TMatrixD point(fgkSize,1);
1580 TMatrixD trackParTmp = point;
1581 point(0,0) = 0; // vertex coordinate - should be taken somewhere
1582 point(1,0) = 0; // vertex coordinate - should be taken somewhere
1583 pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1584 pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1585 TryPoint(point,pointWeight,trackParTmp,dChi2);
1586 *fTrackPar = trackParTmp;
1587 *fWeight += pointWeight;
1588 fChi2 += dChi2; // Chi2
1589 if (fgDebug < 0) return; // no output
1591 cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNmbTrackHits << endl;
1592 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1593 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1594 printf ("%5d", hit->GetChamberNumber());
1598 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1599 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1600 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1601 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1602 printf ("%5d", fgHitForRec->IndexOf(hit));
1607 // from raw clusters
1608 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1609 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1610 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1611 Int_t index = -hit->GetHitNumber() / 100000;
1612 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1613 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1615 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1616 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1618 printf ("%5d", clus->GetTrack(1)%10000000);
1621 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1622 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1623 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1624 Int_t index = -hit->GetHitNumber() / 100000;
1625 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1626 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1628 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1629 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1631 if (clus->GetTrack(2) != -1) printf ("%5d", clus->GetTrack(2)%10000000);
1632 else printf ("%5s", " ");
1635 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1636 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1637 cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1638 //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHits)[i1]))) << " ";
1641 for (Int_t i1=0; i1<fNmbTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1643 cout << "---------------------------------------------------" << endl;
1645 // Get covariance matrix
1646 /* Not needed - covariance matrix is not interesting to anybody
1647 *fCovariance = *fWeight;
1648 if (fCovariance->Determinant() != 0) {
1650 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1652 AliWarning(" Determinant fCovariance=0:" );
1657 //__________________________________________________________________________
1658 void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
1660 /// Adds multiple scattering in a thick layer for linear propagation
1662 Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1663 Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1664 Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1666 sinBeta = TMath::Sin((*fTrackPar)(3,0));
1667 Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1668 Double_t momentum = 1/(*fTrackPar)(4,0);
1669 Double_t velo = 1; // relativistic velocity
1670 Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
1672 // Projected scattering angle
1673 Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0));
1674 Double_t theta02 = theta0*theta0;
1675 Double_t dl2 = step*step/2*theta02;
1676 Double_t dl3 = dl2*step*2/3;
1679 Double_t dYdT = 1/cosAlph;
1680 Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1681 Double_t dXdT = tanAlph*tanBeta;
1682 //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1683 Double_t dXdB = 1/cosBeta;
1684 Double_t dAdT = 1/cosBeta;
1685 Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1687 // Get covariance matrix
1688 *fCovariance = *fWeight;
1689 if (fCovariance->Determinant() != 0) {
1690 // fCovariance->Invert();
1692 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1694 AliWarning(" Determinant fCovariance=0:" );
1697 (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1698 (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1699 (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1700 (*fCovariance)(3,3) += theta02*step; // <bb>
1702 (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1703 (*fCovariance)(1,0) = (*fCovariance)(0,1);
1705 (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1706 (*fCovariance)(2,0) = (*fCovariance)(0,2);
1708 (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1709 (*fCovariance)(3,0) = (*fCovariance)(0,3);
1711 (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
1712 (*fCovariance)(2,1) = (*fCovariance)(1,2);
1714 (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1715 (*fCovariance)(3,1) = (*fCovariance)(1,3);
1717 (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1718 (*fCovariance)(3,2) = (*fCovariance)(2,3);
1720 // Get weight matrix
1721 *fWeight = *fCovariance;
1722 if (fWeight->Determinant() != 0) {
1724 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1726 AliWarning(" Determinant fWeight=0:");
1730 //__________________________________________________________________________
1731 Bool_t AliMUONTrackK::Recover(void)
1733 /// Adds new failed track(s) which can be tried to be recovered
1735 TClonesArray *trackPtr;
1736 AliMUONTrackK *trackK;
1738 if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
1739 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1741 // Remove hit with the highest chi2
1744 for (Int_t i=0; i<fNmbTrackHits; i++) {
1745 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1746 printf("%10.4f", chi2);
1749 for (Int_t i=0; i<fNmbTrackHits; i++) {
1750 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
1754 Double_t chi2max = 0;
1756 for (Int_t i=0; i<fNmbTrackHits; i++) {
1757 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1758 if (chi2 < chi2max) continue;
1762 //if (chi2max < 10) return kFALSE; // !!!
1763 //if (chi2max < 25) imax = fNmbTrackHits - 1;
1764 if (chi2max < 15) imax = fNmbTrackHits - 1; // discard the last point
1765 // Check if the outlier is not from the seed segment
1766 AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
1767 if (skipHit == (AliMUONHitForRec*) fStartSegment->First() || skipHit == (AliMUONHitForRec*) fStartSegment->Second()) {
1768 //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1769 return kFALSE; // to be changed probably
1772 // Make a copy of track hit collection
1773 TObjArray *hits = new TObjArray(*fTrackHits);
1777 // Hits after the found one will be removed
1778 if (GetStation0() == 3 && skipHit->GetChamberNumber() >= 7) {
1779 SortHits(1, fTrackHits); // unsort hits
1780 imax = fTrackHits->IndexOf(skipHit);
1782 Int_t nTrackHits = fNmbTrackHits;
1783 for (Int_t i=imax+1; i<nTrackHits; i++) {
1784 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
1785 fTrackHits->Remove(hit);
1786 hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit
1790 // Check if the track candidate doesn't exist yet
1791 if (ExistDouble()) { delete hits; return kFALSE; }
1793 //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1796 nRecTracks = fgTrackReconstructor->GetNRecTracks();
1797 skipHit = (AliMUONHitForRec*) ((*fTrackHits)[fNmbTrackHits-1]);
1798 // Remove all saved steps and smoother matrices after the skipped hit
1799 RemoveMatrices(skipHit->GetZ());
1801 //AZ(z->-z) if (skipHit->GetZ() > ((AliMUONHitForRec*) fStartSegment->Second())->GetZ() || !fNSteps) {
1802 if (TMath::Abs(skipHit->GetZ()) > TMath::Abs( ((AliMUONHitForRec*) fStartSegment->Second())->GetZ()) || !fNSteps) {
1803 // Propagation toward high Z or skipped hit next to segment -
1804 // start track from segment
1805 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
1806 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1807 trackK->fRecover = 1;
1808 trackK->fSkipHit = skipHit;
1809 trackK->fNmbTrackHits = fNmbTrackHits;
1810 delete trackK->fTrackHits; // not efficient ?
1811 trackK->fTrackHits = new TObjArray(*fTrackHits);
1812 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1816 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1818 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1819 //AZ(z->-z) trackK->fTrackDir = -1;
1820 trackK->fTrackDir = 1;
1821 trackK->fRecover = 1;
1822 trackK->fSkipHit = skipHit;
1823 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1825 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1826 CreateMatrix(trackK->fParFilter);
1828 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1829 trackK->fParFilter->Last()->SetUniqueID(1);
1830 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1831 iD = trackK->fCovFilter->Last()->GetUniqueID();
1833 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1834 CreateMatrix(trackK->fCovFilter);
1836 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1837 trackK->fCovFilter->Last()->SetUniqueID(1);
1838 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1839 if (trackK->fWeight->Determinant() != 0) {
1841 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1843 AliWarning(" Determinant fWeight=0:");
1845 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1847 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1848 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1852 //__________________________________________________________________________
1853 void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1855 /// Adds matrices for the smoother and keep Chi2 for the point
1856 /// Track parameters
1857 //trackK->fParFilter->Last()->Print();
1858 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1860 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1861 CreateMatrix(trackK->fParFilter);
1864 *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1865 trackK->fParFilter->Last()->SetUniqueID(iD);
1867 cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1868 //trackK->fTrackPar->Print();
1869 //trackK->fTrackParNew->Print();
1870 trackK->fParFilter->Last()->Print();
1871 cout << " Add matrices" << endl;
1874 *(trackK->fCovariance) = *(trackK->fWeight);
1875 if (trackK->fCovariance->Determinant() != 0) {
1877 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1879 AliWarning(" Determinant fCovariance=0:");
1881 iD = trackK->fCovFilter->Last()->GetUniqueID();
1883 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1884 CreateMatrix(trackK->fCovFilter);
1887 *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1888 trackK->fCovFilter->Last()->SetUniqueID(iD);
1890 // Save Chi2-increment for point
1891 Int_t indx = trackK->fTrackHits->IndexOf(hitAdd);
1892 if (indx < 0) indx = fNmbTrackHits;
1893 if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10);
1894 trackK->fChi2Array->AddAt(dChi2,indx);
1897 //__________________________________________________________________________
1898 void AliMUONTrackK::CreateMatrix(TObjArray *objArray) const
1900 /// Create new matrix and add it to TObjArray
1902 TMatrixD *matrix = (TMatrixD*) objArray->First();
1903 TMatrixD *tmp = new TMatrixD(*matrix);
1904 objArray->AddAtAndExpand(tmp,objArray->GetLast());
1905 //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1908 //__________________________________________________________________________
1909 void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1911 /// Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1913 for (Int_t i=fNSteps-1; i>=0; i--) {
1914 if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1915 if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1916 RemoveMatrices(this);
1917 } // for (Int_t i=fNSteps-1;
1920 //__________________________________________________________________________
1921 void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1923 /// Remove last saved matrices and steps in the smoother part
1926 Int_t i = trackK->fNSteps;
1929 // Delete only matrices not shared by several tracks
1930 id = trackK->fParExtrap->Last()->GetUniqueID();
1932 trackK->fParExtrap->Last()->SetUniqueID(id-1);
1933 trackK->fParExtrap->RemoveAt(i);
1935 else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1936 id = fParFilter->Last()->GetUniqueID();
1938 trackK->fParFilter->Last()->SetUniqueID(id-1);
1939 trackK->fParFilter->RemoveAt(i);
1941 else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1942 id = trackK->fCovExtrap->Last()->GetUniqueID();
1944 trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1945 trackK->fCovExtrap->RemoveAt(i);
1947 else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1948 id = trackK->fCovFilter->Last()->GetUniqueID();
1950 trackK->fCovFilter->Last()->SetUniqueID(id-1);
1951 trackK->fCovFilter->RemoveAt(i);
1953 else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1954 id = trackK->fJacob->Last()->GetUniqueID();
1956 trackK->fJacob->Last()->SetUniqueID(id-1);
1957 trackK->fJacob->RemoveAt(i);
1959 else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1962 //__________________________________________________________________________
1963 Bool_t AliMUONTrackK::Smooth(void)
1966 Int_t ihit = fNmbTrackHits - 1;
1967 AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1968 fChi2Smooth = new TArrayD(fNmbTrackHits);
1969 fChi2Smooth->Reset(-1);
1971 fParSmooth = new TObjArray(15);
1972 fParSmooth->Clear();
1975 cout << " ******** Enter Smooth " << endl;
1976 cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl;
1978 for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1980 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();}
1982 for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHits)[i])->GetZ() << " ";
1986 // Find last point corresponding to the last hit
1987 Int_t iLast = fNSteps - 1;
1988 for ( ; iLast>=0; iLast--) {
1989 //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ()) break;
1990 if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ())) break;
1993 TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1995 TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1996 TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1997 TMatrixD tmpPar = *fTrackPar;
1998 //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print();
2001 Double_t chi2max = 0;
2002 for (Int_t i=iLast+1; i>0; i--) {
2003 if (i == iLast + 1) goto L33; // temporary fix
2005 // Smoother gain matrix
2006 weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
2007 if (weight.Determinant() != 0) {
2009 mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2011 AliWarning(" Determinant weight=0:");
2014 tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
2015 gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
2016 //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
2018 // Smoothed parameter vector
2019 //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
2020 parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
2021 tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
2022 tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
2025 // Smoothed covariance
2026 covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
2027 weight = TMatrixD(TMatrixD::kTransposed,gain);
2028 tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
2029 covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
2030 covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
2032 // Check if there was a measurement at given z
2034 for ( ; ihit>=0; ihit--) {
2035 hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
2036 if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
2037 //AZ(z->-z) else if (ihit < fNmbTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
2038 else if (ihit < fNmbTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
2040 if (!found) continue; // no measurement - skip the rest
2041 else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
2042 if (ihit == 0) continue; // the first hit - skip the rest
2045 // Smoothed residuals
2047 tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
2048 tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
2050 cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
2051 cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
2053 // Cov. matrix of smoothed residuals
2055 tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
2056 tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
2057 tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
2058 tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
2060 // Calculate Chi2 of smoothed residuals
2061 if (tmp.Determinant() != 0) {
2063 mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2065 AliWarning(" Determinant tmp=0:");
2067 TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
2068 TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
2069 if (fgDebug > 1) chi2.Print();
2070 (*fChi2Smooth)[ihit] = chi2(0,0);
2071 if (chi2(0,0) > chi2max) chi2max = chi2(0,0);
2073 if (chi2(0,0) < 0) {
2075 AliError(Form(" *** chi2 < 0: %d %d ", i, iLast));
2077 // Save smoothed parameters
2078 TMatrixD *par = new TMatrixD(parSmooth);
2079 fParSmooth->AddAtAndExpand(par, ihit);
2081 } // for (Int_t i=iLast+1;
2083 //if (chi2max > 16) {
2084 //if (chi2max > 25) {
2085 //if (chi2max > 50) {
2086 //if (chi2max > 100) {
2087 if (chi2max > fgkChi2max) {
2088 //if (Recover()) DropBranches();
2096 //__________________________________________________________________________
2097 void AliMUONTrackK::Outlier()
2099 /// Adds new track with removed hit having the highest chi2
2102 cout << " ******** Enter Outlier " << endl;
2103 for (Int_t i=0; i<fNmbTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
2105 for (Int_t i=0; i<fNmbTrackHits; i++) {
2106 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
2111 Double_t chi2max = 0;
2113 for (Int_t i=0; i<fNmbTrackHits; i++) {
2114 if ((*fChi2Smooth)[i] < chi2max) continue;
2115 chi2max = (*fChi2Smooth)[i];
2118 // Check if the outlier is not from the seed segment
2119 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
2120 if (hit == (AliMUONHitForRec*) fStartSegment->First() || hit == (AliMUONHitForRec*) fStartSegment->Second()) return; // to be changed probably
2122 // Check for missing station
2125 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--;
2126 } else if (imax == fNmbTrackHits-1) {
2127 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2129 else if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2130 if (!ok) { Recover(); return; } // try to recover track
2131 //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; }
2133 // Remove saved steps and smoother matrices after the outlier
2134 RemoveMatrices(hit->GetZ());
2136 // Check for possible double track candidates
2137 //if (ExistDouble(hit)) return;
2139 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2140 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2142 AliMUONTrackK *trackK = 0;
2143 if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2144 // start track from segment
2145 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
2146 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2147 trackK->fRecover = 2;
2148 trackK->fSkipHit = hit;
2149 trackK->fNmbTrackHits = fNmbTrackHits;
2151 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(0);
2152 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2153 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(1);
2154 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2155 delete trackK->fTrackHits; // not efficient ?
2156 trackK->fTrackHits = new TObjArray(*fTrackHits);
2157 for (Int_t i = 0; i < fNmbTrackHits; i++) {
2158 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
2159 hit->SetNTrackHits(hit->GetNTrackHits()+1);
2162 if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHits);
2163 if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2166 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2168 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2169 trackK->fTrackDir = 1;
2170 trackK->fRecover = 2;
2171 trackK->fSkipHit = hit;
2172 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2174 trackK->fParFilter->Last()->SetUniqueID(iD-1);
2175 CreateMatrix(trackK->fParFilter);
2177 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2178 trackK->fParFilter->Last()->SetUniqueID(1);
2179 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2180 iD = trackK->fCovFilter->Last()->GetUniqueID();
2182 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2183 CreateMatrix(trackK->fCovFilter);
2185 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2186 trackK->fCovFilter->Last()->SetUniqueID(1);
2187 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2188 if (trackK->fWeight->Determinant() != 0) {
2190 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2192 AliWarning(" Determinant fWeight=0:");
2194 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2196 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2197 if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2200 //__________________________________________________________________________
2201 Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2203 /// Return Chi2 at point
2204 return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2208 //__________________________________________________________________________
2209 void AliMUONTrackK::Print(FILE *lun) const
2211 /// Print out track information
2214 AliMUONHitForRec *hit = 0;
2215 // from raw clusters
2216 AliMUONRawCluster *clus = 0;
2217 TClonesArray *rawclusters = 0;
2218 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2219 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2220 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2221 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2222 if (TMath::Abs(clus->GetTrack(1)-1) < 2) {
2223 if (clus->GetTrack(2)) flag = 2;
2226 if (clus->GetTrack(2) && TMath::Abs(clus->GetTrack(2)-1) < 2) {
2233 Int_t sig[2]={1,1}, tid[2]={0};
2234 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2235 if (GetChi2PerPoint(i1) < -0.1) continue;
2236 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2237 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2238 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2239 for (Int_t j=0; j<2; j++) {
2240 tid[j] = clus->GetTrack(j+1) - 1;
2241 if (clus->GetTrack(j+1) < 0) { sig[j] = 0; tid[j] = 999; }
2243 // fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(i1));
2244 if (!(clus->GetTrack(2))) fprintf(lun, "%3d %3d", sig[0], tid[0]); // simple cluster
2245 else { // track overlap
2246 fprintf(lun, "%3d %3d", TMath::Max(sig[0],sig[1]), TMath::Min(tid[0],tid[1]));
2247 //if (tid[0] < 2) flag *= 2;
2248 //else if (tid[1] < 2) flag *= 3;
2250 fprintf (lun, "%3d \n", flag);
2255 //__________________________________________________________________________
2256 void AliMUONTrackK::DropBranches(Int_t imax, TObjArray *hits)
2258 /// Drop branches downstream of the skipped hit
2260 TClonesArray *trackPtr;
2261 AliMUONTrackK *trackK;
2263 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2264 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2265 Int_t icand = trackPtr->IndexOf(this);
2266 if (!hits) hits = fTrackHits;
2268 // Check if the track candidate doesn't exist yet
2269 for (Int_t i=icand+1; i<nRecTracks; i++) {
2270 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2271 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2272 if (trackK->GetRecover() < 0) continue;
2274 if (trackK->fNmbTrackHits >= imax + 1) {
2275 for (Int_t j=0; j<=imax; j++) {
2276 //if (j != fNmbTrackHits-1 && (*trackK->fTrackHits)[j] != (*fTrackHits)[j]) break;
2277 if ((*trackK->fTrackHits)[j] != (*hits)[j]) break;
2279 if (hits != fTrackHits) {
2280 // Drop all branches downstream the hit (for Recover)
2281 trackK->SetRecover(-1);
2282 if (fgDebug >= 0 )cout << " Recover " << i << endl;
2285 // Check if the removal of the hit breaks the track
2288 if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2289 else if (imax == trackK->fNmbTrackHits-1) continue;
2290 // else if (imax == trackK->fNmbTrackHits-1) {
2291 //if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(trackK->fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2293 else if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2294 if (!ok) trackK->SetRecover(-1);
2296 } // for (Int_t j=0;
2298 } // for (Int_t i=0;
2301 //__________________________________________________________________________
2302 void AliMUONTrackK::DropBranches(AliMUONObjectPair *segment)
2304 /// Drop all candidates with the same seed segment
2306 TClonesArray *trackPtr;
2307 AliMUONTrackK *trackK;
2308 AliMUONObjectPair *trackKSegment;
2310 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2311 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2312 Int_t icand = trackPtr->IndexOf(this);
2314 for (Int_t i=icand+1; i<nRecTracks; i++) {
2315 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2316 trackKSegment = trackK->fStartSegment;
2317 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2318 if (trackK->GetRecover() < 0) continue;
2319 if (trackKSegment->First() == segment->First() &&
2320 trackKSegment->Second() == segment->Second()) trackK->SetRecover(-1);
2322 if (fgDebug >= 0) cout << " Drop segment " << endl;
2325 //__________________________________________________________________________
2326 AliMUONHitForRec* AliMUONTrackK::GetHitLastOk(void)
2328 /// Return the hit where track stopped
2330 if (!fNSteps) return (AliMUONHitForRec*)((*fTrackHits)[1]);
2334 //__________________________________________________________________________
2335 Int_t AliMUONTrackK::GetStation0(void)
2337 /// Return seed station number
2338 return ((AliMUONHitForRec*) fStartSegment->First())->GetChamberNumber() / 2;
2341 //__________________________________________________________________________
2342 Bool_t AliMUONTrackK::ExistDouble(AliMUONHitForRec *hit)
2344 /// Check if the track will make a double after outlier removal
2346 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2347 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2348 TObjArray *hitArray = new TObjArray(*fTrackHits);
2349 TObjArray *hitArray1 = new TObjArray(*hitArray);
2350 hitArray1->Remove(hit);
2351 hitArray1->Compress();
2353 Bool_t same = kFALSE;
2354 for (Int_t i=0; i<nRecTracks; i++) {
2355 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2356 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2357 if (trackK == this) continue;
2358 if (trackK->fNmbTrackHits == fNmbTrackHits || trackK->fNmbTrackHits == fNmbTrackHits-1) {
2359 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2361 if (trackK->fNmbTrackHits == fNmbTrackHits) {
2362 for (Int_t j=0; j<fNmbTrackHits; j++) {
2363 if (hits->UncheckedAt(j) != hitArray->UncheckedAt(j)) { same = kFALSE; break; }
2365 if (same) { delete hits; break; }
2366 if (trackK->fSkipHit) {
2367 TObjArray *hits1 = new TObjArray(*hits);
2368 if (hits1->Remove(trackK->fSkipHit) > 0) {
2371 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2372 if (hits1->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2374 if (same) { delete hits1; break; }
2379 // Check with removed outlier
2381 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2382 if (hits->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2384 if (same) { delete hits; break; }
2388 } // for (Int_t i=0; i<nRecTracks;
2389 delete hitArray; delete hitArray1;
2390 if (same && fgDebug >= 0) cout << " Same" << endl;
2394 //__________________________________________________________________________
2395 Bool_t AliMUONTrackK::ExistDouble(void)
2397 /// Check if the track will make a double after recovery
2399 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2400 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2402 TObjArray *hitArray = new TObjArray(*fTrackHits);
2403 if (GetStation0() == 3) SortHits(0, hitArray); // sort
2404 //if (GetStation0() == 3) SortHits(1, hitArray); // unsort
2406 Bool_t same = kFALSE;
2407 for (Int_t i=0; i<nRecTracks; i++) {
2408 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2409 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2410 if (trackK == this) continue;
2411 //AZ if (trackK->GetRecover() < 0) continue; //
2412 if (trackK->fNmbTrackHits >= fNmbTrackHits) {
2413 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2414 if (trackK->GetStation0() == 3) SortHits(0, hits); // sort
2415 //if (trackK->GetStation0() == 3) SortHits(1, hits); // unsort
2416 for (Int_t j=0; j<fNmbTrackHits; j++) {
2417 //cout << fNmbTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2418 if (j != fNmbTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break;
2419 if (j == fNmbTrackHits-1) {
2420 if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE;
2421 //if (trackK->fNmbTrackHits > fNmbTrackHits &&
2422 //if (trackK->fSkipHit) cout << ((AliMUONHitForRec*)((*hitArray)[j]))->GetZ() << " " << trackK->fSkipHit->GetZ() << endl;
2424 } // for (Int_t j=0;
2428 } // for (Int_t i=0;
2433 //______________________________________________________________________________
2434 void mnvertLocal(Double_t *a, Int_t l, Int_t, Int_t n, Int_t &ifail)
2436 ///*-*-*-*-*-*-*-*-*-*-*-*Inverts a symmetric matrix*-*-*-*-*-*-*-*-*-*-*-*-*
2437 ///*-* ==========================
2438 ///*-* inverts a symmetric matrix. matrix is first scaled to
2439 ///*-* have all ones on the diagonal (equivalent to change of units)
2440 ///*-* but no pivoting is done since matrix is positive-definite.
2441 ///*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
2443 // taken from TMinuit package of Root (l>=n)
2444 // fVERTs, fVERTq and fVERTpp changed to localVERTs, localVERTq and localVERTpp
2445 // Double_t localVERTs[n], localVERTq[n], localVERTpp[n];
2446 Double_t * localVERTs = new Double_t[n];
2447 Double_t * localVERTq = new Double_t[n];
2448 Double_t * localVERTpp = new Double_t[n];
2449 // fMaxint changed to localMaxint
2450 Int_t localMaxint = n;
2452 /* System generated locals */
2455 /* Local variables */
2457 Int_t i, j, k, kp1, km1;
2459 /* Parameter adjustments */
2465 if (n < 1) goto L100;
2466 if (n > localMaxint) goto L100;
2467 //*-*- scale matrix by sqrt of diag elements
2468 for (i = 1; i <= n; ++i) {
2470 if (si <= 0) goto L100;
2471 localVERTs[i-1] = 1 / TMath::Sqrt(si);
2473 for (i = 1; i <= n; ++i) {
2474 for (j = 1; j <= n; ++j) {
2475 a[i + j*l] = a[i + j*l]*localVERTs[i-1]*localVERTs[j-1];
2478 //*-*- . . . start main loop . . . .
2479 for (i = 1; i <= n; ++i) {
2481 //*-*- preparation for elimination step1
2482 if (a[k + k*l] != 0) localVERTq[k-1] = 1 / a[k + k*l];
2484 localVERTpp[k-1] = 1;
2488 if (km1 < 0) goto L100;
2489 else if (km1 == 0) goto L50;
2492 for (j = 1; j <= km1; ++j) {
2493 localVERTpp[j-1] = a[j + k*l];
2494 localVERTq[j-1] = a[j + k*l]*localVERTq[k-1];
2498 if (k - n < 0) goto L51;
2499 else if (k - n == 0) goto L60;
2502 for (j = kp1; j <= n; ++j) {
2503 localVERTpp[j-1] = a[k + j*l];
2504 localVERTq[j-1] = -a[k + j*l]*localVERTq[k-1];
2507 //*-*- elimination proper
2509 for (j = 1; j <= n; ++j) {
2510 for (k = j; k <= n; ++k) { a[j + k*l] += localVERTpp[j-1]*localVERTq[k-1]; }
2513 //*-*- elements of left diagonal and unscaling
2514 for (j = 1; j <= n; ++j) {
2515 for (k = 1; k <= j; ++k) {
2516 a[k + j*l] = a[k + j*l]*localVERTs[k-1]*localVERTs[j-1];
2517 a[j + k*l] = a[k + j*l];
2520 delete [] localVERTs;
2521 delete [] localVERTq;
2522 delete [] localVERTpp;
2524 //*-*- failure return
2526 delete [] localVERTs;
2527 delete [] localVERTq;
2528 delete [] localVERTpp;