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()
88 /// Default constructor
90 fgTrackReconstructor = NULL; // pointer to event reconstructor
91 fgHitForRec = NULL; // pointer to points
92 fgNOfPoints = 0; // number of points
97 //__________________________________________________________________________
98 AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructor *TrackReconstructor, TClonesArray *hitForRec)
127 if (!TrackReconstructor) return;
128 fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
129 fgHitForRec = hitForRec; // pointer to points
130 fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
132 if (fgTrackReconstructor->GetTrackMethod() == 3) fgCombi = AliMUONEventRecoCombi::Instance();
135 //__________________________________________________________________________
136 AliMUONTrackK::AliMUONTrackK(AliMUONSegment *segment)
137 //: AliMUONTrack(segment, segment, fgTrackReconstructor)
138 : AliMUONTrack(NULL, segment, fgTrackReconstructor),
139 fStartSegment(segment),
143 fTrackHits(new TObjArray(13)),
149 fTrackPar(new TMatrixD(fgkSize,1)),
150 fTrackParNew(new TMatrixD(fgkSize,1)),
151 fCovariance(new TMatrixD(fgkSize,fgkSize)),
152 fWeight(new TMatrixD(fgkSize,fgkSize)),
153 fParExtrap(new TObjArray(15)),
154 fParFilter(new TObjArray(15)),
156 fCovExtrap(new TObjArray(15)),
157 fCovFilter(new TObjArray(15)),
158 fJacob(new TObjArray(15)),
160 fSteps(new TArrayD(15)),
161 fChi2Array(new TArrayD(13)),
164 /// Constructor from a segment
166 AliMUONHitForRec *hit1, *hit2;
167 AliMUONRawCluster *clus;
168 TClonesArray *rawclusters;
170 // Pointers to hits from the segment
171 hit1 = segment->GetHitForRec1();
172 hit2 = segment->GetHitForRec2();
173 hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
174 hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
175 // check sorting in Z
176 if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
178 hit2 = segment->GetHitForRec1();
181 // Fill array of track parameters
182 if (hit1->GetChamberNumber() > 7) {
183 // last tracking station
184 (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
185 (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
186 fPosition = hit1->GetZ(); // z
187 fTrackHits->Add(hit2); // add hit 2
188 fTrackHits->Add(hit1); // add hit 1
189 //AZ(Z->-Z) fTrackDir = -1;
192 // last but one tracking station
193 (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
194 (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
195 fPosition = hit2->GetZ(); // z
196 fTrackHits->Add(hit1); // add hit 1
197 fTrackHits->Add(hit2); // add hit 2
198 //AZ(Z->-Z) fTrackDir = 1;
201 dZ = hit2->GetZ() - hit1->GetZ();
202 dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
203 dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
204 (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
205 if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
206 (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
207 (*fTrackPar)(2,0) -= TMath::Pi();
208 (*fTrackPar)(4,0) = 1/fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()); // 1/Pt
209 (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
210 // Evaluate covariance (and weight) matrix
213 if (fgDebug < 0 ) return;
214 cout << fgTrackReconstructor->GetNRecTracks()-1 << " " << fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()) << " " << 1/(*fTrackPar)(4,0) << " ";
215 if (fgTrackReconstructor->GetRecTrackRefHits()) {
216 // from track ref. hits
217 cout << ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetTTRTrack() << "<-->" << ((AliMUONHitForRec*)((*fTrackHits)[1]))->GetTTRTrack() << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
220 for (Int_t i=0; i<2; i++) {
221 hit1 = (AliMUONHitForRec*) ((*fTrackHits)[i]);
222 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
223 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
224 cout << clus->GetTrack(1);
225 if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
226 if (i == 0) cout << " <--> ";
228 cout << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
232 //__________________________________________________________________________
233 AliMUONTrackK::~AliMUONTrackK()
238 //cout << fNmbTrackHits << endl;
239 for (Int_t i = 0; i < fNmbTrackHits; i++) {
240 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
241 hit->SetNTrackHits(hit->GetNTrackHits()-1);
243 delete fTrackHits; // delete the TObjArray of pointers to TrackHit's
247 delete fTrackPar; delete fTrackParNew; delete fCovariance;
251 if (fSteps) delete fSteps;
252 if (fChi2Array) delete fChi2Array;
253 if (fChi2Smooth) delete fChi2Smooth;
254 if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
255 // Delete only matrices not shared by several tracks
256 if (!fParExtrap) return;
259 for (Int_t i=0; i<fNSteps; i++) {
260 //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1)
261 // fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
262 id = fParExtrap->UncheckedAt(i)->GetUniqueID();
264 fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
265 fParExtrap->RemoveAt(i);
267 //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1)
268 // fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
269 id = fParFilter->UncheckedAt(i)->GetUniqueID();
271 fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
272 fParFilter->RemoveAt(i);
274 //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1)
275 // fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
276 id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
278 fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
279 fCovExtrap->RemoveAt(i);
282 //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1)
283 // fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
284 id = fCovFilter->UncheckedAt(i)->GetUniqueID();
286 fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
287 fCovFilter->RemoveAt(i);
289 //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1)
290 // fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
291 id = fJacob->UncheckedAt(i)->GetUniqueID();
293 fJacob->UncheckedAt(i)->SetUniqueID(id-1);
298 for (Int_t i=0; i<fNSteps; i++) {
299 if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
300 if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
301 if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
302 cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
303 if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
304 if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
307 fParExtrap->Delete(); fParFilter->Delete();
308 fCovExtrap->Delete(); fCovFilter->Delete();
310 delete fParExtrap; delete fParFilter;
311 delete fCovExtrap; delete fCovFilter;
315 //__________________________________________________________________________
316 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
318 /// Assignment operator
321 if(&source == this) return *this;
323 // base class assignement
324 //AZ TObject::operator=(source);
325 AliMUONTrack::operator=(source);
327 fStartSegment = source.fStartSegment;
328 fNmbTrackHits = source.fNmbTrackHits;
329 fChi2 = source.fChi2;
330 fPosition = source.fPosition;
331 fPositionNew = source.fPositionNew;
332 fTrackDir = source.fTrackDir;
333 fBPFlag = source.fBPFlag;
334 fRecover = source.fRecover;
335 fSkipHit = source.fSkipHit;
338 fTrackHits = new TObjArray(*source.fTrackHits);
339 //source.fTrackHits->Dump();
340 //fTrackHits->Dump();
341 for (Int_t i = 0; i < fNmbTrackHits; i++) {
342 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
343 hit->SetNTrackHits(hit->GetNTrackHits()+1);
346 fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
347 fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
348 fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
349 fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
352 fParExtrap = new TObjArray(*source.fParExtrap);
353 fParFilter = new TObjArray(*source.fParFilter);
354 fCovExtrap = new TObjArray(*source.fCovExtrap);
355 fCovFilter = new TObjArray(*source.fCovFilter);
356 fJacob = new TObjArray(*source.fJacob);
357 fSteps = new TArrayD(*source.fSteps);
358 fNSteps = source.fNSteps;
360 if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
364 for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
365 fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
366 fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
367 fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
368 fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
369 fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
374 //__________________________________________________________________________
375 void AliMUONTrackK::EvalCovariance(Double_t dZ)
377 /// Evaluate covariance (and weight) matrix for track candidate
378 Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
381 sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
382 sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
384 (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
386 (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
388 tanA = TMath::Tan((*fTrackPar)(2,0));
389 dAdY = 1/(1+tanA*tanA)/dZ;
390 (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
391 (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
392 (*fWeight)(2,0) = (*fWeight)(0,2);
394 rad = dZ/TMath::Cos((*fTrackPar)(2,0));
395 tanB = TMath::Tan((*fTrackPar)(3,0));
396 dBdX = 1/(1+tanB*tanB)/rad;
398 (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
399 (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
400 (*fWeight)(3,1) = (*fWeight)(1,3);
402 (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
404 // check whether the Invert method returns flag if matrix cannot be inverted,
405 // and do not calculate the Determinant in that case !!!!
406 if (fWeight->Determinant() != 0) {
407 // fWeight->Invert();
409 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
411 AliWarning(" Determinant fWeight=0:");
416 //__________________________________________________________________________
417 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
419 /// Follows track through detector stations
420 Bool_t miss, success;
421 Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
422 Int_t ihit, firstIndx = -1, lastIndx = -1, currIndx = -1, iz0 = -1, iz = -1;
423 Double_t zEnd, dChi2;
424 AliMUONHitForRec *hitAdd, *firstHit = NULL, *lastHit = NULL, *hit;
425 AliMUONRawCluster *clus;
426 TClonesArray *rawclusters;
427 hit = 0; clus = 0; rawclusters = 0;
429 miss = success = kTRUE;
431 //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
432 iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
433 iMin = TMath::Min(ichamEnd,ichamBeg);
434 iMax = TMath::Max(ichamEnd,ichamBeg);
441 if (((AliMUONHitForRec*)fTrackHits->First())->GetChamberNumber() != ichamb) currIndx = 0;
442 } else if (fRecover) {
443 hit = GetHitLastOk();
444 currIndx = fTrackHits->IndexOf(hit);
445 if (currIndx < 0) hit = fStartSegment->GetHitForRec1(); // for station 3
447 ichamb = hit->GetChamberNumber();
448 if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
449 // start from the last point or outlier
450 // remove the skipped hit
451 fTrackHits->Remove(fSkipHit); // remove hit
453 fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
458 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
459 //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHits)[0]))->GetChamberNumber() == 6) ichambOK = 6;
460 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
461 fSkipHit->GetHitNumber() < 0) {
462 iz0 = fgCombi->IZfromHit(fSkipHit);
465 else currIndx = fgHitForRec->IndexOf(fSkipHit);
468 fTrackHits->Compress();
470 } // if (hit == fSkipHit)
471 else if (currIndx < 0) currIndx = fTrackHits->IndexOf(hit);
472 } // else if (fRecover)
474 // Get indices of the 1'st and last hits on the track candidate
475 firstHit = (AliMUONHitForRec*) fTrackHits->First();
476 lastHit = (AliMUONHitForRec*) fTrackHits->Last();
477 if (fgTrackReconstructor->GetTrackMethod() == 3 &&
478 lastHit->GetHitNumber() < 0) iz0 = fgCombi->IZfromHit(lastHit);
480 firstIndx = fgHitForRec->IndexOf(firstHit);
481 lastIndx = fgHitForRec->IndexOf(lastHit);
482 currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
486 if (iz0 < 0) iz0 = iFB;
487 while (ichamb >= iMin && ichamb <= iMax) {
488 // Find the closest hit in Z, not belonging to the current plane
491 if (currIndx < fNmbTrackHits) {
492 hitAdd = (AliMUONHitForRec*) fTrackHits->UncheckedAt(currIndx);
493 zEnd = hitAdd->GetZ();
494 //AZ(z->-z) } else zEnd = -9999;
497 //AZ(Z->-Z) zEnd = -9999;
499 for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
500 hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
501 //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
502 if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
503 zEnd = hitAdd->GetZ();
509 // Combined cluster / track finder
510 if (zEnd > 999 && iFB < 0 && fgTrackReconstructor->GetTrackMethod() == 3) {
512 AliMUONHitForRec hitTmp;
513 for (iz = iz0 - iFB; iz < fgCombi->Nz(); iz++) {
514 if (TMath::Abs(fgCombi->Z(iz)-fPosition) < 0.5) continue;
515 Int_t *pDEatZ = fgCombi->DEatZ(iz);
516 //cout << iz << " " << fgCombi->Z(iz) << endl;
517 zEnd = fgCombi->Z(iz);
519 AliMUONDetElement *detElem = fgCombi->DetElem(pDEatZ[0]);
521 hitAdd->SetChamberNumber(detElem->Chamber());
522 //hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
527 if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
529 // Check if there is a chamber without hits
530 if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
531 if (!Back && zEnd<999) currIndx -= iFB;
533 zEnd = AliMUONConstants::DefaultChamberZ(ichamb);
536 ichamb = hitAdd->GetChamberNumber();
540 if (ichamb<iMin || ichamb>iMax) break;
541 // Check for missing station
543 dChamb = TMath::Abs(ichamb-ichambOK);
544 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
545 Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
546 if (zEnd > 999) dStatMiss++;
548 //if (dStatMiss == 2 && ichambOK/2 != 3 || dStatMiss > 2) { // AZ - missing st. 3
549 // missing station - abandon track
550 //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
552 for (Int_t i1=0; i1<fgNOfPoints; i1++) {
553 cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
554 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
555 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
556 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
557 cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
560 cout << fNmbTrackHits << endl;
561 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
562 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
563 printf(" * %d %10.4f %10.4f %10.4f",
564 hit->GetChamberNumber(), hit->GetBendingCoor(),
565 hit->GetNonBendingCoor(), hit->GetZ());
566 if (fgTrackReconstructor->GetRecTrackRefHits()) {
567 // from track ref. hits
568 printf(" %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack());
571 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
572 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
573 printf("%3d", clus->GetTrack(1)-1);
574 if (clus->GetTrack(2) != 0) printf("%3d \n", clus->GetTrack(2)-1);
578 } // if (fgDebug >= 10)
579 if (fNmbTrackHits>2 && fRecover==0) Recover(); // try to recover track later
581 } // if (dStatMiss > 1)
583 if (endOfProp != 0) break;
585 // propagate to the found Z
587 // Check if track steps into dipole
588 //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
589 if (fPosition<zDipole2 && zEnd>zDipole2) {
590 //LinearPropagation(zDipole2-zBeg);
591 ParPropagation(zDipole2);
592 MSThin(1); // multiple scattering in the chamber
593 WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
594 fPosition = fPositionNew;
595 *fTrackPar = *fTrackParNew;
596 //MagnetPropagation(zEnd);
597 ParPropagation(zEnd);
598 WeightPropagation(zEnd, kTRUE);
599 fPosition = fPositionNew;
601 // Check if track steps out of dipole
602 //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
603 else if (fPosition<zDipole1 && zEnd>zDipole1) {
604 //MagnetPropagation(zDipole1-zBeg);
605 ParPropagation(zDipole1);
606 MSThin(1); // multiple scattering in the chamber
607 WeightPropagation(zDipole1, kTRUE);
608 fPosition = fPositionNew;
609 *fTrackPar = *fTrackParNew;
610 //LinearPropagation(zEnd-zDipole1);
611 ParPropagation(zEnd);
612 WeightPropagation(zEnd, kTRUE);
613 fPosition = fPositionNew;
615 ParPropagation(zEnd);
616 //MSThin(1); // multiple scattering in the chamber
617 if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
618 WeightPropagation(zEnd, kTRUE);
619 fPosition = fPositionNew;
623 if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
624 // recovered track - remove the hit
626 ichamb = fSkipHit->GetChamberNumber();
627 // remove the skipped hit
628 fTrackHits->Remove(fSkipHit);
630 //AZ fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit
633 ichambOK = ((AliMUONHitForRec*)((*fTrackHits)[fNmbTrackHits-1]))->GetChamberNumber();
634 //? if (fgTrackReconstructor->GetTrackMethod() != 3) currIndx = fgHitForRec->IndexOf(fSkipHit);
635 currIndx = fgHitForRec->IndexOf(fSkipHit);
639 // backward propagator
641 TMatrixD pointWeight(fgkSize,fgkSize);
642 TMatrixD point(fgkSize,1);
643 TMatrixD trackParTmp = point;
644 point(0,0) = hitAdd->GetBendingCoor();
645 point(1,0) = hitAdd->GetNonBendingCoor();
646 pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
647 pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
648 TryPoint(point,pointWeight,trackParTmp,dChi2);
649 *fTrackPar = trackParTmp;
650 *fWeight += pointWeight;
651 if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
652 fChi2 += dChi2; // Chi2
653 } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
654 if (ichamb==ichamEnd) break;
657 // forward propagator
658 if (miss || !FindPoint(ichamb, zEnd, currIndx, iFB, hitAdd, iz)) {
660 *fTrackPar = *fTrackParNew;
663 fTrackHits->Add(hitAdd); // add hit
665 hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
667 currIndx = fgHitForRec->IndexOf(hitAdd); // Check
671 if (fgDebug > 0) cout << fNmbTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
672 if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
676 //__________________________________________________________________________
677 void AliMUONTrackK::ParPropagation(Double_t zEnd)
679 /// Propagation of track parameters to zEnd
681 Double_t dZ, step, distance, charge;
682 Double_t vGeant3[7], vGeant3New[7];
683 AliMUONTrackParam trackParam;
686 // First step using linear extrapolation
687 dZ = zEnd - fPosition;
688 fPositionNew = fPosition;
689 *fTrackParNew = *fTrackPar;
690 if (dZ == 0) return; //AZ ???
691 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
692 step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
693 //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
694 charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
695 SetGeantParam(vGeant3,iFB);
696 //fTrackParNew->Print();
700 step = TMath::Abs(step);
701 // Propagate parameters
702 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
703 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
704 distance = zEnd - vGeant3New[2];
705 step *= dZ/(vGeant3New[2]-fPositionNew);
707 } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
709 GetFromGeantParam(vGeant3New,iFB);
710 //fTrackParNew->Print();
712 // Position adjustment (until within tolerance)
713 while (TMath::Abs(distance) > fgkEpsilon) {
714 dZ = zEnd - fPositionNew;
715 iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
716 step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
717 step = TMath::Abs(step);
718 SetGeantParam(vGeant3,iFB);
721 // Propagate parameters
722 trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
723 //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
724 distance = zEnd - vGeant3New[2];
727 if (nTries > fgkTriesMax) AliError(Form(" Too many tries: %d", nTries));
728 } while (distance*iFB < 0);
730 GetFromGeantParam(vGeant3New,iFB);
732 //cout << nTries << endl;
733 //fTrackParNew->Print();
737 //__________________________________________________________________________
738 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
740 /// Propagation of the weight matrix
741 /// W = DtWD, where D is Jacobian
745 TMatrixD jacob(fgkSize,fgkSize);
748 // Save initial and propagated parameters
749 TMatrixD trackPar0 = *fTrackPar;
750 TMatrixD trackParNew0 = *fTrackParNew;
752 // Get covariance matrix
753 *fCovariance = *fWeight;
754 // check whether the Invert method returns flag if matrix cannot be inverted,
755 // and do not calculate the Determinant in that case !!!!
756 if (fCovariance->Determinant() != 0) {
758 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
759 //fCovariance->Print();
761 AliWarning(" Determinant fCovariance=0:");
764 // Loop over parameters to find change of the propagated vs initial ones
765 for (i=0; i<fgkSize; i++) {
766 dPar = TMath::Sqrt((*fCovariance)(i,i));
767 *fTrackPar = trackPar0;
768 if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
769 (*fTrackPar)(i,0) += dPar;
770 ParPropagation(zEnd);
771 for (j=0; j<fgkSize; j++) {
772 jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
776 //trackParNew0.Print();
777 //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
779 TMatrixD jacob0 = jacob;
780 if (jacob.Determinant() != 0) {
783 AliWarning(" Determinant jacob=0:");
785 TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
786 *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
788 // Restore initial and propagated parameters
789 *fTrackPar = trackPar0;
790 *fTrackParNew = trackParNew0;
793 if (!smooth) return; // do not use smoother
794 if (fTrackDir < 0) return; // only for propagation towards int. point
795 TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
796 fParExtrap->Add(tmp);
798 tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
799 fParFilter->Add(tmp);
801 *fCovariance = *fWeight;
802 if (fCovariance->Determinant() != 0) {
804 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
806 AliWarning(" Determinant fCovariance=0:");
808 tmp = new TMatrixD(*fCovariance); // extrapolated covariance
809 fCovExtrap->Add(tmp);
811 tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
812 fCovFilter->Add(tmp);
814 tmp = new TMatrixD(jacob0); // Jacobian
817 if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
818 fSteps->AddAt(fPositionNew,fNSteps++);
819 if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
823 //__________________________________________________________________________
824 Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd, Int_t iz)
826 /// Picks up point within a window for the chamber No ichamb
827 /// Split the track if there are more than 1 hit
828 Int_t ihit, nRecTracks;
829 Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
830 TClonesArray *trackPtr;
831 AliMUONHitForRec *hit, *hitLoop;
832 AliMUONTrackK *trackK;
833 AliMUONDetElement *detElem = NULL;
837 if (fgTrackReconstructor->GetTrackMethod() == 3 && iz >= 0) {
838 // Combined cluster / track finder
839 // Check if extrapolated track passes thru det. elems. at iz
840 Int_t *pDEatZ = fgCombi->DEatZ(iz);
841 Int_t nDetElem = pDEatZ[-1];
842 //cout << fgCombi->Z(iz) << " " << nDetElem << endl;
843 for (Int_t i = 0; i < nDetElem; i++) {
844 detElem = fgCombi->DetElem(pDEatZ[i]);
845 if (detElem->Inside((*fTrackParNew)(1,0), (*fTrackParNew)(0,0), fPosition)) {
846 detElem->ClusterReco((*fTrackParNew)(1,0), (*fTrackParNew)(0,0));
847 hitAdd = (AliMUONHitForRec*) detElem->HitsForRec()->First();
852 if (!ok) return ok; // outside det. elem.
856 //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
857 //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
858 *fCovariance = *fWeight;
859 // check whether the Invert method returns flag if matrix cannot be inverted,
860 // and do not calculate the Determinant in that case !!!!
861 if (fCovariance->Determinant() != 0) {
863 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
865 AliWarning(" Determinant fCovariance=0:");
867 //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
868 //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
869 // Loop over all hits and take hits from the chamber
870 TMatrixD pointWeight(fgkSize,fgkSize);
871 TMatrixD saveWeight = pointWeight;
872 TMatrixD pointWeightTmp = pointWeight;
873 TMatrixD point(fgkSize,1);
874 TMatrixD trackPar = point;
875 TMatrixD trackParTmp = point;
876 Int_t nHitsOK = 0, ihitB = currIndx, ihitE = fgNOfPoints, iDhit = iFB;
878 zLast = ((AliMUONHitForRec*)fTrackHits->Last())->GetZ();
879 if (fgTrackReconstructor->GetTrackMethod() == 3 && detElem) {
881 ihitE = detElem->NHitsForRec();
886 for (ihit = ihitB; ihit >= 0 && ihit < ihitE; ihit+=iDhit) {
887 if (fgTrackReconstructor->GetTrackMethod() != 3 || !detElem)
888 hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
889 else hit = (AliMUONHitForRec*) detElem->HitsForRec()->UncheckedAt(ihit);
890 if (hit->GetChamberNumber() == ichamb) {
891 //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
892 if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
893 y = hit->GetBendingCoor();
894 x = hit->GetNonBendingCoor();
895 if (hit->GetBendingReso2() < 0) {
896 // Combined cluster / track finder
897 hit->SetBendingReso2(fgTrackReconstructor->GetBendingResolution()*
898 fgTrackReconstructor->GetBendingResolution());
899 hit->SetNonBendingReso2(fgTrackReconstructor->GetNonBendingResolution()*
900 fgTrackReconstructor->GetNonBendingResolution());
902 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
903 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
905 // windowB = TMath::Min (windowB,5.);
906 if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
908 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
909 windowB = TMath::Min (windowB,0.5);
910 windowNonB = TMath::Min (windowNonB,3.);
911 } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
912 windowB = TMath::Min (windowB,1.5);
913 windowNonB = TMath::Min (windowNonB,3.);
914 } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
915 windowB = TMath::Min (windowB,4.);
916 windowNonB = TMath::Min (windowNonB,6.);
922 if (TMath::Abs(hit->GetZ()-zLast) < 50) {
923 windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
924 windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
926 windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
927 windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
931 //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
932 if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
933 TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
934 //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
935 // TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
936 // hit->GetTrackRefSignal() == 1) { // just for test
937 // Vector of measurements and covariance matrix
938 //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
939 if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
940 // Adjust position: for multiple hits in the chamber or misalignment (Z as a function of X or Y)
941 //AliWarning(Form(" *** adjust %f %f ", zEnd, hit->GetZ()));
943 *fTrackPar = *fTrackParNew;
944 ParPropagation(zEnd);
945 WeightPropagation(zEnd, kTRUE);
946 fPosition = fPositionNew;
947 *fTrackPar = *fTrackParNew;
949 *fCovariance = *fWeight;
950 if (fCovariance->Determinant() != 0) {
952 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
954 AliWarning(" Determinant fCovariance=0:" );
960 pointWeight(0,0) = 1/hit->GetBendingReso2();
961 pointWeight(1,1) = 1/hit->GetNonBendingReso2();
962 TryPoint(point,pointWeight,trackPar,dChi2);
963 if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
964 // if (TMath::Sign(1.,(trackPar)(4,0)*(*fTrackPar)(4,0)) < 0) continue; // change of sign
967 //if (nHitsOK > -1) {
969 // Save current members
970 saveWeight = *fWeight;
971 savePosition = fPosition;
972 // temporary storage for the current track
974 trackParTmp = trackPar;
975 pointWeightTmp = pointWeight;
977 if (fgDebug > 0) cout << " Added point: " << x << " " << y << " " << dChi2 << endl;
979 // branching: create a new track
980 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
981 nRecTracks = fgTrackReconstructor->GetNRecTracks();
982 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
984 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
985 if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNmbTrackHits << " " << nRecTracks << endl;
986 trackK->fRecover = 0;
987 *(trackK->fTrackPar) = trackPar;
988 *(trackK->fWeight) += pointWeight;
989 trackK->fChi2 += dChi2;
992 *(trackK->fCovariance) = *(trackK->fWeight);
993 if (trackK->fCovariance->Determinant() != 0) {
995 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
997 cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
999 // Add filtered matrices for the smoother
1000 if (fTrackDir > 0) {
1001 if (nHitsOK > 2) { // check for position adjustment
1002 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
1003 if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
1004 //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
1005 RemoveMatrices(trackK);
1006 AliError(Form(" *** Position adjustment 1: %f %f", hit->GetZ(), (*trackK->fSteps)[i]));
1011 AddMatrices (trackK, dChi2, hit);
1013 // Mark hits as being on 2 tracks
1014 for (Int_t i=0; i<fNmbTrackHits; i++) {
1015 hitLoop = (AliMUONHitForRec*) ((*fTrackHits)[i]);
1016 //AZ hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1);
1019 cout << hitLoop->GetChamberNumber() << " ";
1020 cout << hitLoop->GetBendingCoor() << " ";
1021 cout << hitLoop->GetNonBendingCoor() << " ";
1022 cout << hitLoop->GetZ() << " " << " ";
1023 cout << hitLoop->GetTrackRefSignal() << " " << " ";
1024 cout << hitLoop->GetTTRTrack() << endl;
1025 printf(" ** %d %10.4f %10.4f %10.4f %d %d \n",
1026 hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(),
1027 hitLoop->GetNonBendingCoor(), hitLoop->GetZ(),
1028 hitLoop->GetTrackRefSignal(), hitLoop->GetTTRTrack());
1032 trackK->fTrackHits->Add(hit); // add hit
1033 trackK->fNmbTrackHits ++;
1034 hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
1037 trackK->fTrackDir = 1;
1038 trackK->fBPFlag = kTRUE;
1043 } else break; // different chamber
1044 } // for (ihit=currIndx;
1047 *fTrackPar = trackParTmp;
1048 *fWeight = saveWeight;
1049 *fWeight += pointWeightTmp;
1050 fChi2 += dChi2Tmp; // Chi2
1051 fPosition = savePosition;
1052 // Add filtered matrices for the smoother
1053 if (fTrackDir > 0) {
1054 for (Int_t i=fNSteps-1; i>=0; i--) {
1055 if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
1056 //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
1057 RemoveMatrices(this);
1058 if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
1061 } // for (Int_t i=fNSteps-1;
1062 AddMatrices (this, dChi2Tmp, hitAdd);
1065 for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1066 for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1069 } // if (fTrackDir > 0)
1074 //__________________________________________________________________________
1075 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1077 /// Adds a measurement point (modifies track parameters and computes
1080 // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1081 TMatrixD wu = *fWeight;
1082 wu += pointWeight; // W+U
1083 trackParTmp = point;
1084 trackParTmp -= *fTrackParNew; // m-p
1085 TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1086 TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1087 right += right1; // U(m-p) + (W+U)p
1089 // check whether the Invert method returns flag if matrix cannot be inverted,
1090 // and do not calculate the Determinant in that case !!!!
1091 if (wu.Determinant() != 0) {
1093 mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1095 AliWarning(" Determinant wu=0:");
1097 trackParTmp = TMatrixD(wu,TMatrixD::kMult,right);
1099 right1 = trackParTmp;
1100 right1 -= point; // p'-m
1101 point = trackParTmp;
1102 point -= *fTrackParNew; // p'-p
1103 right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1104 TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1106 right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1107 value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1108 dChi2 += value(0,0);
1112 //__________________________________________________________________________
1113 void AliMUONTrackK::MSThin(Int_t sign)
1115 /// Adds multiple scattering in a thin layer (only angles are affected)
1116 Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1118 // check whether the Invert method returns flag if matrix cannot be inverted,
1119 // and do not calculate the Determinant in that case !!!!
1120 if (fWeight->Determinant() != 0) {
1122 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1124 AliWarning(" Determinant fWeight=0:");
1127 cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1128 cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1129 momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1130 //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1131 velo = 1; // relativistic
1132 path = TMath::Abs(fgTrackReconstructor->GetChamberThicknessInX0()/cosAlph/cosBeta); // path length
1133 theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1135 (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1136 (*fWeight)(3,3) += sign*theta0*theta0; // beta
1138 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1142 //__________________________________________________________________________
1143 void AliMUONTrackK::StartBack(void)
1145 /// Starts backpropagator
1149 for (Int_t i=0; i<fgkSize; i++) {
1150 for (Int_t j=0; j<fgkSize; j++) {
1151 if (j==i) (*fWeight)(i,i) /= 100;
1152 //if (j==i) (*fWeight)(i,i) /= fNmbTrackHits*fNmbTrackHits;
1153 else (*fWeight)(j,i) = 0;
1156 // Sort hits on track in descending order in abs(z)
1157 SortHits(0, fTrackHits);
1160 //__________________________________________________________________________
1161 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1163 /// Sort hits in Z if the seed segment in the last but one station
1164 /// (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1166 if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1167 Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1168 Int_t i = 1, entries = array->GetEntriesFast();
1169 for ( ; i<entries; i++) {
1171 if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1173 z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1174 if (z < zmax) break;
1176 if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1180 for (Int_t j=0; j<=(i-1)/2; j++) {
1181 TObject *hit = array->UncheckedAt(j);
1182 array->AddAt(array->UncheckedAt(i-j),j);
1183 array->AddAt(hit,i-j);
1185 if (fgDebug >= 10) {
1186 for (i=0; i<entries; i++)
1187 cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1188 cout << " - Sort" << endl;
1192 //__________________________________________________________________________
1193 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1195 /// Set vector of Geant3 parameters pointed to by "VGeant3"
1196 /// from track parameters
1198 VGeant3[0] = (*fTrackParNew)(1,0); // X
1199 VGeant3[1] = (*fTrackParNew)(0,0); // Y
1200 VGeant3[2] = fPositionNew; // Z
1201 VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1202 VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1203 VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1204 VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1207 //__________________________________________________________________________
1208 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1210 /// Get track parameters from vector of Geant3 parameters pointed
1213 fPositionNew = VGeant3[2]; // Z
1214 (*fTrackParNew)(0,0) = VGeant3[1]; // Y
1215 (*fTrackParNew)(1,0) = VGeant3[0]; // X
1216 (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1217 (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1218 (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1221 //__________________________________________________________________________
1222 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1224 /// Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1227 AliWarning(Form(" *** Too high Chi2: %f ", fChi2));
1230 if (iChi2 == 0) fChi2 = fNmbTrackHits + (500.-fChi2)/501;
1231 else fChi2 = 500 - (fChi2-fNmbTrackHits)*501;
1234 //__________________________________________________________________________
1235 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1237 /// "Compare" function to sort with decreasing "track quality".
1238 /// Returns +1 (0, -1) if quality of current track
1239 /// is smaller than (equal to, larger than) quality of trackK
1241 if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1242 else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1246 //__________________________________________________________________________
1247 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1249 /// Check whether or not to keep current track
1250 /// (keep, if it has less than half of common hits with track0)
1251 Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1252 AliMUONHitForRec *hit0, *hit1;
1255 nHits0 = track0->fNmbTrackHits;
1256 nTrackHits2 = fNmbTrackHits/2;
1258 for (i=0; i<nHits0; i++) {
1259 // Check if hit belongs to several tracks
1260 hit0 = (AliMUONHitForRec*) (*track0->fTrackHits)[i];
1261 if (hit0->GetNTrackHits() == 1) continue;
1262 for (j=0; j<fNmbTrackHits; j++) {
1263 hit1 = (AliMUONHitForRec*) (*fTrackHits)[j];
1264 if (hit1->GetNTrackHits() == 1) continue;
1267 if (hitsInCommon >= nTrackHits2) return kFALSE;
1275 //__________________________________________________________________________
1276 void AliMUONTrackK::Kill(void)
1278 /// Kill track candidate
1279 fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1282 //__________________________________________________________________________
1283 void AliMUONTrackK::FillMUONTrack(void)
1285 /// Compute track parameters at hit positions (as for AliMUONTrack)
1287 // Set number of hits per track
1288 SetNTrackHits(fNmbTrackHits);
1292 // Set track parameters at vertex
1293 AliMUONTrackParam trackParam;
1294 SetTrackParam(&trackParam, fTrackPar, fPosition);
1295 SetTrackParamAtVertex(&trackParam);
1297 // Set track parameters at hits
1298 for (Int_t i = fNmbTrackHits-1; i>=0; i--) {
1299 if ((*fChi2Smooth)[i] < 0) {
1300 // Propagate through last chambers
1301 trackParam.ExtrapToZ(((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1304 SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHits)[i]))->GetZ());
1306 AddTrackParamAtHit(&trackParam);
1307 // Fill array of HitForRec's
1308 AddHitForRecAtHit((AliMUONHitForRec*)fTrackHits->UncheckedAt(i));
1312 //__________________________________________________________________________
1313 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1315 /// Fill AliMUONTrackParam object
1317 trackParam->SetBendingCoor((*par)(0,0));
1318 trackParam->SetNonBendingCoor((*par)(1,0));
1319 trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1320 trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1321 trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1322 trackParam->SetZ(z);
1325 //__________________________________________________________________________
1326 void AliMUONTrackK::Branson(void)
1328 /// Propagates track to the vertex thru absorber using Branson correction
1329 /// (makes use of the AliMUONTrackParam class)
1331 //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1332 AliMUONTrackParam trackParam = AliMUONTrackParam();
1334 trackParam->SetBendingCoor((*fTrackPar)(0,0));
1335 trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1336 trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1337 trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1338 trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1339 trackParam->SetZ(fPosition);
1341 SetTrackParam(&trackParam, fTrackPar, fPosition);
1343 trackParam.ExtrapToVertex(Double_t(0.), Double_t(0.), Double_t(0.));
1344 //trackParam.ExtrapToVertex();
1346 (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1347 (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1348 (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1349 (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1350 (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1351 fPosition = trackParam.GetZ();
1352 //delete trackParam;
1353 if (fgDebug > 0) cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1355 // Get covariance matrix
1356 *fCovariance = *fWeight;
1357 if (fCovariance->Determinant() != 0) {
1359 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1361 AliWarning(" Determinant fCovariance=0:");
1365 //__________________________________________________________________________
1366 void AliMUONTrackK::GoToZ(Double_t zEnd)
1368 /// Propagates track to given Z
1370 ParPropagation(zEnd);
1371 MSThin(1); // multiple scattering in the chamber
1372 WeightPropagation(zEnd, kFALSE);
1373 fPosition = fPositionNew;
1374 *fTrackPar = *fTrackParNew;
1377 //__________________________________________________________________________
1378 void AliMUONTrackK::GoToVertex(Int_t iflag)
1381 /// Propagates track to the vertex
1382 /// All material constants are taken from AliRoot
1384 static Double_t x01[5] = { 24.282, // C
1389 // inner part theta < 3 degrees
1390 static Double_t x02[5] = { 30413, // Air
1395 // z positions of the materials inside the absober outer part theta > 3 degres
1396 static Double_t zPos[10] = {-90, -105, -315, -443, -468};
1398 Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
1399 AliMUONHitForRec *hit;
1400 AliMUONRawCluster *clus;
1401 TClonesArray *rawclusters;
1403 // First step to the rear end of the absorber
1404 Double_t zRear = -503;
1406 Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1408 // Go through absorber
1409 pOld = 1/(*fTrackPar)(4,0);
1410 Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1411 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1412 r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
1414 Double_t p0, cos25, cos60;
1415 if (!iflag) goto vertex;
1417 for (Int_t i=4; i>=0; i--) {
1418 ParPropagation(zPos[i]);
1419 WeightPropagation(zPos[i], kFALSE);
1420 dZ = TMath::Abs (fPositionNew-fPosition);
1421 if (r0Norm > 1) x0 = x01[i];
1423 MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
1424 fPosition = fPositionNew;
1425 *fTrackPar = *fTrackParNew;
1426 r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) +
1427 (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1428 r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
1430 // Correct momentum for energy losses
1431 pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
1433 cos25 = TMath::Cos(2.5/180*TMath::Pi());
1434 cos60 = TMath::Cos(6.0/180*TMath::Pi());
1435 for (Int_t j=0; j<1; j++) {
1439 deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1441 deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1445 deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1447 deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1455 deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1457 deltaP = 3.0643 + 0.01346*p0;
1463 deltaP = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1465 deltaP = 2.407 + 0.00702*p0;
1474 deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1476 deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1483 deltaP = 2.209 + 0.800e-2*p0;
1485 deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1495 deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1497 deltaP = 3.0714 + 0.011767 * p0;
1502 deltaP = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1504 deltaP = 2.6069 + 0.0051705 * p0;
1510 p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
1512 (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1516 ParPropagation((Double_t)0.);
1517 WeightPropagation((Double_t)0., kFALSE);
1518 fPosition = fPositionNew;
1519 //*fTrackPar = *fTrackParNew;
1520 // Add vertex as a hit
1521 TMatrixD pointWeight(fgkSize,fgkSize);
1522 TMatrixD point(fgkSize,1);
1523 TMatrixD trackParTmp = point;
1524 point(0,0) = 0; // vertex coordinate - should be taken somewhere
1525 point(1,0) = 0; // vertex coordinate - should be taken somewhere
1526 pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1527 pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1528 TryPoint(point,pointWeight,trackParTmp,dChi2);
1529 *fTrackPar = trackParTmp;
1530 *fWeight += pointWeight;
1531 fChi2 += dChi2; // Chi2
1532 if (fgDebug < 0) return; // no output
1534 cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNmbTrackHits << endl;
1535 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1536 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1537 printf ("%5d", hit->GetChamberNumber());
1541 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1542 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1543 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1544 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1545 printf ("%5d", fgHitForRec->IndexOf(hit));
1549 if (fgTrackReconstructor->GetRecTrackRefHits()) {
1550 // from track ref. hits
1551 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1552 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1553 cout << hit->GetTTRTrack() + hit->GetTrackRefSignal()*10000 << " ";
1556 // from raw clusters
1557 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1558 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1559 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1560 Int_t index = -hit->GetHitNumber() / 100000;
1561 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1562 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1564 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1565 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1567 printf ("%5d", clus->GetTrack(1)%10000000);
1570 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1571 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
1572 if (hit->GetHitNumber() < 0) { // combined cluster / track finder
1573 Int_t index = -hit->GetHitNumber() / 100000;
1574 Int_t iPos = -hit->GetHitNumber() - index * 100000;
1575 clus = (AliMUONRawCluster*) fgCombi->DetElem(index-1)->RawClusters()->UncheckedAt(iPos);
1577 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1578 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1580 if (clus->GetTrack(2) != -1) printf ("%5d", clus->GetTrack(2)%10000000);
1581 else printf ("%5s", " ");
1585 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
1586 //cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetHitNumber() << " ";
1587 cout << ((AliMUONHitForRec*)((*fTrackHits)[i1]))->GetZ() << " ";
1588 //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHits)[i1]))) << " ";
1591 for (Int_t i1=0; i1<fNmbTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1593 cout << "---------------------------------------------------" << endl;
1595 // Get covariance matrix
1596 /* Not needed - covariance matrix is not interesting to anybody
1597 *fCovariance = *fWeight;
1598 if (fCovariance->Determinant() != 0) {
1600 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1602 AliWarning(" Determinant fCovariance=0:" );
1607 //__________________________________________________________________________
1608 void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
1610 /// Adds multiple scattering in a thick layer for linear propagation
1612 Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1613 Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1614 Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1616 sinBeta = TMath::Sin((*fTrackPar)(3,0));
1617 Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1618 Double_t momentum = 1/(*fTrackPar)(4,0);
1619 Double_t velo = 1; // relativistic velocity
1620 Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
1622 // Projected scattering angle
1623 Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0));
1624 Double_t theta02 = theta0*theta0;
1625 Double_t dl2 = step*step/2*theta02;
1626 Double_t dl3 = dl2*step*2/3;
1629 Double_t dYdT = 1/cosAlph;
1630 Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1631 Double_t dXdT = tanAlph*tanBeta;
1632 //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1633 Double_t dXdB = 1/cosBeta;
1634 Double_t dAdT = 1/cosBeta;
1635 Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1637 // Get covariance matrix
1638 *fCovariance = *fWeight;
1639 if (fCovariance->Determinant() != 0) {
1640 // fCovariance->Invert();
1642 mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1644 AliWarning(" Determinant fCovariance=0:" );
1647 (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1648 (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1649 (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1650 (*fCovariance)(3,3) += theta02*step; // <bb>
1652 (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1653 (*fCovariance)(1,0) = (*fCovariance)(0,1);
1655 (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1656 (*fCovariance)(2,0) = (*fCovariance)(0,2);
1658 (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1659 (*fCovariance)(3,0) = (*fCovariance)(0,3);
1661 (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
1662 (*fCovariance)(2,1) = (*fCovariance)(1,2);
1664 (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1665 (*fCovariance)(3,1) = (*fCovariance)(1,3);
1667 (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1668 (*fCovariance)(3,2) = (*fCovariance)(2,3);
1670 // Get weight matrix
1671 *fWeight = *fCovariance;
1672 if (fWeight->Determinant() != 0) {
1674 mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1676 AliWarning(" Determinant fWeight=0:");
1680 //__________________________________________________________________________
1681 Bool_t AliMUONTrackK::Recover(void)
1683 /// Adds new failed track(s) which can be tried to be recovered
1685 TClonesArray *trackPtr;
1686 AliMUONTrackK *trackK;
1688 if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
1689 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1691 // Remove hit with the highest chi2
1694 for (Int_t i=0; i<fNmbTrackHits; i++) {
1695 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1696 printf("%10.4f", chi2);
1699 for (Int_t i=0; i<fNmbTrackHits; i++) {
1700 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
1704 Double_t chi2max = 0;
1706 for (Int_t i=0; i<fNmbTrackHits; i++) {
1707 chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1708 if (chi2 < chi2max) continue;
1712 //if (chi2max < 10) return kFALSE; // !!!
1713 //if (chi2max < 25) imax = fNmbTrackHits - 1;
1714 if (chi2max < 15) imax = fNmbTrackHits - 1; // discard the last point
1715 // Check if the outlier is not from the seed segment
1716 AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
1717 if (skipHit == fStartSegment->GetHitForRec1() || skipHit == fStartSegment->GetHitForRec2()) {
1718 //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1719 return kFALSE; // to be changed probably
1722 // Make a copy of track hit collection
1723 TObjArray *hits = new TObjArray(*fTrackHits);
1727 // Hits after the found one will be removed
1728 if (GetStation0() == 3 && skipHit->GetChamberNumber() >= 7) {
1729 SortHits(1, fTrackHits); // unsort hits
1730 imax = fTrackHits->IndexOf(skipHit);
1732 Int_t nTrackHits = fNmbTrackHits;
1733 for (Int_t i=imax+1; i<nTrackHits; i++) {
1734 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
1735 fTrackHits->Remove(hit);
1736 hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit
1740 // Check if the track candidate doesn't exist yet
1741 if (ExistDouble()) { delete hits; return kFALSE; }
1743 //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1746 nRecTracks = fgTrackReconstructor->GetNRecTracks();
1747 skipHit = (AliMUONHitForRec*) ((*fTrackHits)[fNmbTrackHits-1]);
1748 // Remove all saved steps and smoother matrices after the skipped hit
1749 RemoveMatrices(skipHit->GetZ());
1751 //AZ(z->-z) if (skipHit->GetZ() > fStartSegment->GetHitForRec2()->GetZ() || !fNSteps) {
1752 if (TMath::Abs(skipHit->GetZ()) > TMath::Abs(fStartSegment->GetHitForRec2()->GetZ()) || !fNSteps) {
1753 // Propagation toward high Z or skipped hit next to segment -
1754 // start track from segment
1755 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
1756 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1757 trackK->fRecover = 1;
1758 trackK->fSkipHit = skipHit;
1759 trackK->fNmbTrackHits = fNmbTrackHits;
1760 delete trackK->fTrackHits; // not efficient ?
1761 trackK->fTrackHits = new TObjArray(*fTrackHits);
1762 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1766 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1768 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1769 //AZ(z->-z) trackK->fTrackDir = -1;
1770 trackK->fTrackDir = 1;
1771 trackK->fRecover = 1;
1772 trackK->fSkipHit = skipHit;
1773 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1775 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1776 CreateMatrix(trackK->fParFilter);
1778 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1779 trackK->fParFilter->Last()->SetUniqueID(1);
1780 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1781 iD = trackK->fCovFilter->Last()->GetUniqueID();
1783 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1784 CreateMatrix(trackK->fCovFilter);
1786 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1787 trackK->fCovFilter->Last()->SetUniqueID(1);
1788 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1789 if (trackK->fWeight->Determinant() != 0) {
1791 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1793 AliWarning(" Determinant fWeight=0:");
1795 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1797 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1798 if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1802 //__________________________________________________________________________
1803 void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1805 /// Adds matrices for the smoother and keep Chi2 for the point
1806 /// Track parameters
1807 //trackK->fParFilter->Last()->Print();
1808 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1810 trackK->fParFilter->Last()->SetUniqueID(iD-1);
1811 CreateMatrix(trackK->fParFilter);
1814 *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1815 trackK->fParFilter->Last()->SetUniqueID(iD);
1817 cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1818 //trackK->fTrackPar->Print();
1819 //trackK->fTrackParNew->Print();
1820 trackK->fParFilter->Last()->Print();
1821 cout << " Add matrices" << endl;
1824 *(trackK->fCovariance) = *(trackK->fWeight);
1825 if (trackK->fCovariance->Determinant() != 0) {
1827 mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1829 AliWarning(" Determinant fCovariance=0:");
1831 iD = trackK->fCovFilter->Last()->GetUniqueID();
1833 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1834 CreateMatrix(trackK->fCovFilter);
1837 *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1838 trackK->fCovFilter->Last()->SetUniqueID(iD);
1840 // Save Chi2-increment for point
1841 Int_t indx = trackK->fTrackHits->IndexOf(hitAdd);
1842 if (indx < 0) indx = fNmbTrackHits;
1843 if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10);
1844 trackK->fChi2Array->AddAt(dChi2,indx);
1847 //__________________________________________________________________________
1848 void AliMUONTrackK::CreateMatrix(TObjArray *objArray) const
1850 /// Create new matrix and add it to TObjArray
1852 TMatrixD *matrix = (TMatrixD*) objArray->First();
1853 TMatrixD *tmp = new TMatrixD(*matrix);
1854 objArray->AddAtAndExpand(tmp,objArray->GetLast());
1855 //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1858 //__________________________________________________________________________
1859 void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1861 /// Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1863 for (Int_t i=fNSteps-1; i>=0; i--) {
1864 if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1865 if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1866 RemoveMatrices(this);
1867 } // for (Int_t i=fNSteps-1;
1870 //__________________________________________________________________________
1871 void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1873 /// Remove last saved matrices and steps in the smoother part
1876 Int_t i = trackK->fNSteps;
1879 // Delete only matrices not shared by several tracks
1880 id = trackK->fParExtrap->Last()->GetUniqueID();
1882 trackK->fParExtrap->Last()->SetUniqueID(id-1);
1883 trackK->fParExtrap->RemoveAt(i);
1885 else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1886 id = fParFilter->Last()->GetUniqueID();
1888 trackK->fParFilter->Last()->SetUniqueID(id-1);
1889 trackK->fParFilter->RemoveAt(i);
1891 else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1892 id = trackK->fCovExtrap->Last()->GetUniqueID();
1894 trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1895 trackK->fCovExtrap->RemoveAt(i);
1897 else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1898 id = trackK->fCovFilter->Last()->GetUniqueID();
1900 trackK->fCovFilter->Last()->SetUniqueID(id-1);
1901 trackK->fCovFilter->RemoveAt(i);
1903 else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1904 id = trackK->fJacob->Last()->GetUniqueID();
1906 trackK->fJacob->Last()->SetUniqueID(id-1);
1907 trackK->fJacob->RemoveAt(i);
1909 else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1912 //__________________________________________________________________________
1913 Bool_t AliMUONTrackK::Smooth(void)
1916 Int_t ihit = fNmbTrackHits - 1;
1917 AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1918 fChi2Smooth = new TArrayD(fNmbTrackHits);
1919 fChi2Smooth->Reset(-1);
1921 fParSmooth = new TObjArray(15);
1922 fParSmooth->Clear();
1925 cout << " ******** Enter Smooth " << endl;
1926 cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl;
1928 for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1930 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();}
1932 for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHits)[i])->GetZ() << " ";
1936 // Find last point corresponding to the last hit
1937 Int_t iLast = fNSteps - 1;
1938 for ( ; iLast>=0; iLast--) {
1939 //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ()) break;
1940 if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHits)[fNmbTrackHits-1])->GetZ())) break;
1943 TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1945 TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1946 TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1947 TMatrixD tmpPar = *fTrackPar;
1948 //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print();
1951 Double_t chi2max = 0;
1952 for (Int_t i=iLast+1; i>0; i--) {
1953 if (i == iLast + 1) goto L33; // temporary fix
1955 // Smoother gain matrix
1956 weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1957 if (weight.Determinant() != 0) {
1959 mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1961 AliWarning(" Determinant weight=0:");
1964 tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
1965 gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
1966 //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
1968 // Smoothed parameter vector
1969 //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
1970 parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
1971 tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
1972 tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
1975 // Smoothed covariance
1976 covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1977 weight = TMatrixD(TMatrixD::kTransposed,gain);
1978 tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
1979 covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
1980 covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
1982 // Check if there was a measurement at given z
1984 for ( ; ihit>=0; ihit--) {
1985 hit = (AliMUONHitForRec*) (*fTrackHits)[ihit];
1986 if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
1987 //AZ(z->-z) else if (ihit < fNmbTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
1988 else if (ihit < fNmbTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
1990 if (!found) continue; // no measurement - skip the rest
1991 else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
1992 if (ihit == 0) continue; // the first hit - skip the rest
1995 // Smoothed residuals
1997 tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
1998 tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
2000 cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
2001 cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
2003 // Cov. matrix of smoothed residuals
2005 tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
2006 tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
2007 tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
2008 tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
2010 // Calculate Chi2 of smoothed residuals
2011 if (tmp.Determinant() != 0) {
2013 mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2015 AliWarning(" Determinant tmp=0:");
2017 TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
2018 TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
2019 if (fgDebug > 1) chi2.Print();
2020 (*fChi2Smooth)[ihit] = chi2(0,0);
2021 if (chi2(0,0) > chi2max) chi2max = chi2(0,0);
2023 if (chi2(0,0) < 0) {
2025 AliError(Form(" *** chi2 < 0: %d %d ", i, iLast));
2027 // Save smoothed parameters
2028 TMatrixD *par = new TMatrixD(parSmooth);
2029 fParSmooth->AddAtAndExpand(par, ihit);
2031 } // for (Int_t i=iLast+1;
2033 //if (chi2max > 16) {
2034 //if (chi2max > 25) {
2035 //if (chi2max > 50) {
2036 //if (chi2max > 100) {
2037 if (chi2max > fgkChi2max) {
2038 //if (Recover()) DropBranches();
2046 //__________________________________________________________________________
2047 void AliMUONTrackK::Outlier()
2049 /// Adds new track with removed hit having the highest chi2
2052 cout << " ******** Enter Outlier " << endl;
2053 for (Int_t i=0; i<fNmbTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
2055 for (Int_t i=0; i<fNmbTrackHits; i++) {
2056 printf("%10d", ((AliMUONHitForRec*)fTrackHits->UncheckedAt(i))->GetChamberNumber());
2061 Double_t chi2max = 0;
2063 for (Int_t i=0; i<fNmbTrackHits; i++) {
2064 if ((*fChi2Smooth)[i] < chi2max) continue;
2065 chi2max = (*fChi2Smooth)[i];
2068 // Check if the outlier is not from the seed segment
2069 AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(imax);
2070 if (hit == fStartSegment->GetHitForRec1() || hit == fStartSegment->GetHitForRec2()) return; // to be changed probably
2072 // Check for missing station
2075 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--;
2076 } else if (imax == fNmbTrackHits-1) {
2077 if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2079 else if (((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2080 if (!ok) { Recover(); return; } // try to recover track
2081 //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; }
2083 // Remove saved steps and smoother matrices after the outlier
2084 RemoveMatrices(hit->GetZ());
2086 // Check for possible double track candidates
2087 //if (ExistDouble(hit)) return;
2089 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2090 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2092 AliMUONTrackK *trackK = 0;
2093 if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2094 // start track from segment
2095 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment);
2096 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2097 trackK->fRecover = 2;
2098 trackK->fSkipHit = hit;
2099 trackK->fNmbTrackHits = fNmbTrackHits;
2101 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(0);
2102 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2103 hit = (AliMUONHitForRec*) trackK->fTrackHits->UncheckedAt(1);
2104 hit->SetNTrackHits(hit->GetNTrackHits()-1);
2105 delete trackK->fTrackHits; // not efficient ?
2106 trackK->fTrackHits = new TObjArray(*fTrackHits);
2107 for (Int_t i = 0; i < fNmbTrackHits; i++) {
2108 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(i);
2109 hit->SetNTrackHits(hit->GetNTrackHits()+1);
2112 if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHits);
2113 if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2116 trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2118 fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2119 trackK->fTrackDir = 1;
2120 trackK->fRecover = 2;
2121 trackK->fSkipHit = hit;
2122 Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2124 trackK->fParFilter->Last()->SetUniqueID(iD-1);
2125 CreateMatrix(trackK->fParFilter);
2127 *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2128 trackK->fParFilter->Last()->SetUniqueID(1);
2129 *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2130 iD = trackK->fCovFilter->Last()->GetUniqueID();
2132 trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2133 CreateMatrix(trackK->fCovFilter);
2135 *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2136 trackK->fCovFilter->Last()->SetUniqueID(1);
2137 *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2138 if (trackK->fWeight->Determinant() != 0) {
2140 mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2142 AliWarning(" Determinant fWeight=0:");
2144 trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2146 for (Int_t i=0; i<fNmbTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2147 if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2150 //__________________________________________________________________________
2151 Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2153 /// Return Chi2 at point
2154 return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2158 //__________________________________________________________________________
2159 void AliMUONTrackK::Print(FILE *lun) const
2161 /// Print out track information
2164 AliMUONHitForRec *hit = 0;
2165 if (fgTrackReconstructor->GetRecTrackRefHits()) {
2166 // from track ref. hits
2167 for (Int_t j=0; j<fNmbTrackHits; j++) {
2168 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(j);
2169 if (hit->GetTTRTrack() > 1) { flag = 0; break; }
2171 for (Int_t j=0; j<fNmbTrackHits; j++) {
2172 printf("%10.4f", GetChi2PerPoint(j));
2173 if (GetChi2PerPoint(j) > -0.1) {
2174 hit = (AliMUONHitForRec*) fTrackHits->UncheckedAt(j);
2175 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(j));
2176 fprintf(lun, "%3d %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack(), flag);
2181 // from raw clusters
2182 AliMUONRawCluster *clus = 0;
2183 TClonesArray *rawclusters = 0;
2184 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2185 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2186 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2187 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2188 if (TMath::Abs(clus->GetTrack(1)-1) < 2) {
2189 if (clus->GetTrack(2)) flag = 2;
2192 if (clus->GetTrack(2) && TMath::Abs(clus->GetTrack(2)-1) < 2) {
2199 Int_t sig[2]={1,1}, tid[2]={0};
2200 for (Int_t i1=0; i1<fNmbTrackHits; i1++) {
2201 if (GetChi2PerPoint(i1) < -0.1) continue;
2202 hit = (AliMUONHitForRec*) ((*fTrackHits)[i1]);
2203 rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2204 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2205 for (Int_t j=0; j<2; j++) {
2206 tid[j] = clus->GetTrack(j+1) - 1;
2207 if (clus->GetTrack(j+1) < 0) { sig[j] = 0; tid[j] = 999; }
2209 fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(i1));
2210 if (!(clus->GetTrack(2))) fprintf(lun, "%3d %3d", sig[0], tid[0]); // simple cluster
2211 else { // track overlap
2212 fprintf(lun, "%3d %3d", TMath::Max(sig[0],sig[1]), TMath::Min(tid[0],tid[1]));
2213 //if (tid[0] < 2) flag *= 2;
2214 //else if (tid[1] < 2) flag *= 3;
2216 fprintf (lun, "%3d \n", flag);
2221 //__________________________________________________________________________
2222 void AliMUONTrackK::DropBranches(Int_t imax, TObjArray *hits)
2224 /// Drop branches downstream of the skipped hit
2226 TClonesArray *trackPtr;
2227 AliMUONTrackK *trackK;
2229 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2230 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2231 Int_t icand = trackPtr->IndexOf(this);
2232 if (!hits) hits = fTrackHits;
2234 // Check if the track candidate doesn't exist yet
2235 for (Int_t i=icand+1; i<nRecTracks; i++) {
2236 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2237 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2238 if (trackK->GetRecover() < 0) continue;
2240 if (trackK->fNmbTrackHits >= imax + 1) {
2241 for (Int_t j=0; j<=imax; j++) {
2242 //if (j != fNmbTrackHits-1 && (*trackK->fTrackHits)[j] != (*fTrackHits)[j]) break;
2243 if ((*trackK->fTrackHits)[j] != (*hits)[j]) break;
2245 if (hits != fTrackHits) {
2246 // Drop all branches downstream the hit (for Recover)
2247 trackK->SetRecover(-1);
2248 if (fgDebug >= 0 )cout << " Recover " << i << endl;
2251 // Check if the removal of the hit breaks the track
2254 if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2255 else if (imax == trackK->fNmbTrackHits-1) continue;
2256 // else if (imax == trackK->fNmbTrackHits-1) {
2257 //if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(trackK->fNmbTrackHits-2))->GetChamberNumber() > 1) ok--;
2259 else if (((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHits->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2260 if (!ok) trackK->SetRecover(-1);
2262 } // for (Int_t j=0;
2264 } // for (Int_t i=0;
2267 //__________________________________________________________________________
2268 void AliMUONTrackK::DropBranches(AliMUONSegment *segment)
2270 /// Drop all candidates with the same seed segment
2272 TClonesArray *trackPtr;
2273 AliMUONTrackK *trackK;
2275 trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2276 nRecTracks = fgTrackReconstructor->GetNRecTracks();
2277 Int_t icand = trackPtr->IndexOf(this);
2279 for (Int_t i=icand+1; i<nRecTracks; i++) {
2280 trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2281 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2282 if (trackK->GetRecover() < 0) continue;
2283 if (trackK->fStartSegment == segment) trackK->SetRecover(-1);
2285 if (fgDebug >= 0) cout << " Drop segment " << endl;
2288 //__________________________________________________________________________
2289 AliMUONHitForRec* AliMUONTrackK::GetHitLastOk(void)
2291 /// Return the hit where track stopped
2293 if (!fNSteps) return (AliMUONHitForRec*)((*fTrackHits)[1]);
2297 //__________________________________________________________________________
2298 Int_t AliMUONTrackK::GetStation0(void)
2300 /// Return seed station number
2301 return fStartSegment->GetHitForRec1()->GetChamberNumber() / 2;
2304 //__________________________________________________________________________
2305 Bool_t AliMUONTrackK::ExistDouble(AliMUONHitForRec *hit)
2307 /// Check if the track will make a double after outlier removal
2309 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2310 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2311 TObjArray *hitArray = new TObjArray(*fTrackHits);
2312 TObjArray *hitArray1 = new TObjArray(*hitArray);
2313 hitArray1->Remove(hit);
2314 hitArray1->Compress();
2316 Bool_t same = kFALSE;
2317 for (Int_t i=0; i<nRecTracks; i++) {
2318 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2319 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2320 if (trackK == this) continue;
2321 if (trackK->fNmbTrackHits == fNmbTrackHits || trackK->fNmbTrackHits == fNmbTrackHits-1) {
2322 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2324 if (trackK->fNmbTrackHits == fNmbTrackHits) {
2325 for (Int_t j=0; j<fNmbTrackHits; j++) {
2326 if (hits->UncheckedAt(j) != hitArray->UncheckedAt(j)) { same = kFALSE; break; }
2328 if (same) { delete hits; break; }
2329 if (trackK->fSkipHit) {
2330 TObjArray *hits1 = new TObjArray(*hits);
2331 if (hits1->Remove(trackK->fSkipHit) > 0) {
2334 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2335 if (hits1->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2337 if (same) { delete hits1; break; }
2342 // Check with removed outlier
2344 for (Int_t j=0; j<fNmbTrackHits-1; j++) {
2345 if (hits->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2347 if (same) { delete hits; break; }
2351 } // for (Int_t i=0; i<nRecTracks;
2352 delete hitArray; delete hitArray1;
2353 if (same && fgDebug >= 0) cout << " Same" << endl;
2357 //__________________________________________________________________________
2358 Bool_t AliMUONTrackK::ExistDouble(void)
2360 /// Check if the track will make a double after recovery
2362 TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2363 Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2365 TObjArray *hitArray = new TObjArray(*fTrackHits);
2366 if (GetStation0() == 3) SortHits(0, hitArray); // sort
2367 //if (GetStation0() == 3) SortHits(1, hitArray); // unsort
2369 Bool_t same = kFALSE;
2370 for (Int_t i=0; i<nRecTracks; i++) {
2371 AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2372 if (trackK->fNmbTrackHits == 2 && trackK->GetRecover() == 0) continue;
2373 if (trackK == this) continue;
2374 //AZ if (trackK->GetRecover() < 0) continue; //
2375 if (trackK->fNmbTrackHits >= fNmbTrackHits) {
2376 TObjArray *hits = new TObjArray(*trackK->fTrackHits);
2377 if (trackK->GetStation0() == 3) SortHits(0, hits); // sort
2378 //if (trackK->GetStation0() == 3) SortHits(1, hits); // unsort
2379 for (Int_t j=0; j<fNmbTrackHits; j++) {
2380 //cout << fNmbTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2381 if (j != fNmbTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break;
2382 if (j == fNmbTrackHits-1) {
2383 if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE;
2384 //if (trackK->fNmbTrackHits > fNmbTrackHits &&
2385 //if (trackK->fSkipHit) cout << ((AliMUONHitForRec*)((*hitArray)[j]))->GetZ() << " " << trackK->fSkipHit->GetZ() << endl;
2387 } // for (Int_t j=0;
2391 } // for (Int_t i=0;