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 **************************************************************************/
17 //-------------------------------------------------------
18 // Implementation of the TPC tracker
20 // Origin: Marian Ivanov Marian.Ivanov@cern.ch
22 // AliTPC parallel tracker
24 // The track fitting is based on Kalman filtering approach
26 // The track finding steps:
27 // 1. Seeding - with and without vertex constraint
28 // - seeding with vertex constain done at first n^2 proble
29 // - seeding without vertex constraint n^3 problem
30 // 2. Tracking - follow prolongation road - find cluster - update kalman track
32 // The seeding and tracking is repeated several times, in different seeding region.
33 // This approach enables to find the track which cannot be seeded in some region of TPC
34 // This can happen because of low momenta (track do not reach outer radius), or track is currently in the ded region between sectors, or the track is for the moment overlapped with other track (seed quality is poor) ...
36 // With this approach we reach almost 100 % efficiency also for high occupancy events.
37 // (If the seeding efficiency in a region is about 90 % than with logical or of several
38 // regions we will reach 100% (in theory - supposing independence)
40 // Repeating several seeding - tracking procedures some of the tracks can be find
43 // The procedures to remove multi find tacks are impremented:
44 // RemoveUsed2 - fast procedure n problem -
45 // Algorithm - Sorting tracks according quality
46 // remove tracks with some shared fraction
47 // Sharing in respect to all tacks
48 // Signing clusters in gold region
49 // FindSplitted - slower algorithm n^2
50 // Sort the tracks according quality
51 // Loop over pair of tracks
52 // If overlap with other track bigger than threshold - remove track
54 // FindCurling - Finds the pair of tracks which are curling
55 // - About 10% of tracks can be find with this procedure
56 // The combinatorial background is too big to be used in High
57 // multiplicity environment
58 // - n^2 problem - Slow procedure - currently it is disabled because of
61 // The number of splitted tracks can be reduced disabling the sharing of the cluster.
62 // tpcRecoParam-> SetClusterSharing(kFALSE);
63 // IT IS HIGHLY non recomended to use it in high flux enviroonment
64 // Even using this switch some tracks can be found more than once
65 // (because of multiple seeding and low quality tracks which will not cross full chamber)
68 // The tracker itself can be debugged - the information about tracks can be stored in several // phases of the reconstruction
69 // To enable storage of the TPC tracks in the ESD friend track
70 // use AliTPCReconstructor::SetStreamLevel(n);
72 // The debug level - different procedure produce tree for numerical debugging
73 // To enable them set AliTPCReconstructor::SetStreamLevel(n); where nis bigger 1
77 // Adding systematic errors to the covariance:
79 // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
80 // of the tracks (not to the clusters as they are dependent):
81 // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
82 // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
83 // The default values are 0.
85 // The sytematic errors are added to the covariance matrix in following places:
87 // 1. During fisrt itteration - AliTPCtracker::FillESD
88 // 2. Second iteration -
89 // 2.a ITS->TPC - AliTPCtracker::ReadSeeds
90 // 2.b TPC->TRD - AliTPCtracker::PropagateBack
91 // 3. Third iteration -
92 // 3.a TRD->TPC - AliTPCtracker::ReadSeeds
93 // 3.b TPC->ITS - AliTPCtracker::RefitInward
95 // There are several places in the code which can be numerically debuged
96 // This code is keeped in order to enable code development and to check the calibration implementtion
98 // 1. ErrParam stream - dump information about
100 // 2.a) cluster error estimate
101 // 3.a) cluster shape estimate
104 // Debug streamer levels:
106 //-------------------------------------------------------
111 #include "Riostream.h"
112 #include <TClonesArray.h>
114 #include <TObjArray.h>
116 #include <TGraphErrors.h>
117 #include <TTimeStamp.h>
119 #include "AliComplexCluster.h"
120 #include "AliESDEvent.h"
121 #include "AliESDtrack.h"
122 #include "AliESDVertex.h"
125 #include "AliHelix.h"
126 #include "AliRunLoader.h"
127 #include "AliTPCClustersRow.h"
128 #include "AliTPCParam.h"
129 #include "AliTPCReconstructor.h"
130 #include "AliTPCpolyTrack.h"
131 #include "AliTPCreco.h"
132 #include "AliTPCseed.h"
134 #include "AliTPCtrackerSector.h"
135 #include "AliTPCtracker.h"
136 #include "TStopwatch.h"
137 #include "AliTPCReconstructor.h"
138 #include "AliAlignObj.h"
139 #include "AliTrackPointArray.h"
141 #include "AliTPCcalibDB.h"
142 #include "AliTPCcalibDButil.h"
143 #include "AliTPCTransform.h"
144 #include "AliTPCClusterParam.h"
145 #include "AliTPCdEdxInfo.h"
146 #include "AliDCSSensorArray.h"
147 #include "AliDCSSensor.h"
149 #include "AliCosmicTracker.h"
155 ClassImp(AliTPCtracker)
159 class AliTPCFastMath {
162 static Double_t FastAsin(Double_t x);
164 static Double_t fgFastAsin[20000]; //lookup table for fast asin computation
167 Double_t AliTPCFastMath::fgFastAsin[20000];
168 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
170 AliTPCFastMath::AliTPCFastMath(){
172 // initialized lookup table;
173 for (Int_t i=0;i<10000;i++){
174 fgFastAsin[2*i] = TMath::ASin(i/10000.);
175 fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
179 Double_t AliTPCFastMath::FastAsin(Double_t x){
181 // return asin using lookup table
183 Int_t index = int(x*10000);
184 return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
187 Int_t index = int(x*10000);
188 return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
190 //__________________________________________________________________
191 AliTPCtracker::AliTPCtracker()
219 // default constructor
221 for (Int_t irow=0; irow<200; irow++){
228 //_____________________________________________________________________
232 Int_t AliTPCtracker::UpdateTrack(AliTPCseed * track, Int_t accept){
234 //update track information using current cluster - track->fCurrentCluster
237 AliTPCclusterMI* c =track->GetCurrentCluster();
238 if (accept > 0) //sign not accepted clusters
239 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);
240 else // unsign accpeted clusters
241 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);
242 UInt_t i = track->GetCurrentClusterIndex1();
244 Int_t sec=(i&0xff000000)>>24;
245 //Int_t row = (i&0x00ff0000)>>16;
246 track->SetRow((i&0x00ff0000)>>16);
247 track->SetSector(sec);
248 // Int_t index = i&0xFFFF;
249 if (sec>=fkParam->GetNInnerSector()) track->SetRow(track->GetRow()+fkParam->GetNRowLow());
250 track->SetClusterIndex2(track->GetRow(), i);
251 //track->fFirstPoint = row;
252 //if ( track->fLastPoint<row) track->fLastPoint =row;
253 // if (track->fRow<0 || track->fRow>160) {
254 // printf("problem\n");
256 if (track->GetFirstPoint()>track->GetRow())
257 track->SetFirstPoint(track->GetRow());
258 if (track->GetLastPoint()<track->GetRow())
259 track->SetLastPoint(track->GetRow());
262 track->SetClusterPointer(track->GetRow(),c);
265 Double_t angle2 = track->GetSnp()*track->GetSnp();
267 //SET NEW Track Point
269 if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
271 angle2 = TMath::Sqrt(angle2/(1-angle2));
272 AliTPCTrackerPoint &point =*(track->GetTrackPoint(track->GetRow()));
274 point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
275 point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
276 point.SetErrY(sqrt(track->GetErrorY2()));
277 point.SetErrZ(sqrt(track->GetErrorZ2()));
279 point.SetX(track->GetX());
280 point.SetY(track->GetY());
281 point.SetZ(track->GetZ());
282 point.SetAngleY(angle2);
283 point.SetAngleZ(track->GetTgl());
284 if (point.IsShared()){
285 track->SetErrorY2(track->GetErrorY2()*4);
286 track->SetErrorZ2(track->GetErrorZ2()*4);
290 Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
292 // track->SetErrorY2(track->GetErrorY2()*1.3);
293 // track->SetErrorY2(track->GetErrorY2()+0.01);
294 // track->SetErrorZ2(track->GetErrorZ2()*1.3);
295 // track->SetErrorZ2(track->GetErrorZ2()+0.005);
297 if (accept>0) return 0;
298 if (track->GetNumberOfClusters()%20==0){
299 // if (track->fHelixIn){
300 // TClonesArray & larr = *(track->fHelixIn);
301 // Int_t ihelix = larr.GetEntriesFast();
302 // new(larr[ihelix]) AliHelix(*track) ;
305 if (AliTPCReconstructor::StreamLevel()>5) {
306 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
307 AliExternalTrackParam param(*track);
308 TTreeSRedirector &cstream = *fDebugStreamer;
314 track->SetNoCluster(0);
315 return track->Update(c,chi2,i);
320 Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
323 // decide according desired precision to accept given
324 // cluster for tracking
326 seed->GetProlongation(cluster->GetX(),yt,zt);
327 Double_t sy2=ErrY2(seed,cluster);
328 Double_t sz2=ErrZ2(seed,cluster);
330 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
331 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
332 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
333 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
334 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
335 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
336 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
337 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
339 Double_t rdistance2 = rdistancey2+rdistancez2;
342 if (AliTPCReconstructor::StreamLevel()>2 && ( (fIteration>0)|| (seed->GetNumberOfClusters()>20))) {
343 // if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
344 Float_t rmsy2 = seed->GetCurrentSigmaY2();
345 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
346 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
347 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
348 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
349 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
350 AliExternalTrackParam param(*seed);
351 static TVectorD gcl(3),gtr(3);
353 param.GetXYZ(gcl.GetMatrixArray());
354 cluster->GetGlobalXYZ(gclf);
355 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
356 Int_t nclSeed=seed->GetNumberOfClusters();
358 if (AliTPCReconstructor::StreamLevel()>2) {
359 (*fDebugStreamer)<<"ErrParam"<<
360 "iter="<<fIteration<<
362 "nclSeed="<<nclSeed<<
374 "rmsy2p30="<<rmsy2p30<<
375 "rmsz2p30="<<rmsz2p30<<
376 "rmsy2p30R="<<rmsy2p30R<<
377 "rmsz2p30R="<<rmsz2p30R<<
378 // normalize distance -
379 "rdisty="<<rdistancey2<<
380 "rdistz="<<rdistancez2<<
381 "rdist="<<rdistance2<< //
385 //return 0; // temporary
386 if (rdistance2>32) return 3;
389 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
390 return 2; //suspisiouce - will be changed
392 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
393 // strict cut on overlaped cluster
394 return 2; //suspisiouce - will be changed
396 if ( (rdistancey2>1. || rdistancez2>6.25 )
397 && cluster->GetType()<0){
398 seed->SetNFoundable(seed->GetNFoundable()-1);
402 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
404 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
405 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
418 //_____________________________________________________________________________
419 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
421 fkNIS(par->GetNInnerSector()/2),
423 fkNOS(par->GetNOuterSector()/2),
446 //---------------------------------------------------------------------
447 // The main TPC tracker constructor
448 //---------------------------------------------------------------------
449 fInnerSec=new AliTPCtrackerSector[fkNIS];
450 fOuterSec=new AliTPCtrackerSector[fkNOS];
453 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
454 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
457 Int_t nrowlow = par->GetNRowLow();
458 Int_t nrowup = par->GetNRowUp();
461 for (i=0;i<nrowlow;i++){
462 fXRow[i] = par->GetPadRowRadiiLow(i);
463 fPadLength[i]= par->GetPadPitchLength(0,i);
464 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
468 for (i=0;i<nrowup;i++){
469 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
470 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
471 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
474 if (AliTPCReconstructor::StreamLevel()>0) {
475 fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
478 fSeedsPool = new TClonesArray("AliTPCseed",1000);
480 //________________________________________________________________________
481 AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
508 //------------------------------------
509 // dummy copy constructor
510 //------------------------------------------------------------------
512 for (Int_t irow=0; irow<200; irow++){
519 AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
521 //------------------------------
523 //--------------------------------------------------------------
526 //_____________________________________________________________________________
527 AliTPCtracker::~AliTPCtracker() {
528 //------------------------------------------------------------------
529 // TPC tracker destructor
530 //------------------------------------------------------------------
537 if (fDebugStreamer) delete fDebugStreamer;
538 if (fSeedsPool) delete fSeedsPool;
542 void AliTPCtracker::FillESD(const TObjArray* arr)
546 //fill esds using updated tracks
552 // write tracks to the event
553 // store index of the track
554 Int_t nseed=arr->GetEntriesFast();
555 //FindKinks(arr,fEvent);
556 for (Int_t i=0; i<nseed; i++) {
557 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
561 if (AliTPCReconstructor::StreamLevel()>1) {
562 (*fDebugStreamer)<<"Track0"<<
566 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
567 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
568 pt->PropagateTo(fkParam->GetInnerRadiusLow());
571 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
572 iotrack.~AliESDtrack();
573 new(&iotrack) AliESDtrack;
574 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
575 iotrack.SetTPCPoints(pt->GetPoints());
576 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
577 iotrack.SetV0Indexes(pt->GetV0Indexes());
578 // iotrack.SetTPCpid(pt->fTPCr);
579 //iotrack.SetTPCindex(i);
580 MakeESDBitmaps(pt, &iotrack);
581 fEvent->AddTrack(&iotrack);
585 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
586 iotrack.~AliESDtrack();
587 new(&iotrack) AliESDtrack;
588 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
589 iotrack.SetTPCPoints(pt->GetPoints());
590 //iotrack.SetTPCindex(i);
591 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
592 iotrack.SetV0Indexes(pt->GetV0Indexes());
593 MakeESDBitmaps(pt, &iotrack);
594 // iotrack.SetTPCpid(pt->fTPCr);
595 fEvent->AddTrack(&iotrack);
599 // short tracks - maybe decays
601 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
602 Int_t found,foundable,shared;
603 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
604 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
605 iotrack.~AliESDtrack();
606 new(&iotrack) AliESDtrack;
607 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
608 //iotrack.SetTPCindex(i);
609 iotrack.SetTPCPoints(pt->GetPoints());
610 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
611 iotrack.SetV0Indexes(pt->GetV0Indexes());
612 MakeESDBitmaps(pt, &iotrack);
613 //iotrack.SetTPCpid(pt->fTPCr);
614 fEvent->AddTrack(&iotrack);
619 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
620 Int_t found,foundable,shared;
621 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
622 if (found<20) continue;
623 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
625 iotrack.~AliESDtrack();
626 new(&iotrack) AliESDtrack;
627 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
628 iotrack.SetTPCPoints(pt->GetPoints());
629 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
630 iotrack.SetV0Indexes(pt->GetV0Indexes());
631 MakeESDBitmaps(pt, &iotrack);
632 //iotrack.SetTPCpid(pt->fTPCr);
633 //iotrack.SetTPCindex(i);
634 fEvent->AddTrack(&iotrack);
637 // short tracks - secondaties
639 if ( (pt->GetNumberOfClusters()>30) ) {
640 Int_t found,foundable,shared;
641 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
642 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
643 iotrack.~AliESDtrack();
644 new(&iotrack) AliESDtrack;
645 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
646 iotrack.SetTPCPoints(pt->GetPoints());
647 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
648 iotrack.SetV0Indexes(pt->GetV0Indexes());
649 MakeESDBitmaps(pt, &iotrack);
650 //iotrack.SetTPCpid(pt->fTPCr);
651 //iotrack.SetTPCindex(i);
652 fEvent->AddTrack(&iotrack);
657 if ( (pt->GetNumberOfClusters()>15)) {
658 Int_t found,foundable,shared;
659 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
660 if (found<15) continue;
661 if (foundable<=0) continue;
662 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
663 if (float(found)/float(foundable)<0.8) continue;
665 iotrack.~AliESDtrack();
666 new(&iotrack) AliESDtrack;
667 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
668 iotrack.SetTPCPoints(pt->GetPoints());
669 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
670 iotrack.SetV0Indexes(pt->GetV0Indexes());
671 MakeESDBitmaps(pt, &iotrack);
672 // iotrack.SetTPCpid(pt->fTPCr);
673 //iotrack.SetTPCindex(i);
674 fEvent->AddTrack(&iotrack);
678 // >> account for suppressed tracks in the kink indices (RS)
679 int nESDtracks = fEvent->GetNumberOfTracks();
680 for (int it=nESDtracks;it--;) {
681 AliESDtrack* esdTr = fEvent->GetTrack(it);
682 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
683 for (int ik=0;ik<3;ik++) {
685 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
686 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
688 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
691 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
695 // << account for suppressed tracks in the kink indices (RS)
696 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
704 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
707 // Use calibrated cluster error from OCDB
709 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
711 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
712 Int_t ctype = cl->GetType();
713 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
714 Double_t angle = seed->GetSnp()*seed->GetSnp();
715 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
716 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
718 erry2+=0.5; // edge cluster
722 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
723 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
724 erry2+=addErr*addErr;
725 seed->SetErrorY2(erry2);
729 //calculate look-up table at the beginning
730 // static Bool_t ginit = kFALSE;
731 // static Float_t gnoise1,gnoise2,gnoise3;
732 // static Float_t ggg1[10000];
733 // static Float_t ggg2[10000];
734 // static Float_t ggg3[10000];
735 // static Float_t glandau1[10000];
736 // static Float_t glandau2[10000];
737 // static Float_t glandau3[10000];
739 // static Float_t gcor01[500];
740 // static Float_t gcor02[500];
741 // static Float_t gcorp[500];
745 // if (ginit==kFALSE){
746 // for (Int_t i=1;i<500;i++){
747 // Float_t rsigma = float(i)/100.;
748 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
749 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
750 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
754 // for (Int_t i=3;i<10000;i++){
758 // Float_t amp = float(i);
759 // Float_t padlength =0.75;
760 // gnoise1 = 0.0004/padlength;
761 // Float_t nel = 0.268*amp;
762 // Float_t nprim = 0.155*amp;
763 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
764 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
765 // if (glandau1[i]>1) glandau1[i]=1;
766 // glandau1[i]*=padlength*padlength/12.;
770 // gnoise2 = 0.0004/padlength;
772 // nprim = 0.133*amp;
773 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
774 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
775 // if (glandau2[i]>1) glandau2[i]=1;
776 // glandau2[i]*=padlength*padlength/12.;
781 // gnoise3 = 0.0004/padlength;
783 // nprim = 0.133*amp;
784 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
785 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
786 // if (glandau3[i]>1) glandau3[i]=1;
787 // glandau3[i]*=padlength*padlength/12.;
795 // Int_t amp = int(TMath::Abs(cl->GetQ()));
797 // seed->SetErrorY2(1.);
801 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
802 // Int_t ctype = cl->GetType();
803 // Float_t padlength= GetPadPitchLength(seed->GetRow());
804 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
805 // angle2 = angle2/(1-angle2);
807 // //cluster "quality"
808 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
811 // if (fSectors==fInnerSec){
812 // snoise2 = gnoise1;
813 // res = ggg1[amp]*z+glandau1[amp]*angle2;
814 // if (ctype==0) res *= gcor01[rsigmay];
817 // res*= gcorp[rsigmay];
821 // if (padlength<1.1){
822 // snoise2 = gnoise2;
823 // res = ggg2[amp]*z+glandau2[amp]*angle2;
824 // if (ctype==0) res *= gcor02[rsigmay];
827 // res*= gcorp[rsigmay];
831 // snoise2 = gnoise3;
832 // res = ggg3[amp]*z+glandau3[amp]*angle2;
833 // if (ctype==0) res *= gcor02[rsigmay];
836 // res*= gcorp[rsigmay];
843 // res*=2.4; // overestimate error 2 times
847 // if (res<2*snoise2)
850 // seed->SetErrorY2(res);
858 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
861 // Use calibrated cluster error from OCDB
863 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
865 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
866 Int_t ctype = cl->GetType();
867 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
869 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
870 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
871 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
872 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
874 errz2+=0.5; // edge cluster
878 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
879 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
880 errz2+=addErr*addErr;
881 seed->SetErrorZ2(errz2);
887 // //seed->SetErrorY2(0.1);
889 // //calculate look-up table at the beginning
890 // static Bool_t ginit = kFALSE;
891 // static Float_t gnoise1,gnoise2,gnoise3;
892 // static Float_t ggg1[10000];
893 // static Float_t ggg2[10000];
894 // static Float_t ggg3[10000];
895 // static Float_t glandau1[10000];
896 // static Float_t glandau2[10000];
897 // static Float_t glandau3[10000];
899 // static Float_t gcor01[1000];
900 // static Float_t gcor02[1000];
901 // static Float_t gcorp[1000];
905 // if (ginit==kFALSE){
906 // for (Int_t i=1;i<1000;i++){
907 // Float_t rsigma = float(i)/100.;
908 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
909 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
910 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
914 // for (Int_t i=3;i<10000;i++){
918 // Float_t amp = float(i);
919 // Float_t padlength =0.75;
920 // gnoise1 = 0.0004/padlength;
921 // Float_t nel = 0.268*amp;
922 // Float_t nprim = 0.155*amp;
923 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
924 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
925 // if (glandau1[i]>1) glandau1[i]=1;
926 // glandau1[i]*=padlength*padlength/12.;
930 // gnoise2 = 0.0004/padlength;
932 // nprim = 0.133*amp;
933 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
934 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
935 // if (glandau2[i]>1) glandau2[i]=1;
936 // glandau2[i]*=padlength*padlength/12.;
941 // gnoise3 = 0.0004/padlength;
943 // nprim = 0.133*amp;
944 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
945 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
946 // if (glandau3[i]>1) glandau3[i]=1;
947 // glandau3[i]*=padlength*padlength/12.;
955 // Int_t amp = int(TMath::Abs(cl->GetQ()));
957 // seed->SetErrorY2(1.);
961 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
962 // Int_t ctype = cl->GetType();
963 // Float_t padlength= GetPadPitchLength(seed->GetRow());
965 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
966 // // if (angle2<0.6) angle2 = 0.6;
967 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
969 // //cluster "quality"
970 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
973 // if (fSectors==fInnerSec){
974 // snoise2 = gnoise1;
975 // res = ggg1[amp]*z+glandau1[amp]*angle2;
976 // if (ctype==0) res *= gcor01[rsigmaz];
979 // res*= gcorp[rsigmaz];
983 // if (padlength<1.1){
984 // snoise2 = gnoise2;
985 // res = ggg2[amp]*z+glandau2[amp]*angle2;
986 // if (ctype==0) res *= gcor02[rsigmaz];
989 // res*= gcorp[rsigmaz];
993 // snoise2 = gnoise3;
994 // res = ggg3[amp]*z+glandau3[amp]*angle2;
995 // if (ctype==0) res *= gcor02[rsigmaz];
998 // res*= gcorp[rsigmaz];
1007 // if ((ctype<0) &&<70){
1012 // if (res<2*snoise2)
1014 // if (res>3) res =3;
1015 // seed->SetErrorZ2(res);
1023 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1025 //rotate to track "local coordinata
1026 Float_t x = seed->GetX();
1027 Float_t y = seed->GetY();
1028 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1031 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1032 if (!seed->Rotate(fSectors->GetAlpha()))
1034 } else if (y <-ymax) {
1035 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1036 if (!seed->Rotate(-fSectors->GetAlpha()))
1044 //_____________________________________________________________________________
1045 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1046 Double_t x2,Double_t y2,
1047 Double_t x3,Double_t y3) const
1049 //-----------------------------------------------------------------
1050 // Initial approximation of the track curvature
1051 //-----------------------------------------------------------------
1052 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1053 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1054 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1055 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1056 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1058 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1059 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1060 return -xr*yr/sqrt(xr*xr+yr*yr);
1065 //_____________________________________________________________________________
1066 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1067 Double_t x2,Double_t y2,
1068 Double_t x3,Double_t y3) const
1070 //-----------------------------------------------------------------
1071 // Initial approximation of the track curvature
1072 //-----------------------------------------------------------------
1078 Double_t det = x3*y2-x2*y3;
1079 if (TMath::Abs(det)<1e-10){
1083 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1084 Double_t x0 = x3*0.5-y3*u;
1085 Double_t y0 = y3*0.5+x3*u;
1086 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1092 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1093 Double_t x2,Double_t y2,
1094 Double_t x3,Double_t y3) const
1096 //-----------------------------------------------------------------
1097 // Initial approximation of the track curvature
1098 //-----------------------------------------------------------------
1104 Double_t det = x3*y2-x2*y3;
1105 if (TMath::Abs(det)<1e-10) {
1109 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1110 Double_t x0 = x3*0.5-y3*u;
1111 Double_t y0 = y3*0.5+x3*u;
1112 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1121 //_____________________________________________________________________________
1122 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1123 Double_t x2,Double_t y2,
1124 Double_t x3,Double_t y3) const
1126 //-----------------------------------------------------------------
1127 // Initial approximation of the track curvature times center of curvature
1128 //-----------------------------------------------------------------
1129 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1130 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1131 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1132 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1133 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1135 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1137 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1140 //_____________________________________________________________________________
1141 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1142 Double_t x2,Double_t y2,
1143 Double_t z1,Double_t z2) const
1145 //-----------------------------------------------------------------
1146 // Initial approximation of the tangent of the track dip angle
1147 //-----------------------------------------------------------------
1148 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1152 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1153 Double_t x2,Double_t y2,
1154 Double_t z1,Double_t z2, Double_t c) const
1156 //-----------------------------------------------------------------
1157 // Initial approximation of the tangent of the track dip angle
1158 //-----------------------------------------------------------------
1162 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1164 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1165 if (TMath::Abs(d*c*0.5)>1) return 0;
1166 // Double_t angle2 = TMath::ASin(d*c*0.5);
1167 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1168 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1170 angle2 = (z1-z2)*c/(angle2*2.);
1174 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1175 {//-----------------------------------------------------------------
1176 // This function find proloncation of a track to a reference plane x=x2.
1177 //-----------------------------------------------------------------
1181 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1185 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1186 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1190 Double_t dy = dx*(c1+c2)/(r1+r2);
1193 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1195 if (TMath::Abs(delta)>0.01){
1196 dz = x[3]*TMath::ASin(delta)/x[4];
1198 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1201 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1209 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1214 return LoadClusters();
1218 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1221 // load clusters to the memory
1222 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1223 Int_t lower = arr->LowerBound();
1224 Int_t entries = arr->GetEntriesFast();
1226 for (Int_t i=lower; i<entries; i++) {
1227 clrow = (AliTPCClustersRow*) arr->At(i);
1228 if(!clrow) continue;
1229 if(!clrow->GetArray()) continue;
1233 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1235 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1236 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1239 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1240 AliTPCtrackerRow * tpcrow=0;
1243 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1247 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1248 left = (sec-fkNIS*2)/fkNOS;
1251 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1252 for (Int_t j=0;j<tpcrow->GetN1();++j)
1253 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1256 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1257 for (Int_t j=0;j<tpcrow->GetN2();++j)
1258 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1260 clrow->GetArray()->Clear("C");
1269 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1272 // load clusters to the memory from one
1275 AliTPCclusterMI *clust=0;
1276 Int_t count[72][96] = { {0} , {0} };
1278 // loop over clusters
1279 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1280 clust = (AliTPCclusterMI*)arr->At(icl);
1281 if(!clust) continue;
1282 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1284 // transform clusters
1287 // count clusters per pad row
1288 count[clust->GetDetector()][clust->GetRow()]++;
1291 // insert clusters to sectors
1292 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1293 clust = (AliTPCclusterMI*)arr->At(icl);
1294 if(!clust) continue;
1296 Int_t sec = clust->GetDetector();
1297 Int_t row = clust->GetRow();
1299 // filter overlapping pad rows needed by HLT
1300 if(sec<fkNIS*2) { //IROCs
1301 if(row == 30) continue;
1304 if(row == 27 || row == 76) continue;
1309 // left = sec/fkNIS;
1310 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1313 // left = (sec-fkNIS*2)/fkNOS;
1314 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1318 // Load functions must be called behind LoadCluster(TClonesArray*)
1320 //LoadOuterSectors();
1321 //LoadInnerSectors();
1327 Int_t AliTPCtracker::LoadClusters()
1330 // load clusters to the memory
1331 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1333 // TTree * tree = fClustersArray.GetTree();
1334 AliInfo("LoadClusters()\n");
1336 TTree * tree = fInput;
1337 TBranch * br = tree->GetBranch("Segment");
1338 br->SetAddress(&clrow);
1340 // Conversion of pad, row coordinates in local tracking coords.
1341 // Could be skipped here; is already done in clusterfinder
1343 Int_t j=Int_t(tree->GetEntries());
1344 for (Int_t i=0; i<j; i++) {
1348 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1349 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1350 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1353 AliTPCtrackerRow * tpcrow=0;
1356 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1360 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1361 left = (sec-fkNIS*2)/fkNOS;
1364 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1365 for (Int_t k=0;k<tpcrow->GetN1();++k)
1366 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1369 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1370 for (Int_t k=0;k<tpcrow->GetN2();++k)
1371 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1378 if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1383 void AliTPCtracker::UnloadClusters()
1386 // unload clusters from the memory
1388 Int_t nrows = fOuterSec->GetNRows();
1389 for (Int_t sec = 0;sec<fkNOS;sec++)
1390 for (Int_t row = 0;row<nrows;row++){
1391 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1393 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1394 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1396 tpcrow->ResetClusters();
1399 nrows = fInnerSec->GetNRows();
1400 for (Int_t sec = 0;sec<fkNIS;sec++)
1401 for (Int_t row = 0;row<nrows;row++){
1402 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1404 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1405 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1407 tpcrow->ResetClusters();
1413 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1415 // Filling cluster to the array - For visualization purposes
1418 nrows = fOuterSec->GetNRows();
1419 for (Int_t sec = 0;sec<fkNOS;sec++)
1420 for (Int_t row = 0;row<nrows;row++){
1421 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1422 if (!tpcrow) continue;
1423 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1424 array->AddLast((TObject*)((*tpcrow)[icl]));
1427 nrows = fInnerSec->GetNRows();
1428 for (Int_t sec = 0;sec<fkNIS;sec++)
1429 for (Int_t row = 0;row<nrows;row++){
1430 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1431 if (!tpcrow) continue;
1432 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1433 array->AddLast((TObject*)(*tpcrow)[icl]);
1439 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1443 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1444 AliTPCTransform *transform = calibDB->GetTransform() ;
1446 AliFatal("Tranformations not in calibDB");
1449 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1450 Double_t x[3]={static_cast<Double_t>(cluster->GetRow()),static_cast<Double_t>(cluster->GetPad()),static_cast<Double_t>(cluster->GetTimeBin())};
1451 Int_t i[1]={cluster->GetDetector()};
1452 transform->Transform(x,i,0,1);
1453 // if (cluster->GetDetector()%36>17){
1458 // in debug mode check the transformation
1460 if (AliTPCReconstructor::StreamLevel()>2) {
1462 cluster->GetGlobalXYZ(gx);
1463 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1464 TTreeSRedirector &cstream = *fDebugStreamer;
1465 cstream<<"Transform"<<
1476 cluster->SetX(x[0]);
1477 cluster->SetY(x[1]);
1478 cluster->SetZ(x[2]);
1483 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1484 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1485 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1487 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1488 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1489 if (mat) mat->LocalToMaster(pos,posC);
1491 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1493 cluster->SetX(posC[0]);
1494 cluster->SetY(posC[1]);
1495 cluster->SetZ(posC[2]);
1499 void AliTPCtracker::ApplyTailCancellation(){
1501 // Correct the cluster charge for the ion tail effect
1502 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1506 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1507 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1508 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1509 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1510 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1511 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1513 // find the number of clusters for the whole TPC (nclALL)
1515 for (Int_t isector=0; isector<36; isector++){
1516 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1517 nclALL += sector.GetNClInSector(0);
1518 nclALL += sector.GetNClInSector(1);
1521 // start looping over all clusters
1522 for (Int_t iside=0; iside<2; iside++){ // loop over sides
1525 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
1526 // cache experimantal tuning factor for the different chamber type
1527 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
1528 std::cout << " ampfactor = " << ampfactor << std::endl;
1530 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
1533 // Cache time response functions and their positons to COG of the cluster
1534 TGraphErrors ** graphRes = new TGraphErrors *[20];
1535 Float_t * indexAmpGraphs = new Float_t[20];
1536 for (Int_t icache=0; icache<20; icache++)
1538 graphRes[icache] = NULL;
1539 indexAmpGraphs[icache] = 0;
1541 ///////////////////////////// --> position fo sie loop
1542 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
1547 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
1548 Int_t nrows = sector.GetNRows(); // number of rows
1549 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
1551 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1553 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1554 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1555 if (iside>0) ncl=tpcrow.GetN2();
1557 // Order clusters in time for the proper correction of ion tail
1558 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
1559 Float_t qMaxArray[ncl];
1560 Int_t sortedClusterIndex[ncl];
1561 Float_t sortedClusterTimeBin[ncl];
1562 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
1563 for (Int_t i=0;i<ncl;i++)
1567 sortedClusterIndex[i]=i;
1568 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1570 rowClusterArray->AddAt(rowcl,i);
1572 rowClusterArray->RemoveAt(i);
1574 // Fill the timebin info to the array in order to sort wrt tb
1576 sortedClusterTimeBin[i]=0.0;
1578 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
1582 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
1584 // Main cluster correction loops over clusters
1585 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
1587 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
1591 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
1593 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
1595 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
1596 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
1597 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
1599 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
1601 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
1602 Double_t ionTailMax=0.;
1603 Double_t ionTailTotal=0.;
1604 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
1605 ionTailMax=TMath::Abs(ionTailMax);
1606 ionTailTotal=TMath::Abs(ionTailTotal);
1607 qTotArray[icl0]+=ionTailTotal;
1608 qMaxArray[icl0]+=ionTailMax;
1610 // Dump some info for debugging while clusters are being corrected
1611 if (AliTPCReconstructor::StreamLevel()>2) {
1612 TTreeSRedirector &cstream = *fDebugStreamer;
1613 if (gRandom->Rndm() > 0.999){
1614 cstream<<"IonTail"<<
1615 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
1616 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
1617 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
1618 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
1621 }// dump the results to the debug streamer if in debug mode
1623 }//end of second loop over clusters
1625 // Set corrected values of the corrected cluster
1626 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
1627 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
1629 // Dump some info for debugging after clusters are corrected
1630 if (AliTPCReconstructor::StreamLevel()>2) {
1631 TTreeSRedirector &cstream = *fDebugStreamer;
1632 if (gRandom->Rndm() > 0.999){
1633 cstream<<"IonTailCorrected"<<
1634 "cl0.=" << cl0 << // cluster 0 with huge Qmax
1635 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
1636 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
1637 "nclALL=" << nclALL <<
1638 "nclSector=" << nclSector <<
1640 "nclPad=" << nclPad <<
1646 }// dump the results to the debug streamer if in debug mode
1648 }//end of first loop over cluster
1649 delete rowClusterArray;
1650 }//end of loop over rows
1651 for (int i=0; i<20; i++) delete graphRes[i];
1653 delete [] indexAmpGraphs;
1655 }//end of loop over sectors
1656 }//end of loop over IROC/OROC
1657 }// end of side loop
1659 //_____________________________________________________________________________
1660 void AliTPCtracker::GetTailValue(Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
1663 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
1666 const Double_t kMinPRF = 0.5; // minimal PRF width
1667 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
1668 ionTailMax = 0.; // correction value to be added to Qmax of cl0
1670 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
1671 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
1672 Int_t sectorPad = cl1->GetDetector(); // sector number
1673 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
1674 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
1675 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
1676 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
1677 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
1678 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
1681 Double_t sumAmp1=0.;
1682 for (Int_t idelta =-2; idelta<=2;idelta++){
1683 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
1686 Double_t sumAmp0=0.;
1687 for (Int_t idelta =-2; idelta<=2;idelta++){
1688 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
1691 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
1692 Int_t padScan=2; // +-2 pad-timebin window will be scanned
1693 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
1696 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
1697 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
1698 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
1700 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
1702 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
1703 for (Int_t j=0;j<20;j++) {
1704 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
1706 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
1710 if (!graphRes[ampIndex]) continue;
1711 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
1712 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
1714 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
1717 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
1719 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
1720 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
1721 Float_t qMaxPad0 = amp0*qTot0;
1723 // Add 5 timebin range contribution around the max peak (-+2 tb window)
1724 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
1726 if (itb<0) continue;
1727 if (itb>=graphRes[ampIndex]->GetN()) continue;
1729 // calculate contribution to qTot
1730 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
1731 if (ipad1!=padcl0) {
1732 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
1734 ionTailTotal += tailCorr; // for center pad
1736 // calculate contribution to qMax
1737 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
1739 } // end of tb correction loop which is applied over 5 tb range
1741 } // end of cl0 loop
1742 } // end of cl1 loop
1746 //_____________________________________________________________________________
1747 Int_t AliTPCtracker::LoadOuterSectors() {
1748 //-----------------------------------------------------------------
1749 // This function fills outer TPC sectors with clusters.
1750 //-----------------------------------------------------------------
1751 Int_t nrows = fOuterSec->GetNRows();
1753 for (Int_t sec = 0;sec<fkNOS;sec++)
1754 for (Int_t row = 0;row<nrows;row++){
1755 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1756 Int_t sec2 = sec+2*fkNIS;
1758 Int_t ncl = tpcrow->GetN1();
1760 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1761 index=(((sec2<<8)+row)<<16)+ncl;
1762 tpcrow->InsertCluster(c,index);
1765 ncl = tpcrow->GetN2();
1767 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1768 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1769 tpcrow->InsertCluster(c,index);
1772 // write indexes for fast acces
1774 for (Int_t i=0;i<510;i++)
1775 tpcrow->SetFastCluster(i,-1);
1776 for (Int_t i=0;i<tpcrow->GetN();i++){
1777 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1778 tpcrow->SetFastCluster(zi,i); // write index
1781 for (Int_t i=0;i<510;i++){
1782 if (tpcrow->GetFastCluster(i)<0)
1783 tpcrow->SetFastCluster(i,last);
1785 last = tpcrow->GetFastCluster(i);
1794 //_____________________________________________________________________________
1795 Int_t AliTPCtracker::LoadInnerSectors() {
1796 //-----------------------------------------------------------------
1797 // This function fills inner TPC sectors with clusters.
1798 //-----------------------------------------------------------------
1799 Int_t nrows = fInnerSec->GetNRows();
1801 for (Int_t sec = 0;sec<fkNIS;sec++)
1802 for (Int_t row = 0;row<nrows;row++){
1803 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1806 Int_t ncl = tpcrow->GetN1();
1808 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1809 index=(((sec<<8)+row)<<16)+ncl;
1810 tpcrow->InsertCluster(c,index);
1813 ncl = tpcrow->GetN2();
1815 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1816 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1817 tpcrow->InsertCluster(c,index);
1820 // write indexes for fast acces
1822 for (Int_t i=0;i<510;i++)
1823 tpcrow->SetFastCluster(i,-1);
1824 for (Int_t i=0;i<tpcrow->GetN();i++){
1825 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1826 tpcrow->SetFastCluster(zi,i); // write index
1829 for (Int_t i=0;i<510;i++){
1830 if (tpcrow->GetFastCluster(i)<0)
1831 tpcrow->SetFastCluster(i,last);
1833 last = tpcrow->GetFastCluster(i);
1845 //_________________________________________________________________________
1846 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
1847 //--------------------------------------------------------------------
1848 // Return pointer to a given cluster
1849 //--------------------------------------------------------------------
1850 if (index<0) return 0; // no cluster
1851 Int_t sec=(index&0xff000000)>>24;
1852 Int_t row=(index&0x00ff0000)>>16;
1853 Int_t ncl=(index&0x00007fff)>>00;
1855 const AliTPCtrackerRow * tpcrow=0;
1856 TClonesArray * clrow =0;
1858 if (sec<0 || sec>=fkNIS*4) {
1859 AliWarning(Form("Wrong sector %d",sec));
1864 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
1865 if (tracksec.GetNRows()<=row) return 0;
1866 tpcrow = &(tracksec[row]);
1867 if (tpcrow==0) return 0;
1870 if (tpcrow->GetN1()<=ncl) return 0;
1871 clrow = tpcrow->GetClusters1();
1874 if (tpcrow->GetN2()<=ncl) return 0;
1875 clrow = tpcrow->GetClusters2();
1879 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
1880 if (tracksec.GetNRows()<=row) return 0;
1881 tpcrow = &(tracksec[row]);
1882 if (tpcrow==0) return 0;
1884 if (sec-2*fkNIS<fkNOS) {
1885 if (tpcrow->GetN1()<=ncl) return 0;
1886 clrow = tpcrow->GetClusters1();
1889 if (tpcrow->GetN2()<=ncl) return 0;
1890 clrow = tpcrow->GetClusters2();
1894 return (AliTPCclusterMI*)clrow->At(ncl);
1900 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
1901 //-----------------------------------------------------------------
1902 // This function tries to find a track prolongation to next pad row
1903 //-----------------------------------------------------------------
1905 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
1908 AliTPCclusterMI *cl=0;
1909 Int_t tpcindex= t.GetClusterIndex2(nr);
1911 // update current shape info every 5 pad-row
1912 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1916 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
1918 if (tpcindex==-1) return 0; //track in dead zone
1919 if (tpcindex >= 0){ //
1920 cl = t.GetClusterPointer(nr);
1921 //if (cl==0) cl = GetClusterMI(tpcindex);
1922 if (!cl) cl = GetClusterMI(tpcindex);
1923 t.SetCurrentClusterIndex1(tpcindex);
1926 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
1927 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1929 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1930 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1932 if (TMath::Abs(angle-t.GetAlpha())>0.001){
1933 Double_t rotation = angle-t.GetAlpha();
1934 t.SetRelativeSector(relativesector);
1935 if (!t.Rotate(rotation)) {
1936 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1940 if (!t.PropagateTo(x)) {
1941 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1945 t.SetCurrentCluster(cl);
1947 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1948 if ((tpcindex&0x8000)==0) accept =0;
1950 //if founded cluster is acceptible
1951 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
1952 t.SetErrorY2(t.GetErrorY2()+0.03);
1953 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1954 t.SetErrorY2(t.GetErrorY2()*3);
1955 t.SetErrorZ2(t.GetErrorZ2()*3);
1957 t.SetNFoundable(t.GetNFoundable()+1);
1958 UpdateTrack(&t,accept);
1961 else { // Remove old cluster from track
1962 t.SetClusterIndex(nr, -3);
1963 t.SetClusterPointer(nr, 0);
1967 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
1968 if (fIteration>1 && IsFindable(t)){
1969 // not look for new cluster during refitting
1970 t.SetNFoundable(t.GetNFoundable()+1);
1975 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1976 if (!t.PropagateTo(x)) {
1977 if (fIteration==0) t.SetRemoval(10);
1980 Double_t y = t.GetY();
1981 if (TMath::Abs(y)>ymax){
1983 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1984 if (!t.Rotate(fSectors->GetAlpha()))
1986 } else if (y <-ymax) {
1987 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1988 if (!t.Rotate(-fSectors->GetAlpha()))
1991 if (!t.PropagateTo(x)) {
1992 if (fIteration==0) t.SetRemoval(10);
1998 Double_t z=t.GetZ();
2001 if (!IsActive(t.GetRelativeSector(),nr)) {
2003 t.SetClusterIndex2(nr,-1);
2006 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2007 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
2008 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
2010 if (!isActive || !isActive2) return 0;
2012 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2013 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
2015 Double_t roadz = 1.;
2017 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2019 t.SetClusterIndex2(nr,-1);
2025 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2026 t.SetNFoundable(t.GetNFoundable()+1);
2032 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2033 cl = krow.FindNearest2(y,z,roady,roadz,index);
2034 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2037 t.SetCurrentCluster(cl);
2039 if (fIteration==2&&cl->IsUsed(10)) return 0;
2040 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2041 if (fIteration==2&&cl->IsUsed(11)) {
2042 t.SetErrorY2(t.GetErrorY2()+0.03);
2043 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2044 t.SetErrorY2(t.GetErrorY2()*3);
2045 t.SetErrorZ2(t.GetErrorZ2()*3);
2048 if (t.fCurrentCluster->IsUsed(10)){
2053 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2059 if (accept<3) UpdateTrack(&t,accept);
2062 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2070 //_________________________________________________________________________
2071 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2073 // Get track space point by index
2074 // return false in case the cluster doesn't exist
2075 AliTPCclusterMI *cl = GetClusterMI(index);
2076 if (!cl) return kFALSE;
2077 Int_t sector = (index&0xff000000)>>24;
2078 // Int_t row = (index&0x00ff0000)>>16;
2080 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2081 xyz[0] = cl->GetX();
2082 xyz[1] = cl->GetY();
2083 xyz[2] = cl->GetZ();
2085 fkParam->AdjustCosSin(sector,cos,sin);
2086 Float_t x = cos*xyz[0]-sin*xyz[1];
2087 Float_t y = cos*xyz[1]+sin*xyz[0];
2089 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2090 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2091 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2092 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2093 cov[0] = sin*sin*sigmaY2;
2094 cov[1] = -sin*cos*sigmaY2;
2096 cov[3] = cos*cos*sigmaY2;
2099 p.SetXYZ(x,y,xyz[2],cov);
2100 AliGeomManager::ELayerID iLayer;
2102 if (sector < fkParam->GetNInnerSector()) {
2103 iLayer = AliGeomManager::kTPC1;
2107 iLayer = AliGeomManager::kTPC2;
2108 idet = sector - fkParam->GetNInnerSector();
2110 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2111 p.SetVolumeID(volid);
2117 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2118 //-----------------------------------------------------------------
2119 // This function tries to find a track prolongation to next pad row
2120 //-----------------------------------------------------------------
2121 t.SetCurrentCluster(0);
2122 t.SetCurrentClusterIndex1(-3);
2124 Double_t xt=t.GetX();
2125 Int_t row = GetRowNumber(xt)-1;
2126 Double_t ymax= GetMaxY(nr);
2128 if (row < nr) return 1; // don't prolongate if not information until now -
2129 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2131 // return 0; // not prolongate strongly inclined tracks
2133 // if (TMath::Abs(t.GetSnp())>0.95) {
2135 // return 0; // not prolongate strongly inclined tracks
2136 // }// patch 28 fev 06
2138 Double_t x= GetXrow(nr);
2140 //t.PropagateTo(x+0.02);
2141 //t.PropagateTo(x+0.01);
2142 if (!t.PropagateTo(x)){
2149 if (TMath::Abs(y)>ymax){
2151 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2152 if (!t.Rotate(fSectors->GetAlpha()))
2154 } else if (y <-ymax) {
2155 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2156 if (!t.Rotate(-fSectors->GetAlpha()))
2159 // if (!t.PropagateTo(x)){
2166 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2168 if (!IsActive(t.GetRelativeSector(),nr)) {
2170 t.SetClusterIndex2(nr,-1);
2173 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2175 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2177 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2179 t.SetClusterIndex2(nr,-1);
2185 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2186 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2192 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2193 // t.fCurrentSigmaY = GetSigmaY(&t);
2194 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2198 AliTPCclusterMI *cl=0;
2201 Double_t roady = 1.;
2202 Double_t roadz = 1.;
2206 index = t.GetClusterIndex2(nr);
2207 if ( (index >= 0) && (index&0x8000)==0){
2208 cl = t.GetClusterPointer(nr);
2209 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2210 t.SetCurrentClusterIndex1(index);
2212 t.SetCurrentCluster(cl);
2218 // if (index<0) return 0;
2219 UInt_t uindex = TMath::Abs(index);
2222 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2223 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2226 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2227 t.SetCurrentCluster(cl);
2233 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2234 //-----------------------------------------------------------------
2235 // This function tries to find a track prolongation to next pad row
2236 //-----------------------------------------------------------------
2238 //update error according neighborhoud
2240 if (t.GetCurrentCluster()) {
2242 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2244 if (t.GetCurrentCluster()->IsUsed(10)){
2249 t.SetNShared(t.GetNShared()+1);
2250 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2255 if (fIteration>0) accept = 0;
2256 if (accept<3) UpdateTrack(&t,accept);
2260 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2261 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2263 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2271 //_____________________________________________________________________________
2272 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2273 //-----------------------------------------------------------------
2274 // This function tries to find a track prolongation.
2275 //-----------------------------------------------------------------
2276 Double_t xt=t.GetX();
2278 Double_t alpha=t.GetAlpha();
2279 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2280 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2282 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2284 Int_t first = GetRowNumber(xt);
2289 for (Int_t nr= first; nr>=rf; nr-=step) {
2291 if (t.GetKinkIndexes()[0]>0){
2292 for (Int_t i=0;i<3;i++){
2293 Int_t index = t.GetKinkIndexes()[i];
2294 if (index==0) break;
2295 if (index<0) continue;
2297 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2299 printf("PROBLEM\n");
2302 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2304 AliExternalTrackParam paramd(t);
2305 kink->SetDaughter(paramd);
2306 kink->SetStatus(2,5);
2313 if (nr==80) t.UpdateReference();
2314 if (nr<fInnerSec->GetNRows())
2315 fSectors = fInnerSec;
2317 fSectors = fOuterSec;
2318 if (FollowToNext(t,nr)==0)
2331 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2332 //-----------------------------------------------------------------
2333 // This function tries to find a track prolongation.
2334 //-----------------------------------------------------------------
2336 Double_t xt=t.GetX();
2337 Double_t alpha=t.GetAlpha();
2338 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2339 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2340 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2342 Int_t first = t.GetFirstPoint();
2343 Int_t ri = GetRowNumber(xt);
2347 if (first<ri) first = ri;
2349 if (first<0) first=0;
2350 for (Int_t nr=first; nr<=rf; nr++) {
2351 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2352 if (t.GetKinkIndexes()[0]<0){
2353 for (Int_t i=0;i<3;i++){
2354 Int_t index = t.GetKinkIndexes()[i];
2355 if (index==0) break;
2356 if (index>0) continue;
2357 index = TMath::Abs(index);
2358 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2360 printf("PROBLEM\n");
2363 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2365 AliExternalTrackParam paramm(t);
2366 kink->SetMother(paramm);
2367 kink->SetStatus(2,1);
2374 if (nr<fInnerSec->GetNRows())
2375 fSectors = fInnerSec;
2377 fSectors = fOuterSec;
2388 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2390 // overlapping factor
2396 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2399 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2401 Float_t distance = TMath::Sqrt(dz2+dy2);
2402 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2405 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2406 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2411 if (firstpoint>lastpoint) {
2412 firstpoint =lastpoint;
2417 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2418 if (s1->GetClusterIndex2(i)>0) sum1++;
2419 if (s2->GetClusterIndex2(i)>0) sum2++;
2420 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2424 if (sum<5) return 0;
2426 Float_t summin = TMath::Min(sum1+1,sum2+1);
2427 Float_t ratio = (sum+1)/Float_t(summin);
2431 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2435 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2436 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2437 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2438 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2443 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2444 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2445 Int_t firstpoint = 0;
2446 Int_t lastpoint = 160;
2448 // if (firstpoint>=lastpoint-5) return;;
2450 for (Int_t i=firstpoint;i<lastpoint;i++){
2451 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2452 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2456 if (sumshared>cutN0){
2459 for (Int_t i=firstpoint;i<lastpoint;i++){
2460 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2461 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2462 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2463 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2464 if (s1->IsActive()&&s2->IsActive()){
2465 p1->SetShared(kTRUE);
2466 p2->SetShared(kTRUE);
2472 if (sumshared>cutN0){
2473 for (Int_t i=0;i<4;i++){
2474 if (s1->GetOverlapLabel(3*i)==0){
2475 s1->SetOverlapLabel(3*i, s2->GetLabel());
2476 s1->SetOverlapLabel(3*i+1,sumshared);
2477 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2481 for (Int_t i=0;i<4;i++){
2482 if (s2->GetOverlapLabel(3*i)==0){
2483 s2->SetOverlapLabel(3*i, s1->GetLabel());
2484 s2->SetOverlapLabel(3*i+1,sumshared);
2485 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2492 void AliTPCtracker::SignShared(TObjArray * arr)
2495 //sort trackss according sectors
2497 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2498 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2500 //if (pt) RotateToLocal(pt);
2504 arr->Sort(); // sorting according relative sectors
2505 arr->Expand(arr->GetEntries());
2508 Int_t nseed=arr->GetEntriesFast();
2509 for (Int_t i=0; i<nseed; i++) {
2510 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2512 for (Int_t j=0;j<12;j++){
2513 pt->SetOverlapLabel(j,0);
2516 for (Int_t i=0; i<nseed; i++) {
2517 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2519 if (pt->GetRemoval()>10) continue;
2520 for (Int_t j=i+1; j<nseed; j++){
2521 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2522 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2524 if (pt2->GetRemoval()<=10) {
2525 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2533 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
2536 //sort tracks in array according mode criteria
2537 Int_t nseed = arr->GetEntriesFast();
2538 for (Int_t i=0; i<nseed; i++) {
2539 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2550 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
2553 // Loop over all tracks and remove overlaped tracks (with lower quality)
2555 // 1. Unsign clusters
2556 // 2. Sort tracks according quality
2557 // Quality is defined by the number of cluster between first and last points
2559 // 3. Loop over tracks - decreasing quality order
2560 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
2561 // b.) remove - If the minimal number of clusters less than minimal and not ITS
2562 // c.) if track accepted - sign clusters
2564 //Called in - AliTPCtracker::Clusters2Tracks()
2565 // - AliTPCtracker::PropagateBack()
2566 // - AliTPCtracker::RefitInward()
2569 // factor1 - factor for constrained
2570 // factor2 - for non constrained tracks
2571 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
2575 Int_t nseed = arr->GetEntriesFast();
2576 Float_t * quality = new Float_t[nseed];
2577 Int_t * indexes = new Int_t[nseed];
2581 for (Int_t i=0; i<nseed; i++) {
2582 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2587 pt->UpdatePoints(); //select first last max dens points
2588 Float_t * points = pt->GetPoints();
2589 if (points[3]<0.8) quality[i] =-1;
2590 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2591 //prefer high momenta tracks if overlaps
2592 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
2594 TMath::Sort(nseed,quality,indexes);
2597 for (Int_t itrack=0; itrack<nseed; itrack++) {
2598 Int_t trackindex = indexes[itrack];
2599 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
2602 if (quality[trackindex]<0){
2603 MarkSeedFree( arr->RemoveAt(trackindex) );
2608 Int_t first = Int_t(pt->GetPoints()[0]);
2609 Int_t last = Int_t(pt->GetPoints()[2]);
2610 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2612 Int_t found,foundable,shared;
2613 pt->GetClusterStatistic(first,last, found, foundable,shared,kFALSE); // better to get statistic in "high-dens" region do't use full track as in line bellow
2614 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2615 Bool_t itsgold =kFALSE;
2618 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2622 if (Float_t(shared+1)/Float_t(found+1)>factor){
2623 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2624 if( AliTPCReconstructor::StreamLevel()>3){
2625 TTreeSRedirector &cstream = *fDebugStreamer;
2626 cstream<<"RemoveUsed"<<
2627 "iter="<<fIteration<<
2631 MarkSeedFree( arr->RemoveAt(trackindex) );
2634 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
2635 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2636 if( AliTPCReconstructor::StreamLevel()>3){
2637 TTreeSRedirector &cstream = *fDebugStreamer;
2638 cstream<<"RemoveShort"<<
2639 "iter="<<fIteration<<
2643 MarkSeedFree( arr->RemoveAt(trackindex) );
2649 //if (sharedfactor>0.4) continue;
2650 if (pt->GetKinkIndexes()[0]>0) continue;
2651 //Remove tracks with undefined properties - seems
2652 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
2654 for (Int_t i=first; i<last; i++) {
2655 Int_t index=pt->GetClusterIndex2(i);
2656 // if (index<0 || index&0x8000 ) continue;
2657 if (index<0 || index&0x8000 ) continue;
2658 AliTPCclusterMI *c= pt->GetClusterPointer(i);
2665 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2671 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
2674 // Dump clusters after reco
2675 // signed and unsigned cluster can be visualized
2676 // 1. Unsign all cluster
2677 // 2. Sign all used clusters
2680 Int_t nseed = trackArray->GetEntries();
2681 for (Int_t i=0; i<nseed; i++){
2682 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
2686 Bool_t isKink=pt->GetKinkIndex(0)!=0;
2687 for (Int_t j=0; j<160; ++j) {
2688 Int_t index=pt->GetClusterIndex2(j);
2689 if (index<0) continue;
2690 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2692 if (isKink) c->Use(100); // kink
2693 c->Use(10); // by default usage 10
2698 for (Int_t sec=0;sec<fkNIS;sec++){
2699 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2700 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2701 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
2702 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2703 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2704 (*fDebugStreamer)<<"clDump"<<
2712 cla = fInnerSec[sec][row].GetClusters2();
2713 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
2714 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2715 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2716 (*fDebugStreamer)<<"clDump"<<
2727 for (Int_t sec=0;sec<fkNOS;sec++){
2728 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2729 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2730 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
2732 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2733 cl->GetGlobalXYZ(gx);
2734 (*fDebugStreamer)<<"clDump"<<
2742 cla = fOuterSec[sec][row].GetClusters2();
2743 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
2745 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2746 cl->GetGlobalXYZ(gx);
2747 (*fDebugStreamer)<<"clDump"<<
2759 void AliTPCtracker::UnsignClusters()
2762 // loop over all clusters and unsign them
2765 for (Int_t sec=0;sec<fkNIS;sec++){
2766 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2767 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2768 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2769 // if (cl[icl].IsUsed(10))
2770 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2771 cla = fInnerSec[sec][row].GetClusters2();
2772 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2773 //if (cl[icl].IsUsed(10))
2774 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2778 for (Int_t sec=0;sec<fkNOS;sec++){
2779 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2780 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2781 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2782 //if (cl[icl].IsUsed(10))
2783 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2784 cla = fOuterSec[sec][row].GetClusters2();
2785 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2786 //if (cl[icl].IsUsed(10))
2787 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2795 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
2798 //sign clusters to be "used"
2800 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2801 // loop over "primaries"
2815 Int_t nseed = arr->GetEntriesFast();
2816 for (Int_t i=0; i<nseed; i++) {
2817 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2821 if (!(pt->IsActive())) continue;
2822 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2823 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2825 sumdens2+= dens*dens;
2826 sumn += pt->GetNumberOfClusters();
2827 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2828 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2831 sumchi2 +=chi2*chi2;
2836 Float_t mdensity = 0.9;
2837 Float_t meann = 130;
2838 Float_t meanchi = 1;
2839 Float_t sdensity = 0.1;
2840 Float_t smeann = 10;
2841 Float_t smeanchi =0.4;
2845 mdensity = sumdens/sum;
2847 meanchi = sumchi/sum;
2849 sdensity = sumdens2/sum-mdensity*mdensity;
2851 sdensity = TMath::Sqrt(sdensity);
2855 smeann = sumn2/sum-meann*meann;
2857 smeann = TMath::Sqrt(smeann);
2861 smeanchi = sumchi2/sum - meanchi*meanchi;
2863 smeanchi = TMath::Sqrt(smeanchi);
2869 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
2871 for (Int_t i=0; i<nseed; i++) {
2872 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2876 if (pt->GetBSigned()) continue;
2877 if (pt->GetBConstrain()) continue;
2878 //if (!(pt->IsActive())) continue;
2880 Int_t found,foundable,shared;
2881 pt->GetClusterStatistic(0,160,found, foundable,shared);
2882 if (shared/float(found)>0.3) {
2883 if (shared/float(found)>0.9 ){
2884 //MarkSeedFree( arr->RemoveAt(i) );
2889 Bool_t isok =kFALSE;
2890 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2892 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2894 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2896 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2900 for (Int_t j=0; j<160; ++j) {
2901 Int_t index=pt->GetClusterIndex2(j);
2902 if (index<0) continue;
2903 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2905 //if (!(c->IsUsed(10))) c->Use();
2912 Double_t maxchi = meanchi+2.*smeanchi;
2914 for (Int_t i=0; i<nseed; i++) {
2915 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2919 //if (!(pt->IsActive())) continue;
2920 if (pt->GetBSigned()) continue;
2921 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
2922 if (chi>maxchi) continue;
2925 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2927 //sign only tracks with enoug big density at the beginning
2929 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
2932 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2933 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2935 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2936 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2939 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2940 //Int_t noc=pt->GetNumberOfClusters();
2941 pt->SetBSigned(kTRUE);
2942 for (Int_t j=0; j<160; ++j) {
2944 Int_t index=pt->GetClusterIndex2(j);
2945 if (index<0) continue;
2946 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2948 // if (!(c->IsUsed(10))) c->Use();
2953 // gLastCheck = nseed;
2962 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
2965 // back propagation of ESD tracks
2968 if (!event) return 0;
2969 const Int_t kMaxFriendTracks=2000;
2972 // extract correction object for multiplicity dependence of dEdx
2973 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
2975 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
2977 AliFatal("Tranformations not in RefitInward");
2980 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
2981 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
2982 Int_t nContribut = event->GetNumberOfTracks();
2983 TGraphErrors * graphMultDependenceDeDx = 0x0;
2984 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
2985 if (recoParam->GetUseTotCharge()) {
2986 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2988 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2994 //PrepareForProlongation(fSeeds,1);
2995 PropagateForward2(fSeeds);
2996 RemoveUsed2(fSeeds,0.4,0.4,20);
2998 Int_t entriesSeed=fSeeds->GetEntries();
2999 TObjArray arraySeed(entriesSeed);
3000 for (Int_t i=0;i<entriesSeed;i++) {
3001 arraySeed.AddAt(fSeeds->At(i),i);
3003 SignShared(&arraySeed);
3004 // FindCurling(fSeeds, event,2); // find multi found tracks
3005 FindSplitted(fSeeds, event,2); // find multi found tracks
3006 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,2); // find multi found tracks
3009 Int_t nseed = fSeeds->GetEntriesFast();
3010 for (Int_t i=0;i<nseed;i++){
3011 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3012 if (!seed) continue;
3013 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
3014 AliESDtrack *esd=event->GetTrack(i);
3016 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3017 AliExternalTrackParam paramIn;
3018 AliExternalTrackParam paramOut;
3019 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3020 if (AliTPCReconstructor::StreamLevel()>2) {
3021 (*fDebugStreamer)<<"RecoverIn"<<
3025 "pout.="<<¶mOut<<
3030 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3031 seed->SetNumberOfClusters(ncl);
3035 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3036 seed->UpdatePoints();
3037 AddCovariance(seed);
3038 MakeESDBitmaps(seed, esd);
3039 seed->CookdEdx(0.02,0.6);
3040 CookLabel(seed,0.1); //For comparison only
3042 if (AliTPCReconstructor::StreamLevel()>1 && seed!=0) {
3043 TTreeSRedirector &cstream = *fDebugStreamer;
3050 if (seed->GetNumberOfClusters()>15){
3051 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3052 esd->SetTPCPoints(seed->GetPoints());
3053 esd->SetTPCPointsF(seed->GetNFoundable());
3054 Int_t ndedx = seed->GetNCDEDX(0);
3055 Float_t sdedx = seed->GetSDEDX(0);
3056 Float_t dedx = seed->GetdEdx();
3057 // apply mutliplicity dependent dEdx correction if available
3058 if (graphMultDependenceDeDx) {
3059 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3060 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3062 esd->SetTPCsignal(dedx, sdedx, ndedx);
3064 // fill new dEdx information
3066 Double32_t signal[4];
3067 Double32_t signalMax[4];
3071 for(Int_t iarr=0;iarr<3;iarr++) {
3072 signal[iarr] = seed->GetDEDXregion(iarr+1);
3073 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3074 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3075 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3077 signal[3] = seed->GetDEDXregion(4);
3078 signalMax[3] = seed->GetDEDXregion(8);
3081 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3082 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3083 infoTpcPid->SetTPCSignalsQmax(signalMax);
3084 esd->SetTPCdEdxInfo(infoTpcPid);
3086 // add seed to the esd track in Calib level
3088 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3089 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3090 // RS: this is the only place where the seed is created not in the pool,
3091 // since it should belong to ESDevent
3092 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3093 esd->AddCalibObject(seedCopy);
3098 //printf("problem\n");
3101 //FindKinks(fSeeds,event);
3102 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(2,fSeeds);
3103 Info("RefitInward","Number of refitted tracks %d",ntracks);
3105 AliCosmicTracker::FindCosmic(event, kTRUE);
3107 FillClusterOccupancyInfo();
3113 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3116 // back propagation of ESD tracks
3118 if (!event) return 0;
3123 PropagateBack(fSeeds);
3124 RemoveUsed2(fSeeds,0.4,0.4,20);
3125 //FindCurling(fSeeds, fEvent,1);
3126 FindSplitted(fSeeds, event,1); // find multi found tracks
3127 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3130 Int_t nseed = fSeeds->GetEntriesFast();
3132 for (Int_t i=0;i<nseed;i++){
3133 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3134 if (!seed) continue;
3135 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3136 seed->UpdatePoints();
3137 AddCovariance(seed);
3138 AliESDtrack *esd=event->GetTrack(i);
3139 if (!esd) continue; //never happen
3140 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3141 AliExternalTrackParam paramIn;
3142 AliExternalTrackParam paramOut;
3143 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3144 if (AliTPCReconstructor::StreamLevel()>2) {
3145 (*fDebugStreamer)<<"RecoverBack"<<
3149 "pout.="<<¶mOut<<
3154 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3155 seed->SetNumberOfClusters(ncl);
3158 seed->CookdEdx(0.02,0.6);
3159 CookLabel(seed,0.1); //For comparison only
3160 if (seed->GetNumberOfClusters()>15){
3161 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3162 esd->SetTPCPoints(seed->GetPoints());
3163 esd->SetTPCPointsF(seed->GetNFoundable());
3164 Int_t ndedx = seed->GetNCDEDX(0);
3165 Float_t sdedx = seed->GetSDEDX(0);
3166 Float_t dedx = seed->GetdEdx();
3167 esd->SetTPCsignal(dedx, sdedx, ndedx);
3169 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3170 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3171 if (AliTPCReconstructor::StreamLevel()>1 && esd) {
3172 (*fDebugStreamer)<<"Cback"<<
3175 "EventNrInFile="<<eventnumber<<
3180 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(1,fSeeds);
3181 //FindKinks(fSeeds,event);
3182 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3190 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3193 // Post process events
3195 if (!event) return 0;
3198 // Set TPC event status
3201 // event affected by HV dip
3203 if(IsTPCHVDipEvent(event)) {
3204 event->ResetDetectorStatus(AliDAQ::kTPC);
3207 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3213 void AliTPCtracker::DeleteSeeds()
3222 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3225 //read seeds from the event
3227 Int_t nentr=event->GetNumberOfTracks();
3229 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3234 fSeeds = new TObjArray(nentr);
3238 for (Int_t i=0; i<nentr; i++) {
3239 AliESDtrack *esd=event->GetTrack(i);
3240 ULong_t status=esd->GetStatus();
3241 if (!(status&AliESDtrack::kTPCin)) continue;
3242 AliTPCtrack t(*esd);
3243 t.SetNumberOfClusters(0);
3244 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3245 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3246 seed->SetPoolID(fLastSeedID);
3247 seed->SetUniqueID(esd->GetID());
3248 AddCovariance(seed); //add systematic ucertainty
3249 for (Int_t ikink=0;ikink<3;ikink++) {
3250 Int_t index = esd->GetKinkIndex(ikink);
3251 seed->GetKinkIndexes()[ikink] = index;
3252 if (index==0) continue;
3253 index = TMath::Abs(index);
3254 AliESDkink * kink = fEvent->GetKink(index-1);
3255 if (kink&&esd->GetKinkIndex(ikink)<0){
3256 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3257 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3259 if (kink&&esd->GetKinkIndex(ikink)>0){
3260 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3261 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3265 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3266 //RS if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3267 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3268 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3269 // fSeeds->AddAt(0,i);
3270 // MarkSeedFree( seed );
3276 // rotate to the local coordinate system
3278 fSectors=fInnerSec; fN=fkNIS;
3279 Double_t alpha=seed->GetAlpha();
3280 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3281 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3282 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3283 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3284 alpha-=seed->GetAlpha();
3285 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3286 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3287 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3288 AliWarning(Form("Rotating track over %f",alpha));
3289 if (!seed->Rotate(alpha)) {
3290 MarkSeedFree( seed );
3296 if (esd->GetKinkIndex(0)<=0){
3297 for (Int_t irow=0;irow<160;irow++){
3298 Int_t index = seed->GetClusterIndex2(irow);
3301 AliTPCclusterMI * cl = GetClusterMI(index);
3302 seed->SetClusterPointer(irow,cl);
3304 if ((index & 0x8000)==0){
3305 cl->Use(10); // accepted cluster
3307 cl->Use(6); // close cluster not accepted
3310 Info("ReadSeeds","Not found cluster");
3315 fSeeds->AddAt(seed,i);
3321 //_____________________________________________________________________________
3322 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3323 Float_t deltay, Int_t ddsec) {
3324 //-----------------------------------------------------------------
3325 // This function creates track seeds.
3326 // SEEDING WITH VERTEX CONSTRAIN
3327 //-----------------------------------------------------------------
3328 // cuts[0] - fP4 cut
3329 // cuts[1] - tan(phi) cut
3330 // cuts[2] - zvertex cut
3331 // cuts[3] - fP3 cut
3339 Double_t x[5], c[15];
3340 // Int_t di = i1-i2;
3342 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3343 seed->SetPoolID(fLastSeedID);
3344 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3345 Double_t cs=cos(alpha), sn=sin(alpha);
3347 // Double_t x1 =fOuterSec->GetX(i1);
3348 //Double_t xx2=fOuterSec->GetX(i2);
3350 Double_t x1 =GetXrow(i1);
3351 Double_t xx2=GetXrow(i2);
3353 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3355 Int_t imiddle = (i2+i1)/2; //middle pad row index
3356 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3357 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3361 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3362 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3363 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3366 // change cut on curvature if it can't reach this layer
3367 // maximal curvature set to reach it
3368 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3369 if (dvertexmax*0.5*cuts[0]>0.85){
3370 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3372 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3375 if (deltay>0) ddsec = 0;
3376 // loop over clusters
3377 for (Int_t is=0; is < kr1; is++) {
3379 if (kr1[is]->IsUsed(10)) continue;
3380 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3381 //if (TMath::Abs(y1)>ymax) continue;
3383 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3385 // find possible directions
3386 Float_t anglez = (z1-z3)/(x1-x3);
3387 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3390 //find rotation angles relative to line given by vertex and point 1
3391 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3392 Double_t dvertex = TMath::Sqrt(dvertex2);
3393 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3394 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3397 // loop over 2 sectors
3403 Double_t dddz1=0; // direction of delta inclination in z axis
3410 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3411 Int_t sec2 = sec + dsec;
3413 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3414 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3415 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3416 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3417 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3418 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3420 // rotation angles to p1-p3
3421 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3422 Double_t x2, y2, z2;
3424 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3427 Double_t dxx0 = (xx2-x3)*cs13r;
3428 Double_t dyy0 = (xx2-x3)*sn13r;
3429 for (Int_t js=index1; js < index2; js++) {
3430 const AliTPCclusterMI *kcl = kr2[js];
3431 if (kcl->IsUsed(10)) continue;
3433 //calcutate parameters
3435 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3437 if (TMath::Abs(yy0)<0.000001) continue;
3438 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3439 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3440 Double_t r02 = (0.25+y0*y0)*dvertex2;
3441 //curvature (radius) cut
3442 if (r02<r2min) continue;
3446 Double_t c0 = 1/TMath::Sqrt(r02);
3450 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3451 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3452 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3453 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3456 Double_t z0 = kcl->GetZ();
3457 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3458 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3461 Double_t dip = (z1-z0)*c0/dfi1;
3462 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3473 x2= xx2*cs-y2*sn*dsec;
3474 y2=+xx2*sn*dsec+y2*cs;
3484 // do we have cluster at the middle ?
3486 GetProlongation(x1,xm,x,ym,zm);
3488 AliTPCclusterMI * cm=0;
3489 if (TMath::Abs(ym)-ymaxm<0){
3490 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3491 if ((!cm) || (cm->IsUsed(10))) {
3496 // rotate y1 to system 0
3497 // get state vector in rotated system
3498 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3499 Double_t xr2 = x0*cs+yr1*sn*dsec;
3500 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3502 GetProlongation(xx2,xm,xr,ym,zm);
3503 if (TMath::Abs(ym)-ymaxm<0){
3504 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3505 if ((!cm) || (cm->IsUsed(10))) {
3512 // Double_t dym = 0;
3513 // Double_t dzm = 0;
3515 // dym = ym - cm->GetY();
3516 // dzm = zm - cm->GetZ();
3523 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3524 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
3525 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3526 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3527 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3529 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3530 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3531 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3532 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3533 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3534 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3536 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3537 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3538 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3539 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3543 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3544 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3545 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3546 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3547 c[13]=f30*sy1*f40+f32*sy2*f42;
3548 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3550 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3552 UInt_t index=kr1.GetIndex(is);
3553 if (seed) {MarkSeedFree(seed); seed = 0;}
3554 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3555 seed->SetPoolID(fLastSeedID);
3556 track->SetIsSeeding(kTRUE);
3557 track->SetSeed1(i1);
3558 track->SetSeed2(i2);
3559 track->SetSeedType(3);
3563 FollowProlongation(*track, (i1+i2)/2,1);
3564 Int_t foundable,found,shared;
3565 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3566 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3567 MarkSeedFree(seed); seed = 0;
3573 FollowProlongation(*track, i2,1);
3577 track->SetBConstrain(1);
3578 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
3579 track->SetLastPoint(i1); // first cluster in track position
3580 track->SetFirstPoint(track->GetLastPoint());
3582 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3583 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3584 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3585 MarkSeedFree(seed); seed = 0;
3589 // Z VERTEX CONDITION
3590 Double_t zv, bz=GetBz();
3591 if ( !track->GetZAt(0.,bz,zv) ) continue;
3592 if (TMath::Abs(zv-z3)>cuts[2]) {
3593 FollowProlongation(*track, TMath::Max(i2-20,0));
3594 if ( !track->GetZAt(0.,bz,zv) ) continue;
3595 if (TMath::Abs(zv-z3)>cuts[2]){
3596 FollowProlongation(*track, TMath::Max(i2-40,0));
3597 if ( !track->GetZAt(0.,bz,zv) ) continue;
3598 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3599 // make seed without constrain
3600 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3601 FollowProlongation(*track2, i2,1);
3602 track2->SetBConstrain(kFALSE);
3603 track2->SetSeedType(1);
3604 arr->AddLast(track2);
3605 MarkSeedFree( seed ); seed = 0;
3609 MarkSeedFree( seed ); seed = 0;
3616 track->SetSeedType(0);
3617 arr->AddLast(track); // note, track is seed, don't free the seed
3618 seed = new( NextFreeSeed() ) AliTPCseed;
3619 seed->SetPoolID(fLastSeedID);
3621 // don't consider other combinations
3622 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3628 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3630 if (seed) MarkSeedFree( seed );
3634 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3639 //-----------------------------------------------------------------
3640 // This function creates track seeds.
3641 //-----------------------------------------------------------------
3642 // cuts[0] - fP4 cut
3643 // cuts[1] - tan(phi) cut
3644 // cuts[2] - zvertex cut
3645 // cuts[3] - fP3 cut
3655 Double_t x[5], c[15];
3657 // make temporary seed
3658 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3659 seed->SetPoolID(fLastSeedID);
3660 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3661 // Double_t cs=cos(alpha), sn=sin(alpha);
3666 Double_t x1 = GetXrow(i1-1);
3667 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3668 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
3670 Double_t x1p = GetXrow(i1);
3671 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3673 Double_t x1m = GetXrow(i1-2);
3674 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3677 //last 3 padrow for seeding
3678 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
3679 Double_t x3 = GetXrow(i1-7);
3680 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
3682 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
3683 Double_t x3p = GetXrow(i1-6);
3685 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
3686 Double_t x3m = GetXrow(i1-8);
3691 Int_t im = i1-4; //middle pad row index
3692 Double_t xm = GetXrow(im); // radius of middle pad-row
3693 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
3694 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
3697 Double_t deltax = x1-x3;
3698 Double_t dymax = deltax*cuts[1];
3699 Double_t dzmax = deltax*cuts[3];
3701 // loop over clusters
3702 for (Int_t is=0; is < kr1; is++) {
3704 if (kr1[is]->IsUsed(10)) continue;
3705 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3707 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3709 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3710 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3716 for (Int_t js=index1; js < index2; js++) {
3717 const AliTPCclusterMI *kcl = kr3[js];
3718 if (kcl->IsUsed(10)) continue;
3720 // apply angular cuts
3721 if (TMath::Abs(y1-y3)>dymax) continue;
3724 if (TMath::Abs(z1-z3)>dzmax) continue;
3726 Double_t angley = (y1-y3)/(x1-x3);
3727 Double_t anglez = (z1-z3)/(x1-x3);
3729 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3730 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3732 Double_t yyym = angley*(xm-x1)+y1;
3733 Double_t zzzm = anglez*(xm-x1)+z1;
3735 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3737 if (kcm->IsUsed(10)) continue;
3739 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3740 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3747 // look around first
3748 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3754 if (kc1m->IsUsed(10)) used++;
3756 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3762 if (kc1p->IsUsed(10)) used++;
3764 if (used>1) continue;
3765 if (found<1) continue;
3769 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3775 if (kc3m->IsUsed(10)) used++;
3779 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3785 if (kc3p->IsUsed(10)) used++;
3789 if (used>1) continue;
3790 if (found<3) continue;
3800 x[4]=F1(x1,y1,x2,y2,x3,y3);
3801 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3804 x[2]=F2(x1,y1,x2,y2,x3,y3);
3807 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3808 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3812 Double_t sy1=0.1, sz1=0.1;
3813 Double_t sy2=0.1, sz2=0.1;
3814 Double_t sy3=0.1, sy=0.1, sz=0.1;
3816 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3817 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3818 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3819 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3820 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3821 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3823 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3824 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3825 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3826 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3830 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3831 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3832 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3833 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3834 c[13]=f30*sy1*f40+f32*sy2*f42;
3835 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3837 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3839 index=kr1.GetIndex(is);
3840 if (seed) {MarkSeedFree( seed ); seed = 0;}
3841 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3842 seed->SetPoolID(fLastSeedID);
3844 track->SetIsSeeding(kTRUE);
3847 FollowProlongation(*track, i1-7,1);
3848 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
3849 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3850 MarkSeedFree( seed ); seed = 0;
3856 FollowProlongation(*track, i2,1);
3857 track->SetBConstrain(0);
3858 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
3859 track->SetFirstPoint(track->GetLastPoint());
3861 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3862 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
3863 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3864 MarkSeedFree( seed ); seed = 0;
3869 FollowProlongation(*track, TMath::Max(i2-10,0),1);
3870 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3871 FollowProlongation(*track2, i2,1);
3872 track2->SetBConstrain(kFALSE);
3873 track2->SetSeedType(4);
3874 arr->AddLast(track2);
3875 MarkSeedFree( seed ); seed = 0;
3879 //arr->AddLast(track);
3880 //seed = new AliTPCseed;
3886 Info("MakeSeeds5","\nSeeding statiistic:\t%d\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2,nout3);
3888 if (seed) MarkSeedFree(seed);
3892 //_____________________________________________________________________________
3893 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3894 Float_t deltay, Bool_t /*bconstrain*/) {
3895 //-----------------------------------------------------------------
3896 // This function creates track seeds - without vertex constraint
3897 //-----------------------------------------------------------------
3898 // cuts[0] - fP4 cut - not applied
3899 // cuts[1] - tan(phi) cut
3900 // cuts[2] - zvertex cut - not applied
3901 // cuts[3] - fP3 cut
3911 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3912 // Double_t cs=cos(alpha), sn=sin(alpha);
3913 Int_t row0 = (i1+i2)/2;
3914 Int_t drow = (i1-i2)/2;
3915 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3916 AliTPCtrackerRow * kr=0;
3918 AliTPCpolyTrack polytrack;
3919 Int_t nclusters=fSectors[sec][row0];
3920 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3921 seed->SetPoolID(fLastSeedID);
3926 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
3928 Int_t nfoundable =0;
3929 for (Int_t iter =1; iter<2; iter++){ //iterations
3930 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3931 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
3932 const AliTPCclusterMI * cl= kr0[is];
3934 if (cl->IsUsed(10)) {
3940 Double_t x = kr0.GetX();
3941 // Initialization of the polytrack
3946 Double_t y0= cl->GetY();
3947 Double_t z0= cl->GetZ();
3951 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3952 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
3954 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
3955 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
3956 polytrack.AddPoint(x,y0,z0,erry, errz);
3959 if (cl->IsUsed(10)) sumused++;
3962 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3963 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3966 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3967 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3968 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
3969 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3970 if (cl1->IsUsed(10)) sumused++;
3971 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3975 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3977 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
3978 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3979 if (cl2->IsUsed(10)) sumused++;
3980 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3983 if (sumused>0) continue;
3985 polytrack.UpdateParameters();
3991 nfoundable = polytrack.GetN();
3992 nfound = nfoundable;
3994 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3995 Float_t maxdist = 0.8*(1.+3./(ddrow));
3996 for (Int_t delta = -1;delta<=1;delta+=2){
3997 Int_t row = row0+ddrow*delta;
3998 kr = &(fSectors[sec][row]);
3999 Double_t xn = kr->GetX();
4000 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
4001 polytrack.GetFitPoint(xn,yn,zn);
4002 if (TMath::Abs(yn)>ymax1) continue;
4004 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
4006 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
4009 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4010 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4011 if (cln->IsUsed(10)) {
4012 // printf("used\n");
4020 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4025 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4026 polytrack.UpdateParameters();
4029 if ( (sumused>3) || (sumused>0.5*nfound)) {
4030 //printf("sumused %d\n",sumused);
4035 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4036 AliTPCpolyTrack track2;
4038 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4039 if (track2.GetN()<0.5*nfoundable) continue;
4042 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4044 // test seed with and without constrain
4045 for (Int_t constrain=0; constrain<=0;constrain++){
4046 // add polytrack candidate
4048 Double_t x[5], c[15];
4049 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4050 track2.GetBoundaries(x3,x1);
4052 track2.GetFitPoint(x1,y1,z1);
4053 track2.GetFitPoint(x2,y2,z2);
4054 track2.GetFitPoint(x3,y3,z3);
4056 //is track pointing to the vertex ?
4059 polytrack.GetFitPoint(x0,y0,z0);
4072 x[4]=F1(x1,y1,x2,y2,x3,y3);
4074 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4075 x[2]=F2(x1,y1,x2,y2,x3,y3);
4077 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4078 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4079 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4080 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4083 Double_t sy =0.1, sz =0.1;
4084 Double_t sy1=0.02, sz1=0.02;
4085 Double_t sy2=0.02, sz2=0.02;
4089 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4092 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4093 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4094 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4095 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4096 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4097 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4099 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4100 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4101 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4102 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4107 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4108 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4109 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4110 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4111 c[13]=f30*sy1*f40+f32*sy2*f42;
4112 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4114 //Int_t row1 = fSectors->GetRowNumber(x1);
4115 Int_t row1 = GetRowNumber(x1);
4119 if (seed) {MarkSeedFree( seed ); seed = 0;}
4120 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4121 seed->SetPoolID(fLastSeedID);
4122 track->SetIsSeeding(kTRUE);
4123 Int_t rc=FollowProlongation(*track, i2);
4124 if (constrain) track->SetBConstrain(1);
4126 track->SetBConstrain(0);
4127 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4128 track->SetFirstPoint(track->GetLastPoint());
4130 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4131 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4132 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4133 MarkSeedFree( seed ); seed = 0;
4136 arr->AddLast(track); // track IS seed, don't free seed
4137 seed = new( NextFreeSeed() ) AliTPCseed;
4138 seed->SetPoolID(fLastSeedID);
4142 } // if accepted seed
4145 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4147 if (seed) MarkSeedFree( seed );
4151 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4155 //reseed using track points
4156 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4157 Int_t p1 = int(r1*track->GetNumberOfClusters());
4158 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4160 Double_t x0[3],x1[3],x2[3];
4161 for (Int_t i=0;i<3;i++){
4167 // find track position at given ratio of the length
4168 Int_t sec0=0, sec1=0, sec2=0;
4171 for (Int_t i=0;i<160;i++){
4172 if (track->GetClusterPointer(i)){
4174 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4175 if ( (index<p0) || x0[0]<0 ){
4176 if (trpoint->GetX()>1){
4177 clindex = track->GetClusterIndex2(i);
4179 x0[0] = trpoint->GetX();
4180 x0[1] = trpoint->GetY();
4181 x0[2] = trpoint->GetZ();
4182 sec0 = ((clindex&0xff000000)>>24)%18;
4187 if ( (index<p1) &&(trpoint->GetX()>1)){
4188 clindex = track->GetClusterIndex2(i);
4190 x1[0] = trpoint->GetX();
4191 x1[1] = trpoint->GetY();
4192 x1[2] = trpoint->GetZ();
4193 sec1 = ((clindex&0xff000000)>>24)%18;
4196 if ( (index<p2) &&(trpoint->GetX()>1)){
4197 clindex = track->GetClusterIndex2(i);
4199 x2[0] = trpoint->GetX();
4200 x2[1] = trpoint->GetY();
4201 x2[2] = trpoint->GetZ();
4202 sec2 = ((clindex&0xff000000)>>24)%18;
4209 Double_t alpha, cs,sn, xx2,yy2;
4211 alpha = (sec1-sec2)*fSectors->GetAlpha();
4212 cs = TMath::Cos(alpha);
4213 sn = TMath::Sin(alpha);
4214 xx2= x1[0]*cs-x1[1]*sn;
4215 yy2= x1[0]*sn+x1[1]*cs;
4219 alpha = (sec0-sec2)*fSectors->GetAlpha();
4220 cs = TMath::Cos(alpha);
4221 sn = TMath::Sin(alpha);
4222 xx2= x0[0]*cs-x0[1]*sn;
4223 yy2= x0[0]*sn+x0[1]*cs;
4229 Double_t x[5],c[15];
4233 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4234 // if (x[4]>1) return 0;
4235 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4236 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4237 //if (TMath::Abs(x[3]) > 2.2) return 0;
4238 //if (TMath::Abs(x[2]) > 1.99) return 0;
4240 Double_t sy =0.1, sz =0.1;
4242 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4243 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4244 Double_t sy3=0.01+track->GetSigmaY2();
4246 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4247 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4248 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4249 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4250 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4251 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4253 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4254 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4255 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4256 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4261 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4262 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4263 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4264 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4265 c[13]=f30*sy1*f40+f32*sy2*f42;
4266 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4268 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4269 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4270 seed->SetPoolID(fLastSeedID);
4271 // Double_t y0,z0,y1,z1, y2,z2;
4272 //seed->GetProlongation(x0[0],y0,z0);
4273 // seed->GetProlongation(x1[0],y1,z1);
4274 //seed->GetProlongation(x2[0],y2,z2);
4276 seed->SetLastPoint(pp2);
4277 seed->SetFirstPoint(pp2);
4284 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4288 //reseed using founded clusters
4290 // Find the number of clusters
4291 Int_t nclusters = 0;
4292 for (Int_t irow=0;irow<160;irow++){
4293 if (track->GetClusterIndex(irow)>0) nclusters++;
4297 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4298 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4299 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4302 Double_t xyz[3][3]={{0}};
4303 Int_t row[3]={0},sec[3]={0,0,0};
4305 // find track row position at given ratio of the length
4307 for (Int_t irow=0;irow<160;irow++){
4308 if (track->GetClusterIndex2(irow)<0) continue;
4310 for (Int_t ipoint=0;ipoint<3;ipoint++){
4311 if (index<=ipos[ipoint]) row[ipoint] = irow;
4315 //Get cluster and sector position
4316 for (Int_t ipoint=0;ipoint<3;ipoint++){
4317 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4318 AliTPCclusterMI * cl = GetClusterMI(clindex);
4321 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4324 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4325 xyz[ipoint][0] = GetXrow(row[ipoint]);
4326 xyz[ipoint][1] = cl->GetY();
4327 xyz[ipoint][2] = cl->GetZ();
4331 // Calculate seed state vector and covariance matrix
4333 Double_t alpha, cs,sn, xx2,yy2;
4335 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4336 cs = TMath::Cos(alpha);
4337 sn = TMath::Sin(alpha);
4338 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4339 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4343 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4344 cs = TMath::Cos(alpha);
4345 sn = TMath::Sin(alpha);
4346 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4347 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4353 Double_t x[5],c[15];
4357 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4358 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4359 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4361 Double_t sy =0.1, sz =0.1;
4363 Double_t sy1=0.2, sz1=0.2;
4364 Double_t sy2=0.2, sz2=0.2;
4367 Double_t f40=(F1(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[4])/sy;
4368 Double_t f42=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[4])/sy;
4369 Double_t f43=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[4])/sy;
4370 Double_t f20=(F2(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[2])/sy;
4371 Double_t f22=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[2])/sy;
4372 Double_t f23=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[2])/sy;
4374 Double_t f30=(F3(xyz[2][0],xyz[2][1]+sy,xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2])-x[3])/sy;
4375 Double_t f31=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2]+sz,xyz[0][2])-x[3])/sz;
4376 Double_t f32=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1]+sy,xyz[2][2],xyz[0][2])-x[3])/sy;
4377 Double_t f34=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2]+sz)-x[3])/sz;
4382 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4383 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4384 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4385 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4386 c[13]=f30*sy1*f40+f32*sy2*f42;
4387 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4389 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4390 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4391 seed->SetPoolID(fLastSeedID);
4392 seed->SetLastPoint(row[2]);
4393 seed->SetFirstPoint(row[2]);
4398 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4402 //reseed using founded clusters
4405 Int_t row[3]={0,0,0};
4406 Int_t sec[3]={0,0,0};
4408 // forward direction
4410 for (Int_t irow=r0;irow<160;irow++){
4411 if (track->GetClusterIndex(irow)>0){
4416 for (Int_t irow=160;irow>r0;irow--){
4417 if (track->GetClusterIndex(irow)>0){
4422 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4423 if (track->GetClusterIndex(irow)>0){
4431 for (Int_t irow=0;irow<r0;irow++){
4432 if (track->GetClusterIndex(irow)>0){
4437 for (Int_t irow=r0;irow>0;irow--){
4438 if (track->GetClusterIndex(irow)>0){
4443 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4444 if (track->GetClusterIndex(irow)>0){
4451 if ((row[2]-row[0])<20) return 0;
4452 if (row[1]==0) return 0;
4455 //Get cluster and sector position
4456 for (Int_t ipoint=0;ipoint<3;ipoint++){
4457 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4458 AliTPCclusterMI * cl = GetClusterMI(clindex);
4461 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4464 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4465 xyz[ipoint][0] = GetXrow(row[ipoint]);
4466 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4467 if (point&&ipoint<2){
4469 xyz[ipoint][1] = point->GetY();
4470 xyz[ipoint][2] = point->GetZ();
4473 xyz[ipoint][1] = cl->GetY();
4474 xyz[ipoint][2] = cl->GetZ();
4481 // Calculate seed state vector and covariance matrix
4483 Double_t alpha, cs,sn, xx2,yy2;
4485 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4486 cs = TMath::Cos(alpha);
4487 sn = TMath::Sin(alpha);
4488 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4489 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4493 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4494 cs = TMath::Cos(alpha);
4495 sn = TMath::Sin(alpha);
4496 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4497 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4503 Double_t x[5],c[15];
4507 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4508 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4509 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4511 Double_t sy =0.1, sz =0.1;
4513 Double_t sy1=0.2, sz1=0.2;
4514 Double_t sy2=0.2, sz2=0.2;
4517 Double_t f40=(F1(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[4])/sy;
4518 Double_t f42=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[4])/sy;
4519 Double_t f43=(F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[4])/sy;
4520 Double_t f20=(F2(xyz[2][0],xyz[2][1]+sy,xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1])-x[2])/sy;
4521 Double_t f22=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1]+sy,xyz[0][0],xyz[0][1])-x[2])/sy;
4522 Double_t f23=(F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]+sy)-x[2])/sy;
4524 Double_t f30=(F3(xyz[2][0],xyz[2][1]+sy,xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2])-x[3])/sy;
4525 Double_t f31=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2]+sz,xyz[0][2])-x[3])/sz;
4526 Double_t f32=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1]+sy,xyz[2][2],xyz[0][2])-x[3])/sy;
4527 Double_t f34=(F3(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2]+sz)-x[3])/sz;
4532 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4533 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4534 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4535 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4536 c[13]=f30*sy1*f40+f32*sy2*f42;
4537 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4539 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4540 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4541 seed->SetPoolID(fLastSeedID);
4542 seed->SetLastPoint(row[2]);
4543 seed->SetFirstPoint(row[2]);
4544 for (Int_t i=row[0];i<row[2];i++){
4545 seed->SetClusterIndex(i, track->GetClusterIndex(i));
4553 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4556 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4558 // Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4560 // Two reasons to have multiple find tracks
4561 // 1. Curling tracks can be find more than once
4562 // 2. Splitted tracks
4563 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
4564 // b.) Edge effect on the sector boundaries
4567 // Algorithm done in 2 phases - because of CPU consumption
4568 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4570 // Algorihm for curling tracks sign:
4571 // 1 phase -makes a very rough fast cuts to minimize combinatorics
4572 // a.) opposite sign
4573 // b.) one of the tracks - not pointing to the primary vertex -
4574 // c.) delta tan(theta)
4576 // 2 phase - calculates DCA between tracks - time consument
4581 // General cuts - for splitted tracks and for curling tracks
4583 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
4585 // Curling tracks cuts
4590 Int_t nentries = array->GetEntriesFast();
4591 AliHelix *helixes = new AliHelix[nentries];
4592 Float_t *xm = new Float_t[nentries];
4593 Float_t *dz0 = new Float_t[nentries];
4594 Float_t *dz1 = new Float_t[nentries];
4600 // Find track COG in x direction - point with best defined parameters
4602 for (Int_t i=0;i<nentries;i++){
4603 AliTPCseed* track = (AliTPCseed*)array->At(i);
4604 if (!track) continue;
4605 track->SetCircular(0);
4606 new (&helixes[i]) AliHelix(*track);
4610 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4613 for (Int_t icl=0; icl<160; icl++){
4614 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
4620 if (ncl>0) xm[i]/=Float_t(ncl);
4623 for (Int_t i0=0;i0<nentries;i0++){
4624 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4625 if (!track0) continue;
4626 Float_t xc0 = helixes[i0].GetHelix(6);
4627 Float_t yc0 = helixes[i0].GetHelix(7);
4628 Float_t r0 = helixes[i0].GetHelix(8);
4629 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4630 Float_t fi0 = TMath::ATan2(yc0,xc0);
4632 for (Int_t i1=i0+1;i1<nentries;i1++){
4633 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4634 if (!track1) continue;
4635 Int_t lab0=track0->GetLabel();
4636 Int_t lab1=track1->GetLabel();
4637 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4639 Float_t xc1 = helixes[i1].GetHelix(6);
4640 Float_t yc1 = helixes[i1].GetHelix(7);
4641 Float_t r1 = helixes[i1].GetHelix(8);
4642 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4643 Float_t fi1 = TMath::ATan2(yc1,xc1);
4645 Float_t dfi = fi0-fi1;
4648 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4649 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4650 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4652 // if short tracks with undefined sign
4653 fi1 = -TMath::ATan2(yc1,-xc1);
4656 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4659 // debug stream to tune "fast cuts"
4661 Double_t dist[3]; // distance at X
4662 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
4663 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4664 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4665 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4666 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4667 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4668 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4669 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4673 for (Int_t icl=0; icl<160; icl++){
4674 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
4675 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
4678 if (cl0==cl1) sums++;
4682 if (AliTPCReconstructor::StreamLevel()>5) {
4683 TTreeSRedirector &cstream = *fDebugStreamer;
4688 "Tr0.="<<track0<< // seed0
4689 "Tr1.="<<track1<< // seed1
4690 "h0.="<<&helixes[i0]<<
4691 "h1.="<<&helixes[i1]<<
4693 "sum="<<sum<< //the sum of rows with cl in both
4694 "sums="<<sums<< //the sum of shared clusters
4695 "xm0="<<xm[i0]<< // the center of track
4696 "xm1="<<xm[i1]<< // the x center of track
4697 // General cut variables
4698 "dfi="<<dfi<< // distance in fi angle
4699 "dtheta="<<dtheta<< // distance int theta angle
4705 "dist0="<<dist[0]<< //distance x
4706 "dist1="<<dist[1]<< //distance y
4707 "dist2="<<dist[2]<< //distance z
4708 "mdist0="<<mdist[0]<< //distance x
4709 "mdist1="<<mdist[1]<< //distance y
4710 "mdist2="<<mdist[2]<< //distance z
4726 if (AliTPCReconstructor::StreamLevel()>1) {
4727 AliInfo("Time for curling tracks removal DEBUGGING MC");
4734 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
4736 // Find Splitted tracks and remove the one with worst quality
4737 // Corresponding debug streamer to tune selections - "Splitted2"
4739 // 0. Sort tracks according quility
4740 // 1. Propagate the tracks to the reference radius
4741 // 2. Double_t loop to select close tracks (only to speed up process)
4742 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
4743 // 4. Delete temporary parameters
4745 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
4747 const Double_t kCutP1=10; // delta Z cut 10 cm
4748 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
4749 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
4750 const Double_t kCutAlpha=0.15; // delta alpha cut
4751 Int_t firstpoint = 0;
4752 Int_t lastpoint = 160;
4754 Int_t nentries = array->GetEntriesFast();
4755 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
4761 //0. Sort tracks according quality
4762 //1. Propagate the ext. param to reference radius
4763 Int_t nseed = array->GetEntriesFast();
4764 if (nseed<=0) return;
4765 Float_t * quality = new Float_t[nseed];
4766 Int_t * indexes = new Int_t[nseed];
4767 for (Int_t i=0; i<nseed; i++) {
4768 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
4773 pt->UpdatePoints(); //select first last max dens points
4774 Float_t * points = pt->GetPoints();
4775 if (points[3]<0.8) quality[i] =-1;
4776 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4777 //prefer high momenta tracks if overlaps
4778 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
4780 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
4781 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
4783 TMath::Sort(nseed,quality,indexes);
4785 // 3. Loop over pair of tracks
4787 for (Int_t i0=0; i0<nseed; i0++) {
4788 Int_t index0=indexes[i0];
4789 if (!(array->UncheckedAt(index0))) continue;
4790 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
4791 if (!s1->IsActive()) continue;
4792 AliExternalTrackParam &par0=params[index0];
4793 for (Int_t i1=i0+1; i1<nseed; i1++) {
4794 Int_t index1=indexes[i1];
4795 if (!(array->UncheckedAt(index1))) continue;
4796 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
4797 if (!s2->IsActive()) continue;
4798 if (s2->GetKinkIndexes()[0]!=0)
4799 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
4800 AliExternalTrackParam &par1=params[index1];
4801 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
4802 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
4803 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
4804 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
4805 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
4806 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
4811 Int_t firstShared=lastpoint, lastShared=firstpoint;
4812 Int_t firstRow=lastpoint, lastRow=firstpoint;
4814 for (Int_t i=firstpoint;i<lastpoint;i++){
4815 if (s1->GetClusterIndex2(i)>0) nall0++;
4816 if (s2->GetClusterIndex2(i)>0) nall1++;
4817 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
4818 if (i<firstRow) firstRow=i;
4819 if (i>lastRow) lastRow=i;
4821 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
4822 if (i<firstShared) firstShared=i;
4823 if (i>lastShared) lastShared=i;
4827 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
4828 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
4830 if( AliTPCReconstructor::StreamLevel()>1){
4831 TTreeSRedirector &cstream = *fDebugStreamer;
4832 Int_t n0=s1->GetNumberOfClusters();
4833 Int_t n1=s2->GetNumberOfClusters();
4834 Int_t n0F=s1->GetNFoundable();
4835 Int_t n1F=s2->GetNFoundable();
4836 Int_t lab0=s1->GetLabel();
4837 Int_t lab1=s2->GetLabel();
4839 cstream<<"Splitted2"<<
4840 "iter="<<fIteration<<
4841 "lab0="<<lab0<< // MC label if exist
4842 "lab1="<<lab1<< // MC label if exist
4845 "ratio0="<<ratio0<< // shared ratio
4846 "ratio1="<<ratio1<< // shared ratio
4847 "p0.="<<&par0<< // track parameters
4849 "s0.="<<s1<< // full seed
4851 "n0="<<n0<< // number of clusters track 0
4852 "n1="<<n1<< // number of clusters track 1
4853 "nall0="<<nall0<< // number of clusters track 0
4854 "nall1="<<nall1<< // number of clusters track 1
4855 "n0F="<<n0F<< // number of findable
4856 "n1F="<<n1F<< // number of findable
4857 "shared="<<sumShared<< // number of shared clusters
4858 "firstS="<<firstShared<< // first and the last shared row
4859 "lastS="<<lastShared<<
4860 "firstRow="<<firstRow<< // first and the last row with cluster
4861 "lastRow="<<lastRow<< //
4865 // remove track with lower quality
4867 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
4868 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
4872 MarkSeedFree( array->RemoveAt(index1) );
4877 // 4. Delete temporary array
4887 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4890 // find Curling tracks
4891 // Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4894 // Algorithm done in 2 phases - because of CPU consumption
4895 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4896 // see detal in MC part what can be used to cut
4900 const Float_t kMaxC = 400; // maximal curvature to of the track
4901 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
4902 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
4903 const Float_t kPtRatio = 0.3; // ratio between pt
4904 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
4907 // Curling tracks cuts
4910 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
4911 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
4912 const Float_t kMinAngle = 2.9; // angle between tracks
4913 const Float_t kMaxDist = 5; // biggest distance
4915 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4918 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4919 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4920 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4921 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4922 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
4924 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4925 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4927 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
4928 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4930 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4936 Int_t nentries = array->GetEntriesFast();
4937 AliHelix *helixes = new AliHelix[nentries];
4938 for (Int_t i=0;i<nentries;i++){
4939 AliTPCseed* track = (AliTPCseed*)array->At(i);
4940 if (!track) continue;
4941 track->SetCircular(0);
4942 new (&helixes[i]) AliHelix(*track);
4948 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4954 for (Int_t i0=0;i0<nentries;i0++){
4955 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4956 if (!track0) continue;
4957 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4958 Float_t xc0 = helixes[i0].GetHelix(6);
4959 Float_t yc0 = helixes[i0].GetHelix(7);
4960 Float_t r0 = helixes[i0].GetHelix(8);
4961 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4962 Float_t fi0 = TMath::ATan2(yc0,xc0);
4964 for (Int_t i1=i0+1;i1<nentries;i1++){
4965 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4966 if (!track1) continue;
4967 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
4968 Float_t xc1 = helixes[i1].GetHelix(6);
4969 Float_t yc1 = helixes[i1].GetHelix(7);
4970 Float_t r1 = helixes[i1].GetHelix(8);
4971 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4972 Float_t fi1 = TMath::ATan2(yc1,xc1);
4974 Float_t dfi = fi0-fi1;
4977 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4978 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4979 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4983 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
4984 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
4985 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4986 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
4987 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4989 Float_t pt0 = track0->GetSignedPt();
4990 Float_t pt1 = track1->GetSignedPt();
4991 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
4992 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4993 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
4994 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
4997 // Now find closest approach
5001 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5002 if (npoints==0) continue;
5003 helixes[i0].GetClosestPhases(helixes[i1], phase);
5007 Double_t hangles[3];
5008 helixes[i0].Evaluate(phase[0][0],xyz0);
5009 helixes[i1].Evaluate(phase[0][1],xyz1);
5011 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5012 Double_t deltah[2],deltabest;
5013 if (TMath::Abs(hangles[2])<kMinAngle) continue;
5017 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5019 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5020 if (deltah[1]<deltah[0]) ibest=1;
5022 deltabest = TMath::Sqrt(deltah[ibest]);
5023 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5024 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5025 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5026 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5028 if (deltabest>kMaxDist) continue;
5029 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5030 Bool_t sign =kFALSE;
5031 if (hangles[2]>kMinAngle) sign =kTRUE;
5034 // circular[i0] = kTRUE;
5035 // circular[i1] = kTRUE;
5036 if (track0->OneOverPt()<track1->OneOverPt()){
5037 track0->SetCircular(track0->GetCircular()+1);
5038 track1->SetCircular(track1->GetCircular()+2);
5041 track1->SetCircular(track1->GetCircular()+1);
5042 track0->SetCircular(track0->GetCircular()+2);
5045 if (AliTPCReconstructor::StreamLevel()>2){
5047 //debug stream to tune "fine" cuts
5048 Int_t lab0=track0->GetLabel();
5049 Int_t lab1=track1->GetLabel();
5050 TTreeSRedirector &cstream = *fDebugStreamer;
5051 cstream<<"Curling2"<<
5067 "npoints="<<npoints<<
5068 "hangles0="<<hangles[0]<<
5069 "hangles1="<<hangles[1]<<
5070 "hangles2="<<hangles[2]<<
5073 "radius="<<radiusbest<<
5074 "deltabest="<<deltabest<<
5075 "phase0="<<phase[ibest][0]<<
5076 "phase1="<<phase[ibest][1]<<
5084 if (AliTPCReconstructor::StreamLevel()>1) {
5085 AliInfo("Time for curling tracks removal");
5091 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5097 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5100 TObjArray *kinks= new TObjArray(10000);
5101 // TObjArray *v0s= new TObjArray(10000);
5102 Int_t nentries = array->GetEntriesFast();
5103 AliHelix *helixes = new AliHelix[nentries];
5104 Int_t *sign = new Int_t[nentries];
5105 Int_t *nclusters = new Int_t[nentries];
5106 Float_t *alpha = new Float_t[nentries];
5107 AliKink *kink = new AliKink();
5108 Int_t * usage = new Int_t[nentries];
5109 Float_t *zm = new Float_t[nentries];
5110 Float_t *z0 = new Float_t[nentries];
5111 Float_t *fim = new Float_t[nentries];
5112 Float_t *shared = new Float_t[nentries];
5113 Bool_t *circular = new Bool_t[nentries];
5114 Float_t *dca = new Float_t[nentries];
5115 //const AliESDVertex * primvertex = esd->GetVertex();
5117 // nentries = array->GetEntriesFast();
5122 for (Int_t i=0;i<nentries;i++){
5125 AliTPCseed* track = (AliTPCseed*)array->At(i);
5126 if (!track) continue;
5127 track->SetCircular(0);
5129 track->UpdatePoints();
5130 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5132 nclusters[i]=track->GetNumberOfClusters();
5133 alpha[i] = track->GetAlpha();
5134 new (&helixes[i]) AliHelix(*track);
5136 helixes[i].Evaluate(0,xyz);
5137 sign[i] = (track->GetC()>0) ? -1:1;
5140 if (track->GetProlongation(x,y,z)){
5142 fim[i] = alpha[i]+TMath::ATan2(y,x);
5145 zm[i] = track->GetZ();
5149 circular[i]= kFALSE;
5150 if (track->GetProlongation(0,y,z)) z0[i] = z;
5151 dca[i] = track->GetD(0,0);
5157 Int_t ncandidates =0;
5160 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5163 // Find circling track
5165 for (Int_t i0=0;i0<nentries;i0++){
5166 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5167 if (!track0) continue;
5168 if (track0->GetNumberOfClusters()<40) continue;
5169 if (TMath::Abs(1./track0->GetC())>200) continue;
5170 for (Int_t i1=i0+1;i1<nentries;i1++){
5171 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5172 if (!track1) continue;
5173 if (track1->GetNumberOfClusters()<40) continue;
5174 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5175 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5176 if (TMath::Abs(1./track1->GetC())>200) continue;
5177 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5178 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5179 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5180 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5181 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5183 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5184 if (mindcar<5) continue;
5185 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5186 if (mindcaz<5) continue;
5187 if (mindcar+mindcaz<20) continue;
5190 Float_t xc0 = helixes[i0].GetHelix(6);
5191 Float_t yc0 = helixes[i0].GetHelix(7);
5192 Float_t r0 = helixes[i0].GetHelix(8);
5193 Float_t xc1 = helixes[i1].GetHelix(6);
5194 Float_t yc1 = helixes[i1].GetHelix(7);
5195 Float_t r1 = helixes[i1].GetHelix(8);
5197 Float_t rmean = (r0+r1)*0.5;
5198 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5199 //if (delta>30) continue;
5200 if (delta>rmean*0.25) continue;
5201 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5203 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5204 if (npoints==0) continue;
5205 helixes[i0].GetClosestPhases(helixes[i1], phase);
5209 Double_t hangles[3];
5210 helixes[i0].Evaluate(phase[0][0],xyz0);
5211 helixes[i1].Evaluate(phase[0][1],xyz1);
5213 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5214 Double_t deltah[2],deltabest;
5215 if (hangles[2]<2.8) continue;
5218 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5220 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5221 if (deltah[1]<deltah[0]) ibest=1;
5223 deltabest = TMath::Sqrt(deltah[ibest]);
5224 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5225 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5226 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5227 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5229 if (deltabest>6) continue;
5230 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5231 Bool_t lsign =kFALSE;
5232 if (hangles[2]>3.06) lsign =kTRUE;
5235 circular[i0] = kTRUE;
5236 circular[i1] = kTRUE;
5237 if (track0->OneOverPt()<track1->OneOverPt()){
5238 track0->SetCircular(track0->GetCircular()+1);
5239 track1->SetCircular(track1->GetCircular()+2);
5242 track1->SetCircular(track1->GetCircular()+1);
5243 track0->SetCircular(track0->GetCircular()+2);
5246 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5248 Int_t lab0=track0->GetLabel();
5249 Int_t lab1=track1->GetLabel();
5250 TTreeSRedirector &cstream = *fDebugStreamer;
5251 cstream<<"Curling"<<
5258 "mindcar="<<mindcar<<
5259 "mindcaz="<<mindcaz<<
5262 "npoints="<<npoints<<
5263 "hangles0="<<hangles[0]<<
5264 "hangles2="<<hangles[2]<<
5269 "radius="<<radiusbest<<
5270 "deltabest="<<deltabest<<
5271 "phase0="<<phase[ibest][0]<<
5272 "phase1="<<phase[ibest][1]<<
5282 for (Int_t i =0;i<nentries;i++){
5283 if (sign[i]==0) continue;
5284 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5291 Double_t cradius0 = 40*40;
5292 Double_t cradius1 = 270*270;
5295 Double_t cdist3=0.55;
5296 for (Int_t j =i+1;j<nentries;j++){
5298 if (sign[j]*sign[i]<1) continue;
5299 if ( (nclusters[i]+nclusters[j])>200) continue;
5300 if ( (nclusters[i]+nclusters[j])<80) continue;
5301 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5302 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5303 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5304 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5305 if (npoints<1) continue;
5308 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5311 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5314 Double_t delta1=10000,delta2=10000;
5315 // cuts on the intersection radius
5316 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5317 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5318 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5320 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5321 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5322 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5325 Double_t distance1 = TMath::Min(delta1,delta2);
5326 if (distance1>cdist1) continue; // cut on DCA linear approximation
5328 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5329 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5330 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5331 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5334 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5335 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5336 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5338 distance1 = TMath::Min(delta1,delta2);
5341 rkink = TMath::Sqrt(radius[0]);
5344 rkink = TMath::Sqrt(radius[1]);
5346 if (distance1>cdist2) continue;
5349 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5352 Int_t row0 = GetRowNumber(rkink);
5353 if (row0<10) continue;
5354 if (row0>150) continue;
5357 Float_t dens00=-1,dens01=-1;
5358 Float_t dens10=-1,dens11=-1;
5360 Int_t found,foundable,ishared;
5361 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5362 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5363 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5364 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5366 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5367 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5368 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5369 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5371 if (dens00<dens10 && dens01<dens11) continue;
5372 if (dens00>dens10 && dens01>dens11) continue;
5373 if (TMath::Max(dens00,dens10)<0.1) continue;
5374 if (TMath::Max(dens01,dens11)<0.3) continue;
5376 if (TMath::Min(dens00,dens10)>0.6) continue;
5377 if (TMath::Min(dens01,dens11)>0.6) continue;
5380 AliTPCseed * ktrack0, *ktrack1;
5389 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5390 AliExternalTrackParam paramm(*ktrack0);
5391 AliExternalTrackParam paramd(*ktrack1);
5392 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5395 kink->SetMother(paramm);
5396 kink->SetDaughter(paramd);
5399 Float_t x[3] = { static_cast<Float_t>(kink->GetPosition()[0]),static_cast<Float_t>(kink->GetPosition()[1]),static_cast<Float_t>(kink->GetPosition()[2])};
5401 fkParam->Transform0to1(x,index);
5402 fkParam->Transform1to2(x,index);
5403 row0 = GetRowNumber(x[0]);
5405 if (kink->GetR()<100) continue;
5406 if (kink->GetR()>240) continue;
5407 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5408 if (kink->GetDistance()>cdist3) continue;
5409 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5410 if (dird<0) continue;
5412 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5413 if (dirm<0) continue;
5414 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5415 if (mpt<0.2) continue;
5418 //for high momenta momentum not defined well in first iteration
5419 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5420 if (qt>0.35) continue;
5423 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5424 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5426 kink->SetTPCDensity(dens00,0,0);
5427 kink->SetTPCDensity(dens01,0,1);
5428 kink->SetTPCDensity(dens10,1,0);
5429 kink->SetTPCDensity(dens11,1,1);
5430 kink->SetIndex(i,0);
5431 kink->SetIndex(j,1);
5434 kink->SetTPCDensity(dens10,0,0);
5435 kink->SetTPCDensity(dens11,0,1);
5436 kink->SetTPCDensity(dens00,1,0);
5437 kink->SetTPCDensity(dens01,1,1);
5438 kink->SetIndex(j,0);
5439 kink->SetIndex(i,1);
5442 if (mpt<1||kink->GetAngle(2)>0.1){
5443 // angle and densities not defined yet
5444 if (kink->GetTPCDensityFactor()<0.8) continue;
5445 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5446 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5447 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5448 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5450 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5451 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5452 criticalangle= 3*TMath::Sqrt(criticalangle);
5453 if (criticalangle>0.02) criticalangle=0.02;
5454 if (kink->GetAngle(2)<criticalangle) continue;
5457 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5458 Float_t shapesum =0;
5460 for ( Int_t row = row0-drow; row<row0+drow;row++){
5461 if (row<0) continue;
5462 if (row>155) continue;
5463 if (ktrack0->GetClusterPointer(row)){
5464 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5465 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5468 if (ktrack1->GetClusterPointer(row)){
5469 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5470 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5475 kink->SetShapeFactor(-1.);
5478 kink->SetShapeFactor(shapesum/sum);
5480 // esd->AddKink(kink);
5482 // kink->SetMother(paramm);
5483 //kink->SetDaughter(paramd);
5485 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5487 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5488 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5490 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5492 if (AliTPCReconstructor::StreamLevel()>1) {
5493 (*fDebugStreamer)<<"kinkLpt"<<
5501 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5505 kinks->AddLast(kink);
5511 // sort the kinks according quality - and refit them towards vertex
5513 Int_t nkinks = kinks->GetEntriesFast();
5514 Float_t *quality = new Float_t[nkinks];
5515 Int_t *indexes = new Int_t[nkinks];
5516 AliTPCseed *mothers = new AliTPCseed[nkinks];
5517 AliTPCseed *daughters = new AliTPCseed[nkinks];
5520 for (Int_t i=0;i<nkinks;i++){
5522 AliKink *kinkl = (AliKink*)kinks->At(i);
5524 // refit kinks towards vertex
5526 Int_t index0 = kinkl->GetIndex(0);
5527 Int_t index1 = kinkl->GetIndex(1);
5528 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5529 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5531 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5533 // Refit Kink under if too small angle
5535 if (kinkl->GetAngle(2)<0.05){
5536 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5537 Int_t row0 = kinkl->GetTPCRow0();
5538 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5541 Int_t last = row0-drow;
5542 if (last<40) last=40;
5543 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5544 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5547 Int_t first = row0+drow;
5548 if (first>130) first=130;
5549 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5550 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5552 if (seed0 && seed1){
5553 kinkl->SetStatus(1,8);
5554 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5555 row0 = GetRowNumber(kinkl->GetR());
5556 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5557 mothers[i] = *seed0;
5558 daughters[i] = *seed1;
5561 delete kinks->RemoveAt(i);
5562 if (seed0) MarkSeedFree( seed0 );
5563 if (seed1) MarkSeedFree( seed1 );
5566 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
5567 delete kinks->RemoveAt(i);
5568 if (seed0) MarkSeedFree( seed0 );
5569 if (seed1) MarkSeedFree( seed1 );
5573 MarkSeedFree( seed0 );
5574 MarkSeedFree( seed1 );
5577 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
5579 TMath::Sort(nkinks,quality,indexes,kFALSE);
5581 //remove double find kinks
5583 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5584 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5585 if (!kink0) continue;
5587 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5588 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5589 if (!kink0) continue;
5590 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5591 if (!kink1) continue;
5592 // if not close kink continue
5593 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5594 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5595 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5597 AliTPCseed &mother0 = mothers[indexes[ikink0]];
5598 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5599 AliTPCseed &mother1 = mothers[indexes[ikink1]];
5600 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5601 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5610 for (Int_t i=0;i<row0;i++){
5611 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5614 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5621 for (Int_t i=row0;i<158;i++){
5622 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
5623 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
5626 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5632 Float_t ratio = Float_t(same+1)/Float_t(both+1);
5633 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5634 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5635 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5636 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5637 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5639 shared[kink0->GetIndex(0)]= kTRUE;
5640 shared[kink0->GetIndex(1)]= kTRUE;
5641 delete kinks->RemoveAt(indexes[ikink0]);
5645 shared[kink1->GetIndex(0)]= kTRUE;
5646 shared[kink1->GetIndex(1)]= kTRUE;
5647 delete kinks->RemoveAt(indexes[ikink1]);
5654 for (Int_t i=0;i<nkinks;i++){
5655 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
5656 if (!kinkl) continue;
5657 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5658 Int_t index0 = kinkl->GetIndex(0);
5659 Int_t index1 = kinkl->GetIndex(1);
5660 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
5661 kinkl->SetMultiple(usage[index0],0);
5662 kinkl->SetMultiple(usage[index1],1);
5663 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
5664 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5665 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
5666 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
5668 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5669 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5670 if (!ktrack0 || !ktrack1) continue;
5671 Int_t index = esd->AddKink(kinkl);
5674 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
5675 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5676 *ktrack0 = mothers[indexes[i]];
5677 *ktrack1 = daughters[indexes[i]];
5681 ktrack0->SetKinkIndex(usage[index0],-(index+1));
5682 ktrack1->SetKinkIndex(usage[index1], (index+1));
5687 // Remove tracks corresponding to shared kink's
5689 for (Int_t i=0;i<nentries;i++){
5690 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5691 if (!track0) continue;
5692 if (track0->GetKinkIndex(0)!=0) continue;
5693 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
5698 RemoveUsed2(array,0.5,0.4,30);
5700 for (Int_t i=0;i<nentries;i++){
5701 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5702 if (!track0) continue;
5703 track0->CookdEdx(0.02,0.6);
5707 for (Int_t i=0;i<nentries;i++){
5708 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5709 if (!track0) continue;
5710 if (track0->Pt()<1.4) continue;
5711 //remove double high momenta tracks - overlapped with kink candidates
5714 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5715 if (track0->GetClusterPointer(icl)!=0){
5717 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
5720 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
5721 MarkSeedFree( array->RemoveAt(i) );
5725 if (track0->GetKinkIndex(0)!=0) continue;
5726 if (track0->GetNumberOfClusters()<80) continue;
5728 AliTPCseed *pmother = new AliTPCseed();
5729 AliTPCseed *pdaughter = new AliTPCseed();
5730 AliKink *pkink = new AliKink;
5732 AliTPCseed & mother = *pmother;
5733 AliTPCseed & daughter = *pdaughter;
5734 AliKink & kinkl = *pkink;
5735 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
5736 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5740 continue; //too short tracks
5742 if (mother.Pt()<1.4) {
5748 Int_t row0= kinkl.GetTPCRow0();
5749 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
5756 Int_t index = esd->AddKink(&kinkl);
5757 mother.SetKinkIndex(0,-(index+1));
5758 daughter.SetKinkIndex(0,index+1);
5759 if (mother.GetNumberOfClusters()>50) {
5760 MarkSeedFree( array->RemoveAt(i) );
5761 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5762 mtc->SetPoolID(fLastSeedID);
5763 array->AddAt(mtc,i);
5766 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5767 mtc->SetPoolID(fLastSeedID);
5768 array->AddLast(mtc);
5770 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
5771 dtc->SetPoolID(fLastSeedID);
5772 array->AddLast(dtc);
5773 for (Int_t icl=0;icl<row0;icl++) {
5774 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5777 for (Int_t icl=row0;icl<158;icl++) {
5778 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5787 delete [] daughters;
5809 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
5815 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5822 TObjArray *kinks= new TObjArray(10000);
5823 // TObjArray *v0s= new TObjArray(10000);
5824 Int_t nentries = array->GetEntriesFast();
5825 AliHelix *helixes = new AliHelix[nentries];
5826 Int_t *sign = new Int_t[nentries];
5827 Int_t *nclusters = new Int_t[nentries];
5828 Float_t *alpha = new Float_t[nentries];
5829 AliKink *kink = new AliKink();
5830 Int_t * usage = new Int_t[nentries];
5831 Float_t *zm = new Float_t[nentries];
5832 Float_t *z0 = new Float_t[nentries];
5833 Float_t *fim = new Float_t[nentries];
5834 Float_t *shared = new Float_t[nentries];
5835 Bool_t *circular = new Bool_t[nentries];
5836 Float_t *dca = new Float_t[nentries];
5837 //const AliESDVertex * primvertex = esd->GetVertex();
5839 // nentries = array->GetEntriesFast();
5844 for (Int_t i=0;i<nentries;i++){
5847 AliTPCseed* track = (AliTPCseed*)array->At(i);
5848 if (!track) continue;
5849 track->SetCircular(0);
5851 track->UpdatePoints();
5852 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5854 nclusters[i]=track->GetNumberOfClusters();
5855 alpha[i] = track->GetAlpha();
5856 new (&helixes[i]) AliHelix(*track);
5858 helixes[i].Evaluate(0,xyz);
5859 sign[i] = (track->GetC()>0) ? -1:1;
5862 if (track->GetProlongation(x,y,z)){
5864 fim[i] = alpha[i]+TMath::ATan2(y,x);
5867 zm[i] = track->GetZ();
5871 circular[i]= kFALSE;
5872 if (track->GetProlongation(0,y,z)) z0[i] = z;
5873 dca[i] = track->GetD(0,0);
5879 Int_t ncandidates =0;
5882 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5885 // Find circling track
5887 for (Int_t i0=0;i0<nentries;i0++){
5888 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5889 if (!track0) continue;
5890 if (track0->GetNumberOfClusters()<40) continue;
5891 if (TMath::Abs(1./track0->GetC())>200) continue;
5892 for (Int_t i1=i0+1;i1<nentries;i1++){
5893 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5894 if (!track1) continue;
5895 if (track1->GetNumberOfClusters()<40) continue;
5896 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5897 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5898 if (TMath::Abs(1./track1->GetC())>200) continue;
5899 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5900 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5901 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5902 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5903 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5905 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5906 if (mindcar<5) continue;
5907 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5908 if (mindcaz<5) continue;
5909 if (mindcar+mindcaz<20) continue;
5912 Float_t xc0 = helixes[i0].GetHelix(6);
5913 Float_t yc0 = helixes[i0].GetHelix(7);
5914 Float_t r0 = helixes[i0].GetHelix(8);
5915 Float_t xc1 = helixes[i1].GetHelix(6);
5916 Float_t yc1 = helixes[i1].GetHelix(7);
5917 Float_t r1 = helixes[i1].GetHelix(8);
5919 Float_t rmean = (r0+r1)*0.5;
5920 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5921 //if (delta>30) continue;
5922 if (delta>rmean*0.25) continue;
5923 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5925 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5926 if (npoints==0) continue;
5927 helixes[i0].GetClosestPhases(helixes[i1], phase);
5931 Double_t hangles[3];
5932 helixes[i0].Evaluate(phase[0][0],xyz0);
5933 helixes[i1].Evaluate(phase[0][1],xyz1);
5935 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5936 Double_t deltah[2],deltabest;
5937 if (hangles[2]<2.8) continue;
5940 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5942 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5943 if (deltah[1]<deltah[0]) ibest=1;
5945 deltabest = TMath::Sqrt(deltah[ibest]);
5946 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5947 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5948 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5949 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5951 if (deltabest>6) continue;
5952 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5953 Bool_t lsign =kFALSE;
5954 if (hangles[2]>3.06) lsign =kTRUE;
5957 circular[i0] = kTRUE;
5958 circular[i1] = kTRUE;
5959 if (track0->OneOverPt()<track1->OneOverPt()){
5960 track0->SetCircular(track0->GetCircular()+1);
5961 track1->SetCircular(track1->GetCircular()+2);
5964 track1->SetCircular(track1->GetCircular()+1);
5965 track0->SetCircular(track0->GetCircular()+2);
5968 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5970 Int_t lab0=track0->GetLabel();
5971 Int_t lab1=track1->GetLabel();
5972 TTreeSRedirector &cstream = *fDebugStreamer;
5973 cstream<<"Curling"<<
5980 "mindcar="<<mindcar<<
5981 "mindcaz="<<mindcaz<<
5984 "npoints="<<npoints<<
5985 "hangles0="<<hangles[0]<<
5986 "hangles2="<<hangles[2]<<
5991 "radius="<<radiusbest<<
5992 "deltabest="<<deltabest<<
5993 "phase0="<<phase[ibest][0]<<
5994 "phase1="<<phase[ibest][1]<<
6004 for (Int_t i =0;i<nentries;i++){
6005 if (sign[i]==0) continue;
6006 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6013 Double_t cradius0 = 40*40;
6014 Double_t cradius1 = 270*270;
6017 Double_t cdist3=0.55;
6018 for (Int_t j =i+1;j<nentries;j++){
6020 if (sign[j]*sign[i]<1) continue;
6021 if ( (nclusters[i]+nclusters[j])>200) continue;
6022 if ( (nclusters[i]+nclusters[j])<80) continue;
6023 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6024 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6025 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6026 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6027 if (npoints<1) continue;
6030 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6033 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6036 Double_t delta1=10000,delta2=10000;
6037 // cuts on the intersection radius
6038 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6039 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6040 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6042 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6043 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6044 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6047 Double_t distance1 = TMath::Min(delta1,delta2);
6048 if (distance1>cdist1) continue; // cut on DCA linear approximation
6050 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6051 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6052 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6053 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6056 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6057 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6058 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6060 distance1 = TMath::Min(delta1,delta2);
6063 rkink = TMath::Sqrt(radius[0]);
6066 rkink = TMath::Sqrt(radius[1]);
6068 if (distance1>cdist2) continue;
6071 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6074 Int_t row0 = GetRowNumber(rkink);
6075 if (row0<10) continue;
6076 if (row0>150) continue;
6079 Float_t dens00=-1,dens01=-1;
6080 Float_t dens10=-1,dens11=-1;
6082 Int_t found,foundable,ishared;
6083 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6084 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6085 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6086 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6088 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6089 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6090 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6091 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6093 if (dens00<dens10 && dens01<dens11) continue;
6094 if (dens00>dens10 && dens01>dens11) continue;
6095 if (TMath::Max(dens00,dens10)<0.1) continue;
6096 if (TMath::Max(dens01,dens11)<0.3) continue;
6098 if (TMath::Min(dens00,dens10)>0.6) continue;
6099 if (TMath::Min(dens01,dens11)>0.6) continue;
6102 AliTPCseed * ktrack0, *ktrack1;
6111 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6112 AliExternalTrackParam paramm(*ktrack0);
6113 AliExternalTrackParam paramd(*ktrack1);
6114 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6117 kink->SetMother(paramm);
6118 kink->SetDaughter(paramd);
6121 Float_t x[3] = { static_cast<Float_t>(kink->GetPosition()[0]),static_cast<Float_t>(kink->GetPosition()[1]),static_cast<Float_t>(kink->GetPosition()[2])};
6123 fkParam->Transform0to1(x,index);
6124 fkParam->Transform1to2(x,index);
6125 row0 = GetRowNumber(x[0]);
6127 if (kink->GetR()<100) continue;
6128 if (kink->GetR()>240) continue;
6129 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6130 if (kink->GetDistance()>cdist3) continue;
6131 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6132 if (dird<0) continue;
6134 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6135 if (dirm<0) continue;
6136 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6137 if (mpt<0.2) continue;
6140 //for high momenta momentum not defined well in first iteration
6141 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6142 if (qt>0.35) continue;
6145 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6146 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6148 kink->SetTPCDensity(dens00,0,0);
6149 kink->SetTPCDensity(dens01,0,1);
6150 kink->SetTPCDensity(dens10,1,0);
6151 kink->SetTPCDensity(dens11,1,1);
6152 kink->SetIndex(i,0);
6153 kink->SetIndex(j,1);
6156 kink->SetTPCDensity(dens10,0,0);
6157 kink->SetTPCDensity(dens11,0,1);
6158 kink->SetTPCDensity(dens00,1,0);
6159 kink->SetTPCDensity(dens01,1,1);
6160 kink->SetIndex(j,0);
6161 kink->SetIndex(i,1);
6164 if (mpt<1||kink->GetAngle(2)>0.1){
6165 // angle and densities not defined yet
6166 if (kink->GetTPCDensityFactor()<0.8) continue;
6167 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6168 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6169 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6170 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6172 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6173 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6174 criticalangle= 3*TMath::Sqrt(criticalangle);
6175 if (criticalangle>0.02) criticalangle=0.02;
6176 if (kink->GetAngle(2)<criticalangle) continue;
6179 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6180 Float_t shapesum =0;
6182 for ( Int_t row = row0-drow; row<row0+drow;row++){
6183 if (row<0) continue;
6184 if (row>155) continue;
6185 if (ktrack0->GetClusterPointer(row)){
6186 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6187 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6190 if (ktrack1->GetClusterPointer(row)){
6191 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6192 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6197 kink->SetShapeFactor(-1.);
6200 kink->SetShapeFactor(shapesum/sum);
6202 // esd->AddKink(kink);
6204 // kink->SetMother(paramm);
6205 //kink->SetDaughter(paramd);
6207 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6209 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6210 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6212 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6214 if (AliTPCReconstructor::StreamLevel()>1) {
6215 (*fDebugStreamer)<<"kinkLpt"<<
6223 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6227 kinks->AddLast(kink);
6233 // sort the kinks according quality - and refit them towards vertex
6235 Int_t nkinks = kinks->GetEntriesFast();
6236 Float_t *quality = new Float_t[nkinks];
6237 Int_t *indexes = new Int_t[nkinks];
6238 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6239 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6242 for (Int_t i=0;i<nkinks;i++){
6244 AliKink *kinkl = (AliKink*)kinks->At(i);
6246 // refit kinks towards vertex
6248 Int_t index0 = kinkl->GetIndex(0);
6249 Int_t index1 = kinkl->GetIndex(1);
6250 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6251 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6253 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6255 // Refit Kink under if too small angle
6257 if (kinkl->GetAngle(2)<0.05){
6258 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6259 Int_t row0 = kinkl->GetTPCRow0();
6260 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6263 Int_t last = row0-drow;
6264 if (last<40) last=40;
6265 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6266 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6269 Int_t first = row0+drow;
6270 if (first>130) first=130;
6271 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6272 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6274 if (seed0 && seed1){
6275 kinkl->SetStatus(1,8);
6276 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6277 row0 = GetRowNumber(kinkl->GetR());
6278 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6279 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6280 mothers[i]->SetPoolID(fLastSeedID);
6281 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6282 daughters[i]->SetPoolID(fLastSeedID);
6285 delete kinks->RemoveAt(i);
6286 if (seed0) MarkSeedFree( seed0 );
6287 if (seed1) MarkSeedFree( seed1 );
6290 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6291 delete kinks->RemoveAt(i);
6292 if (seed0) MarkSeedFree( seed0 );
6293 if (seed1) MarkSeedFree( seed1 );
6297 MarkSeedFree( seed0 );
6298 MarkSeedFree( seed1 );
6301 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6303 TMath::Sort(nkinks,quality,indexes,kFALSE);
6305 //remove double find kinks
6307 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6308 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6309 if (!kink0) continue;
6311 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6312 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6313 if (!kink0) continue;
6314 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6315 if (!kink1) continue;
6316 // if not close kink continue
6317 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6318 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6319 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6321 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6322 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6323 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6324 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6325 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6334 for (Int_t i=0;i<row0;i++){
6335 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6338 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6345 for (Int_t i=row0;i<158;i++){
6346 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6347 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6350 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6356 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6357 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6358 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6359 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6360 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6361 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6363 shared[kink0->GetIndex(0)]= kTRUE;
6364 shared[kink0->GetIndex(1)]= kTRUE;
6365 delete kinks->RemoveAt(indexes[ikink0]);
6369 shared[kink1->GetIndex(0)]= kTRUE;
6370 shared[kink1->GetIndex(1)]= kTRUE;
6371 delete kinks->RemoveAt(indexes[ikink1]);
6378 for (Int_t i=0;i<nkinks;i++){
6379 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6380 if (!kinkl) continue;
6381 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6382 Int_t index0 = kinkl->GetIndex(0);
6383 Int_t index1 = kinkl->GetIndex(1);
6384 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6385 kinkl->SetMultiple(usage[index0],0);
6386 kinkl->SetMultiple(usage[index1],1);
6387 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6388 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6389 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6390 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6392 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6393 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6394 if (!ktrack0 || !ktrack1) continue;
6395 Int_t index = esd->AddKink(kinkl);
6398 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6399 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6400 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6401 *ktrack0 = *mothers[indexes[i]];
6402 *ktrack1 = *daughters[indexes[i]];
6406 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6407 ktrack1->SetKinkIndex(usage[index1], (index+1));
6412 // Remove tracks corresponding to shared kink's
6414 for (Int_t i=0;i<nentries;i++){
6415 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6416 if (!track0) continue;
6417 if (track0->GetKinkIndex(0)!=0) continue;
6418 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6423 RemoveUsed2(array,0.5,0.4,30);
6425 for (Int_t i=0;i<nentries;i++){
6426 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6427 if (!track0) continue;
6428 track0->CookdEdx(0.02,0.6);
6432 for (Int_t i=0;i<nentries;i++){
6433 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6434 if (!track0) continue;
6435 if (track0->Pt()<1.4) continue;
6436 //remove double high momenta tracks - overlapped with kink candidates
6439 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6440 if (track0->GetClusterPointer(icl)!=0){
6442 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6445 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6446 MarkSeedFree( array->RemoveAt(i) );
6450 if (track0->GetKinkIndex(0)!=0) continue;
6451 if (track0->GetNumberOfClusters()<80) continue;
6453 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6454 pmother->SetPoolID(fLastSeedID);
6455 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6456 pdaughter->SetPoolID(fLastSeedID);
6457 AliKink *pkink = new AliKink;
6459 AliTPCseed & mother = *pmother;
6460 AliTPCseed & daughter = *pdaughter;
6461 AliKink & kinkl = *pkink;
6462 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6463 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6464 MarkSeedFree( pmother );
6465 MarkSeedFree( pdaughter );
6467 continue; //too short tracks
6469 if (mother.Pt()<1.4) {
6470 MarkSeedFree( pmother );
6471 MarkSeedFree( pdaughter );
6475 Int_t row0= kinkl.GetTPCRow0();
6476 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6477 MarkSeedFree( pmother );
6478 MarkSeedFree( pdaughter );
6483 Int_t index = esd->AddKink(&kinkl);
6484 mother.SetKinkIndex(0,-(index+1));
6485 daughter.SetKinkIndex(0,index+1);
6486 if (mother.GetNumberOfClusters()>50) {
6487 MarkSeedFree( array->RemoveAt(i) );
6488 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6489 mtc->SetPoolID(fLastSeedID);
6490 array->AddAt(mtc,i);
6493 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6494 mtc->SetPoolID(fLastSeedID);
6495 array->AddLast(mtc);
6497 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6498 dtc->SetPoolID(fLastSeedID);
6499 array->AddLast(dtc);
6500 for (Int_t icl=0;icl<row0;icl++) {
6501 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6504 for (Int_t icl=row0;icl<158;icl++) {
6505 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6509 MarkSeedFree( pmother );
6510 MarkSeedFree( pdaughter );
6514 delete [] daughters;
6536 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6541 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6544 // refit kink towards to the vertex
6547 AliKink &kink=(AliKink &)knk;
6549 Int_t row0 = GetRowNumber(kink.GetR());
6550 FollowProlongation(mother,0);
6551 mother.Reset(kFALSE);
6553 FollowProlongation(daughter,row0);
6554 daughter.Reset(kFALSE);
6555 FollowBackProlongation(daughter,158);
6556 daughter.Reset(kFALSE);
6557 Int_t first = TMath::Max(row0-20,30);
6558 Int_t last = TMath::Min(row0+20,140);
6560 const Int_t kNdiv =5;
6561 AliTPCseed param0[kNdiv]; // parameters along the track
6562 AliTPCseed param1[kNdiv]; // parameters along the track
6563 AliKink kinks[kNdiv]; // corresponding kink parameters
6566 for (Int_t irow=0; irow<kNdiv;irow++){
6567 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
6569 // store parameters along the track
6571 for (Int_t irow=0;irow<kNdiv;irow++){
6572 FollowBackProlongation(mother, rows[irow]);
6573 FollowProlongation(daughter,rows[kNdiv-1-irow]);
6574 param0[irow] = mother;
6575 param1[kNdiv-1-irow] = daughter;
6579 for (Int_t irow=0; irow<kNdiv-1;irow++){
6580 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
6581 kinks[irow].SetMother(param0[irow]);
6582 kinks[irow].SetDaughter(param1[irow]);
6583 kinks[irow].Update();
6586 // choose kink with best "quality"
6588 Double_t mindist = 10000;
6589 for (Int_t irow=0;irow<kNdiv;irow++){
6590 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
6591 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6592 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
6594 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
6595 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
6596 if (normdist < mindist){
6602 if (index==-1) return 0;
6605 param0[index].Reset(kTRUE);
6606 FollowProlongation(param0[index],0);
6608 mother = param0[index];
6609 daughter = param1[index]; // daughter in vertex
6611 kink.SetMother(mother);
6612 kink.SetDaughter(daughter);
6614 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
6615 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6616 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6617 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
6618 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
6619 mother.SetLabel(kink.GetLabel(0));
6620 daughter.SetLabel(kink.GetLabel(1));
6626 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
6628 // update Kink quality information for mother after back propagation
6630 if (seed->GetKinkIndex(0)>=0) return;
6631 for (Int_t ikink=0;ikink<3;ikink++){
6632 Int_t index = seed->GetKinkIndex(ikink);
6633 if (index>=0) break;
6634 index = TMath::Abs(index)-1;
6635 AliESDkink * kink = fEvent->GetKink(index);
6636 kink->SetTPCDensity(-1,0,0);
6637 kink->SetTPCDensity(1,0,1);
6639 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6640 if (row0<15) row0=15;
6642 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6643 if (row1>145) row1=145;
6645 Int_t found,foundable,shared;
6646 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6647 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
6648 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6649 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
6654 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
6656 // update Kink quality information for daughter after refit
6658 if (seed->GetKinkIndex(0)<=0) return;
6659 for (Int_t ikink=0;ikink<3;ikink++){
6660 Int_t index = seed->GetKinkIndex(ikink);
6661 if (index<=0) break;
6662 index = TMath::Abs(index)-1;
6663 AliESDkink * kink = fEvent->GetKink(index);
6664 kink->SetTPCDensity(-1,1,0);
6665 kink->SetTPCDensity(-1,1,1);
6667 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6668 if (row0<15) row0=15;
6670 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6671 if (row1>145) row1=145;
6673 Int_t found,foundable,shared;
6674 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6675 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
6676 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6677 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
6683 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6686 // check kink point for given track
6687 // if return value=0 kink point not found
6688 // otherwise seed0 correspond to mother particle
6689 // seed1 correspond to daughter particle
6690 // kink parameter of kink point
6691 AliKink &kink=(AliKink &)knk;
6693 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
6694 Int_t first = seed->GetFirstPoint();
6695 Int_t last = seed->GetLastPoint();
6696 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
6699 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
6700 if (!seed1) return 0;
6701 FollowProlongation(*seed1,seed->GetLastPoint()-20);
6702 seed1->Reset(kTRUE);
6703 FollowProlongation(*seed1,158);
6704 seed1->Reset(kTRUE);
6705 last = seed1->GetLastPoint();
6707 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
6708 seed0->SetPoolID(fLastSeedID);
6709 seed0->Reset(kFALSE);
6712 AliTPCseed param0[20]; // parameters along the track
6713 AliTPCseed param1[20]; // parameters along the track
6714 AliKink kinks[20]; // corresponding kink parameters
6716 for (Int_t irow=0; irow<20;irow++){
6717 rows[irow] = first +((last-first)*irow)/19;
6719 // store parameters along the track
6721 for (Int_t irow=0;irow<20;irow++){
6722 FollowBackProlongation(*seed0, rows[irow]);
6723 FollowProlongation(*seed1,rows[19-irow]);
6724 param0[irow] = *seed0;
6725 param1[19-irow] = *seed1;
6729 for (Int_t irow=0; irow<19;irow++){
6730 kinks[irow].SetMother(param0[irow]);
6731 kinks[irow].SetDaughter(param1[irow]);
6732 kinks[irow].Update();
6735 // choose kink with biggest change of angle
6737 Double_t maxchange= 0;
6738 for (Int_t irow=1;irow<19;irow++){
6739 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6740 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
6741 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6742 if ( quality > maxchange){
6743 maxchange = quality;
6748 MarkSeedFree( seed0 );
6749 MarkSeedFree( seed1 );
6750 if (index<0) return 0;
6752 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
6753 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
6754 seed0->SetPoolID(fLastSeedID);
6755 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
6756 seed1->SetPoolID(fLastSeedID);
6757 seed0->Reset(kFALSE);
6758 seed1->Reset(kFALSE);
6759 seed0->ResetCovariance(10.);
6760 seed1->ResetCovariance(10.);
6761 FollowProlongation(*seed0,0);
6762 FollowBackProlongation(*seed1,158);
6763 mother = *seed0; // backup mother at position 0
6764 seed0->Reset(kFALSE);
6765 seed1->Reset(kFALSE);
6766 seed0->ResetCovariance(10.);
6767 seed1->ResetCovariance(10.);
6769 first = TMath::Max(row0-20,0);
6770 last = TMath::Min(row0+20,158);
6772 for (Int_t irow=0; irow<20;irow++){
6773 rows[irow] = first +((last-first)*irow)/19;
6775 // store parameters along the track
6777 for (Int_t irow=0;irow<20;irow++){
6778 FollowBackProlongation(*seed0, rows[irow]);
6779 FollowProlongation(*seed1,rows[19-irow]);
6780 param0[irow] = *seed0;
6781 param1[19-irow] = *seed1;
6785 for (Int_t irow=0; irow<19;irow++){
6786 kinks[irow].SetMother(param0[irow]);
6787 kinks[irow].SetDaughter(param1[irow]);
6788 // param0[irow].Dump();
6789 //param1[irow].Dump();
6790 kinks[irow].Update();
6793 // choose kink with biggest change of angle
6796 for (Int_t irow=0;irow<20;irow++){
6797 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
6798 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
6799 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6800 if ( quality > maxchange){
6801 maxchange = quality;
6808 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
6809 MarkSeedFree( seed0 );
6810 MarkSeedFree( seed1 );
6814 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
6816 kink.SetMother(param0[index]);
6817 kink.SetDaughter(param1[index]);
6820 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
6822 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
6823 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
6825 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
6827 if (AliTPCReconstructor::StreamLevel()>1) {
6828 (*fDebugStreamer)<<"kinkHpt"<<
6831 "p0.="<<¶m0[index]<<
6832 "p1.="<<¶m1[index]<<
6836 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6837 MarkSeedFree( seed0 );
6838 MarkSeedFree( seed1 );
6843 row0 = GetRowNumber(kink.GetR());
6844 kink.SetTPCRow0(row0);
6845 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
6846 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
6847 kink.SetIndex(-10,0);
6848 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
6849 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6850 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6853 // new (&mother) AliTPCseed(param0[index]);
6854 daughter = param1[index];
6855 daughter.SetLabel(kink.GetLabel(1));
6856 param0[index].Reset(kTRUE);
6857 FollowProlongation(param0[index],0);
6858 mother = param0[index];
6859 mother.SetLabel(kink.GetLabel(0));
6860 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
6863 MarkSeedFree( seed0 );
6864 MarkSeedFree( seed1 );
6872 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
6875 // reseed - refit - track
6878 // Int_t last = fSectors->GetNRows()-1;
6880 if (fSectors == fOuterSec){
6881 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
6885 first = t->GetFirstPoint();
6887 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
6888 FollowBackProlongation(*t,fSectors->GetNRows()-1);
6890 FollowProlongation(*t,first);
6900 //_____________________________________________________________________________
6901 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
6902 //-----------------------------------------------------------------
6903 // This function reades track seeds.
6904 //-----------------------------------------------------------------
6905 TDirectory *savedir=gDirectory;
6907 TFile *in=(TFile*)inp;
6908 if (!in->IsOpen()) {
6909 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
6914 TTree *seedTree=(TTree*)in->Get("Seeds");
6916 cerr<<"AliTPCtracker::ReadSeeds(): ";
6917 cerr<<"can't get a tree with track seeds !\n";
6920 AliTPCtrack *seed=new AliTPCtrack;
6921 seedTree->SetBranchAddress("tracks",&seed);
6923 if (fSeeds==0) fSeeds=new TObjArray(15000);
6925 Int_t n=(Int_t)seedTree->GetEntries();
6926 for (Int_t i=0; i<n; i++) {
6927 seedTree->GetEvent(i);
6928 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
6929 sdc->SetPoolID(fLastSeedID);
6930 fSeeds->AddLast(sdc);
6933 delete seed; // RS: this seed is not from the pool, delete it !!!
6939 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
6942 // clusters to tracks
6943 if (fSeeds) DeleteSeeds();
6944 else ResetSeedsPool();
6946 fEventHLT = hltEvent;
6948 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
6949 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
6950 transform->SetCurrentRun(esd->GetRunNumber());
6954 if (!fSeeds) return 1;
6956 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(0,fSeeds);
6961 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
6964 // clusters to tracks
6965 return Clusters2TracksHLT( esd, 0);
6968 //_____________________________________________________________________________
6969 Int_t AliTPCtracker::Clusters2Tracks() {
6970 //-----------------------------------------------------------------
6971 // This is a track finder.
6972 //-----------------------------------------------------------------
6973 TDirectory *savedir=gDirectory;
6977 fSeeds = Tracking();
6980 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6982 //activate again some tracks
6983 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6984 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6986 Int_t nc=t.GetNumberOfClusters();
6988 MarkSeedFree( fSeeds->RemoveAt(i) );
6992 if (pt->GetRemoval()==10) {
6993 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6994 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
6996 pt->Desactivate(20);
6997 MarkSeedFree( fSeeds->RemoveAt(i) );
7002 RemoveUsed2(fSeeds,0.85,0.85,0);
7003 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
7004 //FindCurling(fSeeds, fEvent,0);
7005 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
7006 RemoveUsed2(fSeeds,0.5,0.4,20);
7007 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
7008 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
7011 // // refit short tracks
7013 Int_t nseed=fSeeds->GetEntriesFast();
7016 for (Int_t i=0; i<nseed; i++) {
7017 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7019 Int_t nc=t.GetNumberOfClusters();
7021 MarkSeedFree( fSeeds->RemoveAt(i) );
7024 CookLabel(pt,0.1); //For comparison only
7025 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7026 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7028 if (fDebug>0) cerr<<found<<'\r';
7032 MarkSeedFree( fSeeds->RemoveAt(i) );
7036 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7038 //RemoveUsed(fSeeds,0.9,0.9,6);
7040 nseed=fSeeds->GetEntriesFast();
7042 for (Int_t i=0; i<nseed; i++) {
7043 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7045 Int_t nc=t.GetNumberOfClusters();
7047 MarkSeedFree( fSeeds->RemoveAt(i) );
7051 t.CookdEdx(0.02,0.6);
7052 // CheckKinkPoint(&t,0.05);
7053 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7054 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7062 MarkSeedFree( fSeeds->RemoveAt(i) );
7063 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7065 // FollowProlongation(*seed1,0);
7066 // Int_t n = seed1->GetNumberOfClusters();
7067 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7068 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7071 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7075 SortTracks(fSeeds, 1);
7079 PrepareForBackProlongation(fSeeds,5.);
7080 PropagateBack(fSeeds);
7081 printf("Time for back propagation: \t");timer.Print();timer.Start();
7085 PrepareForProlongation(fSeeds,5.);
7086 PropagateForard2(fSeeds);
7088 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7089 // RemoveUsed(fSeeds,0.7,0.7,6);
7090 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7092 nseed=fSeeds->GetEntriesFast();
7094 for (Int_t i=0; i<nseed; i++) {
7095 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7097 Int_t nc=t.GetNumberOfClusters();
7099 MarkSeedFree( fSeeds->RemoveAt(i) );
7102 t.CookdEdx(0.02,0.6);
7103 // CookLabel(pt,0.1); //For comparison only
7104 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7105 if ((pt->IsActive() || (pt->fRemoval==10) )){
7106 cerr<<found++<<'\r';
7109 MarkSeedFree( fSeeds->RemoveAt(i) );
7114 // fNTracks = found;
7116 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7119 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7120 Info("Clusters2Tracks","Number of found tracks %d",found);
7122 // UnloadClusters();
7127 void AliTPCtracker::Tracking(TObjArray * arr)
7130 // tracking of the seeds
7133 fSectors = fOuterSec;
7134 ParallelTracking(arr,150,63);
7135 fSectors = fOuterSec;
7136 ParallelTracking(arr,63,0);
7139 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7144 static TObjArray arrTracks;
7145 TObjArray * arr = &arrTracks;
7147 fSectors = fOuterSec;
7150 for (Int_t sec=0;sec<fkNOS;sec++){
7151 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7152 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7153 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7156 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7168 TObjArray * AliTPCtracker::Tracking()
7172 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7175 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7177 TObjArray * seeds = new TObjArray;
7179 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7180 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7181 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7189 Float_t fnumber = 3.0;
7190 Float_t fdensity = 3.0;
7193 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7194 arr = MakeSeedsHLT( fEventHLT );
7196 SumTracks(seeds,arr);
7199 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7200 //SignClusters(seeds,fnumber,fdensity);
7207 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7211 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7212 SumTracks(seeds,arr);
7213 SignClusters(seeds,fnumber,fdensity);
7215 for (Int_t i=2;i<6;i+=2){
7216 // seed high pt tracks
7219 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7220 SumTracks(seeds,arr);
7221 SignClusters(seeds,fnumber,fdensity);
7226 // RemoveUsed(seeds,0.9,0.9,1);
7227 // UnsignClusters();
7228 // SignClusters(seeds,fnumber,fdensity);
7232 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7234 // seed high pt tracks
7238 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7239 SumTracks(seeds,arr);
7240 SignClusters(seeds,fnumber,fdensity);
7245 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7246 SumTracks(seeds,arr);
7247 SignClusters(seeds,fnumber,fdensity);
7258 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7262 // RemoveUsed(seeds,0.75,0.75,1);
7264 //SignClusters(seeds,fnumber,fdensity);
7273 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7274 SumTracks(seeds,arr);
7275 SignClusters(seeds,fnumber,fdensity);
7277 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7278 SumTracks(seeds,arr);
7279 SignClusters(seeds,fnumber,fdensity);
7281 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7282 SumTracks(seeds,arr);
7283 SignClusters(seeds,fnumber,fdensity);
7285 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7286 SumTracks(seeds,arr);
7287 SignClusters(seeds,fnumber,fdensity);
7289 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7290 SumTracks(seeds,arr);
7291 SignClusters(seeds,fnumber,fdensity);
7294 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7295 SumTracks(seeds,arr);
7296 SignClusters(seeds,fnumber,fdensity);
7300 for (Int_t delta = 9; delta<30; delta+=gapSec){
7306 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7307 SumTracks(seeds,arr);
7308 SignClusters(seeds,fnumber,fdensity);
7310 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7311 SumTracks(seeds,arr);
7312 SignClusters(seeds,fnumber,fdensity);
7325 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7331 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7332 SumTracks(seeds,arr);
7333 SignClusters(seeds,fnumber,fdensity);
7335 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7336 SumTracks(seeds,arr);
7337 SignClusters(seeds,fnumber,fdensity);
7341 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7352 TObjArray * AliTPCtracker::TrackingSpecial()
7355 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7356 // no primary vertex seeding tried
7360 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7362 TObjArray * seeds = new TObjArray;
7367 Float_t fnumber = 3.0;
7368 Float_t fdensity = 3.0;
7371 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7372 cuts[1] = 3.5; // max tan(phi) angle for seeding
7373 cuts[2] = 3.; // not used (cut on z primary vertex)
7374 cuts[3] = 3.5; // max tan(theta) angle for seeding
7376 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7378 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7379 SumTracks(seeds,arr);
7380 SignClusters(seeds,fnumber,fdensity);
7384 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7395 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7398 //sum tracks to common container
7399 //remove suspicious tracks
7400 // RS: Attention: supplied tracks come in the static array, don't delete them
7401 Int_t nseed = arr2->GetEntriesFast();
7402 for (Int_t i=0;i<nseed;i++){
7403 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7406 // remove tracks with too big curvature
7408 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7409 MarkSeedFree( arr2->RemoveAt(i) );
7412 // REMOVE VERY SHORT TRACKS
7413 if (pt->GetNumberOfClusters()<20){
7414 MarkSeedFree( arr2->RemoveAt(i) );
7417 // NORMAL ACTIVE TRACK
7418 if (pt->IsActive()){
7419 arr1->AddLast(arr2->RemoveAt(i));
7422 //remove not usable tracks
7423 if (pt->GetRemoval()!=10){
7424 MarkSeedFree( arr2->RemoveAt(i) );
7428 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7429 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7430 arr1->AddLast(arr2->RemoveAt(i));
7432 MarkSeedFree( arr2->RemoveAt(i) );
7436 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7441 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7444 // try to track in parralel
7446 Int_t nseed=arr->GetEntriesFast();
7447 //prepare seeds for tracking
7448 for (Int_t i=0; i<nseed; i++) {
7449 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7451 if (!t.IsActive()) continue;
7452 // follow prolongation to the first layer
7453 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7454 FollowProlongation(t, rfirst+1);
7459 for (Int_t nr=rfirst; nr>=rlast; nr--){
7460 if (nr<fInnerSec->GetNRows())
7461 fSectors = fInnerSec;
7463 fSectors = fOuterSec;
7464 // make indexes with the cluster tracks for given
7466 // find nearest cluster
7467 for (Int_t i=0; i<nseed; i++) {
7468 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7470 if (nr==80) pt->UpdateReference();
7471 if (!pt->IsActive()) continue;
7472 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7473 if (pt->GetRelativeSector()>17) {
7476 UpdateClusters(t,nr);
7478 // prolonagate to the nearest cluster - if founded
7479 for (Int_t i=0; i<nseed; i++) {
7480 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7482 if (!pt->IsActive()) continue;
7483 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7484 if (pt->GetRelativeSector()>17) {
7487 FollowToNextCluster(*pt,nr);
7492 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7496 // if we use TPC track itself we have to "update" covariance
7498 Int_t nseed= arr->GetEntriesFast();
7499 for (Int_t i=0;i<nseed;i++){
7500 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7504 //rotate to current local system at first accepted point
7505 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
7506 Int_t sec = (index&0xff000000)>>24;
7508 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
7509 if (angle1>TMath::Pi())
7510 angle1-=2.*TMath::Pi();
7511 Float_t angle2 = pt->GetAlpha();
7513 if (TMath::Abs(angle1-angle2)>0.001){
7514 if (!pt->Rotate(angle1-angle2)) return;
7515 //angle2 = pt->GetAlpha();
7516 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
7517 //if (pt->GetAlpha()<0)
7518 // pt->fRelativeSector+=18;
7519 //sec = pt->fRelativeSector;
7528 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
7532 // if we use TPC track itself we have to "update" covariance
7534 Int_t nseed= arr->GetEntriesFast();
7535 for (Int_t i=0;i<nseed;i++){
7536 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7539 pt->SetFirstPoint(pt->GetLastPoint());
7547 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
7550 // make back propagation
7552 Int_t nseed= arr->GetEntriesFast();
7553 for (Int_t i=0;i<nseed;i++){
7554 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7555 if (pt&& pt->GetKinkIndex(0)<=0) {
7556 //AliTPCseed *pt2 = new AliTPCseed(*pt);
7557 fSectors = fInnerSec;
7558 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
7559 //fSectors = fOuterSec;
7560 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7561 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
7562 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
7563 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
7566 if (pt&& pt->GetKinkIndex(0)>0) {
7567 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
7568 pt->SetFirstPoint(kink->GetTPCRow0());
7569 fSectors = fInnerSec;
7570 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7578 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
7581 // make forward propagation
7583 Int_t nseed= arr->GetEntriesFast();
7585 for (Int_t i=0;i<nseed;i++){
7586 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7588 FollowProlongation(*pt,0,1,1);
7597 Int_t AliTPCtracker::PropagateForward()
7600 // propagate track forward
7602 Int_t nseed = fSeeds->GetEntriesFast();
7603 for (Int_t i=0;i<nseed;i++){
7604 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
7606 AliTPCseed &t = *pt;
7607 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
7608 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
7609 if (alpha < 0. ) alpha += 2.*TMath::Pi();
7610 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
7614 fSectors = fOuterSec;
7615 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
7616 fSectors = fInnerSec;
7617 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
7626 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
7629 // make back propagation, in between row0 and row1
7633 fSectors = fInnerSec;
7636 if (row1<fSectors->GetNRows())
7639 r1 = fSectors->GetNRows()-1;
7641 if (row0<fSectors->GetNRows()&& r1>0 )
7642 FollowBackProlongation(*pt,r1);
7643 if (row1<=fSectors->GetNRows())
7646 r1 = row1 - fSectors->GetNRows();
7647 if (r1<=0) return 0;
7648 if (r1>=fOuterSec->GetNRows()) return 0;
7649 fSectors = fOuterSec;
7650 return FollowBackProlongation(*pt,r1);
7658 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
7660 // gets cluster shape
7662 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
7663 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
7664 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
7665 Double_t angulary = seed->GetSnp();
7667 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
7668 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
7671 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
7672 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
7674 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
7675 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
7676 seed->SetCurrentSigmaY2(sigmay*sigmay);
7677 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
7678 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
7679 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
7680 // Float_t padlength = GetPadPitchLength(row);
7682 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
7683 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
7685 // Float_t sresz = fkParam->GetZSigma();
7686 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
7688 Float_t wy = GetSigmaY(seed);
7689 Float_t wz = GetSigmaZ(seed);
7692 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
7693 printf("problem\n");
7700 //__________________________________________________________________________
7701 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
7702 //--------------------------------------------------------------------
7703 //This function "cooks" a track label. If label<0, this track is fake.
7704 //--------------------------------------------------------------------
7705 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
7707 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
7711 Int_t noc=t->GetNumberOfClusters();
7713 //printf("\nnot founded prolongation\n\n\n");
7719 AliTPCclusterMI *clusters[160];
7721 for (Int_t i=0;i<160;i++) {
7728 for (i=0; i<160 && current<noc; i++) {
7730 Int_t index=t->GetClusterIndex2(i);
7731 if (index<=0) continue;
7732 if (index&0x8000) continue;
7734 //clusters[current]=GetClusterMI(index);
7735 if (t->GetClusterPointer(i)){
7736 clusters[current]=t->GetClusterPointer(i);
7742 Int_t lab=123456789;
7743 for (i=0; i<noc; i++) {
7744 AliTPCclusterMI *c=clusters[i];
7746 lab=TMath::Abs(c->GetLabel(0));
7748 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7754 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7756 for (i=0; i<noc; i++) {
7757 AliTPCclusterMI *c=clusters[i];
7759 if (TMath::Abs(c->GetLabel(1)) == lab ||
7760 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7762 if (noc<=0) { lab=-1; return;}
7763 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7766 Int_t tail=Int_t(0.10*noc);
7769 for (i=1; i<160&&ind<tail; i++) {
7770 // AliTPCclusterMI *c=clusters[noc-i];
7771 AliTPCclusterMI *c=clusters[i];
7773 if (lab == TMath::Abs(c->GetLabel(0)) ||
7774 lab == TMath::Abs(c->GetLabel(1)) ||
7775 lab == TMath::Abs(c->GetLabel(2))) max++;
7778 if (max < Int_t(0.5*tail)) lab=-lab;
7785 //delete[] clusters;
7789 //__________________________________________________________________________
7790 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
7791 //--------------------------------------------------------------------
7792 //This function "cooks" a track label. If label<0, this track is fake.
7793 //--------------------------------------------------------------------
7794 Int_t noc=t->GetNumberOfClusters();
7796 //printf("\nnot founded prolongation\n\n\n");
7802 AliTPCclusterMI *clusters[160];
7804 for (Int_t i=0;i<160;i++) {
7811 for (i=0; i<160 && current<noc; i++) {
7812 if (i<first) continue;
7813 if (i>last) continue;
7814 Int_t index=t->GetClusterIndex2(i);
7815 if (index<=0) continue;
7816 if (index&0x8000) continue;
7818 //clusters[current]=GetClusterMI(index);
7819 if (t->GetClusterPointer(i)){
7820 clusters[current]=t->GetClusterPointer(i);
7825 //if (noc<5) return -1;
7826 Int_t lab=123456789;
7827 for (i=0; i<noc; i++) {
7828 AliTPCclusterMI *c=clusters[i];
7830 lab=TMath::Abs(c->GetLabel(0));
7832 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7838 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7840 for (i=0; i<noc; i++) {
7841 AliTPCclusterMI *c=clusters[i];
7843 if (TMath::Abs(c->GetLabel(1)) == lab ||
7844 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7846 if (noc<=0) { lab=-1; return -1;}
7847 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7850 Int_t tail=Int_t(0.10*noc);
7853 for (i=1; i<160&&ind<tail; i++) {
7854 // AliTPCclusterMI *c=clusters[noc-i];
7855 AliTPCclusterMI *c=clusters[i];
7857 if (lab == TMath::Abs(c->GetLabel(0)) ||
7858 lab == TMath::Abs(c->GetLabel(1)) ||
7859 lab == TMath::Abs(c->GetLabel(2))) max++;
7862 if (max < Int_t(0.5*tail)) lab=-lab;
7865 // t->SetLabel(lab);
7869 //delete[] clusters;
7873 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
7875 //return pad row number for given x vector
7876 Float_t phi = TMath::ATan2(x[1],x[0]);
7877 if(phi<0) phi=2.*TMath::Pi()+phi;
7878 // Get the local angle in the sector philoc
7879 const Float_t kRaddeg = 180/3.14159265358979312;
7880 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
7881 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
7882 return GetRowNumber(localx);
7887 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
7889 //-----------------------------------------------------------------------
7890 // Fill the cluster and sharing bitmaps of the track
7891 //-----------------------------------------------------------------------
7893 Int_t firstpoint = 0;
7894 Int_t lastpoint = 159;
7895 AliTPCTrackerPoint *point;
7896 AliTPCclusterMI *cluster;
7899 TBits clusterMap(159);
7900 TBits sharedMap(159);
7902 for (int iter=firstpoint; iter<lastpoint; iter++) {
7903 // Change to cluster pointers to see if we have a cluster at given padrow
7905 cluster = t->GetClusterPointer(iter);
7907 clusterMap.SetBitNumber(iter, kTRUE);
7908 point = t->GetTrackPoint(iter);
7909 if (point->IsShared())
7910 sharedMap.SetBitNumber(iter,kTRUE);
7912 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
7913 fitMap.SetBitNumber(iter, kTRUE);
7917 esd->SetTPCClusterMap(clusterMap);
7918 esd->SetTPCSharedMap(sharedMap);
7919 esd->SetTPCFitMap(fitMap);
7920 if (nclsf != t->GetNumberOfClusters())
7921 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
7924 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
7926 // return flag if there is findable cluster at given position
7929 Float_t z = track.GetZ();
7931 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
7932 TMath::Abs(z)<fkParam->GetZLength(0) &&
7933 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
7939 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
7942 // Adding systematic error estimate to the covariance matrix
7943 // !!!! the systematic error for element 4 is in 1/GeV
7944 // 03.03.2012 MI changed in respect to the previous versions
7945 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7947 // use only the diagonal part if not specified otherwise
7948 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
7950 Double_t *covarS= (Double_t*)seed->GetCovariance();
7951 Double_t factor[5]={1,1,1,1,1};
7952 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
7953 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
7954 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
7955 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
7956 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
7958 factor[0]=factor[2];
7959 factor[4]=factor[2];
7965 for (Int_t i=0; i<5; i++){
7966 for (Int_t j=i; j<5; j++){
7967 Int_t index=seed->GetIndex(i,j);
7968 covarS[index]*=factor[i]*factor[j];
7974 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
7976 // Adding systematic error - as additive factor without correlation
7978 // !!!! the systematic error for element 4 is in 1/GeV
7979 // 03.03.2012 MI changed in respect to the previous versions
7981 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7982 Double_t *covarIn= (Double_t*)seed->GetCovariance();
7984 for (Int_t i=0;i<15;i++) covar[i]=0;
7990 covar[0] = param[0]*param[0];
7991 covar[2] = param[1]*param[1];
7992 covar[5] = param[2]*param[2];
7993 covar[9] = param[3]*param[3];
7994 covar[14]= param[4]*param[4];
7996 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
7998 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
7999 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
8001 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
8002 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
8003 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
8005 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
8006 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
8007 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
8008 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
8010 seed->AddCovariance(covar);
8013 //_____________________________________________________________________________
8014 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8017 // check events affected by TPC HV dip
8019 if(!esdEvent) return kFALSE;
8022 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8023 if(!db) return kFALSE;
8024 db->SetRun(esdEvent->GetRunNumber());
8026 // maximum allowed voltage before an event is identified as a dip event
8027 // and scanning period
8028 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8029 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8030 const Double_t tevSec = esdEvent->GetTimeStamp();
8032 for(Int_t sector=0; sector<72; sector++)
8034 // don't use excluded chambers, since the state is not defined at all
8035 if (!db->GetChamberHVStatus(sector)) continue;
8037 // get hv sensor of the chamber
8038 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8039 if (!sensor) continue;
8040 TGraph *grSensor=sensor->GetGraph();
8041 if (!grSensor) continue;
8042 if (grSensor->GetN()<1) continue;
8045 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8046 if(median < 1.) continue;
8048 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8049 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8050 if (tevSec-dipEventScanPeriod>nextTime) continue;
8051 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8052 if (deltaV>kTPCHVdip) {
8053 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8056 if (nextTime>tevSec+dipEventScanPeriod) break;
8063 //________________________________________
8064 void AliTPCtracker::MarkSeedFree(TObject *sd)
8066 // account that this seed is "deleted"
8067 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8069 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8072 int id = seed->GetPoolID();
8074 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8077 // AliInfo(Form("%d %p",id, seed));
8078 fSeedsPool->RemoveAt(id);
8079 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8080 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8083 //________________________________________
8084 TObject *&AliTPCtracker::NextFreeSeed()
8086 // return next free slot where the seed can be created
8087 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8088 // AliInfo(Form("%d",fLastSeedID));
8089 return (*fSeedsPool)[ fLastSeedID ];
8093 //________________________________________
8094 void AliTPCtracker::ResetSeedsPool()
8096 // mark all seeds in the pool as unused
8097 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8099 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8102 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8105 Double_t x= GetXrow(nrow);
8106 Double_t ymax= GetMaxY(nrow);
8112 if (!t.PropagateTo(x) ){
8113 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8119 Double_t y = t.GetY();
8121 if( rotate!=-1 ) rotate=1;
8122 } else if (y <-ymax) {
8123 if( rotate!=1 ) rotate = -1;
8125 if( rotate==0 ) break;
8126 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8127 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8128 //cout<<"can't rotate "<<endl;
8132 nRotations+= rotate;
8134 if( nRotations!=0 ){
8135 int newSec= t.GetRelativeSector()+nRotations;
8136 if( newSec>=fN ) newSec-=fN;
8137 else if( newSec<0 ) newSec +=fN;
8138 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8139 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8140 t.SetRelativeSector(newSec);
8145 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8148 // try to track in parralel
8150 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8153 Int_t nseed=arr->GetEntriesFast();
8154 //cout<<"Parallel tracking My.."<<endl;
8155 double shapeY2[160], shapeZ2[160];
8156 Int_t clusterIndex[160];
8158 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8159 //if( iSeed!=1 ) continue;
8160 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8164 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8168 for( int iter=0; iter<3; iter++ ){
8171 t.SetLastPoint(0); // first cluster in track position
8172 t.SetFirstPoint(nRows-1);
8173 t.ResetCovariance(.1);
8174 t.SetNumberOfClusters(0);
8175 for( int i=0; i<nRows; i++ ){
8179 t.SetClusterIndex2(i,-1);
8180 t.SetClusterIndex(i,-1);
8183 // pick up the clusters
8185 Double_t roady = 20.;
8186 Double_t roadz = 20.;
8193 t0.SetRelativeSector(t.GetRelativeSector());
8194 t0.SetLastPoint(0); // first cluster in track position
8195 t0.SetFirstPoint(159);
8196 for (Int_t nr=0; nr<nRows; nr++){
8197 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8198 else fSectors=fOuterSec;
8200 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8201 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8202 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8205 if (!IsActive(t0.GetRelativeSector(),nr)) {
8211 shapeY2[nr]=t0.GetCurrentSigmaY2();
8212 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8215 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8216 if( !krow ) continue;
8218 t.SetClusterIndex2(nr,-3); // foundable
8219 t.SetClusterIndex(nr,-3);
8221 AliTPCclusterMI *cl=0;
8223 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8225 double dy = cl->GetY()-t0.GetY();
8226 double dz = cl->GetZ()-t0.GetZ();
8227 double dr = sqrt(dy*dy+dz*dz);
8229 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8232 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8234 t0.SetClusterPointer(nr, cl);
8235 clusterIndex[nr] = krow.GetIndex(uindex);
8236 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8237 t0.SetLastPoint(nr);
8243 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8246 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8250 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8252 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8253 if( !t0.GetClusterPointer(nr) ) continue;
8254 int d = TMath::Abs(nr-midRow);
8262 // first fit 3 base points
8264 //cout<<"Fit3: "<<endl;
8265 for( int icl=0; icl<3; icl++){
8266 int nr = basePoints[icl];
8268 if( nr>=fInnerSec->GetNRows()){
8269 lr = nr - fInnerSec->GetNRows();
8271 } else fSectors=fInnerSec;
8273 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8275 //cout<<"WRONG!!!!"<<endl;
8278 int iSec = cl->GetDetector() %fkNIS;
8279 int rotate = iSec - t.GetRelativeSector();
8281 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8282 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8283 //cout<<"can't rotate "<<endl;
8286 t.SetRelativeSector(iSec);
8288 Double_t x= cl->GetX();
8289 if (!t.PropagateTo(x)){
8290 //cout<<"can't propagate to x="<<x<<endl;
8294 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8295 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8298 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8300 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8301 t.SetCurrentCluster(cl);
8304 t.SetErrorY2(shapeY2[nr]);
8305 t.SetErrorZ2(shapeZ2[nr]);
8308 for( int j=0; j<15; j++ ) cov[j]=0;
8314 t.AliExternalTrackParam::AddCovariance(cov);
8316 if( !UpdateTrack(&t,0) ){
8317 //cout<<"Can not update"<<endl;
8319 t.SetClusterIndex2(nr,-1);
8320 t.SetClusterIndex(nr,-1);
8321 t.SetClusterPointer(nr,0);
8324 //t.SetClusterPointer(nr, cl);
8327 //t.SetLastPoint(t0.GetLastPoint());
8328 //t.SetFirstPoint(t0.GetFirstPoint());
8330 //cout<<"Fit: "<<endl;
8331 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8333 if( nr>=fInnerSec->GetNRows()){
8334 lr = nr - fInnerSec->GetNRows();
8336 } else fSectors=fInnerSec;
8339 if( nr == basePoints[0] ) continue;
8340 if( nr == basePoints[1] ) continue;
8341 if( nr == basePoints[2] ) continue;
8343 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8346 int iSec = cl->GetDetector() %fkNIS;
8347 int rotate = iSec - t.GetRelativeSector();
8349 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8350 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8351 //cout<<"can't rotate "<<endl;
8354 t.SetRelativeSector(iSec);
8356 Double_t x= cl->GetX();
8357 if (!t.PropagateTo(x)){
8358 //cout<<"can't propagate to x="<<x<<endl;
8361 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8362 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8366 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8368 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8369 t.SetCurrentCluster(cl);
8371 t.SetErrorY2(shapeY2[nr]);
8372 t.SetErrorZ2(shapeZ2[nr]);
8374 if( !UpdateTrack(&t,0) ){
8375 //cout<<"Can not update"<<endl;
8377 t.SetClusterIndex2(nr,-1);
8378 t.SetClusterIndex(nr,-1);
8381 //t.SetClusterPointer(nr, cl);
8384 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8387 //cout<<"fitted track"<<iSeed<<endl;
8389 //cout<<"Statistics: "<<endl;
8390 Int_t foundable,found,shared;
8391 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8392 t.SetNFoundable(foundable);
8393 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8399 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8404 if( !hltEvent ) return 0;
8407 Int_t nentr=hltEvent->GetNumberOfTracks();
8409 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8411 TObjArray * seeds = new TObjArray(nentr);
8413 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8416 Int_t nTr=hltEvent->GetNumberOfTracks();
8418 for( int itr=0; itr<nTr; itr++ ){
8419 //if( itr!=97 ) continue;
8420 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8421 if( !param ) continue;
8422 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8423 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8425 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8426 tr.SetNumberOfClusters(0);
8427 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8429 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8430 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8431 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8433 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8434 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8436 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8437 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8439 seed->Rotate(alphaSec - alpha);
8441 seed->SetPoolID(fLastSeedID);
8442 seed->SetIsSeeding(kTRUE);
8443 seed->SetSeed1(nup-1);
8444 seed->SetSeed2(nup-2);
8445 seed->SetSeedType(0);
8446 seed->SetFirstPoint(-1);
8447 seed->SetLastPoint(-1);
8448 seeds->AddLast(seed); // note, track is seed, don't free the seed
8450 //if( index>3 ) break;
8454 fSectors = fOuterSec;
8456 TrackFollowingHLT(seeds );
8458 nTr = seeds->GetEntriesFast();
8459 for( int itr=0; itr<nTr; itr++ ){
8460 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8461 if( !seed ) continue;
8462 //FollowBackProlongation(*seed,0);
8463 // cout<<seed->GetNumberOfClusters()<<endl;
8464 Int_t foundable,found,shared;
8465 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8466 seed->SetNFoundable(foundable);
8467 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8468 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8469 //MarkSeedFree(seeds->RemoveAt(itr));
8472 if (seed->GetNumberOfClusters()<30 ||
8473 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8474 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8475 MarkSeedFree(seeds->RemoveAt(itr));
8479 for( int ir=0; ir<nup; ir++){
8480 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8484 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8488 void AliTPCtracker::FillClusterOccupancyInfo()
8490 //fill the cluster occupancy info into the ESD friend
8491 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8492 if (!esdFriend) return;
8494 for (Int_t isector=0; isector<18; isector++){
8495 AliTPCtrackerSector &iroc = fInnerSec[isector];
8496 AliTPCtrackerSector &oroc = fOuterSec[isector];
8498 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
8499 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
8500 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
8501 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
8502 //clusters used in tracking
8503 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
8504 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
8505 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
8506 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));