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"
33 #include "AliMUONTrackReconstructor.h"
35 #include "AliMUONSegment.h"
36 #include "AliMUONHitForRec.h"
37 #include "AliMUONRawCluster.h"
38 #include "AliMUONTrackParam.h"
39 #include "AliMUONEventRecoCombi.h"
40 #include "AliMUONDetElement.h"
44 const Int_t AliMUONTrackK::fgkSize = 5;
45 const Int_t AliMUONTrackK::fgkNSigma = 12;
46 const Double_t AliMUONTrackK::fgkChi2max = 100;
47 const Int_t AliMUONTrackK::fgkTriesMax = 10000;
48 const Double_t AliMUONTrackK::fgkEpsilon = 0.002;
50 void mnvertLocal(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail); // from AliMUONTrack
52 Int_t AliMUONTrackK::fgDebug = -1; //-1;
53 Int_t AliMUONTrackK::fgNOfPoints = 0;
54 AliMUONTrackReconstructor* AliMUONTrackK::fgTrackReconstructor = NULL;
55 TClonesArray* AliMUONTrackK::fgHitForRec = NULL;
56 AliMUONEventRecoCombi *AliMUONTrackK::fgCombi = NULL;
58 ClassImp(AliMUONTrackK) // Class implementation in ROOT context
60 //__________________________________________________________________________
61 AliMUONTrackK::AliMUONTrackK()
65 /// Default constructor
67 fgTrackReconstructor = NULL; // pointer to event reconstructor
68 fgHitForRec = NULL; // pointer to points
69 fgNOfPoints = 0; // number of points
74 fTrackPar = fTrackParNew = NULL;
75 fCovariance = fWeight = NULL;
77 fParExtrap = fParFilter = fParSmooth = NULL;
78 fCovExtrap = fCovFilter = NULL;
80 fSteps = NULL; fNSteps = 0;
87 //__________________________________________________________________________
88 AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructor *TrackReconstructor, TClonesArray *hitForRec)
93 if (!TrackReconstructor) return;
94 fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
95 fgHitForRec = hitForRec; // pointer to points
96 fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
98 if (fgTrackReconstructor->GetTrackMethod() == 3) fgCombi = AliMUONEventRecoCombi::Instance();
100 fStartSegment = NULL;
104 fTrackPar = fTrackParNew = NULL;
105 fCovariance = fWeight = NULL;
107 fParExtrap = fParFilter = fParSmooth = NULL;
108 fCovExtrap = fCovFilter = NULL;
110 fSteps = NULL; fNSteps = 0;
115 //__________________________________________________________________________
116 AliMUONTrackK::AliMUONTrackK(AliMUONSegment *segment)
117 //: AliMUONTrack(segment, segment, fgTrackReconstructor)
118 : AliMUONTrack(NULL, segment, fgTrackReconstructor)
120 /// Constructor from a segment
122 AliMUONHitForRec *hit1, *hit2;
123 AliMUONRawCluster *clus;
124 TClonesArray *rawclusters;
126 fStartSegment = segment;
129 // Pointers to hits from the segment
130 hit1 = segment->GetHitForRec1();
131 hit2 = segment->GetHitForRec2();
132 hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
133 hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
134 // check sorting in Z
135 if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
137 hit2 = segment->GetHitForRec1();
139 // memory allocation for the TObjArray of pointers to reconstructed TrackHit's
140 fTrackHits = new TObjArray(13);
144 fTrackPar = new TMatrixD(fgkSize,1); // track parameters
145 fTrackParNew = new TMatrixD(fgkSize,1); // track parameters
146 fCovariance = new TMatrixD(fgkSize,fgkSize); // covariance matrix
147 fWeight = new TMatrixD(fgkSize,fgkSize); // weight matrix (inverse of covariance)
149 // Fill array of track parameters
150 if (hit1->GetChamberNumber() > 7) {
151 // last tracking station
152 (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
153 (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
154 fPosition = hit1->GetZ(); // z
155 fTrackHits->Add(hit2); // add hit 2
156 fTrackHits->Add(hit1); // add hit 1
157 //AZ(Z->-Z) fTrackDir = -1;
160 // last but one tracking station
161 (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
162 (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
163 fPosition = hit2->GetZ(); // z
164 fTrackHits->Add(hit1); // add hit 1
165 fTrackHits->Add(hit2); // add hit 2
166 //AZ(Z->-Z) fTrackDir = 1;
169 dZ = hit2->GetZ() - hit1->GetZ();
170 dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
171 dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
172 (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
173 if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
174 (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
175 (*fTrackPar)(2,0) -= TMath::Pi();
176 (*fTrackPar)(4,0) = 1/fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()); // 1/Pt
177 (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
178 // Evaluate covariance (and weight) matrix
182 fParExtrap = new TObjArray(15);
183 fParFilter = new TObjArray(15);
184 fCovExtrap = new TObjArray(15);
185 fCovFilter = new TObjArray(15);
186 fJacob = new TObjArray(15);
187 fSteps = new TArrayD(15);
189 fChi2Array = new TArrayD(13);
193 if (fgDebug < 0 ) return;
194 cout << fgTrackReconstructor->GetNRecTracks()-1 << " " << fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()) << " " << 1/(*fTrackPar)(4,0) << " ";
195 if (fgTrackReconstructor->GetRecTrackRefHits()) {
196 // from track ref. hits
197 cout << ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetTTRTrack() << "<-->" << ((AliMUONHitForRec*)((*fTrackHits)[1]))->GetTTRTrack() << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
200 for (Int_t i=0; i<2; i++) {
201 hit1 = (AliMUONHitForRec*) ((*fTrackHits)[i]);
202 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
203 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
204 cout << clus->GetTrack(1);
205 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
206 if (i == 0) cout << " <--> ";
208 cout << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
212 //__________________________________________________________________________
213 AliMUONTrackK::~AliMUONTrackK()
218 //cout << fNmbTrackHits << endl;
219 for (Int_t i = 0; i < fNmbTrackHits; i++) {
220 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
221 hit->SetNTrackHits(hit->GetNTrackHits()-1);
223 delete fTrackHits; // delete the TObjArray of pointers to TrackHit's
227 delete fTrackPar; delete fTrackParNew; delete fCovariance;
231 if (fSteps) delete fSteps;
232 if (fChi2Array) delete fChi2Array;
233 if (fChi2Smooth) delete fChi2Smooth;
234 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
235 // Delete only matrices not shared by several tracks
236 if (!fParExtrap) return;
239 for (Int_t i=0; i<fNSteps; i++) {
240 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
241 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
242 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
244 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
245 fParExtrap->RemoveAt(i);
247 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
248 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
249 id = fParFilter->UncheckedAt(i)->GetUniqueID();
251 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
252 fParFilter->RemoveAt(i);
254 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
255 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
256 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
258 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
259 fCovExtrap->RemoveAt(i);
262 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
263 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
264 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
266 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
267 fCovFilter->RemoveAt(i);
269 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
270 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
271 id = fJacob->UncheckedAt(i)->GetUniqueID();
273 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
278 for (Int_t i=0; i<fNSteps; i++) {
279 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
280 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
281 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
282 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
283 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
284 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
287 fParExtrap->Delete(); fParFilter->Delete();
288 fCovExtrap->Delete(); fCovFilter->Delete();
290 delete fParExtrap; delete fParFilter;
291 delete fCovExtrap; delete fCovFilter;
295 //__________________________________________________________________________
296 AliMUONTrackK::AliMUONTrackK (const AliMUONTrackK& source)
297 : AliMUONTrack(source)
299 /// Protected copy constructor
300 AliFatal("Not implemented.");
303 //__________________________________________________________________________
304 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
306 /// Assignment operator
309 if(&source == this) return *this;
311 // base class assignement
312 //AZ TObject::operator=(source);
313 AliMUONTrack::operator=(source);
315 fStartSegment = source.fStartSegment;
316 fNmbTrackHits = source.fNmbTrackHits;
317 fChi2 = source.fChi2;
318 fPosition = source.fPosition;
319 fPositionNew = source.fPositionNew;
320 fTrackDir = source.fTrackDir;
321 fBPFlag = source.fBPFlag;
322 fRecover = source.fRecover;
323 fSkipHit = source.fSkipHit;
326 fTrackHits = new TObjArray(*source.fTrackHits);
327 //source.fTrackHits->Dump();
328 //fTrackHits->Dump();
329 for (Int_t i = 0; i < fNmbTrackHits; i++) {
330 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
331 hit->SetNTrackHits(hit->GetNTrackHits()+1);
334 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
335 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
336 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
337 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
340 fParExtrap = new TObjArray(*source.fParExtrap);
341 fParFilter = new TObjArray(*source.fParFilter);
342 fCovExtrap = new TObjArray(*source.fCovExtrap);
343 fCovFilter = new TObjArray(*source.fCovFilter);
344 fJacob = new TObjArray(*source.fJacob);
345 fSteps = new TArrayD(*source.fSteps);
346 fNSteps = source.fNSteps;
348 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
352 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
353 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
354 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
355 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
356 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
357 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
362 //__________________________________________________________________________
363 void AliMUONTrackK::EvalCovariance(Double_t dZ)
365 /// Evaluate covariance (and weight) matrix for track candidate
366 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
369 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
370 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
372 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
374 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
376 tanA = TMath::Tan((*fTrackPar)(2,0));
377 dAdY = 1/(1+tanA*tanA)/dZ;
378 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
379 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
380 (*fWeight)(2,0) = (*fWeight)(0,2);
382 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
383 tanB = TMath::Tan((*fTrackPar)(3,0));
384 dBdX = 1/(1+tanB*tanB)/rad;
386 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
387 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
388 (*fWeight)(3,1) = (*fWeight)(1,3);
390 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
392 // check whether the Invert method returns flag if matrix cannot be inverted,
393 // and do not calculate the Determinant in that case !!!!
394 if (fWeight->Determinant() != 0) {
395 // fWeight->Invert();
397 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
399 AliWarning(" Determinant fWeight=0:");
404 //__________________________________________________________________________
405 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
407 /// Follows track through detector stations
408 Bool_t miss, success;
409 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
410 Int_t ihit, firstIndx = -1, lastIndx = -1, currIndx = -1, iz0 = -1, iz = -1;
411 Double_t zEnd, dChi2;
412 AliMUONHitForRec *hitAdd, *firstHit = NULL, *lastHit = NULL, *hit;
413 AliMUONRawCluster *clus;
414 TClonesArray *rawclusters;
415 hit = 0; clus = 0; rawclusters = 0;
417 miss = success = kTRUE;
419 //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
420 iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
421 iMin = TMath::Min(ichamEnd,ichamBeg);
422 iMax = TMath::Max(ichamEnd,ichamBeg);
429 if (((AliMUONHitForRec*)fTrackHits->First())->GetChamberNumber() != ichamb) currIndx = 0;
430 } else if (fRecover) {
431 hit = GetHitLastOk();
432 currIndx = fTrackHits->IndexOf(hit);
433 if (currIndx < 0) hit = fStartSegment->GetHitForRec1(); // for station 3
435 ichamb = hit->GetChamberNumber();
436 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
437 // start from the last point or outlier
438 // remove the skipped hit
439 fTrackHits->Remove(fSkipHit); // remove hit
441 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
446 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
447 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetChamberNumber() == 6) ichambOK = 6;
448 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
449 fSkipHit->GetHitNumber() < 0) {
450 iz0 = fgCombi->IZfromHit(fSkipHit);
453 else currIndx = fgHitForRec->IndexOf(fSkipHit);
456 fTrackHits->Compress();
458 } // if (hit == fSkipHit)
459 else if (currIndx < 0) currIndx = fTrackHits->IndexOf(hit);
460 } // else if (fRecover)
462 // Get indices of the 1'st and last hits on the track candidate
463 firstHit = (AliMUONHitForRec*) fTrackHits->First();
464 lastHit = (AliMUONHitForRec*) fTrackHits->Last();
465 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
466 lastHit->GetHitNumber() < 0) iz0 = fgCombi->IZfromHit(lastHit);
468 firstIndx = fgHitForRec->IndexOf(firstHit);
469 lastIndx = fgHitForRec->IndexOf(lastHit);
470 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
474 if (iz0 < 0) iz0 = iFB;
475 while (ichamb >= iMin && ichamb <= iMax) {
476 // Find the closest hit in Z, not belonging to the current plane
479 if (currIndx < fNmbTrackHits) {
480 hitAdd = (AliMUONHitForRec*) fTrackHits->UncheckedAt(currIndx);
481 zEnd = hitAdd->GetZ();
482 //AZ(z->-z) } else zEnd = -9999;
485 //AZ(Z->-Z) zEnd = -9999;
487 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
488 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
489 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
490 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
491 zEnd = hitAdd->GetZ();
497 // Combined cluster / track finder
498 if (zEnd > 999 && iFB < 0 && fgTrackReconstructor->GetTrackMethod() == 3) {
500 AliMUONHitForRec hitTmp;
501 for (iz = iz0 - iFB; iz < fgCombi->Nz(); iz++) {
502 if (TMath::Abs(fgCombi->Z(iz)-fPosition) < 0.5) continue;
503 Int_t *pDEatZ = fgCombi->DEatZ(iz);
504 //cout << iz << " " << fgCombi->Z(iz) << endl;
505 zEnd = fgCombi->Z(iz);
507 AliMUONDetElement *detElem = fgCombi->DetElem(pDEatZ[0]);
509 hitAdd->SetChamberNumber(detElem->Chamber());
510 //hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
515 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
517 // Check if there is a chamber without hits
518 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
519 if (!Back && zEnd<999) currIndx -= iFB;
521 zEnd = AliMUONConstants::DefaultChamberZ(ichamb);
524 ichamb = hitAdd->GetChamberNumber();
528 if (ichamb<iMin || ichamb>iMax) break;
529 // Check for missing station
531 dChamb = TMath::Abs(ichamb-ichambOK);
532 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
533 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
534 if (zEnd > 999) dStatMiss++;
536 //if (dStatMiss == 2 && ichambOK/2 != 3 || dStatMiss > 2) { // AZ - missing st. 3
537 // missing station - abandon track
538 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
540 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
541 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
542 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
543 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
544 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
545 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
548 cout << fNmbTrackHits << endl;
549 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
550 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
551 printf(" * %d %10.4f %10.4f %10.4f",
552 hit->GetChamberNumber(), hit->GetBendingCoor(),
553 hit->GetNonBendingCoor(), hit->GetZ());
554 if (fgTrackReconstructor->GetRecTrackRefHits()) {
555 // from track ref. hits
556 printf(" %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack());
559 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
560 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
561 printf("%3d", clus->GetTrack(1)-1);
562 if (clus->GetTrack(2) != 0) printf("%3d \n", clus->GetTrack(2)-1);
566 } // if (fgDebug >= 10)
567 if (fNmbTrackHits>2 && fRecover==0) Recover(); // try to recover track later
569 } // if (dStatMiss > 1)
571 if (endOfProp != 0) break;
573 // propagate to the found Z
575 // Check if track steps into dipole
576 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
577 if (fPosition<zDipole2 && zEnd>zDipole2) {
578 //LinearPropagation(zDipole2-zBeg);
579 ParPropagation(zDipole2);
580 MSThin(1); // multiple scattering in the chamber
581 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
582 fPosition = fPositionNew;
583 *fTrackPar = *fTrackParNew;
584 //MagnetPropagation(zEnd);
585 ParPropagation(zEnd);
586 WeightPropagation(zEnd, kTRUE);
587 fPosition = fPositionNew;
589 // Check if track steps out of dipole
590 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
591 else if (fPosition<zDipole1 && zEnd>zDipole1) {
592 //MagnetPropagation(zDipole1-zBeg);
593 ParPropagation(zDipole1);
594 MSThin(1); // multiple scattering in the chamber
595 WeightPropagation(zDipole1, kTRUE);
596 fPosition = fPositionNew;
597 *fTrackPar = *fTrackParNew;
598 //LinearPropagation(zEnd-zDipole1);
599 ParPropagation(zEnd);
600 WeightPropagation(zEnd, kTRUE);
601 fPosition = fPositionNew;
603 ParPropagation(zEnd);
604 //MSThin(1); // multiple scattering in the chamber
605 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
606 WeightPropagation(zEnd, kTRUE);
607 fPosition = fPositionNew;
611 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
612 // recovered track - remove the hit
614 ichamb = fSkipHit->GetChamberNumber();
615 // remove the skipped hit
616 fTrackHits->Remove(fSkipHit);
618 //AZ fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
621 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
622 //? if (fgTrackReconstructor->GetTrackMethod() != 3) currIndx = fgHitForRec->IndexOf(fSkipHit);
623 currIndx = fgHitForRec->IndexOf(fSkipHit);
627 // backward propagator
629 TMatrixD pointWeight(fgkSize,fgkSize);
630 TMatrixD point(fgkSize,1);
631 TMatrixD trackParTmp = point;
632 point(0,0) = hitAdd->GetBendingCoor();
633 point(1,0) = hitAdd->GetNonBendingCoor();
634 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
635 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
636 TryPoint(point,pointWeight,trackParTmp,dChi2);
637 *fTrackPar = trackParTmp;
638 *fWeight += pointWeight;
639 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
640 fChi2 += dChi2; // Chi2
641 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
642 if (ichamb==ichamEnd) break;
645 // forward propagator
646 if (miss || !FindPoint(ichamb, zEnd, currIndx, iFB, hitAdd, iz)) {
648 *fTrackPar = *fTrackParNew;
651 fTrackHits->Add(hitAdd); // add hit
653 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
655 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
659 if (fgDebug > 0) cout << fNmbTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
660 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
664 //__________________________________________________________________________
665 void AliMUONTrackK::ParPropagation(Double_t zEnd)
667 /// Propagation of track parameters to zEnd
669 Double_t dZ, step, distance, charge;
670 Double_t vGeant3[7], vGeant3New[7];
671 AliMUONTrackParam trackParam;
674 // First step using linear extrapolation
675 dZ = zEnd - fPosition;
676 fPositionNew = fPosition;
677 *fTrackParNew = *fTrackPar;
678 if (dZ == 0) return; //AZ ???
679 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
680 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
681 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
682 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
683 SetGeantParam(vGeant3,iFB);
684 //fTrackParNew->Print();
688 step = TMath::Abs(step);
689 // Propagate parameters
690 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
691 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
692 distance = zEnd - vGeant3New[2];
693 step *= dZ/(vGeant3New[2]-fPositionNew);
695 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
697 GetFromGeantParam(vGeant3New,iFB);
698 //fTrackParNew->Print();
700 // Position adjustment (until within tolerance)
701 while (TMath::Abs(distance) > fgkEpsilon) {
702 dZ = zEnd - fPositionNew;
703 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
704 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
705 step = TMath::Abs(step);
706 SetGeantParam(vGeant3,iFB);
709 // Propagate parameters
710 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
711 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
712 distance = zEnd - vGeant3New[2];
715 if (nTries > fgkTriesMax) AliError(Form(" Too many tries: %d", nTries));
716 } while (distance*iFB < 0);
718 GetFromGeantParam(vGeant3New,iFB);
720 //cout << nTries << endl;
721 //fTrackParNew->Print();
725 //__________________________________________________________________________
726 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
728 /// Propagation of the weight matrix
729 /// W = DtWD, where D is Jacobian
733 TMatrixD jacob(fgkSize,fgkSize);
736 // Save initial and propagated parameters
737 TMatrixD trackPar0 = *fTrackPar;
738 TMatrixD trackParNew0 = *fTrackParNew;
740 // Get covariance matrix
741 *fCovariance = *fWeight;
742 // check whether the Invert method returns flag if matrix cannot be inverted,
743 // and do not calculate the Determinant in that case !!!!
744 if (fCovariance->Determinant() != 0) {
746 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
747 //fCovariance->Print();
749 AliWarning(" Determinant fCovariance=0:");
752 // Loop over parameters to find change of the propagated vs initial ones
753 for (i=0; i<fgkSize; i++) {
754 dPar = TMath::Sqrt((*fCovariance)(i,i));
755 *fTrackPar = trackPar0;
756 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
757 (*fTrackPar)(i,0) += dPar;
758 ParPropagation(zEnd);
759 for (j=0; j<fgkSize; j++) {
760 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
764 //trackParNew0.Print();
765 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
767 TMatrixD jacob0 = jacob;
768 if (jacob.Determinant() != 0) {
771 AliWarning(" Determinant jacob=0:");
773 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
774 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
776 // Restore initial and propagated parameters
777 *fTrackPar = trackPar0;
778 *fTrackParNew = trackParNew0;
781 if (!smooth) return; // do not use smoother
782 if (fTrackDir < 0) return; // only for propagation towards int. point
783 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
784 fParExtrap->Add(tmp);
786 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
787 fParFilter->Add(tmp);
789 *fCovariance = *fWeight;
790 if (fCovariance->Determinant() != 0) {
792 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
794 AliWarning(" Determinant fCovariance=0:");
796 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
797 fCovExtrap->Add(tmp);
799 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
800 fCovFilter->Add(tmp);
802 tmp = new TMatrixD(jacob0); // Jacobian
805 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
806 fSteps->AddAt(fPositionNew,fNSteps++);
807 if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
811 //__________________________________________________________________________
812 Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd, Int_t iz)
814 /// Picks up point within a window for the chamber No ichamb
815 /// Split the track if there are more than 1 hit
816 Int_t ihit, nRecTracks;
817 Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
818 TClonesArray *trackPtr;
819 AliMUONHitForRec *hit, *hitLoop;
820 AliMUONTrackK *trackK;
821 AliMUONDetElement *detElem = NULL;
825 if (fgTrackReconstructor->GetTrackMethod() == 3 && iz >= 0) {
826 // Combined cluster / track finder
827 // Check if extrapolated track passes thru det. elems. at iz
828 Int_t *pDEatZ = fgCombi->DEatZ(iz);
829 Int_t nDetElem = pDEatZ[-1];
830 //cout << fgCombi->Z(iz) << " " << nDetElem << endl;
831 for (Int_t i = 0; i < nDetElem; i++) {
832 detElem = fgCombi->DetElem(pDEatZ[i]);
833 if (detElem->Inside((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPosition)) {
834 detElem->ClusterReco((*fTrackParNew)(1,0), (*fTrackParNew)(0,0));
835 hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
840 if (!ok) return ok; // outside det. elem.
844 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
845 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
846 *fCovariance = *fWeight;
847 // check whether the Invert method returns flag if matrix cannot be inverted,
848 // and do not calculate the Determinant in that case !!!!
849 if (fCovariance->Determinant() != 0) {
851 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
853 AliWarning(" Determinant fCovariance=0:");
855 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
856 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
857 // Loop over all hits and take hits from the chamber
858 TMatrixD pointWeight(fgkSize,fgkSize);
859 TMatrixD saveWeight = pointWeight;
860 TMatrixD pointWeightTmp = pointWeight;
861 TMatrixD point(fgkSize,1);
862 TMatrixD trackPar = point;
863 TMatrixD trackParTmp = point;
864 Int_t nHitsOK = 0, ihitB = currIndx, ihitE = fgNOfPoints, iDhit = iFB;
866 zLast = ((AliMUONHitForRec*)fTrackHits->Last())->GetZ();
867 if (fgTrackReconstructor->GetTrackMethod() == 3 && detElem) {
869 ihitE = detElem->NHitsForRec();
874 for (ihit = ihitB; ihit >= 0 && ihit < ihitE; ihit+=iDhit) {
875 if (fgTrackReconstructor->GetTrackMethod() != 3 || !detElem)
876 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
877 else hit = (AliMUONHitForRec*) detElem->HitsForRec()->UncheckedAt(ihit);
878 if (hit->GetChamberNumber() == ichamb) {
879 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
880 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
881 y = hit->GetBendingCoor();
882 x = hit->GetNonBendingCoor();
883 if (hit->GetBendingReso2() < 0) {
884 // Combined cluster / track finder
885 hit->SetBendingReso2(fgTrackReconstructor->GetBendingResolution()*
886 fgTrackReconstructor->GetBendingResolution());
887 hit->SetNonBendingReso2(fgTrackReconstructor->GetNonBendingResolution()*
888 fgTrackReconstructor->GetNonBendingResolution());
890 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
891 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
893 // windowB = TMath::Min (windowB,5.);
894 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
896 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
897 windowB = TMath::Min (windowB,0.5);
898 windowNonB = TMath::Min (windowNonB,3.);
899 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
900 windowB = TMath::Min (windowB,1.5);
901 windowNonB = TMath::Min (windowNonB,3.);
902 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
903 windowB = TMath::Min (windowB,4.);
904 windowNonB = TMath::Min (windowNonB,6.);
910 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
911 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
912 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
914 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
915 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
919 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
920 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
921 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
922 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
923 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
924 // hit->GetTrackRefSignal() == 1) { // just for test
925 // Vector of measurements and covariance matrix
926 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
927 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
928 // Adjust position: for multiple hits in the chamber or misalignment (Z as a function of X or Y)
929 //AliWarning(Form(" *** adjust %f %f ", zEnd, hit->GetZ()));
931 *fTrackPar = *fTrackParNew;
932 ParPropagation(zEnd);
933 WeightPropagation(zEnd, kTRUE);
934 fPosition = fPositionNew;
935 *fTrackPar = *fTrackParNew;
937 *fCovariance = *fWeight;
938 if (fCovariance->Determinant() != 0) {
940 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
942 AliWarning(" Determinant fCovariance=0:" );
948 pointWeight(0,0) = 1/hit->GetBendingReso2();
949 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
950 TryPoint(point,pointWeight,trackPar,dChi2);
951 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
952 // if (TMath::Sign(1.,(trackPar)(4,0)*(*fTrackPar)(4,0)) < 0) continue; // change of sign
955 //if (nHitsOK > -1) {
957 // Save current members
958 saveWeight = *fWeight;
959 savePosition = fPosition;
960 // temporary storage for the current track
962 trackParTmp = trackPar;
963 pointWeightTmp = pointWeight;
965 if (fgDebug > 0) cout << " Added point: " << x << " " << y << " " << dChi2 << endl;
967 // branching: create a new track
968 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
969 nRecTracks = fgTrackReconstructor->GetNRecTracks();
970 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
972 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
973 if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNmbTrackHits << " " << nRecTracks << endl;
974 trackK->fRecover = 0;
975 *(trackK->fTrackPar) = trackPar;
976 *(trackK->fWeight) += pointWeight;
977 trackK->fChi2 += dChi2;
980 *(trackK->fCovariance) = *(trackK->fWeight);
981 if (trackK->fCovariance->Determinant() != 0) {
983 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
985 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
987 // Add filtered matrices for the smoother
989 if (nHitsOK > 2) { // check for position adjustment
990 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
991 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
992 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
993 RemoveMatrices(trackK);
994 AliError(Form(" *** Position adjustment 1: %f %f", hit->GetZ(), (*trackK->fSteps)[i]));
999 AddMatrices (trackK, dChi2, hit);
1001 // Mark hits as being on 2 tracks
1002 for (Int_t i=0; i<fNmbTrackHits; i++) {
1003 hitLoop = (AliMUONHitForRec*) ((*fTrackHits)[i]);
1004 //AZ hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
1007 cout << hitLoop->GetChamberNumber() << " ";
1008 cout << hitLoop->GetBendingCoor() << " ";
1009 cout << hitLoop->GetNonBendingCoor() << " ";
1010 cout << hitLoop->GetZ() << " " << " ";
1011 cout << hitLoop->GetTrackRefSignal() << " " << " ";
1012 cout << hitLoop->GetTTRTrack() << endl;
1013 printf(" ** %d %10.4f %10.4f %10.4f %d %d \n",
1014 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
1015 hitLoop->GetNonBendingCoor(), hitLoop->GetZ(),
1016 hitLoop->GetTrackRefSignal(), hitLoop->GetTTRTrack());
1020 trackK->fTrackHits->Add(hit); // add hit
1021 trackK->fNmbTrackHits ++;
1022 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
1025 trackK->fTrackDir = 1;
1026 trackK->fBPFlag = kTRUE;
1031 } else break; // different chamber
1032 } // for (ihit=currIndx;
1035 *fTrackPar = trackParTmp;
1036 *fWeight = saveWeight;
1037 *fWeight += pointWeightTmp;
1038 fChi2 += dChi2Tmp; // Chi2
1039 fPosition = savePosition;
1040 // Add filtered matrices for the smoother
1041 if (fTrackDir > 0) {
1042 for (Int_t i=fNSteps-1; i>=0; i--) {
1043 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
1044 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
1045 RemoveMatrices(this);
1046 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
1049 } // for (Int_t i=fNSteps-1;
1050 AddMatrices (this, dChi2Tmp, hitAdd);
1053 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1054 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1057 } // if (fTrackDir > 0)
1062 //__________________________________________________________________________
1063 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1065 /// Adds a measurement point (modifies track parameters and computes
1068 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1069 TMatrixD wu = *fWeight;
1070 wu += pointWeight; // W+U
1071 trackParTmp = point;
1072 trackParTmp -= *fTrackParNew; // m-p
1073 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1074 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1075 right += right1; // U(m-p) + (W+U)p
1077 // check whether the Invert method returns flag if matrix cannot be inverted,
1078 // and do not calculate the Determinant in that case !!!!
1079 if (wu.Determinant() != 0) {
1081 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1083 AliWarning(" Determinant wu=0:");
1085 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1087 right1 = trackParTmp;
1088 right1 -= point; // p'-m
1089 point = trackParTmp;
1090 point -= *fTrackParNew; // p'-p
1091 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1092 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1094 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1095 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1096 dChi2 += value(0,0);
1100 //__________________________________________________________________________
1101 void AliMUONTrackK::MSThin(Int_t sign)
1103 /// Adds multiple scattering in a thin layer (only angles are affected)
1104 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1106 // check whether the Invert method returns flag if matrix cannot be inverted,
1107 // and do not calculate the Determinant in that case !!!!
1108 if (fWeight->Determinant() != 0) {
1110 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1112 AliWarning(" Determinant fWeight=0:");
1115 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1116 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1117 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1118 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1119 velo = 1; // relativistic
1120 path = TMath::Abs(fgTrackReconstructor->GetChamberThicknessInX0()/cosAlph/cosBeta); // path length
1121 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1123 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1124 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1126 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1130 //__________________________________________________________________________
1131 void AliMUONTrackK::StartBack(void)
1133 /// Starts backpropagator
1137 for (Int_t i=0; i<fgkSize; i++) {
1138 for (Int_t j=0; j<fgkSize; j++) {
1139 if (j==i) (*fWeight)(i,i) /= 100;
1140 //if (j==i) (*fWeight)(i,i) /= fNmbTrackHits*fNmbTrackHits;
1141 else (*fWeight)(j,i) = 0;
1144 // Sort hits on track in descending order in abs(z)
1145 SortHits(0, fTrackHits);
1148 //__________________________________________________________________________
1149 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1151 /// Sort hits in Z if the seed segment in the last but one station
1152 /// (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1154 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1155 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1156 Int_t i = 1, entries = array->GetEntriesFast();
1157 for ( ; i<entries; i++) {
1159 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1161 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1162 if (z < zmax) break;
1164 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1168 for (Int_t j=0; j<=(i-1)/2; j++) {
1169 TObject *hit = array->UncheckedAt(j);
1170 array->AddAt(array->UncheckedAt(i-j),j);
1171 array->AddAt(hit,i-j);
1173 if (fgDebug >= 10) {
1174 for (i=0; i<entries; i++)
1175 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1176 cout << " - Sort" << endl;
1180 //__________________________________________________________________________
1181 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1183 /// Set vector of Geant3 parameters pointed to by "VGeant3"
1184 /// from track parameters
1186 VGeant3[0] = (*fTrackParNew)(1,0); // X
1187 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1188 VGeant3[2] = fPositionNew; // Z
1189 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1190 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1191 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1192 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1195 //__________________________________________________________________________
1196 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1198 /// Get track parameters from vector of Geant3 parameters pointed
1201 fPositionNew = VGeant3[2]; // Z
1202 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1203 (*fTrackParNew)(1,0) = VGeant3[0]; // X
1204 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1205 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1206 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1209 //__________________________________________________________________________
1210 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1212 /// Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1215 AliWarning(Form(" *** Too high Chi2: %f ", fChi2));
1218 if (iChi2 == 0) fChi2 = fNmbTrackHits + (500.-fChi2)/501;
1219 else fChi2 = 500 - (fChi2-fNmbTrackHits)*501;
1222 //__________________________________________________________________________
1223 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1225 /// "Compare" function to sort with decreasing "track quality".
1226 /// Returns +1 (0, -1) if quality of current track
1227 /// is smaller than (equal to, larger than) quality of trackK
1229 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1230 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1234 //__________________________________________________________________________
1235 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1237 /// Check whether or not to keep current track
1238 /// (keep, if it has less than half of common hits with track0)
1239 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1240 AliMUONHitForRec *hit0, *hit1;
1243 nHits0 = track0->fNmbTrackHits;
1244 nTrackHits2 = fNmbTrackHits/2;
1246 for (i=0; i<nHits0; i++) {
1247 // Check if hit belongs to several tracks
1248 hit0 = (AliMUONHitForRec*) (*track0->fTrackHits)[i];
1249 if (hit0->GetNTrackHits() == 1) continue;
1250 for (j=0; j<fNmbTrackHits; j++) {
1251 hit1 = (AliMUONHitForRec*) (*fTrackHits)[j];
1252 if (hit1->GetNTrackHits() == 1) continue;
1255 if (hitsInCommon >= nTrackHits2) return kFALSE;
1263 //__________________________________________________________________________
1264 void AliMUONTrackK::Kill(void)
1266 /// Kill track candidate
1267 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1270 //__________________________________________________________________________
1271 void AliMUONTrackK::FillMUONTrack(void)
1273 /// Compute track parameters at hit positions (as for AliMUONTrack)
1275 // Set number of hits per track
1276 SetNTrackHits(fNmbTrackHits);
1280 // Set track parameters at vertex
1281 AliMUONTrackParam trackParam;
1282 SetTrackParam(&trackParam, fTrackPar, fPosition);
1283 SetTrackParamAtVertex(&trackParam);
1285 // Set track parameters at hits
1286 for (Int_t i = fNmbTrackHits-1; i>=0; i--) {
1287 if ((*fChi2Smooth)[i] < 0) {
1288 // Propagate through last chambers
1289 trackParam.ExtrapToZ(((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1292 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1294 AddTrackParamAtHit(&trackParam);
1295 // Fill array of HitForRec's
1296 AddHitForRecAtHit((AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1300 //__________________________________________________________________________
1301 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1303 /// Fill AliMUONTrackParam object
1305 trackParam->SetBendingCoor((*par)(0,0));
1306 trackParam->SetNonBendingCoor((*par)(1,0));
1307 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1308 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1309 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1310 trackParam->SetZ(z);
1313 //__________________________________________________________________________
1314 void AliMUONTrackK::Branson(void)
1316 /// Propagates track to the vertex thru absorber using Branson correction
1317 /// (makes use of the AliMUONTrackParam class)
1319 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1320 AliMUONTrackParam trackParam = AliMUONTrackParam();
1322 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1323 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1324 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1325 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1326 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1327 trackParam->SetZ(fPosition);
1329 SetTrackParam(&trackParam, fTrackPar, fPosition);
1331 trackParam.ExtrapToVertex(Double_t(0.), Double_t(0.), Double_t(0.));
1332 //trackParam.ExtrapToVertex();
1334 (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1335 (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1336 (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1337 (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1338 (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1339 fPosition = trackParam.GetZ();
1340 //delete trackParam;
1341 if (fgDebug > 0) cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1343 // Get covariance matrix
1344 *fCovariance = *fWeight;
1345 if (fCovariance->Determinant() != 0) {
1347 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1349 AliWarning(" Determinant fCovariance=0:");
1353 //__________________________________________________________________________
1354 void AliMUONTrackK::GoToZ(Double_t zEnd)
1356 /// Propagates track to given Z
1358 ParPropagation(zEnd);
1359 MSThin(1); // multiple scattering in the chamber
1360 WeightPropagation(zEnd, kFALSE);
1361 fPosition = fPositionNew;
1362 *fTrackPar = *fTrackParNew;
1365 //__________________________________________________________________________
1366 void AliMUONTrackK::GoToVertex(Int_t iflag)
1369 /// Propagates track to the vertex
1370 /// All material constants are taken from AliRoot
1372 static Double_t x01[5] = { 24.282, // C
1377 // inner part theta < 3 degrees
1378 static Double_t x02[5] = { 30413, // Air
1383 // z positions of the materials inside the absober outer part theta > 3 degres
1384 static Double_t zPos[10] = {-90, -105, -315, -443, -468};
1386 Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
1387 AliMUONHitForRec *hit;
1388 AliMUONRawCluster *clus;
1389 TClonesArray *rawclusters;
1391 // First step to the rear end of the absorber
1392 Double_t zRear = -503;
1394 Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1396 // Go through absorber
1397 pOld = 1/(*fTrackPar)(4,0);
1398 Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1399 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1400 r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
1402 Double_t p0, cos25, cos60;
1403 if (!iflag) goto vertex;
1405 for (Int_t i=4; i>=0; i--) {
1406 ParPropagation(zPos[i]);
1407 WeightPropagation(zPos[i], kFALSE);
1408 dZ = TMath::Abs (fPositionNew-fPosition);
1409 if (r0Norm > 1) x0 = x01[i];
1411 MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
1412 fPosition = fPositionNew;
1413 *fTrackPar = *fTrackParNew;
1414 r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1415 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1416 r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
1418 // Correct momentum for energy losses
1419 pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
1421 cos25 = TMath::Cos(2.5/180*TMath::Pi());
1422 cos60 = TMath::Cos(6.0/180*TMath::Pi());
1423 for (Int_t j=0; j<1; j++) {
1427 deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1429 deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1433 deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1435 deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1443 deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1445 deltaP = 3.0643 + 0.01346*p0;
1451 deltaP = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1453 deltaP = 2.407 + 0.00702*p0;
1462 deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1464 deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1471 deltaP = 2.209 + 0.800e-2*p0;
1473 deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1483 deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1485 deltaP = 3.0714 + 0.011767 * p0;
1490 deltaP = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1492 deltaP = 2.6069 + 0.0051705 * p0;
1498 p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
1500 (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1504 ParPropagation((Double_t)0.);
1505 WeightPropagation((Double_t)0., kFALSE);
1506 fPosition = fPositionNew;
1507 //*fTrackPar = *fTrackParNew;
1508 // Add vertex as a hit
1509 TMatrixD pointWeight(fgkSize,fgkSize);
1510 TMatrixD point(fgkSize,1);
1511 TMatrixD trackParTmp = point;
1512 point(0,0) = 0; // vertex coordinate - should be taken somewhere
1513 point(1,0) = 0; // vertex coordinate - should be taken somewhere
1514 pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1515 pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1516 TryPoint(point,pointWeight,trackParTmp,dChi2);
1517 *fTrackPar = trackParTmp;
1518 *fWeight += pointWeight;
1519 fChi2 += dChi2; // Chi2
1520 if (fgDebug < 0) return; // no output
1522 cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNmbTrackHits << endl;
1523 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1524 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1525 printf ("%5d", hit->GetChamberNumber());
1529 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1530 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1531 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1532 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1533 printf ("%5d", fgHitForRec->IndexOf(hit));
1537 if (fgTrackReconstructor->GetRecTrackRefHits()) {
1538 // from track ref. hits
1539 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1540 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1541 cout << hit->GetTTRTrack() + hit->GetTrackRefSignal()*10000 << " ";
1544 // from raw clusters
1545 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1546 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1547 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1548 Int_t index = -hit->GetHitNumber() / 100000;
1549 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1550 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1552 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1553 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1555 printf ("%5d", clus->GetTrack(1)%10000000);
1558 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1559 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1560 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1561 Int_t index = -hit->GetHitNumber() / 100000;
1562 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1563 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1565 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1566 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1568 if (clus->GetTrack(2) != -1) printf ("%5d", clus->GetTrack(2)%10000000);
1569 else printf ("%5s", " ");
1573 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1574 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1575 cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1576 //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHits)[i1]))) << " ";
1579 for (Int_t i1=0; i1<fNmbTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1581 cout << "---------------------------------------------------" << endl;
1583 // Get covariance matrix
1584 /* Not needed - covariance matrix is not interesting to anybody
1585 *fCovariance = *fWeight;
1586 if (fCovariance->Determinant() != 0) {
1588 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1590 AliWarning(" Determinant fCovariance=0:" );
1595 //__________________________________________________________________________
1596 void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
1598 /// Adds multiple scattering in a thick layer for linear propagation
1600 Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1601 Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1602 Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1604 sinBeta = TMath::Sin((*fTrackPar)(3,0));
1605 Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1606 Double_t momentum = 1/(*fTrackPar)(4,0);
1607 Double_t velo = 1; // relativistic velocity
1608 Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
1610 // Projected scattering angle
1611 Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0));
1612 Double_t theta02 = theta0*theta0;
1613 Double_t dl2 = step*step/2*theta02;
1614 Double_t dl3 = dl2*step*2/3;
1617 Double_t dYdT = 1/cosAlph;
1618 Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1619 Double_t dXdT = tanAlph*tanBeta;
1620 //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1621 Double_t dXdB = 1/cosBeta;
1622 Double_t dAdT = 1/cosBeta;
1623 Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1625 // Get covariance matrix
1626 *fCovariance = *fWeight;
1627 if (fCovariance->Determinant() != 0) {
1628 // fCovariance->Invert();
1630 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1632 AliWarning(" Determinant fCovariance=0:" );
1635 (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1636 (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1637 (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1638 (*fCovariance)(3,3) += theta02*step; // <bb>
1640 (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1641 (*fCovariance)(1,0) = (*fCovariance)(0,1);
1643 (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1644 (*fCovariance)(2,0) = (*fCovariance)(0,2);
1646 (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1647 (*fCovariance)(3,0) = (*fCovariance)(0,3);
1649 (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
1650 (*fCovariance)(2,1) = (*fCovariance)(1,2);
1652 (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1653 (*fCovariance)(3,1) = (*fCovariance)(1,3);
1655 (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1656 (*fCovariance)(3,2) = (*fCovariance)(2,3);
1658 // Get weight matrix
1659 *fWeight = *fCovariance;
1660 if (fWeight->Determinant() != 0) {
1662 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1664 AliWarning(" Determinant fWeight=0:");
1668 //__________________________________________________________________________
1669 Bool_t AliMUONTrackK::Recover(void)
1671 /// Adds new failed track(s) which can be tried to be recovered
1673 TClonesArray *trackPtr;
1674 AliMUONTrackK *trackK;
1676 if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
1677 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1679 // Remove hit with the highest chi2
1682 for (Int_t i=0; i<fNmbTrackHits; i++) {
1683 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1684 printf("%10.4f", chi2);
1687 for (Int_t i=0; i<fNmbTrackHits; i++) {
1688 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
1692 Double_t chi2max = 0;
1694 for (Int_t i=0; i<fNmbTrackHits; i++) {
1695 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1696 if (chi2 < chi2max) continue;
1700 //if (chi2max < 10) return kFALSE; // !!!
1701 //if (chi2max < 25) imax = fNmbTrackHits - 1;
1702 if (chi2max < 15) imax = fNmbTrackHits - 1; // discard the last point
1703 // Check if the outlier is not from the seed segment
1704 AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
1705 if (skipHit == fStartSegment->GetHitForRec1() || skipHit == fStartSegment->GetHitForRec2()) {
1706 //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1707 return kFALSE; // to be changed probably
1710 // Make a copy of track hit collection
1711 TObjArray *hits = new TObjArray(*fTrackHits);
1715 // Hits after the found one will be removed
1716 if (GetStation0() == 3 && skipHit->GetChamberNumber() >= 7) {
1717 SortHits(1, fTrackHits); // unsort hits
1718 imax = fTrackHits->IndexOf(skipHit);
1720 Int_t nTrackHits = fNmbTrackHits;
1721 for (Int_t i=imax+1; i<nTrackHits; i++) {
1722 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
1723 fTrackHits->Remove(hit);
1724 hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit
1728 // Check if the track candidate doesn't exist yet
1729 if (ExistDouble()) { delete hits; return kFALSE; }
1731 //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1734 nRecTracks = fgTrackReconstructor->GetNRecTracks();
1735 skipHit = (AliMUONHitForRec*) ((*fTrackHits)[fNmbTrackHits-1]);
1736 // Remove all saved steps and smoother matrices after the skipped hit
1737 RemoveMatrices(skipHit->GetZ());
1739 //AZ(z->-z) if (skipHit->GetZ() > fStartSegment->GetHitForRec2()->GetZ() || !fNSteps) {
1740 if (TMath::Abs(skipHit->GetZ()) > TMath::Abs(fStartSegment->GetHitForRec2()->GetZ()) || !fNSteps) {
1741 // Propagation toward high Z or skipped hit next to segment -
1742 // start track from segment
1743 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
1744 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1745 trackK->fRecover = 1;
1746 trackK->fSkipHit = skipHit;
1747 trackK->fNmbTrackHits = fNmbTrackHits;
1748 delete trackK->fTrackHits; // not efficient ?
1749 trackK->fTrackHits = new TObjArray(*fTrackHits);
1750 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1754 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1756 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1757 //AZ(z->-z) trackK->fTrackDir = -1;
1758 trackK->fTrackDir = 1;
1759 trackK->fRecover = 1;
1760 trackK->fSkipHit = skipHit;
1761 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1763 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1764 CreateMatrix(trackK->fParFilter);
1766 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1767 trackK->fParFilter->Last()->SetUniqueID(1);
1768 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1769 iD = trackK->fCovFilter->Last()->GetUniqueID();
1771 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1772 CreateMatrix(trackK->fCovFilter);
1774 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1775 trackK->fCovFilter->Last()->SetUniqueID(1);
1776 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1777 if (trackK->fWeight->Determinant() != 0) {
1779 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1781 AliWarning(" Determinant fWeight=0:");
1783 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1785 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1786 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1790 //__________________________________________________________________________
1791 void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1793 /// Adds matrices for the smoother and keep Chi2 for the point
1794 /// Track parameters
1795 //trackK->fParFilter->Last()->Print();
1796 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1798 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1799 CreateMatrix(trackK->fParFilter);
1802 *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1803 trackK->fParFilter->Last()->SetUniqueID(iD);
1805 cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1806 //trackK->fTrackPar->Print();
1807 //trackK->fTrackParNew->Print();
1808 trackK->fParFilter->Last()->Print();
1809 cout << " Add matrices" << endl;
1812 *(trackK->fCovariance) = *(trackK->fWeight);
1813 if (trackK->fCovariance->Determinant() != 0) {
1815 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1817 AliWarning(" Determinant fCovariance=0:");
1819 iD = trackK->fCovFilter->Last()->GetUniqueID();
1821 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1822 CreateMatrix(trackK->fCovFilter);
1825 *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1826 trackK->fCovFilter->Last()->SetUniqueID(iD);
1828 // Save Chi2-increment for point
1829 Int_t indx = trackK->fTrackHits->IndexOf(hitAdd);
1830 if (indx < 0) indx = fNmbTrackHits;
1831 if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10);
1832 trackK->fChi2Array->AddAt(dChi2,indx);
1835 //__________________________________________________________________________
1836 void AliMUONTrackK::CreateMatrix(TObjArray *objArray) const
1838 /// Create new matrix and add it to TObjArray
1840 TMatrixD *matrix = (TMatrixD*) objArray->First();
1841 TMatrixD *tmp = new TMatrixD(*matrix);
1842 objArray->AddAtAndExpand(tmp,objArray->GetLast());
1843 //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1846 //__________________________________________________________________________
1847 void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1849 /// Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1851 for (Int_t i=fNSteps-1; i>=0; i--) {
1852 if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1853 if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1854 RemoveMatrices(this);
1855 } // for (Int_t i=fNSteps-1;
1858 //__________________________________________________________________________
1859 void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1861 /// Remove last saved matrices and steps in the smoother part
1864 Int_t i = trackK->fNSteps;
1867 // Delete only matrices not shared by several tracks
1868 id = trackK->fParExtrap->Last()->GetUniqueID();
1870 trackK->fParExtrap->Last()->SetUniqueID(id-1);
1871 trackK->fParExtrap->RemoveAt(i);
1873 else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1874 id = fParFilter->Last()->GetUniqueID();
1876 trackK->fParFilter->Last()->SetUniqueID(id-1);
1877 trackK->fParFilter->RemoveAt(i);
1879 else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1880 id = trackK->fCovExtrap->Last()->GetUniqueID();
1882 trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1883 trackK->fCovExtrap->RemoveAt(i);
1885 else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1886 id = trackK->fCovFilter->Last()->GetUniqueID();
1888 trackK->fCovFilter->Last()->SetUniqueID(id-1);
1889 trackK->fCovFilter->RemoveAt(i);
1891 else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1892 id = trackK->fJacob->Last()->GetUniqueID();
1894 trackK->fJacob->Last()->SetUniqueID(id-1);
1895 trackK->fJacob->RemoveAt(i);
1897 else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1900 //__________________________________________________________________________
1901 Bool_t AliMUONTrackK::Smooth(void)
1904 Int_t ihit = fNmbTrackHits - 1;
1905 AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1906 fChi2Smooth = new TArrayD(fNmbTrackHits);
1907 fChi2Smooth->Reset(-1);
1909 fParSmooth = new TObjArray(15);
1910 fParSmooth->Clear();
1913 cout << " ******** Enter Smooth " << endl;
1914 cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl;
1916 for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1918 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();}
1920 for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHits)[i])->GetZ() << " ";
1924 // Find last point corresponding to the last hit
1925 Int_t iLast = fNSteps - 1;
1926 for ( ; iLast>=0; iLast--) {
1927 //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ()) break;
1928 if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ())) break;
1931 TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1933 TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1934 TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1935 TMatrixD tmpPar = *fTrackPar;
1936 //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print();
1939 Double_t chi2max = 0;
1940 for (Int_t i=iLast+1; i>0; i--) {
1941 if (i == iLast + 1) goto L33; // temporary fix
1943 // Smoother gain matrix
1944 weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1945 if (weight.Determinant() != 0) {
1947 mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1949 AliWarning(" Determinant weight=0:");
1952 tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
1953 gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
1954 //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
1956 // Smoothed parameter vector
1957 //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
1958 parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
1959 tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
1960 tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
1963 // Smoothed covariance
1964 covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1965 weight = TMatrixD(TMatrixD::kTransposed,gain);
1966 tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
1967 covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
1968 covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
1970 // Check if there was a measurement at given z
1972 for ( ; ihit>=0; ihit--) {
1973 hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1974 if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
1975 //AZ(z->-z) else if (ihit < fNmbTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
1976 else if (ihit < fNmbTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
1978 if (!found) continue; // no measurement - skip the rest
1979 else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
1980 if (ihit == 0) continue; // the first hit - skip the rest
1983 // Smoothed residuals
1985 tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
1986 tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
1988 cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
1989 cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
1991 // Cov. matrix of smoothed residuals
1993 tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
1994 tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
1995 tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
1996 tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
1998 // Calculate Chi2 of smoothed residuals
1999 if (tmp.Determinant() != 0) {
2001 mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2003 AliWarning(" Determinant tmp=0:");
2005 TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
2006 TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
2007 if (fgDebug > 1) chi2.Print();
2008 (*fChi2Smooth)[ihit] = chi2(0,0);
2009 if (chi2(0,0) > chi2max) chi2max = chi2(0,0);
2011 if (chi2(0,0) < 0) {
2013 AliError(Form(" *** chi2 < 0: %d %d ", i, iLast));
2015 // Save smoothed parameters
2016 TMatrixD *par = new TMatrixD(parSmooth);
2017 fParSmooth->AddAtAndExpand(par, ihit);
2019 } // for (Int_t i=iLast+1;
2021 //if (chi2max > 16) {
2022 //if (chi2max > 25) {
2023 //if (chi2max > 50) {
2024 //if (chi2max > 100) {
2025 if (chi2max > fgkChi2max) {
2026 //if (Recover()) DropBranches();
2034 //__________________________________________________________________________
2035 void AliMUONTrackK::Outlier()
2037 /// Adds new track with removed hit having the highest chi2
2040 cout << " ******** Enter Outlier " << endl;
2041 for (Int_t i=0; i<fNmbTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
2043 for (Int_t i=0; i<fNmbTrackHits; i++) {
2044 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
2049 Double_t chi2max = 0;
2051 for (Int_t i=0; i<fNmbTrackHits; i++) {
2052 if ((*fChi2Smooth)[i] < chi2max) continue;
2053 chi2max = (*fChi2Smooth)[i];
2056 // Check if the outlier is not from the seed segment
2057 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
2058 if (hit == fStartSegment->GetHitForRec1() || hit == fStartSegment->GetHitForRec2()) return; // to be changed probably
2060 // Check for missing station
2063 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--;
2064 } else if (imax == fNmbTrackHits-1) {
2065 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2067 else if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2068 if (!ok) { Recover(); return; } // try to recover track
2069 //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; }
2071 // Remove saved steps and smoother matrices after the outlier
2072 RemoveMatrices(hit->GetZ());
2074 // Check for possible double track candidates
2075 //if (ExistDouble(hit)) return;
2077 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2078 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2080 AliMUONTrackK *trackK = 0;
2081 if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2082 // start track from segment
2083 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
2084 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2085 trackK->fRecover = 2;
2086 trackK->fSkipHit = hit;
2087 trackK->fNmbTrackHits = fNmbTrackHits;
2089 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(0);
2090 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2091 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(1);
2092 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2093 delete trackK->fTrackHits; // not efficient ?
2094 trackK->fTrackHits = new TObjArray(*fTrackHits);
2095 for (Int_t i = 0; i < fNmbTrackHits; i++) {
2096 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
2097 hit->SetNTrackHits(hit->GetNTrackHits()+1);
2100 if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHits);
2101 if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2104 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2106 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2107 trackK->fTrackDir = 1;
2108 trackK->fRecover = 2;
2109 trackK->fSkipHit = hit;
2110 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2112 trackK->fParFilter->Last()->SetUniqueID(iD-1);
2113 CreateMatrix(trackK->fParFilter);
2115 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2116 trackK->fParFilter->Last()->SetUniqueID(1);
2117 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2118 iD = trackK->fCovFilter->Last()->GetUniqueID();
2120 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2121 CreateMatrix(trackK->fCovFilter);
2123 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2124 trackK->fCovFilter->Last()->SetUniqueID(1);
2125 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2126 if (trackK->fWeight->Determinant() != 0) {
2128 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2130 AliWarning(" Determinant fWeight=0:");
2132 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2134 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2135 if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2138 //__________________________________________________________________________
2139 Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2141 /// Return Chi2 at point
2142 return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2146 //__________________________________________________________________________
2147 void AliMUONTrackK::Print(FILE *lun) const
2149 /// Print out track information
2152 AliMUONHitForRec *hit = 0;
2153 if (fgTrackReconstructor->GetRecTrackRefHits()) {
2154 // from track ref. hits
2155 for (Int_t j=0; j<fNmbTrackHits; j++) {
2156 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(j);
2157 if (hit->GetTTRTrack() > 1) { flag = 0; break; }
2159 for (Int_t j=0; j<fNmbTrackHits; j++) {
2160 printf("%10.4f", GetChi2PerPoint(j));
2161 if (GetChi2PerPoint(j) > -0.1) {
2162 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(j);
2163 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(j));
2164 fprintf(lun, "%3d %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack(), flag);
2169 // from raw clusters
2170 AliMUONRawCluster *clus = 0;
2171 TClonesArray *rawclusters = 0;
2172 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2173 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2174 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2175 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2176 if (TMath::Abs(clus->GetTrack(1)-1) < 2) {
2177 if (clus->GetTrack(2)) flag = 2;
2180 if (clus->GetTrack(2) && TMath::Abs(clus->GetTrack(2)-1) < 2) {
2187 Int_t sig[2]={1,1}, tid[2]={0};
2188 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2189 if (GetChi2PerPoint(i1) < -0.1) continue;
2190 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2191 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2192 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2193 for (Int_t j=0; j<2; j++) {
2194 tid[j] = clus->GetTrack(j+1) - 1;
2195 if (clus->GetTrack(j+1) < 0) { sig[j] = 0; tid[j] = 999; }
2197 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(i1));
2198 if (!(clus->GetTrack(2))) fprintf(lun, "%3d %3d", sig[0], tid[0]); // simple cluster
2199 else { // track overlap
2200 fprintf(lun, "%3d %3d", TMath::Max(sig[0],sig[1]), TMath::Min(tid[0],tid[1]));
2201 //if (tid[0] < 2) flag *= 2;
2202 //else if (tid[1] < 2) flag *= 3;
2204 fprintf (lun, "%3d \n", flag);
2209 //__________________________________________________________________________
2210 void AliMUONTrackK::DropBranches(Int_t imax, TObjArray *hits)
2212 /// Drop branches downstream of the skipped hit
2214 TClonesArray *trackPtr;
2215 AliMUONTrackK *trackK;
2217 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2218 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2219 Int_t icand = trackPtr->IndexOf(this);
2220 if (!hits) hits = fTrackHits;
2222 // Check if the track candidate doesn't exist yet
2223 for (Int_t i=icand+1; i<nRecTracks; i++) {
2224 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2225 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2226 if (trackK->GetRecover() < 0) continue;
2228 if (trackK->fNmbTrackHits >= imax + 1) {
2229 for (Int_t j=0; j<=imax; j++) {
2230 //if (j != fNmbTrackHits-1 && (*trackK->fTrackHits)[j] != (*fTrackHits)[j]) break;
2231 if ((*trackK->fTrackHits)[j] != (*hits)[j]) break;
2233 if (hits != fTrackHits) {
2234 // Drop all branches downstream the hit (for Recover)
2235 trackK->SetRecover(-1);
2236 if (fgDebug >= 0 )cout << " Recover " << i << endl;
2239 // Check if the removal of the hit breaks the track
2242 if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2243 else if (imax == trackK->fNmbTrackHits-1) continue;
2244 // else if (imax == trackK->fNmbTrackHits-1) {
2245 //if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(trackK->fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2247 else if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2248 if (!ok) trackK->SetRecover(-1);
2250 } // for (Int_t j=0;
2252 } // for (Int_t i=0;
2255 //__________________________________________________________________________
2256 void AliMUONTrackK::DropBranches(AliMUONSegment *segment)
2258 /// Drop all candidates with the same seed segment
2260 TClonesArray *trackPtr;
2261 AliMUONTrackK *trackK;
2263 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2264 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2265 Int_t icand = trackPtr->IndexOf(this);
2267 for (Int_t i=icand+1; i<nRecTracks; i++) {
2268 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2269 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2270 if (trackK->GetRecover() < 0) continue;
2271 if (trackK->fStartSegment == segment) trackK->SetRecover(-1);
2273 if (fgDebug >= 0) cout << " Drop segment " << endl;
2276 //__________________________________________________________________________
2277 AliMUONHitForRec* AliMUONTrackK::GetHitLastOk(void)
2279 /// Return the hit where track stopped
2281 if (!fNSteps) return (AliMUONHitForRec*)((*fTrackHits)[1]);
2285 //__________________________________________________________________________
2286 Int_t AliMUONTrackK::GetStation0(void)
2288 /// Return seed station number
2289 return fStartSegment->GetHitForRec1()->GetChamberNumber() / 2;
2292 //__________________________________________________________________________
2293 Bool_t AliMUONTrackK::ExistDouble(AliMUONHitForRec *hit)
2295 /// Check if the track will make a double after outlier removal
2297 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2298 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2299 TObjArray *hitArray = new TObjArray(*fTrackHits);
2300 TObjArray *hitArray1 = new TObjArray(*hitArray);
2301 hitArray1->Remove(hit);
2302 hitArray1->Compress();
2304 Bool_t same = kFALSE;
2305 for (Int_t i=0; i<nRecTracks; i++) {
2306 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2307 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2308 if (trackK == this) continue;
2309 if (trackK->fNmbTrackHits == fNmbTrackHits || trackK->fNmbTrackHits == fNmbTrackHits-1) {
2310 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2312 if (trackK->fNmbTrackHits == fNmbTrackHits) {
2313 for (Int_t j=0; j<fNmbTrackHits; j++) {
2314 if (hits->UncheckedAt(j) != hitArray->UncheckedAt(j)) { same = kFALSE; break; }
2316 if (same) { delete hits; break; }
2317 if (trackK->fSkipHit) {
2318 TObjArray *hits1 = new TObjArray(*hits);
2319 if (hits1->Remove(trackK->fSkipHit) > 0) {
2322 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2323 if (hits1->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2325 if (same) { delete hits1; break; }
2330 // Check with removed outlier
2332 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2333 if (hits->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2335 if (same) { delete hits; break; }
2339 } // for (Int_t i=0; i<nRecTracks;
2340 delete hitArray; delete hitArray1;
2341 if (same && fgDebug >= 0) cout << " Same" << endl;
2345 //__________________________________________________________________________
2346 Bool_t AliMUONTrackK::ExistDouble(void)
2348 /// Check if the track will make a double after recovery
2350 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2351 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2353 TObjArray *hitArray = new TObjArray(*fTrackHits);
2354 if (GetStation0() == 3) SortHits(0, hitArray); // sort
2355 //if (GetStation0() == 3) SortHits(1, hitArray); // unsort
2357 Bool_t same = kFALSE;
2358 for (Int_t i=0; i<nRecTracks; i++) {
2359 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2360 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2361 if (trackK == this) continue;
2362 //AZ if (trackK->GetRecover() < 0) continue; //
2363 if (trackK->fNmbTrackHits >= fNmbTrackHits) {
2364 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2365 if (trackK->GetStation0() == 3) SortHits(0, hits); // sort
2366 //if (trackK->GetStation0() == 3) SortHits(1, hits); // unsort
2367 for (Int_t j=0; j<fNmbTrackHits; j++) {
2368 //cout << fNmbTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2369 if (j != fNmbTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break;
2370 if (j == fNmbTrackHits-1) {
2371 if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE;
2372 //if (trackK->fNmbTrackHits > fNmbTrackHits &&
2373 //if (trackK->fSkipHit) cout << ((AliMUONHitForRec*)((*hitArray)[j]))->GetZ() << " " << trackK->fSkipHit->GetZ() << endl;
2375 } // for (Int_t j=0;
2379 } // for (Int_t i=0;