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 track->SetNoCluster(0);
306 return track->Update(c,chi2,i);
311 Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
314 // decide according desired precision to accept given
315 // cluster for tracking
317 seed->GetProlongation(cluster->GetX(),yt,zt);
318 Double_t sy2=ErrY2(seed,cluster);
319 Double_t sz2=ErrZ2(seed,cluster);
321 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
322 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
323 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
324 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
325 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
326 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
327 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
328 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
330 Double_t rdistance2 = rdistancey2+rdistancez2;
333 if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
334 Float_t rmsy2 = seed->GetCurrentSigmaY2();
335 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
336 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
337 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
338 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
339 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
340 AliExternalTrackParam param(*seed);
341 static TVectorD gcl(3),gtr(3);
343 param.GetXYZ(gcl.GetMatrixArray());
344 cluster->GetGlobalXYZ(gclf);
345 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
348 if (AliTPCReconstructor::StreamLevel()>2) {
349 (*fDebugStreamer)<<"ErrParam"<<
362 "rmsy2p30="<<rmsy2p30<<
363 "rmsz2p30="<<rmsz2p30<<
364 "rmsy2p30R="<<rmsy2p30R<<
365 "rmsz2p30R="<<rmsz2p30R<<
366 // normalize distance -
367 "rdisty="<<rdistancey2<<
368 "rdistz="<<rdistancez2<<
369 "rdist="<<rdistance2<< //
373 //return 0; // temporary
374 if (rdistance2>32) return 3;
377 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
378 return 2; //suspisiouce - will be changed
380 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
381 // strict cut on overlaped cluster
382 return 2; //suspisiouce - will be changed
384 if ( (rdistancey2>1. || rdistancez2>6.25 )
385 && cluster->GetType()<0){
386 seed->SetNFoundable(seed->GetNFoundable()-1);
390 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
392 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
393 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
406 //_____________________________________________________________________________
407 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
409 fkNIS(par->GetNInnerSector()/2),
411 fkNOS(par->GetNOuterSector()/2),
434 //---------------------------------------------------------------------
435 // The main TPC tracker constructor
436 //---------------------------------------------------------------------
437 fInnerSec=new AliTPCtrackerSector[fkNIS];
438 fOuterSec=new AliTPCtrackerSector[fkNOS];
441 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
442 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
445 Int_t nrowlow = par->GetNRowLow();
446 Int_t nrowup = par->GetNRowUp();
449 for (i=0;i<nrowlow;i++){
450 fXRow[i] = par->GetPadRowRadiiLow(i);
451 fPadLength[i]= par->GetPadPitchLength(0,i);
452 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
456 for (i=0;i<nrowup;i++){
457 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
458 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
459 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
462 if (AliTPCReconstructor::StreamLevel()>0) {
463 fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
466 fSeedsPool = new TClonesArray("AliTPCseed",1000);
468 //________________________________________________________________________
469 AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
496 //------------------------------------
497 // dummy copy constructor
498 //------------------------------------------------------------------
500 for (Int_t irow=0; irow<200; irow++){
507 AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
509 //------------------------------
511 //--------------------------------------------------------------
514 //_____________________________________________________________________________
515 AliTPCtracker::~AliTPCtracker() {
516 //------------------------------------------------------------------
517 // TPC tracker destructor
518 //------------------------------------------------------------------
525 if (fDebugStreamer) delete fDebugStreamer;
526 if (fSeedsPool) delete fSeedsPool;
530 void AliTPCtracker::FillESD(const TObjArray* arr)
534 //fill esds using updated tracks
537 // write tracks to the event
538 // store index of the track
539 Int_t nseed=arr->GetEntriesFast();
540 //FindKinks(arr,fEvent);
541 for (Int_t i=0; i<nseed; i++) {
542 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
546 if (AliTPCReconstructor::StreamLevel()>1) {
547 (*fDebugStreamer)<<"Track0"<<
551 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
552 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
553 pt->PropagateTo(fkParam->GetInnerRadiusLow());
556 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
558 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
559 iotrack.SetTPCPoints(pt->GetPoints());
560 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
561 iotrack.SetV0Indexes(pt->GetV0Indexes());
562 // iotrack.SetTPCpid(pt->fTPCr);
563 //iotrack.SetTPCindex(i);
564 MakeESDBitmaps(pt, &iotrack);
565 fEvent->AddTrack(&iotrack);
569 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
571 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
572 iotrack.SetTPCPoints(pt->GetPoints());
573 //iotrack.SetTPCindex(i);
574 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
575 iotrack.SetV0Indexes(pt->GetV0Indexes());
576 MakeESDBitmaps(pt, &iotrack);
577 // iotrack.SetTPCpid(pt->fTPCr);
578 fEvent->AddTrack(&iotrack);
582 // short tracks - maybe decays
584 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
585 Int_t found,foundable,shared;
586 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
587 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
589 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
590 //iotrack.SetTPCindex(i);
591 iotrack.SetTPCPoints(pt->GetPoints());
592 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
593 iotrack.SetV0Indexes(pt->GetV0Indexes());
594 MakeESDBitmaps(pt, &iotrack);
595 //iotrack.SetTPCpid(pt->fTPCr);
596 fEvent->AddTrack(&iotrack);
601 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
602 Int_t found,foundable,shared;
603 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
604 if (found<20) continue;
605 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
608 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
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 //iotrack.SetTPCindex(i);
615 fEvent->AddTrack(&iotrack);
618 // short tracks - secondaties
620 if ( (pt->GetNumberOfClusters()>30) ) {
621 Int_t found,foundable,shared;
622 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
623 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
625 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
626 iotrack.SetTPCPoints(pt->GetPoints());
627 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
628 iotrack.SetV0Indexes(pt->GetV0Indexes());
629 MakeESDBitmaps(pt, &iotrack);
630 //iotrack.SetTPCpid(pt->fTPCr);
631 //iotrack.SetTPCindex(i);
632 fEvent->AddTrack(&iotrack);
637 if ( (pt->GetNumberOfClusters()>15)) {
638 Int_t found,foundable,shared;
639 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
640 if (found<15) continue;
641 if (foundable<=0) continue;
642 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
643 if (float(found)/float(foundable)<0.8) continue;
646 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
647 iotrack.SetTPCPoints(pt->GetPoints());
648 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
649 iotrack.SetV0Indexes(pt->GetV0Indexes());
650 MakeESDBitmaps(pt, &iotrack);
651 // iotrack.SetTPCpid(pt->fTPCr);
652 //iotrack.SetTPCindex(i);
653 fEvent->AddTrack(&iotrack);
657 // >> account for suppressed tracks in the kink indices (RS)
658 int nESDtracks = fEvent->GetNumberOfTracks();
659 for (int it=nESDtracks;it--;) {
660 AliESDtrack* esdTr = fEvent->GetTrack(it);
661 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
662 for (int ik=0;ik<3;ik++) {
664 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
665 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
667 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
670 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
673 // << account for suppressed tracks in the kink indices (RS)
674 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
682 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
685 // Use calibrated cluster error from OCDB
687 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
689 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
690 Int_t ctype = cl->GetType();
691 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
692 Double_t angle = seed->GetSnp()*seed->GetSnp();
693 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
694 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
696 erry2+=0.5; // edge cluster
700 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
701 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
702 erry2+=addErr*addErr;
703 seed->SetErrorY2(erry2);
707 //calculate look-up table at the beginning
708 // static Bool_t ginit = kFALSE;
709 // static Float_t gnoise1,gnoise2,gnoise3;
710 // static Float_t ggg1[10000];
711 // static Float_t ggg2[10000];
712 // static Float_t ggg3[10000];
713 // static Float_t glandau1[10000];
714 // static Float_t glandau2[10000];
715 // static Float_t glandau3[10000];
717 // static Float_t gcor01[500];
718 // static Float_t gcor02[500];
719 // static Float_t gcorp[500];
723 // if (ginit==kFALSE){
724 // for (Int_t i=1;i<500;i++){
725 // Float_t rsigma = float(i)/100.;
726 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
727 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
728 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
732 // for (Int_t i=3;i<10000;i++){
736 // Float_t amp = float(i);
737 // Float_t padlength =0.75;
738 // gnoise1 = 0.0004/padlength;
739 // Float_t nel = 0.268*amp;
740 // Float_t nprim = 0.155*amp;
741 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
742 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
743 // if (glandau1[i]>1) glandau1[i]=1;
744 // glandau1[i]*=padlength*padlength/12.;
748 // gnoise2 = 0.0004/padlength;
750 // nprim = 0.133*amp;
751 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
752 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
753 // if (glandau2[i]>1) glandau2[i]=1;
754 // glandau2[i]*=padlength*padlength/12.;
759 // gnoise3 = 0.0004/padlength;
761 // nprim = 0.133*amp;
762 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
763 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
764 // if (glandau3[i]>1) glandau3[i]=1;
765 // glandau3[i]*=padlength*padlength/12.;
773 // Int_t amp = int(TMath::Abs(cl->GetQ()));
775 // seed->SetErrorY2(1.);
779 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
780 // Int_t ctype = cl->GetType();
781 // Float_t padlength= GetPadPitchLength(seed->GetRow());
782 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
783 // angle2 = angle2/(1-angle2);
785 // //cluster "quality"
786 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
789 // if (fSectors==fInnerSec){
790 // snoise2 = gnoise1;
791 // res = ggg1[amp]*z+glandau1[amp]*angle2;
792 // if (ctype==0) res *= gcor01[rsigmay];
795 // res*= gcorp[rsigmay];
799 // if (padlength<1.1){
800 // snoise2 = gnoise2;
801 // res = ggg2[amp]*z+glandau2[amp]*angle2;
802 // if (ctype==0) res *= gcor02[rsigmay];
805 // res*= gcorp[rsigmay];
809 // snoise2 = gnoise3;
810 // res = ggg3[amp]*z+glandau3[amp]*angle2;
811 // if (ctype==0) res *= gcor02[rsigmay];
814 // res*= gcorp[rsigmay];
821 // res*=2.4; // overestimate error 2 times
825 // if (res<2*snoise2)
828 // seed->SetErrorY2(res);
836 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
839 // Use calibrated cluster error from OCDB
841 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
843 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
844 Int_t ctype = cl->GetType();
845 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
847 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
848 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
849 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
850 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
852 errz2+=0.5; // edge cluster
856 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
857 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
858 errz2+=addErr*addErr;
859 seed->SetErrorZ2(errz2);
865 // //seed->SetErrorY2(0.1);
867 // //calculate look-up table at the beginning
868 // static Bool_t ginit = kFALSE;
869 // static Float_t gnoise1,gnoise2,gnoise3;
870 // static Float_t ggg1[10000];
871 // static Float_t ggg2[10000];
872 // static Float_t ggg3[10000];
873 // static Float_t glandau1[10000];
874 // static Float_t glandau2[10000];
875 // static Float_t glandau3[10000];
877 // static Float_t gcor01[1000];
878 // static Float_t gcor02[1000];
879 // static Float_t gcorp[1000];
883 // if (ginit==kFALSE){
884 // for (Int_t i=1;i<1000;i++){
885 // Float_t rsigma = float(i)/100.;
886 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
887 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
888 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
892 // for (Int_t i=3;i<10000;i++){
896 // Float_t amp = float(i);
897 // Float_t padlength =0.75;
898 // gnoise1 = 0.0004/padlength;
899 // Float_t nel = 0.268*amp;
900 // Float_t nprim = 0.155*amp;
901 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
902 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
903 // if (glandau1[i]>1) glandau1[i]=1;
904 // glandau1[i]*=padlength*padlength/12.;
908 // gnoise2 = 0.0004/padlength;
910 // nprim = 0.133*amp;
911 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
912 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
913 // if (glandau2[i]>1) glandau2[i]=1;
914 // glandau2[i]*=padlength*padlength/12.;
919 // gnoise3 = 0.0004/padlength;
921 // nprim = 0.133*amp;
922 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
923 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
924 // if (glandau3[i]>1) glandau3[i]=1;
925 // glandau3[i]*=padlength*padlength/12.;
933 // Int_t amp = int(TMath::Abs(cl->GetQ()));
935 // seed->SetErrorY2(1.);
939 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
940 // Int_t ctype = cl->GetType();
941 // Float_t padlength= GetPadPitchLength(seed->GetRow());
943 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
944 // // if (angle2<0.6) angle2 = 0.6;
945 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
947 // //cluster "quality"
948 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
951 // if (fSectors==fInnerSec){
952 // snoise2 = gnoise1;
953 // res = ggg1[amp]*z+glandau1[amp]*angle2;
954 // if (ctype==0) res *= gcor01[rsigmaz];
957 // res*= gcorp[rsigmaz];
961 // if (padlength<1.1){
962 // snoise2 = gnoise2;
963 // res = ggg2[amp]*z+glandau2[amp]*angle2;
964 // if (ctype==0) res *= gcor02[rsigmaz];
967 // res*= gcorp[rsigmaz];
971 // snoise2 = gnoise3;
972 // res = ggg3[amp]*z+glandau3[amp]*angle2;
973 // if (ctype==0) res *= gcor02[rsigmaz];
976 // res*= gcorp[rsigmaz];
985 // if ((ctype<0) &&<70){
990 // if (res<2*snoise2)
992 // if (res>3) res =3;
993 // seed->SetErrorZ2(res);
1001 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1003 //rotate to track "local coordinata
1004 Float_t x = seed->GetX();
1005 Float_t y = seed->GetY();
1006 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1009 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1010 if (!seed->Rotate(fSectors->GetAlpha()))
1012 } else if (y <-ymax) {
1013 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1014 if (!seed->Rotate(-fSectors->GetAlpha()))
1022 //_____________________________________________________________________________
1023 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1024 Double_t x2,Double_t y2,
1025 Double_t x3,Double_t y3) const
1027 //-----------------------------------------------------------------
1028 // Initial approximation of the track curvature
1029 //-----------------------------------------------------------------
1030 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1031 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1032 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1033 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1034 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1036 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1037 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1038 return -xr*yr/sqrt(xr*xr+yr*yr);
1043 //_____________________________________________________________________________
1044 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1045 Double_t x2,Double_t y2,
1046 Double_t x3,Double_t y3) const
1048 //-----------------------------------------------------------------
1049 // Initial approximation of the track curvature
1050 //-----------------------------------------------------------------
1056 Double_t det = x3*y2-x2*y3;
1057 if (TMath::Abs(det)<1e-10){
1061 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1062 Double_t x0 = x3*0.5-y3*u;
1063 Double_t y0 = y3*0.5+x3*u;
1064 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1070 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1071 Double_t x2,Double_t y2,
1072 Double_t x3,Double_t y3) const
1074 //-----------------------------------------------------------------
1075 // Initial approximation of the track curvature
1076 //-----------------------------------------------------------------
1082 Double_t det = x3*y2-x2*y3;
1083 if (TMath::Abs(det)<1e-10) {
1087 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1088 Double_t x0 = x3*0.5-y3*u;
1089 Double_t y0 = y3*0.5+x3*u;
1090 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1099 //_____________________________________________________________________________
1100 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1101 Double_t x2,Double_t y2,
1102 Double_t x3,Double_t y3) const
1104 //-----------------------------------------------------------------
1105 // Initial approximation of the track curvature times center of curvature
1106 //-----------------------------------------------------------------
1107 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1108 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1109 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1110 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1111 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1113 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1115 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1118 //_____________________________________________________________________________
1119 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1120 Double_t x2,Double_t y2,
1121 Double_t z1,Double_t z2) const
1123 //-----------------------------------------------------------------
1124 // Initial approximation of the tangent of the track dip angle
1125 //-----------------------------------------------------------------
1126 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1130 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1131 Double_t x2,Double_t y2,
1132 Double_t z1,Double_t z2, Double_t c) const
1134 //-----------------------------------------------------------------
1135 // Initial approximation of the tangent of the track dip angle
1136 //-----------------------------------------------------------------
1140 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1142 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1143 if (TMath::Abs(d*c*0.5)>1) return 0;
1144 // Double_t angle2 = TMath::ASin(d*c*0.5);
1145 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1146 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1148 angle2 = (z1-z2)*c/(angle2*2.);
1152 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1153 {//-----------------------------------------------------------------
1154 // This function find proloncation of a track to a reference plane x=x2.
1155 //-----------------------------------------------------------------
1159 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1163 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1164 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1168 Double_t dy = dx*(c1+c2)/(r1+r2);
1171 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1173 if (TMath::Abs(delta)>0.01){
1174 dz = x[3]*TMath::ASin(delta)/x[4];
1176 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1179 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1187 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1192 return LoadClusters();
1196 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1199 // load clusters to the memory
1200 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1201 Int_t lower = arr->LowerBound();
1202 Int_t entries = arr->GetEntriesFast();
1204 for (Int_t i=lower; i<entries; i++) {
1205 clrow = (AliTPCClustersRow*) arr->At(i);
1206 if(!clrow) continue;
1207 if(!clrow->GetArray()) continue;
1211 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1213 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1214 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1217 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1218 AliTPCtrackerRow * tpcrow=0;
1221 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1225 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1226 left = (sec-fkNIS*2)/fkNOS;
1229 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1230 for (Int_t j=0;j<tpcrow->GetN1();++j)
1231 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1234 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1235 for (Int_t j=0;j<tpcrow->GetN2();++j)
1236 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1238 clrow->GetArray()->Clear("C");
1247 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1250 // load clusters to the memory from one
1253 AliTPCclusterMI *clust=0;
1254 Int_t count[72][96] = { {0} , {0} };
1256 // loop over clusters
1257 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1258 clust = (AliTPCclusterMI*)arr->At(icl);
1259 if(!clust) continue;
1260 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1262 // transform clusters
1265 // count clusters per pad row
1266 count[clust->GetDetector()][clust->GetRow()]++;
1269 // insert clusters to sectors
1270 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1271 clust = (AliTPCclusterMI*)arr->At(icl);
1272 if(!clust) continue;
1274 Int_t sec = clust->GetDetector();
1275 Int_t row = clust->GetRow();
1277 // filter overlapping pad rows needed by HLT
1278 if(sec<fkNIS*2) { //IROCs
1279 if(row == 30) continue;
1282 if(row == 27 || row == 76) continue;
1287 // left = sec/fkNIS;
1288 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1291 // left = (sec-fkNIS*2)/fkNOS;
1292 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1296 // Load functions must be called behind LoadCluster(TClonesArray*)
1298 //LoadOuterSectors();
1299 //LoadInnerSectors();
1305 Int_t AliTPCtracker::LoadClusters()
1308 // load clusters to the memory
1309 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1311 // TTree * tree = fClustersArray.GetTree();
1312 AliInfo("LoadClusters()\n");
1314 TTree * tree = fInput;
1315 TBranch * br = tree->GetBranch("Segment");
1316 br->SetAddress(&clrow);
1318 // Conversion of pad, row coordinates in local tracking coords.
1319 // Could be skipped here; is already done in clusterfinder
1321 Int_t j=Int_t(tree->GetEntries());
1322 for (Int_t i=0; i<j; i++) {
1326 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1327 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1328 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1331 AliTPCtrackerRow * tpcrow=0;
1334 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1338 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1339 left = (sec-fkNIS*2)/fkNOS;
1342 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1343 for (Int_t k=0;k<tpcrow->GetN1();++k)
1344 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1347 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1348 for (Int_t k=0;k<tpcrow->GetN2();++k)
1349 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1356 if(!AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1361 void AliTPCtracker::UnloadClusters()
1364 // unload clusters from the memory
1366 Int_t nrows = fOuterSec->GetNRows();
1367 for (Int_t sec = 0;sec<fkNOS;sec++)
1368 for (Int_t row = 0;row<nrows;row++){
1369 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1371 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1372 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1374 tpcrow->ResetClusters();
1377 nrows = fInnerSec->GetNRows();
1378 for (Int_t sec = 0;sec<fkNIS;sec++)
1379 for (Int_t row = 0;row<nrows;row++){
1380 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1382 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1383 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1385 tpcrow->ResetClusters();
1391 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1393 // Filling cluster to the array - For visualization purposes
1396 nrows = fOuterSec->GetNRows();
1397 for (Int_t sec = 0;sec<fkNOS;sec++)
1398 for (Int_t row = 0;row<nrows;row++){
1399 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1400 if (!tpcrow) continue;
1401 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1402 array->AddLast((TObject*)((*tpcrow)[icl]));
1405 nrows = fInnerSec->GetNRows();
1406 for (Int_t sec = 0;sec<fkNIS;sec++)
1407 for (Int_t row = 0;row<nrows;row++){
1408 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1409 if (!tpcrow) continue;
1410 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1411 array->AddLast((TObject*)(*tpcrow)[icl]);
1417 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1421 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1422 AliTPCTransform *transform = calibDB->GetTransform() ;
1424 AliFatal("Tranformations not in calibDB");
1427 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1428 Double_t x[3]={cluster->GetRow(),cluster->GetPad(),cluster->GetTimeBin()};
1429 Int_t i[1]={cluster->GetDetector()};
1430 transform->Transform(x,i,0,1);
1431 // if (cluster->GetDetector()%36>17){
1436 // in debug mode check the transformation
1438 if (AliTPCReconstructor::StreamLevel()>2) {
1440 cluster->GetGlobalXYZ(gx);
1441 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1442 TTreeSRedirector &cstream = *fDebugStreamer;
1443 cstream<<"Transform"<<
1454 cluster->SetX(x[0]);
1455 cluster->SetY(x[1]);
1456 cluster->SetZ(x[2]);
1461 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1462 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1463 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1465 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1466 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1467 if (mat) mat->LocalToMaster(pos,posC);
1469 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1471 cluster->SetX(posC[0]);
1472 cluster->SetY(posC[1]);
1473 cluster->SetZ(posC[2]);
1477 void AliTPCtracker::ApplyTailCancellation(){
1479 // Correct the cluster charge for the ion tail effect
1480 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1484 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1485 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1486 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1487 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1488 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1489 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1491 // find the number of clusters for the whole TPC (nclALL)
1493 for (Int_t isector=0; isector<36; isector++){
1494 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1495 nclALL += sector.GetNClInSector(0);
1496 nclALL += sector.GetNClInSector(1);
1499 // start looping over all clusters
1500 for (Int_t iside=0; iside<2; iside++){ // loop over sides
1503 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
1504 // cache experimantal tuning factor for the different chamber type
1505 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
1506 std::cout << " ampfactor = " << ampfactor << std::endl;
1508 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
1511 // Cache time response functions and their positons to COG of the cluster
1512 TGraphErrors ** graphRes = new TGraphErrors *[20];
1513 Float_t * indexAmpGraphs = new Float_t[20];
1514 for (Int_t icache=0; icache<20; icache++)
1516 graphRes[icache] = NULL;
1517 indexAmpGraphs[icache] = 0;
1519 ///////////////////////////// --> position fo sie loop
1520 AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs);
1522 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
1523 Int_t nrows = sector.GetNRows(); // number of rows
1524 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
1526 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1528 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1529 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1530 if (iside>0) ncl=tpcrow.GetN2();
1532 // Order clusters in time for the proper correction of ion tail
1533 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
1534 Float_t qMaxArray[ncl];
1535 Int_t sortedClusterIndex[ncl];
1536 Float_t sortedClusterTimeBin[ncl];
1537 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
1538 for (Int_t i=0;i<ncl;i++)
1542 sortedClusterIndex[i]=i;
1543 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1545 rowClusterArray->AddAt(rowcl,i);
1547 rowClusterArray->RemoveAt(i);
1549 // Fill the timebin info to the array in order to sort wrt tb
1551 sortedClusterTimeBin[i]=0.0;
1553 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
1557 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
1559 // Main cluster correction loops over clusters
1560 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
1562 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
1566 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
1568 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
1570 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
1571 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
1572 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
1574 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
1576 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
1577 Double_t ionTailMax=0.;
1578 Double_t ionTailTotal=0.;
1579 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
1580 ionTailMax=TMath::Abs(ionTailMax);
1581 ionTailTotal=TMath::Abs(ionTailTotal);
1582 qTotArray[icl0]+=ionTailTotal;
1583 qMaxArray[icl0]+=ionTailMax;
1585 // Dump some info for debugging while clusters are being corrected
1586 if (AliTPCReconstructor::StreamLevel()==1) {
1587 TTreeSRedirector &cstream = *fDebugStreamer;
1588 if (gRandom->Rndm() > 0.999){
1589 cstream<<"IonTail"<<
1590 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
1591 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
1592 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
1593 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
1596 }// dump the results to the debug streamer if in debug mode
1598 }//end of second loop over clusters
1600 // Set corrected values of the corrected cluster
1601 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
1602 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
1604 // Dump some info for debugging after clusters are corrected
1605 if (AliTPCReconstructor::StreamLevel()==1) {
1606 TTreeSRedirector &cstream = *fDebugStreamer;
1607 if (gRandom->Rndm() > 0.999){
1608 cstream<<"IonTailCorrected"<<
1609 "cl0.=" << cl0 << // cluster 0 with huge Qmax
1610 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
1611 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
1612 "nclALL=" << nclALL <<
1613 "nclSector=" << nclSector <<
1615 "nclPad=" << nclPad <<
1621 }// dump the results to the debug streamer if in debug mode
1623 }//end of first loop over cluster
1624 delete rowClusterArray;
1625 }//end of loop over rows
1626 for (int i=0; i<20; i++) delete graphRes[i];
1628 delete [] indexAmpGraphs;
1630 }//end of loop over sectors
1631 }//end of loop over IROC/OROC
1632 }// end of side loop
1634 //_____________________________________________________________________________
1635 void AliTPCtracker::GetTailValue(const Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
1638 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
1641 const Double_t kMinPRF = 0.5; // minimal PRF width
1642 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
1643 ionTailMax = 0.; // correction value to be added to Qmax of cl0
1645 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
1646 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
1647 Int_t sectorPad = cl1->GetDetector(); // sector number
1648 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
1649 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
1650 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
1651 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
1652 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
1653 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
1655 Double_t sumAmp1=0.;
1656 for (Int_t idelta =-2; idelta<=2;idelta++){
1657 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
1660 Double_t sumAmp0=0.;
1661 for (Int_t idelta =-2; idelta<=2;idelta++){
1662 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
1665 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
1666 Int_t padScan=2; // +-2 pad-timebin window will be scanned
1667 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
1670 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
1671 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
1672 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
1674 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
1676 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
1677 for (Int_t j=0;j<20;j++) {
1678 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
1680 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
1684 if (!graphRes[ampIndex]) continue;
1685 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
1687 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
1690 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
1692 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
1693 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
1694 Float_t qMaxPad0 = amp0*qTot0;
1696 // Add 5 timebin range contribution around the max peak (-+2 tb window)
1697 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
1699 if (itb<0) continue;
1700 if (itb>=graphRes[ampIndex]->GetN()) continue;
1702 // calculate contribution to qTot
1703 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
1704 if (ipad1!=padcl0) {
1705 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
1707 ionTailTotal += tailCorr; // for center pad
1709 // calculate contribution to qMax
1710 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
1712 } // end of tb correction loop which is applied over 5 tb range
1714 } // end of cl0 loop
1715 } // end of cl1 loop
1719 //_____________________________________________________________________________
1720 Int_t AliTPCtracker::LoadOuterSectors() {
1721 //-----------------------------------------------------------------
1722 // This function fills outer TPC sectors with clusters.
1723 //-----------------------------------------------------------------
1724 Int_t nrows = fOuterSec->GetNRows();
1726 for (Int_t sec = 0;sec<fkNOS;sec++)
1727 for (Int_t row = 0;row<nrows;row++){
1728 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1729 Int_t sec2 = sec+2*fkNIS;
1731 Int_t ncl = tpcrow->GetN1();
1733 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1734 index=(((sec2<<8)+row)<<16)+ncl;
1735 tpcrow->InsertCluster(c,index);
1738 ncl = tpcrow->GetN2();
1740 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1741 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1742 tpcrow->InsertCluster(c,index);
1745 // write indexes for fast acces
1747 for (Int_t i=0;i<510;i++)
1748 tpcrow->SetFastCluster(i,-1);
1749 for (Int_t i=0;i<tpcrow->GetN();i++){
1750 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1751 tpcrow->SetFastCluster(zi,i); // write index
1754 for (Int_t i=0;i<510;i++){
1755 if (tpcrow->GetFastCluster(i)<0)
1756 tpcrow->SetFastCluster(i,last);
1758 last = tpcrow->GetFastCluster(i);
1767 //_____________________________________________________________________________
1768 Int_t AliTPCtracker::LoadInnerSectors() {
1769 //-----------------------------------------------------------------
1770 // This function fills inner TPC sectors with clusters.
1771 //-----------------------------------------------------------------
1772 Int_t nrows = fInnerSec->GetNRows();
1774 for (Int_t sec = 0;sec<fkNIS;sec++)
1775 for (Int_t row = 0;row<nrows;row++){
1776 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1779 Int_t ncl = tpcrow->GetN1();
1781 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1782 index=(((sec<<8)+row)<<16)+ncl;
1783 tpcrow->InsertCluster(c,index);
1786 ncl = tpcrow->GetN2();
1788 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1789 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1790 tpcrow->InsertCluster(c,index);
1793 // write indexes for fast acces
1795 for (Int_t i=0;i<510;i++)
1796 tpcrow->SetFastCluster(i,-1);
1797 for (Int_t i=0;i<tpcrow->GetN();i++){
1798 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1799 tpcrow->SetFastCluster(zi,i); // write index
1802 for (Int_t i=0;i<510;i++){
1803 if (tpcrow->GetFastCluster(i)<0)
1804 tpcrow->SetFastCluster(i,last);
1806 last = tpcrow->GetFastCluster(i);
1818 //_________________________________________________________________________
1819 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
1820 //--------------------------------------------------------------------
1821 // Return pointer to a given cluster
1822 //--------------------------------------------------------------------
1823 if (index<0) return 0; // no cluster
1824 Int_t sec=(index&0xff000000)>>24;
1825 Int_t row=(index&0x00ff0000)>>16;
1826 Int_t ncl=(index&0x00007fff)>>00;
1828 const AliTPCtrackerRow * tpcrow=0;
1829 TClonesArray * clrow =0;
1831 if (sec<0 || sec>=fkNIS*4) {
1832 AliWarning(Form("Wrong sector %d",sec));
1837 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
1838 if (tracksec.GetNRows()<=row) return 0;
1839 tpcrow = &(tracksec[row]);
1840 if (tpcrow==0) return 0;
1843 if (tpcrow->GetN1()<=ncl) return 0;
1844 clrow = tpcrow->GetClusters1();
1847 if (tpcrow->GetN2()<=ncl) return 0;
1848 clrow = tpcrow->GetClusters2();
1852 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
1853 if (tracksec.GetNRows()<=row) return 0;
1854 tpcrow = &(tracksec[row]);
1855 if (tpcrow==0) return 0;
1857 if (sec-2*fkNIS<fkNOS) {
1858 if (tpcrow->GetN1()<=ncl) return 0;
1859 clrow = tpcrow->GetClusters1();
1862 if (tpcrow->GetN2()<=ncl) return 0;
1863 clrow = tpcrow->GetClusters2();
1867 return (AliTPCclusterMI*)clrow->At(ncl);
1873 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
1874 //-----------------------------------------------------------------
1875 // This function tries to find a track prolongation to next pad row
1876 //-----------------------------------------------------------------
1878 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
1881 AliTPCclusterMI *cl=0;
1882 Int_t tpcindex= t.GetClusterIndex2(nr);
1884 // update current shape info every 5 pad-row
1885 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1889 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
1891 if (tpcindex==-1) return 0; //track in dead zone
1892 if (tpcindex >= 0){ //
1893 cl = t.GetClusterPointer(nr);
1894 //if (cl==0) cl = GetClusterMI(tpcindex);
1895 if (!cl) cl = GetClusterMI(tpcindex);
1896 t.SetCurrentClusterIndex1(tpcindex);
1899 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
1900 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1902 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1903 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1905 if (TMath::Abs(angle-t.GetAlpha())>0.001){
1906 Double_t rotation = angle-t.GetAlpha();
1907 t.SetRelativeSector(relativesector);
1908 if (!t.Rotate(rotation)) {
1909 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1913 if (!t.PropagateTo(x)) {
1914 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1918 t.SetCurrentCluster(cl);
1920 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1921 if ((tpcindex&0x8000)==0) accept =0;
1923 //if founded cluster is acceptible
1924 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
1925 t.SetErrorY2(t.GetErrorY2()+0.03);
1926 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1927 t.SetErrorY2(t.GetErrorY2()*3);
1928 t.SetErrorZ2(t.GetErrorZ2()*3);
1930 t.SetNFoundable(t.GetNFoundable()+1);
1931 UpdateTrack(&t,accept);
1934 else { // Remove old cluster from track
1935 t.SetClusterIndex(nr, -3);
1936 t.SetClusterPointer(nr, 0);
1940 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
1941 if (fIteration>1 && IsFindable(t)){
1942 // not look for new cluster during refitting
1943 t.SetNFoundable(t.GetNFoundable()+1);
1948 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1949 if (!t.PropagateTo(x)) {
1950 if (fIteration==0) t.SetRemoval(10);
1953 Double_t y = t.GetY();
1954 if (TMath::Abs(y)>ymax){
1956 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1957 if (!t.Rotate(fSectors->GetAlpha()))
1959 } else if (y <-ymax) {
1960 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1961 if (!t.Rotate(-fSectors->GetAlpha()))
1964 if (!t.PropagateTo(x)) {
1965 if (fIteration==0) t.SetRemoval(10);
1971 Double_t z=t.GetZ();
1974 if (!IsActive(t.GetRelativeSector(),nr)) {
1976 t.SetClusterIndex2(nr,-1);
1979 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1980 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
1981 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
1983 if (!isActive || !isActive2) return 0;
1985 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
1986 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
1988 Double_t roadz = 1.;
1990 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1992 t.SetClusterIndex2(nr,-1);
1998 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
1999 t.SetNFoundable(t.GetNFoundable()+1);
2005 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2006 cl = krow.FindNearest2(y,z,roady,roadz,index);
2007 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2010 t.SetCurrentCluster(cl);
2012 if (fIteration==2&&cl->IsUsed(10)) return 0;
2013 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2014 if (fIteration==2&&cl->IsUsed(11)) {
2015 t.SetErrorY2(t.GetErrorY2()+0.03);
2016 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2017 t.SetErrorY2(t.GetErrorY2()*3);
2018 t.SetErrorZ2(t.GetErrorZ2()*3);
2021 if (t.fCurrentCluster->IsUsed(10)){
2026 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2032 if (accept<3) UpdateTrack(&t,accept);
2035 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2043 //_________________________________________________________________________
2044 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2046 // Get track space point by index
2047 // return false in case the cluster doesn't exist
2048 AliTPCclusterMI *cl = GetClusterMI(index);
2049 if (!cl) return kFALSE;
2050 Int_t sector = (index&0xff000000)>>24;
2051 // Int_t row = (index&0x00ff0000)>>16;
2053 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2054 xyz[0] = cl->GetX();
2055 xyz[1] = cl->GetY();
2056 xyz[2] = cl->GetZ();
2058 fkParam->AdjustCosSin(sector,cos,sin);
2059 Float_t x = cos*xyz[0]-sin*xyz[1];
2060 Float_t y = cos*xyz[1]+sin*xyz[0];
2062 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2063 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2064 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2065 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2066 cov[0] = sin*sin*sigmaY2;
2067 cov[1] = -sin*cos*sigmaY2;
2069 cov[3] = cos*cos*sigmaY2;
2072 p.SetXYZ(x,y,xyz[2],cov);
2073 AliGeomManager::ELayerID iLayer;
2075 if (sector < fkParam->GetNInnerSector()) {
2076 iLayer = AliGeomManager::kTPC1;
2080 iLayer = AliGeomManager::kTPC2;
2081 idet = sector - fkParam->GetNInnerSector();
2083 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2084 p.SetVolumeID(volid);
2090 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2091 //-----------------------------------------------------------------
2092 // This function tries to find a track prolongation to next pad row
2093 //-----------------------------------------------------------------
2094 t.SetCurrentCluster(0);
2095 t.SetCurrentClusterIndex1(-3);
2097 Double_t xt=t.GetX();
2098 Int_t row = GetRowNumber(xt)-1;
2099 Double_t ymax= GetMaxY(nr);
2101 if (row < nr) return 1; // don't prolongate if not information until now -
2102 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2104 // return 0; // not prolongate strongly inclined tracks
2106 // if (TMath::Abs(t.GetSnp())>0.95) {
2108 // return 0; // not prolongate strongly inclined tracks
2109 // }// patch 28 fev 06
2111 Double_t x= GetXrow(nr);
2113 //t.PropagateTo(x+0.02);
2114 //t.PropagateTo(x+0.01);
2115 if (!t.PropagateTo(x)){
2122 if (TMath::Abs(y)>ymax){
2124 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2125 if (!t.Rotate(fSectors->GetAlpha()))
2127 } else if (y <-ymax) {
2128 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2129 if (!t.Rotate(-fSectors->GetAlpha()))
2132 // if (!t.PropagateTo(x)){
2139 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2141 if (!IsActive(t.GetRelativeSector(),nr)) {
2143 t.SetClusterIndex2(nr,-1);
2146 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2148 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2150 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2152 t.SetClusterIndex2(nr,-1);
2158 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2159 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2165 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2166 // t.fCurrentSigmaY = GetSigmaY(&t);
2167 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2171 AliTPCclusterMI *cl=0;
2174 Double_t roady = 1.;
2175 Double_t roadz = 1.;
2179 index = t.GetClusterIndex2(nr);
2180 if ( (index >= 0) && (index&0x8000)==0){
2181 cl = t.GetClusterPointer(nr);
2182 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2183 t.SetCurrentClusterIndex1(index);
2185 t.SetCurrentCluster(cl);
2191 // if (index<0) return 0;
2192 UInt_t uindex = TMath::Abs(index);
2195 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2196 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2199 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2200 t.SetCurrentCluster(cl);
2206 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2207 //-----------------------------------------------------------------
2208 // This function tries to find a track prolongation to next pad row
2209 //-----------------------------------------------------------------
2211 //update error according neighborhoud
2213 if (t.GetCurrentCluster()) {
2215 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2217 if (t.GetCurrentCluster()->IsUsed(10)){
2222 t.SetNShared(t.GetNShared()+1);
2223 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2228 if (fIteration>0) accept = 0;
2229 if (accept<3) UpdateTrack(&t,accept);
2233 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2234 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2236 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2244 //_____________________________________________________________________________
2245 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2246 //-----------------------------------------------------------------
2247 // This function tries to find a track prolongation.
2248 //-----------------------------------------------------------------
2249 Double_t xt=t.GetX();
2251 Double_t alpha=t.GetAlpha();
2252 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2253 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2255 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2257 Int_t first = GetRowNumber(xt);
2262 for (Int_t nr= first; nr>=rf; nr-=step) {
2264 if (t.GetKinkIndexes()[0]>0){
2265 for (Int_t i=0;i<3;i++){
2266 Int_t index = t.GetKinkIndexes()[i];
2267 if (index==0) break;
2268 if (index<0) continue;
2270 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2272 printf("PROBLEM\n");
2275 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2277 AliExternalTrackParam paramd(t);
2278 kink->SetDaughter(paramd);
2279 kink->SetStatus(2,5);
2286 if (nr==80) t.UpdateReference();
2287 if (nr<fInnerSec->GetNRows())
2288 fSectors = fInnerSec;
2290 fSectors = fOuterSec;
2291 if (FollowToNext(t,nr)==0)
2304 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2305 //-----------------------------------------------------------------
2306 // This function tries to find a track prolongation.
2307 //-----------------------------------------------------------------
2309 Double_t xt=t.GetX();
2310 Double_t alpha=t.GetAlpha();
2311 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2312 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2313 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2315 Int_t first = t.GetFirstPoint();
2316 Int_t ri = GetRowNumber(xt);
2320 if (first<ri) first = ri;
2322 if (first<0) first=0;
2323 for (Int_t nr=first; nr<=rf; nr++) {
2324 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2325 if (t.GetKinkIndexes()[0]<0){
2326 for (Int_t i=0;i<3;i++){
2327 Int_t index = t.GetKinkIndexes()[i];
2328 if (index==0) break;
2329 if (index>0) continue;
2330 index = TMath::Abs(index);
2331 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2333 printf("PROBLEM\n");
2336 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2338 AliExternalTrackParam paramm(t);
2339 kink->SetMother(paramm);
2340 kink->SetStatus(2,1);
2347 if (nr<fInnerSec->GetNRows())
2348 fSectors = fInnerSec;
2350 fSectors = fOuterSec;
2361 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2363 // overlapping factor
2369 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2372 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2374 Float_t distance = TMath::Sqrt(dz2+dy2);
2375 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2378 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2379 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2384 if (firstpoint>lastpoint) {
2385 firstpoint =lastpoint;
2390 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2391 if (s1->GetClusterIndex2(i)>0) sum1++;
2392 if (s2->GetClusterIndex2(i)>0) sum2++;
2393 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2397 if (sum<5) return 0;
2399 Float_t summin = TMath::Min(sum1+1,sum2+1);
2400 Float_t ratio = (sum+1)/Float_t(summin);
2404 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2408 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2409 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2410 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2411 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2416 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2417 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2418 Int_t firstpoint = 0;
2419 Int_t lastpoint = 160;
2421 // if (firstpoint>=lastpoint-5) return;;
2423 for (Int_t i=firstpoint;i<lastpoint;i++){
2424 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2425 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2429 if (sumshared>cutN0){
2432 for (Int_t i=firstpoint;i<lastpoint;i++){
2433 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2434 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2435 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2436 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2437 if (s1->IsActive()&&s2->IsActive()){
2438 p1->SetShared(kTRUE);
2439 p2->SetShared(kTRUE);
2445 if (sumshared>cutN0){
2446 for (Int_t i=0;i<4;i++){
2447 if (s1->GetOverlapLabel(3*i)==0){
2448 s1->SetOverlapLabel(3*i, s2->GetLabel());
2449 s1->SetOverlapLabel(3*i+1,sumshared);
2450 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2454 for (Int_t i=0;i<4;i++){
2455 if (s2->GetOverlapLabel(3*i)==0){
2456 s2->SetOverlapLabel(3*i, s1->GetLabel());
2457 s2->SetOverlapLabel(3*i+1,sumshared);
2458 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2465 void AliTPCtracker::SignShared(TObjArray * arr)
2468 //sort trackss according sectors
2470 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2471 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2473 //if (pt) RotateToLocal(pt);
2477 arr->Sort(); // sorting according relative sectors
2478 arr->Expand(arr->GetEntries());
2481 Int_t nseed=arr->GetEntriesFast();
2482 for (Int_t i=0; i<nseed; i++) {
2483 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2485 for (Int_t j=0;j<12;j++){
2486 pt->SetOverlapLabel(j,0);
2489 for (Int_t i=0; i<nseed; i++) {
2490 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2492 if (pt->GetRemoval()>10) continue;
2493 for (Int_t j=i+1; j<nseed; j++){
2494 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2495 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2497 if (pt2->GetRemoval()<=10) {
2498 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2506 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
2509 //sort tracks in array according mode criteria
2510 Int_t nseed = arr->GetEntriesFast();
2511 for (Int_t i=0; i<nseed; i++) {
2512 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2523 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
2526 // Loop over all tracks and remove overlaped tracks (with lower quality)
2528 // 1. Unsign clusters
2529 // 2. Sort tracks according quality
2530 // Quality is defined by the number of cluster between first and last points
2532 // 3. Loop over tracks - decreasing quality order
2533 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
2534 // b.) remove - If the minimal number of clusters less than minimal and not ITS
2535 // c.) if track accepted - sign clusters
2537 //Called in - AliTPCtracker::Clusters2Tracks()
2538 // - AliTPCtracker::PropagateBack()
2539 // - AliTPCtracker::RefitInward()
2542 // factor1 - factor for constrained
2543 // factor2 - for non constrained tracks
2544 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
2548 Int_t nseed = arr->GetEntriesFast();
2549 Float_t * quality = new Float_t[nseed];
2550 Int_t * indexes = new Int_t[nseed];
2554 for (Int_t i=0; i<nseed; i++) {
2555 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2560 pt->UpdatePoints(); //select first last max dens points
2561 Float_t * points = pt->GetPoints();
2562 if (points[3]<0.8) quality[i] =-1;
2563 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2564 //prefer high momenta tracks if overlaps
2565 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
2567 TMath::Sort(nseed,quality,indexes);
2570 for (Int_t itrack=0; itrack<nseed; itrack++) {
2571 Int_t trackindex = indexes[itrack];
2572 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
2575 if (quality[trackindex]<0){
2576 MarkSeedFree( arr->RemoveAt(trackindex) );
2581 Int_t first = Int_t(pt->GetPoints()[0]);
2582 Int_t last = Int_t(pt->GetPoints()[2]);
2583 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2585 Int_t found,foundable,shared;
2586 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
2587 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2588 Bool_t itsgold =kFALSE;
2591 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2595 if (Float_t(shared+1)/Float_t(found+1)>factor){
2596 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2597 if( AliTPCReconstructor::StreamLevel()>3){
2598 TTreeSRedirector &cstream = *fDebugStreamer;
2599 cstream<<"RemoveUsed"<<
2600 "iter="<<fIteration<<
2604 MarkSeedFree( arr->RemoveAt(trackindex) );
2607 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
2608 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2609 if( AliTPCReconstructor::StreamLevel()>3){
2610 TTreeSRedirector &cstream = *fDebugStreamer;
2611 cstream<<"RemoveShort"<<
2612 "iter="<<fIteration<<
2616 MarkSeedFree( arr->RemoveAt(trackindex) );
2622 //if (sharedfactor>0.4) continue;
2623 if (pt->GetKinkIndexes()[0]>0) continue;
2624 //Remove tracks with undefined properties - seems
2625 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
2627 for (Int_t i=first; i<last; i++) {
2628 Int_t index=pt->GetClusterIndex2(i);
2629 // if (index<0 || index&0x8000 ) continue;
2630 if (index<0 || index&0x8000 ) continue;
2631 AliTPCclusterMI *c= pt->GetClusterPointer(i);
2638 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2644 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
2647 // Dump clusters after reco
2648 // signed and unsigned cluster can be visualized
2649 // 1. Unsign all cluster
2650 // 2. Sign all used clusters
2653 Int_t nseed = trackArray->GetEntries();
2654 for (Int_t i=0; i<nseed; i++){
2655 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
2659 Bool_t isKink=pt->GetKinkIndex(0)!=0;
2660 for (Int_t j=0; j<160; ++j) {
2661 Int_t index=pt->GetClusterIndex2(j);
2662 if (index<0) continue;
2663 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2665 if (isKink) c->Use(100); // kink
2666 c->Use(10); // by default usage 10
2671 for (Int_t sec=0;sec<fkNIS;sec++){
2672 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2673 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2674 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
2675 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2676 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2677 (*fDebugStreamer)<<"clDump"<<
2685 cla = fInnerSec[sec][row].GetClusters2();
2686 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
2687 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2688 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2689 (*fDebugStreamer)<<"clDump"<<
2700 for (Int_t sec=0;sec<fkNOS;sec++){
2701 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2702 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2703 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
2705 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2706 cl->GetGlobalXYZ(gx);
2707 (*fDebugStreamer)<<"clDump"<<
2715 cla = fOuterSec[sec][row].GetClusters2();
2716 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
2718 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2719 cl->GetGlobalXYZ(gx);
2720 (*fDebugStreamer)<<"clDump"<<
2732 void AliTPCtracker::UnsignClusters()
2735 // loop over all clusters and unsign them
2738 for (Int_t sec=0;sec<fkNIS;sec++){
2739 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2740 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2741 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2742 // if (cl[icl].IsUsed(10))
2743 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2744 cla = fInnerSec[sec][row].GetClusters2();
2745 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2746 //if (cl[icl].IsUsed(10))
2747 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2751 for (Int_t sec=0;sec<fkNOS;sec++){
2752 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2753 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2754 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2755 //if (cl[icl].IsUsed(10))
2756 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2757 cla = fOuterSec[sec][row].GetClusters2();
2758 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2759 //if (cl[icl].IsUsed(10))
2760 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2768 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
2771 //sign clusters to be "used"
2773 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2774 // loop over "primaries"
2788 Int_t nseed = arr->GetEntriesFast();
2789 for (Int_t i=0; i<nseed; i++) {
2790 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2794 if (!(pt->IsActive())) continue;
2795 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2796 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2798 sumdens2+= dens*dens;
2799 sumn += pt->GetNumberOfClusters();
2800 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2801 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2804 sumchi2 +=chi2*chi2;
2809 Float_t mdensity = 0.9;
2810 Float_t meann = 130;
2811 Float_t meanchi = 1;
2812 Float_t sdensity = 0.1;
2813 Float_t smeann = 10;
2814 Float_t smeanchi =0.4;
2818 mdensity = sumdens/sum;
2820 meanchi = sumchi/sum;
2822 sdensity = sumdens2/sum-mdensity*mdensity;
2824 sdensity = TMath::Sqrt(sdensity);
2828 smeann = sumn2/sum-meann*meann;
2830 smeann = TMath::Sqrt(smeann);
2834 smeanchi = sumchi2/sum - meanchi*meanchi;
2836 smeanchi = TMath::Sqrt(smeanchi);
2842 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
2844 for (Int_t i=0; i<nseed; i++) {
2845 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2849 if (pt->GetBSigned()) continue;
2850 if (pt->GetBConstrain()) continue;
2851 //if (!(pt->IsActive())) continue;
2853 Int_t found,foundable,shared;
2854 pt->GetClusterStatistic(0,160,found, foundable,shared);
2855 if (shared/float(found)>0.3) {
2856 if (shared/float(found)>0.9 ){
2857 //MarkSeedFree( arr->RemoveAt(i) );
2862 Bool_t isok =kFALSE;
2863 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2865 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2867 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2869 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2873 for (Int_t j=0; j<160; ++j) {
2874 Int_t index=pt->GetClusterIndex2(j);
2875 if (index<0) continue;
2876 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2878 //if (!(c->IsUsed(10))) c->Use();
2885 Double_t maxchi = meanchi+2.*smeanchi;
2887 for (Int_t i=0; i<nseed; i++) {
2888 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2892 //if (!(pt->IsActive())) continue;
2893 if (pt->GetBSigned()) continue;
2894 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
2895 if (chi>maxchi) continue;
2898 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2900 //sign only tracks with enoug big density at the beginning
2902 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
2905 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2906 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2908 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2909 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2912 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2913 //Int_t noc=pt->GetNumberOfClusters();
2914 pt->SetBSigned(kTRUE);
2915 for (Int_t j=0; j<160; ++j) {
2917 Int_t index=pt->GetClusterIndex2(j);
2918 if (index<0) continue;
2919 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2921 // if (!(c->IsUsed(10))) c->Use();
2926 // gLastCheck = nseed;
2935 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
2938 // back propagation of ESD tracks
2941 if (!event) return 0;
2942 const Int_t kMaxFriendTracks=2000;
2945 // extract correction object for multiplicity dependence of dEdx
2946 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
2948 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
2950 AliFatal("Tranformations not in RefitInward");
2953 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
2954 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
2955 Int_t nContribut = event->GetNumberOfTracks();
2956 TGraphErrors * graphMultDependenceDeDx = 0x0;
2957 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
2958 if (recoParam->GetUseTotCharge()) {
2959 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2961 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2967 //PrepareForProlongation(fSeeds,1);
2968 PropagateForward2(fSeeds);
2969 RemoveUsed2(fSeeds,0.4,0.4,20);
2971 TObjArray arraySeed(fSeeds->GetEntries());
2972 for (Int_t i=0;i<fSeeds->GetEntries();i++) {
2973 arraySeed.AddAt(fSeeds->At(i),i);
2975 SignShared(&arraySeed);
2976 // FindCurling(fSeeds, event,2); // find multi found tracks
2977 FindSplitted(fSeeds, event,2); // find multi found tracks
2978 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,2); // find multi found tracks
2981 Int_t nseed = fSeeds->GetEntriesFast();
2982 for (Int_t i=0;i<nseed;i++){
2983 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2984 if (!seed) continue;
2985 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
2986 AliESDtrack *esd=event->GetTrack(i);
2988 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
2989 AliExternalTrackParam paramIn;
2990 AliExternalTrackParam paramOut;
2991 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
2992 if (AliTPCReconstructor::StreamLevel()>2) {
2993 (*fDebugStreamer)<<"RecoverIn"<<
2997 "pout.="<<¶mOut<<
3002 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3003 seed->SetNumberOfClusters(ncl);
3007 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3008 seed->UpdatePoints();
3009 AddCovariance(seed);
3010 MakeESDBitmaps(seed, esd);
3011 seed->CookdEdx(0.02,0.6);
3012 CookLabel(seed,0.1); //For comparison only
3014 if (AliTPCReconstructor::StreamLevel()>1 && seed!=0) {
3015 TTreeSRedirector &cstream = *fDebugStreamer;
3022 if (seed->GetNumberOfClusters()>15){
3023 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3024 esd->SetTPCPoints(seed->GetPoints());
3025 esd->SetTPCPointsF(seed->GetNFoundable());
3026 Int_t ndedx = seed->GetNCDEDX(0);
3027 Float_t sdedx = seed->GetSDEDX(0);
3028 Float_t dedx = seed->GetdEdx();
3029 // apply mutliplicity dependent dEdx correction if available
3030 if (graphMultDependenceDeDx) {
3031 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3032 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3034 esd->SetTPCsignal(dedx, sdedx, ndedx);
3036 // fill new dEdx information
3038 Double32_t signal[4];
3039 Double32_t signalMax[4];
3043 for(Int_t iarr=0;iarr<3;iarr++) {
3044 signal[iarr] = seed->GetDEDXregion(iarr+1);
3045 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3046 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3047 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3049 signal[3] = seed->GetDEDXregion(4);
3050 signalMax[3] = seed->GetDEDXregion(8);
3053 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3054 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3055 infoTpcPid->SetTPCSignalsQmax(signalMax);
3056 esd->SetTPCdEdxInfo(infoTpcPid);
3058 // add seed to the esd track in Calib level
3060 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3061 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3062 // RS: this is the only place where the seed is created not in the pool,
3063 // since it should belong to ESDevent
3064 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3065 esd->AddCalibObject(seedCopy);
3070 //printf("problem\n");
3073 //FindKinks(fSeeds,event);
3074 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(2,fSeeds);
3075 Info("RefitInward","Number of refitted tracks %d",ntracks);
3077 AliCosmicTracker::FindCosmic(event, kTRUE);
3083 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3086 // back propagation of ESD tracks
3088 if (!event) return 0;
3093 PropagateBack(fSeeds);
3094 RemoveUsed2(fSeeds,0.4,0.4,20);
3095 //FindCurling(fSeeds, fEvent,1);
3096 FindSplitted(fSeeds, event,1); // find multi found tracks
3097 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3100 Int_t nseed = fSeeds->GetEntriesFast();
3102 for (Int_t i=0;i<nseed;i++){
3103 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3104 if (!seed) continue;
3105 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3106 seed->UpdatePoints();
3107 AddCovariance(seed);
3108 AliESDtrack *esd=event->GetTrack(i);
3109 if (!esd) continue; //never happen
3110 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3111 AliExternalTrackParam paramIn;
3112 AliExternalTrackParam paramOut;
3113 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3114 if (AliTPCReconstructor::StreamLevel()>2) {
3115 (*fDebugStreamer)<<"RecoverBack"<<
3119 "pout.="<<¶mOut<<
3124 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3125 seed->SetNumberOfClusters(ncl);
3128 seed->CookdEdx(0.02,0.6);
3129 CookLabel(seed,0.1); //For comparison only
3130 if (seed->GetNumberOfClusters()>15){
3131 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3132 esd->SetTPCPoints(seed->GetPoints());
3133 esd->SetTPCPointsF(seed->GetNFoundable());
3134 Int_t ndedx = seed->GetNCDEDX(0);
3135 Float_t sdedx = seed->GetSDEDX(0);
3136 Float_t dedx = seed->GetdEdx();
3137 esd->SetTPCsignal(dedx, sdedx, ndedx);
3139 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3140 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3141 if (AliTPCReconstructor::StreamLevel()>1 && esd) {
3142 (*fDebugStreamer)<<"Cback"<<
3145 "EventNrInFile="<<eventnumber<<
3150 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(1,fSeeds);
3151 //FindKinks(fSeeds,event);
3152 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3160 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3163 // Post process events
3165 if (!event) return 0;
3168 // Set TPC event status
3171 // event affected by HV dip
3173 if(IsTPCHVDipEvent(event)) {
3174 event->ResetDetectorStatus(AliDAQ::kTPC);
3177 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3183 void AliTPCtracker::DeleteSeeds()
3192 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3195 //read seeds from the event
3197 Int_t nentr=event->GetNumberOfTracks();
3199 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3204 fSeeds = new TObjArray(nentr);
3208 for (Int_t i=0; i<nentr; i++) {
3209 AliESDtrack *esd=event->GetTrack(i);
3210 ULong_t status=esd->GetStatus();
3211 if (!(status&AliESDtrack::kTPCin)) continue;
3212 AliTPCtrack t(*esd);
3213 t.SetNumberOfClusters(0);
3214 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3215 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3216 seed->SetPoolID(fLastSeedID);
3217 seed->SetUniqueID(esd->GetID());
3218 AddCovariance(seed); //add systematic ucertainty
3219 for (Int_t ikink=0;ikink<3;ikink++) {
3220 Int_t index = esd->GetKinkIndex(ikink);
3221 seed->GetKinkIndexes()[ikink] = index;
3222 if (index==0) continue;
3223 index = TMath::Abs(index);
3224 AliESDkink * kink = fEvent->GetKink(index-1);
3225 if (kink&&esd->GetKinkIndex(ikink)<0){
3226 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3227 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3229 if (kink&&esd->GetKinkIndex(ikink)>0){
3230 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3231 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3235 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3236 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3237 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3238 // fSeeds->AddAt(0,i);
3239 // MarkSeedFree( seed );
3242 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) > 0 ) {
3243 Double_t par0[5],par1[5],alpha,x;
3244 esd->GetInnerExternalParameters(alpha,x,par0);
3245 esd->GetExternalParameters(x,par1);
3246 Double_t delta1 = TMath::Abs(par0[4]-par1[4])/(0.000000001+TMath::Abs(par0[4]+par1[4]));
3247 Double_t delta2 = TMath::Abs(par0[3]-par1[3]);
3249 if (esd->GetTRDncls()>0) trdchi2 = esd->GetTRDchi2()/esd->GetTRDncls();
3250 //reset covariance if suspicious
3251 if ( (delta1>0.1) || (delta2>0.006) ||trdchi2>7.)
3252 seed->ResetCovariance(10.);
3257 // rotate to the local coordinate system
3259 fSectors=fInnerSec; fN=fkNIS;
3260 Double_t alpha=seed->GetAlpha();
3261 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3262 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3263 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3264 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3265 alpha-=seed->GetAlpha();
3266 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3267 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3268 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3269 AliWarning(Form("Rotating track over %f",alpha));
3270 if (!seed->Rotate(alpha)) {
3271 MarkSeedFree( seed );
3277 if (esd->GetKinkIndex(0)<=0){
3278 for (Int_t irow=0;irow<160;irow++){
3279 Int_t index = seed->GetClusterIndex2(irow);
3282 AliTPCclusterMI * cl = GetClusterMI(index);
3283 seed->SetClusterPointer(irow,cl);
3285 if ((index & 0x8000)==0){
3286 cl->Use(10); // accepted cluster
3288 cl->Use(6); // close cluster not accepted
3291 Info("ReadSeeds","Not found cluster");
3296 fSeeds->AddAt(seed,i);
3302 //_____________________________________________________________________________
3303 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3304 Float_t deltay, Int_t ddsec) {
3305 //-----------------------------------------------------------------
3306 // This function creates track seeds.
3307 // SEEDING WITH VERTEX CONSTRAIN
3308 //-----------------------------------------------------------------
3309 // cuts[0] - fP4 cut
3310 // cuts[1] - tan(phi) cut
3311 // cuts[2] - zvertex cut
3312 // cuts[3] - fP3 cut
3320 Double_t x[5], c[15];
3321 // Int_t di = i1-i2;
3323 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3324 seed->SetPoolID(fLastSeedID);
3325 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3326 Double_t cs=cos(alpha), sn=sin(alpha);
3328 // Double_t x1 =fOuterSec->GetX(i1);
3329 //Double_t xx2=fOuterSec->GetX(i2);
3331 Double_t x1 =GetXrow(i1);
3332 Double_t xx2=GetXrow(i2);
3334 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3336 Int_t imiddle = (i2+i1)/2; //middle pad row index
3337 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3338 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3342 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3343 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3344 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3347 // change cut on curvature if it can't reach this layer
3348 // maximal curvature set to reach it
3349 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3350 if (dvertexmax*0.5*cuts[0]>0.85){
3351 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3353 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3356 if (deltay>0) ddsec = 0;
3357 // loop over clusters
3358 for (Int_t is=0; is < kr1; is++) {
3360 if (kr1[is]->IsUsed(10)) continue;
3361 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3362 //if (TMath::Abs(y1)>ymax) continue;
3364 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3366 // find possible directions
3367 Float_t anglez = (z1-z3)/(x1-x3);
3368 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3371 //find rotation angles relative to line given by vertex and point 1
3372 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3373 Double_t dvertex = TMath::Sqrt(dvertex2);
3374 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3375 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3378 // loop over 2 sectors
3384 Double_t dddz1=0; // direction of delta inclination in z axis
3391 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3392 Int_t sec2 = sec + dsec;
3394 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3395 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3396 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3397 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3398 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3399 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3401 // rotation angles to p1-p3
3402 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3403 Double_t x2, y2, z2;
3405 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3408 Double_t dxx0 = (xx2-x3)*cs13r;
3409 Double_t dyy0 = (xx2-x3)*sn13r;
3410 for (Int_t js=index1; js < index2; js++) {
3411 const AliTPCclusterMI *kcl = kr2[js];
3412 if (kcl->IsUsed(10)) continue;
3414 //calcutate parameters
3416 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3418 if (TMath::Abs(yy0)<0.000001) continue;
3419 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3420 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3421 Double_t r02 = (0.25+y0*y0)*dvertex2;
3422 //curvature (radius) cut
3423 if (r02<r2min) continue;
3427 Double_t c0 = 1/TMath::Sqrt(r02);
3431 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3432 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3433 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3434 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3437 Double_t z0 = kcl->GetZ();
3438 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3439 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3442 Double_t dip = (z1-z0)*c0/dfi1;
3443 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3454 x2= xx2*cs-y2*sn*dsec;
3455 y2=+xx2*sn*dsec+y2*cs;
3465 // do we have cluster at the middle ?
3467 GetProlongation(x1,xm,x,ym,zm);
3469 AliTPCclusterMI * cm=0;
3470 if (TMath::Abs(ym)-ymaxm<0){
3471 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3472 if ((!cm) || (cm->IsUsed(10))) {
3477 // rotate y1 to system 0
3478 // get state vector in rotated system
3479 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3480 Double_t xr2 = x0*cs+yr1*sn*dsec;
3481 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3483 GetProlongation(xx2,xm,xr,ym,zm);
3484 if (TMath::Abs(ym)-ymaxm<0){
3485 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3486 if ((!cm) || (cm->IsUsed(10))) {
3493 // Double_t dym = 0;
3494 // Double_t dzm = 0;
3496 // dym = ym - cm->GetY();
3497 // dzm = zm - cm->GetZ();
3504 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3505 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
3506 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3507 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3508 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3510 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3511 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3512 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3513 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3514 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3515 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3517 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3518 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3519 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3520 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3524 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3525 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3526 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3527 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3528 c[13]=f30*sy1*f40+f32*sy2*f42;
3529 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3531 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3533 UInt_t index=kr1.GetIndex(is);
3534 if (seed) {MarkSeedFree(seed); seed = 0;}
3535 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3536 seed->SetPoolID(fLastSeedID);
3537 track->SetIsSeeding(kTRUE);
3538 track->SetSeed1(i1);
3539 track->SetSeed2(i2);
3540 track->SetSeedType(3);
3544 FollowProlongation(*track, (i1+i2)/2,1);
3545 Int_t foundable,found,shared;
3546 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3547 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3548 MarkSeedFree(seed); seed = 0;
3554 FollowProlongation(*track, i2,1);
3558 track->SetBConstrain(1);
3559 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
3560 track->SetLastPoint(i1); // first cluster in track position
3561 track->SetFirstPoint(track->GetLastPoint());
3563 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3564 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3565 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3566 MarkSeedFree(seed); seed = 0;
3570 // Z VERTEX CONDITION
3571 Double_t zv, bz=GetBz();
3572 if ( !track->GetZAt(0.,bz,zv) ) continue;
3573 if (TMath::Abs(zv-z3)>cuts[2]) {
3574 FollowProlongation(*track, TMath::Max(i2-20,0));
3575 if ( !track->GetZAt(0.,bz,zv) ) continue;
3576 if (TMath::Abs(zv-z3)>cuts[2]){
3577 FollowProlongation(*track, TMath::Max(i2-40,0));
3578 if ( !track->GetZAt(0.,bz,zv) ) continue;
3579 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3580 // make seed without constrain
3581 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3582 FollowProlongation(*track2, i2,1);
3583 track2->SetBConstrain(kFALSE);
3584 track2->SetSeedType(1);
3585 arr->AddLast(track2);
3586 MarkSeedFree( seed ); seed = 0;
3590 MarkSeedFree( seed ); seed = 0;
3597 track->SetSeedType(0);
3598 arr->AddLast(track); // note, track is seed, don't free the seed
3599 seed = new( NextFreeSeed() ) AliTPCseed;
3600 seed->SetPoolID(fLastSeedID);
3602 // don't consider other combinations
3603 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3609 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3611 if (seed) MarkSeedFree( seed );
3615 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3620 //-----------------------------------------------------------------
3621 // This function creates track seeds.
3622 //-----------------------------------------------------------------
3623 // cuts[0] - fP4 cut
3624 // cuts[1] - tan(phi) cut
3625 // cuts[2] - zvertex cut
3626 // cuts[3] - fP3 cut
3636 Double_t x[5], c[15];
3638 // make temporary seed
3639 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3640 seed->SetPoolID(fLastSeedID);
3641 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3642 // Double_t cs=cos(alpha), sn=sin(alpha);
3647 Double_t x1 = GetXrow(i1-1);
3648 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3649 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
3651 Double_t x1p = GetXrow(i1);
3652 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3654 Double_t x1m = GetXrow(i1-2);
3655 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3658 //last 3 padrow for seeding
3659 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
3660 Double_t x3 = GetXrow(i1-7);
3661 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
3663 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
3664 Double_t x3p = GetXrow(i1-6);
3666 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
3667 Double_t x3m = GetXrow(i1-8);
3672 Int_t im = i1-4; //middle pad row index
3673 Double_t xm = GetXrow(im); // radius of middle pad-row
3674 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
3675 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
3678 Double_t deltax = x1-x3;
3679 Double_t dymax = deltax*cuts[1];
3680 Double_t dzmax = deltax*cuts[3];
3682 // loop over clusters
3683 for (Int_t is=0; is < kr1; is++) {
3685 if (kr1[is]->IsUsed(10)) continue;
3686 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3688 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3690 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3691 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3697 for (Int_t js=index1; js < index2; js++) {
3698 const AliTPCclusterMI *kcl = kr3[js];
3699 if (kcl->IsUsed(10)) continue;
3701 // apply angular cuts
3702 if (TMath::Abs(y1-y3)>dymax) continue;
3705 if (TMath::Abs(z1-z3)>dzmax) continue;
3707 Double_t angley = (y1-y3)/(x1-x3);
3708 Double_t anglez = (z1-z3)/(x1-x3);
3710 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3711 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3713 Double_t yyym = angley*(xm-x1)+y1;
3714 Double_t zzzm = anglez*(xm-x1)+z1;
3716 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3718 if (kcm->IsUsed(10)) continue;
3720 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3721 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3728 // look around first
3729 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3735 if (kc1m->IsUsed(10)) used++;
3737 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3743 if (kc1p->IsUsed(10)) used++;
3745 if (used>1) continue;
3746 if (found<1) continue;
3750 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3756 if (kc3m->IsUsed(10)) used++;
3760 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3766 if (kc3p->IsUsed(10)) used++;
3770 if (used>1) continue;
3771 if (found<3) continue;
3781 x[4]=F1(x1,y1,x2,y2,x3,y3);
3782 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3785 x[2]=F2(x1,y1,x2,y2,x3,y3);
3788 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3789 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3793 Double_t sy1=0.1, sz1=0.1;
3794 Double_t sy2=0.1, sz2=0.1;
3795 Double_t sy3=0.1, sy=0.1, sz=0.1;
3797 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3798 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3799 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3800 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3801 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3802 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3804 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3805 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3806 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3807 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3811 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3812 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3813 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3814 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3815 c[13]=f30*sy1*f40+f32*sy2*f42;
3816 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3818 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3820 index=kr1.GetIndex(is);
3821 if (seed) {MarkSeedFree( seed ); seed = 0;}
3822 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3823 seed->SetPoolID(fLastSeedID);
3825 track->SetIsSeeding(kTRUE);
3828 FollowProlongation(*track, i1-7,1);
3829 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
3830 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3831 MarkSeedFree( seed ); seed = 0;
3837 FollowProlongation(*track, i2,1);
3838 track->SetBConstrain(0);
3839 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
3840 track->SetFirstPoint(track->GetLastPoint());
3842 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3843 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
3844 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3845 MarkSeedFree( seed ); seed = 0;
3850 FollowProlongation(*track, TMath::Max(i2-10,0),1);
3851 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3852 FollowProlongation(*track2, i2,1);
3853 track2->SetBConstrain(kFALSE);
3854 track2->SetSeedType(4);
3855 arr->AddLast(track2);
3856 MarkSeedFree( seed ); seed = 0;
3860 //arr->AddLast(track);
3861 //seed = new AliTPCseed;
3867 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);
3869 if (seed) MarkSeedFree(seed);
3873 //_____________________________________________________________________________
3874 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3875 Float_t deltay, Bool_t /*bconstrain*/) {
3876 //-----------------------------------------------------------------
3877 // This function creates track seeds - without vertex constraint
3878 //-----------------------------------------------------------------
3879 // cuts[0] - fP4 cut - not applied
3880 // cuts[1] - tan(phi) cut
3881 // cuts[2] - zvertex cut - not applied
3882 // cuts[3] - fP3 cut
3892 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3893 // Double_t cs=cos(alpha), sn=sin(alpha);
3894 Int_t row0 = (i1+i2)/2;
3895 Int_t drow = (i1-i2)/2;
3896 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3897 AliTPCtrackerRow * kr=0;
3899 AliTPCpolyTrack polytrack;
3900 Int_t nclusters=fSectors[sec][row0];
3901 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3902 seed->SetPoolID(fLastSeedID);
3907 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
3909 Int_t nfoundable =0;
3910 for (Int_t iter =1; iter<2; iter++){ //iterations
3911 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3912 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
3913 const AliTPCclusterMI * cl= kr0[is];
3915 if (cl->IsUsed(10)) {
3921 Double_t x = kr0.GetX();
3922 // Initialization of the polytrack
3927 Double_t y0= cl->GetY();
3928 Double_t z0= cl->GetZ();
3932 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3933 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
3935 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
3936 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
3937 polytrack.AddPoint(x,y0,z0,erry, errz);
3940 if (cl->IsUsed(10)) sumused++;
3943 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3944 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3947 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3948 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3949 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
3950 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3951 if (cl1->IsUsed(10)) sumused++;
3952 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3956 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3958 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
3959 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3960 if (cl2->IsUsed(10)) sumused++;
3961 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3964 if (sumused>0) continue;
3966 polytrack.UpdateParameters();
3972 nfoundable = polytrack.GetN();
3973 nfound = nfoundable;
3975 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3976 Float_t maxdist = 0.8*(1.+3./(ddrow));
3977 for (Int_t delta = -1;delta<=1;delta+=2){
3978 Int_t row = row0+ddrow*delta;
3979 kr = &(fSectors[sec][row]);
3980 Double_t xn = kr->GetX();
3981 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3982 polytrack.GetFitPoint(xn,yn,zn);
3983 if (TMath::Abs(yn)>ymax1) continue;
3985 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3987 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3990 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3991 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3992 if (cln->IsUsed(10)) {
3993 // printf("used\n");
4001 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4006 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4007 polytrack.UpdateParameters();
4010 if ( (sumused>3) || (sumused>0.5*nfound)) {
4011 //printf("sumused %d\n",sumused);
4016 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4017 AliTPCpolyTrack track2;
4019 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4020 if (track2.GetN()<0.5*nfoundable) continue;
4023 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4025 // test seed with and without constrain
4026 for (Int_t constrain=0; constrain<=0;constrain++){
4027 // add polytrack candidate
4029 Double_t x[5], c[15];
4030 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4031 track2.GetBoundaries(x3,x1);
4033 track2.GetFitPoint(x1,y1,z1);
4034 track2.GetFitPoint(x2,y2,z2);
4035 track2.GetFitPoint(x3,y3,z3);
4037 //is track pointing to the vertex ?
4040 polytrack.GetFitPoint(x0,y0,z0);
4053 x[4]=F1(x1,y1,x2,y2,x3,y3);
4055 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4056 x[2]=F2(x1,y1,x2,y2,x3,y3);
4058 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4059 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4060 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4061 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4064 Double_t sy =0.1, sz =0.1;
4065 Double_t sy1=0.02, sz1=0.02;
4066 Double_t sy2=0.02, sz2=0.02;
4070 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4073 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4074 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4075 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4076 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4077 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4078 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4080 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4081 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4082 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4083 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4088 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4089 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4090 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4091 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4092 c[13]=f30*sy1*f40+f32*sy2*f42;
4093 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4095 //Int_t row1 = fSectors->GetRowNumber(x1);
4096 Int_t row1 = GetRowNumber(x1);
4100 if (seed) {MarkSeedFree( seed ); seed = 0;}
4101 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4102 seed->SetPoolID(fLastSeedID);
4103 track->SetIsSeeding(kTRUE);
4104 Int_t rc=FollowProlongation(*track, i2);
4105 if (constrain) track->SetBConstrain(1);
4107 track->SetBConstrain(0);
4108 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4109 track->SetFirstPoint(track->GetLastPoint());
4111 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4112 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4113 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4114 MarkSeedFree( seed ); seed = 0;
4117 arr->AddLast(track); // track IS seed, don't free seed
4118 seed = new( NextFreeSeed() ) AliTPCseed;
4119 seed->SetPoolID(fLastSeedID);
4123 } // if accepted seed
4126 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4128 if (seed) MarkSeedFree( seed );
4132 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4136 //reseed using track points
4137 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4138 Int_t p1 = int(r1*track->GetNumberOfClusters());
4139 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4141 Double_t x0[3],x1[3],x2[3];
4142 for (Int_t i=0;i<3;i++){
4148 // find track position at given ratio of the length
4149 Int_t sec0=0, sec1=0, sec2=0;
4152 for (Int_t i=0;i<160;i++){
4153 if (track->GetClusterPointer(i)){
4155 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4156 if ( (index<p0) || x0[0]<0 ){
4157 if (trpoint->GetX()>1){
4158 clindex = track->GetClusterIndex2(i);
4160 x0[0] = trpoint->GetX();
4161 x0[1] = trpoint->GetY();
4162 x0[2] = trpoint->GetZ();
4163 sec0 = ((clindex&0xff000000)>>24)%18;
4168 if ( (index<p1) &&(trpoint->GetX()>1)){
4169 clindex = track->GetClusterIndex2(i);
4171 x1[0] = trpoint->GetX();
4172 x1[1] = trpoint->GetY();
4173 x1[2] = trpoint->GetZ();
4174 sec1 = ((clindex&0xff000000)>>24)%18;
4177 if ( (index<p2) &&(trpoint->GetX()>1)){
4178 clindex = track->GetClusterIndex2(i);
4180 x2[0] = trpoint->GetX();
4181 x2[1] = trpoint->GetY();
4182 x2[2] = trpoint->GetZ();
4183 sec2 = ((clindex&0xff000000)>>24)%18;
4190 Double_t alpha, cs,sn, xx2,yy2;
4192 alpha = (sec1-sec2)*fSectors->GetAlpha();
4193 cs = TMath::Cos(alpha);
4194 sn = TMath::Sin(alpha);
4195 xx2= x1[0]*cs-x1[1]*sn;
4196 yy2= x1[0]*sn+x1[1]*cs;
4200 alpha = (sec0-sec2)*fSectors->GetAlpha();
4201 cs = TMath::Cos(alpha);
4202 sn = TMath::Sin(alpha);
4203 xx2= x0[0]*cs-x0[1]*sn;
4204 yy2= x0[0]*sn+x0[1]*cs;
4210 Double_t x[5],c[15];
4214 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4215 // if (x[4]>1) return 0;
4216 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4217 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4218 //if (TMath::Abs(x[3]) > 2.2) return 0;
4219 //if (TMath::Abs(x[2]) > 1.99) return 0;
4221 Double_t sy =0.1, sz =0.1;
4223 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4224 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4225 Double_t sy3=0.01+track->GetSigmaY2();
4227 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4228 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4229 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4230 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4231 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4232 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4234 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4235 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4236 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4237 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4242 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4243 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4244 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4245 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4246 c[13]=f30*sy1*f40+f32*sy2*f42;
4247 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4249 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4250 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4251 seed->SetPoolID(fLastSeedID);
4252 // Double_t y0,z0,y1,z1, y2,z2;
4253 //seed->GetProlongation(x0[0],y0,z0);
4254 // seed->GetProlongation(x1[0],y1,z1);
4255 //seed->GetProlongation(x2[0],y2,z2);
4257 seed->SetLastPoint(pp2);
4258 seed->SetFirstPoint(pp2);
4265 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4269 //reseed using founded clusters
4271 // Find the number of clusters
4272 Int_t nclusters = 0;
4273 for (Int_t irow=0;irow<160;irow++){
4274 if (track->GetClusterIndex(irow)>0) nclusters++;
4278 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4279 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4280 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4283 Double_t xyz[3][3]={{0}};
4284 Int_t row[3]={0},sec[3]={0,0,0};
4286 // find track row position at given ratio of the length
4288 for (Int_t irow=0;irow<160;irow++){
4289 if (track->GetClusterIndex2(irow)<0) continue;
4291 for (Int_t ipoint=0;ipoint<3;ipoint++){
4292 if (index<=ipos[ipoint]) row[ipoint] = irow;
4296 //Get cluster and sector position
4297 for (Int_t ipoint=0;ipoint<3;ipoint++){
4298 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4299 AliTPCclusterMI * cl = GetClusterMI(clindex);
4302 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4305 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4306 xyz[ipoint][0] = GetXrow(row[ipoint]);
4307 xyz[ipoint][1] = cl->GetY();
4308 xyz[ipoint][2] = cl->GetZ();
4312 // Calculate seed state vector and covariance matrix
4314 Double_t alpha, cs,sn, xx2,yy2;
4316 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4317 cs = TMath::Cos(alpha);
4318 sn = TMath::Sin(alpha);
4319 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4320 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4324 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4325 cs = TMath::Cos(alpha);
4326 sn = TMath::Sin(alpha);
4327 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4328 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4334 Double_t x[5],c[15];
4338 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4339 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4340 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4342 Double_t sy =0.1, sz =0.1;
4344 Double_t sy1=0.2, sz1=0.2;
4345 Double_t sy2=0.2, sz2=0.2;
4348 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;
4349 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;
4350 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;
4351 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;
4352 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;
4353 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;
4355 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;
4356 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;
4357 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;
4358 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;
4363 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4364 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4365 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4366 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4367 c[13]=f30*sy1*f40+f32*sy2*f42;
4368 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4370 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4371 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4372 seed->SetPoolID(fLastSeedID);
4373 seed->SetLastPoint(row[2]);
4374 seed->SetFirstPoint(row[2]);
4379 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4383 //reseed using founded clusters
4386 Int_t row[3]={0,0,0};
4387 Int_t sec[3]={0,0,0};
4389 // forward direction
4391 for (Int_t irow=r0;irow<160;irow++){
4392 if (track->GetClusterIndex(irow)>0){
4397 for (Int_t irow=160;irow>r0;irow--){
4398 if (track->GetClusterIndex(irow)>0){
4403 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4404 if (track->GetClusterIndex(irow)>0){
4412 for (Int_t irow=0;irow<r0;irow++){
4413 if (track->GetClusterIndex(irow)>0){
4418 for (Int_t irow=r0;irow>0;irow--){
4419 if (track->GetClusterIndex(irow)>0){
4424 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4425 if (track->GetClusterIndex(irow)>0){
4432 if ((row[2]-row[0])<20) return 0;
4433 if (row[1]==0) return 0;
4436 //Get cluster and sector position
4437 for (Int_t ipoint=0;ipoint<3;ipoint++){
4438 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4439 AliTPCclusterMI * cl = GetClusterMI(clindex);
4442 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4445 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4446 xyz[ipoint][0] = GetXrow(row[ipoint]);
4447 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4448 if (point&&ipoint<2){
4450 xyz[ipoint][1] = point->GetY();
4451 xyz[ipoint][2] = point->GetZ();
4454 xyz[ipoint][1] = cl->GetY();
4455 xyz[ipoint][2] = cl->GetZ();
4462 // Calculate seed state vector and covariance matrix
4464 Double_t alpha, cs,sn, xx2,yy2;
4466 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4467 cs = TMath::Cos(alpha);
4468 sn = TMath::Sin(alpha);
4469 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4470 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4474 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4475 cs = TMath::Cos(alpha);
4476 sn = TMath::Sin(alpha);
4477 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4478 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4484 Double_t x[5],c[15];
4488 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4489 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4490 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4492 Double_t sy =0.1, sz =0.1;
4494 Double_t sy1=0.2, sz1=0.2;
4495 Double_t sy2=0.2, sz2=0.2;
4498 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;
4499 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;
4500 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;
4501 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;
4502 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;
4503 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;
4505 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;
4506 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;
4507 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;
4508 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;
4513 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4514 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4515 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4516 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4517 c[13]=f30*sy1*f40+f32*sy2*f42;
4518 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4520 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4521 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4522 seed->SetPoolID(fLastSeedID);
4523 seed->SetLastPoint(row[2]);
4524 seed->SetFirstPoint(row[2]);
4525 for (Int_t i=row[0];i<row[2];i++){
4526 seed->SetClusterIndex(i, track->GetClusterIndex(i));
4534 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4537 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4539 // Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4541 // Two reasons to have multiple find tracks
4542 // 1. Curling tracks can be find more than once
4543 // 2. Splitted tracks
4544 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
4545 // b.) Edge effect on the sector boundaries
4548 // Algorithm done in 2 phases - because of CPU consumption
4549 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4551 // Algorihm for curling tracks sign:
4552 // 1 phase -makes a very rough fast cuts to minimize combinatorics
4553 // a.) opposite sign
4554 // b.) one of the tracks - not pointing to the primary vertex -
4555 // c.) delta tan(theta)
4557 // 2 phase - calculates DCA between tracks - time consument
4562 // General cuts - for splitted tracks and for curling tracks
4564 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
4566 // Curling tracks cuts
4571 Int_t nentries = array->GetEntriesFast();
4572 AliHelix *helixes = new AliHelix[nentries];
4573 Float_t *xm = new Float_t[nentries];
4574 Float_t *dz0 = new Float_t[nentries];
4575 Float_t *dz1 = new Float_t[nentries];
4581 // Find track COG in x direction - point with best defined parameters
4583 for (Int_t i=0;i<nentries;i++){
4584 AliTPCseed* track = (AliTPCseed*)array->At(i);
4585 if (!track) continue;
4586 track->SetCircular(0);
4587 new (&helixes[i]) AliHelix(*track);
4591 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4594 for (Int_t icl=0; icl<160; icl++){
4595 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
4601 if (ncl>0) xm[i]/=Float_t(ncl);
4604 for (Int_t i0=0;i0<nentries;i0++){
4605 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4606 if (!track0) continue;
4607 Float_t xc0 = helixes[i0].GetHelix(6);
4608 Float_t yc0 = helixes[i0].GetHelix(7);
4609 Float_t r0 = helixes[i0].GetHelix(8);
4610 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4611 Float_t fi0 = TMath::ATan2(yc0,xc0);
4613 for (Int_t i1=i0+1;i1<nentries;i1++){
4614 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4615 if (!track1) continue;
4616 Int_t lab0=track0->GetLabel();
4617 Int_t lab1=track1->GetLabel();
4618 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4620 Float_t xc1 = helixes[i1].GetHelix(6);
4621 Float_t yc1 = helixes[i1].GetHelix(7);
4622 Float_t r1 = helixes[i1].GetHelix(8);
4623 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4624 Float_t fi1 = TMath::ATan2(yc1,xc1);
4626 Float_t dfi = fi0-fi1;
4629 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4630 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4631 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4633 // if short tracks with undefined sign
4634 fi1 = -TMath::ATan2(yc1,-xc1);
4637 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4640 // debug stream to tune "fast cuts"
4642 Double_t dist[3]; // distance at X
4643 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
4644 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4645 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4646 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4647 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4648 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4649 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4650 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4654 for (Int_t icl=0; icl<160; icl++){
4655 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
4656 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
4659 if (cl0==cl1) sums++;
4663 if (AliTPCReconstructor::StreamLevel()>5) {
4664 TTreeSRedirector &cstream = *fDebugStreamer;
4669 "Tr0.="<<track0<< // seed0
4670 "Tr1.="<<track1<< // seed1
4671 "h0.="<<&helixes[i0]<<
4672 "h1.="<<&helixes[i1]<<
4674 "sum="<<sum<< //the sum of rows with cl in both
4675 "sums="<<sums<< //the sum of shared clusters
4676 "xm0="<<xm[i0]<< // the center of track
4677 "xm1="<<xm[i1]<< // the x center of track
4678 // General cut variables
4679 "dfi="<<dfi<< // distance in fi angle
4680 "dtheta="<<dtheta<< // distance int theta angle
4686 "dist0="<<dist[0]<< //distance x
4687 "dist1="<<dist[1]<< //distance y
4688 "dist2="<<dist[2]<< //distance z
4689 "mdist0="<<mdist[0]<< //distance x
4690 "mdist1="<<mdist[1]<< //distance y
4691 "mdist2="<<mdist[2]<< //distance z
4707 if (AliTPCReconstructor::StreamLevel()>1) {
4708 AliInfo("Time for curling tracks removal DEBUGGING MC");
4715 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
4717 // Find Splitted tracks and remove the one with worst quality
4718 // Corresponding debug streamer to tune selections - "Splitted2"
4720 // 0. Sort tracks according quility
4721 // 1. Propagate the tracks to the reference radius
4722 // 2. Double_t loop to select close tracks (only to speed up process)
4723 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
4724 // 4. Delete temporary parameters
4726 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
4728 const Double_t kCutP1=10; // delta Z cut 10 cm
4729 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
4730 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
4731 const Double_t kCutAlpha=0.15; // delta alpha cut
4732 Int_t firstpoint = 0;
4733 Int_t lastpoint = 160;
4735 Int_t nentries = array->GetEntriesFast();
4736 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
4742 //0. Sort tracks according quality
4743 //1. Propagate the ext. param to reference radius
4744 Int_t nseed = array->GetEntriesFast();
4745 if (nseed<=0) return;
4746 Float_t * quality = new Float_t[nseed];
4747 Int_t * indexes = new Int_t[nseed];
4748 for (Int_t i=0; i<nseed; i++) {
4749 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
4754 pt->UpdatePoints(); //select first last max dens points
4755 Float_t * points = pt->GetPoints();
4756 if (points[3]<0.8) quality[i] =-1;
4757 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4758 //prefer high momenta tracks if overlaps
4759 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
4761 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
4762 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
4764 TMath::Sort(nseed,quality,indexes);
4766 // 3. Loop over pair of tracks
4768 for (Int_t i0=0; i0<nseed; i0++) {
4769 Int_t index0=indexes[i0];
4770 if (!(array->UncheckedAt(index0))) continue;
4771 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
4772 if (!s1->IsActive()) continue;
4773 AliExternalTrackParam &par0=params[index0];
4774 for (Int_t i1=i0+1; i1<nseed; i1++) {
4775 Int_t index1=indexes[i1];
4776 if (!(array->UncheckedAt(index1))) continue;
4777 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
4778 if (!s2->IsActive()) continue;
4779 if (s2->GetKinkIndexes()[0]!=0)
4780 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
4781 AliExternalTrackParam &par1=params[index1];
4782 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
4783 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
4784 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
4785 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
4786 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
4787 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
4792 Int_t firstShared=lastpoint, lastShared=firstpoint;
4793 Int_t firstRow=lastpoint, lastRow=firstpoint;
4795 for (Int_t i=firstpoint;i<lastpoint;i++){
4796 if (s1->GetClusterIndex2(i)>0) nall0++;
4797 if (s2->GetClusterIndex2(i)>0) nall1++;
4798 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
4799 if (i<firstRow) firstRow=i;
4800 if (i>lastRow) lastRow=i;
4802 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
4803 if (i<firstShared) firstShared=i;
4804 if (i>lastShared) lastShared=i;
4808 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
4809 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
4811 if( AliTPCReconstructor::StreamLevel()>1){
4812 TTreeSRedirector &cstream = *fDebugStreamer;
4813 Int_t n0=s1->GetNumberOfClusters();
4814 Int_t n1=s2->GetNumberOfClusters();
4815 Int_t n0F=s1->GetNFoundable();
4816 Int_t n1F=s2->GetNFoundable();
4817 Int_t lab0=s1->GetLabel();
4818 Int_t lab1=s2->GetLabel();
4820 cstream<<"Splitted2"<<
4821 "iter="<<fIteration<<
4822 "lab0="<<lab0<< // MC label if exist
4823 "lab1="<<lab1<< // MC label if exist
4826 "ratio0="<<ratio0<< // shared ratio
4827 "ratio1="<<ratio1<< // shared ratio
4828 "p0.="<<&par0<< // track parameters
4830 "s0.="<<s1<< // full seed
4832 "n0="<<n0<< // number of clusters track 0
4833 "n1="<<n1<< // number of clusters track 1
4834 "nall0="<<nall0<< // number of clusters track 0
4835 "nall1="<<nall1<< // number of clusters track 1
4836 "n0F="<<n0F<< // number of findable
4837 "n1F="<<n1F<< // number of findable
4838 "shared="<<sumShared<< // number of shared clusters
4839 "firstS="<<firstShared<< // first and the last shared row
4840 "lastS="<<lastShared<<
4841 "firstRow="<<firstRow<< // first and the last row with cluster
4842 "lastRow="<<lastRow<< //
4846 // remove track with lower quality
4848 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
4849 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
4853 MarkSeedFree( array->RemoveAt(index1) );
4858 // 4. Delete temporary array
4868 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4871 // find Curling tracks
4872 // Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4875 // Algorithm done in 2 phases - because of CPU consumption
4876 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4877 // see detal in MC part what can be used to cut
4881 const Float_t kMaxC = 400; // maximal curvature to of the track
4882 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
4883 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
4884 const Float_t kPtRatio = 0.3; // ratio between pt
4885 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
4888 // Curling tracks cuts
4891 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
4892 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
4893 const Float_t kMinAngle = 2.9; // angle between tracks
4894 const Float_t kMaxDist = 5; // biggest distance
4896 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4899 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4900 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4901 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4902 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4903 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
4905 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4906 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4908 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
4909 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4911 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4917 Int_t nentries = array->GetEntriesFast();
4918 AliHelix *helixes = new AliHelix[nentries];
4919 for (Int_t i=0;i<nentries;i++){
4920 AliTPCseed* track = (AliTPCseed*)array->At(i);
4921 if (!track) continue;
4922 track->SetCircular(0);
4923 new (&helixes[i]) AliHelix(*track);
4929 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4935 for (Int_t i0=0;i0<nentries;i0++){
4936 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4937 if (!track0) continue;
4938 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4939 Float_t xc0 = helixes[i0].GetHelix(6);
4940 Float_t yc0 = helixes[i0].GetHelix(7);
4941 Float_t r0 = helixes[i0].GetHelix(8);
4942 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4943 Float_t fi0 = TMath::ATan2(yc0,xc0);
4945 for (Int_t i1=i0+1;i1<nentries;i1++){
4946 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4947 if (!track1) continue;
4948 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
4949 Float_t xc1 = helixes[i1].GetHelix(6);
4950 Float_t yc1 = helixes[i1].GetHelix(7);
4951 Float_t r1 = helixes[i1].GetHelix(8);
4952 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4953 Float_t fi1 = TMath::ATan2(yc1,xc1);
4955 Float_t dfi = fi0-fi1;
4958 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4959 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4960 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4964 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
4965 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
4966 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4967 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
4968 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4970 Float_t pt0 = track0->GetSignedPt();
4971 Float_t pt1 = track1->GetSignedPt();
4972 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
4973 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4974 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
4975 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
4978 // Now find closest approach
4982 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4983 if (npoints==0) continue;
4984 helixes[i0].GetClosestPhases(helixes[i1], phase);
4988 Double_t hangles[3];
4989 helixes[i0].Evaluate(phase[0][0],xyz0);
4990 helixes[i1].Evaluate(phase[0][1],xyz1);
4992 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4993 Double_t deltah[2],deltabest;
4994 if (TMath::Abs(hangles[2])<kMinAngle) continue;
4998 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5000 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5001 if (deltah[1]<deltah[0]) ibest=1;
5003 deltabest = TMath::Sqrt(deltah[ibest]);
5004 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5005 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5006 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5007 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5009 if (deltabest>kMaxDist) continue;
5010 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5011 Bool_t sign =kFALSE;
5012 if (hangles[2]>kMinAngle) sign =kTRUE;
5015 // circular[i0] = kTRUE;
5016 // circular[i1] = kTRUE;
5017 if (track0->OneOverPt()<track1->OneOverPt()){
5018 track0->SetCircular(track0->GetCircular()+1);
5019 track1->SetCircular(track1->GetCircular()+2);
5022 track1->SetCircular(track1->GetCircular()+1);
5023 track0->SetCircular(track0->GetCircular()+2);
5026 if (AliTPCReconstructor::StreamLevel()>2){
5028 //debug stream to tune "fine" cuts
5029 Int_t lab0=track0->GetLabel();
5030 Int_t lab1=track1->GetLabel();
5031 TTreeSRedirector &cstream = *fDebugStreamer;
5032 cstream<<"Curling2"<<
5048 "npoints="<<npoints<<
5049 "hangles0="<<hangles[0]<<
5050 "hangles1="<<hangles[1]<<
5051 "hangles2="<<hangles[2]<<
5054 "radius="<<radiusbest<<
5055 "deltabest="<<deltabest<<
5056 "phase0="<<phase[ibest][0]<<
5057 "phase1="<<phase[ibest][1]<<
5065 if (AliTPCReconstructor::StreamLevel()>1) {
5066 AliInfo("Time for curling tracks removal");
5072 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5078 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5081 TObjArray *kinks= new TObjArray(10000);
5082 // TObjArray *v0s= new TObjArray(10000);
5083 Int_t nentries = array->GetEntriesFast();
5084 AliHelix *helixes = new AliHelix[nentries];
5085 Int_t *sign = new Int_t[nentries];
5086 Int_t *nclusters = new Int_t[nentries];
5087 Float_t *alpha = new Float_t[nentries];
5088 AliKink *kink = new AliKink();
5089 Int_t * usage = new Int_t[nentries];
5090 Float_t *zm = new Float_t[nentries];
5091 Float_t *z0 = new Float_t[nentries];
5092 Float_t *fim = new Float_t[nentries];
5093 Float_t *shared = new Float_t[nentries];
5094 Bool_t *circular = new Bool_t[nentries];
5095 Float_t *dca = new Float_t[nentries];
5096 //const AliESDVertex * primvertex = esd->GetVertex();
5098 // nentries = array->GetEntriesFast();
5103 for (Int_t i=0;i<nentries;i++){
5106 AliTPCseed* track = (AliTPCseed*)array->At(i);
5107 if (!track) continue;
5108 track->SetCircular(0);
5110 track->UpdatePoints();
5111 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5113 nclusters[i]=track->GetNumberOfClusters();
5114 alpha[i] = track->GetAlpha();
5115 new (&helixes[i]) AliHelix(*track);
5117 helixes[i].Evaluate(0,xyz);
5118 sign[i] = (track->GetC()>0) ? -1:1;
5121 if (track->GetProlongation(x,y,z)){
5123 fim[i] = alpha[i]+TMath::ATan2(y,x);
5126 zm[i] = track->GetZ();
5130 circular[i]= kFALSE;
5131 if (track->GetProlongation(0,y,z)) z0[i] = z;
5132 dca[i] = track->GetD(0,0);
5138 Int_t ncandidates =0;
5141 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5144 // Find circling track
5146 for (Int_t i0=0;i0<nentries;i0++){
5147 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5148 if (!track0) continue;
5149 if (track0->GetNumberOfClusters()<40) continue;
5150 if (TMath::Abs(1./track0->GetC())>200) continue;
5151 for (Int_t i1=i0+1;i1<nentries;i1++){
5152 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5153 if (!track1) continue;
5154 if (track1->GetNumberOfClusters()<40) continue;
5155 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5156 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5157 if (TMath::Abs(1./track1->GetC())>200) continue;
5158 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5159 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5160 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5161 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5162 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5164 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5165 if (mindcar<5) continue;
5166 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5167 if (mindcaz<5) continue;
5168 if (mindcar+mindcaz<20) continue;
5171 Float_t xc0 = helixes[i0].GetHelix(6);
5172 Float_t yc0 = helixes[i0].GetHelix(7);
5173 Float_t r0 = helixes[i0].GetHelix(8);
5174 Float_t xc1 = helixes[i1].GetHelix(6);
5175 Float_t yc1 = helixes[i1].GetHelix(7);
5176 Float_t r1 = helixes[i1].GetHelix(8);
5178 Float_t rmean = (r0+r1)*0.5;
5179 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5180 //if (delta>30) continue;
5181 if (delta>rmean*0.25) continue;
5182 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5184 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5185 if (npoints==0) continue;
5186 helixes[i0].GetClosestPhases(helixes[i1], phase);
5190 Double_t hangles[3];
5191 helixes[i0].Evaluate(phase[0][0],xyz0);
5192 helixes[i1].Evaluate(phase[0][1],xyz1);
5194 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5195 Double_t deltah[2],deltabest;
5196 if (hangles[2]<2.8) continue;
5199 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5201 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5202 if (deltah[1]<deltah[0]) ibest=1;
5204 deltabest = TMath::Sqrt(deltah[ibest]);
5205 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5206 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5207 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5208 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5210 if (deltabest>6) continue;
5211 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5212 Bool_t lsign =kFALSE;
5213 if (hangles[2]>3.06) lsign =kTRUE;
5216 circular[i0] = kTRUE;
5217 circular[i1] = kTRUE;
5218 if (track0->OneOverPt()<track1->OneOverPt()){
5219 track0->SetCircular(track0->GetCircular()+1);
5220 track1->SetCircular(track1->GetCircular()+2);
5223 track1->SetCircular(track1->GetCircular()+1);
5224 track0->SetCircular(track0->GetCircular()+2);
5227 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5229 Int_t lab0=track0->GetLabel();
5230 Int_t lab1=track1->GetLabel();
5231 TTreeSRedirector &cstream = *fDebugStreamer;
5232 cstream<<"Curling"<<
5239 "mindcar="<<mindcar<<
5240 "mindcaz="<<mindcaz<<
5243 "npoints="<<npoints<<
5244 "hangles0="<<hangles[0]<<
5245 "hangles2="<<hangles[2]<<
5250 "radius="<<radiusbest<<
5251 "deltabest="<<deltabest<<
5252 "phase0="<<phase[ibest][0]<<
5253 "phase1="<<phase[ibest][1]<<
5263 for (Int_t i =0;i<nentries;i++){
5264 if (sign[i]==0) continue;
5265 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5272 Double_t cradius0 = 40*40;
5273 Double_t cradius1 = 270*270;
5276 Double_t cdist3=0.55;
5277 for (Int_t j =i+1;j<nentries;j++){
5279 if (sign[j]*sign[i]<1) continue;
5280 if ( (nclusters[i]+nclusters[j])>200) continue;
5281 if ( (nclusters[i]+nclusters[j])<80) continue;
5282 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5283 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5284 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5285 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5286 if (npoints<1) continue;
5289 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5292 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5295 Double_t delta1=10000,delta2=10000;
5296 // cuts on the intersection radius
5297 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5298 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5299 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5301 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5302 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5303 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5306 Double_t distance1 = TMath::Min(delta1,delta2);
5307 if (distance1>cdist1) continue; // cut on DCA linear approximation
5309 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5310 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5311 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5312 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5315 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5316 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5317 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5319 distance1 = TMath::Min(delta1,delta2);
5322 rkink = TMath::Sqrt(radius[0]);
5325 rkink = TMath::Sqrt(radius[1]);
5327 if (distance1>cdist2) continue;
5330 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5333 Int_t row0 = GetRowNumber(rkink);
5334 if (row0<10) continue;
5335 if (row0>150) continue;
5338 Float_t dens00=-1,dens01=-1;
5339 Float_t dens10=-1,dens11=-1;
5341 Int_t found,foundable,ishared;
5342 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5343 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5344 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5345 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5347 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5348 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5349 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5350 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5352 if (dens00<dens10 && dens01<dens11) continue;
5353 if (dens00>dens10 && dens01>dens11) continue;
5354 if (TMath::Max(dens00,dens10)<0.1) continue;
5355 if (TMath::Max(dens01,dens11)<0.3) continue;
5357 if (TMath::Min(dens00,dens10)>0.6) continue;
5358 if (TMath::Min(dens01,dens11)>0.6) continue;
5361 AliTPCseed * ktrack0, *ktrack1;
5370 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5371 AliExternalTrackParam paramm(*ktrack0);
5372 AliExternalTrackParam paramd(*ktrack1);
5373 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5376 kink->SetMother(paramm);
5377 kink->SetDaughter(paramd);
5380 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
5382 fkParam->Transform0to1(x,index);
5383 fkParam->Transform1to2(x,index);
5384 row0 = GetRowNumber(x[0]);
5386 if (kink->GetR()<100) continue;
5387 if (kink->GetR()>240) continue;
5388 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5389 if (kink->GetDistance()>cdist3) continue;
5390 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5391 if (dird<0) continue;
5393 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5394 if (dirm<0) continue;
5395 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5396 if (mpt<0.2) continue;
5399 //for high momenta momentum not defined well in first iteration
5400 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5401 if (qt>0.35) continue;
5404 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5405 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5407 kink->SetTPCDensity(dens00,0,0);
5408 kink->SetTPCDensity(dens01,0,1);
5409 kink->SetTPCDensity(dens10,1,0);
5410 kink->SetTPCDensity(dens11,1,1);
5411 kink->SetIndex(i,0);
5412 kink->SetIndex(j,1);
5415 kink->SetTPCDensity(dens10,0,0);
5416 kink->SetTPCDensity(dens11,0,1);
5417 kink->SetTPCDensity(dens00,1,0);
5418 kink->SetTPCDensity(dens01,1,1);
5419 kink->SetIndex(j,0);
5420 kink->SetIndex(i,1);
5423 if (mpt<1||kink->GetAngle(2)>0.1){
5424 // angle and densities not defined yet
5425 if (kink->GetTPCDensityFactor()<0.8) continue;
5426 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5427 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5428 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5429 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5431 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5432 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5433 criticalangle= 3*TMath::Sqrt(criticalangle);
5434 if (criticalangle>0.02) criticalangle=0.02;
5435 if (kink->GetAngle(2)<criticalangle) continue;
5438 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5439 Float_t shapesum =0;
5441 for ( Int_t row = row0-drow; row<row0+drow;row++){
5442 if (row<0) continue;
5443 if (row>155) continue;
5444 if (ktrack0->GetClusterPointer(row)){
5445 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5446 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5449 if (ktrack1->GetClusterPointer(row)){
5450 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5451 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5456 kink->SetShapeFactor(-1.);
5459 kink->SetShapeFactor(shapesum/sum);
5461 // esd->AddKink(kink);
5463 // kink->SetMother(paramm);
5464 //kink->SetDaughter(paramd);
5466 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5468 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5469 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5471 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5473 if (AliTPCReconstructor::StreamLevel()>1) {
5474 (*fDebugStreamer)<<"kinkLpt"<<
5482 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5486 kinks->AddLast(kink);
5492 // sort the kinks according quality - and refit them towards vertex
5494 Int_t nkinks = kinks->GetEntriesFast();
5495 Float_t *quality = new Float_t[nkinks];
5496 Int_t *indexes = new Int_t[nkinks];
5497 AliTPCseed *mothers = new AliTPCseed[nkinks];
5498 AliTPCseed *daughters = new AliTPCseed[nkinks];
5501 for (Int_t i=0;i<nkinks;i++){
5503 AliKink *kinkl = (AliKink*)kinks->At(i);
5505 // refit kinks towards vertex
5507 Int_t index0 = kinkl->GetIndex(0);
5508 Int_t index1 = kinkl->GetIndex(1);
5509 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5510 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5512 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5514 // Refit Kink under if too small angle
5516 if (kinkl->GetAngle(2)<0.05){
5517 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5518 Int_t row0 = kinkl->GetTPCRow0();
5519 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5522 Int_t last = row0-drow;
5523 if (last<40) last=40;
5524 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5525 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5528 Int_t first = row0+drow;
5529 if (first>130) first=130;
5530 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5531 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5533 if (seed0 && seed1){
5534 kinkl->SetStatus(1,8);
5535 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5536 row0 = GetRowNumber(kinkl->GetR());
5537 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5538 mothers[i] = *seed0;
5539 daughters[i] = *seed1;
5542 delete kinks->RemoveAt(i);
5543 if (seed0) MarkSeedFree( seed0 );
5544 if (seed1) MarkSeedFree( seed1 );
5547 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
5548 delete kinks->RemoveAt(i);
5549 if (seed0) MarkSeedFree( seed0 );
5550 if (seed1) MarkSeedFree( seed1 );
5554 MarkSeedFree( seed0 );
5555 MarkSeedFree( seed1 );
5558 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
5560 TMath::Sort(nkinks,quality,indexes,kFALSE);
5562 //remove double find kinks
5564 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5565 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5566 if (!kink0) continue;
5568 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5569 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5570 if (!kink0) continue;
5571 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5572 if (!kink1) continue;
5573 // if not close kink continue
5574 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5575 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5576 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5578 AliTPCseed &mother0 = mothers[indexes[ikink0]];
5579 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5580 AliTPCseed &mother1 = mothers[indexes[ikink1]];
5581 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5582 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5591 for (Int_t i=0;i<row0;i++){
5592 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5595 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5602 for (Int_t i=row0;i<158;i++){
5603 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
5604 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
5607 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5613 Float_t ratio = Float_t(same+1)/Float_t(both+1);
5614 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5615 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5616 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5617 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5618 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5620 shared[kink0->GetIndex(0)]= kTRUE;
5621 shared[kink0->GetIndex(1)]= kTRUE;
5622 delete kinks->RemoveAt(indexes[ikink0]);
5626 shared[kink1->GetIndex(0)]= kTRUE;
5627 shared[kink1->GetIndex(1)]= kTRUE;
5628 delete kinks->RemoveAt(indexes[ikink1]);
5635 for (Int_t i=0;i<nkinks;i++){
5636 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
5637 if (!kinkl) continue;
5638 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5639 Int_t index0 = kinkl->GetIndex(0);
5640 Int_t index1 = kinkl->GetIndex(1);
5641 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
5642 kinkl->SetMultiple(usage[index0],0);
5643 kinkl->SetMultiple(usage[index1],1);
5644 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
5645 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5646 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
5647 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
5649 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5650 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5651 if (!ktrack0 || !ktrack1) continue;
5652 Int_t index = esd->AddKink(kinkl);
5655 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
5656 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5657 *ktrack0 = mothers[indexes[i]];
5658 *ktrack1 = daughters[indexes[i]];
5662 ktrack0->SetKinkIndex(usage[index0],-(index+1));
5663 ktrack1->SetKinkIndex(usage[index1], (index+1));
5668 // Remove tracks corresponding to shared kink's
5670 for (Int_t i=0;i<nentries;i++){
5671 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5672 if (!track0) continue;
5673 if (track0->GetKinkIndex(0)!=0) continue;
5674 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
5679 RemoveUsed2(array,0.5,0.4,30);
5681 for (Int_t i=0;i<nentries;i++){
5682 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5683 if (!track0) continue;
5684 track0->CookdEdx(0.02,0.6);
5688 for (Int_t i=0;i<nentries;i++){
5689 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5690 if (!track0) continue;
5691 if (track0->Pt()<1.4) continue;
5692 //remove double high momenta tracks - overlapped with kink candidates
5695 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5696 if (track0->GetClusterPointer(icl)!=0){
5698 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
5701 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
5702 MarkSeedFree( array->RemoveAt(i) );
5706 if (track0->GetKinkIndex(0)!=0) continue;
5707 if (track0->GetNumberOfClusters()<80) continue;
5709 AliTPCseed *pmother = new AliTPCseed();
5710 AliTPCseed *pdaughter = new AliTPCseed();
5711 AliKink *pkink = new AliKink;
5713 AliTPCseed & mother = *pmother;
5714 AliTPCseed & daughter = *pdaughter;
5715 AliKink & kinkl = *pkink;
5716 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
5717 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5721 continue; //too short tracks
5723 if (mother.Pt()<1.4) {
5729 Int_t row0= kinkl.GetTPCRow0();
5730 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
5737 Int_t index = esd->AddKink(&kinkl);
5738 mother.SetKinkIndex(0,-(index+1));
5739 daughter.SetKinkIndex(0,index+1);
5740 if (mother.GetNumberOfClusters()>50) {
5741 MarkSeedFree( array->RemoveAt(i) );
5742 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5743 mtc->SetPoolID(fLastSeedID);
5744 array->AddAt(mtc,i);
5747 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5748 mtc->SetPoolID(fLastSeedID);
5749 array->AddLast(mtc);
5751 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
5752 dtc->SetPoolID(fLastSeedID);
5753 array->AddLast(dtc);
5754 for (Int_t icl=0;icl<row0;icl++) {
5755 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5758 for (Int_t icl=row0;icl<158;icl++) {
5759 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5768 delete [] daughters;
5790 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
5796 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5803 TObjArray *kinks= new TObjArray(10000);
5804 // TObjArray *v0s= new TObjArray(10000);
5805 Int_t nentries = array->GetEntriesFast();
5806 AliHelix *helixes = new AliHelix[nentries];
5807 Int_t *sign = new Int_t[nentries];
5808 Int_t *nclusters = new Int_t[nentries];
5809 Float_t *alpha = new Float_t[nentries];
5810 AliKink *kink = new AliKink();
5811 Int_t * usage = new Int_t[nentries];
5812 Float_t *zm = new Float_t[nentries];
5813 Float_t *z0 = new Float_t[nentries];
5814 Float_t *fim = new Float_t[nentries];
5815 Float_t *shared = new Float_t[nentries];
5816 Bool_t *circular = new Bool_t[nentries];
5817 Float_t *dca = new Float_t[nentries];
5818 //const AliESDVertex * primvertex = esd->GetVertex();
5820 // nentries = array->GetEntriesFast();
5825 for (Int_t i=0;i<nentries;i++){
5828 AliTPCseed* track = (AliTPCseed*)array->At(i);
5829 if (!track) continue;
5830 track->SetCircular(0);
5832 track->UpdatePoints();
5833 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5835 nclusters[i]=track->GetNumberOfClusters();
5836 alpha[i] = track->GetAlpha();
5837 new (&helixes[i]) AliHelix(*track);
5839 helixes[i].Evaluate(0,xyz);
5840 sign[i] = (track->GetC()>0) ? -1:1;
5843 if (track->GetProlongation(x,y,z)){
5845 fim[i] = alpha[i]+TMath::ATan2(y,x);
5848 zm[i] = track->GetZ();
5852 circular[i]= kFALSE;
5853 if (track->GetProlongation(0,y,z)) z0[i] = z;
5854 dca[i] = track->GetD(0,0);
5860 Int_t ncandidates =0;
5863 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5866 // Find circling track
5868 for (Int_t i0=0;i0<nentries;i0++){
5869 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5870 if (!track0) continue;
5871 if (track0->GetNumberOfClusters()<40) continue;
5872 if (TMath::Abs(1./track0->GetC())>200) continue;
5873 for (Int_t i1=i0+1;i1<nentries;i1++){
5874 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5875 if (!track1) continue;
5876 if (track1->GetNumberOfClusters()<40) continue;
5877 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5878 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5879 if (TMath::Abs(1./track1->GetC())>200) continue;
5880 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5881 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5882 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5883 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5884 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5886 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5887 if (mindcar<5) continue;
5888 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5889 if (mindcaz<5) continue;
5890 if (mindcar+mindcaz<20) continue;
5893 Float_t xc0 = helixes[i0].GetHelix(6);
5894 Float_t yc0 = helixes[i0].GetHelix(7);
5895 Float_t r0 = helixes[i0].GetHelix(8);
5896 Float_t xc1 = helixes[i1].GetHelix(6);
5897 Float_t yc1 = helixes[i1].GetHelix(7);
5898 Float_t r1 = helixes[i1].GetHelix(8);
5900 Float_t rmean = (r0+r1)*0.5;
5901 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5902 //if (delta>30) continue;
5903 if (delta>rmean*0.25) continue;
5904 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5906 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5907 if (npoints==0) continue;
5908 helixes[i0].GetClosestPhases(helixes[i1], phase);
5912 Double_t hangles[3];
5913 helixes[i0].Evaluate(phase[0][0],xyz0);
5914 helixes[i1].Evaluate(phase[0][1],xyz1);
5916 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5917 Double_t deltah[2],deltabest;
5918 if (hangles[2]<2.8) continue;
5921 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5923 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5924 if (deltah[1]<deltah[0]) ibest=1;
5926 deltabest = TMath::Sqrt(deltah[ibest]);
5927 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5928 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5929 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5930 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5932 if (deltabest>6) continue;
5933 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5934 Bool_t lsign =kFALSE;
5935 if (hangles[2]>3.06) lsign =kTRUE;
5938 circular[i0] = kTRUE;
5939 circular[i1] = kTRUE;
5940 if (track0->OneOverPt()<track1->OneOverPt()){
5941 track0->SetCircular(track0->GetCircular()+1);
5942 track1->SetCircular(track1->GetCircular()+2);
5945 track1->SetCircular(track1->GetCircular()+1);
5946 track0->SetCircular(track0->GetCircular()+2);
5949 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5951 Int_t lab0=track0->GetLabel();
5952 Int_t lab1=track1->GetLabel();
5953 TTreeSRedirector &cstream = *fDebugStreamer;
5954 cstream<<"Curling"<<
5961 "mindcar="<<mindcar<<
5962 "mindcaz="<<mindcaz<<
5965 "npoints="<<npoints<<
5966 "hangles0="<<hangles[0]<<
5967 "hangles2="<<hangles[2]<<
5972 "radius="<<radiusbest<<
5973 "deltabest="<<deltabest<<
5974 "phase0="<<phase[ibest][0]<<
5975 "phase1="<<phase[ibest][1]<<
5985 for (Int_t i =0;i<nentries;i++){
5986 if (sign[i]==0) continue;
5987 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5994 Double_t cradius0 = 40*40;
5995 Double_t cradius1 = 270*270;
5998 Double_t cdist3=0.55;
5999 for (Int_t j =i+1;j<nentries;j++){
6001 if (sign[j]*sign[i]<1) continue;
6002 if ( (nclusters[i]+nclusters[j])>200) continue;
6003 if ( (nclusters[i]+nclusters[j])<80) continue;
6004 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6005 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6006 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6007 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6008 if (npoints<1) continue;
6011 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6014 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6017 Double_t delta1=10000,delta2=10000;
6018 // cuts on the intersection radius
6019 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6020 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6021 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6023 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6024 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6025 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6028 Double_t distance1 = TMath::Min(delta1,delta2);
6029 if (distance1>cdist1) continue; // cut on DCA linear approximation
6031 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6032 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6033 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6034 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6037 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6038 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6039 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6041 distance1 = TMath::Min(delta1,delta2);
6044 rkink = TMath::Sqrt(radius[0]);
6047 rkink = TMath::Sqrt(radius[1]);
6049 if (distance1>cdist2) continue;
6052 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6055 Int_t row0 = GetRowNumber(rkink);
6056 if (row0<10) continue;
6057 if (row0>150) continue;
6060 Float_t dens00=-1,dens01=-1;
6061 Float_t dens10=-1,dens11=-1;
6063 Int_t found,foundable,ishared;
6064 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6065 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6066 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6067 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6069 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6070 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6071 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6072 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6074 if (dens00<dens10 && dens01<dens11) continue;
6075 if (dens00>dens10 && dens01>dens11) continue;
6076 if (TMath::Max(dens00,dens10)<0.1) continue;
6077 if (TMath::Max(dens01,dens11)<0.3) continue;
6079 if (TMath::Min(dens00,dens10)>0.6) continue;
6080 if (TMath::Min(dens01,dens11)>0.6) continue;
6083 AliTPCseed * ktrack0, *ktrack1;
6092 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6093 AliExternalTrackParam paramm(*ktrack0);
6094 AliExternalTrackParam paramd(*ktrack1);
6095 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6098 kink->SetMother(paramm);
6099 kink->SetDaughter(paramd);
6102 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
6104 fkParam->Transform0to1(x,index);
6105 fkParam->Transform1to2(x,index);
6106 row0 = GetRowNumber(x[0]);
6108 if (kink->GetR()<100) continue;
6109 if (kink->GetR()>240) continue;
6110 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6111 if (kink->GetDistance()>cdist3) continue;
6112 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6113 if (dird<0) continue;
6115 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6116 if (dirm<0) continue;
6117 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6118 if (mpt<0.2) continue;
6121 //for high momenta momentum not defined well in first iteration
6122 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6123 if (qt>0.35) continue;
6126 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6127 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6129 kink->SetTPCDensity(dens00,0,0);
6130 kink->SetTPCDensity(dens01,0,1);
6131 kink->SetTPCDensity(dens10,1,0);
6132 kink->SetTPCDensity(dens11,1,1);
6133 kink->SetIndex(i,0);
6134 kink->SetIndex(j,1);
6137 kink->SetTPCDensity(dens10,0,0);
6138 kink->SetTPCDensity(dens11,0,1);
6139 kink->SetTPCDensity(dens00,1,0);
6140 kink->SetTPCDensity(dens01,1,1);
6141 kink->SetIndex(j,0);
6142 kink->SetIndex(i,1);
6145 if (mpt<1||kink->GetAngle(2)>0.1){
6146 // angle and densities not defined yet
6147 if (kink->GetTPCDensityFactor()<0.8) continue;
6148 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6149 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6150 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6151 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6153 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6154 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6155 criticalangle= 3*TMath::Sqrt(criticalangle);
6156 if (criticalangle>0.02) criticalangle=0.02;
6157 if (kink->GetAngle(2)<criticalangle) continue;
6160 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6161 Float_t shapesum =0;
6163 for ( Int_t row = row0-drow; row<row0+drow;row++){
6164 if (row<0) continue;
6165 if (row>155) continue;
6166 if (ktrack0->GetClusterPointer(row)){
6167 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6168 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6171 if (ktrack1->GetClusterPointer(row)){
6172 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6173 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6178 kink->SetShapeFactor(-1.);
6181 kink->SetShapeFactor(shapesum/sum);
6183 // esd->AddKink(kink);
6185 // kink->SetMother(paramm);
6186 //kink->SetDaughter(paramd);
6188 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6190 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6191 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6193 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6195 if (AliTPCReconstructor::StreamLevel()>1) {
6196 (*fDebugStreamer)<<"kinkLpt"<<
6204 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6208 kinks->AddLast(kink);
6214 // sort the kinks according quality - and refit them towards vertex
6216 Int_t nkinks = kinks->GetEntriesFast();
6217 Float_t *quality = new Float_t[nkinks];
6218 Int_t *indexes = new Int_t[nkinks];
6219 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6220 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6223 for (Int_t i=0;i<nkinks;i++){
6225 AliKink *kinkl = (AliKink*)kinks->At(i);
6227 // refit kinks towards vertex
6229 Int_t index0 = kinkl->GetIndex(0);
6230 Int_t index1 = kinkl->GetIndex(1);
6231 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6232 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6234 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6236 // Refit Kink under if too small angle
6238 if (kinkl->GetAngle(2)<0.05){
6239 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6240 Int_t row0 = kinkl->GetTPCRow0();
6241 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6244 Int_t last = row0-drow;
6245 if (last<40) last=40;
6246 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6247 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6250 Int_t first = row0+drow;
6251 if (first>130) first=130;
6252 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6253 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6255 if (seed0 && seed1){
6256 kinkl->SetStatus(1,8);
6257 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6258 row0 = GetRowNumber(kinkl->GetR());
6259 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6260 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6261 mothers[i]->SetPoolID(fLastSeedID);
6262 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6263 daughters[i]->SetPoolID(fLastSeedID);
6266 delete kinks->RemoveAt(i);
6267 if (seed0) MarkSeedFree( seed0 );
6268 if (seed1) MarkSeedFree( seed1 );
6271 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6272 delete kinks->RemoveAt(i);
6273 if (seed0) MarkSeedFree( seed0 );
6274 if (seed1) MarkSeedFree( seed1 );
6278 MarkSeedFree( seed0 );
6279 MarkSeedFree( seed1 );
6282 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6284 TMath::Sort(nkinks,quality,indexes,kFALSE);
6286 //remove double find kinks
6288 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6289 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6290 if (!kink0) continue;
6292 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6293 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6294 if (!kink0) continue;
6295 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6296 if (!kink1) continue;
6297 // if not close kink continue
6298 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6299 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6300 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6302 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6303 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6304 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6305 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6306 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6315 for (Int_t i=0;i<row0;i++){
6316 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6319 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6326 for (Int_t i=row0;i<158;i++){
6327 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6328 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6331 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6337 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6338 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6339 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6340 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6341 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6342 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6344 shared[kink0->GetIndex(0)]= kTRUE;
6345 shared[kink0->GetIndex(1)]= kTRUE;
6346 delete kinks->RemoveAt(indexes[ikink0]);
6350 shared[kink1->GetIndex(0)]= kTRUE;
6351 shared[kink1->GetIndex(1)]= kTRUE;
6352 delete kinks->RemoveAt(indexes[ikink1]);
6359 for (Int_t i=0;i<nkinks;i++){
6360 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6361 if (!kinkl) continue;
6362 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6363 Int_t index0 = kinkl->GetIndex(0);
6364 Int_t index1 = kinkl->GetIndex(1);
6365 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6366 kinkl->SetMultiple(usage[index0],0);
6367 kinkl->SetMultiple(usage[index1],1);
6368 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6369 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6370 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6371 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6373 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6374 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6375 if (!ktrack0 || !ktrack1) continue;
6376 Int_t index = esd->AddKink(kinkl);
6379 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6380 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6381 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6382 *ktrack0 = *mothers[indexes[i]];
6383 *ktrack1 = *daughters[indexes[i]];
6387 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6388 ktrack1->SetKinkIndex(usage[index1], (index+1));
6393 // Remove tracks corresponding to shared kink's
6395 for (Int_t i=0;i<nentries;i++){
6396 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6397 if (!track0) continue;
6398 if (track0->GetKinkIndex(0)!=0) continue;
6399 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6404 RemoveUsed2(array,0.5,0.4,30);
6406 for (Int_t i=0;i<nentries;i++){
6407 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6408 if (!track0) continue;
6409 track0->CookdEdx(0.02,0.6);
6413 for (Int_t i=0;i<nentries;i++){
6414 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6415 if (!track0) continue;
6416 if (track0->Pt()<1.4) continue;
6417 //remove double high momenta tracks - overlapped with kink candidates
6420 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6421 if (track0->GetClusterPointer(icl)!=0){
6423 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6426 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6427 MarkSeedFree( array->RemoveAt(i) );
6431 if (track0->GetKinkIndex(0)!=0) continue;
6432 if (track0->GetNumberOfClusters()<80) continue;
6434 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6435 pmother->SetPoolID(fLastSeedID);
6436 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6437 pdaughter->SetPoolID(fLastSeedID);
6438 AliKink *pkink = new AliKink;
6440 AliTPCseed & mother = *pmother;
6441 AliTPCseed & daughter = *pdaughter;
6442 AliKink & kinkl = *pkink;
6443 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6444 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6445 MarkSeedFree( pmother );
6446 MarkSeedFree( pdaughter );
6448 continue; //too short tracks
6450 if (mother.Pt()<1.4) {
6451 MarkSeedFree( pmother );
6452 MarkSeedFree( pdaughter );
6456 Int_t row0= kinkl.GetTPCRow0();
6457 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6458 MarkSeedFree( pmother );
6459 MarkSeedFree( pdaughter );
6464 Int_t index = esd->AddKink(&kinkl);
6465 mother.SetKinkIndex(0,-(index+1));
6466 daughter.SetKinkIndex(0,index+1);
6467 if (mother.GetNumberOfClusters()>50) {
6468 MarkSeedFree( array->RemoveAt(i) );
6469 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6470 mtc->SetPoolID(fLastSeedID);
6471 array->AddAt(mtc,i);
6474 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6475 mtc->SetPoolID(fLastSeedID);
6476 array->AddLast(mtc);
6478 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6479 dtc->SetPoolID(fLastSeedID);
6480 array->AddLast(dtc);
6481 for (Int_t icl=0;icl<row0;icl++) {
6482 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6485 for (Int_t icl=row0;icl<158;icl++) {
6486 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6490 MarkSeedFree( pmother );
6491 MarkSeedFree( pdaughter );
6495 delete [] daughters;
6517 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6522 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6525 // refit kink towards to the vertex
6528 AliKink &kink=(AliKink &)knk;
6530 Int_t row0 = GetRowNumber(kink.GetR());
6531 FollowProlongation(mother,0);
6532 mother.Reset(kFALSE);
6534 FollowProlongation(daughter,row0);
6535 daughter.Reset(kFALSE);
6536 FollowBackProlongation(daughter,158);
6537 daughter.Reset(kFALSE);
6538 Int_t first = TMath::Max(row0-20,30);
6539 Int_t last = TMath::Min(row0+20,140);
6541 const Int_t kNdiv =5;
6542 AliTPCseed param0[kNdiv]; // parameters along the track
6543 AliTPCseed param1[kNdiv]; // parameters along the track
6544 AliKink kinks[kNdiv]; // corresponding kink parameters
6547 for (Int_t irow=0; irow<kNdiv;irow++){
6548 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
6550 // store parameters along the track
6552 for (Int_t irow=0;irow<kNdiv;irow++){
6553 FollowBackProlongation(mother, rows[irow]);
6554 FollowProlongation(daughter,rows[kNdiv-1-irow]);
6555 param0[irow] = mother;
6556 param1[kNdiv-1-irow] = daughter;
6560 for (Int_t irow=0; irow<kNdiv-1;irow++){
6561 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
6562 kinks[irow].SetMother(param0[irow]);
6563 kinks[irow].SetDaughter(param1[irow]);
6564 kinks[irow].Update();
6567 // choose kink with best "quality"
6569 Double_t mindist = 10000;
6570 for (Int_t irow=0;irow<kNdiv;irow++){
6571 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
6572 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6573 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
6575 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
6576 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
6577 if (normdist < mindist){
6583 if (index==-1) return 0;
6586 param0[index].Reset(kTRUE);
6587 FollowProlongation(param0[index],0);
6589 mother = param0[index];
6590 daughter = param1[index]; // daughter in vertex
6592 kink.SetMother(mother);
6593 kink.SetDaughter(daughter);
6595 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
6596 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6597 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6598 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
6599 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
6600 mother.SetLabel(kink.GetLabel(0));
6601 daughter.SetLabel(kink.GetLabel(1));
6607 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
6609 // update Kink quality information for mother after back propagation
6611 if (seed->GetKinkIndex(0)>=0) return;
6612 for (Int_t ikink=0;ikink<3;ikink++){
6613 Int_t index = seed->GetKinkIndex(ikink);
6614 if (index>=0) break;
6615 index = TMath::Abs(index)-1;
6616 AliESDkink * kink = fEvent->GetKink(index);
6617 kink->SetTPCDensity(-1,0,0);
6618 kink->SetTPCDensity(1,0,1);
6620 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6621 if (row0<15) row0=15;
6623 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6624 if (row1>145) row1=145;
6626 Int_t found,foundable,shared;
6627 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6628 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
6629 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6630 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
6635 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
6637 // update Kink quality information for daughter after refit
6639 if (seed->GetKinkIndex(0)<=0) return;
6640 for (Int_t ikink=0;ikink<3;ikink++){
6641 Int_t index = seed->GetKinkIndex(ikink);
6642 if (index<=0) break;
6643 index = TMath::Abs(index)-1;
6644 AliESDkink * kink = fEvent->GetKink(index);
6645 kink->SetTPCDensity(-1,1,0);
6646 kink->SetTPCDensity(-1,1,1);
6648 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6649 if (row0<15) row0=15;
6651 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6652 if (row1>145) row1=145;
6654 Int_t found,foundable,shared;
6655 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6656 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
6657 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6658 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
6664 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6667 // check kink point for given track
6668 // if return value=0 kink point not found
6669 // otherwise seed0 correspond to mother particle
6670 // seed1 correspond to daughter particle
6671 // kink parameter of kink point
6672 AliKink &kink=(AliKink &)knk;
6674 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
6675 Int_t first = seed->GetFirstPoint();
6676 Int_t last = seed->GetLastPoint();
6677 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
6680 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
6681 if (!seed1) return 0;
6682 FollowProlongation(*seed1,seed->GetLastPoint()-20);
6683 seed1->Reset(kTRUE);
6684 FollowProlongation(*seed1,158);
6685 seed1->Reset(kTRUE);
6686 last = seed1->GetLastPoint();
6688 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
6689 seed0->SetPoolID(fLastSeedID);
6690 seed0->Reset(kFALSE);
6693 AliTPCseed param0[20]; // parameters along the track
6694 AliTPCseed param1[20]; // parameters along the track
6695 AliKink kinks[20]; // corresponding kink parameters
6697 for (Int_t irow=0; irow<20;irow++){
6698 rows[irow] = first +((last-first)*irow)/19;
6700 // store parameters along the track
6702 for (Int_t irow=0;irow<20;irow++){
6703 FollowBackProlongation(*seed0, rows[irow]);
6704 FollowProlongation(*seed1,rows[19-irow]);
6705 param0[irow] = *seed0;
6706 param1[19-irow] = *seed1;
6710 for (Int_t irow=0; irow<19;irow++){
6711 kinks[irow].SetMother(param0[irow]);
6712 kinks[irow].SetDaughter(param1[irow]);
6713 kinks[irow].Update();
6716 // choose kink with biggest change of angle
6718 Double_t maxchange= 0;
6719 for (Int_t irow=1;irow<19;irow++){
6720 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6721 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
6722 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6723 if ( quality > maxchange){
6724 maxchange = quality;
6729 MarkSeedFree( seed0 );
6730 MarkSeedFree( seed1 );
6731 if (index<0) return 0;
6733 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
6734 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
6735 seed0->SetPoolID(fLastSeedID);
6736 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
6737 seed1->SetPoolID(fLastSeedID);
6738 seed0->Reset(kFALSE);
6739 seed1->Reset(kFALSE);
6740 seed0->ResetCovariance(10.);
6741 seed1->ResetCovariance(10.);
6742 FollowProlongation(*seed0,0);
6743 FollowBackProlongation(*seed1,158);
6744 mother = *seed0; // backup mother at position 0
6745 seed0->Reset(kFALSE);
6746 seed1->Reset(kFALSE);
6747 seed0->ResetCovariance(10.);
6748 seed1->ResetCovariance(10.);
6750 first = TMath::Max(row0-20,0);
6751 last = TMath::Min(row0+20,158);
6753 for (Int_t irow=0; irow<20;irow++){
6754 rows[irow] = first +((last-first)*irow)/19;
6756 // store parameters along the track
6758 for (Int_t irow=0;irow<20;irow++){
6759 FollowBackProlongation(*seed0, rows[irow]);
6760 FollowProlongation(*seed1,rows[19-irow]);
6761 param0[irow] = *seed0;
6762 param1[19-irow] = *seed1;
6766 for (Int_t irow=0; irow<19;irow++){
6767 kinks[irow].SetMother(param0[irow]);
6768 kinks[irow].SetDaughter(param1[irow]);
6769 // param0[irow].Dump();
6770 //param1[irow].Dump();
6771 kinks[irow].Update();
6774 // choose kink with biggest change of angle
6777 for (Int_t irow=0;irow<20;irow++){
6778 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
6779 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
6780 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6781 if ( quality > maxchange){
6782 maxchange = quality;
6789 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
6790 MarkSeedFree( seed0 );
6791 MarkSeedFree( seed1 );
6795 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
6797 kink.SetMother(param0[index]);
6798 kink.SetDaughter(param1[index]);
6801 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
6803 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
6804 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
6806 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
6808 if (AliTPCReconstructor::StreamLevel()>1) {
6809 (*fDebugStreamer)<<"kinkHpt"<<
6812 "p0.="<<¶m0[index]<<
6813 "p1.="<<¶m1[index]<<
6817 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6818 MarkSeedFree( seed0 );
6819 MarkSeedFree( seed1 );
6824 row0 = GetRowNumber(kink.GetR());
6825 kink.SetTPCRow0(row0);
6826 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
6827 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
6828 kink.SetIndex(-10,0);
6829 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
6830 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6831 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6834 // new (&mother) AliTPCseed(param0[index]);
6835 daughter = param1[index];
6836 daughter.SetLabel(kink.GetLabel(1));
6837 param0[index].Reset(kTRUE);
6838 FollowProlongation(param0[index],0);
6839 mother = param0[index];
6840 mother.SetLabel(kink.GetLabel(0));
6841 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
6844 MarkSeedFree( seed0 );
6845 MarkSeedFree( seed1 );
6853 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
6856 // reseed - refit - track
6859 // Int_t last = fSectors->GetNRows()-1;
6861 if (fSectors == fOuterSec){
6862 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
6866 first = t->GetFirstPoint();
6868 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
6869 FollowBackProlongation(*t,fSectors->GetNRows()-1);
6871 FollowProlongation(*t,first);
6881 //_____________________________________________________________________________
6882 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
6883 //-----------------------------------------------------------------
6884 // This function reades track seeds.
6885 //-----------------------------------------------------------------
6886 TDirectory *savedir=gDirectory;
6888 TFile *in=(TFile*)inp;
6889 if (!in->IsOpen()) {
6890 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
6895 TTree *seedTree=(TTree*)in->Get("Seeds");
6897 cerr<<"AliTPCtracker::ReadSeeds(): ";
6898 cerr<<"can't get a tree with track seeds !\n";
6901 AliTPCtrack *seed=new AliTPCtrack;
6902 seedTree->SetBranchAddress("tracks",&seed);
6904 if (fSeeds==0) fSeeds=new TObjArray(15000);
6906 Int_t n=(Int_t)seedTree->GetEntries();
6907 for (Int_t i=0; i<n; i++) {
6908 seedTree->GetEvent(i);
6909 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
6910 sdc->SetPoolID(fLastSeedID);
6911 fSeeds->AddLast(sdc);
6914 delete seed; // RS: this seed is not from the pool, delete it !!!
6920 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
6923 // clusters to tracks
6924 if (fSeeds) DeleteSeeds();
6925 else ResetSeedsPool();
6927 fEventHLT = hltEvent;
6929 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
6930 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
6931 transform->SetCurrentRun(esd->GetRunNumber());
6935 if (!fSeeds) return 1;
6937 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(0,fSeeds);
6942 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
6945 // clusters to tracks
6946 return Clusters2TracksHLT( esd, 0);
6949 //_____________________________________________________________________________
6950 Int_t AliTPCtracker::Clusters2Tracks() {
6951 //-----------------------------------------------------------------
6952 // This is a track finder.
6953 //-----------------------------------------------------------------
6954 TDirectory *savedir=gDirectory;
6958 fSeeds = Tracking();
6961 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6963 //activate again some tracks
6964 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6965 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6967 Int_t nc=t.GetNumberOfClusters();
6969 MarkSeedFree( fSeeds->RemoveAt(i) );
6973 if (pt->GetRemoval()==10) {
6974 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6975 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
6977 pt->Desactivate(20);
6978 MarkSeedFree( fSeeds->RemoveAt(i) );
6983 RemoveUsed2(fSeeds,0.85,0.85,0);
6984 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
6985 //FindCurling(fSeeds, fEvent,0);
6986 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
6987 RemoveUsed2(fSeeds,0.5,0.4,20);
6988 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
6989 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
6992 // // refit short tracks
6994 Int_t nseed=fSeeds->GetEntriesFast();
6997 for (Int_t i=0; i<nseed; i++) {
6998 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7000 Int_t nc=t.GetNumberOfClusters();
7002 MarkSeedFree( fSeeds->RemoveAt(i) );
7005 CookLabel(pt,0.1); //For comparison only
7006 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7007 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7009 if (fDebug>0) cerr<<found<<'\r';
7013 MarkSeedFree( fSeeds->RemoveAt(i) );
7017 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7019 //RemoveUsed(fSeeds,0.9,0.9,6);
7021 nseed=fSeeds->GetEntriesFast();
7023 for (Int_t i=0; i<nseed; i++) {
7024 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7026 Int_t nc=t.GetNumberOfClusters();
7028 MarkSeedFree( fSeeds->RemoveAt(i) );
7032 t.CookdEdx(0.02,0.6);
7033 // CheckKinkPoint(&t,0.05);
7034 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7035 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7043 MarkSeedFree( fSeeds->RemoveAt(i) );
7044 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7046 // FollowProlongation(*seed1,0);
7047 // Int_t n = seed1->GetNumberOfClusters();
7048 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7049 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7052 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7056 SortTracks(fSeeds, 1);
7060 PrepareForBackProlongation(fSeeds,5.);
7061 PropagateBack(fSeeds);
7062 printf("Time for back propagation: \t");timer.Print();timer.Start();
7066 PrepareForProlongation(fSeeds,5.);
7067 PropagateForard2(fSeeds);
7069 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7070 // RemoveUsed(fSeeds,0.7,0.7,6);
7071 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7073 nseed=fSeeds->GetEntriesFast();
7075 for (Int_t i=0; i<nseed; i++) {
7076 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7078 Int_t nc=t.GetNumberOfClusters();
7080 MarkSeedFree( fSeeds->RemoveAt(i) );
7083 t.CookdEdx(0.02,0.6);
7084 // CookLabel(pt,0.1); //For comparison only
7085 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7086 if ((pt->IsActive() || (pt->fRemoval==10) )){
7087 cerr<<found++<<'\r';
7090 MarkSeedFree( fSeeds->RemoveAt(i) );
7095 // fNTracks = found;
7097 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7100 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7101 Info("Clusters2Tracks","Number of found tracks %d",found);
7103 // UnloadClusters();
7108 void AliTPCtracker::Tracking(TObjArray * arr)
7111 // tracking of the seeds
7114 fSectors = fOuterSec;
7115 ParallelTracking(arr,150,63);
7116 fSectors = fOuterSec;
7117 ParallelTracking(arr,63,0);
7120 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7125 static TObjArray arrTracks;
7126 TObjArray * arr = &arrTracks;
7128 fSectors = fOuterSec;
7131 for (Int_t sec=0;sec<fkNOS;sec++){
7132 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7133 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7134 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7137 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7149 TObjArray * AliTPCtracker::Tracking()
7153 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7156 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7158 TObjArray * seeds = new TObjArray;
7160 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7161 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7162 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7170 Float_t fnumber = 3.0;
7171 Float_t fdensity = 3.0;
7174 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7175 arr = MakeSeedsHLT( fEventHLT );
7177 SumTracks(seeds,arr);
7180 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7181 //SignClusters(seeds,fnumber,fdensity);
7188 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7192 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7193 SumTracks(seeds,arr);
7194 SignClusters(seeds,fnumber,fdensity);
7196 for (Int_t i=2;i<6;i+=2){
7197 // seed high pt tracks
7200 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7201 SumTracks(seeds,arr);
7202 SignClusters(seeds,fnumber,fdensity);
7207 // RemoveUsed(seeds,0.9,0.9,1);
7208 // UnsignClusters();
7209 // SignClusters(seeds,fnumber,fdensity);
7213 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7215 // seed high pt tracks
7219 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7220 SumTracks(seeds,arr);
7221 SignClusters(seeds,fnumber,fdensity);
7226 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7227 SumTracks(seeds,arr);
7228 SignClusters(seeds,fnumber,fdensity);
7239 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7243 // RemoveUsed(seeds,0.75,0.75,1);
7245 //SignClusters(seeds,fnumber,fdensity);
7254 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7255 SumTracks(seeds,arr);
7256 SignClusters(seeds,fnumber,fdensity);
7258 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7259 SumTracks(seeds,arr);
7260 SignClusters(seeds,fnumber,fdensity);
7262 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7263 SumTracks(seeds,arr);
7264 SignClusters(seeds,fnumber,fdensity);
7266 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7267 SumTracks(seeds,arr);
7268 SignClusters(seeds,fnumber,fdensity);
7270 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7271 SumTracks(seeds,arr);
7272 SignClusters(seeds,fnumber,fdensity);
7275 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7276 SumTracks(seeds,arr);
7277 SignClusters(seeds,fnumber,fdensity);
7281 for (Int_t delta = 9; delta<30; delta+=gapSec){
7287 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7288 SumTracks(seeds,arr);
7289 SignClusters(seeds,fnumber,fdensity);
7291 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7292 SumTracks(seeds,arr);
7293 SignClusters(seeds,fnumber,fdensity);
7306 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7312 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7313 SumTracks(seeds,arr);
7314 SignClusters(seeds,fnumber,fdensity);
7316 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7317 SumTracks(seeds,arr);
7318 SignClusters(seeds,fnumber,fdensity);
7322 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7333 TObjArray * AliTPCtracker::TrackingSpecial()
7336 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7337 // no primary vertex seeding tried
7341 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7343 TObjArray * seeds = new TObjArray;
7348 Float_t fnumber = 3.0;
7349 Float_t fdensity = 3.0;
7352 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7353 cuts[1] = 3.5; // max tan(phi) angle for seeding
7354 cuts[2] = 3.; // not used (cut on z primary vertex)
7355 cuts[3] = 3.5; // max tan(theta) angle for seeding
7357 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7359 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7360 SumTracks(seeds,arr);
7361 SignClusters(seeds,fnumber,fdensity);
7365 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7376 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7379 //sum tracks to common container
7380 //remove suspicious tracks
7381 // RS: Attention: supplied tracks come in the static array, don't delete them
7382 Int_t nseed = arr2->GetEntriesFast();
7383 for (Int_t i=0;i<nseed;i++){
7384 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7387 // remove tracks with too big curvature
7389 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7390 MarkSeedFree( arr2->RemoveAt(i) );
7393 // REMOVE VERY SHORT TRACKS
7394 if (pt->GetNumberOfClusters()<20){
7395 MarkSeedFree( arr2->RemoveAt(i) );
7398 // NORMAL ACTIVE TRACK
7399 if (pt->IsActive()){
7400 arr1->AddLast(arr2->RemoveAt(i));
7403 //remove not usable tracks
7404 if (pt->GetRemoval()!=10){
7405 MarkSeedFree( arr2->RemoveAt(i) );
7409 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7410 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7411 arr1->AddLast(arr2->RemoveAt(i));
7413 MarkSeedFree( arr2->RemoveAt(i) );
7417 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7422 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7425 // try to track in parralel
7427 Int_t nseed=arr->GetEntriesFast();
7428 //prepare seeds for tracking
7429 for (Int_t i=0; i<nseed; i++) {
7430 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7432 if (!t.IsActive()) continue;
7433 // follow prolongation to the first layer
7434 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7435 FollowProlongation(t, rfirst+1);
7440 for (Int_t nr=rfirst; nr>=rlast; nr--){
7441 if (nr<fInnerSec->GetNRows())
7442 fSectors = fInnerSec;
7444 fSectors = fOuterSec;
7445 // make indexes with the cluster tracks for given
7447 // find nearest cluster
7448 for (Int_t i=0; i<nseed; i++) {
7449 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7451 if (nr==80) pt->UpdateReference();
7452 if (!pt->IsActive()) continue;
7453 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7454 if (pt->GetRelativeSector()>17) {
7457 UpdateClusters(t,nr);
7459 // prolonagate to the nearest cluster - if founded
7460 for (Int_t i=0; i<nseed; i++) {
7461 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7463 if (!pt->IsActive()) continue;
7464 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7465 if (pt->GetRelativeSector()>17) {
7468 FollowToNextCluster(*pt,nr);
7473 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7477 // if we use TPC track itself we have to "update" covariance
7479 Int_t nseed= arr->GetEntriesFast();
7480 for (Int_t i=0;i<nseed;i++){
7481 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7485 //rotate to current local system at first accepted point
7486 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
7487 Int_t sec = (index&0xff000000)>>24;
7489 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
7490 if (angle1>TMath::Pi())
7491 angle1-=2.*TMath::Pi();
7492 Float_t angle2 = pt->GetAlpha();
7494 if (TMath::Abs(angle1-angle2)>0.001){
7495 if (!pt->Rotate(angle1-angle2)) return;
7496 //angle2 = pt->GetAlpha();
7497 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
7498 //if (pt->GetAlpha()<0)
7499 // pt->fRelativeSector+=18;
7500 //sec = pt->fRelativeSector;
7509 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
7513 // if we use TPC track itself we have to "update" covariance
7515 Int_t nseed= arr->GetEntriesFast();
7516 for (Int_t i=0;i<nseed;i++){
7517 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7520 pt->SetFirstPoint(pt->GetLastPoint());
7528 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
7531 // make back propagation
7533 Int_t nseed= arr->GetEntriesFast();
7534 for (Int_t i=0;i<nseed;i++){
7535 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7536 if (pt&& pt->GetKinkIndex(0)<=0) {
7537 //AliTPCseed *pt2 = new AliTPCseed(*pt);
7538 fSectors = fInnerSec;
7539 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
7540 //fSectors = fOuterSec;
7541 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7542 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
7543 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
7544 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
7547 if (pt&& pt->GetKinkIndex(0)>0) {
7548 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
7549 pt->SetFirstPoint(kink->GetTPCRow0());
7550 fSectors = fInnerSec;
7551 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7559 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
7562 // make forward propagation
7564 Int_t nseed= arr->GetEntriesFast();
7566 for (Int_t i=0;i<nseed;i++){
7567 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7569 FollowProlongation(*pt,0,1,1);
7578 Int_t AliTPCtracker::PropagateForward()
7581 // propagate track forward
7583 Int_t nseed = fSeeds->GetEntriesFast();
7584 for (Int_t i=0;i<nseed;i++){
7585 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
7587 AliTPCseed &t = *pt;
7588 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
7589 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
7590 if (alpha < 0. ) alpha += 2.*TMath::Pi();
7591 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
7595 fSectors = fOuterSec;
7596 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
7597 fSectors = fInnerSec;
7598 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
7607 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
7610 // make back propagation, in between row0 and row1
7614 fSectors = fInnerSec;
7617 if (row1<fSectors->GetNRows())
7620 r1 = fSectors->GetNRows()-1;
7622 if (row0<fSectors->GetNRows()&& r1>0 )
7623 FollowBackProlongation(*pt,r1);
7624 if (row1<=fSectors->GetNRows())
7627 r1 = row1 - fSectors->GetNRows();
7628 if (r1<=0) return 0;
7629 if (r1>=fOuterSec->GetNRows()) return 0;
7630 fSectors = fOuterSec;
7631 return FollowBackProlongation(*pt,r1);
7639 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
7641 // gets cluster shape
7643 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
7644 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
7645 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
7646 Double_t angulary = seed->GetSnp();
7648 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
7649 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
7652 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
7653 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
7655 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
7656 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
7657 seed->SetCurrentSigmaY2(sigmay*sigmay);
7658 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
7659 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
7660 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
7661 // Float_t padlength = GetPadPitchLength(row);
7663 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
7664 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
7666 // Float_t sresz = fkParam->GetZSigma();
7667 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
7669 Float_t wy = GetSigmaY(seed);
7670 Float_t wz = GetSigmaZ(seed);
7673 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
7674 printf("problem\n");
7681 //__________________________________________________________________________
7682 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
7683 //--------------------------------------------------------------------
7684 //This function "cooks" a track label. If label<0, this track is fake.
7685 //--------------------------------------------------------------------
7686 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
7688 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
7692 Int_t noc=t->GetNumberOfClusters();
7694 //printf("\nnot founded prolongation\n\n\n");
7700 AliTPCclusterMI *clusters[160];
7702 for (Int_t i=0;i<160;i++) {
7709 for (i=0; i<160 && current<noc; i++) {
7711 Int_t index=t->GetClusterIndex2(i);
7712 if (index<=0) continue;
7713 if (index&0x8000) continue;
7715 //clusters[current]=GetClusterMI(index);
7716 if (t->GetClusterPointer(i)){
7717 clusters[current]=t->GetClusterPointer(i);
7723 Int_t lab=123456789;
7724 for (i=0; i<noc; i++) {
7725 AliTPCclusterMI *c=clusters[i];
7727 lab=TMath::Abs(c->GetLabel(0));
7729 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7735 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7737 for (i=0; i<noc; i++) {
7738 AliTPCclusterMI *c=clusters[i];
7740 if (TMath::Abs(c->GetLabel(1)) == lab ||
7741 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7743 if (noc<=0) { lab=-1; return;}
7744 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7747 Int_t tail=Int_t(0.10*noc);
7750 for (i=1; i<160&&ind<tail; i++) {
7751 // AliTPCclusterMI *c=clusters[noc-i];
7752 AliTPCclusterMI *c=clusters[i];
7754 if (lab == TMath::Abs(c->GetLabel(0)) ||
7755 lab == TMath::Abs(c->GetLabel(1)) ||
7756 lab == TMath::Abs(c->GetLabel(2))) max++;
7759 if (max < Int_t(0.5*tail)) lab=-lab;
7766 //delete[] clusters;
7770 //__________________________________________________________________________
7771 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
7772 //--------------------------------------------------------------------
7773 //This function "cooks" a track label. If label<0, this track is fake.
7774 //--------------------------------------------------------------------
7775 Int_t noc=t->GetNumberOfClusters();
7777 //printf("\nnot founded prolongation\n\n\n");
7783 AliTPCclusterMI *clusters[160];
7785 for (Int_t i=0;i<160;i++) {
7792 for (i=0; i<160 && current<noc; i++) {
7793 if (i<first) continue;
7794 if (i>last) continue;
7795 Int_t index=t->GetClusterIndex2(i);
7796 if (index<=0) continue;
7797 if (index&0x8000) continue;
7799 //clusters[current]=GetClusterMI(index);
7800 if (t->GetClusterPointer(i)){
7801 clusters[current]=t->GetClusterPointer(i);
7806 //if (noc<5) return -1;
7807 Int_t lab=123456789;
7808 for (i=0; i<noc; i++) {
7809 AliTPCclusterMI *c=clusters[i];
7811 lab=TMath::Abs(c->GetLabel(0));
7813 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7819 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7821 for (i=0; i<noc; i++) {
7822 AliTPCclusterMI *c=clusters[i];
7824 if (TMath::Abs(c->GetLabel(1)) == lab ||
7825 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7827 if (noc<=0) { lab=-1; return -1;}
7828 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7831 Int_t tail=Int_t(0.10*noc);
7834 for (i=1; i<160&&ind<tail; i++) {
7835 // AliTPCclusterMI *c=clusters[noc-i];
7836 AliTPCclusterMI *c=clusters[i];
7838 if (lab == TMath::Abs(c->GetLabel(0)) ||
7839 lab == TMath::Abs(c->GetLabel(1)) ||
7840 lab == TMath::Abs(c->GetLabel(2))) max++;
7843 if (max < Int_t(0.5*tail)) lab=-lab;
7846 // t->SetLabel(lab);
7850 //delete[] clusters;
7854 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
7856 //return pad row number for given x vector
7857 Float_t phi = TMath::ATan2(x[1],x[0]);
7858 if(phi<0) phi=2.*TMath::Pi()+phi;
7859 // Get the local angle in the sector philoc
7860 const Float_t kRaddeg = 180/3.14159265358979312;
7861 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
7862 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
7863 return GetRowNumber(localx);
7868 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
7870 //-----------------------------------------------------------------------
7871 // Fill the cluster and sharing bitmaps of the track
7872 //-----------------------------------------------------------------------
7874 Int_t firstpoint = 0;
7875 Int_t lastpoint = 159;
7876 AliTPCTrackerPoint *point;
7877 AliTPCclusterMI *cluster;
7880 TBits clusterMap(159);
7881 TBits sharedMap(159);
7883 for (int iter=firstpoint; iter<lastpoint; iter++) {
7884 // Change to cluster pointers to see if we have a cluster at given padrow
7886 cluster = t->GetClusterPointer(iter);
7888 clusterMap.SetBitNumber(iter, kTRUE);
7889 point = t->GetTrackPoint(iter);
7890 if (point->IsShared())
7891 sharedMap.SetBitNumber(iter,kTRUE);
7893 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
7894 fitMap.SetBitNumber(iter, kTRUE);
7898 esd->SetTPCClusterMap(clusterMap);
7899 esd->SetTPCSharedMap(sharedMap);
7900 esd->SetTPCFitMap(fitMap);
7901 if (nclsf != t->GetNumberOfClusters())
7902 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
7905 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
7907 // return flag if there is findable cluster at given position
7910 Float_t z = track.GetZ();
7912 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
7913 TMath::Abs(z)<fkParam->GetZLength(0) &&
7914 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
7920 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
7922 // Adding systematic error estimate to the covariance matrix
7923 // !!!! the systematic error for element 4 is in 1/GeV
7924 // 03.03.2012 MI changed in respect to the previous versions
7925 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7927 // use only the diagonal part if not specified otherwise
7928 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
7930 Double_t *covarS= (Double_t*)seed->GetCovariance();
7931 Double_t factor[5]={1,1,1,1,1};
7932 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
7933 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
7934 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
7935 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
7936 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
7938 factor[0]=factor[2];
7939 factor[4]=factor[2];
7945 for (Int_t i=0; i<5; i++){
7946 for (Int_t j=i; j<5; j++){
7947 Int_t index=seed->GetIndex(i,j);
7948 covarS[index]*=factor[i]*factor[j];
7954 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
7956 // Adding systematic error - as additive factor without correlation
7958 // !!!! the systematic error for element 4 is in 1/GeV
7959 // 03.03.2012 MI changed in respect to the previous versions
7961 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7962 Double_t *covarIn= (Double_t*)seed->GetCovariance();
7964 for (Int_t i=0;i<15;i++) covar[i]=0;
7970 covar[0] = param[0]*param[0];
7971 covar[2] = param[1]*param[1];
7972 covar[5] = param[2]*param[2];
7973 covar[9] = param[3]*param[3];
7974 covar[14]= param[4]*param[4];
7976 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
7978 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
7979 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
7981 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
7982 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
7983 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
7985 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
7986 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
7987 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
7988 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
7990 seed->AddCovariance(covar);
7993 //_____________________________________________________________________________
7994 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
7997 // check events affected by TPC HV dip
7999 if(!esdEvent) return kFALSE;
8002 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8003 if(!db) return kFALSE;
8004 db->SetRun(esdEvent->GetRunNumber());
8006 // maximum allowed voltage before an event is identified as a dip event
8007 // and scanning period
8008 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8009 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8010 const Double_t tevSec = esdEvent->GetTimeStamp();
8012 for(Int_t sector=0; sector<72; sector++)
8014 // don't use excluded chambers, since the state is not defined at all
8015 if (!db->GetChamberHVStatus(sector)) continue;
8017 // get hv sensor of the chamber
8018 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8019 if (!sensor) continue;
8020 TGraph *grSensor=sensor->GetGraph();
8021 if (!grSensor) continue;
8022 if (grSensor->GetN()<1) continue;
8025 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8026 if(median < 1.) continue;
8028 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8029 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8030 if (tevSec-dipEventScanPeriod>nextTime) continue;
8031 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8032 if (deltaV>kTPCHVdip) {
8033 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8036 if (nextTime>tevSec+dipEventScanPeriod) break;
8043 //________________________________________
8044 void AliTPCtracker::MarkSeedFree(TObject *sd)
8046 // account that this seed is "deleted"
8047 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8049 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8052 int id = seed->GetPoolID();
8054 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8057 // AliInfo(Form("%d %p",id, seed));
8058 fSeedsPool->RemoveAt(id);
8059 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8060 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8063 //________________________________________
8064 TObject *&AliTPCtracker::NextFreeSeed()
8066 // return next free slot where the seed can be created
8067 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8068 // AliInfo(Form("%d",fLastSeedID));
8069 return (*fSeedsPool)[ fLastSeedID ];
8073 //________________________________________
8074 void AliTPCtracker::ResetSeedsPool()
8076 // mark all seeds in the pool as unused
8077 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8079 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8082 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8085 Double_t x= GetXrow(nrow);
8086 Double_t ymax= GetMaxY(nrow);
8092 if (!t.PropagateTo(x) ){
8093 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8099 Double_t y = t.GetY();
8101 if( rotate!=-1 ) rotate=1;
8102 } else if (y <-ymax) {
8103 if( rotate!=1 ) rotate = -1;
8105 if( rotate==0 ) break;
8106 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8107 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8108 //cout<<"can't rotate "<<endl;
8112 nRotations+= rotate;
8114 if( nRotations!=0 ){
8115 int newSec= t.GetRelativeSector()+nRotations;
8116 if( newSec>=fN ) newSec-=fN;
8117 else if( newSec<0 ) newSec +=fN;
8118 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8119 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8120 t.SetRelativeSector(newSec);
8125 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8128 // try to track in parralel
8130 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8133 Int_t nseed=arr->GetEntriesFast();
8134 //cout<<"Parallel tracking My.."<<endl;
8135 double shapeY2[160], shapeZ2[160];
8136 Int_t clusterIndex[160];
8138 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8139 //if( iSeed!=1 ) continue;
8140 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8144 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8148 for( int iter=0; iter<3; iter++ ){
8151 t.SetLastPoint(0); // first cluster in track position
8152 t.SetFirstPoint(nRows-1);
8153 t.ResetCovariance(.1);
8154 t.SetNumberOfClusters(0);
8155 for( int i=0; i<nRows; i++ ){
8159 t.SetClusterIndex2(i,-1);
8160 t.SetClusterIndex(i,-1);
8163 // pick up the clusters
8165 Double_t roady = 20.;
8166 Double_t roadz = 20.;
8173 t0.SetRelativeSector(t.GetRelativeSector());
8174 t0.SetLastPoint(0); // first cluster in track position
8175 t0.SetFirstPoint(159);
8176 for (Int_t nr=0; nr<nRows; nr++){
8177 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8178 else fSectors=fOuterSec;
8180 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8181 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8182 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8185 if (!IsActive(t0.GetRelativeSector(),nr)) {
8191 shapeY2[nr]=t0.GetCurrentSigmaY2();
8192 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8195 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8196 if( !krow ) continue;
8198 t.SetClusterIndex2(nr,-3); // foundable
8199 t.SetClusterIndex(nr,-3);
8201 AliTPCclusterMI *cl=0;
8203 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8205 double dy = cl->GetY()-t0.GetY();
8206 double dz = cl->GetZ()-t0.GetZ();
8207 double dr = sqrt(dy*dy+dz*dz);
8209 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8212 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8214 t0.SetClusterPointer(nr, cl);
8215 clusterIndex[nr] = krow.GetIndex(uindex);
8216 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8217 t0.SetLastPoint(nr);
8223 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8226 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8230 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8232 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8233 if( !t0.GetClusterPointer(nr) ) continue;
8234 int d = TMath::Abs(nr-midRow);
8242 // first fit 3 base points
8244 //cout<<"Fit3: "<<endl;
8245 for( int icl=0; icl<3; icl++){
8246 int nr = basePoints[icl];
8248 if( nr>=fInnerSec->GetNRows()){
8249 lr = nr - fInnerSec->GetNRows();
8251 } else fSectors=fInnerSec;
8253 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8255 //cout<<"WRONG!!!!"<<endl;
8258 int iSec = cl->GetDetector() %fkNIS;
8259 int rotate = iSec - t.GetRelativeSector();
8261 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8262 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8263 //cout<<"can't rotate "<<endl;
8266 t.SetRelativeSector(iSec);
8268 Double_t x= cl->GetX();
8269 if (!t.PropagateTo(x)){
8270 //cout<<"can't propagate to x="<<x<<endl;
8274 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8275 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8278 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8280 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8281 t.SetCurrentCluster(cl);
8284 t.SetErrorY2(shapeY2[nr]);
8285 t.SetErrorZ2(shapeZ2[nr]);
8288 for( int j=0; j<15; j++ ) cov[j]=0;
8294 t.AliExternalTrackParam::AddCovariance(cov);
8296 if( !UpdateTrack(&t,0) ){
8297 //cout<<"Can not update"<<endl;
8299 t.SetClusterIndex2(nr,-1);
8300 t.SetClusterIndex(nr,-1);
8301 t.SetClusterPointer(nr,0);
8304 //t.SetClusterPointer(nr, cl);
8307 //t.SetLastPoint(t0.GetLastPoint());
8308 //t.SetFirstPoint(t0.GetFirstPoint());
8310 //cout<<"Fit: "<<endl;
8311 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8313 if( nr>=fInnerSec->GetNRows()){
8314 lr = nr - fInnerSec->GetNRows();
8316 } else fSectors=fInnerSec;
8319 if( nr == basePoints[0] ) continue;
8320 if( nr == basePoints[1] ) continue;
8321 if( nr == basePoints[2] ) continue;
8323 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8326 int iSec = cl->GetDetector() %fkNIS;
8327 int rotate = iSec - t.GetRelativeSector();
8329 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8330 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8331 //cout<<"can't rotate "<<endl;
8334 t.SetRelativeSector(iSec);
8336 Double_t x= cl->GetX();
8337 if (!t.PropagateTo(x)){
8338 //cout<<"can't propagate to x="<<x<<endl;
8341 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8342 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8346 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8348 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8349 t.SetCurrentCluster(cl);
8351 t.SetErrorY2(shapeY2[nr]);
8352 t.SetErrorZ2(shapeZ2[nr]);
8354 if( !UpdateTrack(&t,0) ){
8355 //cout<<"Can not update"<<endl;
8357 t.SetClusterIndex2(nr,-1);
8358 t.SetClusterIndex(nr,-1);
8361 //t.SetClusterPointer(nr, cl);
8364 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8367 //cout<<"fitted track"<<iSeed<<endl;
8369 //cout<<"Statistics: "<<endl;
8370 Int_t foundable,found,shared;
8371 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8372 t.SetNFoundable(foundable);
8373 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8379 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8384 if( !hltEvent ) return 0;
8387 Int_t nentr=hltEvent->GetNumberOfTracks();
8389 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8391 TObjArray * seeds = new TObjArray(nentr);
8393 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8396 Int_t nTr=hltEvent->GetNumberOfTracks();
8398 for( int itr=0; itr<nTr; itr++ ){
8399 //if( itr!=97 ) continue;
8400 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8401 if( !param ) continue;
8402 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8403 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8405 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8406 tr.SetNumberOfClusters(0);
8407 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8409 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8410 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8411 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8413 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8414 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8416 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8417 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8419 seed->Rotate(alphaSec - alpha);
8421 seed->SetPoolID(fLastSeedID);
8422 seed->SetIsSeeding(kTRUE);
8423 seed->SetSeed1(nup-1);
8424 seed->SetSeed2(nup-2);
8425 seed->SetSeedType(0);
8426 seed->SetFirstPoint(-1);
8427 seed->SetLastPoint(-1);
8428 seeds->AddLast(seed); // note, track is seed, don't free the seed
8430 //if( index>3 ) break;
8434 fSectors = fOuterSec;
8436 TrackFollowingHLT(seeds );
8438 nTr = seeds->GetEntriesFast();
8439 for( int itr=0; itr<nTr; itr++ ){
8440 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8441 if( !seed ) continue;
8442 //FollowBackProlongation(*seed,0);
8443 // cout<<seed->GetNumberOfClusters()<<endl;
8444 Int_t foundable,found,shared;
8445 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8446 seed->SetNFoundable(foundable);
8447 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8448 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8449 //MarkSeedFree(seeds->RemoveAt(itr));
8452 if (seed->GetNumberOfClusters()<30 ||
8453 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8454 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8455 MarkSeedFree(seeds->RemoveAt(itr));
8459 for( int ir=0; ir<nup; ir++){
8460 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8464 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;