1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 //-------------------------------------------------------
18 // Implementation of the TPC tracker
20 // Origin: Marian Ivanov Marian.Ivanov@cern.ch
22 // AliTPC parallel tracker
24 // The track fitting is based on Kalman filtering approach
26 // The track finding steps:
27 // 1. Seeding - with and without vertex constraint
28 // - seeding with vertex constain done at first n^2 proble
29 // - seeding without vertex constraint n^3 problem
30 // 2. Tracking - follow prolongation road - find cluster - update kalman track
32 // The seeding and tracking is repeated several times, in different seeding region.
33 // This approach enables to find the track which cannot be seeded in some region of TPC
34 // This can happen because of low momenta (track do not reach outer radius), or track is currently in the ded region between sectors, or the track is for the moment overlapped with other track (seed quality is poor) ...
36 // With this approach we reach almost 100 % efficiency also for high occupancy events.
37 // (If the seeding efficiency in a region is about 90 % than with logical or of several
38 // regions we will reach 100% (in theory - supposing independence)
40 // Repeating several seeding - tracking procedures some of the tracks can be find
43 // The procedures to remove multi find tacks are impremented:
44 // RemoveUsed2 - fast procedure n problem -
45 // Algorithm - Sorting tracks according quality
46 // remove tracks with some shared fraction
47 // Sharing in respect to all tacks
48 // Signing clusters in gold region
49 // FindSplitted - slower algorithm n^2
50 // Sort the tracks according quality
51 // Loop over pair of tracks
52 // If overlap with other track bigger than threshold - remove track
54 // FindCurling - Finds the pair of tracks which are curling
55 // - About 10% of tracks can be find with this procedure
56 // The combinatorial background is too big to be used in High
57 // multiplicity environment
58 // - n^2 problem - Slow procedure - currently it is disabled because of
61 // The number of splitted tracks can be reduced disabling the sharing of the cluster.
62 // tpcRecoParam-> SetClusterSharing(kFALSE);
63 // IT IS HIGHLY non recomended to use it in high flux enviroonment
64 // Even using this switch some tracks can be found more than once
65 // (because of multiple seeding and low quality tracks which will not cross full chamber)
68 // The tracker itself can be debugged - the information about tracks can be stored in several // phases of the reconstruction
69 // To enable storage of the TPC tracks in the ESD friend track
70 // use AliTPCReconstructor::SetStreamLevel(n);
72 // The debug level - different procedure produce tree for numerical debugging
73 // To enable them set AliTPCReconstructor::SetStreamLevel(n); where nis bigger 1
77 // Adding systematic errors to the covariance:
79 // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
80 // of the tracks (not to the clusters as they are dependent):
81 // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
82 // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
83 // The default values are 0.
85 // The sytematic errors are added to the covariance matrix in following places:
87 // 1. During fisrt itteration - AliTPCtracker::FillESD
88 // 2. Second iteration -
89 // 2.a ITS->TPC - AliTPCtracker::ReadSeeds
90 // 2.b TPC->TRD - AliTPCtracker::PropagateBack
91 // 3. Third iteration -
92 // 3.a TRD->TPC - AliTPCtracker::ReadSeeds
93 // 3.b TPC->ITS - AliTPCtracker::RefitInward
95 // There are several places in the code which can be numerically debuged
96 // This code is keeped in order to enable code development and to check the calibration implementtion
98 // 1. ErrParam stream - dump information about
100 // 2.a) cluster error estimate
101 // 3.a) cluster shape estimate
104 // Debug streamer levels:
106 //-------------------------------------------------------
111 #include "Riostream.h"
112 #include <TClonesArray.h>
114 #include <TObjArray.h>
116 #include <TGraphErrors.h>
117 #include <TTimeStamp.h>
119 #include "AliComplexCluster.h"
120 #include "AliESDEvent.h"
121 #include "AliESDtrack.h"
122 #include "AliESDVertex.h"
125 #include "AliHelix.h"
126 #include "AliRunLoader.h"
127 #include "AliTPCClustersRow.h"
128 #include "AliTPCParam.h"
129 #include "AliTPCReconstructor.h"
130 #include "AliTPCpolyTrack.h"
131 #include "AliTPCreco.h"
132 #include "AliTPCseed.h"
134 #include "AliTPCtrackerSector.h"
135 #include "AliTPCtracker.h"
136 #include "TStopwatch.h"
137 #include "AliTPCReconstructor.h"
138 #include "AliAlignObj.h"
139 #include "AliTrackPointArray.h"
141 #include "AliTPCcalibDB.h"
142 #include "AliTPCcalibDButil.h"
143 #include "AliTPCTransform.h"
144 #include "AliTPCClusterParam.h"
145 #include "AliTPCdEdxInfo.h"
146 #include "AliDCSSensorArray.h"
147 #include "AliDCSSensor.h"
149 #include "AliCosmicTracker.h"
155 ClassImp(AliTPCtracker)
159 class AliTPCFastMath {
162 static Double_t FastAsin(Double_t x);
164 static Double_t fgFastAsin[20000]; //lookup table for fast asin computation
167 Double_t AliTPCFastMath::fgFastAsin[20000];
168 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
170 AliTPCFastMath::AliTPCFastMath(){
172 // initialized lookup table;
173 for (Int_t i=0;i<10000;i++){
174 fgFastAsin[2*i] = TMath::ASin(i/10000.);
175 fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
179 Double_t AliTPCFastMath::FastAsin(Double_t x){
181 // return asin using lookup table
183 Int_t index = int(x*10000);
184 return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
187 Int_t index = int(x*10000);
188 return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
190 //__________________________________________________________________
191 AliTPCtracker::AliTPCtracker()
219 // default constructor
221 for (Int_t irow=0; irow<200; irow++){
228 //_____________________________________________________________________
232 Int_t AliTPCtracker::UpdateTrack(AliTPCseed * track, Int_t accept){
234 //update track information using current cluster - track->fCurrentCluster
237 AliTPCclusterMI* c =track->GetCurrentCluster();
238 if (accept > 0) //sign not accepted clusters
239 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);
240 else // unsign accpeted clusters
241 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);
242 UInt_t i = track->GetCurrentClusterIndex1();
244 Int_t sec=(i&0xff000000)>>24;
245 //Int_t row = (i&0x00ff0000)>>16;
246 track->SetRow((i&0x00ff0000)>>16);
247 track->SetSector(sec);
248 // Int_t index = i&0xFFFF;
249 if (sec>=fkParam->GetNInnerSector()) track->SetRow(track->GetRow()+fkParam->GetNRowLow());
250 track->SetClusterIndex2(track->GetRow(), i);
251 //track->fFirstPoint = row;
252 //if ( track->fLastPoint<row) track->fLastPoint =row;
253 // if (track->fRow<0 || track->fRow>160) {
254 // printf("problem\n");
256 if (track->GetFirstPoint()>track->GetRow())
257 track->SetFirstPoint(track->GetRow());
258 if (track->GetLastPoint()<track->GetRow())
259 track->SetLastPoint(track->GetRow());
262 track->SetClusterPointer(track->GetRow(),c);
265 Double_t angle2 = track->GetSnp()*track->GetSnp();
267 //SET NEW Track Point
269 if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
271 angle2 = TMath::Sqrt(angle2/(1-angle2));
272 AliTPCTrackerPoint &point =*(track->GetTrackPoint(track->GetRow()));
274 point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
275 point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
276 point.SetErrY(sqrt(track->GetErrorY2()));
277 point.SetErrZ(sqrt(track->GetErrorZ2()));
279 point.SetX(track->GetX());
280 point.SetY(track->GetY());
281 point.SetZ(track->GetZ());
282 point.SetAngleY(angle2);
283 point.SetAngleZ(track->GetTgl());
284 if (point.IsShared()){
285 track->SetErrorY2(track->GetErrorY2()*4);
286 track->SetErrorZ2(track->GetErrorZ2()*4);
290 Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
292 // track->SetErrorY2(track->GetErrorY2()*1.3);
293 // track->SetErrorY2(track->GetErrorY2()+0.01);
294 // track->SetErrorZ2(track->GetErrorZ2()*1.3);
295 // track->SetErrorZ2(track->GetErrorZ2()+0.005);
297 if (accept>0) return 0;
298 if (track->GetNumberOfClusters()%20==0){
299 // if (track->fHelixIn){
300 // TClonesArray & larr = *(track->fHelixIn);
301 // Int_t ihelix = larr.GetEntriesFast();
302 // new(larr[ihelix]) AliHelix(*track) ;
305 if (AliTPCReconstructor::StreamLevel()>0) {
306 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
307 AliExternalTrackParam param(*track);
308 TTreeSRedirector &cstream = *fDebugStreamer;
314 track->SetNoCluster(0);
315 return track->Update(c,chi2,i);
320 Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
323 // decide according desired precision to accept given
324 // cluster for tracking
326 seed->GetProlongation(cluster->GetX(),yt,zt);
327 Double_t sy2=ErrY2(seed,cluster);
328 Double_t sz2=ErrZ2(seed,cluster);
330 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
331 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
332 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
333 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
334 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
335 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
336 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
337 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
339 Double_t rdistance2 = rdistancey2+rdistancez2;
342 if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
343 Float_t rmsy2 = seed->GetCurrentSigmaY2();
344 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
345 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
346 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
347 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
348 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
349 AliExternalTrackParam param(*seed);
350 static TVectorD gcl(3),gtr(3);
352 param.GetXYZ(gcl.GetMatrixArray());
353 cluster->GetGlobalXYZ(gclf);
354 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
357 if (AliTPCReconstructor::StreamLevel()>2) {
358 (*fDebugStreamer)<<"ErrParam"<<
359 "iter="<<fIteration<<
372 "rmsy2p30="<<rmsy2p30<<
373 "rmsz2p30="<<rmsz2p30<<
374 "rmsy2p30R="<<rmsy2p30R<<
375 "rmsz2p30R="<<rmsz2p30R<<
376 // normalize distance -
377 "rdisty="<<rdistancey2<<
378 "rdistz="<<rdistancez2<<
379 "rdist="<<rdistance2<< //
383 //return 0; // temporary
384 if (rdistance2>32) return 3;
387 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
388 return 2; //suspisiouce - will be changed
390 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
391 // strict cut on overlaped cluster
392 return 2; //suspisiouce - will be changed
394 if ( (rdistancey2>1. || rdistancez2>6.25 )
395 && cluster->GetType()<0){
396 seed->SetNFoundable(seed->GetNFoundable()-1);
400 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
402 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
403 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
416 //_____________________________________________________________________________
417 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
419 fkNIS(par->GetNInnerSector()/2),
421 fkNOS(par->GetNOuterSector()/2),
444 //---------------------------------------------------------------------
445 // The main TPC tracker constructor
446 //---------------------------------------------------------------------
447 fInnerSec=new AliTPCtrackerSector[fkNIS];
448 fOuterSec=new AliTPCtrackerSector[fkNOS];
451 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
452 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
455 Int_t nrowlow = par->GetNRowLow();
456 Int_t nrowup = par->GetNRowUp();
459 for (i=0;i<nrowlow;i++){
460 fXRow[i] = par->GetPadRowRadiiLow(i);
461 fPadLength[i]= par->GetPadPitchLength(0,i);
462 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
466 for (i=0;i<nrowup;i++){
467 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
468 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
469 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
472 if (AliTPCReconstructor::StreamLevel()>0) {
473 fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
476 fSeedsPool = new TClonesArray("AliTPCseed",1000);
478 //________________________________________________________________________
479 AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
506 //------------------------------------
507 // dummy copy constructor
508 //------------------------------------------------------------------
510 for (Int_t irow=0; irow<200; irow++){
517 AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
519 //------------------------------
521 //--------------------------------------------------------------
524 //_____________________________________________________________________________
525 AliTPCtracker::~AliTPCtracker() {
526 //------------------------------------------------------------------
527 // TPC tracker destructor
528 //------------------------------------------------------------------
535 if (fDebugStreamer) delete fDebugStreamer;
536 if (fSeedsPool) delete fSeedsPool;
540 void AliTPCtracker::FillESD(const TObjArray* arr)
544 //fill esds using updated tracks
547 // write tracks to the event
548 // store index of the track
549 Int_t nseed=arr->GetEntriesFast();
550 //FindKinks(arr,fEvent);
551 for (Int_t i=0; i<nseed; i++) {
552 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
556 if (AliTPCReconstructor::StreamLevel()>1) {
557 (*fDebugStreamer)<<"Track0"<<
561 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
562 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
563 pt->PropagateTo(fkParam->GetInnerRadiusLow());
566 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
568 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
569 iotrack.SetTPCPoints(pt->GetPoints());
570 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
571 iotrack.SetV0Indexes(pt->GetV0Indexes());
572 // iotrack.SetTPCpid(pt->fTPCr);
573 //iotrack.SetTPCindex(i);
574 MakeESDBitmaps(pt, &iotrack);
575 fEvent->AddTrack(&iotrack);
579 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
581 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
582 iotrack.SetTPCPoints(pt->GetPoints());
583 //iotrack.SetTPCindex(i);
584 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
585 iotrack.SetV0Indexes(pt->GetV0Indexes());
586 MakeESDBitmaps(pt, &iotrack);
587 // iotrack.SetTPCpid(pt->fTPCr);
588 fEvent->AddTrack(&iotrack);
592 // short tracks - maybe decays
594 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
595 Int_t found,foundable,shared;
596 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
597 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
599 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
600 //iotrack.SetTPCindex(i);
601 iotrack.SetTPCPoints(pt->GetPoints());
602 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
603 iotrack.SetV0Indexes(pt->GetV0Indexes());
604 MakeESDBitmaps(pt, &iotrack);
605 //iotrack.SetTPCpid(pt->fTPCr);
606 fEvent->AddTrack(&iotrack);
611 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
612 Int_t found,foundable,shared;
613 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
614 if (found<20) continue;
615 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
618 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
619 iotrack.SetTPCPoints(pt->GetPoints());
620 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
621 iotrack.SetV0Indexes(pt->GetV0Indexes());
622 MakeESDBitmaps(pt, &iotrack);
623 //iotrack.SetTPCpid(pt->fTPCr);
624 //iotrack.SetTPCindex(i);
625 fEvent->AddTrack(&iotrack);
628 // short tracks - secondaties
630 if ( (pt->GetNumberOfClusters()>30) ) {
631 Int_t found,foundable,shared;
632 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
633 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
635 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
636 iotrack.SetTPCPoints(pt->GetPoints());
637 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
638 iotrack.SetV0Indexes(pt->GetV0Indexes());
639 MakeESDBitmaps(pt, &iotrack);
640 //iotrack.SetTPCpid(pt->fTPCr);
641 //iotrack.SetTPCindex(i);
642 fEvent->AddTrack(&iotrack);
647 if ( (pt->GetNumberOfClusters()>15)) {
648 Int_t found,foundable,shared;
649 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
650 if (found<15) continue;
651 if (foundable<=0) continue;
652 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
653 if (float(found)/float(foundable)<0.8) continue;
656 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
657 iotrack.SetTPCPoints(pt->GetPoints());
658 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
659 iotrack.SetV0Indexes(pt->GetV0Indexes());
660 MakeESDBitmaps(pt, &iotrack);
661 // iotrack.SetTPCpid(pt->fTPCr);
662 //iotrack.SetTPCindex(i);
663 fEvent->AddTrack(&iotrack);
667 // >> account for suppressed tracks in the kink indices (RS)
668 int nESDtracks = fEvent->GetNumberOfTracks();
669 for (int it=nESDtracks;it--;) {
670 AliESDtrack* esdTr = fEvent->GetTrack(it);
671 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
672 for (int ik=0;ik<3;ik++) {
674 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
675 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
677 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
680 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
683 // << account for suppressed tracks in the kink indices (RS)
684 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
692 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
695 // Use calibrated cluster error from OCDB
697 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
699 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
700 Int_t ctype = cl->GetType();
701 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
702 Double_t angle = seed->GetSnp()*seed->GetSnp();
703 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
704 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
706 erry2+=0.5; // edge cluster
710 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
711 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
712 erry2+=addErr*addErr;
713 seed->SetErrorY2(erry2);
717 //calculate look-up table at the beginning
718 // static Bool_t ginit = kFALSE;
719 // static Float_t gnoise1,gnoise2,gnoise3;
720 // static Float_t ggg1[10000];
721 // static Float_t ggg2[10000];
722 // static Float_t ggg3[10000];
723 // static Float_t glandau1[10000];
724 // static Float_t glandau2[10000];
725 // static Float_t glandau3[10000];
727 // static Float_t gcor01[500];
728 // static Float_t gcor02[500];
729 // static Float_t gcorp[500];
733 // if (ginit==kFALSE){
734 // for (Int_t i=1;i<500;i++){
735 // Float_t rsigma = float(i)/100.;
736 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
737 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
738 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
742 // for (Int_t i=3;i<10000;i++){
746 // Float_t amp = float(i);
747 // Float_t padlength =0.75;
748 // gnoise1 = 0.0004/padlength;
749 // Float_t nel = 0.268*amp;
750 // Float_t nprim = 0.155*amp;
751 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
752 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
753 // if (glandau1[i]>1) glandau1[i]=1;
754 // glandau1[i]*=padlength*padlength/12.;
758 // gnoise2 = 0.0004/padlength;
760 // nprim = 0.133*amp;
761 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
762 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
763 // if (glandau2[i]>1) glandau2[i]=1;
764 // glandau2[i]*=padlength*padlength/12.;
769 // gnoise3 = 0.0004/padlength;
771 // nprim = 0.133*amp;
772 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
773 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
774 // if (glandau3[i]>1) glandau3[i]=1;
775 // glandau3[i]*=padlength*padlength/12.;
783 // Int_t amp = int(TMath::Abs(cl->GetQ()));
785 // seed->SetErrorY2(1.);
789 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
790 // Int_t ctype = cl->GetType();
791 // Float_t padlength= GetPadPitchLength(seed->GetRow());
792 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
793 // angle2 = angle2/(1-angle2);
795 // //cluster "quality"
796 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
799 // if (fSectors==fInnerSec){
800 // snoise2 = gnoise1;
801 // res = ggg1[amp]*z+glandau1[amp]*angle2;
802 // if (ctype==0) res *= gcor01[rsigmay];
805 // res*= gcorp[rsigmay];
809 // if (padlength<1.1){
810 // snoise2 = gnoise2;
811 // res = ggg2[amp]*z+glandau2[amp]*angle2;
812 // if (ctype==0) res *= gcor02[rsigmay];
815 // res*= gcorp[rsigmay];
819 // snoise2 = gnoise3;
820 // res = ggg3[amp]*z+glandau3[amp]*angle2;
821 // if (ctype==0) res *= gcor02[rsigmay];
824 // res*= gcorp[rsigmay];
831 // res*=2.4; // overestimate error 2 times
835 // if (res<2*snoise2)
838 // seed->SetErrorY2(res);
846 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
849 // Use calibrated cluster error from OCDB
851 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
853 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
854 Int_t ctype = cl->GetType();
855 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
857 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
858 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
859 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
860 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
862 errz2+=0.5; // edge cluster
866 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
867 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
868 errz2+=addErr*addErr;
869 seed->SetErrorZ2(errz2);
875 // //seed->SetErrorY2(0.1);
877 // //calculate look-up table at the beginning
878 // static Bool_t ginit = kFALSE;
879 // static Float_t gnoise1,gnoise2,gnoise3;
880 // static Float_t ggg1[10000];
881 // static Float_t ggg2[10000];
882 // static Float_t ggg3[10000];
883 // static Float_t glandau1[10000];
884 // static Float_t glandau2[10000];
885 // static Float_t glandau3[10000];
887 // static Float_t gcor01[1000];
888 // static Float_t gcor02[1000];
889 // static Float_t gcorp[1000];
893 // if (ginit==kFALSE){
894 // for (Int_t i=1;i<1000;i++){
895 // Float_t rsigma = float(i)/100.;
896 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
897 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
898 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
902 // for (Int_t i=3;i<10000;i++){
906 // Float_t amp = float(i);
907 // Float_t padlength =0.75;
908 // gnoise1 = 0.0004/padlength;
909 // Float_t nel = 0.268*amp;
910 // Float_t nprim = 0.155*amp;
911 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
912 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
913 // if (glandau1[i]>1) glandau1[i]=1;
914 // glandau1[i]*=padlength*padlength/12.;
918 // gnoise2 = 0.0004/padlength;
920 // nprim = 0.133*amp;
921 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
922 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
923 // if (glandau2[i]>1) glandau2[i]=1;
924 // glandau2[i]*=padlength*padlength/12.;
929 // gnoise3 = 0.0004/padlength;
931 // nprim = 0.133*amp;
932 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
933 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
934 // if (glandau3[i]>1) glandau3[i]=1;
935 // glandau3[i]*=padlength*padlength/12.;
943 // Int_t amp = int(TMath::Abs(cl->GetQ()));
945 // seed->SetErrorY2(1.);
949 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
950 // Int_t ctype = cl->GetType();
951 // Float_t padlength= GetPadPitchLength(seed->GetRow());
953 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
954 // // if (angle2<0.6) angle2 = 0.6;
955 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
957 // //cluster "quality"
958 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
961 // if (fSectors==fInnerSec){
962 // snoise2 = gnoise1;
963 // res = ggg1[amp]*z+glandau1[amp]*angle2;
964 // if (ctype==0) res *= gcor01[rsigmaz];
967 // res*= gcorp[rsigmaz];
971 // if (padlength<1.1){
972 // snoise2 = gnoise2;
973 // res = ggg2[amp]*z+glandau2[amp]*angle2;
974 // if (ctype==0) res *= gcor02[rsigmaz];
977 // res*= gcorp[rsigmaz];
981 // snoise2 = gnoise3;
982 // res = ggg3[amp]*z+glandau3[amp]*angle2;
983 // if (ctype==0) res *= gcor02[rsigmaz];
986 // res*= gcorp[rsigmaz];
995 // if ((ctype<0) &&<70){
1000 // if (res<2*snoise2)
1002 // if (res>3) res =3;
1003 // seed->SetErrorZ2(res);
1011 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1013 //rotate to track "local coordinata
1014 Float_t x = seed->GetX();
1015 Float_t y = seed->GetY();
1016 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1019 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1020 if (!seed->Rotate(fSectors->GetAlpha()))
1022 } else if (y <-ymax) {
1023 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1024 if (!seed->Rotate(-fSectors->GetAlpha()))
1032 //_____________________________________________________________________________
1033 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1034 Double_t x2,Double_t y2,
1035 Double_t x3,Double_t y3) const
1037 //-----------------------------------------------------------------
1038 // Initial approximation of the track curvature
1039 //-----------------------------------------------------------------
1040 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1041 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1042 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1043 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1044 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1046 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1047 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1048 return -xr*yr/sqrt(xr*xr+yr*yr);
1053 //_____________________________________________________________________________
1054 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1055 Double_t x2,Double_t y2,
1056 Double_t x3,Double_t y3) const
1058 //-----------------------------------------------------------------
1059 // Initial approximation of the track curvature
1060 //-----------------------------------------------------------------
1066 Double_t det = x3*y2-x2*y3;
1067 if (TMath::Abs(det)<1e-10){
1071 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1072 Double_t x0 = x3*0.5-y3*u;
1073 Double_t y0 = y3*0.5+x3*u;
1074 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1080 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1081 Double_t x2,Double_t y2,
1082 Double_t x3,Double_t y3) const
1084 //-----------------------------------------------------------------
1085 // Initial approximation of the track curvature
1086 //-----------------------------------------------------------------
1092 Double_t det = x3*y2-x2*y3;
1093 if (TMath::Abs(det)<1e-10) {
1097 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1098 Double_t x0 = x3*0.5-y3*u;
1099 Double_t y0 = y3*0.5+x3*u;
1100 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1109 //_____________________________________________________________________________
1110 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1111 Double_t x2,Double_t y2,
1112 Double_t x3,Double_t y3) const
1114 //-----------------------------------------------------------------
1115 // Initial approximation of the track curvature times center of curvature
1116 //-----------------------------------------------------------------
1117 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1118 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1119 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1120 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1121 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1123 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1125 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1128 //_____________________________________________________________________________
1129 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1130 Double_t x2,Double_t y2,
1131 Double_t z1,Double_t z2) const
1133 //-----------------------------------------------------------------
1134 // Initial approximation of the tangent of the track dip angle
1135 //-----------------------------------------------------------------
1136 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1140 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1141 Double_t x2,Double_t y2,
1142 Double_t z1,Double_t z2, Double_t c) const
1144 //-----------------------------------------------------------------
1145 // Initial approximation of the tangent of the track dip angle
1146 //-----------------------------------------------------------------
1150 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1152 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1153 if (TMath::Abs(d*c*0.5)>1) return 0;
1154 // Double_t angle2 = TMath::ASin(d*c*0.5);
1155 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1156 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1158 angle2 = (z1-z2)*c/(angle2*2.);
1162 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1163 {//-----------------------------------------------------------------
1164 // This function find proloncation of a track to a reference plane x=x2.
1165 //-----------------------------------------------------------------
1169 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1173 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1174 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1178 Double_t dy = dx*(c1+c2)/(r1+r2);
1181 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1183 if (TMath::Abs(delta)>0.01){
1184 dz = x[3]*TMath::ASin(delta)/x[4];
1186 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1189 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1197 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1202 return LoadClusters();
1206 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1209 // load clusters to the memory
1210 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1211 Int_t lower = arr->LowerBound();
1212 Int_t entries = arr->GetEntriesFast();
1214 for (Int_t i=lower; i<entries; i++) {
1215 clrow = (AliTPCClustersRow*) arr->At(i);
1216 if(!clrow) continue;
1217 if(!clrow->GetArray()) continue;
1221 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1223 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1224 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1227 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1228 AliTPCtrackerRow * tpcrow=0;
1231 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1235 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1236 left = (sec-fkNIS*2)/fkNOS;
1239 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1240 for (Int_t j=0;j<tpcrow->GetN1();++j)
1241 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1244 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1245 for (Int_t j=0;j<tpcrow->GetN2();++j)
1246 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1248 clrow->GetArray()->Clear("C");
1257 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1260 // load clusters to the memory from one
1263 AliTPCclusterMI *clust=0;
1264 Int_t count[72][96] = { {0} , {0} };
1266 // loop over clusters
1267 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1268 clust = (AliTPCclusterMI*)arr->At(icl);
1269 if(!clust) continue;
1270 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1272 // transform clusters
1275 // count clusters per pad row
1276 count[clust->GetDetector()][clust->GetRow()]++;
1279 // insert clusters to sectors
1280 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1281 clust = (AliTPCclusterMI*)arr->At(icl);
1282 if(!clust) continue;
1284 Int_t sec = clust->GetDetector();
1285 Int_t row = clust->GetRow();
1287 // filter overlapping pad rows needed by HLT
1288 if(sec<fkNIS*2) { //IROCs
1289 if(row == 30) continue;
1292 if(row == 27 || row == 76) continue;
1297 // left = sec/fkNIS;
1298 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1301 // left = (sec-fkNIS*2)/fkNOS;
1302 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1306 // Load functions must be called behind LoadCluster(TClonesArray*)
1308 //LoadOuterSectors();
1309 //LoadInnerSectors();
1315 Int_t AliTPCtracker::LoadClusters()
1318 // load clusters to the memory
1319 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1321 // TTree * tree = fClustersArray.GetTree();
1322 AliInfo("LoadClusters()\n");
1324 TTree * tree = fInput;
1325 TBranch * br = tree->GetBranch("Segment");
1326 br->SetAddress(&clrow);
1328 // Conversion of pad, row coordinates in local tracking coords.
1329 // Could be skipped here; is already done in clusterfinder
1331 Int_t j=Int_t(tree->GetEntries());
1332 for (Int_t i=0; i<j; i++) {
1336 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1337 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1338 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1341 AliTPCtrackerRow * tpcrow=0;
1344 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1348 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1349 left = (sec-fkNIS*2)/fkNOS;
1352 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1353 for (Int_t k=0;k<tpcrow->GetN1();++k)
1354 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1357 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1358 for (Int_t k=0;k<tpcrow->GetN2();++k)
1359 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1366 if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1371 void AliTPCtracker::UnloadClusters()
1374 // unload clusters from the memory
1376 Int_t nrows = fOuterSec->GetNRows();
1377 for (Int_t sec = 0;sec<fkNOS;sec++)
1378 for (Int_t row = 0;row<nrows;row++){
1379 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1381 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1382 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1384 tpcrow->ResetClusters();
1387 nrows = fInnerSec->GetNRows();
1388 for (Int_t sec = 0;sec<fkNIS;sec++)
1389 for (Int_t row = 0;row<nrows;row++){
1390 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1392 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1393 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1395 tpcrow->ResetClusters();
1401 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1403 // Filling cluster to the array - For visualization purposes
1406 nrows = fOuterSec->GetNRows();
1407 for (Int_t sec = 0;sec<fkNOS;sec++)
1408 for (Int_t row = 0;row<nrows;row++){
1409 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1410 if (!tpcrow) continue;
1411 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1412 array->AddLast((TObject*)((*tpcrow)[icl]));
1415 nrows = fInnerSec->GetNRows();
1416 for (Int_t sec = 0;sec<fkNIS;sec++)
1417 for (Int_t row = 0;row<nrows;row++){
1418 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1419 if (!tpcrow) continue;
1420 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1421 array->AddLast((TObject*)(*tpcrow)[icl]);
1427 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1431 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1432 AliTPCTransform *transform = calibDB->GetTransform() ;
1434 AliFatal("Tranformations not in calibDB");
1437 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1438 Double_t x[3]={cluster->GetRow(),cluster->GetPad(),cluster->GetTimeBin()};
1439 Int_t i[1]={cluster->GetDetector()};
1440 transform->Transform(x,i,0,1);
1441 // if (cluster->GetDetector()%36>17){
1446 // in debug mode check the transformation
1448 if (AliTPCReconstructor::StreamLevel()>2) {
1450 cluster->GetGlobalXYZ(gx);
1451 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1452 TTreeSRedirector &cstream = *fDebugStreamer;
1453 cstream<<"Transform"<<
1464 cluster->SetX(x[0]);
1465 cluster->SetY(x[1]);
1466 cluster->SetZ(x[2]);
1471 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1472 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1473 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1475 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1476 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1477 if (mat) mat->LocalToMaster(pos,posC);
1479 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1481 cluster->SetX(posC[0]);
1482 cluster->SetY(posC[1]);
1483 cluster->SetZ(posC[2]);
1487 void AliTPCtracker::ApplyTailCancellation(){
1489 // Correct the cluster charge for the ion tail effect
1490 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1494 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1495 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1496 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1497 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1498 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1499 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1501 // find the number of clusters for the whole TPC (nclALL)
1503 for (Int_t isector=0; isector<36; isector++){
1504 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1505 nclALL += sector.GetNClInSector(0);
1506 nclALL += sector.GetNClInSector(1);
1509 // start looping over all clusters
1510 for (Int_t iside=0; iside<2; iside++){ // loop over sides
1513 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
1514 // cache experimantal tuning factor for the different chamber type
1515 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
1516 std::cout << " ampfactor = " << ampfactor << std::endl;
1518 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
1521 // Cache time response functions and their positons to COG of the cluster
1522 TGraphErrors ** graphRes = new TGraphErrors *[20];
1523 Float_t * indexAmpGraphs = new Float_t[20];
1524 for (Int_t icache=0; icache<20; icache++)
1526 graphRes[icache] = NULL;
1527 indexAmpGraphs[icache] = 0;
1529 ///////////////////////////// --> position fo sie loop
1530 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
1535 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
1536 Int_t nrows = sector.GetNRows(); // number of rows
1537 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
1539 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1541 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1542 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1543 if (iside>0) ncl=tpcrow.GetN2();
1545 // Order clusters in time for the proper correction of ion tail
1546 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
1547 Float_t qMaxArray[ncl];
1548 Int_t sortedClusterIndex[ncl];
1549 Float_t sortedClusterTimeBin[ncl];
1550 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
1551 for (Int_t i=0;i<ncl;i++)
1555 sortedClusterIndex[i]=i;
1556 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1558 rowClusterArray->AddAt(rowcl,i);
1560 rowClusterArray->RemoveAt(i);
1562 // Fill the timebin info to the array in order to sort wrt tb
1564 sortedClusterTimeBin[i]=0.0;
1566 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
1570 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
1572 // Main cluster correction loops over clusters
1573 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
1575 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
1579 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
1581 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
1583 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
1584 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
1585 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
1587 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
1589 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
1590 Double_t ionTailMax=0.;
1591 Double_t ionTailTotal=0.;
1592 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
1593 ionTailMax=TMath::Abs(ionTailMax);
1594 ionTailTotal=TMath::Abs(ionTailTotal);
1595 qTotArray[icl0]+=ionTailTotal;
1596 qMaxArray[icl0]+=ionTailMax;
1598 // Dump some info for debugging while clusters are being corrected
1599 if (AliTPCReconstructor::StreamLevel()==1) {
1600 TTreeSRedirector &cstream = *fDebugStreamer;
1601 if (gRandom->Rndm() > 0.999){
1602 cstream<<"IonTail"<<
1603 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
1604 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
1605 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
1606 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
1609 }// dump the results to the debug streamer if in debug mode
1611 }//end of second loop over clusters
1613 // Set corrected values of the corrected cluster
1614 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
1615 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
1617 // Dump some info for debugging after clusters are corrected
1618 if (AliTPCReconstructor::StreamLevel()==1) {
1619 TTreeSRedirector &cstream = *fDebugStreamer;
1620 if (gRandom->Rndm() > 0.999){
1621 cstream<<"IonTailCorrected"<<
1622 "cl0.=" << cl0 << // cluster 0 with huge Qmax
1623 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
1624 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
1625 "nclALL=" << nclALL <<
1626 "nclSector=" << nclSector <<
1628 "nclPad=" << nclPad <<
1634 }// dump the results to the debug streamer if in debug mode
1636 }//end of first loop over cluster
1637 delete rowClusterArray;
1638 }//end of loop over rows
1639 for (int i=0; i<20; i++) delete graphRes[i];
1641 delete [] indexAmpGraphs;
1643 }//end of loop over sectors
1644 }//end of loop over IROC/OROC
1645 }// end of side loop
1647 //_____________________________________________________________________________
1648 void AliTPCtracker::GetTailValue(const Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
1651 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
1654 const Double_t kMinPRF = 0.5; // minimal PRF width
1655 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
1656 ionTailMax = 0.; // correction value to be added to Qmax of cl0
1658 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
1659 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
1660 Int_t sectorPad = cl1->GetDetector(); // sector number
1661 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
1662 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
1663 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
1664 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
1665 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
1666 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
1669 Double_t sumAmp1=0.;
1670 for (Int_t idelta =-2; idelta<=2;idelta++){
1671 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
1674 Double_t sumAmp0=0.;
1675 for (Int_t idelta =-2; idelta<=2;idelta++){
1676 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
1679 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
1680 Int_t padScan=2; // +-2 pad-timebin window will be scanned
1681 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
1684 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
1685 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
1686 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
1688 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
1690 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
1691 for (Int_t j=0;j<20;j++) {
1692 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
1694 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
1698 if (!graphRes[ampIndex]) continue;
1699 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
1700 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
1702 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
1705 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
1707 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
1708 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
1709 Float_t qMaxPad0 = amp0*qTot0;
1711 // Add 5 timebin range contribution around the max peak (-+2 tb window)
1712 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
1714 if (itb<0) continue;
1715 if (itb>=graphRes[ampIndex]->GetN()) continue;
1717 // calculate contribution to qTot
1718 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
1719 if (ipad1!=padcl0) {
1720 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
1722 ionTailTotal += tailCorr; // for center pad
1724 // calculate contribution to qMax
1725 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
1727 } // end of tb correction loop which is applied over 5 tb range
1729 } // end of cl0 loop
1730 } // end of cl1 loop
1734 //_____________________________________________________________________________
1735 Int_t AliTPCtracker::LoadOuterSectors() {
1736 //-----------------------------------------------------------------
1737 // This function fills outer TPC sectors with clusters.
1738 //-----------------------------------------------------------------
1739 Int_t nrows = fOuterSec->GetNRows();
1741 for (Int_t sec = 0;sec<fkNOS;sec++)
1742 for (Int_t row = 0;row<nrows;row++){
1743 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1744 Int_t sec2 = sec+2*fkNIS;
1746 Int_t ncl = tpcrow->GetN1();
1748 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1749 index=(((sec2<<8)+row)<<16)+ncl;
1750 tpcrow->InsertCluster(c,index);
1753 ncl = tpcrow->GetN2();
1755 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1756 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1757 tpcrow->InsertCluster(c,index);
1760 // write indexes for fast acces
1762 for (Int_t i=0;i<510;i++)
1763 tpcrow->SetFastCluster(i,-1);
1764 for (Int_t i=0;i<tpcrow->GetN();i++){
1765 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1766 tpcrow->SetFastCluster(zi,i); // write index
1769 for (Int_t i=0;i<510;i++){
1770 if (tpcrow->GetFastCluster(i)<0)
1771 tpcrow->SetFastCluster(i,last);
1773 last = tpcrow->GetFastCluster(i);
1782 //_____________________________________________________________________________
1783 Int_t AliTPCtracker::LoadInnerSectors() {
1784 //-----------------------------------------------------------------
1785 // This function fills inner TPC sectors with clusters.
1786 //-----------------------------------------------------------------
1787 Int_t nrows = fInnerSec->GetNRows();
1789 for (Int_t sec = 0;sec<fkNIS;sec++)
1790 for (Int_t row = 0;row<nrows;row++){
1791 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1794 Int_t ncl = tpcrow->GetN1();
1796 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1797 index=(((sec<<8)+row)<<16)+ncl;
1798 tpcrow->InsertCluster(c,index);
1801 ncl = tpcrow->GetN2();
1803 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1804 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1805 tpcrow->InsertCluster(c,index);
1808 // write indexes for fast acces
1810 for (Int_t i=0;i<510;i++)
1811 tpcrow->SetFastCluster(i,-1);
1812 for (Int_t i=0;i<tpcrow->GetN();i++){
1813 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1814 tpcrow->SetFastCluster(zi,i); // write index
1817 for (Int_t i=0;i<510;i++){
1818 if (tpcrow->GetFastCluster(i)<0)
1819 tpcrow->SetFastCluster(i,last);
1821 last = tpcrow->GetFastCluster(i);
1833 //_________________________________________________________________________
1834 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
1835 //--------------------------------------------------------------------
1836 // Return pointer to a given cluster
1837 //--------------------------------------------------------------------
1838 if (index<0) return 0; // no cluster
1839 Int_t sec=(index&0xff000000)>>24;
1840 Int_t row=(index&0x00ff0000)>>16;
1841 Int_t ncl=(index&0x00007fff)>>00;
1843 const AliTPCtrackerRow * tpcrow=0;
1844 TClonesArray * clrow =0;
1846 if (sec<0 || sec>=fkNIS*4) {
1847 AliWarning(Form("Wrong sector %d",sec));
1852 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
1853 if (tracksec.GetNRows()<=row) return 0;
1854 tpcrow = &(tracksec[row]);
1855 if (tpcrow==0) return 0;
1858 if (tpcrow->GetN1()<=ncl) return 0;
1859 clrow = tpcrow->GetClusters1();
1862 if (tpcrow->GetN2()<=ncl) return 0;
1863 clrow = tpcrow->GetClusters2();
1867 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
1868 if (tracksec.GetNRows()<=row) return 0;
1869 tpcrow = &(tracksec[row]);
1870 if (tpcrow==0) return 0;
1872 if (sec-2*fkNIS<fkNOS) {
1873 if (tpcrow->GetN1()<=ncl) return 0;
1874 clrow = tpcrow->GetClusters1();
1877 if (tpcrow->GetN2()<=ncl) return 0;
1878 clrow = tpcrow->GetClusters2();
1882 return (AliTPCclusterMI*)clrow->At(ncl);
1888 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
1889 //-----------------------------------------------------------------
1890 // This function tries to find a track prolongation to next pad row
1891 //-----------------------------------------------------------------
1893 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
1896 AliTPCclusterMI *cl=0;
1897 Int_t tpcindex= t.GetClusterIndex2(nr);
1899 // update current shape info every 5 pad-row
1900 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1904 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
1906 if (tpcindex==-1) return 0; //track in dead zone
1907 if (tpcindex >= 0){ //
1908 cl = t.GetClusterPointer(nr);
1909 //if (cl==0) cl = GetClusterMI(tpcindex);
1910 if (!cl) cl = GetClusterMI(tpcindex);
1911 t.SetCurrentClusterIndex1(tpcindex);
1914 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
1915 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1917 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1918 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1920 if (TMath::Abs(angle-t.GetAlpha())>0.001){
1921 Double_t rotation = angle-t.GetAlpha();
1922 t.SetRelativeSector(relativesector);
1923 if (!t.Rotate(rotation)) {
1924 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1928 if (!t.PropagateTo(x)) {
1929 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1933 t.SetCurrentCluster(cl);
1935 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1936 if ((tpcindex&0x8000)==0) accept =0;
1938 //if founded cluster is acceptible
1939 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
1940 t.SetErrorY2(t.GetErrorY2()+0.03);
1941 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1942 t.SetErrorY2(t.GetErrorY2()*3);
1943 t.SetErrorZ2(t.GetErrorZ2()*3);
1945 t.SetNFoundable(t.GetNFoundable()+1);
1946 UpdateTrack(&t,accept);
1949 else { // Remove old cluster from track
1950 t.SetClusterIndex(nr, -3);
1951 t.SetClusterPointer(nr, 0);
1955 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
1956 if (fIteration>1 && IsFindable(t)){
1957 // not look for new cluster during refitting
1958 t.SetNFoundable(t.GetNFoundable()+1);
1963 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1964 if (!t.PropagateTo(x)) {
1965 if (fIteration==0) t.SetRemoval(10);
1968 Double_t y = t.GetY();
1969 if (TMath::Abs(y)>ymax){
1971 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1972 if (!t.Rotate(fSectors->GetAlpha()))
1974 } else if (y <-ymax) {
1975 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1976 if (!t.Rotate(-fSectors->GetAlpha()))
1979 if (!t.PropagateTo(x)) {
1980 if (fIteration==0) t.SetRemoval(10);
1986 Double_t z=t.GetZ();
1989 if (!IsActive(t.GetRelativeSector(),nr)) {
1991 t.SetClusterIndex2(nr,-1);
1994 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1995 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
1996 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
1998 if (!isActive || !isActive2) return 0;
2000 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2001 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
2003 Double_t roadz = 1.;
2005 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2007 t.SetClusterIndex2(nr,-1);
2013 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2014 t.SetNFoundable(t.GetNFoundable()+1);
2020 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2021 cl = krow.FindNearest2(y,z,roady,roadz,index);
2022 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2025 t.SetCurrentCluster(cl);
2027 if (fIteration==2&&cl->IsUsed(10)) return 0;
2028 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2029 if (fIteration==2&&cl->IsUsed(11)) {
2030 t.SetErrorY2(t.GetErrorY2()+0.03);
2031 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2032 t.SetErrorY2(t.GetErrorY2()*3);
2033 t.SetErrorZ2(t.GetErrorZ2()*3);
2036 if (t.fCurrentCluster->IsUsed(10)){
2041 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2047 if (accept<3) UpdateTrack(&t,accept);
2050 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2058 //_________________________________________________________________________
2059 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2061 // Get track space point by index
2062 // return false in case the cluster doesn't exist
2063 AliTPCclusterMI *cl = GetClusterMI(index);
2064 if (!cl) return kFALSE;
2065 Int_t sector = (index&0xff000000)>>24;
2066 // Int_t row = (index&0x00ff0000)>>16;
2068 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2069 xyz[0] = cl->GetX();
2070 xyz[1] = cl->GetY();
2071 xyz[2] = cl->GetZ();
2073 fkParam->AdjustCosSin(sector,cos,sin);
2074 Float_t x = cos*xyz[0]-sin*xyz[1];
2075 Float_t y = cos*xyz[1]+sin*xyz[0];
2077 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2078 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2079 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2080 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2081 cov[0] = sin*sin*sigmaY2;
2082 cov[1] = -sin*cos*sigmaY2;
2084 cov[3] = cos*cos*sigmaY2;
2087 p.SetXYZ(x,y,xyz[2],cov);
2088 AliGeomManager::ELayerID iLayer;
2090 if (sector < fkParam->GetNInnerSector()) {
2091 iLayer = AliGeomManager::kTPC1;
2095 iLayer = AliGeomManager::kTPC2;
2096 idet = sector - fkParam->GetNInnerSector();
2098 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2099 p.SetVolumeID(volid);
2105 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2106 //-----------------------------------------------------------------
2107 // This function tries to find a track prolongation to next pad row
2108 //-----------------------------------------------------------------
2109 t.SetCurrentCluster(0);
2110 t.SetCurrentClusterIndex1(-3);
2112 Double_t xt=t.GetX();
2113 Int_t row = GetRowNumber(xt)-1;
2114 Double_t ymax= GetMaxY(nr);
2116 if (row < nr) return 1; // don't prolongate if not information until now -
2117 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2119 // return 0; // not prolongate strongly inclined tracks
2121 // if (TMath::Abs(t.GetSnp())>0.95) {
2123 // return 0; // not prolongate strongly inclined tracks
2124 // }// patch 28 fev 06
2126 Double_t x= GetXrow(nr);
2128 //t.PropagateTo(x+0.02);
2129 //t.PropagateTo(x+0.01);
2130 if (!t.PropagateTo(x)){
2137 if (TMath::Abs(y)>ymax){
2139 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2140 if (!t.Rotate(fSectors->GetAlpha()))
2142 } else if (y <-ymax) {
2143 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2144 if (!t.Rotate(-fSectors->GetAlpha()))
2147 // if (!t.PropagateTo(x)){
2154 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2156 if (!IsActive(t.GetRelativeSector(),nr)) {
2158 t.SetClusterIndex2(nr,-1);
2161 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2163 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2165 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2167 t.SetClusterIndex2(nr,-1);
2173 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2174 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2180 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2181 // t.fCurrentSigmaY = GetSigmaY(&t);
2182 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2186 AliTPCclusterMI *cl=0;
2189 Double_t roady = 1.;
2190 Double_t roadz = 1.;
2194 index = t.GetClusterIndex2(nr);
2195 if ( (index >= 0) && (index&0x8000)==0){
2196 cl = t.GetClusterPointer(nr);
2197 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2198 t.SetCurrentClusterIndex1(index);
2200 t.SetCurrentCluster(cl);
2206 // if (index<0) return 0;
2207 UInt_t uindex = TMath::Abs(index);
2210 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2211 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2214 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2215 t.SetCurrentCluster(cl);
2221 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2222 //-----------------------------------------------------------------
2223 // This function tries to find a track prolongation to next pad row
2224 //-----------------------------------------------------------------
2226 //update error according neighborhoud
2228 if (t.GetCurrentCluster()) {
2230 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2232 if (t.GetCurrentCluster()->IsUsed(10)){
2237 t.SetNShared(t.GetNShared()+1);
2238 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2243 if (fIteration>0) accept = 0;
2244 if (accept<3) UpdateTrack(&t,accept);
2248 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2249 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2251 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2259 //_____________________________________________________________________________
2260 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2261 //-----------------------------------------------------------------
2262 // This function tries to find a track prolongation.
2263 //-----------------------------------------------------------------
2264 Double_t xt=t.GetX();
2266 Double_t alpha=t.GetAlpha();
2267 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2268 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2270 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2272 Int_t first = GetRowNumber(xt);
2277 for (Int_t nr= first; nr>=rf; nr-=step) {
2279 if (t.GetKinkIndexes()[0]>0){
2280 for (Int_t i=0;i<3;i++){
2281 Int_t index = t.GetKinkIndexes()[i];
2282 if (index==0) break;
2283 if (index<0) continue;
2285 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2287 printf("PROBLEM\n");
2290 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2292 AliExternalTrackParam paramd(t);
2293 kink->SetDaughter(paramd);
2294 kink->SetStatus(2,5);
2301 if (nr==80) t.UpdateReference();
2302 if (nr<fInnerSec->GetNRows())
2303 fSectors = fInnerSec;
2305 fSectors = fOuterSec;
2306 if (FollowToNext(t,nr)==0)
2319 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2320 //-----------------------------------------------------------------
2321 // This function tries to find a track prolongation.
2322 //-----------------------------------------------------------------
2324 Double_t xt=t.GetX();
2325 Double_t alpha=t.GetAlpha();
2326 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2327 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2328 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2330 Int_t first = t.GetFirstPoint();
2331 Int_t ri = GetRowNumber(xt);
2335 if (first<ri) first = ri;
2337 if (first<0) first=0;
2338 for (Int_t nr=first; nr<=rf; nr++) {
2339 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2340 if (t.GetKinkIndexes()[0]<0){
2341 for (Int_t i=0;i<3;i++){
2342 Int_t index = t.GetKinkIndexes()[i];
2343 if (index==0) break;
2344 if (index>0) continue;
2345 index = TMath::Abs(index);
2346 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2348 printf("PROBLEM\n");
2351 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2353 AliExternalTrackParam paramm(t);
2354 kink->SetMother(paramm);
2355 kink->SetStatus(2,1);
2362 if (nr<fInnerSec->GetNRows())
2363 fSectors = fInnerSec;
2365 fSectors = fOuterSec;
2376 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2378 // overlapping factor
2384 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2387 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2389 Float_t distance = TMath::Sqrt(dz2+dy2);
2390 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2393 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2394 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2399 if (firstpoint>lastpoint) {
2400 firstpoint =lastpoint;
2405 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2406 if (s1->GetClusterIndex2(i)>0) sum1++;
2407 if (s2->GetClusterIndex2(i)>0) sum2++;
2408 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2412 if (sum<5) return 0;
2414 Float_t summin = TMath::Min(sum1+1,sum2+1);
2415 Float_t ratio = (sum+1)/Float_t(summin);
2419 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2423 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2424 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2425 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2426 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2431 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2432 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2433 Int_t firstpoint = 0;
2434 Int_t lastpoint = 160;
2436 // if (firstpoint>=lastpoint-5) return;;
2438 for (Int_t i=firstpoint;i<lastpoint;i++){
2439 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2440 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2444 if (sumshared>cutN0){
2447 for (Int_t i=firstpoint;i<lastpoint;i++){
2448 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2449 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2450 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2451 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2452 if (s1->IsActive()&&s2->IsActive()){
2453 p1->SetShared(kTRUE);
2454 p2->SetShared(kTRUE);
2460 if (sumshared>cutN0){
2461 for (Int_t i=0;i<4;i++){
2462 if (s1->GetOverlapLabel(3*i)==0){
2463 s1->SetOverlapLabel(3*i, s2->GetLabel());
2464 s1->SetOverlapLabel(3*i+1,sumshared);
2465 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2469 for (Int_t i=0;i<4;i++){
2470 if (s2->GetOverlapLabel(3*i)==0){
2471 s2->SetOverlapLabel(3*i, s1->GetLabel());
2472 s2->SetOverlapLabel(3*i+1,sumshared);
2473 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2480 void AliTPCtracker::SignShared(TObjArray * arr)
2483 //sort trackss according sectors
2485 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2486 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2488 //if (pt) RotateToLocal(pt);
2492 arr->Sort(); // sorting according relative sectors
2493 arr->Expand(arr->GetEntries());
2496 Int_t nseed=arr->GetEntriesFast();
2497 for (Int_t i=0; i<nseed; i++) {
2498 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2500 for (Int_t j=0;j<12;j++){
2501 pt->SetOverlapLabel(j,0);
2504 for (Int_t i=0; i<nseed; i++) {
2505 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2507 if (pt->GetRemoval()>10) continue;
2508 for (Int_t j=i+1; j<nseed; j++){
2509 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2510 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2512 if (pt2->GetRemoval()<=10) {
2513 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2521 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
2524 //sort tracks in array according mode criteria
2525 Int_t nseed = arr->GetEntriesFast();
2526 for (Int_t i=0; i<nseed; i++) {
2527 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2538 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
2541 // Loop over all tracks and remove overlaped tracks (with lower quality)
2543 // 1. Unsign clusters
2544 // 2. Sort tracks according quality
2545 // Quality is defined by the number of cluster between first and last points
2547 // 3. Loop over tracks - decreasing quality order
2548 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
2549 // b.) remove - If the minimal number of clusters less than minimal and not ITS
2550 // c.) if track accepted - sign clusters
2552 //Called in - AliTPCtracker::Clusters2Tracks()
2553 // - AliTPCtracker::PropagateBack()
2554 // - AliTPCtracker::RefitInward()
2557 // factor1 - factor for constrained
2558 // factor2 - for non constrained tracks
2559 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
2563 Int_t nseed = arr->GetEntriesFast();
2564 Float_t * quality = new Float_t[nseed];
2565 Int_t * indexes = new Int_t[nseed];
2569 for (Int_t i=0; i<nseed; i++) {
2570 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2575 pt->UpdatePoints(); //select first last max dens points
2576 Float_t * points = pt->GetPoints();
2577 if (points[3]<0.8) quality[i] =-1;
2578 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2579 //prefer high momenta tracks if overlaps
2580 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
2582 TMath::Sort(nseed,quality,indexes);
2585 for (Int_t itrack=0; itrack<nseed; itrack++) {
2586 Int_t trackindex = indexes[itrack];
2587 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
2590 if (quality[trackindex]<0){
2591 MarkSeedFree( arr->RemoveAt(trackindex) );
2596 Int_t first = Int_t(pt->GetPoints()[0]);
2597 Int_t last = Int_t(pt->GetPoints()[2]);
2598 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2600 Int_t found,foundable,shared;
2601 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
2602 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2603 Bool_t itsgold =kFALSE;
2606 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2610 if (Float_t(shared+1)/Float_t(found+1)>factor){
2611 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2612 if( AliTPCReconstructor::StreamLevel()>3){
2613 TTreeSRedirector &cstream = *fDebugStreamer;
2614 cstream<<"RemoveUsed"<<
2615 "iter="<<fIteration<<
2619 MarkSeedFree( arr->RemoveAt(trackindex) );
2622 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
2623 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2624 if( AliTPCReconstructor::StreamLevel()>3){
2625 TTreeSRedirector &cstream = *fDebugStreamer;
2626 cstream<<"RemoveShort"<<
2627 "iter="<<fIteration<<
2631 MarkSeedFree( arr->RemoveAt(trackindex) );
2637 //if (sharedfactor>0.4) continue;
2638 if (pt->GetKinkIndexes()[0]>0) continue;
2639 //Remove tracks with undefined properties - seems
2640 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
2642 for (Int_t i=first; i<last; i++) {
2643 Int_t index=pt->GetClusterIndex2(i);
2644 // if (index<0 || index&0x8000 ) continue;
2645 if (index<0 || index&0x8000 ) continue;
2646 AliTPCclusterMI *c= pt->GetClusterPointer(i);
2653 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2659 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
2662 // Dump clusters after reco
2663 // signed and unsigned cluster can be visualized
2664 // 1. Unsign all cluster
2665 // 2. Sign all used clusters
2668 Int_t nseed = trackArray->GetEntries();
2669 for (Int_t i=0; i<nseed; i++){
2670 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
2674 Bool_t isKink=pt->GetKinkIndex(0)!=0;
2675 for (Int_t j=0; j<160; ++j) {
2676 Int_t index=pt->GetClusterIndex2(j);
2677 if (index<0) continue;
2678 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2680 if (isKink) c->Use(100); // kink
2681 c->Use(10); // by default usage 10
2686 for (Int_t sec=0;sec<fkNIS;sec++){
2687 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2688 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2689 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
2690 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2691 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2692 (*fDebugStreamer)<<"clDump"<<
2700 cla = fInnerSec[sec][row].GetClusters2();
2701 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
2702 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2703 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2704 (*fDebugStreamer)<<"clDump"<<
2715 for (Int_t sec=0;sec<fkNOS;sec++){
2716 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2717 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2718 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
2720 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2721 cl->GetGlobalXYZ(gx);
2722 (*fDebugStreamer)<<"clDump"<<
2730 cla = fOuterSec[sec][row].GetClusters2();
2731 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
2733 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2734 cl->GetGlobalXYZ(gx);
2735 (*fDebugStreamer)<<"clDump"<<
2747 void AliTPCtracker::UnsignClusters()
2750 // loop over all clusters and unsign them
2753 for (Int_t sec=0;sec<fkNIS;sec++){
2754 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2755 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2756 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2757 // if (cl[icl].IsUsed(10))
2758 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2759 cla = fInnerSec[sec][row].GetClusters2();
2760 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2761 //if (cl[icl].IsUsed(10))
2762 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2766 for (Int_t sec=0;sec<fkNOS;sec++){
2767 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2768 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2769 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2770 //if (cl[icl].IsUsed(10))
2771 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2772 cla = fOuterSec[sec][row].GetClusters2();
2773 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2774 //if (cl[icl].IsUsed(10))
2775 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2783 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
2786 //sign clusters to be "used"
2788 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2789 // loop over "primaries"
2803 Int_t nseed = arr->GetEntriesFast();
2804 for (Int_t i=0; i<nseed; i++) {
2805 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2809 if (!(pt->IsActive())) continue;
2810 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2811 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2813 sumdens2+= dens*dens;
2814 sumn += pt->GetNumberOfClusters();
2815 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2816 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2819 sumchi2 +=chi2*chi2;
2824 Float_t mdensity = 0.9;
2825 Float_t meann = 130;
2826 Float_t meanchi = 1;
2827 Float_t sdensity = 0.1;
2828 Float_t smeann = 10;
2829 Float_t smeanchi =0.4;
2833 mdensity = sumdens/sum;
2835 meanchi = sumchi/sum;
2837 sdensity = sumdens2/sum-mdensity*mdensity;
2839 sdensity = TMath::Sqrt(sdensity);
2843 smeann = sumn2/sum-meann*meann;
2845 smeann = TMath::Sqrt(smeann);
2849 smeanchi = sumchi2/sum - meanchi*meanchi;
2851 smeanchi = TMath::Sqrt(smeanchi);
2857 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
2859 for (Int_t i=0; i<nseed; i++) {
2860 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2864 if (pt->GetBSigned()) continue;
2865 if (pt->GetBConstrain()) continue;
2866 //if (!(pt->IsActive())) continue;
2868 Int_t found,foundable,shared;
2869 pt->GetClusterStatistic(0,160,found, foundable,shared);
2870 if (shared/float(found)>0.3) {
2871 if (shared/float(found)>0.9 ){
2872 //MarkSeedFree( arr->RemoveAt(i) );
2877 Bool_t isok =kFALSE;
2878 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2880 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2882 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2884 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2888 for (Int_t j=0; j<160; ++j) {
2889 Int_t index=pt->GetClusterIndex2(j);
2890 if (index<0) continue;
2891 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2893 //if (!(c->IsUsed(10))) c->Use();
2900 Double_t maxchi = meanchi+2.*smeanchi;
2902 for (Int_t i=0; i<nseed; i++) {
2903 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2907 //if (!(pt->IsActive())) continue;
2908 if (pt->GetBSigned()) continue;
2909 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
2910 if (chi>maxchi) continue;
2913 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2915 //sign only tracks with enoug big density at the beginning
2917 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
2920 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2921 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2923 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2924 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2927 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2928 //Int_t noc=pt->GetNumberOfClusters();
2929 pt->SetBSigned(kTRUE);
2930 for (Int_t j=0; j<160; ++j) {
2932 Int_t index=pt->GetClusterIndex2(j);
2933 if (index<0) continue;
2934 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2936 // if (!(c->IsUsed(10))) c->Use();
2941 // gLastCheck = nseed;
2950 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
2953 // back propagation of ESD tracks
2956 if (!event) return 0;
2957 const Int_t kMaxFriendTracks=2000;
2960 // extract correction object for multiplicity dependence of dEdx
2961 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
2963 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
2965 AliFatal("Tranformations not in RefitInward");
2968 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
2969 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
2970 Int_t nContribut = event->GetNumberOfTracks();
2971 TGraphErrors * graphMultDependenceDeDx = 0x0;
2972 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
2973 if (recoParam->GetUseTotCharge()) {
2974 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2976 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2982 //PrepareForProlongation(fSeeds,1);
2983 PropagateForward2(fSeeds);
2984 RemoveUsed2(fSeeds,0.4,0.4,20);
2986 Int_t entriesSeed=fSeeds->GetEntries();
2987 TObjArray arraySeed(entriesSeed);
2988 for (Int_t i=0;i<entriesSeed;i++) {
2989 arraySeed.AddAt(fSeeds->At(i),i);
2991 SignShared(&arraySeed);
2992 // FindCurling(fSeeds, event,2); // find multi found tracks
2993 FindSplitted(fSeeds, event,2); // find multi found tracks
2994 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,2); // find multi found tracks
2997 Int_t nseed = fSeeds->GetEntriesFast();
2998 for (Int_t i=0;i<nseed;i++){
2999 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3000 if (!seed) continue;
3001 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
3002 AliESDtrack *esd=event->GetTrack(i);
3004 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3005 AliExternalTrackParam paramIn;
3006 AliExternalTrackParam paramOut;
3007 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3008 if (AliTPCReconstructor::StreamLevel()>2) {
3009 (*fDebugStreamer)<<"RecoverIn"<<
3013 "pout.="<<¶mOut<<
3018 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3019 seed->SetNumberOfClusters(ncl);
3023 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3024 seed->UpdatePoints();
3025 AddCovariance(seed);
3026 MakeESDBitmaps(seed, esd);
3027 seed->CookdEdx(0.02,0.6);
3028 CookLabel(seed,0.1); //For comparison only
3030 if (AliTPCReconstructor::StreamLevel()>1 && seed!=0) {
3031 TTreeSRedirector &cstream = *fDebugStreamer;
3038 if (seed->GetNumberOfClusters()>15){
3039 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3040 esd->SetTPCPoints(seed->GetPoints());
3041 esd->SetTPCPointsF(seed->GetNFoundable());
3042 Int_t ndedx = seed->GetNCDEDX(0);
3043 Float_t sdedx = seed->GetSDEDX(0);
3044 Float_t dedx = seed->GetdEdx();
3045 // apply mutliplicity dependent dEdx correction if available
3046 if (graphMultDependenceDeDx) {
3047 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3048 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3050 esd->SetTPCsignal(dedx, sdedx, ndedx);
3052 // fill new dEdx information
3054 Double32_t signal[4];
3055 Double32_t signalMax[4];
3059 for(Int_t iarr=0;iarr<3;iarr++) {
3060 signal[iarr] = seed->GetDEDXregion(iarr+1);
3061 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3062 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3063 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3065 signal[3] = seed->GetDEDXregion(4);
3066 signalMax[3] = seed->GetDEDXregion(8);
3069 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3070 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3071 infoTpcPid->SetTPCSignalsQmax(signalMax);
3072 esd->SetTPCdEdxInfo(infoTpcPid);
3074 // add seed to the esd track in Calib level
3076 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3077 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3078 // RS: this is the only place where the seed is created not in the pool,
3079 // since it should belong to ESDevent
3080 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3081 esd->AddCalibObject(seedCopy);
3086 //printf("problem\n");
3089 //FindKinks(fSeeds,event);
3090 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(2,fSeeds);
3091 Info("RefitInward","Number of refitted tracks %d",ntracks);
3093 AliCosmicTracker::FindCosmic(event, kTRUE);
3095 FillClusterOccupancyInfo();
3101 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3104 // back propagation of ESD tracks
3106 if (!event) return 0;
3111 PropagateBack(fSeeds);
3112 RemoveUsed2(fSeeds,0.4,0.4,20);
3113 //FindCurling(fSeeds, fEvent,1);
3114 FindSplitted(fSeeds, event,1); // find multi found tracks
3115 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3118 Int_t nseed = fSeeds->GetEntriesFast();
3120 for (Int_t i=0;i<nseed;i++){
3121 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3122 if (!seed) continue;
3123 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3124 seed->UpdatePoints();
3125 AddCovariance(seed);
3126 AliESDtrack *esd=event->GetTrack(i);
3127 if (!esd) continue; //never happen
3128 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3129 AliExternalTrackParam paramIn;
3130 AliExternalTrackParam paramOut;
3131 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3132 if (AliTPCReconstructor::StreamLevel()>2) {
3133 (*fDebugStreamer)<<"RecoverBack"<<
3137 "pout.="<<¶mOut<<
3142 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3143 seed->SetNumberOfClusters(ncl);
3146 seed->CookdEdx(0.02,0.6);
3147 CookLabel(seed,0.1); //For comparison only
3148 if (seed->GetNumberOfClusters()>15){
3149 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3150 esd->SetTPCPoints(seed->GetPoints());
3151 esd->SetTPCPointsF(seed->GetNFoundable());
3152 Int_t ndedx = seed->GetNCDEDX(0);
3153 Float_t sdedx = seed->GetSDEDX(0);
3154 Float_t dedx = seed->GetdEdx();
3155 esd->SetTPCsignal(dedx, sdedx, ndedx);
3157 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3158 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3159 if (AliTPCReconstructor::StreamLevel()>1 && esd) {
3160 (*fDebugStreamer)<<"Cback"<<
3163 "EventNrInFile="<<eventnumber<<
3168 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(1,fSeeds);
3169 //FindKinks(fSeeds,event);
3170 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3178 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3181 // Post process events
3183 if (!event) return 0;
3186 // Set TPC event status
3189 // event affected by HV dip
3191 if(IsTPCHVDipEvent(event)) {
3192 event->ResetDetectorStatus(AliDAQ::kTPC);
3195 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3201 void AliTPCtracker::DeleteSeeds()
3210 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3213 //read seeds from the event
3215 Int_t nentr=event->GetNumberOfTracks();
3217 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3222 fSeeds = new TObjArray(nentr);
3226 for (Int_t i=0; i<nentr; i++) {
3227 AliESDtrack *esd=event->GetTrack(i);
3228 ULong_t status=esd->GetStatus();
3229 if (!(status&AliESDtrack::kTPCin)) continue;
3230 AliTPCtrack t(*esd);
3231 t.SetNumberOfClusters(0);
3232 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3233 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3234 seed->SetPoolID(fLastSeedID);
3235 seed->SetUniqueID(esd->GetID());
3236 AddCovariance(seed); //add systematic ucertainty
3237 for (Int_t ikink=0;ikink<3;ikink++) {
3238 Int_t index = esd->GetKinkIndex(ikink);
3239 seed->GetKinkIndexes()[ikink] = index;
3240 if (index==0) continue;
3241 index = TMath::Abs(index);
3242 AliESDkink * kink = fEvent->GetKink(index-1);
3243 if (kink&&esd->GetKinkIndex(ikink)<0){
3244 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3245 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3247 if (kink&&esd->GetKinkIndex(ikink)>0){
3248 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3249 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3253 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3254 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3255 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3256 // fSeeds->AddAt(0,i);
3257 // MarkSeedFree( seed );
3263 // rotate to the local coordinate system
3265 fSectors=fInnerSec; fN=fkNIS;
3266 Double_t alpha=seed->GetAlpha();
3267 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3268 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3269 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3270 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3271 alpha-=seed->GetAlpha();
3272 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3273 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3274 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3275 AliWarning(Form("Rotating track over %f",alpha));
3276 if (!seed->Rotate(alpha)) {
3277 MarkSeedFree( seed );
3283 if (esd->GetKinkIndex(0)<=0){
3284 for (Int_t irow=0;irow<160;irow++){
3285 Int_t index = seed->GetClusterIndex2(irow);
3288 AliTPCclusterMI * cl = GetClusterMI(index);
3289 seed->SetClusterPointer(irow,cl);
3291 if ((index & 0x8000)==0){
3292 cl->Use(10); // accepted cluster
3294 cl->Use(6); // close cluster not accepted
3297 Info("ReadSeeds","Not found cluster");
3302 fSeeds->AddAt(seed,i);
3308 //_____________________________________________________________________________
3309 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3310 Float_t deltay, Int_t ddsec) {
3311 //-----------------------------------------------------------------
3312 // This function creates track seeds.
3313 // SEEDING WITH VERTEX CONSTRAIN
3314 //-----------------------------------------------------------------
3315 // cuts[0] - fP4 cut
3316 // cuts[1] - tan(phi) cut
3317 // cuts[2] - zvertex cut
3318 // cuts[3] - fP3 cut
3326 Double_t x[5], c[15];
3327 // Int_t di = i1-i2;
3329 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3330 seed->SetPoolID(fLastSeedID);
3331 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3332 Double_t cs=cos(alpha), sn=sin(alpha);
3334 // Double_t x1 =fOuterSec->GetX(i1);
3335 //Double_t xx2=fOuterSec->GetX(i2);
3337 Double_t x1 =GetXrow(i1);
3338 Double_t xx2=GetXrow(i2);
3340 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3342 Int_t imiddle = (i2+i1)/2; //middle pad row index
3343 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3344 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3348 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3349 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3350 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3353 // change cut on curvature if it can't reach this layer
3354 // maximal curvature set to reach it
3355 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3356 if (dvertexmax*0.5*cuts[0]>0.85){
3357 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3359 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3362 if (deltay>0) ddsec = 0;
3363 // loop over clusters
3364 for (Int_t is=0; is < kr1; is++) {
3366 if (kr1[is]->IsUsed(10)) continue;
3367 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3368 //if (TMath::Abs(y1)>ymax) continue;
3370 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3372 // find possible directions
3373 Float_t anglez = (z1-z3)/(x1-x3);
3374 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3377 //find rotation angles relative to line given by vertex and point 1
3378 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3379 Double_t dvertex = TMath::Sqrt(dvertex2);
3380 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3381 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3384 // loop over 2 sectors
3390 Double_t dddz1=0; // direction of delta inclination in z axis
3397 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3398 Int_t sec2 = sec + dsec;
3400 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3401 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3402 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3403 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3404 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3405 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3407 // rotation angles to p1-p3
3408 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3409 Double_t x2, y2, z2;
3411 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3414 Double_t dxx0 = (xx2-x3)*cs13r;
3415 Double_t dyy0 = (xx2-x3)*sn13r;
3416 for (Int_t js=index1; js < index2; js++) {
3417 const AliTPCclusterMI *kcl = kr2[js];
3418 if (kcl->IsUsed(10)) continue;
3420 //calcutate parameters
3422 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3424 if (TMath::Abs(yy0)<0.000001) continue;
3425 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3426 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3427 Double_t r02 = (0.25+y0*y0)*dvertex2;
3428 //curvature (radius) cut
3429 if (r02<r2min) continue;
3433 Double_t c0 = 1/TMath::Sqrt(r02);
3437 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3438 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3439 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3440 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3443 Double_t z0 = kcl->GetZ();
3444 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3445 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3448 Double_t dip = (z1-z0)*c0/dfi1;
3449 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3460 x2= xx2*cs-y2*sn*dsec;
3461 y2=+xx2*sn*dsec+y2*cs;
3471 // do we have cluster at the middle ?
3473 GetProlongation(x1,xm,x,ym,zm);
3475 AliTPCclusterMI * cm=0;
3476 if (TMath::Abs(ym)-ymaxm<0){
3477 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3478 if ((!cm) || (cm->IsUsed(10))) {
3483 // rotate y1 to system 0
3484 // get state vector in rotated system
3485 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3486 Double_t xr2 = x0*cs+yr1*sn*dsec;
3487 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3489 GetProlongation(xx2,xm,xr,ym,zm);
3490 if (TMath::Abs(ym)-ymaxm<0){
3491 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3492 if ((!cm) || (cm->IsUsed(10))) {
3499 // Double_t dym = 0;
3500 // Double_t dzm = 0;
3502 // dym = ym - cm->GetY();
3503 // dzm = zm - cm->GetZ();
3510 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3511 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
3512 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3513 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3514 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3516 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3517 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3518 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3519 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3520 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3521 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3523 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3524 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3525 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3526 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3530 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3531 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3532 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3533 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3534 c[13]=f30*sy1*f40+f32*sy2*f42;
3535 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3537 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3539 UInt_t index=kr1.GetIndex(is);
3540 if (seed) {MarkSeedFree(seed); seed = 0;}
3541 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3542 seed->SetPoolID(fLastSeedID);
3543 track->SetIsSeeding(kTRUE);
3544 track->SetSeed1(i1);
3545 track->SetSeed2(i2);
3546 track->SetSeedType(3);
3550 FollowProlongation(*track, (i1+i2)/2,1);
3551 Int_t foundable,found,shared;
3552 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3553 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3554 MarkSeedFree(seed); seed = 0;
3560 FollowProlongation(*track, i2,1);
3564 track->SetBConstrain(1);
3565 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
3566 track->SetLastPoint(i1); // first cluster in track position
3567 track->SetFirstPoint(track->GetLastPoint());
3569 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3570 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3571 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3572 MarkSeedFree(seed); seed = 0;
3576 // Z VERTEX CONDITION
3577 Double_t zv, bz=GetBz();
3578 if ( !track->GetZAt(0.,bz,zv) ) continue;
3579 if (TMath::Abs(zv-z3)>cuts[2]) {
3580 FollowProlongation(*track, TMath::Max(i2-20,0));
3581 if ( !track->GetZAt(0.,bz,zv) ) continue;
3582 if (TMath::Abs(zv-z3)>cuts[2]){
3583 FollowProlongation(*track, TMath::Max(i2-40,0));
3584 if ( !track->GetZAt(0.,bz,zv) ) continue;
3585 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3586 // make seed without constrain
3587 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3588 FollowProlongation(*track2, i2,1);
3589 track2->SetBConstrain(kFALSE);
3590 track2->SetSeedType(1);
3591 arr->AddLast(track2);
3592 MarkSeedFree( seed ); seed = 0;
3596 MarkSeedFree( seed ); seed = 0;
3603 track->SetSeedType(0);
3604 arr->AddLast(track); // note, track is seed, don't free the seed
3605 seed = new( NextFreeSeed() ) AliTPCseed;
3606 seed->SetPoolID(fLastSeedID);
3608 // don't consider other combinations
3609 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3615 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3617 if (seed) MarkSeedFree( seed );
3621 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3626 //-----------------------------------------------------------------
3627 // This function creates track seeds.
3628 //-----------------------------------------------------------------
3629 // cuts[0] - fP4 cut
3630 // cuts[1] - tan(phi) cut
3631 // cuts[2] - zvertex cut
3632 // cuts[3] - fP3 cut
3642 Double_t x[5], c[15];
3644 // make temporary seed
3645 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3646 seed->SetPoolID(fLastSeedID);
3647 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3648 // Double_t cs=cos(alpha), sn=sin(alpha);
3653 Double_t x1 = GetXrow(i1-1);
3654 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3655 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
3657 Double_t x1p = GetXrow(i1);
3658 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3660 Double_t x1m = GetXrow(i1-2);
3661 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3664 //last 3 padrow for seeding
3665 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
3666 Double_t x3 = GetXrow(i1-7);
3667 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
3669 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
3670 Double_t x3p = GetXrow(i1-6);
3672 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
3673 Double_t x3m = GetXrow(i1-8);
3678 Int_t im = i1-4; //middle pad row index
3679 Double_t xm = GetXrow(im); // radius of middle pad-row
3680 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
3681 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
3684 Double_t deltax = x1-x3;
3685 Double_t dymax = deltax*cuts[1];
3686 Double_t dzmax = deltax*cuts[3];
3688 // loop over clusters
3689 for (Int_t is=0; is < kr1; is++) {
3691 if (kr1[is]->IsUsed(10)) continue;
3692 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3694 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3696 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3697 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3703 for (Int_t js=index1; js < index2; js++) {
3704 const AliTPCclusterMI *kcl = kr3[js];
3705 if (kcl->IsUsed(10)) continue;
3707 // apply angular cuts
3708 if (TMath::Abs(y1-y3)>dymax) continue;
3711 if (TMath::Abs(z1-z3)>dzmax) continue;
3713 Double_t angley = (y1-y3)/(x1-x3);
3714 Double_t anglez = (z1-z3)/(x1-x3);
3716 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3717 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3719 Double_t yyym = angley*(xm-x1)+y1;
3720 Double_t zzzm = anglez*(xm-x1)+z1;
3722 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3724 if (kcm->IsUsed(10)) continue;
3726 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3727 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3734 // look around first
3735 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3741 if (kc1m->IsUsed(10)) used++;
3743 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3749 if (kc1p->IsUsed(10)) used++;
3751 if (used>1) continue;
3752 if (found<1) continue;
3756 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3762 if (kc3m->IsUsed(10)) used++;
3766 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3772 if (kc3p->IsUsed(10)) used++;
3776 if (used>1) continue;
3777 if (found<3) continue;
3787 x[4]=F1(x1,y1,x2,y2,x3,y3);
3788 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3791 x[2]=F2(x1,y1,x2,y2,x3,y3);
3794 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3795 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3799 Double_t sy1=0.1, sz1=0.1;
3800 Double_t sy2=0.1, sz2=0.1;
3801 Double_t sy3=0.1, sy=0.1, sz=0.1;
3803 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3804 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3805 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3806 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3807 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3808 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3810 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3811 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3812 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3813 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3817 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3818 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3819 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3820 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3821 c[13]=f30*sy1*f40+f32*sy2*f42;
3822 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3824 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3826 index=kr1.GetIndex(is);
3827 if (seed) {MarkSeedFree( seed ); seed = 0;}
3828 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3829 seed->SetPoolID(fLastSeedID);
3831 track->SetIsSeeding(kTRUE);
3834 FollowProlongation(*track, i1-7,1);
3835 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
3836 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3837 MarkSeedFree( seed ); seed = 0;
3843 FollowProlongation(*track, i2,1);
3844 track->SetBConstrain(0);
3845 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
3846 track->SetFirstPoint(track->GetLastPoint());
3848 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3849 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
3850 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3851 MarkSeedFree( seed ); seed = 0;
3856 FollowProlongation(*track, TMath::Max(i2-10,0),1);
3857 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3858 FollowProlongation(*track2, i2,1);
3859 track2->SetBConstrain(kFALSE);
3860 track2->SetSeedType(4);
3861 arr->AddLast(track2);
3862 MarkSeedFree( seed ); seed = 0;
3866 //arr->AddLast(track);
3867 //seed = new AliTPCseed;
3873 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);
3875 if (seed) MarkSeedFree(seed);
3879 //_____________________________________________________________________________
3880 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3881 Float_t deltay, Bool_t /*bconstrain*/) {
3882 //-----------------------------------------------------------------
3883 // This function creates track seeds - without vertex constraint
3884 //-----------------------------------------------------------------
3885 // cuts[0] - fP4 cut - not applied
3886 // cuts[1] - tan(phi) cut
3887 // cuts[2] - zvertex cut - not applied
3888 // cuts[3] - fP3 cut
3898 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3899 // Double_t cs=cos(alpha), sn=sin(alpha);
3900 Int_t row0 = (i1+i2)/2;
3901 Int_t drow = (i1-i2)/2;
3902 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3903 AliTPCtrackerRow * kr=0;
3905 AliTPCpolyTrack polytrack;
3906 Int_t nclusters=fSectors[sec][row0];
3907 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3908 seed->SetPoolID(fLastSeedID);
3913 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
3915 Int_t nfoundable =0;
3916 for (Int_t iter =1; iter<2; iter++){ //iterations
3917 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3918 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
3919 const AliTPCclusterMI * cl= kr0[is];
3921 if (cl->IsUsed(10)) {
3927 Double_t x = kr0.GetX();
3928 // Initialization of the polytrack
3933 Double_t y0= cl->GetY();
3934 Double_t z0= cl->GetZ();
3938 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3939 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
3941 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
3942 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
3943 polytrack.AddPoint(x,y0,z0,erry, errz);
3946 if (cl->IsUsed(10)) sumused++;
3949 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3950 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3953 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3954 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3955 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
3956 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3957 if (cl1->IsUsed(10)) sumused++;
3958 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3962 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3964 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
3965 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3966 if (cl2->IsUsed(10)) sumused++;
3967 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3970 if (sumused>0) continue;
3972 polytrack.UpdateParameters();
3978 nfoundable = polytrack.GetN();
3979 nfound = nfoundable;
3981 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3982 Float_t maxdist = 0.8*(1.+3./(ddrow));
3983 for (Int_t delta = -1;delta<=1;delta+=2){
3984 Int_t row = row0+ddrow*delta;
3985 kr = &(fSectors[sec][row]);
3986 Double_t xn = kr->GetX();
3987 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3988 polytrack.GetFitPoint(xn,yn,zn);
3989 if (TMath::Abs(yn)>ymax1) continue;
3991 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3993 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3996 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3997 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3998 if (cln->IsUsed(10)) {
3999 // printf("used\n");
4007 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4012 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4013 polytrack.UpdateParameters();
4016 if ( (sumused>3) || (sumused>0.5*nfound)) {
4017 //printf("sumused %d\n",sumused);
4022 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4023 AliTPCpolyTrack track2;
4025 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4026 if (track2.GetN()<0.5*nfoundable) continue;
4029 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4031 // test seed with and without constrain
4032 for (Int_t constrain=0; constrain<=0;constrain++){
4033 // add polytrack candidate
4035 Double_t x[5], c[15];
4036 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4037 track2.GetBoundaries(x3,x1);
4039 track2.GetFitPoint(x1,y1,z1);
4040 track2.GetFitPoint(x2,y2,z2);
4041 track2.GetFitPoint(x3,y3,z3);
4043 //is track pointing to the vertex ?
4046 polytrack.GetFitPoint(x0,y0,z0);
4059 x[4]=F1(x1,y1,x2,y2,x3,y3);
4061 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4062 x[2]=F2(x1,y1,x2,y2,x3,y3);
4064 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4065 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4066 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4067 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4070 Double_t sy =0.1, sz =0.1;
4071 Double_t sy1=0.02, sz1=0.02;
4072 Double_t sy2=0.02, sz2=0.02;
4076 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4079 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4080 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4081 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4082 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4083 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4084 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4086 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4087 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4088 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4089 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4094 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4095 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4096 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4097 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4098 c[13]=f30*sy1*f40+f32*sy2*f42;
4099 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4101 //Int_t row1 = fSectors->GetRowNumber(x1);
4102 Int_t row1 = GetRowNumber(x1);
4106 if (seed) {MarkSeedFree( seed ); seed = 0;}
4107 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4108 seed->SetPoolID(fLastSeedID);
4109 track->SetIsSeeding(kTRUE);
4110 Int_t rc=FollowProlongation(*track, i2);
4111 if (constrain) track->SetBConstrain(1);
4113 track->SetBConstrain(0);
4114 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4115 track->SetFirstPoint(track->GetLastPoint());
4117 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4118 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4119 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4120 MarkSeedFree( seed ); seed = 0;
4123 arr->AddLast(track); // track IS seed, don't free seed
4124 seed = new( NextFreeSeed() ) AliTPCseed;
4125 seed->SetPoolID(fLastSeedID);
4129 } // if accepted seed
4132 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4134 if (seed) MarkSeedFree( seed );
4138 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4142 //reseed using track points
4143 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4144 Int_t p1 = int(r1*track->GetNumberOfClusters());
4145 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4147 Double_t x0[3],x1[3],x2[3];
4148 for (Int_t i=0;i<3;i++){
4154 // find track position at given ratio of the length
4155 Int_t sec0=0, sec1=0, sec2=0;
4158 for (Int_t i=0;i<160;i++){
4159 if (track->GetClusterPointer(i)){
4161 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4162 if ( (index<p0) || x0[0]<0 ){
4163 if (trpoint->GetX()>1){
4164 clindex = track->GetClusterIndex2(i);
4166 x0[0] = trpoint->GetX();
4167 x0[1] = trpoint->GetY();
4168 x0[2] = trpoint->GetZ();
4169 sec0 = ((clindex&0xff000000)>>24)%18;
4174 if ( (index<p1) &&(trpoint->GetX()>1)){
4175 clindex = track->GetClusterIndex2(i);
4177 x1[0] = trpoint->GetX();
4178 x1[1] = trpoint->GetY();
4179 x1[2] = trpoint->GetZ();
4180 sec1 = ((clindex&0xff000000)>>24)%18;
4183 if ( (index<p2) &&(trpoint->GetX()>1)){
4184 clindex = track->GetClusterIndex2(i);
4186 x2[0] = trpoint->GetX();
4187 x2[1] = trpoint->GetY();
4188 x2[2] = trpoint->GetZ();
4189 sec2 = ((clindex&0xff000000)>>24)%18;
4196 Double_t alpha, cs,sn, xx2,yy2;
4198 alpha = (sec1-sec2)*fSectors->GetAlpha();
4199 cs = TMath::Cos(alpha);
4200 sn = TMath::Sin(alpha);
4201 xx2= x1[0]*cs-x1[1]*sn;
4202 yy2= x1[0]*sn+x1[1]*cs;
4206 alpha = (sec0-sec2)*fSectors->GetAlpha();
4207 cs = TMath::Cos(alpha);
4208 sn = TMath::Sin(alpha);
4209 xx2= x0[0]*cs-x0[1]*sn;
4210 yy2= x0[0]*sn+x0[1]*cs;
4216 Double_t x[5],c[15];
4220 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4221 // if (x[4]>1) return 0;
4222 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4223 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4224 //if (TMath::Abs(x[3]) > 2.2) return 0;
4225 //if (TMath::Abs(x[2]) > 1.99) return 0;
4227 Double_t sy =0.1, sz =0.1;
4229 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4230 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4231 Double_t sy3=0.01+track->GetSigmaY2();
4233 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4234 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4235 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4236 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4237 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4238 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4240 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4241 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4242 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4243 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4248 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4249 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4250 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4251 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4252 c[13]=f30*sy1*f40+f32*sy2*f42;
4253 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4255 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4256 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4257 seed->SetPoolID(fLastSeedID);
4258 // Double_t y0,z0,y1,z1, y2,z2;
4259 //seed->GetProlongation(x0[0],y0,z0);
4260 // seed->GetProlongation(x1[0],y1,z1);
4261 //seed->GetProlongation(x2[0],y2,z2);
4263 seed->SetLastPoint(pp2);
4264 seed->SetFirstPoint(pp2);
4271 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4275 //reseed using founded clusters
4277 // Find the number of clusters
4278 Int_t nclusters = 0;
4279 for (Int_t irow=0;irow<160;irow++){
4280 if (track->GetClusterIndex(irow)>0) nclusters++;
4284 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4285 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4286 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4289 Double_t xyz[3][3]={{0}};
4290 Int_t row[3]={0},sec[3]={0,0,0};
4292 // find track row position at given ratio of the length
4294 for (Int_t irow=0;irow<160;irow++){
4295 if (track->GetClusterIndex2(irow)<0) continue;
4297 for (Int_t ipoint=0;ipoint<3;ipoint++){
4298 if (index<=ipos[ipoint]) row[ipoint] = irow;
4302 //Get cluster and sector position
4303 for (Int_t ipoint=0;ipoint<3;ipoint++){
4304 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4305 AliTPCclusterMI * cl = GetClusterMI(clindex);
4308 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4311 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4312 xyz[ipoint][0] = GetXrow(row[ipoint]);
4313 xyz[ipoint][1] = cl->GetY();
4314 xyz[ipoint][2] = cl->GetZ();
4318 // Calculate seed state vector and covariance matrix
4320 Double_t alpha, cs,sn, xx2,yy2;
4322 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4323 cs = TMath::Cos(alpha);
4324 sn = TMath::Sin(alpha);
4325 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4326 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4330 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4331 cs = TMath::Cos(alpha);
4332 sn = TMath::Sin(alpha);
4333 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4334 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4340 Double_t x[5],c[15];
4344 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4345 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4346 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4348 Double_t sy =0.1, sz =0.1;
4350 Double_t sy1=0.2, sz1=0.2;
4351 Double_t sy2=0.2, sz2=0.2;
4354 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;
4355 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;
4356 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;
4357 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;
4358 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;
4359 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;
4361 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;
4362 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;
4363 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;
4364 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;
4369 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4370 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4371 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4372 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4373 c[13]=f30*sy1*f40+f32*sy2*f42;
4374 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4376 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4377 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4378 seed->SetPoolID(fLastSeedID);
4379 seed->SetLastPoint(row[2]);
4380 seed->SetFirstPoint(row[2]);
4385 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4389 //reseed using founded clusters
4392 Int_t row[3]={0,0,0};
4393 Int_t sec[3]={0,0,0};
4395 // forward direction
4397 for (Int_t irow=r0;irow<160;irow++){
4398 if (track->GetClusterIndex(irow)>0){
4403 for (Int_t irow=160;irow>r0;irow--){
4404 if (track->GetClusterIndex(irow)>0){
4409 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4410 if (track->GetClusterIndex(irow)>0){
4418 for (Int_t irow=0;irow<r0;irow++){
4419 if (track->GetClusterIndex(irow)>0){
4424 for (Int_t irow=r0;irow>0;irow--){
4425 if (track->GetClusterIndex(irow)>0){
4430 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4431 if (track->GetClusterIndex(irow)>0){
4438 if ((row[2]-row[0])<20) return 0;
4439 if (row[1]==0) return 0;
4442 //Get cluster and sector position
4443 for (Int_t ipoint=0;ipoint<3;ipoint++){
4444 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4445 AliTPCclusterMI * cl = GetClusterMI(clindex);
4448 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4451 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4452 xyz[ipoint][0] = GetXrow(row[ipoint]);
4453 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4454 if (point&&ipoint<2){
4456 xyz[ipoint][1] = point->GetY();
4457 xyz[ipoint][2] = point->GetZ();
4460 xyz[ipoint][1] = cl->GetY();
4461 xyz[ipoint][2] = cl->GetZ();
4468 // Calculate seed state vector and covariance matrix
4470 Double_t alpha, cs,sn, xx2,yy2;
4472 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4473 cs = TMath::Cos(alpha);
4474 sn = TMath::Sin(alpha);
4475 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4476 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4480 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4481 cs = TMath::Cos(alpha);
4482 sn = TMath::Sin(alpha);
4483 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4484 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4490 Double_t x[5],c[15];
4494 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4495 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4496 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4498 Double_t sy =0.1, sz =0.1;
4500 Double_t sy1=0.2, sz1=0.2;
4501 Double_t sy2=0.2, sz2=0.2;
4504 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;
4505 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;
4506 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;
4507 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;
4508 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;
4509 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;
4511 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;
4512 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;
4513 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;
4514 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;
4519 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4520 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4521 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4522 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4523 c[13]=f30*sy1*f40+f32*sy2*f42;
4524 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4526 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4527 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4528 seed->SetPoolID(fLastSeedID);
4529 seed->SetLastPoint(row[2]);
4530 seed->SetFirstPoint(row[2]);
4531 for (Int_t i=row[0];i<row[2];i++){
4532 seed->SetClusterIndex(i, track->GetClusterIndex(i));
4540 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4543 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4545 // Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4547 // Two reasons to have multiple find tracks
4548 // 1. Curling tracks can be find more than once
4549 // 2. Splitted tracks
4550 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
4551 // b.) Edge effect on the sector boundaries
4554 // Algorithm done in 2 phases - because of CPU consumption
4555 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4557 // Algorihm for curling tracks sign:
4558 // 1 phase -makes a very rough fast cuts to minimize combinatorics
4559 // a.) opposite sign
4560 // b.) one of the tracks - not pointing to the primary vertex -
4561 // c.) delta tan(theta)
4563 // 2 phase - calculates DCA between tracks - time consument
4568 // General cuts - for splitted tracks and for curling tracks
4570 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
4572 // Curling tracks cuts
4577 Int_t nentries = array->GetEntriesFast();
4578 AliHelix *helixes = new AliHelix[nentries];
4579 Float_t *xm = new Float_t[nentries];
4580 Float_t *dz0 = new Float_t[nentries];
4581 Float_t *dz1 = new Float_t[nentries];
4587 // Find track COG in x direction - point with best defined parameters
4589 for (Int_t i=0;i<nentries;i++){
4590 AliTPCseed* track = (AliTPCseed*)array->At(i);
4591 if (!track) continue;
4592 track->SetCircular(0);
4593 new (&helixes[i]) AliHelix(*track);
4597 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4600 for (Int_t icl=0; icl<160; icl++){
4601 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
4607 if (ncl>0) xm[i]/=Float_t(ncl);
4610 for (Int_t i0=0;i0<nentries;i0++){
4611 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4612 if (!track0) continue;
4613 Float_t xc0 = helixes[i0].GetHelix(6);
4614 Float_t yc0 = helixes[i0].GetHelix(7);
4615 Float_t r0 = helixes[i0].GetHelix(8);
4616 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4617 Float_t fi0 = TMath::ATan2(yc0,xc0);
4619 for (Int_t i1=i0+1;i1<nentries;i1++){
4620 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4621 if (!track1) continue;
4622 Int_t lab0=track0->GetLabel();
4623 Int_t lab1=track1->GetLabel();
4624 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4626 Float_t xc1 = helixes[i1].GetHelix(6);
4627 Float_t yc1 = helixes[i1].GetHelix(7);
4628 Float_t r1 = helixes[i1].GetHelix(8);
4629 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4630 Float_t fi1 = TMath::ATan2(yc1,xc1);
4632 Float_t dfi = fi0-fi1;
4635 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4636 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4637 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4639 // if short tracks with undefined sign
4640 fi1 = -TMath::ATan2(yc1,-xc1);
4643 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4646 // debug stream to tune "fast cuts"
4648 Double_t dist[3]; // distance at X
4649 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
4650 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4651 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4652 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4653 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4654 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4655 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4656 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4660 for (Int_t icl=0; icl<160; icl++){
4661 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
4662 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
4665 if (cl0==cl1) sums++;
4669 if (AliTPCReconstructor::StreamLevel()>5) {
4670 TTreeSRedirector &cstream = *fDebugStreamer;
4675 "Tr0.="<<track0<< // seed0
4676 "Tr1.="<<track1<< // seed1
4677 "h0.="<<&helixes[i0]<<
4678 "h1.="<<&helixes[i1]<<
4680 "sum="<<sum<< //the sum of rows with cl in both
4681 "sums="<<sums<< //the sum of shared clusters
4682 "xm0="<<xm[i0]<< // the center of track
4683 "xm1="<<xm[i1]<< // the x center of track
4684 // General cut variables
4685 "dfi="<<dfi<< // distance in fi angle
4686 "dtheta="<<dtheta<< // distance int theta angle
4692 "dist0="<<dist[0]<< //distance x
4693 "dist1="<<dist[1]<< //distance y
4694 "dist2="<<dist[2]<< //distance z
4695 "mdist0="<<mdist[0]<< //distance x
4696 "mdist1="<<mdist[1]<< //distance y
4697 "mdist2="<<mdist[2]<< //distance z
4713 if (AliTPCReconstructor::StreamLevel()>1) {
4714 AliInfo("Time for curling tracks removal DEBUGGING MC");
4721 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
4723 // Find Splitted tracks and remove the one with worst quality
4724 // Corresponding debug streamer to tune selections - "Splitted2"
4726 // 0. Sort tracks according quility
4727 // 1. Propagate the tracks to the reference radius
4728 // 2. Double_t loop to select close tracks (only to speed up process)
4729 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
4730 // 4. Delete temporary parameters
4732 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
4734 const Double_t kCutP1=10; // delta Z cut 10 cm
4735 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
4736 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
4737 const Double_t kCutAlpha=0.15; // delta alpha cut
4738 Int_t firstpoint = 0;
4739 Int_t lastpoint = 160;
4741 Int_t nentries = array->GetEntriesFast();
4742 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
4748 //0. Sort tracks according quality
4749 //1. Propagate the ext. param to reference radius
4750 Int_t nseed = array->GetEntriesFast();
4751 if (nseed<=0) return;
4752 Float_t * quality = new Float_t[nseed];
4753 Int_t * indexes = new Int_t[nseed];
4754 for (Int_t i=0; i<nseed; i++) {
4755 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
4760 pt->UpdatePoints(); //select first last max dens points
4761 Float_t * points = pt->GetPoints();
4762 if (points[3]<0.8) quality[i] =-1;
4763 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4764 //prefer high momenta tracks if overlaps
4765 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
4767 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
4768 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
4770 TMath::Sort(nseed,quality,indexes);
4772 // 3. Loop over pair of tracks
4774 for (Int_t i0=0; i0<nseed; i0++) {
4775 Int_t index0=indexes[i0];
4776 if (!(array->UncheckedAt(index0))) continue;
4777 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
4778 if (!s1->IsActive()) continue;
4779 AliExternalTrackParam &par0=params[index0];
4780 for (Int_t i1=i0+1; i1<nseed; i1++) {
4781 Int_t index1=indexes[i1];
4782 if (!(array->UncheckedAt(index1))) continue;
4783 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
4784 if (!s2->IsActive()) continue;
4785 if (s2->GetKinkIndexes()[0]!=0)
4786 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
4787 AliExternalTrackParam &par1=params[index1];
4788 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
4789 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
4790 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
4791 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
4792 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
4793 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
4798 Int_t firstShared=lastpoint, lastShared=firstpoint;
4799 Int_t firstRow=lastpoint, lastRow=firstpoint;
4801 for (Int_t i=firstpoint;i<lastpoint;i++){
4802 if (s1->GetClusterIndex2(i)>0) nall0++;
4803 if (s2->GetClusterIndex2(i)>0) nall1++;
4804 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
4805 if (i<firstRow) firstRow=i;
4806 if (i>lastRow) lastRow=i;
4808 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
4809 if (i<firstShared) firstShared=i;
4810 if (i>lastShared) lastShared=i;
4814 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
4815 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
4817 if( AliTPCReconstructor::StreamLevel()>1){
4818 TTreeSRedirector &cstream = *fDebugStreamer;
4819 Int_t n0=s1->GetNumberOfClusters();
4820 Int_t n1=s2->GetNumberOfClusters();
4821 Int_t n0F=s1->GetNFoundable();
4822 Int_t n1F=s2->GetNFoundable();
4823 Int_t lab0=s1->GetLabel();
4824 Int_t lab1=s2->GetLabel();
4826 cstream<<"Splitted2"<<
4827 "iter="<<fIteration<<
4828 "lab0="<<lab0<< // MC label if exist
4829 "lab1="<<lab1<< // MC label if exist
4832 "ratio0="<<ratio0<< // shared ratio
4833 "ratio1="<<ratio1<< // shared ratio
4834 "p0.="<<&par0<< // track parameters
4836 "s0.="<<s1<< // full seed
4838 "n0="<<n0<< // number of clusters track 0
4839 "n1="<<n1<< // number of clusters track 1
4840 "nall0="<<nall0<< // number of clusters track 0
4841 "nall1="<<nall1<< // number of clusters track 1
4842 "n0F="<<n0F<< // number of findable
4843 "n1F="<<n1F<< // number of findable
4844 "shared="<<sumShared<< // number of shared clusters
4845 "firstS="<<firstShared<< // first and the last shared row
4846 "lastS="<<lastShared<<
4847 "firstRow="<<firstRow<< // first and the last row with cluster
4848 "lastRow="<<lastRow<< //
4852 // remove track with lower quality
4854 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
4855 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
4859 MarkSeedFree( array->RemoveAt(index1) );
4864 // 4. Delete temporary array
4874 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4877 // find Curling tracks
4878 // Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4881 // Algorithm done in 2 phases - because of CPU consumption
4882 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4883 // see detal in MC part what can be used to cut
4887 const Float_t kMaxC = 400; // maximal curvature to of the track
4888 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
4889 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
4890 const Float_t kPtRatio = 0.3; // ratio between pt
4891 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
4894 // Curling tracks cuts
4897 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
4898 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
4899 const Float_t kMinAngle = 2.9; // angle between tracks
4900 const Float_t kMaxDist = 5; // biggest distance
4902 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4905 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4906 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4907 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4908 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4909 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
4911 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4912 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4914 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
4915 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4917 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4923 Int_t nentries = array->GetEntriesFast();
4924 AliHelix *helixes = new AliHelix[nentries];
4925 for (Int_t i=0;i<nentries;i++){
4926 AliTPCseed* track = (AliTPCseed*)array->At(i);
4927 if (!track) continue;
4928 track->SetCircular(0);
4929 new (&helixes[i]) AliHelix(*track);
4935 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4941 for (Int_t i0=0;i0<nentries;i0++){
4942 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4943 if (!track0) continue;
4944 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4945 Float_t xc0 = helixes[i0].GetHelix(6);
4946 Float_t yc0 = helixes[i0].GetHelix(7);
4947 Float_t r0 = helixes[i0].GetHelix(8);
4948 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4949 Float_t fi0 = TMath::ATan2(yc0,xc0);
4951 for (Int_t i1=i0+1;i1<nentries;i1++){
4952 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4953 if (!track1) continue;
4954 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
4955 Float_t xc1 = helixes[i1].GetHelix(6);
4956 Float_t yc1 = helixes[i1].GetHelix(7);
4957 Float_t r1 = helixes[i1].GetHelix(8);
4958 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4959 Float_t fi1 = TMath::ATan2(yc1,xc1);
4961 Float_t dfi = fi0-fi1;
4964 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4965 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4966 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4970 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
4971 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
4972 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4973 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
4974 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4976 Float_t pt0 = track0->GetSignedPt();
4977 Float_t pt1 = track1->GetSignedPt();
4978 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
4979 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4980 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
4981 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
4984 // Now find closest approach
4988 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4989 if (npoints==0) continue;
4990 helixes[i0].GetClosestPhases(helixes[i1], phase);
4994 Double_t hangles[3];
4995 helixes[i0].Evaluate(phase[0][0],xyz0);
4996 helixes[i1].Evaluate(phase[0][1],xyz1);
4998 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4999 Double_t deltah[2],deltabest;
5000 if (TMath::Abs(hangles[2])<kMinAngle) continue;
5004 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5006 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5007 if (deltah[1]<deltah[0]) ibest=1;
5009 deltabest = TMath::Sqrt(deltah[ibest]);
5010 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5011 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5012 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5013 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5015 if (deltabest>kMaxDist) continue;
5016 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5017 Bool_t sign =kFALSE;
5018 if (hangles[2]>kMinAngle) sign =kTRUE;
5021 // circular[i0] = kTRUE;
5022 // circular[i1] = kTRUE;
5023 if (track0->OneOverPt()<track1->OneOverPt()){
5024 track0->SetCircular(track0->GetCircular()+1);
5025 track1->SetCircular(track1->GetCircular()+2);
5028 track1->SetCircular(track1->GetCircular()+1);
5029 track0->SetCircular(track0->GetCircular()+2);
5032 if (AliTPCReconstructor::StreamLevel()>2){
5034 //debug stream to tune "fine" cuts
5035 Int_t lab0=track0->GetLabel();
5036 Int_t lab1=track1->GetLabel();
5037 TTreeSRedirector &cstream = *fDebugStreamer;
5038 cstream<<"Curling2"<<
5054 "npoints="<<npoints<<
5055 "hangles0="<<hangles[0]<<
5056 "hangles1="<<hangles[1]<<
5057 "hangles2="<<hangles[2]<<
5060 "radius="<<radiusbest<<
5061 "deltabest="<<deltabest<<
5062 "phase0="<<phase[ibest][0]<<
5063 "phase1="<<phase[ibest][1]<<
5071 if (AliTPCReconstructor::StreamLevel()>1) {
5072 AliInfo("Time for curling tracks removal");
5078 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5084 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5087 TObjArray *kinks= new TObjArray(10000);
5088 // TObjArray *v0s= new TObjArray(10000);
5089 Int_t nentries = array->GetEntriesFast();
5090 AliHelix *helixes = new AliHelix[nentries];
5091 Int_t *sign = new Int_t[nentries];
5092 Int_t *nclusters = new Int_t[nentries];
5093 Float_t *alpha = new Float_t[nentries];
5094 AliKink *kink = new AliKink();
5095 Int_t * usage = new Int_t[nentries];
5096 Float_t *zm = new Float_t[nentries];
5097 Float_t *z0 = new Float_t[nentries];
5098 Float_t *fim = new Float_t[nentries];
5099 Float_t *shared = new Float_t[nentries];
5100 Bool_t *circular = new Bool_t[nentries];
5101 Float_t *dca = new Float_t[nentries];
5102 //const AliESDVertex * primvertex = esd->GetVertex();
5104 // nentries = array->GetEntriesFast();
5109 for (Int_t i=0;i<nentries;i++){
5112 AliTPCseed* track = (AliTPCseed*)array->At(i);
5113 if (!track) continue;
5114 track->SetCircular(0);
5116 track->UpdatePoints();
5117 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5119 nclusters[i]=track->GetNumberOfClusters();
5120 alpha[i] = track->GetAlpha();
5121 new (&helixes[i]) AliHelix(*track);
5123 helixes[i].Evaluate(0,xyz);
5124 sign[i] = (track->GetC()>0) ? -1:1;
5127 if (track->GetProlongation(x,y,z)){
5129 fim[i] = alpha[i]+TMath::ATan2(y,x);
5132 zm[i] = track->GetZ();
5136 circular[i]= kFALSE;
5137 if (track->GetProlongation(0,y,z)) z0[i] = z;
5138 dca[i] = track->GetD(0,0);
5144 Int_t ncandidates =0;
5147 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5150 // Find circling track
5152 for (Int_t i0=0;i0<nentries;i0++){
5153 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5154 if (!track0) continue;
5155 if (track0->GetNumberOfClusters()<40) continue;
5156 if (TMath::Abs(1./track0->GetC())>200) continue;
5157 for (Int_t i1=i0+1;i1<nentries;i1++){
5158 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5159 if (!track1) continue;
5160 if (track1->GetNumberOfClusters()<40) continue;
5161 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5162 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5163 if (TMath::Abs(1./track1->GetC())>200) continue;
5164 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5165 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5166 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5167 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5168 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5170 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5171 if (mindcar<5) continue;
5172 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5173 if (mindcaz<5) continue;
5174 if (mindcar+mindcaz<20) continue;
5177 Float_t xc0 = helixes[i0].GetHelix(6);
5178 Float_t yc0 = helixes[i0].GetHelix(7);
5179 Float_t r0 = helixes[i0].GetHelix(8);
5180 Float_t xc1 = helixes[i1].GetHelix(6);
5181 Float_t yc1 = helixes[i1].GetHelix(7);
5182 Float_t r1 = helixes[i1].GetHelix(8);
5184 Float_t rmean = (r0+r1)*0.5;
5185 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5186 //if (delta>30) continue;
5187 if (delta>rmean*0.25) continue;
5188 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5190 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5191 if (npoints==0) continue;
5192 helixes[i0].GetClosestPhases(helixes[i1], phase);
5196 Double_t hangles[3];
5197 helixes[i0].Evaluate(phase[0][0],xyz0);
5198 helixes[i1].Evaluate(phase[0][1],xyz1);
5200 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5201 Double_t deltah[2],deltabest;
5202 if (hangles[2]<2.8) continue;
5205 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5207 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5208 if (deltah[1]<deltah[0]) ibest=1;
5210 deltabest = TMath::Sqrt(deltah[ibest]);
5211 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5212 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5213 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5214 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5216 if (deltabest>6) continue;
5217 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5218 Bool_t lsign =kFALSE;
5219 if (hangles[2]>3.06) lsign =kTRUE;
5222 circular[i0] = kTRUE;
5223 circular[i1] = kTRUE;
5224 if (track0->OneOverPt()<track1->OneOverPt()){
5225 track0->SetCircular(track0->GetCircular()+1);
5226 track1->SetCircular(track1->GetCircular()+2);
5229 track1->SetCircular(track1->GetCircular()+1);
5230 track0->SetCircular(track0->GetCircular()+2);
5233 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5235 Int_t lab0=track0->GetLabel();
5236 Int_t lab1=track1->GetLabel();
5237 TTreeSRedirector &cstream = *fDebugStreamer;
5238 cstream<<"Curling"<<
5245 "mindcar="<<mindcar<<
5246 "mindcaz="<<mindcaz<<
5249 "npoints="<<npoints<<
5250 "hangles0="<<hangles[0]<<
5251 "hangles2="<<hangles[2]<<
5256 "radius="<<radiusbest<<
5257 "deltabest="<<deltabest<<
5258 "phase0="<<phase[ibest][0]<<
5259 "phase1="<<phase[ibest][1]<<
5269 for (Int_t i =0;i<nentries;i++){
5270 if (sign[i]==0) continue;
5271 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5278 Double_t cradius0 = 40*40;
5279 Double_t cradius1 = 270*270;
5282 Double_t cdist3=0.55;
5283 for (Int_t j =i+1;j<nentries;j++){
5285 if (sign[j]*sign[i]<1) continue;
5286 if ( (nclusters[i]+nclusters[j])>200) continue;
5287 if ( (nclusters[i]+nclusters[j])<80) continue;
5288 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5289 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5290 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5291 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5292 if (npoints<1) continue;
5295 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5298 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5301 Double_t delta1=10000,delta2=10000;
5302 // cuts on the intersection radius
5303 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5304 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5305 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5307 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5308 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5309 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5312 Double_t distance1 = TMath::Min(delta1,delta2);
5313 if (distance1>cdist1) continue; // cut on DCA linear approximation
5315 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5316 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5317 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5318 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5321 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5322 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5323 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5325 distance1 = TMath::Min(delta1,delta2);
5328 rkink = TMath::Sqrt(radius[0]);
5331 rkink = TMath::Sqrt(radius[1]);
5333 if (distance1>cdist2) continue;
5336 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5339 Int_t row0 = GetRowNumber(rkink);
5340 if (row0<10) continue;
5341 if (row0>150) continue;
5344 Float_t dens00=-1,dens01=-1;
5345 Float_t dens10=-1,dens11=-1;
5347 Int_t found,foundable,ishared;
5348 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5349 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5350 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5351 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5353 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5354 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5355 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5356 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5358 if (dens00<dens10 && dens01<dens11) continue;
5359 if (dens00>dens10 && dens01>dens11) continue;
5360 if (TMath::Max(dens00,dens10)<0.1) continue;
5361 if (TMath::Max(dens01,dens11)<0.3) continue;
5363 if (TMath::Min(dens00,dens10)>0.6) continue;
5364 if (TMath::Min(dens01,dens11)>0.6) continue;
5367 AliTPCseed * ktrack0, *ktrack1;
5376 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5377 AliExternalTrackParam paramm(*ktrack0);
5378 AliExternalTrackParam paramd(*ktrack1);
5379 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5382 kink->SetMother(paramm);
5383 kink->SetDaughter(paramd);
5386 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
5388 fkParam->Transform0to1(x,index);
5389 fkParam->Transform1to2(x,index);
5390 row0 = GetRowNumber(x[0]);
5392 if (kink->GetR()<100) continue;
5393 if (kink->GetR()>240) continue;
5394 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5395 if (kink->GetDistance()>cdist3) continue;
5396 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5397 if (dird<0) continue;
5399 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5400 if (dirm<0) continue;
5401 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5402 if (mpt<0.2) continue;
5405 //for high momenta momentum not defined well in first iteration
5406 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5407 if (qt>0.35) continue;
5410 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5411 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5413 kink->SetTPCDensity(dens00,0,0);
5414 kink->SetTPCDensity(dens01,0,1);
5415 kink->SetTPCDensity(dens10,1,0);
5416 kink->SetTPCDensity(dens11,1,1);
5417 kink->SetIndex(i,0);
5418 kink->SetIndex(j,1);
5421 kink->SetTPCDensity(dens10,0,0);
5422 kink->SetTPCDensity(dens11,0,1);
5423 kink->SetTPCDensity(dens00,1,0);
5424 kink->SetTPCDensity(dens01,1,1);
5425 kink->SetIndex(j,0);
5426 kink->SetIndex(i,1);
5429 if (mpt<1||kink->GetAngle(2)>0.1){
5430 // angle and densities not defined yet
5431 if (kink->GetTPCDensityFactor()<0.8) continue;
5432 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5433 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5434 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5435 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5437 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5438 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5439 criticalangle= 3*TMath::Sqrt(criticalangle);
5440 if (criticalangle>0.02) criticalangle=0.02;
5441 if (kink->GetAngle(2)<criticalangle) continue;
5444 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5445 Float_t shapesum =0;
5447 for ( Int_t row = row0-drow; row<row0+drow;row++){
5448 if (row<0) continue;
5449 if (row>155) continue;
5450 if (ktrack0->GetClusterPointer(row)){
5451 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5452 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5455 if (ktrack1->GetClusterPointer(row)){
5456 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5457 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5462 kink->SetShapeFactor(-1.);
5465 kink->SetShapeFactor(shapesum/sum);
5467 // esd->AddKink(kink);
5469 // kink->SetMother(paramm);
5470 //kink->SetDaughter(paramd);
5472 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5474 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5475 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5477 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5479 if (AliTPCReconstructor::StreamLevel()>1) {
5480 (*fDebugStreamer)<<"kinkLpt"<<
5488 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5492 kinks->AddLast(kink);
5498 // sort the kinks according quality - and refit them towards vertex
5500 Int_t nkinks = kinks->GetEntriesFast();
5501 Float_t *quality = new Float_t[nkinks];
5502 Int_t *indexes = new Int_t[nkinks];
5503 AliTPCseed *mothers = new AliTPCseed[nkinks];
5504 AliTPCseed *daughters = new AliTPCseed[nkinks];
5507 for (Int_t i=0;i<nkinks;i++){
5509 AliKink *kinkl = (AliKink*)kinks->At(i);
5511 // refit kinks towards vertex
5513 Int_t index0 = kinkl->GetIndex(0);
5514 Int_t index1 = kinkl->GetIndex(1);
5515 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5516 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5518 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5520 // Refit Kink under if too small angle
5522 if (kinkl->GetAngle(2)<0.05){
5523 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5524 Int_t row0 = kinkl->GetTPCRow0();
5525 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5528 Int_t last = row0-drow;
5529 if (last<40) last=40;
5530 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5531 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5534 Int_t first = row0+drow;
5535 if (first>130) first=130;
5536 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5537 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5539 if (seed0 && seed1){
5540 kinkl->SetStatus(1,8);
5541 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5542 row0 = GetRowNumber(kinkl->GetR());
5543 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5544 mothers[i] = *seed0;
5545 daughters[i] = *seed1;
5548 delete kinks->RemoveAt(i);
5549 if (seed0) MarkSeedFree( seed0 );
5550 if (seed1) MarkSeedFree( seed1 );
5553 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
5554 delete kinks->RemoveAt(i);
5555 if (seed0) MarkSeedFree( seed0 );
5556 if (seed1) MarkSeedFree( seed1 );
5560 MarkSeedFree( seed0 );
5561 MarkSeedFree( seed1 );
5564 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
5566 TMath::Sort(nkinks,quality,indexes,kFALSE);
5568 //remove double find kinks
5570 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5571 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5572 if (!kink0) continue;
5574 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5575 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5576 if (!kink0) continue;
5577 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5578 if (!kink1) continue;
5579 // if not close kink continue
5580 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5581 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5582 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5584 AliTPCseed &mother0 = mothers[indexes[ikink0]];
5585 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5586 AliTPCseed &mother1 = mothers[indexes[ikink1]];
5587 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5588 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5597 for (Int_t i=0;i<row0;i++){
5598 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5601 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5608 for (Int_t i=row0;i<158;i++){
5609 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
5610 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
5613 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5619 Float_t ratio = Float_t(same+1)/Float_t(both+1);
5620 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5621 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5622 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5623 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5624 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5626 shared[kink0->GetIndex(0)]= kTRUE;
5627 shared[kink0->GetIndex(1)]= kTRUE;
5628 delete kinks->RemoveAt(indexes[ikink0]);
5632 shared[kink1->GetIndex(0)]= kTRUE;
5633 shared[kink1->GetIndex(1)]= kTRUE;
5634 delete kinks->RemoveAt(indexes[ikink1]);
5641 for (Int_t i=0;i<nkinks;i++){
5642 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
5643 if (!kinkl) continue;
5644 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5645 Int_t index0 = kinkl->GetIndex(0);
5646 Int_t index1 = kinkl->GetIndex(1);
5647 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
5648 kinkl->SetMultiple(usage[index0],0);
5649 kinkl->SetMultiple(usage[index1],1);
5650 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
5651 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5652 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
5653 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
5655 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5656 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5657 if (!ktrack0 || !ktrack1) continue;
5658 Int_t index = esd->AddKink(kinkl);
5661 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
5662 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5663 *ktrack0 = mothers[indexes[i]];
5664 *ktrack1 = daughters[indexes[i]];
5668 ktrack0->SetKinkIndex(usage[index0],-(index+1));
5669 ktrack1->SetKinkIndex(usage[index1], (index+1));
5674 // Remove tracks corresponding to shared kink's
5676 for (Int_t i=0;i<nentries;i++){
5677 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5678 if (!track0) continue;
5679 if (track0->GetKinkIndex(0)!=0) continue;
5680 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
5685 RemoveUsed2(array,0.5,0.4,30);
5687 for (Int_t i=0;i<nentries;i++){
5688 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5689 if (!track0) continue;
5690 track0->CookdEdx(0.02,0.6);
5694 for (Int_t i=0;i<nentries;i++){
5695 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5696 if (!track0) continue;
5697 if (track0->Pt()<1.4) continue;
5698 //remove double high momenta tracks - overlapped with kink candidates
5701 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5702 if (track0->GetClusterPointer(icl)!=0){
5704 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
5707 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
5708 MarkSeedFree( array->RemoveAt(i) );
5712 if (track0->GetKinkIndex(0)!=0) continue;
5713 if (track0->GetNumberOfClusters()<80) continue;
5715 AliTPCseed *pmother = new AliTPCseed();
5716 AliTPCseed *pdaughter = new AliTPCseed();
5717 AliKink *pkink = new AliKink;
5719 AliTPCseed & mother = *pmother;
5720 AliTPCseed & daughter = *pdaughter;
5721 AliKink & kinkl = *pkink;
5722 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
5723 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5727 continue; //too short tracks
5729 if (mother.Pt()<1.4) {
5735 Int_t row0= kinkl.GetTPCRow0();
5736 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
5743 Int_t index = esd->AddKink(&kinkl);
5744 mother.SetKinkIndex(0,-(index+1));
5745 daughter.SetKinkIndex(0,index+1);
5746 if (mother.GetNumberOfClusters()>50) {
5747 MarkSeedFree( array->RemoveAt(i) );
5748 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5749 mtc->SetPoolID(fLastSeedID);
5750 array->AddAt(mtc,i);
5753 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5754 mtc->SetPoolID(fLastSeedID);
5755 array->AddLast(mtc);
5757 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
5758 dtc->SetPoolID(fLastSeedID);
5759 array->AddLast(dtc);
5760 for (Int_t icl=0;icl<row0;icl++) {
5761 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5764 for (Int_t icl=row0;icl<158;icl++) {
5765 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5774 delete [] daughters;
5796 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
5802 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5809 TObjArray *kinks= new TObjArray(10000);
5810 // TObjArray *v0s= new TObjArray(10000);
5811 Int_t nentries = array->GetEntriesFast();
5812 AliHelix *helixes = new AliHelix[nentries];
5813 Int_t *sign = new Int_t[nentries];
5814 Int_t *nclusters = new Int_t[nentries];
5815 Float_t *alpha = new Float_t[nentries];
5816 AliKink *kink = new AliKink();
5817 Int_t * usage = new Int_t[nentries];
5818 Float_t *zm = new Float_t[nentries];
5819 Float_t *z0 = new Float_t[nentries];
5820 Float_t *fim = new Float_t[nentries];
5821 Float_t *shared = new Float_t[nentries];
5822 Bool_t *circular = new Bool_t[nentries];
5823 Float_t *dca = new Float_t[nentries];
5824 //const AliESDVertex * primvertex = esd->GetVertex();
5826 // nentries = array->GetEntriesFast();
5831 for (Int_t i=0;i<nentries;i++){
5834 AliTPCseed* track = (AliTPCseed*)array->At(i);
5835 if (!track) continue;
5836 track->SetCircular(0);
5838 track->UpdatePoints();
5839 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5841 nclusters[i]=track->GetNumberOfClusters();
5842 alpha[i] = track->GetAlpha();
5843 new (&helixes[i]) AliHelix(*track);
5845 helixes[i].Evaluate(0,xyz);
5846 sign[i] = (track->GetC()>0) ? -1:1;
5849 if (track->GetProlongation(x,y,z)){
5851 fim[i] = alpha[i]+TMath::ATan2(y,x);
5854 zm[i] = track->GetZ();
5858 circular[i]= kFALSE;
5859 if (track->GetProlongation(0,y,z)) z0[i] = z;
5860 dca[i] = track->GetD(0,0);
5866 Int_t ncandidates =0;
5869 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5872 // Find circling track
5874 for (Int_t i0=0;i0<nentries;i0++){
5875 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5876 if (!track0) continue;
5877 if (track0->GetNumberOfClusters()<40) continue;
5878 if (TMath::Abs(1./track0->GetC())>200) continue;
5879 for (Int_t i1=i0+1;i1<nentries;i1++){
5880 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5881 if (!track1) continue;
5882 if (track1->GetNumberOfClusters()<40) continue;
5883 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5884 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5885 if (TMath::Abs(1./track1->GetC())>200) continue;
5886 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5887 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5888 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5889 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5890 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5892 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5893 if (mindcar<5) continue;
5894 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5895 if (mindcaz<5) continue;
5896 if (mindcar+mindcaz<20) continue;
5899 Float_t xc0 = helixes[i0].GetHelix(6);
5900 Float_t yc0 = helixes[i0].GetHelix(7);
5901 Float_t r0 = helixes[i0].GetHelix(8);
5902 Float_t xc1 = helixes[i1].GetHelix(6);
5903 Float_t yc1 = helixes[i1].GetHelix(7);
5904 Float_t r1 = helixes[i1].GetHelix(8);
5906 Float_t rmean = (r0+r1)*0.5;
5907 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5908 //if (delta>30) continue;
5909 if (delta>rmean*0.25) continue;
5910 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5912 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5913 if (npoints==0) continue;
5914 helixes[i0].GetClosestPhases(helixes[i1], phase);
5918 Double_t hangles[3];
5919 helixes[i0].Evaluate(phase[0][0],xyz0);
5920 helixes[i1].Evaluate(phase[0][1],xyz1);
5922 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5923 Double_t deltah[2],deltabest;
5924 if (hangles[2]<2.8) continue;
5927 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5929 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5930 if (deltah[1]<deltah[0]) ibest=1;
5932 deltabest = TMath::Sqrt(deltah[ibest]);
5933 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5934 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5935 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5936 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5938 if (deltabest>6) continue;
5939 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5940 Bool_t lsign =kFALSE;
5941 if (hangles[2]>3.06) lsign =kTRUE;
5944 circular[i0] = kTRUE;
5945 circular[i1] = kTRUE;
5946 if (track0->OneOverPt()<track1->OneOverPt()){
5947 track0->SetCircular(track0->GetCircular()+1);
5948 track1->SetCircular(track1->GetCircular()+2);
5951 track1->SetCircular(track1->GetCircular()+1);
5952 track0->SetCircular(track0->GetCircular()+2);
5955 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5957 Int_t lab0=track0->GetLabel();
5958 Int_t lab1=track1->GetLabel();
5959 TTreeSRedirector &cstream = *fDebugStreamer;
5960 cstream<<"Curling"<<
5967 "mindcar="<<mindcar<<
5968 "mindcaz="<<mindcaz<<
5971 "npoints="<<npoints<<
5972 "hangles0="<<hangles[0]<<
5973 "hangles2="<<hangles[2]<<
5978 "radius="<<radiusbest<<
5979 "deltabest="<<deltabest<<
5980 "phase0="<<phase[ibest][0]<<
5981 "phase1="<<phase[ibest][1]<<
5991 for (Int_t i =0;i<nentries;i++){
5992 if (sign[i]==0) continue;
5993 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6000 Double_t cradius0 = 40*40;
6001 Double_t cradius1 = 270*270;
6004 Double_t cdist3=0.55;
6005 for (Int_t j =i+1;j<nentries;j++){
6007 if (sign[j]*sign[i]<1) continue;
6008 if ( (nclusters[i]+nclusters[j])>200) continue;
6009 if ( (nclusters[i]+nclusters[j])<80) continue;
6010 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6011 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6012 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6013 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6014 if (npoints<1) continue;
6017 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6020 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6023 Double_t delta1=10000,delta2=10000;
6024 // cuts on the intersection radius
6025 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6026 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6027 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6029 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6030 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6031 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6034 Double_t distance1 = TMath::Min(delta1,delta2);
6035 if (distance1>cdist1) continue; // cut on DCA linear approximation
6037 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6038 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6039 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6040 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6043 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6044 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6045 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6047 distance1 = TMath::Min(delta1,delta2);
6050 rkink = TMath::Sqrt(radius[0]);
6053 rkink = TMath::Sqrt(radius[1]);
6055 if (distance1>cdist2) continue;
6058 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6061 Int_t row0 = GetRowNumber(rkink);
6062 if (row0<10) continue;
6063 if (row0>150) continue;
6066 Float_t dens00=-1,dens01=-1;
6067 Float_t dens10=-1,dens11=-1;
6069 Int_t found,foundable,ishared;
6070 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6071 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6072 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6073 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6075 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6076 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6077 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6078 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6080 if (dens00<dens10 && dens01<dens11) continue;
6081 if (dens00>dens10 && dens01>dens11) continue;
6082 if (TMath::Max(dens00,dens10)<0.1) continue;
6083 if (TMath::Max(dens01,dens11)<0.3) continue;
6085 if (TMath::Min(dens00,dens10)>0.6) continue;
6086 if (TMath::Min(dens01,dens11)>0.6) continue;
6089 AliTPCseed * ktrack0, *ktrack1;
6098 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6099 AliExternalTrackParam paramm(*ktrack0);
6100 AliExternalTrackParam paramd(*ktrack1);
6101 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6104 kink->SetMother(paramm);
6105 kink->SetDaughter(paramd);
6108 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
6110 fkParam->Transform0to1(x,index);
6111 fkParam->Transform1to2(x,index);
6112 row0 = GetRowNumber(x[0]);
6114 if (kink->GetR()<100) continue;
6115 if (kink->GetR()>240) continue;
6116 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6117 if (kink->GetDistance()>cdist3) continue;
6118 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6119 if (dird<0) continue;
6121 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6122 if (dirm<0) continue;
6123 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6124 if (mpt<0.2) continue;
6127 //for high momenta momentum not defined well in first iteration
6128 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6129 if (qt>0.35) continue;
6132 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6133 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6135 kink->SetTPCDensity(dens00,0,0);
6136 kink->SetTPCDensity(dens01,0,1);
6137 kink->SetTPCDensity(dens10,1,0);
6138 kink->SetTPCDensity(dens11,1,1);
6139 kink->SetIndex(i,0);
6140 kink->SetIndex(j,1);
6143 kink->SetTPCDensity(dens10,0,0);
6144 kink->SetTPCDensity(dens11,0,1);
6145 kink->SetTPCDensity(dens00,1,0);
6146 kink->SetTPCDensity(dens01,1,1);
6147 kink->SetIndex(j,0);
6148 kink->SetIndex(i,1);
6151 if (mpt<1||kink->GetAngle(2)>0.1){
6152 // angle and densities not defined yet
6153 if (kink->GetTPCDensityFactor()<0.8) continue;
6154 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6155 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6156 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6157 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6159 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6160 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6161 criticalangle= 3*TMath::Sqrt(criticalangle);
6162 if (criticalangle>0.02) criticalangle=0.02;
6163 if (kink->GetAngle(2)<criticalangle) continue;
6166 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6167 Float_t shapesum =0;
6169 for ( Int_t row = row0-drow; row<row0+drow;row++){
6170 if (row<0) continue;
6171 if (row>155) continue;
6172 if (ktrack0->GetClusterPointer(row)){
6173 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6174 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6177 if (ktrack1->GetClusterPointer(row)){
6178 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6179 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6184 kink->SetShapeFactor(-1.);
6187 kink->SetShapeFactor(shapesum/sum);
6189 // esd->AddKink(kink);
6191 // kink->SetMother(paramm);
6192 //kink->SetDaughter(paramd);
6194 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6196 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6197 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6199 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6201 if (AliTPCReconstructor::StreamLevel()>1) {
6202 (*fDebugStreamer)<<"kinkLpt"<<
6210 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6214 kinks->AddLast(kink);
6220 // sort the kinks according quality - and refit them towards vertex
6222 Int_t nkinks = kinks->GetEntriesFast();
6223 Float_t *quality = new Float_t[nkinks];
6224 Int_t *indexes = new Int_t[nkinks];
6225 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6226 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6229 for (Int_t i=0;i<nkinks;i++){
6231 AliKink *kinkl = (AliKink*)kinks->At(i);
6233 // refit kinks towards vertex
6235 Int_t index0 = kinkl->GetIndex(0);
6236 Int_t index1 = kinkl->GetIndex(1);
6237 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6238 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6240 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6242 // Refit Kink under if too small angle
6244 if (kinkl->GetAngle(2)<0.05){
6245 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6246 Int_t row0 = kinkl->GetTPCRow0();
6247 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6250 Int_t last = row0-drow;
6251 if (last<40) last=40;
6252 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6253 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6256 Int_t first = row0+drow;
6257 if (first>130) first=130;
6258 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6259 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6261 if (seed0 && seed1){
6262 kinkl->SetStatus(1,8);
6263 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6264 row0 = GetRowNumber(kinkl->GetR());
6265 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6266 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6267 mothers[i]->SetPoolID(fLastSeedID);
6268 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6269 daughters[i]->SetPoolID(fLastSeedID);
6272 delete kinks->RemoveAt(i);
6273 if (seed0) MarkSeedFree( seed0 );
6274 if (seed1) MarkSeedFree( seed1 );
6277 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6278 delete kinks->RemoveAt(i);
6279 if (seed0) MarkSeedFree( seed0 );
6280 if (seed1) MarkSeedFree( seed1 );
6284 MarkSeedFree( seed0 );
6285 MarkSeedFree( seed1 );
6288 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6290 TMath::Sort(nkinks,quality,indexes,kFALSE);
6292 //remove double find kinks
6294 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6295 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6296 if (!kink0) continue;
6298 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6299 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6300 if (!kink0) continue;
6301 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6302 if (!kink1) continue;
6303 // if not close kink continue
6304 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6305 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6306 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6308 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6309 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6310 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6311 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6312 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6321 for (Int_t i=0;i<row0;i++){
6322 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6325 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6332 for (Int_t i=row0;i<158;i++){
6333 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6334 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6337 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6343 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6344 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6345 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6346 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6347 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6348 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6350 shared[kink0->GetIndex(0)]= kTRUE;
6351 shared[kink0->GetIndex(1)]= kTRUE;
6352 delete kinks->RemoveAt(indexes[ikink0]);
6356 shared[kink1->GetIndex(0)]= kTRUE;
6357 shared[kink1->GetIndex(1)]= kTRUE;
6358 delete kinks->RemoveAt(indexes[ikink1]);
6365 for (Int_t i=0;i<nkinks;i++){
6366 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6367 if (!kinkl) continue;
6368 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6369 Int_t index0 = kinkl->GetIndex(0);
6370 Int_t index1 = kinkl->GetIndex(1);
6371 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6372 kinkl->SetMultiple(usage[index0],0);
6373 kinkl->SetMultiple(usage[index1],1);
6374 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6375 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6376 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6377 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6379 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6380 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6381 if (!ktrack0 || !ktrack1) continue;
6382 Int_t index = esd->AddKink(kinkl);
6385 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6386 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6387 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6388 *ktrack0 = *mothers[indexes[i]];
6389 *ktrack1 = *daughters[indexes[i]];
6393 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6394 ktrack1->SetKinkIndex(usage[index1], (index+1));
6399 // Remove tracks corresponding to shared kink's
6401 for (Int_t i=0;i<nentries;i++){
6402 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6403 if (!track0) continue;
6404 if (track0->GetKinkIndex(0)!=0) continue;
6405 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6410 RemoveUsed2(array,0.5,0.4,30);
6412 for (Int_t i=0;i<nentries;i++){
6413 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6414 if (!track0) continue;
6415 track0->CookdEdx(0.02,0.6);
6419 for (Int_t i=0;i<nentries;i++){
6420 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6421 if (!track0) continue;
6422 if (track0->Pt()<1.4) continue;
6423 //remove double high momenta tracks - overlapped with kink candidates
6426 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6427 if (track0->GetClusterPointer(icl)!=0){
6429 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6432 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6433 MarkSeedFree( array->RemoveAt(i) );
6437 if (track0->GetKinkIndex(0)!=0) continue;
6438 if (track0->GetNumberOfClusters()<80) continue;
6440 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6441 pmother->SetPoolID(fLastSeedID);
6442 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6443 pdaughter->SetPoolID(fLastSeedID);
6444 AliKink *pkink = new AliKink;
6446 AliTPCseed & mother = *pmother;
6447 AliTPCseed & daughter = *pdaughter;
6448 AliKink & kinkl = *pkink;
6449 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6450 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6451 MarkSeedFree( pmother );
6452 MarkSeedFree( pdaughter );
6454 continue; //too short tracks
6456 if (mother.Pt()<1.4) {
6457 MarkSeedFree( pmother );
6458 MarkSeedFree( pdaughter );
6462 Int_t row0= kinkl.GetTPCRow0();
6463 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6464 MarkSeedFree( pmother );
6465 MarkSeedFree( pdaughter );
6470 Int_t index = esd->AddKink(&kinkl);
6471 mother.SetKinkIndex(0,-(index+1));
6472 daughter.SetKinkIndex(0,index+1);
6473 if (mother.GetNumberOfClusters()>50) {
6474 MarkSeedFree( array->RemoveAt(i) );
6475 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6476 mtc->SetPoolID(fLastSeedID);
6477 array->AddAt(mtc,i);
6480 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6481 mtc->SetPoolID(fLastSeedID);
6482 array->AddLast(mtc);
6484 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6485 dtc->SetPoolID(fLastSeedID);
6486 array->AddLast(dtc);
6487 for (Int_t icl=0;icl<row0;icl++) {
6488 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6491 for (Int_t icl=row0;icl<158;icl++) {
6492 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6496 MarkSeedFree( pmother );
6497 MarkSeedFree( pdaughter );
6501 delete [] daughters;
6523 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6528 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6531 // refit kink towards to the vertex
6534 AliKink &kink=(AliKink &)knk;
6536 Int_t row0 = GetRowNumber(kink.GetR());
6537 FollowProlongation(mother,0);
6538 mother.Reset(kFALSE);
6540 FollowProlongation(daughter,row0);
6541 daughter.Reset(kFALSE);
6542 FollowBackProlongation(daughter,158);
6543 daughter.Reset(kFALSE);
6544 Int_t first = TMath::Max(row0-20,30);
6545 Int_t last = TMath::Min(row0+20,140);
6547 const Int_t kNdiv =5;
6548 AliTPCseed param0[kNdiv]; // parameters along the track
6549 AliTPCseed param1[kNdiv]; // parameters along the track
6550 AliKink kinks[kNdiv]; // corresponding kink parameters
6553 for (Int_t irow=0; irow<kNdiv;irow++){
6554 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
6556 // store parameters along the track
6558 for (Int_t irow=0;irow<kNdiv;irow++){
6559 FollowBackProlongation(mother, rows[irow]);
6560 FollowProlongation(daughter,rows[kNdiv-1-irow]);
6561 param0[irow] = mother;
6562 param1[kNdiv-1-irow] = daughter;
6566 for (Int_t irow=0; irow<kNdiv-1;irow++){
6567 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
6568 kinks[irow].SetMother(param0[irow]);
6569 kinks[irow].SetDaughter(param1[irow]);
6570 kinks[irow].Update();
6573 // choose kink with best "quality"
6575 Double_t mindist = 10000;
6576 for (Int_t irow=0;irow<kNdiv;irow++){
6577 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
6578 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6579 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
6581 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
6582 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
6583 if (normdist < mindist){
6589 if (index==-1) return 0;
6592 param0[index].Reset(kTRUE);
6593 FollowProlongation(param0[index],0);
6595 mother = param0[index];
6596 daughter = param1[index]; // daughter in vertex
6598 kink.SetMother(mother);
6599 kink.SetDaughter(daughter);
6601 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
6602 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6603 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6604 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
6605 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
6606 mother.SetLabel(kink.GetLabel(0));
6607 daughter.SetLabel(kink.GetLabel(1));
6613 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
6615 // update Kink quality information for mother after back propagation
6617 if (seed->GetKinkIndex(0)>=0) return;
6618 for (Int_t ikink=0;ikink<3;ikink++){
6619 Int_t index = seed->GetKinkIndex(ikink);
6620 if (index>=0) break;
6621 index = TMath::Abs(index)-1;
6622 AliESDkink * kink = fEvent->GetKink(index);
6623 kink->SetTPCDensity(-1,0,0);
6624 kink->SetTPCDensity(1,0,1);
6626 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6627 if (row0<15) row0=15;
6629 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6630 if (row1>145) row1=145;
6632 Int_t found,foundable,shared;
6633 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6634 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
6635 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6636 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
6641 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
6643 // update Kink quality information for daughter after refit
6645 if (seed->GetKinkIndex(0)<=0) return;
6646 for (Int_t ikink=0;ikink<3;ikink++){
6647 Int_t index = seed->GetKinkIndex(ikink);
6648 if (index<=0) break;
6649 index = TMath::Abs(index)-1;
6650 AliESDkink * kink = fEvent->GetKink(index);
6651 kink->SetTPCDensity(-1,1,0);
6652 kink->SetTPCDensity(-1,1,1);
6654 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6655 if (row0<15) row0=15;
6657 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6658 if (row1>145) row1=145;
6660 Int_t found,foundable,shared;
6661 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6662 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
6663 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6664 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
6670 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6673 // check kink point for given track
6674 // if return value=0 kink point not found
6675 // otherwise seed0 correspond to mother particle
6676 // seed1 correspond to daughter particle
6677 // kink parameter of kink point
6678 AliKink &kink=(AliKink &)knk;
6680 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
6681 Int_t first = seed->GetFirstPoint();
6682 Int_t last = seed->GetLastPoint();
6683 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
6686 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
6687 if (!seed1) return 0;
6688 FollowProlongation(*seed1,seed->GetLastPoint()-20);
6689 seed1->Reset(kTRUE);
6690 FollowProlongation(*seed1,158);
6691 seed1->Reset(kTRUE);
6692 last = seed1->GetLastPoint();
6694 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
6695 seed0->SetPoolID(fLastSeedID);
6696 seed0->Reset(kFALSE);
6699 AliTPCseed param0[20]; // parameters along the track
6700 AliTPCseed param1[20]; // parameters along the track
6701 AliKink kinks[20]; // corresponding kink parameters
6703 for (Int_t irow=0; irow<20;irow++){
6704 rows[irow] = first +((last-first)*irow)/19;
6706 // store parameters along the track
6708 for (Int_t irow=0;irow<20;irow++){
6709 FollowBackProlongation(*seed0, rows[irow]);
6710 FollowProlongation(*seed1,rows[19-irow]);
6711 param0[irow] = *seed0;
6712 param1[19-irow] = *seed1;
6716 for (Int_t irow=0; irow<19;irow++){
6717 kinks[irow].SetMother(param0[irow]);
6718 kinks[irow].SetDaughter(param1[irow]);
6719 kinks[irow].Update();
6722 // choose kink with biggest change of angle
6724 Double_t maxchange= 0;
6725 for (Int_t irow=1;irow<19;irow++){
6726 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6727 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
6728 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6729 if ( quality > maxchange){
6730 maxchange = quality;
6735 MarkSeedFree( seed0 );
6736 MarkSeedFree( seed1 );
6737 if (index<0) return 0;
6739 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
6740 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
6741 seed0->SetPoolID(fLastSeedID);
6742 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
6743 seed1->SetPoolID(fLastSeedID);
6744 seed0->Reset(kFALSE);
6745 seed1->Reset(kFALSE);
6746 seed0->ResetCovariance(10.);
6747 seed1->ResetCovariance(10.);
6748 FollowProlongation(*seed0,0);
6749 FollowBackProlongation(*seed1,158);
6750 mother = *seed0; // backup mother at position 0
6751 seed0->Reset(kFALSE);
6752 seed1->Reset(kFALSE);
6753 seed0->ResetCovariance(10.);
6754 seed1->ResetCovariance(10.);
6756 first = TMath::Max(row0-20,0);
6757 last = TMath::Min(row0+20,158);
6759 for (Int_t irow=0; irow<20;irow++){
6760 rows[irow] = first +((last-first)*irow)/19;
6762 // store parameters along the track
6764 for (Int_t irow=0;irow<20;irow++){
6765 FollowBackProlongation(*seed0, rows[irow]);
6766 FollowProlongation(*seed1,rows[19-irow]);
6767 param0[irow] = *seed0;
6768 param1[19-irow] = *seed1;
6772 for (Int_t irow=0; irow<19;irow++){
6773 kinks[irow].SetMother(param0[irow]);
6774 kinks[irow].SetDaughter(param1[irow]);
6775 // param0[irow].Dump();
6776 //param1[irow].Dump();
6777 kinks[irow].Update();
6780 // choose kink with biggest change of angle
6783 for (Int_t irow=0;irow<20;irow++){
6784 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
6785 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
6786 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6787 if ( quality > maxchange){
6788 maxchange = quality;
6795 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
6796 MarkSeedFree( seed0 );
6797 MarkSeedFree( seed1 );
6801 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
6803 kink.SetMother(param0[index]);
6804 kink.SetDaughter(param1[index]);
6807 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
6809 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
6810 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
6812 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
6814 if (AliTPCReconstructor::StreamLevel()>1) {
6815 (*fDebugStreamer)<<"kinkHpt"<<
6818 "p0.="<<¶m0[index]<<
6819 "p1.="<<¶m1[index]<<
6823 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6824 MarkSeedFree( seed0 );
6825 MarkSeedFree( seed1 );
6830 row0 = GetRowNumber(kink.GetR());
6831 kink.SetTPCRow0(row0);
6832 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
6833 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
6834 kink.SetIndex(-10,0);
6835 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
6836 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6837 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6840 // new (&mother) AliTPCseed(param0[index]);
6841 daughter = param1[index];
6842 daughter.SetLabel(kink.GetLabel(1));
6843 param0[index].Reset(kTRUE);
6844 FollowProlongation(param0[index],0);
6845 mother = param0[index];
6846 mother.SetLabel(kink.GetLabel(0));
6847 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
6850 MarkSeedFree( seed0 );
6851 MarkSeedFree( seed1 );
6859 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
6862 // reseed - refit - track
6865 // Int_t last = fSectors->GetNRows()-1;
6867 if (fSectors == fOuterSec){
6868 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
6872 first = t->GetFirstPoint();
6874 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
6875 FollowBackProlongation(*t,fSectors->GetNRows()-1);
6877 FollowProlongation(*t,first);
6887 //_____________________________________________________________________________
6888 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
6889 //-----------------------------------------------------------------
6890 // This function reades track seeds.
6891 //-----------------------------------------------------------------
6892 TDirectory *savedir=gDirectory;
6894 TFile *in=(TFile*)inp;
6895 if (!in->IsOpen()) {
6896 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
6901 TTree *seedTree=(TTree*)in->Get("Seeds");
6903 cerr<<"AliTPCtracker::ReadSeeds(): ";
6904 cerr<<"can't get a tree with track seeds !\n";
6907 AliTPCtrack *seed=new AliTPCtrack;
6908 seedTree->SetBranchAddress("tracks",&seed);
6910 if (fSeeds==0) fSeeds=new TObjArray(15000);
6912 Int_t n=(Int_t)seedTree->GetEntries();
6913 for (Int_t i=0; i<n; i++) {
6914 seedTree->GetEvent(i);
6915 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
6916 sdc->SetPoolID(fLastSeedID);
6917 fSeeds->AddLast(sdc);
6920 delete seed; // RS: this seed is not from the pool, delete it !!!
6926 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
6929 // clusters to tracks
6930 if (fSeeds) DeleteSeeds();
6931 else ResetSeedsPool();
6933 fEventHLT = hltEvent;
6935 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
6936 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
6937 transform->SetCurrentRun(esd->GetRunNumber());
6941 if (!fSeeds) return 1;
6943 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(0,fSeeds);
6948 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
6951 // clusters to tracks
6952 return Clusters2TracksHLT( esd, 0);
6955 //_____________________________________________________________________________
6956 Int_t AliTPCtracker::Clusters2Tracks() {
6957 //-----------------------------------------------------------------
6958 // This is a track finder.
6959 //-----------------------------------------------------------------
6960 TDirectory *savedir=gDirectory;
6964 fSeeds = Tracking();
6967 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6969 //activate again some tracks
6970 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6971 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6973 Int_t nc=t.GetNumberOfClusters();
6975 MarkSeedFree( fSeeds->RemoveAt(i) );
6979 if (pt->GetRemoval()==10) {
6980 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6981 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
6983 pt->Desactivate(20);
6984 MarkSeedFree( fSeeds->RemoveAt(i) );
6989 RemoveUsed2(fSeeds,0.85,0.85,0);
6990 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
6991 //FindCurling(fSeeds, fEvent,0);
6992 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
6993 RemoveUsed2(fSeeds,0.5,0.4,20);
6994 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
6995 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
6998 // // refit short tracks
7000 Int_t nseed=fSeeds->GetEntriesFast();
7003 for (Int_t i=0; i<nseed; i++) {
7004 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7006 Int_t nc=t.GetNumberOfClusters();
7008 MarkSeedFree( fSeeds->RemoveAt(i) );
7011 CookLabel(pt,0.1); //For comparison only
7012 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7013 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7015 if (fDebug>0) cerr<<found<<'\r';
7019 MarkSeedFree( fSeeds->RemoveAt(i) );
7023 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7025 //RemoveUsed(fSeeds,0.9,0.9,6);
7027 nseed=fSeeds->GetEntriesFast();
7029 for (Int_t i=0; i<nseed; i++) {
7030 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7032 Int_t nc=t.GetNumberOfClusters();
7034 MarkSeedFree( fSeeds->RemoveAt(i) );
7038 t.CookdEdx(0.02,0.6);
7039 // CheckKinkPoint(&t,0.05);
7040 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7041 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7049 MarkSeedFree( fSeeds->RemoveAt(i) );
7050 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7052 // FollowProlongation(*seed1,0);
7053 // Int_t n = seed1->GetNumberOfClusters();
7054 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7055 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7058 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7062 SortTracks(fSeeds, 1);
7066 PrepareForBackProlongation(fSeeds,5.);
7067 PropagateBack(fSeeds);
7068 printf("Time for back propagation: \t");timer.Print();timer.Start();
7072 PrepareForProlongation(fSeeds,5.);
7073 PropagateForard2(fSeeds);
7075 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7076 // RemoveUsed(fSeeds,0.7,0.7,6);
7077 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7079 nseed=fSeeds->GetEntriesFast();
7081 for (Int_t i=0; i<nseed; i++) {
7082 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7084 Int_t nc=t.GetNumberOfClusters();
7086 MarkSeedFree( fSeeds->RemoveAt(i) );
7089 t.CookdEdx(0.02,0.6);
7090 // CookLabel(pt,0.1); //For comparison only
7091 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7092 if ((pt->IsActive() || (pt->fRemoval==10) )){
7093 cerr<<found++<<'\r';
7096 MarkSeedFree( fSeeds->RemoveAt(i) );
7101 // fNTracks = found;
7103 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7106 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7107 Info("Clusters2Tracks","Number of found tracks %d",found);
7109 // UnloadClusters();
7114 void AliTPCtracker::Tracking(TObjArray * arr)
7117 // tracking of the seeds
7120 fSectors = fOuterSec;
7121 ParallelTracking(arr,150,63);
7122 fSectors = fOuterSec;
7123 ParallelTracking(arr,63,0);
7126 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7131 static TObjArray arrTracks;
7132 TObjArray * arr = &arrTracks;
7134 fSectors = fOuterSec;
7137 for (Int_t sec=0;sec<fkNOS;sec++){
7138 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7139 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7140 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7143 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7155 TObjArray * AliTPCtracker::Tracking()
7159 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7162 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7164 TObjArray * seeds = new TObjArray;
7166 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7167 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7168 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7176 Float_t fnumber = 3.0;
7177 Float_t fdensity = 3.0;
7180 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7181 arr = MakeSeedsHLT( fEventHLT );
7183 SumTracks(seeds,arr);
7186 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7187 //SignClusters(seeds,fnumber,fdensity);
7194 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7198 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7199 SumTracks(seeds,arr);
7200 SignClusters(seeds,fnumber,fdensity);
7202 for (Int_t i=2;i<6;i+=2){
7203 // seed high pt tracks
7206 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7207 SumTracks(seeds,arr);
7208 SignClusters(seeds,fnumber,fdensity);
7213 // RemoveUsed(seeds,0.9,0.9,1);
7214 // UnsignClusters();
7215 // SignClusters(seeds,fnumber,fdensity);
7219 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7221 // seed high pt tracks
7225 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7226 SumTracks(seeds,arr);
7227 SignClusters(seeds,fnumber,fdensity);
7232 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7233 SumTracks(seeds,arr);
7234 SignClusters(seeds,fnumber,fdensity);
7245 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7249 // RemoveUsed(seeds,0.75,0.75,1);
7251 //SignClusters(seeds,fnumber,fdensity);
7260 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7261 SumTracks(seeds,arr);
7262 SignClusters(seeds,fnumber,fdensity);
7264 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7265 SumTracks(seeds,arr);
7266 SignClusters(seeds,fnumber,fdensity);
7268 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7269 SumTracks(seeds,arr);
7270 SignClusters(seeds,fnumber,fdensity);
7272 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7273 SumTracks(seeds,arr);
7274 SignClusters(seeds,fnumber,fdensity);
7276 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7277 SumTracks(seeds,arr);
7278 SignClusters(seeds,fnumber,fdensity);
7281 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7282 SumTracks(seeds,arr);
7283 SignClusters(seeds,fnumber,fdensity);
7287 for (Int_t delta = 9; delta<30; delta+=gapSec){
7293 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7294 SumTracks(seeds,arr);
7295 SignClusters(seeds,fnumber,fdensity);
7297 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7298 SumTracks(seeds,arr);
7299 SignClusters(seeds,fnumber,fdensity);
7312 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7318 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7319 SumTracks(seeds,arr);
7320 SignClusters(seeds,fnumber,fdensity);
7322 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7323 SumTracks(seeds,arr);
7324 SignClusters(seeds,fnumber,fdensity);
7328 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7339 TObjArray * AliTPCtracker::TrackingSpecial()
7342 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7343 // no primary vertex seeding tried
7347 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7349 TObjArray * seeds = new TObjArray;
7354 Float_t fnumber = 3.0;
7355 Float_t fdensity = 3.0;
7358 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7359 cuts[1] = 3.5; // max tan(phi) angle for seeding
7360 cuts[2] = 3.; // not used (cut on z primary vertex)
7361 cuts[3] = 3.5; // max tan(theta) angle for seeding
7363 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7365 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7366 SumTracks(seeds,arr);
7367 SignClusters(seeds,fnumber,fdensity);
7371 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7382 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7385 //sum tracks to common container
7386 //remove suspicious tracks
7387 // RS: Attention: supplied tracks come in the static array, don't delete them
7388 Int_t nseed = arr2->GetEntriesFast();
7389 for (Int_t i=0;i<nseed;i++){
7390 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7393 // remove tracks with too big curvature
7395 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7396 MarkSeedFree( arr2->RemoveAt(i) );
7399 // REMOVE VERY SHORT TRACKS
7400 if (pt->GetNumberOfClusters()<20){
7401 MarkSeedFree( arr2->RemoveAt(i) );
7404 // NORMAL ACTIVE TRACK
7405 if (pt->IsActive()){
7406 arr1->AddLast(arr2->RemoveAt(i));
7409 //remove not usable tracks
7410 if (pt->GetRemoval()!=10){
7411 MarkSeedFree( arr2->RemoveAt(i) );
7415 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7416 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7417 arr1->AddLast(arr2->RemoveAt(i));
7419 MarkSeedFree( arr2->RemoveAt(i) );
7423 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7428 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7431 // try to track in parralel
7433 Int_t nseed=arr->GetEntriesFast();
7434 //prepare seeds for tracking
7435 for (Int_t i=0; i<nseed; i++) {
7436 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7438 if (!t.IsActive()) continue;
7439 // follow prolongation to the first layer
7440 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7441 FollowProlongation(t, rfirst+1);
7446 for (Int_t nr=rfirst; nr>=rlast; nr--){
7447 if (nr<fInnerSec->GetNRows())
7448 fSectors = fInnerSec;
7450 fSectors = fOuterSec;
7451 // make indexes with the cluster tracks for given
7453 // find nearest cluster
7454 for (Int_t i=0; i<nseed; i++) {
7455 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7457 if (nr==80) pt->UpdateReference();
7458 if (!pt->IsActive()) continue;
7459 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7460 if (pt->GetRelativeSector()>17) {
7463 UpdateClusters(t,nr);
7465 // prolonagate to the nearest cluster - if founded
7466 for (Int_t i=0; i<nseed; i++) {
7467 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7469 if (!pt->IsActive()) continue;
7470 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7471 if (pt->GetRelativeSector()>17) {
7474 FollowToNextCluster(*pt,nr);
7479 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7483 // if we use TPC track itself we have to "update" covariance
7485 Int_t nseed= arr->GetEntriesFast();
7486 for (Int_t i=0;i<nseed;i++){
7487 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7491 //rotate to current local system at first accepted point
7492 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
7493 Int_t sec = (index&0xff000000)>>24;
7495 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
7496 if (angle1>TMath::Pi())
7497 angle1-=2.*TMath::Pi();
7498 Float_t angle2 = pt->GetAlpha();
7500 if (TMath::Abs(angle1-angle2)>0.001){
7501 if (!pt->Rotate(angle1-angle2)) return;
7502 //angle2 = pt->GetAlpha();
7503 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
7504 //if (pt->GetAlpha()<0)
7505 // pt->fRelativeSector+=18;
7506 //sec = pt->fRelativeSector;
7515 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
7519 // if we use TPC track itself we have to "update" covariance
7521 Int_t nseed= arr->GetEntriesFast();
7522 for (Int_t i=0;i<nseed;i++){
7523 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7526 pt->SetFirstPoint(pt->GetLastPoint());
7534 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
7537 // make back propagation
7539 Int_t nseed= arr->GetEntriesFast();
7540 for (Int_t i=0;i<nseed;i++){
7541 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7542 if (pt&& pt->GetKinkIndex(0)<=0) {
7543 //AliTPCseed *pt2 = new AliTPCseed(*pt);
7544 fSectors = fInnerSec;
7545 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
7546 //fSectors = fOuterSec;
7547 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7548 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
7549 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
7550 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
7553 if (pt&& pt->GetKinkIndex(0)>0) {
7554 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
7555 pt->SetFirstPoint(kink->GetTPCRow0());
7556 fSectors = fInnerSec;
7557 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7565 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
7568 // make forward propagation
7570 Int_t nseed= arr->GetEntriesFast();
7572 for (Int_t i=0;i<nseed;i++){
7573 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7575 FollowProlongation(*pt,0,1,1);
7584 Int_t AliTPCtracker::PropagateForward()
7587 // propagate track forward
7589 Int_t nseed = fSeeds->GetEntriesFast();
7590 for (Int_t i=0;i<nseed;i++){
7591 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
7593 AliTPCseed &t = *pt;
7594 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
7595 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
7596 if (alpha < 0. ) alpha += 2.*TMath::Pi();
7597 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
7601 fSectors = fOuterSec;
7602 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
7603 fSectors = fInnerSec;
7604 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
7613 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
7616 // make back propagation, in between row0 and row1
7620 fSectors = fInnerSec;
7623 if (row1<fSectors->GetNRows())
7626 r1 = fSectors->GetNRows()-1;
7628 if (row0<fSectors->GetNRows()&& r1>0 )
7629 FollowBackProlongation(*pt,r1);
7630 if (row1<=fSectors->GetNRows())
7633 r1 = row1 - fSectors->GetNRows();
7634 if (r1<=0) return 0;
7635 if (r1>=fOuterSec->GetNRows()) return 0;
7636 fSectors = fOuterSec;
7637 return FollowBackProlongation(*pt,r1);
7645 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
7647 // gets cluster shape
7649 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
7650 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
7651 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
7652 Double_t angulary = seed->GetSnp();
7654 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
7655 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
7658 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
7659 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
7661 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
7662 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
7663 seed->SetCurrentSigmaY2(sigmay*sigmay);
7664 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
7665 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
7666 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
7667 // Float_t padlength = GetPadPitchLength(row);
7669 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
7670 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
7672 // Float_t sresz = fkParam->GetZSigma();
7673 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
7675 Float_t wy = GetSigmaY(seed);
7676 Float_t wz = GetSigmaZ(seed);
7679 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
7680 printf("problem\n");
7687 //__________________________________________________________________________
7688 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
7689 //--------------------------------------------------------------------
7690 //This function "cooks" a track label. If label<0, this track is fake.
7691 //--------------------------------------------------------------------
7692 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
7694 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
7698 Int_t noc=t->GetNumberOfClusters();
7700 //printf("\nnot founded prolongation\n\n\n");
7706 AliTPCclusterMI *clusters[160];
7708 for (Int_t i=0;i<160;i++) {
7715 for (i=0; i<160 && current<noc; i++) {
7717 Int_t index=t->GetClusterIndex2(i);
7718 if (index<=0) continue;
7719 if (index&0x8000) continue;
7721 //clusters[current]=GetClusterMI(index);
7722 if (t->GetClusterPointer(i)){
7723 clusters[current]=t->GetClusterPointer(i);
7729 Int_t lab=123456789;
7730 for (i=0; i<noc; i++) {
7731 AliTPCclusterMI *c=clusters[i];
7733 lab=TMath::Abs(c->GetLabel(0));
7735 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7741 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7743 for (i=0; i<noc; i++) {
7744 AliTPCclusterMI *c=clusters[i];
7746 if (TMath::Abs(c->GetLabel(1)) == lab ||
7747 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7749 if (noc<=0) { lab=-1; return;}
7750 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7753 Int_t tail=Int_t(0.10*noc);
7756 for (i=1; i<160&&ind<tail; i++) {
7757 // AliTPCclusterMI *c=clusters[noc-i];
7758 AliTPCclusterMI *c=clusters[i];
7760 if (lab == TMath::Abs(c->GetLabel(0)) ||
7761 lab == TMath::Abs(c->GetLabel(1)) ||
7762 lab == TMath::Abs(c->GetLabel(2))) max++;
7765 if (max < Int_t(0.5*tail)) lab=-lab;
7772 //delete[] clusters;
7776 //__________________________________________________________________________
7777 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
7778 //--------------------------------------------------------------------
7779 //This function "cooks" a track label. If label<0, this track is fake.
7780 //--------------------------------------------------------------------
7781 Int_t noc=t->GetNumberOfClusters();
7783 //printf("\nnot founded prolongation\n\n\n");
7789 AliTPCclusterMI *clusters[160];
7791 for (Int_t i=0;i<160;i++) {
7798 for (i=0; i<160 && current<noc; i++) {
7799 if (i<first) continue;
7800 if (i>last) continue;
7801 Int_t index=t->GetClusterIndex2(i);
7802 if (index<=0) continue;
7803 if (index&0x8000) continue;
7805 //clusters[current]=GetClusterMI(index);
7806 if (t->GetClusterPointer(i)){
7807 clusters[current]=t->GetClusterPointer(i);
7812 //if (noc<5) return -1;
7813 Int_t lab=123456789;
7814 for (i=0; i<noc; i++) {
7815 AliTPCclusterMI *c=clusters[i];
7817 lab=TMath::Abs(c->GetLabel(0));
7819 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7825 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7827 for (i=0; i<noc; i++) {
7828 AliTPCclusterMI *c=clusters[i];
7830 if (TMath::Abs(c->GetLabel(1)) == lab ||
7831 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7833 if (noc<=0) { lab=-1; return -1;}
7834 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7837 Int_t tail=Int_t(0.10*noc);
7840 for (i=1; i<160&&ind<tail; i++) {
7841 // AliTPCclusterMI *c=clusters[noc-i];
7842 AliTPCclusterMI *c=clusters[i];
7844 if (lab == TMath::Abs(c->GetLabel(0)) ||
7845 lab == TMath::Abs(c->GetLabel(1)) ||
7846 lab == TMath::Abs(c->GetLabel(2))) max++;
7849 if (max < Int_t(0.5*tail)) lab=-lab;
7852 // t->SetLabel(lab);
7856 //delete[] clusters;
7860 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
7862 //return pad row number for given x vector
7863 Float_t phi = TMath::ATan2(x[1],x[0]);
7864 if(phi<0) phi=2.*TMath::Pi()+phi;
7865 // Get the local angle in the sector philoc
7866 const Float_t kRaddeg = 180/3.14159265358979312;
7867 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
7868 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
7869 return GetRowNumber(localx);
7874 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
7876 //-----------------------------------------------------------------------
7877 // Fill the cluster and sharing bitmaps of the track
7878 //-----------------------------------------------------------------------
7880 Int_t firstpoint = 0;
7881 Int_t lastpoint = 159;
7882 AliTPCTrackerPoint *point;
7883 AliTPCclusterMI *cluster;
7886 TBits clusterMap(159);
7887 TBits sharedMap(159);
7889 for (int iter=firstpoint; iter<lastpoint; iter++) {
7890 // Change to cluster pointers to see if we have a cluster at given padrow
7892 cluster = t->GetClusterPointer(iter);
7894 clusterMap.SetBitNumber(iter, kTRUE);
7895 point = t->GetTrackPoint(iter);
7896 if (point->IsShared())
7897 sharedMap.SetBitNumber(iter,kTRUE);
7899 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
7900 fitMap.SetBitNumber(iter, kTRUE);
7904 esd->SetTPCClusterMap(clusterMap);
7905 esd->SetTPCSharedMap(sharedMap);
7906 esd->SetTPCFitMap(fitMap);
7907 if (nclsf != t->GetNumberOfClusters())
7908 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
7911 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
7913 // return flag if there is findable cluster at given position
7916 Float_t z = track.GetZ();
7918 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
7919 TMath::Abs(z)<fkParam->GetZLength(0) &&
7920 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
7926 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
7928 // Adding systematic error estimate to the covariance matrix
7929 // !!!! the systematic error for element 4 is in 1/GeV
7930 // 03.03.2012 MI changed in respect to the previous versions
7931 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7933 // use only the diagonal part if not specified otherwise
7934 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
7936 Double_t *covarS= (Double_t*)seed->GetCovariance();
7937 Double_t factor[5]={1,1,1,1,1};
7938 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
7939 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
7940 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
7941 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
7942 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
7944 factor[0]=factor[2];
7945 factor[4]=factor[2];
7951 for (Int_t i=0; i<5; i++){
7952 for (Int_t j=i; j<5; j++){
7953 Int_t index=seed->GetIndex(i,j);
7954 covarS[index]*=factor[i]*factor[j];
7960 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
7962 // Adding systematic error - as additive factor without correlation
7964 // !!!! the systematic error for element 4 is in 1/GeV
7965 // 03.03.2012 MI changed in respect to the previous versions
7967 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7968 Double_t *covarIn= (Double_t*)seed->GetCovariance();
7970 for (Int_t i=0;i<15;i++) covar[i]=0;
7976 covar[0] = param[0]*param[0];
7977 covar[2] = param[1]*param[1];
7978 covar[5] = param[2]*param[2];
7979 covar[9] = param[3]*param[3];
7980 covar[14]= param[4]*param[4];
7982 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
7984 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
7985 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
7987 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
7988 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
7989 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
7991 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
7992 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
7993 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
7994 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
7996 seed->AddCovariance(covar);
7999 //_____________________________________________________________________________
8000 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8003 // check events affected by TPC HV dip
8005 if(!esdEvent) return kFALSE;
8008 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8009 if(!db) return kFALSE;
8010 db->SetRun(esdEvent->GetRunNumber());
8012 // maximum allowed voltage before an event is identified as a dip event
8013 // and scanning period
8014 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8015 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8016 const Double_t tevSec = esdEvent->GetTimeStamp();
8018 for(Int_t sector=0; sector<72; sector++)
8020 // don't use excluded chambers, since the state is not defined at all
8021 if (!db->GetChamberHVStatus(sector)) continue;
8023 // get hv sensor of the chamber
8024 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8025 if (!sensor) continue;
8026 TGraph *grSensor=sensor->GetGraph();
8027 if (!grSensor) continue;
8028 if (grSensor->GetN()<1) continue;
8031 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8032 if(median < 1.) continue;
8034 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8035 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8036 if (tevSec-dipEventScanPeriod>nextTime) continue;
8037 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8038 if (deltaV>kTPCHVdip) {
8039 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8042 if (nextTime>tevSec+dipEventScanPeriod) break;
8049 //________________________________________
8050 void AliTPCtracker::MarkSeedFree(TObject *sd)
8052 // account that this seed is "deleted"
8053 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8055 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8058 int id = seed->GetPoolID();
8060 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8063 // AliInfo(Form("%d %p",id, seed));
8064 fSeedsPool->RemoveAt(id);
8065 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8066 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8069 //________________________________________
8070 TObject *&AliTPCtracker::NextFreeSeed()
8072 // return next free slot where the seed can be created
8073 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8074 // AliInfo(Form("%d",fLastSeedID));
8075 return (*fSeedsPool)[ fLastSeedID ];
8079 //________________________________________
8080 void AliTPCtracker::ResetSeedsPool()
8082 // mark all seeds in the pool as unused
8083 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8085 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8088 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8091 Double_t x= GetXrow(nrow);
8092 Double_t ymax= GetMaxY(nrow);
8098 if (!t.PropagateTo(x) ){
8099 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8105 Double_t y = t.GetY();
8107 if( rotate!=-1 ) rotate=1;
8108 } else if (y <-ymax) {
8109 if( rotate!=1 ) rotate = -1;
8111 if( rotate==0 ) break;
8112 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8113 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8114 //cout<<"can't rotate "<<endl;
8118 nRotations+= rotate;
8120 if( nRotations!=0 ){
8121 int newSec= t.GetRelativeSector()+nRotations;
8122 if( newSec>=fN ) newSec-=fN;
8123 else if( newSec<0 ) newSec +=fN;
8124 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8125 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8126 t.SetRelativeSector(newSec);
8131 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8134 // try to track in parralel
8136 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8139 Int_t nseed=arr->GetEntriesFast();
8140 //cout<<"Parallel tracking My.."<<endl;
8141 double shapeY2[160], shapeZ2[160];
8142 Int_t clusterIndex[160];
8144 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8145 //if( iSeed!=1 ) continue;
8146 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8150 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8154 for( int iter=0; iter<3; iter++ ){
8157 t.SetLastPoint(0); // first cluster in track position
8158 t.SetFirstPoint(nRows-1);
8159 t.ResetCovariance(.1);
8160 t.SetNumberOfClusters(0);
8161 for( int i=0; i<nRows; i++ ){
8165 t.SetClusterIndex2(i,-1);
8166 t.SetClusterIndex(i,-1);
8169 // pick up the clusters
8171 Double_t roady = 20.;
8172 Double_t roadz = 20.;
8179 t0.SetRelativeSector(t.GetRelativeSector());
8180 t0.SetLastPoint(0); // first cluster in track position
8181 t0.SetFirstPoint(159);
8182 for (Int_t nr=0; nr<nRows; nr++){
8183 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8184 else fSectors=fOuterSec;
8186 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8187 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8188 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8191 if (!IsActive(t0.GetRelativeSector(),nr)) {
8197 shapeY2[nr]=t0.GetCurrentSigmaY2();
8198 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8201 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8202 if( !krow ) continue;
8204 t.SetClusterIndex2(nr,-3); // foundable
8205 t.SetClusterIndex(nr,-3);
8207 AliTPCclusterMI *cl=0;
8209 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8211 double dy = cl->GetY()-t0.GetY();
8212 double dz = cl->GetZ()-t0.GetZ();
8213 double dr = sqrt(dy*dy+dz*dz);
8215 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8218 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8220 t0.SetClusterPointer(nr, cl);
8221 clusterIndex[nr] = krow.GetIndex(uindex);
8222 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8223 t0.SetLastPoint(nr);
8229 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8232 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8236 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8238 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8239 if( !t0.GetClusterPointer(nr) ) continue;
8240 int d = TMath::Abs(nr-midRow);
8248 // first fit 3 base points
8250 //cout<<"Fit3: "<<endl;
8251 for( int icl=0; icl<3; icl++){
8252 int nr = basePoints[icl];
8254 if( nr>=fInnerSec->GetNRows()){
8255 lr = nr - fInnerSec->GetNRows();
8257 } else fSectors=fInnerSec;
8259 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8261 //cout<<"WRONG!!!!"<<endl;
8264 int iSec = cl->GetDetector() %fkNIS;
8265 int rotate = iSec - t.GetRelativeSector();
8267 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8268 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8269 //cout<<"can't rotate "<<endl;
8272 t.SetRelativeSector(iSec);
8274 Double_t x= cl->GetX();
8275 if (!t.PropagateTo(x)){
8276 //cout<<"can't propagate to x="<<x<<endl;
8280 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8281 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8284 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8286 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8287 t.SetCurrentCluster(cl);
8290 t.SetErrorY2(shapeY2[nr]);
8291 t.SetErrorZ2(shapeZ2[nr]);
8294 for( int j=0; j<15; j++ ) cov[j]=0;
8300 t.AliExternalTrackParam::AddCovariance(cov);
8302 if( !UpdateTrack(&t,0) ){
8303 //cout<<"Can not update"<<endl;
8305 t.SetClusterIndex2(nr,-1);
8306 t.SetClusterIndex(nr,-1);
8307 t.SetClusterPointer(nr,0);
8310 //t.SetClusterPointer(nr, cl);
8313 //t.SetLastPoint(t0.GetLastPoint());
8314 //t.SetFirstPoint(t0.GetFirstPoint());
8316 //cout<<"Fit: "<<endl;
8317 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8319 if( nr>=fInnerSec->GetNRows()){
8320 lr = nr - fInnerSec->GetNRows();
8322 } else fSectors=fInnerSec;
8325 if( nr == basePoints[0] ) continue;
8326 if( nr == basePoints[1] ) continue;
8327 if( nr == basePoints[2] ) continue;
8329 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8332 int iSec = cl->GetDetector() %fkNIS;
8333 int rotate = iSec - t.GetRelativeSector();
8335 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8336 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8337 //cout<<"can't rotate "<<endl;
8340 t.SetRelativeSector(iSec);
8342 Double_t x= cl->GetX();
8343 if (!t.PropagateTo(x)){
8344 //cout<<"can't propagate to x="<<x<<endl;
8347 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8348 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8352 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8354 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8355 t.SetCurrentCluster(cl);
8357 t.SetErrorY2(shapeY2[nr]);
8358 t.SetErrorZ2(shapeZ2[nr]);
8360 if( !UpdateTrack(&t,0) ){
8361 //cout<<"Can not update"<<endl;
8363 t.SetClusterIndex2(nr,-1);
8364 t.SetClusterIndex(nr,-1);
8367 //t.SetClusterPointer(nr, cl);
8370 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8373 //cout<<"fitted track"<<iSeed<<endl;
8375 //cout<<"Statistics: "<<endl;
8376 Int_t foundable,found,shared;
8377 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8378 t.SetNFoundable(foundable);
8379 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8385 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8390 if( !hltEvent ) return 0;
8393 Int_t nentr=hltEvent->GetNumberOfTracks();
8395 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8397 TObjArray * seeds = new TObjArray(nentr);
8399 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8402 Int_t nTr=hltEvent->GetNumberOfTracks();
8404 for( int itr=0; itr<nTr; itr++ ){
8405 //if( itr!=97 ) continue;
8406 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8407 if( !param ) continue;
8408 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8409 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8411 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8412 tr.SetNumberOfClusters(0);
8413 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8415 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8416 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8417 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8419 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8420 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8422 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8423 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8425 seed->Rotate(alphaSec - alpha);
8427 seed->SetPoolID(fLastSeedID);
8428 seed->SetIsSeeding(kTRUE);
8429 seed->SetSeed1(nup-1);
8430 seed->SetSeed2(nup-2);
8431 seed->SetSeedType(0);
8432 seed->SetFirstPoint(-1);
8433 seed->SetLastPoint(-1);
8434 seeds->AddLast(seed); // note, track is seed, don't free the seed
8436 //if( index>3 ) break;
8440 fSectors = fOuterSec;
8442 TrackFollowingHLT(seeds );
8444 nTr = seeds->GetEntriesFast();
8445 for( int itr=0; itr<nTr; itr++ ){
8446 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8447 if( !seed ) continue;
8448 //FollowBackProlongation(*seed,0);
8449 // cout<<seed->GetNumberOfClusters()<<endl;
8450 Int_t foundable,found,shared;
8451 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8452 seed->SetNFoundable(foundable);
8453 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8454 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8455 //MarkSeedFree(seeds->RemoveAt(itr));
8458 if (seed->GetNumberOfClusters()<30 ||
8459 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8460 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8461 MarkSeedFree(seeds->RemoveAt(itr));
8465 for( int ir=0; ir<nup; ir++){
8466 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8470 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8474 void AliTPCtracker::FillClusterOccupancyInfo()
8476 //fill the cluster occupancy info into the ESD friend
8477 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8478 if (!esdFriend) return;
8480 for (Int_t isector=0; isector<18; isector++){
8481 AliTPCtrackerSector &iroc = fInnerSec[isector];
8482 AliTPCtrackerSector &oroc = fOuterSec[isector];
8484 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
8485 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
8486 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
8487 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
8488 //clusters used in tracking
8489 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
8490 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
8491 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
8492 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));