1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 //-------------------------------------------------------
18 // Implementation of the TPC tracker
20 // Origin: Marian Ivanov Marian.Ivanov@cern.ch
22 // AliTPC parallel tracker
24 // The track fitting is based on Kalman filtering approach
26 // The track finding steps:
27 // 1. Seeding - with and without vertex constraint
28 // - seeding with vertex constain done at first n^2 proble
29 // - seeding without vertex constraint n^3 problem
30 // 2. Tracking - follow prolongation road - find cluster - update kalman track
32 // The seeding and tracking is repeated several times, in different seeding region.
33 // This approach enables to find the track which cannot be seeded in some region of TPC
34 // This can happen because of low momenta (track do not reach outer radius), or track is currently in the ded region between sectors, or the track is for the moment overlapped with other track (seed quality is poor) ...
36 // With this approach we reach almost 100 % efficiency also for high occupancy events.
37 // (If the seeding efficiency in a region is about 90 % than with logical or of several
38 // regions we will reach 100% (in theory - supposing independence)
40 // Repeating several seeding - tracking procedures some of the tracks can be find
43 // The procedures to remove multi find tacks are impremented:
44 // RemoveUsed2 - fast procedure n problem -
45 // Algorithm - Sorting tracks according quality
46 // remove tracks with some shared fraction
47 // Sharing in respect to all tacks
48 // Signing clusters in gold region
49 // FindSplitted - slower algorithm n^2
50 // Sort the tracks according quality
51 // Loop over pair of tracks
52 // If overlap with other track bigger than threshold - remove track
54 // FindCurling - Finds the pair of tracks which are curling
55 // - About 10% of tracks can be find with this procedure
56 // The combinatorial background is too big to be used in High
57 // multiplicity environment
58 // - n^2 problem - Slow procedure - currently it is disabled because of
61 // The number of splitted tracks can be reduced disabling the sharing of the cluster.
62 // tpcRecoParam-> SetClusterSharing(kFALSE);
63 // IT IS HIGHLY non recomended to use it in high flux enviroonment
64 // Even using this switch some tracks can be found more than once
65 // (because of multiple seeding and low quality tracks which will not cross full chamber)
68 // The tracker itself can be debugged - the information about tracks can be stored in several // phases of the reconstruction
69 // To enable storage of the TPC tracks in the ESD friend track
70 // use AliTPCReconstructor::SetStreamLevel(n);
72 // The debug level - different procedure produce tree for numerical debugging
73 // To enable them set AliTPCReconstructor::SetStreamLevel(n); where nis bigger 1
77 // Adding systematic errors to the covariance:
79 // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
80 // of the tracks (not to the clusters as they are dependent):
81 // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
82 // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
83 // The default values are 0.
85 // The sytematic errors are added to the covariance matrix in following places:
87 // 1. During fisrt itteration - AliTPCtracker::FillESD
88 // 2. Second iteration -
89 // 2.a ITS->TPC - AliTPCtracker::ReadSeeds
90 // 2.b TPC->TRD - AliTPCtracker::PropagateBack
91 // 3. Third iteration -
92 // 3.a TRD->TPC - AliTPCtracker::ReadSeeds
93 // 3.b TPC->ITS - AliTPCtracker::RefitInward
95 // There are several places in the code which can be numerically debuged
96 // This code is keeped in order to enable code development and to check the calibration implementtion
98 // 1. ErrParam stream - dump information about
100 // 2.a) cluster error estimate
101 // 3.a) cluster shape estimate
104 // Debug streamer levels:
106 //-------------------------------------------------------
111 #include "Riostream.h"
112 #include <TClonesArray.h>
114 #include <TObjArray.h>
116 #include <TGraphErrors.h>
117 #include <TTimeStamp.h>
119 #include "AliComplexCluster.h"
120 #include "AliESDEvent.h"
121 #include "AliESDtrack.h"
122 #include "AliESDVertex.h"
125 #include "AliHelix.h"
126 #include "AliRunLoader.h"
127 #include "AliTPCClustersRow.h"
128 #include "AliTPCParam.h"
129 #include "AliTPCReconstructor.h"
130 #include "AliTPCpolyTrack.h"
131 #include "AliTPCreco.h"
132 #include "AliTPCseed.h"
134 #include "AliTPCtrackerSector.h"
135 #include "AliTPCtracker.h"
136 #include "TStopwatch.h"
137 #include "AliTPCReconstructor.h"
138 #include "AliAlignObj.h"
139 #include "AliTrackPointArray.h"
141 #include "AliTPCcalibDB.h"
142 #include "AliTPCcalibDButil.h"
143 #include "AliTPCTransform.h"
144 #include "AliTPCClusterParam.h"
145 #include "AliTPCdEdxInfo.h"
146 #include "AliDCSSensorArray.h"
147 #include "AliDCSSensor.h"
149 #include "AliCosmicTracker.h"
155 ClassImp(AliTPCtracker)
159 class AliTPCFastMath {
162 static Double_t FastAsin(Double_t x);
164 static Double_t fgFastAsin[20000]; //lookup table for fast asin computation
167 Double_t AliTPCFastMath::fgFastAsin[20000];
168 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
170 AliTPCFastMath::AliTPCFastMath(){
172 // initialized lookup table;
173 for (Int_t i=0;i<10000;i++){
174 fgFastAsin[2*i] = TMath::ASin(i/10000.);
175 fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
179 Double_t AliTPCFastMath::FastAsin(Double_t x){
181 // return asin using lookup table
183 Int_t index = int(x*10000);
184 return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
187 Int_t index = int(x*10000);
188 return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
190 //__________________________________________________________________
191 AliTPCtracker::AliTPCtracker()
219 // default constructor
221 for (Int_t irow=0; irow<200; irow++){
228 //_____________________________________________________________________
232 Int_t AliTPCtracker::UpdateTrack(AliTPCseed * track, Int_t accept){
234 //update track information using current cluster - track->fCurrentCluster
237 AliTPCclusterMI* c =track->GetCurrentCluster();
238 if (accept > 0) //sign not accepted clusters
239 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);
240 else // unsign accpeted clusters
241 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);
242 UInt_t i = track->GetCurrentClusterIndex1();
244 Int_t sec=(i&0xff000000)>>24;
245 //Int_t row = (i&0x00ff0000)>>16;
246 track->SetRow((i&0x00ff0000)>>16);
247 track->SetSector(sec);
248 // Int_t index = i&0xFFFF;
249 if (sec>=fkParam->GetNInnerSector()) track->SetRow(track->GetRow()+fkParam->GetNRowLow());
250 track->SetClusterIndex2(track->GetRow(), i);
251 //track->fFirstPoint = row;
252 //if ( track->fLastPoint<row) track->fLastPoint =row;
253 // if (track->fRow<0 || track->fRow>160) {
254 // printf("problem\n");
256 if (track->GetFirstPoint()>track->GetRow())
257 track->SetFirstPoint(track->GetRow());
258 if (track->GetLastPoint()<track->GetRow())
259 track->SetLastPoint(track->GetRow());
262 track->SetClusterPointer(track->GetRow(),c);
265 Double_t angle2 = track->GetSnp()*track->GetSnp();
267 //SET NEW Track Point
269 if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
271 angle2 = TMath::Sqrt(angle2/(1-angle2));
272 AliTPCTrackerPoint &point =*(track->GetTrackPoint(track->GetRow()));
274 point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
275 point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
276 point.SetErrY(sqrt(track->GetErrorY2()));
277 point.SetErrZ(sqrt(track->GetErrorZ2()));
279 point.SetX(track->GetX());
280 point.SetY(track->GetY());
281 point.SetZ(track->GetZ());
282 point.SetAngleY(angle2);
283 point.SetAngleZ(track->GetTgl());
284 if (point.IsShared()){
285 track->SetErrorY2(track->GetErrorY2()*4);
286 track->SetErrorZ2(track->GetErrorZ2()*4);
290 Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
292 // track->SetErrorY2(track->GetErrorY2()*1.3);
293 // track->SetErrorY2(track->GetErrorY2()+0.01);
294 // track->SetErrorZ2(track->GetErrorZ2()*1.3);
295 // track->SetErrorZ2(track->GetErrorZ2()+0.005);
297 if (accept>0) return 0;
298 if (track->GetNumberOfClusters()%20==0){
299 // if (track->fHelixIn){
300 // TClonesArray & larr = *(track->fHelixIn);
301 // Int_t ihelix = larr.GetEntriesFast();
302 // new(larr[ihelix]) AliHelix(*track) ;
305 track->SetNoCluster(0);
306 return track->Update(c,chi2,i);
311 Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
314 // decide according desired precision to accept given
315 // cluster for tracking
317 seed->GetProlongation(cluster->GetX(),yt,zt);
318 Double_t sy2=ErrY2(seed,cluster);
319 Double_t sz2=ErrZ2(seed,cluster);
321 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
322 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
323 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
324 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
325 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
326 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
327 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
328 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
330 Double_t rdistance2 = rdistancey2+rdistancez2;
333 if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
334 Float_t rmsy2 = seed->GetCurrentSigmaY2();
335 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
336 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
337 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
338 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
339 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
340 AliExternalTrackParam param(*seed);
341 static TVectorD gcl(3),gtr(3);
343 param.GetXYZ(gcl.GetMatrixArray());
344 cluster->GetGlobalXYZ(gclf);
345 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
348 if (AliTPCReconstructor::StreamLevel()>2) {
349 (*fDebugStreamer)<<"ErrParam"<<
362 "rmsy2p30="<<rmsy2p30<<
363 "rmsz2p30="<<rmsz2p30<<
364 "rmsy2p30R="<<rmsy2p30R<<
365 "rmsz2p30R="<<rmsz2p30R<<
366 // normalize distance -
367 "rdisty="<<rdistancey2<<
368 "rdistz="<<rdistancez2<<
369 "rdist="<<rdistance2<< //
373 //return 0; // temporary
374 if (rdistance2>32) return 3;
377 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
378 return 2; //suspisiouce - will be changed
380 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
381 // strict cut on overlaped cluster
382 return 2; //suspisiouce - will be changed
384 if ( (rdistancey2>1. || rdistancez2>6.25 )
385 && cluster->GetType()<0){
386 seed->SetNFoundable(seed->GetNFoundable()-1);
390 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
392 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
393 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
406 //_____________________________________________________________________________
407 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
409 fkNIS(par->GetNInnerSector()/2),
411 fkNOS(par->GetNOuterSector()/2),
434 //---------------------------------------------------------------------
435 // The main TPC tracker constructor
436 //---------------------------------------------------------------------
437 fInnerSec=new AliTPCtrackerSector[fkNIS];
438 fOuterSec=new AliTPCtrackerSector[fkNOS];
441 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
442 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
445 Int_t nrowlow = par->GetNRowLow();
446 Int_t nrowup = par->GetNRowUp();
449 for (i=0;i<nrowlow;i++){
450 fXRow[i] = par->GetPadRowRadiiLow(i);
451 fPadLength[i]= par->GetPadPitchLength(0,i);
452 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
456 for (i=0;i<nrowup;i++){
457 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
458 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
459 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
462 if (AliTPCReconstructor::StreamLevel()>0) {
463 fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
466 fSeedsPool = new TClonesArray("AliTPCseed",1000);
468 //________________________________________________________________________
469 AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
496 //------------------------------------
497 // dummy copy constructor
498 //------------------------------------------------------------------
500 for (Int_t irow=0; irow<200; irow++){
507 AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
509 //------------------------------
511 //--------------------------------------------------------------
514 //_____________________________________________________________________________
515 AliTPCtracker::~AliTPCtracker() {
516 //------------------------------------------------------------------
517 // TPC tracker destructor
518 //------------------------------------------------------------------
525 if (fDebugStreamer) delete fDebugStreamer;
526 if (fSeedsPool) delete fSeedsPool;
530 void AliTPCtracker::FillESD(const TObjArray* arr)
534 //fill esds using updated tracks
537 // write tracks to the event
538 // store index of the track
539 Int_t nseed=arr->GetEntriesFast();
540 //FindKinks(arr,fEvent);
541 for (Int_t i=0; i<nseed; i++) {
542 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
546 if (AliTPCReconstructor::StreamLevel()>1) {
547 (*fDebugStreamer)<<"Track0"<<
551 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
552 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
553 pt->PropagateTo(fkParam->GetInnerRadiusLow());
556 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
558 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
559 iotrack.SetTPCPoints(pt->GetPoints());
560 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
561 iotrack.SetV0Indexes(pt->GetV0Indexes());
562 // iotrack.SetTPCpid(pt->fTPCr);
563 //iotrack.SetTPCindex(i);
564 MakeESDBitmaps(pt, &iotrack);
565 fEvent->AddTrack(&iotrack);
569 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
571 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
572 iotrack.SetTPCPoints(pt->GetPoints());
573 //iotrack.SetTPCindex(i);
574 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
575 iotrack.SetV0Indexes(pt->GetV0Indexes());
576 MakeESDBitmaps(pt, &iotrack);
577 // iotrack.SetTPCpid(pt->fTPCr);
578 fEvent->AddTrack(&iotrack);
582 // short tracks - maybe decays
584 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
585 Int_t found,foundable,shared;
586 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
587 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
589 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
590 //iotrack.SetTPCindex(i);
591 iotrack.SetTPCPoints(pt->GetPoints());
592 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
593 iotrack.SetV0Indexes(pt->GetV0Indexes());
594 MakeESDBitmaps(pt, &iotrack);
595 //iotrack.SetTPCpid(pt->fTPCr);
596 fEvent->AddTrack(&iotrack);
601 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
602 Int_t found,foundable,shared;
603 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
604 if (found<20) continue;
605 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
608 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
609 iotrack.SetTPCPoints(pt->GetPoints());
610 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
611 iotrack.SetV0Indexes(pt->GetV0Indexes());
612 MakeESDBitmaps(pt, &iotrack);
613 //iotrack.SetTPCpid(pt->fTPCr);
614 //iotrack.SetTPCindex(i);
615 fEvent->AddTrack(&iotrack);
618 // short tracks - secondaties
620 if ( (pt->GetNumberOfClusters()>30) ) {
621 Int_t found,foundable,shared;
622 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
623 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
625 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
626 iotrack.SetTPCPoints(pt->GetPoints());
627 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
628 iotrack.SetV0Indexes(pt->GetV0Indexes());
629 MakeESDBitmaps(pt, &iotrack);
630 //iotrack.SetTPCpid(pt->fTPCr);
631 //iotrack.SetTPCindex(i);
632 fEvent->AddTrack(&iotrack);
637 if ( (pt->GetNumberOfClusters()>15)) {
638 Int_t found,foundable,shared;
639 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
640 if (found<15) continue;
641 if (foundable<=0) continue;
642 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
643 if (float(found)/float(foundable)<0.8) continue;
646 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
647 iotrack.SetTPCPoints(pt->GetPoints());
648 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
649 iotrack.SetV0Indexes(pt->GetV0Indexes());
650 MakeESDBitmaps(pt, &iotrack);
651 // iotrack.SetTPCpid(pt->fTPCr);
652 //iotrack.SetTPCindex(i);
653 fEvent->AddTrack(&iotrack);
657 // >> account for suppressed tracks in the kink indices (RS)
658 int nESDtracks = fEvent->GetNumberOfTracks();
659 for (int it=nESDtracks;it--;) {
660 AliESDtrack* esdTr = fEvent->GetTrack(it);
661 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
662 for (int ik=0;ik<3;ik++) {
664 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
665 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
667 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
670 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
673 // << account for suppressed tracks in the kink indices (RS)
674 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
682 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
685 // Use calibrated cluster error from OCDB
687 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
689 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
690 Int_t ctype = cl->GetType();
691 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
692 Double_t angle = seed->GetSnp()*seed->GetSnp();
693 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
694 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
696 erry2+=0.5; // edge cluster
700 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
701 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
702 erry2+=addErr*addErr;
703 seed->SetErrorY2(erry2);
707 //calculate look-up table at the beginning
708 // static Bool_t ginit = kFALSE;
709 // static Float_t gnoise1,gnoise2,gnoise3;
710 // static Float_t ggg1[10000];
711 // static Float_t ggg2[10000];
712 // static Float_t ggg3[10000];
713 // static Float_t glandau1[10000];
714 // static Float_t glandau2[10000];
715 // static Float_t glandau3[10000];
717 // static Float_t gcor01[500];
718 // static Float_t gcor02[500];
719 // static Float_t gcorp[500];
723 // if (ginit==kFALSE){
724 // for (Int_t i=1;i<500;i++){
725 // Float_t rsigma = float(i)/100.;
726 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
727 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
728 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
732 // for (Int_t i=3;i<10000;i++){
736 // Float_t amp = float(i);
737 // Float_t padlength =0.75;
738 // gnoise1 = 0.0004/padlength;
739 // Float_t nel = 0.268*amp;
740 // Float_t nprim = 0.155*amp;
741 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
742 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
743 // if (glandau1[i]>1) glandau1[i]=1;
744 // glandau1[i]*=padlength*padlength/12.;
748 // gnoise2 = 0.0004/padlength;
750 // nprim = 0.133*amp;
751 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
752 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
753 // if (glandau2[i]>1) glandau2[i]=1;
754 // glandau2[i]*=padlength*padlength/12.;
759 // gnoise3 = 0.0004/padlength;
761 // nprim = 0.133*amp;
762 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
763 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
764 // if (glandau3[i]>1) glandau3[i]=1;
765 // glandau3[i]*=padlength*padlength/12.;
773 // Int_t amp = int(TMath::Abs(cl->GetQ()));
775 // seed->SetErrorY2(1.);
779 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
780 // Int_t ctype = cl->GetType();
781 // Float_t padlength= GetPadPitchLength(seed->GetRow());
782 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
783 // angle2 = angle2/(1-angle2);
785 // //cluster "quality"
786 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
789 // if (fSectors==fInnerSec){
790 // snoise2 = gnoise1;
791 // res = ggg1[amp]*z+glandau1[amp]*angle2;
792 // if (ctype==0) res *= gcor01[rsigmay];
795 // res*= gcorp[rsigmay];
799 // if (padlength<1.1){
800 // snoise2 = gnoise2;
801 // res = ggg2[amp]*z+glandau2[amp]*angle2;
802 // if (ctype==0) res *= gcor02[rsigmay];
805 // res*= gcorp[rsigmay];
809 // snoise2 = gnoise3;
810 // res = ggg3[amp]*z+glandau3[amp]*angle2;
811 // if (ctype==0) res *= gcor02[rsigmay];
814 // res*= gcorp[rsigmay];
821 // res*=2.4; // overestimate error 2 times
825 // if (res<2*snoise2)
828 // seed->SetErrorY2(res);
836 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
839 // Use calibrated cluster error from OCDB
841 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
843 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
844 Int_t ctype = cl->GetType();
845 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
847 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
848 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
849 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
850 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
852 errz2+=0.5; // edge cluster
856 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
857 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
858 errz2+=addErr*addErr;
859 seed->SetErrorZ2(errz2);
865 // //seed->SetErrorY2(0.1);
867 // //calculate look-up table at the beginning
868 // static Bool_t ginit = kFALSE;
869 // static Float_t gnoise1,gnoise2,gnoise3;
870 // static Float_t ggg1[10000];
871 // static Float_t ggg2[10000];
872 // static Float_t ggg3[10000];
873 // static Float_t glandau1[10000];
874 // static Float_t glandau2[10000];
875 // static Float_t glandau3[10000];
877 // static Float_t gcor01[1000];
878 // static Float_t gcor02[1000];
879 // static Float_t gcorp[1000];
883 // if (ginit==kFALSE){
884 // for (Int_t i=1;i<1000;i++){
885 // Float_t rsigma = float(i)/100.;
886 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
887 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
888 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
892 // for (Int_t i=3;i<10000;i++){
896 // Float_t amp = float(i);
897 // Float_t padlength =0.75;
898 // gnoise1 = 0.0004/padlength;
899 // Float_t nel = 0.268*amp;
900 // Float_t nprim = 0.155*amp;
901 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
902 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
903 // if (glandau1[i]>1) glandau1[i]=1;
904 // glandau1[i]*=padlength*padlength/12.;
908 // gnoise2 = 0.0004/padlength;
910 // nprim = 0.133*amp;
911 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
912 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
913 // if (glandau2[i]>1) glandau2[i]=1;
914 // glandau2[i]*=padlength*padlength/12.;
919 // gnoise3 = 0.0004/padlength;
921 // nprim = 0.133*amp;
922 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
923 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
924 // if (glandau3[i]>1) glandau3[i]=1;
925 // glandau3[i]*=padlength*padlength/12.;
933 // Int_t amp = int(TMath::Abs(cl->GetQ()));
935 // seed->SetErrorY2(1.);
939 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
940 // Int_t ctype = cl->GetType();
941 // Float_t padlength= GetPadPitchLength(seed->GetRow());
943 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
944 // // if (angle2<0.6) angle2 = 0.6;
945 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
947 // //cluster "quality"
948 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
951 // if (fSectors==fInnerSec){
952 // snoise2 = gnoise1;
953 // res = ggg1[amp]*z+glandau1[amp]*angle2;
954 // if (ctype==0) res *= gcor01[rsigmaz];
957 // res*= gcorp[rsigmaz];
961 // if (padlength<1.1){
962 // snoise2 = gnoise2;
963 // res = ggg2[amp]*z+glandau2[amp]*angle2;
964 // if (ctype==0) res *= gcor02[rsigmaz];
967 // res*= gcorp[rsigmaz];
971 // snoise2 = gnoise3;
972 // res = ggg3[amp]*z+glandau3[amp]*angle2;
973 // if (ctype==0) res *= gcor02[rsigmaz];
976 // res*= gcorp[rsigmaz];
985 // if ((ctype<0) &&<70){
990 // if (res<2*snoise2)
992 // if (res>3) res =3;
993 // seed->SetErrorZ2(res);
1001 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1003 //rotate to track "local coordinata
1004 Float_t x = seed->GetX();
1005 Float_t y = seed->GetY();
1006 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1009 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1010 if (!seed->Rotate(fSectors->GetAlpha()))
1012 } else if (y <-ymax) {
1013 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1014 if (!seed->Rotate(-fSectors->GetAlpha()))
1022 //_____________________________________________________________________________
1023 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1024 Double_t x2,Double_t y2,
1025 Double_t x3,Double_t y3) const
1027 //-----------------------------------------------------------------
1028 // Initial approximation of the track curvature
1029 //-----------------------------------------------------------------
1030 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1031 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1032 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1033 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1034 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1036 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1037 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1038 return -xr*yr/sqrt(xr*xr+yr*yr);
1043 //_____________________________________________________________________________
1044 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1045 Double_t x2,Double_t y2,
1046 Double_t x3,Double_t y3) const
1048 //-----------------------------------------------------------------
1049 // Initial approximation of the track curvature
1050 //-----------------------------------------------------------------
1056 Double_t det = x3*y2-x2*y3;
1057 if (TMath::Abs(det)<1e-10){
1061 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1062 Double_t x0 = x3*0.5-y3*u;
1063 Double_t y0 = y3*0.5+x3*u;
1064 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1070 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1071 Double_t x2,Double_t y2,
1072 Double_t x3,Double_t y3) const
1074 //-----------------------------------------------------------------
1075 // Initial approximation of the track curvature
1076 //-----------------------------------------------------------------
1082 Double_t det = x3*y2-x2*y3;
1083 if (TMath::Abs(det)<1e-10) {
1087 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1088 Double_t x0 = x3*0.5-y3*u;
1089 Double_t y0 = y3*0.5+x3*u;
1090 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1099 //_____________________________________________________________________________
1100 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1101 Double_t x2,Double_t y2,
1102 Double_t x3,Double_t y3) const
1104 //-----------------------------------------------------------------
1105 // Initial approximation of the track curvature times center of curvature
1106 //-----------------------------------------------------------------
1107 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1108 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1109 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1110 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1111 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1113 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1115 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1118 //_____________________________________________________________________________
1119 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1120 Double_t x2,Double_t y2,
1121 Double_t z1,Double_t z2) const
1123 //-----------------------------------------------------------------
1124 // Initial approximation of the tangent of the track dip angle
1125 //-----------------------------------------------------------------
1126 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1130 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1131 Double_t x2,Double_t y2,
1132 Double_t z1,Double_t z2, Double_t c) const
1134 //-----------------------------------------------------------------
1135 // Initial approximation of the tangent of the track dip angle
1136 //-----------------------------------------------------------------
1140 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1142 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1143 if (TMath::Abs(d*c*0.5)>1) return 0;
1144 // Double_t angle2 = TMath::ASin(d*c*0.5);
1145 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1146 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1148 angle2 = (z1-z2)*c/(angle2*2.);
1152 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1153 {//-----------------------------------------------------------------
1154 // This function find proloncation of a track to a reference plane x=x2.
1155 //-----------------------------------------------------------------
1159 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1163 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1164 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1168 Double_t dy = dx*(c1+c2)/(r1+r2);
1171 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1173 if (TMath::Abs(delta)>0.01){
1174 dz = x[3]*TMath::ASin(delta)/x[4];
1176 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1179 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1187 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1192 return LoadClusters();
1196 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1199 // load clusters to the memory
1200 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1201 Int_t lower = arr->LowerBound();
1202 Int_t entries = arr->GetEntriesFast();
1204 for (Int_t i=lower; i<entries; i++) {
1205 clrow = (AliTPCClustersRow*) arr->At(i);
1206 if(!clrow) continue;
1207 if(!clrow->GetArray()) continue;
1211 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1213 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1214 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1217 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1218 AliTPCtrackerRow * tpcrow=0;
1221 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1225 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1226 left = (sec-fkNIS*2)/fkNOS;
1229 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1230 for (Int_t j=0;j<tpcrow->GetN1();++j)
1231 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1234 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1235 for (Int_t j=0;j<tpcrow->GetN2();++j)
1236 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1238 clrow->GetArray()->Clear("C");
1247 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1250 // load clusters to the memory from one
1253 AliTPCclusterMI *clust=0;
1254 Int_t count[72][96] = { {0} , {0} };
1256 // loop over clusters
1257 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1258 clust = (AliTPCclusterMI*)arr->At(icl);
1259 if(!clust) continue;
1260 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1262 // transform clusters
1265 // count clusters per pad row
1266 count[clust->GetDetector()][clust->GetRow()]++;
1269 // insert clusters to sectors
1270 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1271 clust = (AliTPCclusterMI*)arr->At(icl);
1272 if(!clust) continue;
1274 Int_t sec = clust->GetDetector();
1275 Int_t row = clust->GetRow();
1277 // filter overlapping pad rows needed by HLT
1278 if(sec<fkNIS*2) { //IROCs
1279 if(row == 30) continue;
1282 if(row == 27 || row == 76) continue;
1287 // left = sec/fkNIS;
1288 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1291 // left = (sec-fkNIS*2)/fkNOS;
1292 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1296 // Load functions must be called behind LoadCluster(TClonesArray*)
1298 //LoadOuterSectors();
1299 //LoadInnerSectors();
1305 Int_t AliTPCtracker::LoadClusters()
1308 // load clusters to the memory
1309 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1311 // TTree * tree = fClustersArray.GetTree();
1312 AliInfo("LoadClusters()\n");
1314 TTree * tree = fInput;
1315 TBranch * br = tree->GetBranch("Segment");
1316 br->SetAddress(&clrow);
1318 // Conversion of pad, row coordinates in local tracking coords.
1319 // Could be skipped here; is already done in clusterfinder
1321 Int_t j=Int_t(tree->GetEntries());
1322 for (Int_t i=0; i<j; i++) {
1326 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1327 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1328 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1331 AliTPCtrackerRow * tpcrow=0;
1334 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1338 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1339 left = (sec-fkNIS*2)/fkNOS;
1342 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1343 for (Int_t k=0;k<tpcrow->GetN1();++k)
1344 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1347 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1348 for (Int_t k=0;k<tpcrow->GetN2();++k)
1349 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1356 if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1361 void AliTPCtracker::UnloadClusters()
1364 // unload clusters from the memory
1366 Int_t nrows = fOuterSec->GetNRows();
1367 for (Int_t sec = 0;sec<fkNOS;sec++)
1368 for (Int_t row = 0;row<nrows;row++){
1369 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1371 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1372 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1374 tpcrow->ResetClusters();
1377 nrows = fInnerSec->GetNRows();
1378 for (Int_t sec = 0;sec<fkNIS;sec++)
1379 for (Int_t row = 0;row<nrows;row++){
1380 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1382 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1383 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1385 tpcrow->ResetClusters();
1391 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1393 // Filling cluster to the array - For visualization purposes
1396 nrows = fOuterSec->GetNRows();
1397 for (Int_t sec = 0;sec<fkNOS;sec++)
1398 for (Int_t row = 0;row<nrows;row++){
1399 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1400 if (!tpcrow) continue;
1401 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1402 array->AddLast((TObject*)((*tpcrow)[icl]));
1405 nrows = fInnerSec->GetNRows();
1406 for (Int_t sec = 0;sec<fkNIS;sec++)
1407 for (Int_t row = 0;row<nrows;row++){
1408 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1409 if (!tpcrow) continue;
1410 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1411 array->AddLast((TObject*)(*tpcrow)[icl]);
1417 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1421 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1422 AliTPCTransform *transform = calibDB->GetTransform() ;
1424 AliFatal("Tranformations not in calibDB");
1427 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1428 Double_t x[3]={cluster->GetRow(),cluster->GetPad(),cluster->GetTimeBin()};
1429 Int_t i[1]={cluster->GetDetector()};
1430 transform->Transform(x,i,0,1);
1431 // if (cluster->GetDetector()%36>17){
1436 // in debug mode check the transformation
1438 if (AliTPCReconstructor::StreamLevel()>2) {
1440 cluster->GetGlobalXYZ(gx);
1441 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1442 TTreeSRedirector &cstream = *fDebugStreamer;
1443 cstream<<"Transform"<<
1454 cluster->SetX(x[0]);
1455 cluster->SetY(x[1]);
1456 cluster->SetZ(x[2]);
1461 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1462 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1463 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1465 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1466 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1467 if (mat) mat->LocalToMaster(pos,posC);
1469 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1471 cluster->SetX(posC[0]);
1472 cluster->SetY(posC[1]);
1473 cluster->SetZ(posC[2]);
1477 void AliTPCtracker::ApplyTailCancellation(){
1479 // Correct the cluster charge for the ion tail effect
1480 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1484 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1485 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1486 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1487 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1488 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1489 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1491 // find the number of clusters for the whole TPC (nclALL)
1493 for (Int_t isector=0; isector<36; isector++){
1494 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1495 nclALL += sector.GetNClInSector(0);
1496 nclALL += sector.GetNClInSector(1);
1499 // start looping over all clusters
1500 for (Int_t iside=0; iside<2; iside++){ // loop over sides
1503 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
1504 // cache experimantal tuning factor for the different chamber type
1505 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
1506 std::cout << " ampfactor = " << ampfactor << std::endl;
1508 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
1511 // Cache time response functions and their positons to COG of the cluster
1512 TGraphErrors ** graphRes = new TGraphErrors *[20];
1513 Float_t * indexAmpGraphs = new Float_t[20];
1514 for (Int_t icache=0; icache<20; icache++)
1516 graphRes[icache] = NULL;
1517 indexAmpGraphs[icache] = 0;
1519 ///////////////////////////// --> position fo sie loop
1520 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
1525 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
1526 Int_t nrows = sector.GetNRows(); // number of rows
1527 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
1529 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1531 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1532 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1533 if (iside>0) ncl=tpcrow.GetN2();
1535 // Order clusters in time for the proper correction of ion tail
1536 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
1537 Float_t qMaxArray[ncl];
1538 Int_t sortedClusterIndex[ncl];
1539 Float_t sortedClusterTimeBin[ncl];
1540 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
1541 for (Int_t i=0;i<ncl;i++)
1545 sortedClusterIndex[i]=i;
1546 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1548 rowClusterArray->AddAt(rowcl,i);
1550 rowClusterArray->RemoveAt(i);
1552 // Fill the timebin info to the array in order to sort wrt tb
1554 sortedClusterTimeBin[i]=0.0;
1556 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
1560 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
1562 // Main cluster correction loops over clusters
1563 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
1565 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
1569 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
1571 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
1573 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
1574 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
1575 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
1577 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
1579 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
1580 Double_t ionTailMax=0.;
1581 Double_t ionTailTotal=0.;
1582 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
1583 ionTailMax=TMath::Abs(ionTailMax);
1584 ionTailTotal=TMath::Abs(ionTailTotal);
1585 qTotArray[icl0]+=ionTailTotal;
1586 qMaxArray[icl0]+=ionTailMax;
1588 // Dump some info for debugging while clusters are being corrected
1589 if (AliTPCReconstructor::StreamLevel()==1) {
1590 TTreeSRedirector &cstream = *fDebugStreamer;
1591 if (gRandom->Rndm() > 0.999){
1592 cstream<<"IonTail"<<
1593 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
1594 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
1595 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
1596 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
1599 }// dump the results to the debug streamer if in debug mode
1601 }//end of second loop over clusters
1603 // Set corrected values of the corrected cluster
1604 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
1605 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
1607 // Dump some info for debugging after clusters are corrected
1608 if (AliTPCReconstructor::StreamLevel()==1) {
1609 TTreeSRedirector &cstream = *fDebugStreamer;
1610 if (gRandom->Rndm() > 0.999){
1611 cstream<<"IonTailCorrected"<<
1612 "cl0.=" << cl0 << // cluster 0 with huge Qmax
1613 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
1614 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
1615 "nclALL=" << nclALL <<
1616 "nclSector=" << nclSector <<
1618 "nclPad=" << nclPad <<
1624 }// dump the results to the debug streamer if in debug mode
1626 }//end of first loop over cluster
1627 delete rowClusterArray;
1628 }//end of loop over rows
1629 for (int i=0; i<20; i++) delete graphRes[i];
1631 delete [] indexAmpGraphs;
1633 }//end of loop over sectors
1634 }//end of loop over IROC/OROC
1635 }// end of side loop
1637 //_____________________________________________________________________________
1638 void AliTPCtracker::GetTailValue(const Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
1641 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
1644 const Double_t kMinPRF = 0.5; // minimal PRF width
1645 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
1646 ionTailMax = 0.; // correction value to be added to Qmax of cl0
1648 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
1649 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
1650 Int_t sectorPad = cl1->GetDetector(); // sector number
1651 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
1652 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
1653 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
1654 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
1655 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
1656 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
1659 Double_t sumAmp1=0.;
1660 for (Int_t idelta =-2; idelta<=2;idelta++){
1661 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
1664 Double_t sumAmp0=0.;
1665 for (Int_t idelta =-2; idelta<=2;idelta++){
1666 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
1669 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
1670 Int_t padScan=2; // +-2 pad-timebin window will be scanned
1671 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
1674 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
1675 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
1676 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
1678 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
1680 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
1681 for (Int_t j=0;j<20;j++) {
1682 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
1684 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
1688 if (!graphRes[ampIndex]) continue;
1689 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
1690 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
1692 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
1695 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
1697 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
1698 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
1699 Float_t qMaxPad0 = amp0*qTot0;
1701 // Add 5 timebin range contribution around the max peak (-+2 tb window)
1702 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
1704 if (itb<0) continue;
1705 if (itb>=graphRes[ampIndex]->GetN()) continue;
1707 // calculate contribution to qTot
1708 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
1709 if (ipad1!=padcl0) {
1710 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
1712 ionTailTotal += tailCorr; // for center pad
1714 // calculate contribution to qMax
1715 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
1717 } // end of tb correction loop which is applied over 5 tb range
1719 } // end of cl0 loop
1720 } // end of cl1 loop
1724 //_____________________________________________________________________________
1725 Int_t AliTPCtracker::LoadOuterSectors() {
1726 //-----------------------------------------------------------------
1727 // This function fills outer TPC sectors with clusters.
1728 //-----------------------------------------------------------------
1729 Int_t nrows = fOuterSec->GetNRows();
1731 for (Int_t sec = 0;sec<fkNOS;sec++)
1732 for (Int_t row = 0;row<nrows;row++){
1733 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1734 Int_t sec2 = sec+2*fkNIS;
1736 Int_t ncl = tpcrow->GetN1();
1738 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1739 index=(((sec2<<8)+row)<<16)+ncl;
1740 tpcrow->InsertCluster(c,index);
1743 ncl = tpcrow->GetN2();
1745 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1746 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1747 tpcrow->InsertCluster(c,index);
1750 // write indexes for fast acces
1752 for (Int_t i=0;i<510;i++)
1753 tpcrow->SetFastCluster(i,-1);
1754 for (Int_t i=0;i<tpcrow->GetN();i++){
1755 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1756 tpcrow->SetFastCluster(zi,i); // write index
1759 for (Int_t i=0;i<510;i++){
1760 if (tpcrow->GetFastCluster(i)<0)
1761 tpcrow->SetFastCluster(i,last);
1763 last = tpcrow->GetFastCluster(i);
1772 //_____________________________________________________________________________
1773 Int_t AliTPCtracker::LoadInnerSectors() {
1774 //-----------------------------------------------------------------
1775 // This function fills inner TPC sectors with clusters.
1776 //-----------------------------------------------------------------
1777 Int_t nrows = fInnerSec->GetNRows();
1779 for (Int_t sec = 0;sec<fkNIS;sec++)
1780 for (Int_t row = 0;row<nrows;row++){
1781 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1784 Int_t ncl = tpcrow->GetN1();
1786 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1787 index=(((sec<<8)+row)<<16)+ncl;
1788 tpcrow->InsertCluster(c,index);
1791 ncl = tpcrow->GetN2();
1793 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1794 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1795 tpcrow->InsertCluster(c,index);
1798 // write indexes for fast acces
1800 for (Int_t i=0;i<510;i++)
1801 tpcrow->SetFastCluster(i,-1);
1802 for (Int_t i=0;i<tpcrow->GetN();i++){
1803 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1804 tpcrow->SetFastCluster(zi,i); // write index
1807 for (Int_t i=0;i<510;i++){
1808 if (tpcrow->GetFastCluster(i)<0)
1809 tpcrow->SetFastCluster(i,last);
1811 last = tpcrow->GetFastCluster(i);
1823 //_________________________________________________________________________
1824 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
1825 //--------------------------------------------------------------------
1826 // Return pointer to a given cluster
1827 //--------------------------------------------------------------------
1828 if (index<0) return 0; // no cluster
1829 Int_t sec=(index&0xff000000)>>24;
1830 Int_t row=(index&0x00ff0000)>>16;
1831 Int_t ncl=(index&0x00007fff)>>00;
1833 const AliTPCtrackerRow * tpcrow=0;
1834 TClonesArray * clrow =0;
1836 if (sec<0 || sec>=fkNIS*4) {
1837 AliWarning(Form("Wrong sector %d",sec));
1842 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
1843 if (tracksec.GetNRows()<=row) return 0;
1844 tpcrow = &(tracksec[row]);
1845 if (tpcrow==0) return 0;
1848 if (tpcrow->GetN1()<=ncl) return 0;
1849 clrow = tpcrow->GetClusters1();
1852 if (tpcrow->GetN2()<=ncl) return 0;
1853 clrow = tpcrow->GetClusters2();
1857 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
1858 if (tracksec.GetNRows()<=row) return 0;
1859 tpcrow = &(tracksec[row]);
1860 if (tpcrow==0) return 0;
1862 if (sec-2*fkNIS<fkNOS) {
1863 if (tpcrow->GetN1()<=ncl) return 0;
1864 clrow = tpcrow->GetClusters1();
1867 if (tpcrow->GetN2()<=ncl) return 0;
1868 clrow = tpcrow->GetClusters2();
1872 return (AliTPCclusterMI*)clrow->At(ncl);
1878 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
1879 //-----------------------------------------------------------------
1880 // This function tries to find a track prolongation to next pad row
1881 //-----------------------------------------------------------------
1883 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
1886 AliTPCclusterMI *cl=0;
1887 Int_t tpcindex= t.GetClusterIndex2(nr);
1889 // update current shape info every 5 pad-row
1890 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1894 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
1896 if (tpcindex==-1) return 0; //track in dead zone
1897 if (tpcindex >= 0){ //
1898 cl = t.GetClusterPointer(nr);
1899 //if (cl==0) cl = GetClusterMI(tpcindex);
1900 if (!cl) cl = GetClusterMI(tpcindex);
1901 t.SetCurrentClusterIndex1(tpcindex);
1904 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
1905 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1907 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1908 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1910 if (TMath::Abs(angle-t.GetAlpha())>0.001){
1911 Double_t rotation = angle-t.GetAlpha();
1912 t.SetRelativeSector(relativesector);
1913 if (!t.Rotate(rotation)) {
1914 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1918 if (!t.PropagateTo(x)) {
1919 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1923 t.SetCurrentCluster(cl);
1925 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1926 if ((tpcindex&0x8000)==0) accept =0;
1928 //if founded cluster is acceptible
1929 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
1930 t.SetErrorY2(t.GetErrorY2()+0.03);
1931 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1932 t.SetErrorY2(t.GetErrorY2()*3);
1933 t.SetErrorZ2(t.GetErrorZ2()*3);
1935 t.SetNFoundable(t.GetNFoundable()+1);
1936 UpdateTrack(&t,accept);
1939 else { // Remove old cluster from track
1940 t.SetClusterIndex(nr, -3);
1941 t.SetClusterPointer(nr, 0);
1945 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
1946 if (fIteration>1 && IsFindable(t)){
1947 // not look for new cluster during refitting
1948 t.SetNFoundable(t.GetNFoundable()+1);
1953 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1954 if (!t.PropagateTo(x)) {
1955 if (fIteration==0) t.SetRemoval(10);
1958 Double_t y = t.GetY();
1959 if (TMath::Abs(y)>ymax){
1961 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1962 if (!t.Rotate(fSectors->GetAlpha()))
1964 } else if (y <-ymax) {
1965 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1966 if (!t.Rotate(-fSectors->GetAlpha()))
1969 if (!t.PropagateTo(x)) {
1970 if (fIteration==0) t.SetRemoval(10);
1976 Double_t z=t.GetZ();
1979 if (!IsActive(t.GetRelativeSector(),nr)) {
1981 t.SetClusterIndex2(nr,-1);
1984 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1985 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
1986 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
1988 if (!isActive || !isActive2) return 0;
1990 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
1991 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
1993 Double_t roadz = 1.;
1995 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1997 t.SetClusterIndex2(nr,-1);
2003 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2004 t.SetNFoundable(t.GetNFoundable()+1);
2010 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2011 cl = krow.FindNearest2(y,z,roady,roadz,index);
2012 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2015 t.SetCurrentCluster(cl);
2017 if (fIteration==2&&cl->IsUsed(10)) return 0;
2018 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2019 if (fIteration==2&&cl->IsUsed(11)) {
2020 t.SetErrorY2(t.GetErrorY2()+0.03);
2021 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2022 t.SetErrorY2(t.GetErrorY2()*3);
2023 t.SetErrorZ2(t.GetErrorZ2()*3);
2026 if (t.fCurrentCluster->IsUsed(10)){
2031 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2037 if (accept<3) UpdateTrack(&t,accept);
2040 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2048 //_________________________________________________________________________
2049 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2051 // Get track space point by index
2052 // return false in case the cluster doesn't exist
2053 AliTPCclusterMI *cl = GetClusterMI(index);
2054 if (!cl) return kFALSE;
2055 Int_t sector = (index&0xff000000)>>24;
2056 // Int_t row = (index&0x00ff0000)>>16;
2058 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2059 xyz[0] = cl->GetX();
2060 xyz[1] = cl->GetY();
2061 xyz[2] = cl->GetZ();
2063 fkParam->AdjustCosSin(sector,cos,sin);
2064 Float_t x = cos*xyz[0]-sin*xyz[1];
2065 Float_t y = cos*xyz[1]+sin*xyz[0];
2067 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2068 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2069 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2070 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2071 cov[0] = sin*sin*sigmaY2;
2072 cov[1] = -sin*cos*sigmaY2;
2074 cov[3] = cos*cos*sigmaY2;
2077 p.SetXYZ(x,y,xyz[2],cov);
2078 AliGeomManager::ELayerID iLayer;
2080 if (sector < fkParam->GetNInnerSector()) {
2081 iLayer = AliGeomManager::kTPC1;
2085 iLayer = AliGeomManager::kTPC2;
2086 idet = sector - fkParam->GetNInnerSector();
2088 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2089 p.SetVolumeID(volid);
2095 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2096 //-----------------------------------------------------------------
2097 // This function tries to find a track prolongation to next pad row
2098 //-----------------------------------------------------------------
2099 t.SetCurrentCluster(0);
2100 t.SetCurrentClusterIndex1(-3);
2102 Double_t xt=t.GetX();
2103 Int_t row = GetRowNumber(xt)-1;
2104 Double_t ymax= GetMaxY(nr);
2106 if (row < nr) return 1; // don't prolongate if not information until now -
2107 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2109 // return 0; // not prolongate strongly inclined tracks
2111 // if (TMath::Abs(t.GetSnp())>0.95) {
2113 // return 0; // not prolongate strongly inclined tracks
2114 // }// patch 28 fev 06
2116 Double_t x= GetXrow(nr);
2118 //t.PropagateTo(x+0.02);
2119 //t.PropagateTo(x+0.01);
2120 if (!t.PropagateTo(x)){
2127 if (TMath::Abs(y)>ymax){
2129 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2130 if (!t.Rotate(fSectors->GetAlpha()))
2132 } else if (y <-ymax) {
2133 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2134 if (!t.Rotate(-fSectors->GetAlpha()))
2137 // if (!t.PropagateTo(x)){
2144 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2146 if (!IsActive(t.GetRelativeSector(),nr)) {
2148 t.SetClusterIndex2(nr,-1);
2151 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2153 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2155 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2157 t.SetClusterIndex2(nr,-1);
2163 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2164 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2170 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2171 // t.fCurrentSigmaY = GetSigmaY(&t);
2172 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2176 AliTPCclusterMI *cl=0;
2179 Double_t roady = 1.;
2180 Double_t roadz = 1.;
2184 index = t.GetClusterIndex2(nr);
2185 if ( (index >= 0) && (index&0x8000)==0){
2186 cl = t.GetClusterPointer(nr);
2187 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2188 t.SetCurrentClusterIndex1(index);
2190 t.SetCurrentCluster(cl);
2196 // if (index<0) return 0;
2197 UInt_t uindex = TMath::Abs(index);
2200 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2201 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2204 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2205 t.SetCurrentCluster(cl);
2211 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2212 //-----------------------------------------------------------------
2213 // This function tries to find a track prolongation to next pad row
2214 //-----------------------------------------------------------------
2216 //update error according neighborhoud
2218 if (t.GetCurrentCluster()) {
2220 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2222 if (t.GetCurrentCluster()->IsUsed(10)){
2227 t.SetNShared(t.GetNShared()+1);
2228 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2233 if (fIteration>0) accept = 0;
2234 if (accept<3) UpdateTrack(&t,accept);
2238 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2239 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2241 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2249 //_____________________________________________________________________________
2250 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2251 //-----------------------------------------------------------------
2252 // This function tries to find a track prolongation.
2253 //-----------------------------------------------------------------
2254 Double_t xt=t.GetX();
2256 Double_t alpha=t.GetAlpha();
2257 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2258 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2260 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2262 Int_t first = GetRowNumber(xt);
2267 for (Int_t nr= first; nr>=rf; nr-=step) {
2269 if (t.GetKinkIndexes()[0]>0){
2270 for (Int_t i=0;i<3;i++){
2271 Int_t index = t.GetKinkIndexes()[i];
2272 if (index==0) break;
2273 if (index<0) continue;
2275 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2277 printf("PROBLEM\n");
2280 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2282 AliExternalTrackParam paramd(t);
2283 kink->SetDaughter(paramd);
2284 kink->SetStatus(2,5);
2291 if (nr==80) t.UpdateReference();
2292 if (nr<fInnerSec->GetNRows())
2293 fSectors = fInnerSec;
2295 fSectors = fOuterSec;
2296 if (FollowToNext(t,nr)==0)
2309 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2310 //-----------------------------------------------------------------
2311 // This function tries to find a track prolongation.
2312 //-----------------------------------------------------------------
2314 Double_t xt=t.GetX();
2315 Double_t alpha=t.GetAlpha();
2316 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2317 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2318 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2320 Int_t first = t.GetFirstPoint();
2321 Int_t ri = GetRowNumber(xt);
2325 if (first<ri) first = ri;
2327 if (first<0) first=0;
2328 for (Int_t nr=first; nr<=rf; nr++) {
2329 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2330 if (t.GetKinkIndexes()[0]<0){
2331 for (Int_t i=0;i<3;i++){
2332 Int_t index = t.GetKinkIndexes()[i];
2333 if (index==0) break;
2334 if (index>0) continue;
2335 index = TMath::Abs(index);
2336 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2338 printf("PROBLEM\n");
2341 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2343 AliExternalTrackParam paramm(t);
2344 kink->SetMother(paramm);
2345 kink->SetStatus(2,1);
2352 if (nr<fInnerSec->GetNRows())
2353 fSectors = fInnerSec;
2355 fSectors = fOuterSec;
2366 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2368 // overlapping factor
2374 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2377 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2379 Float_t distance = TMath::Sqrt(dz2+dy2);
2380 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2383 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2384 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2389 if (firstpoint>lastpoint) {
2390 firstpoint =lastpoint;
2395 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2396 if (s1->GetClusterIndex2(i)>0) sum1++;
2397 if (s2->GetClusterIndex2(i)>0) sum2++;
2398 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2402 if (sum<5) return 0;
2404 Float_t summin = TMath::Min(sum1+1,sum2+1);
2405 Float_t ratio = (sum+1)/Float_t(summin);
2409 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2413 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2414 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2415 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2416 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2421 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2422 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2423 Int_t firstpoint = 0;
2424 Int_t lastpoint = 160;
2426 // if (firstpoint>=lastpoint-5) return;;
2428 for (Int_t i=firstpoint;i<lastpoint;i++){
2429 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2430 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2434 if (sumshared>cutN0){
2437 for (Int_t i=firstpoint;i<lastpoint;i++){
2438 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2439 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2440 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2441 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2442 if (s1->IsActive()&&s2->IsActive()){
2443 p1->SetShared(kTRUE);
2444 p2->SetShared(kTRUE);
2450 if (sumshared>cutN0){
2451 for (Int_t i=0;i<4;i++){
2452 if (s1->GetOverlapLabel(3*i)==0){
2453 s1->SetOverlapLabel(3*i, s2->GetLabel());
2454 s1->SetOverlapLabel(3*i+1,sumshared);
2455 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2459 for (Int_t i=0;i<4;i++){
2460 if (s2->GetOverlapLabel(3*i)==0){
2461 s2->SetOverlapLabel(3*i, s1->GetLabel());
2462 s2->SetOverlapLabel(3*i+1,sumshared);
2463 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2470 void AliTPCtracker::SignShared(TObjArray * arr)
2473 //sort trackss according sectors
2475 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2476 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2478 //if (pt) RotateToLocal(pt);
2482 arr->Sort(); // sorting according relative sectors
2483 arr->Expand(arr->GetEntries());
2486 Int_t nseed=arr->GetEntriesFast();
2487 for (Int_t i=0; i<nseed; i++) {
2488 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2490 for (Int_t j=0;j<12;j++){
2491 pt->SetOverlapLabel(j,0);
2494 for (Int_t i=0; i<nseed; i++) {
2495 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2497 if (pt->GetRemoval()>10) continue;
2498 for (Int_t j=i+1; j<nseed; j++){
2499 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2500 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2502 if (pt2->GetRemoval()<=10) {
2503 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2511 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
2514 //sort tracks in array according mode criteria
2515 Int_t nseed = arr->GetEntriesFast();
2516 for (Int_t i=0; i<nseed; i++) {
2517 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2528 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
2531 // Loop over all tracks and remove overlaped tracks (with lower quality)
2533 // 1. Unsign clusters
2534 // 2. Sort tracks according quality
2535 // Quality is defined by the number of cluster between first and last points
2537 // 3. Loop over tracks - decreasing quality order
2538 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
2539 // b.) remove - If the minimal number of clusters less than minimal and not ITS
2540 // c.) if track accepted - sign clusters
2542 //Called in - AliTPCtracker::Clusters2Tracks()
2543 // - AliTPCtracker::PropagateBack()
2544 // - AliTPCtracker::RefitInward()
2547 // factor1 - factor for constrained
2548 // factor2 - for non constrained tracks
2549 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
2553 Int_t nseed = arr->GetEntriesFast();
2554 Float_t * quality = new Float_t[nseed];
2555 Int_t * indexes = new Int_t[nseed];
2559 for (Int_t i=0; i<nseed; i++) {
2560 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2565 pt->UpdatePoints(); //select first last max dens points
2566 Float_t * points = pt->GetPoints();
2567 if (points[3]<0.8) quality[i] =-1;
2568 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2569 //prefer high momenta tracks if overlaps
2570 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
2572 TMath::Sort(nseed,quality,indexes);
2575 for (Int_t itrack=0; itrack<nseed; itrack++) {
2576 Int_t trackindex = indexes[itrack];
2577 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
2580 if (quality[trackindex]<0){
2581 MarkSeedFree( arr->RemoveAt(trackindex) );
2586 Int_t first = Int_t(pt->GetPoints()[0]);
2587 Int_t last = Int_t(pt->GetPoints()[2]);
2588 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2590 Int_t found,foundable,shared;
2591 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
2592 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2593 Bool_t itsgold =kFALSE;
2596 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2600 if (Float_t(shared+1)/Float_t(found+1)>factor){
2601 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2602 if( AliTPCReconstructor::StreamLevel()>3){
2603 TTreeSRedirector &cstream = *fDebugStreamer;
2604 cstream<<"RemoveUsed"<<
2605 "iter="<<fIteration<<
2609 MarkSeedFree( arr->RemoveAt(trackindex) );
2612 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
2613 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2614 if( AliTPCReconstructor::StreamLevel()>3){
2615 TTreeSRedirector &cstream = *fDebugStreamer;
2616 cstream<<"RemoveShort"<<
2617 "iter="<<fIteration<<
2621 MarkSeedFree( arr->RemoveAt(trackindex) );
2627 //if (sharedfactor>0.4) continue;
2628 if (pt->GetKinkIndexes()[0]>0) continue;
2629 //Remove tracks with undefined properties - seems
2630 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
2632 for (Int_t i=first; i<last; i++) {
2633 Int_t index=pt->GetClusterIndex2(i);
2634 // if (index<0 || index&0x8000 ) continue;
2635 if (index<0 || index&0x8000 ) continue;
2636 AliTPCclusterMI *c= pt->GetClusterPointer(i);
2643 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2649 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
2652 // Dump clusters after reco
2653 // signed and unsigned cluster can be visualized
2654 // 1. Unsign all cluster
2655 // 2. Sign all used clusters
2658 Int_t nseed = trackArray->GetEntries();
2659 for (Int_t i=0; i<nseed; i++){
2660 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
2664 Bool_t isKink=pt->GetKinkIndex(0)!=0;
2665 for (Int_t j=0; j<160; ++j) {
2666 Int_t index=pt->GetClusterIndex2(j);
2667 if (index<0) continue;
2668 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2670 if (isKink) c->Use(100); // kink
2671 c->Use(10); // by default usage 10
2676 for (Int_t sec=0;sec<fkNIS;sec++){
2677 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2678 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2679 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
2680 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2681 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2682 (*fDebugStreamer)<<"clDump"<<
2690 cla = fInnerSec[sec][row].GetClusters2();
2691 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
2692 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2693 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2694 (*fDebugStreamer)<<"clDump"<<
2705 for (Int_t sec=0;sec<fkNOS;sec++){
2706 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2707 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2708 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
2710 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2711 cl->GetGlobalXYZ(gx);
2712 (*fDebugStreamer)<<"clDump"<<
2720 cla = fOuterSec[sec][row].GetClusters2();
2721 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
2723 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2724 cl->GetGlobalXYZ(gx);
2725 (*fDebugStreamer)<<"clDump"<<
2737 void AliTPCtracker::UnsignClusters()
2740 // loop over all clusters and unsign them
2743 for (Int_t sec=0;sec<fkNIS;sec++){
2744 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2745 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2746 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2747 // if (cl[icl].IsUsed(10))
2748 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2749 cla = fInnerSec[sec][row].GetClusters2();
2750 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2751 //if (cl[icl].IsUsed(10))
2752 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2756 for (Int_t sec=0;sec<fkNOS;sec++){
2757 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2758 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2759 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2760 //if (cl[icl].IsUsed(10))
2761 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2762 cla = fOuterSec[sec][row].GetClusters2();
2763 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2764 //if (cl[icl].IsUsed(10))
2765 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2773 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
2776 //sign clusters to be "used"
2778 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2779 // loop over "primaries"
2793 Int_t nseed = arr->GetEntriesFast();
2794 for (Int_t i=0; i<nseed; i++) {
2795 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2799 if (!(pt->IsActive())) continue;
2800 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2801 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2803 sumdens2+= dens*dens;
2804 sumn += pt->GetNumberOfClusters();
2805 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2806 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2809 sumchi2 +=chi2*chi2;
2814 Float_t mdensity = 0.9;
2815 Float_t meann = 130;
2816 Float_t meanchi = 1;
2817 Float_t sdensity = 0.1;
2818 Float_t smeann = 10;
2819 Float_t smeanchi =0.4;
2823 mdensity = sumdens/sum;
2825 meanchi = sumchi/sum;
2827 sdensity = sumdens2/sum-mdensity*mdensity;
2829 sdensity = TMath::Sqrt(sdensity);
2833 smeann = sumn2/sum-meann*meann;
2835 smeann = TMath::Sqrt(smeann);
2839 smeanchi = sumchi2/sum - meanchi*meanchi;
2841 smeanchi = TMath::Sqrt(smeanchi);
2847 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
2849 for (Int_t i=0; i<nseed; i++) {
2850 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2854 if (pt->GetBSigned()) continue;
2855 if (pt->GetBConstrain()) continue;
2856 //if (!(pt->IsActive())) continue;
2858 Int_t found,foundable,shared;
2859 pt->GetClusterStatistic(0,160,found, foundable,shared);
2860 if (shared/float(found)>0.3) {
2861 if (shared/float(found)>0.9 ){
2862 //MarkSeedFree( arr->RemoveAt(i) );
2867 Bool_t isok =kFALSE;
2868 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2870 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2872 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2874 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2878 for (Int_t j=0; j<160; ++j) {
2879 Int_t index=pt->GetClusterIndex2(j);
2880 if (index<0) continue;
2881 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2883 //if (!(c->IsUsed(10))) c->Use();
2890 Double_t maxchi = meanchi+2.*smeanchi;
2892 for (Int_t i=0; i<nseed; i++) {
2893 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2897 //if (!(pt->IsActive())) continue;
2898 if (pt->GetBSigned()) continue;
2899 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
2900 if (chi>maxchi) continue;
2903 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2905 //sign only tracks with enoug big density at the beginning
2907 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
2910 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2911 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2913 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2914 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2917 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2918 //Int_t noc=pt->GetNumberOfClusters();
2919 pt->SetBSigned(kTRUE);
2920 for (Int_t j=0; j<160; ++j) {
2922 Int_t index=pt->GetClusterIndex2(j);
2923 if (index<0) continue;
2924 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2926 // if (!(c->IsUsed(10))) c->Use();
2931 // gLastCheck = nseed;
2940 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
2943 // back propagation of ESD tracks
2946 if (!event) return 0;
2947 const Int_t kMaxFriendTracks=2000;
2950 // extract correction object for multiplicity dependence of dEdx
2951 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
2953 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
2955 AliFatal("Tranformations not in RefitInward");
2958 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
2959 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
2960 Int_t nContribut = event->GetNumberOfTracks();
2961 TGraphErrors * graphMultDependenceDeDx = 0x0;
2962 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
2963 if (recoParam->GetUseTotCharge()) {
2964 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2966 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2972 //PrepareForProlongation(fSeeds,1);
2973 PropagateForward2(fSeeds);
2974 RemoveUsed2(fSeeds,0.4,0.4,20);
2976 TObjArray arraySeed(fSeeds->GetEntries());
2977 for (Int_t i=0;i<fSeeds->GetEntries();i++) {
2978 arraySeed.AddAt(fSeeds->At(i),i);
2980 SignShared(&arraySeed);
2981 // FindCurling(fSeeds, event,2); // find multi found tracks
2982 FindSplitted(fSeeds, event,2); // find multi found tracks
2983 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,2); // find multi found tracks
2986 Int_t nseed = fSeeds->GetEntriesFast();
2987 for (Int_t i=0;i<nseed;i++){
2988 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2989 if (!seed) continue;
2990 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
2991 AliESDtrack *esd=event->GetTrack(i);
2993 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
2994 AliExternalTrackParam paramIn;
2995 AliExternalTrackParam paramOut;
2996 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
2997 if (AliTPCReconstructor::StreamLevel()>2) {
2998 (*fDebugStreamer)<<"RecoverIn"<<
3002 "pout.="<<¶mOut<<
3007 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3008 seed->SetNumberOfClusters(ncl);
3012 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3013 seed->UpdatePoints();
3014 AddCovariance(seed);
3015 MakeESDBitmaps(seed, esd);
3016 seed->CookdEdx(0.02,0.6);
3017 CookLabel(seed,0.1); //For comparison only
3019 if (AliTPCReconstructor::StreamLevel()>1 && seed!=0) {
3020 TTreeSRedirector &cstream = *fDebugStreamer;
3027 if (seed->GetNumberOfClusters()>15){
3028 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3029 esd->SetTPCPoints(seed->GetPoints());
3030 esd->SetTPCPointsF(seed->GetNFoundable());
3031 Int_t ndedx = seed->GetNCDEDX(0);
3032 Float_t sdedx = seed->GetSDEDX(0);
3033 Float_t dedx = seed->GetdEdx();
3034 // apply mutliplicity dependent dEdx correction if available
3035 if (graphMultDependenceDeDx) {
3036 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3037 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3039 esd->SetTPCsignal(dedx, sdedx, ndedx);
3041 // fill new dEdx information
3043 Double32_t signal[4];
3044 Double32_t signalMax[4];
3048 for(Int_t iarr=0;iarr<3;iarr++) {
3049 signal[iarr] = seed->GetDEDXregion(iarr+1);
3050 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3051 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3052 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3054 signal[3] = seed->GetDEDXregion(4);
3055 signalMax[3] = seed->GetDEDXregion(8);
3058 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3059 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3060 infoTpcPid->SetTPCSignalsQmax(signalMax);
3061 esd->SetTPCdEdxInfo(infoTpcPid);
3063 // add seed to the esd track in Calib level
3065 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3066 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3067 // RS: this is the only place where the seed is created not in the pool,
3068 // since it should belong to ESDevent
3069 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3070 esd->AddCalibObject(seedCopy);
3075 //printf("problem\n");
3078 //FindKinks(fSeeds,event);
3079 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(2,fSeeds);
3080 Info("RefitInward","Number of refitted tracks %d",ntracks);
3082 AliCosmicTracker::FindCosmic(event, kTRUE);
3084 FillClusterOccupancyInfo();
3090 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3093 // back propagation of ESD tracks
3095 if (!event) return 0;
3100 PropagateBack(fSeeds);
3101 RemoveUsed2(fSeeds,0.4,0.4,20);
3102 //FindCurling(fSeeds, fEvent,1);
3103 FindSplitted(fSeeds, event,1); // find multi found tracks
3104 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3107 Int_t nseed = fSeeds->GetEntriesFast();
3109 for (Int_t i=0;i<nseed;i++){
3110 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3111 if (!seed) continue;
3112 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3113 seed->UpdatePoints();
3114 AddCovariance(seed);
3115 AliESDtrack *esd=event->GetTrack(i);
3116 if (!esd) continue; //never happen
3117 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3118 AliExternalTrackParam paramIn;
3119 AliExternalTrackParam paramOut;
3120 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3121 if (AliTPCReconstructor::StreamLevel()>2) {
3122 (*fDebugStreamer)<<"RecoverBack"<<
3126 "pout.="<<¶mOut<<
3131 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3132 seed->SetNumberOfClusters(ncl);
3135 seed->CookdEdx(0.02,0.6);
3136 CookLabel(seed,0.1); //For comparison only
3137 if (seed->GetNumberOfClusters()>15){
3138 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3139 esd->SetTPCPoints(seed->GetPoints());
3140 esd->SetTPCPointsF(seed->GetNFoundable());
3141 Int_t ndedx = seed->GetNCDEDX(0);
3142 Float_t sdedx = seed->GetSDEDX(0);
3143 Float_t dedx = seed->GetdEdx();
3144 esd->SetTPCsignal(dedx, sdedx, ndedx);
3146 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3147 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3148 if (AliTPCReconstructor::StreamLevel()>1 && esd) {
3149 (*fDebugStreamer)<<"Cback"<<
3152 "EventNrInFile="<<eventnumber<<
3157 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(1,fSeeds);
3158 //FindKinks(fSeeds,event);
3159 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3167 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3170 // Post process events
3172 if (!event) return 0;
3175 // Set TPC event status
3178 // event affected by HV dip
3180 if(IsTPCHVDipEvent(event)) {
3181 event->ResetDetectorStatus(AliDAQ::kTPC);
3184 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3190 void AliTPCtracker::DeleteSeeds()
3199 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3202 //read seeds from the event
3204 Int_t nentr=event->GetNumberOfTracks();
3206 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3211 fSeeds = new TObjArray(nentr);
3215 for (Int_t i=0; i<nentr; i++) {
3216 AliESDtrack *esd=event->GetTrack(i);
3217 ULong_t status=esd->GetStatus();
3218 if (!(status&AliESDtrack::kTPCin)) continue;
3219 AliTPCtrack t(*esd);
3220 t.SetNumberOfClusters(0);
3221 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3222 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3223 seed->SetPoolID(fLastSeedID);
3224 seed->SetUniqueID(esd->GetID());
3225 AddCovariance(seed); //add systematic ucertainty
3226 for (Int_t ikink=0;ikink<3;ikink++) {
3227 Int_t index = esd->GetKinkIndex(ikink);
3228 seed->GetKinkIndexes()[ikink] = index;
3229 if (index==0) continue;
3230 index = TMath::Abs(index);
3231 AliESDkink * kink = fEvent->GetKink(index-1);
3232 if (kink&&esd->GetKinkIndex(ikink)<0){
3233 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3234 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3236 if (kink&&esd->GetKinkIndex(ikink)>0){
3237 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3238 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3242 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3243 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3244 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3245 // fSeeds->AddAt(0,i);
3246 // MarkSeedFree( seed );
3252 // rotate to the local coordinate system
3254 fSectors=fInnerSec; fN=fkNIS;
3255 Double_t alpha=seed->GetAlpha();
3256 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3257 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3258 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3259 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3260 alpha-=seed->GetAlpha();
3261 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3262 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3263 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3264 AliWarning(Form("Rotating track over %f",alpha));
3265 if (!seed->Rotate(alpha)) {
3266 MarkSeedFree( seed );
3272 if (esd->GetKinkIndex(0)<=0){
3273 for (Int_t irow=0;irow<160;irow++){
3274 Int_t index = seed->GetClusterIndex2(irow);
3277 AliTPCclusterMI * cl = GetClusterMI(index);
3278 seed->SetClusterPointer(irow,cl);
3280 if ((index & 0x8000)==0){
3281 cl->Use(10); // accepted cluster
3283 cl->Use(6); // close cluster not accepted
3286 Info("ReadSeeds","Not found cluster");
3291 fSeeds->AddAt(seed,i);
3297 //_____________________________________________________________________________
3298 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3299 Float_t deltay, Int_t ddsec) {
3300 //-----------------------------------------------------------------
3301 // This function creates track seeds.
3302 // SEEDING WITH VERTEX CONSTRAIN
3303 //-----------------------------------------------------------------
3304 // cuts[0] - fP4 cut
3305 // cuts[1] - tan(phi) cut
3306 // cuts[2] - zvertex cut
3307 // cuts[3] - fP3 cut
3315 Double_t x[5], c[15];
3316 // Int_t di = i1-i2;
3318 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3319 seed->SetPoolID(fLastSeedID);
3320 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3321 Double_t cs=cos(alpha), sn=sin(alpha);
3323 // Double_t x1 =fOuterSec->GetX(i1);
3324 //Double_t xx2=fOuterSec->GetX(i2);
3326 Double_t x1 =GetXrow(i1);
3327 Double_t xx2=GetXrow(i2);
3329 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3331 Int_t imiddle = (i2+i1)/2; //middle pad row index
3332 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3333 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3337 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3338 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3339 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3342 // change cut on curvature if it can't reach this layer
3343 // maximal curvature set to reach it
3344 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3345 if (dvertexmax*0.5*cuts[0]>0.85){
3346 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3348 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3351 if (deltay>0) ddsec = 0;
3352 // loop over clusters
3353 for (Int_t is=0; is < kr1; is++) {
3355 if (kr1[is]->IsUsed(10)) continue;
3356 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3357 //if (TMath::Abs(y1)>ymax) continue;
3359 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3361 // find possible directions
3362 Float_t anglez = (z1-z3)/(x1-x3);
3363 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3366 //find rotation angles relative to line given by vertex and point 1
3367 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3368 Double_t dvertex = TMath::Sqrt(dvertex2);
3369 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3370 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3373 // loop over 2 sectors
3379 Double_t dddz1=0; // direction of delta inclination in z axis
3386 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3387 Int_t sec2 = sec + dsec;
3389 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3390 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3391 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3392 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3393 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3394 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3396 // rotation angles to p1-p3
3397 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3398 Double_t x2, y2, z2;
3400 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3403 Double_t dxx0 = (xx2-x3)*cs13r;
3404 Double_t dyy0 = (xx2-x3)*sn13r;
3405 for (Int_t js=index1; js < index2; js++) {
3406 const AliTPCclusterMI *kcl = kr2[js];
3407 if (kcl->IsUsed(10)) continue;
3409 //calcutate parameters
3411 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3413 if (TMath::Abs(yy0)<0.000001) continue;
3414 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3415 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3416 Double_t r02 = (0.25+y0*y0)*dvertex2;
3417 //curvature (radius) cut
3418 if (r02<r2min) continue;
3422 Double_t c0 = 1/TMath::Sqrt(r02);
3426 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3427 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3428 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3429 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3432 Double_t z0 = kcl->GetZ();
3433 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3434 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3437 Double_t dip = (z1-z0)*c0/dfi1;
3438 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3449 x2= xx2*cs-y2*sn*dsec;
3450 y2=+xx2*sn*dsec+y2*cs;
3460 // do we have cluster at the middle ?
3462 GetProlongation(x1,xm,x,ym,zm);
3464 AliTPCclusterMI * cm=0;
3465 if (TMath::Abs(ym)-ymaxm<0){
3466 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3467 if ((!cm) || (cm->IsUsed(10))) {
3472 // rotate y1 to system 0
3473 // get state vector in rotated system
3474 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3475 Double_t xr2 = x0*cs+yr1*sn*dsec;
3476 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3478 GetProlongation(xx2,xm,xr,ym,zm);
3479 if (TMath::Abs(ym)-ymaxm<0){
3480 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3481 if ((!cm) || (cm->IsUsed(10))) {
3488 // Double_t dym = 0;
3489 // Double_t dzm = 0;
3491 // dym = ym - cm->GetY();
3492 // dzm = zm - cm->GetZ();
3499 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3500 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
3501 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3502 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3503 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3505 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3506 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3507 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3508 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3509 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3510 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3512 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3513 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3514 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3515 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3519 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3520 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3521 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3522 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3523 c[13]=f30*sy1*f40+f32*sy2*f42;
3524 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3526 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3528 UInt_t index=kr1.GetIndex(is);
3529 if (seed) {MarkSeedFree(seed); seed = 0;}
3530 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3531 seed->SetPoolID(fLastSeedID);
3532 track->SetIsSeeding(kTRUE);
3533 track->SetSeed1(i1);
3534 track->SetSeed2(i2);
3535 track->SetSeedType(3);
3539 FollowProlongation(*track, (i1+i2)/2,1);
3540 Int_t foundable,found,shared;
3541 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3542 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3543 MarkSeedFree(seed); seed = 0;
3549 FollowProlongation(*track, i2,1);
3553 track->SetBConstrain(1);
3554 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
3555 track->SetLastPoint(i1); // first cluster in track position
3556 track->SetFirstPoint(track->GetLastPoint());
3558 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3559 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3560 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3561 MarkSeedFree(seed); seed = 0;
3565 // Z VERTEX CONDITION
3566 Double_t zv, bz=GetBz();
3567 if ( !track->GetZAt(0.,bz,zv) ) continue;
3568 if (TMath::Abs(zv-z3)>cuts[2]) {
3569 FollowProlongation(*track, TMath::Max(i2-20,0));
3570 if ( !track->GetZAt(0.,bz,zv) ) continue;
3571 if (TMath::Abs(zv-z3)>cuts[2]){
3572 FollowProlongation(*track, TMath::Max(i2-40,0));
3573 if ( !track->GetZAt(0.,bz,zv) ) continue;
3574 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3575 // make seed without constrain
3576 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3577 FollowProlongation(*track2, i2,1);
3578 track2->SetBConstrain(kFALSE);
3579 track2->SetSeedType(1);
3580 arr->AddLast(track2);
3581 MarkSeedFree( seed ); seed = 0;
3585 MarkSeedFree( seed ); seed = 0;
3592 track->SetSeedType(0);
3593 arr->AddLast(track); // note, track is seed, don't free the seed
3594 seed = new( NextFreeSeed() ) AliTPCseed;
3595 seed->SetPoolID(fLastSeedID);
3597 // don't consider other combinations
3598 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3604 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3606 if (seed) MarkSeedFree( seed );
3610 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3615 //-----------------------------------------------------------------
3616 // This function creates track seeds.
3617 //-----------------------------------------------------------------
3618 // cuts[0] - fP4 cut
3619 // cuts[1] - tan(phi) cut
3620 // cuts[2] - zvertex cut
3621 // cuts[3] - fP3 cut
3631 Double_t x[5], c[15];
3633 // make temporary seed
3634 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3635 seed->SetPoolID(fLastSeedID);
3636 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3637 // Double_t cs=cos(alpha), sn=sin(alpha);
3642 Double_t x1 = GetXrow(i1-1);
3643 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3644 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
3646 Double_t x1p = GetXrow(i1);
3647 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3649 Double_t x1m = GetXrow(i1-2);
3650 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3653 //last 3 padrow for seeding
3654 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
3655 Double_t x3 = GetXrow(i1-7);
3656 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
3658 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
3659 Double_t x3p = GetXrow(i1-6);
3661 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
3662 Double_t x3m = GetXrow(i1-8);
3667 Int_t im = i1-4; //middle pad row index
3668 Double_t xm = GetXrow(im); // radius of middle pad-row
3669 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
3670 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
3673 Double_t deltax = x1-x3;
3674 Double_t dymax = deltax*cuts[1];
3675 Double_t dzmax = deltax*cuts[3];
3677 // loop over clusters
3678 for (Int_t is=0; is < kr1; is++) {
3680 if (kr1[is]->IsUsed(10)) continue;
3681 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3683 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3685 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3686 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3692 for (Int_t js=index1; js < index2; js++) {
3693 const AliTPCclusterMI *kcl = kr3[js];
3694 if (kcl->IsUsed(10)) continue;
3696 // apply angular cuts
3697 if (TMath::Abs(y1-y3)>dymax) continue;
3700 if (TMath::Abs(z1-z3)>dzmax) continue;
3702 Double_t angley = (y1-y3)/(x1-x3);
3703 Double_t anglez = (z1-z3)/(x1-x3);
3705 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3706 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3708 Double_t yyym = angley*(xm-x1)+y1;
3709 Double_t zzzm = anglez*(xm-x1)+z1;
3711 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3713 if (kcm->IsUsed(10)) continue;
3715 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3716 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3723 // look around first
3724 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3730 if (kc1m->IsUsed(10)) used++;
3732 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3738 if (kc1p->IsUsed(10)) used++;
3740 if (used>1) continue;
3741 if (found<1) continue;
3745 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3751 if (kc3m->IsUsed(10)) used++;
3755 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3761 if (kc3p->IsUsed(10)) used++;
3765 if (used>1) continue;
3766 if (found<3) continue;
3776 x[4]=F1(x1,y1,x2,y2,x3,y3);
3777 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3780 x[2]=F2(x1,y1,x2,y2,x3,y3);
3783 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3784 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3788 Double_t sy1=0.1, sz1=0.1;
3789 Double_t sy2=0.1, sz2=0.1;
3790 Double_t sy3=0.1, sy=0.1, sz=0.1;
3792 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3793 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3794 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3795 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3796 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3797 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3799 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3800 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3801 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3802 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3806 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3807 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3808 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3809 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3810 c[13]=f30*sy1*f40+f32*sy2*f42;
3811 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3813 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3815 index=kr1.GetIndex(is);
3816 if (seed) {MarkSeedFree( seed ); seed = 0;}
3817 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3818 seed->SetPoolID(fLastSeedID);
3820 track->SetIsSeeding(kTRUE);
3823 FollowProlongation(*track, i1-7,1);
3824 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
3825 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3826 MarkSeedFree( seed ); seed = 0;
3832 FollowProlongation(*track, i2,1);
3833 track->SetBConstrain(0);
3834 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
3835 track->SetFirstPoint(track->GetLastPoint());
3837 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3838 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
3839 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3840 MarkSeedFree( seed ); seed = 0;
3845 FollowProlongation(*track, TMath::Max(i2-10,0),1);
3846 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3847 FollowProlongation(*track2, i2,1);
3848 track2->SetBConstrain(kFALSE);
3849 track2->SetSeedType(4);
3850 arr->AddLast(track2);
3851 MarkSeedFree( seed ); seed = 0;
3855 //arr->AddLast(track);
3856 //seed = new AliTPCseed;
3862 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);
3864 if (seed) MarkSeedFree(seed);
3868 //_____________________________________________________________________________
3869 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3870 Float_t deltay, Bool_t /*bconstrain*/) {
3871 //-----------------------------------------------------------------
3872 // This function creates track seeds - without vertex constraint
3873 //-----------------------------------------------------------------
3874 // cuts[0] - fP4 cut - not applied
3875 // cuts[1] - tan(phi) cut
3876 // cuts[2] - zvertex cut - not applied
3877 // cuts[3] - fP3 cut
3887 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3888 // Double_t cs=cos(alpha), sn=sin(alpha);
3889 Int_t row0 = (i1+i2)/2;
3890 Int_t drow = (i1-i2)/2;
3891 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3892 AliTPCtrackerRow * kr=0;
3894 AliTPCpolyTrack polytrack;
3895 Int_t nclusters=fSectors[sec][row0];
3896 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3897 seed->SetPoolID(fLastSeedID);
3902 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
3904 Int_t nfoundable =0;
3905 for (Int_t iter =1; iter<2; iter++){ //iterations
3906 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3907 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
3908 const AliTPCclusterMI * cl= kr0[is];
3910 if (cl->IsUsed(10)) {
3916 Double_t x = kr0.GetX();
3917 // Initialization of the polytrack
3922 Double_t y0= cl->GetY();
3923 Double_t z0= cl->GetZ();
3927 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3928 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
3930 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
3931 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
3932 polytrack.AddPoint(x,y0,z0,erry, errz);
3935 if (cl->IsUsed(10)) sumused++;
3938 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3939 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3942 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3943 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3944 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
3945 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3946 if (cl1->IsUsed(10)) sumused++;
3947 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3951 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3953 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
3954 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3955 if (cl2->IsUsed(10)) sumused++;
3956 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3959 if (sumused>0) continue;
3961 polytrack.UpdateParameters();
3967 nfoundable = polytrack.GetN();
3968 nfound = nfoundable;
3970 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3971 Float_t maxdist = 0.8*(1.+3./(ddrow));
3972 for (Int_t delta = -1;delta<=1;delta+=2){
3973 Int_t row = row0+ddrow*delta;
3974 kr = &(fSectors[sec][row]);
3975 Double_t xn = kr->GetX();
3976 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3977 polytrack.GetFitPoint(xn,yn,zn);
3978 if (TMath::Abs(yn)>ymax1) continue;
3980 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3982 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3985 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3986 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3987 if (cln->IsUsed(10)) {
3988 // printf("used\n");
3996 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4001 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4002 polytrack.UpdateParameters();
4005 if ( (sumused>3) || (sumused>0.5*nfound)) {
4006 //printf("sumused %d\n",sumused);
4011 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4012 AliTPCpolyTrack track2;
4014 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4015 if (track2.GetN()<0.5*nfoundable) continue;
4018 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4020 // test seed with and without constrain
4021 for (Int_t constrain=0; constrain<=0;constrain++){
4022 // add polytrack candidate
4024 Double_t x[5], c[15];
4025 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4026 track2.GetBoundaries(x3,x1);
4028 track2.GetFitPoint(x1,y1,z1);
4029 track2.GetFitPoint(x2,y2,z2);
4030 track2.GetFitPoint(x3,y3,z3);
4032 //is track pointing to the vertex ?
4035 polytrack.GetFitPoint(x0,y0,z0);
4048 x[4]=F1(x1,y1,x2,y2,x3,y3);
4050 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4051 x[2]=F2(x1,y1,x2,y2,x3,y3);
4053 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4054 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4055 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4056 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4059 Double_t sy =0.1, sz =0.1;
4060 Double_t sy1=0.02, sz1=0.02;
4061 Double_t sy2=0.02, sz2=0.02;
4065 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4068 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4069 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4070 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4071 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4072 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4073 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4075 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4076 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4077 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4078 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4083 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4084 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4085 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4086 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4087 c[13]=f30*sy1*f40+f32*sy2*f42;
4088 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4090 //Int_t row1 = fSectors->GetRowNumber(x1);
4091 Int_t row1 = GetRowNumber(x1);
4095 if (seed) {MarkSeedFree( seed ); seed = 0;}
4096 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4097 seed->SetPoolID(fLastSeedID);
4098 track->SetIsSeeding(kTRUE);
4099 Int_t rc=FollowProlongation(*track, i2);
4100 if (constrain) track->SetBConstrain(1);
4102 track->SetBConstrain(0);
4103 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4104 track->SetFirstPoint(track->GetLastPoint());
4106 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4107 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4108 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4109 MarkSeedFree( seed ); seed = 0;
4112 arr->AddLast(track); // track IS seed, don't free seed
4113 seed = new( NextFreeSeed() ) AliTPCseed;
4114 seed->SetPoolID(fLastSeedID);
4118 } // if accepted seed
4121 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4123 if (seed) MarkSeedFree( seed );
4127 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4131 //reseed using track points
4132 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4133 Int_t p1 = int(r1*track->GetNumberOfClusters());
4134 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4136 Double_t x0[3],x1[3],x2[3];
4137 for (Int_t i=0;i<3;i++){
4143 // find track position at given ratio of the length
4144 Int_t sec0=0, sec1=0, sec2=0;
4147 for (Int_t i=0;i<160;i++){
4148 if (track->GetClusterPointer(i)){
4150 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4151 if ( (index<p0) || x0[0]<0 ){
4152 if (trpoint->GetX()>1){
4153 clindex = track->GetClusterIndex2(i);
4155 x0[0] = trpoint->GetX();
4156 x0[1] = trpoint->GetY();
4157 x0[2] = trpoint->GetZ();
4158 sec0 = ((clindex&0xff000000)>>24)%18;
4163 if ( (index<p1) &&(trpoint->GetX()>1)){
4164 clindex = track->GetClusterIndex2(i);
4166 x1[0] = trpoint->GetX();
4167 x1[1] = trpoint->GetY();
4168 x1[2] = trpoint->GetZ();
4169 sec1 = ((clindex&0xff000000)>>24)%18;
4172 if ( (index<p2) &&(trpoint->GetX()>1)){
4173 clindex = track->GetClusterIndex2(i);
4175 x2[0] = trpoint->GetX();
4176 x2[1] = trpoint->GetY();
4177 x2[2] = trpoint->GetZ();
4178 sec2 = ((clindex&0xff000000)>>24)%18;
4185 Double_t alpha, cs,sn, xx2,yy2;
4187 alpha = (sec1-sec2)*fSectors->GetAlpha();
4188 cs = TMath::Cos(alpha);
4189 sn = TMath::Sin(alpha);
4190 xx2= x1[0]*cs-x1[1]*sn;
4191 yy2= x1[0]*sn+x1[1]*cs;
4195 alpha = (sec0-sec2)*fSectors->GetAlpha();
4196 cs = TMath::Cos(alpha);
4197 sn = TMath::Sin(alpha);
4198 xx2= x0[0]*cs-x0[1]*sn;
4199 yy2= x0[0]*sn+x0[1]*cs;
4205 Double_t x[5],c[15];
4209 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4210 // if (x[4]>1) return 0;
4211 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4212 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4213 //if (TMath::Abs(x[3]) > 2.2) return 0;
4214 //if (TMath::Abs(x[2]) > 1.99) return 0;
4216 Double_t sy =0.1, sz =0.1;
4218 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4219 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4220 Double_t sy3=0.01+track->GetSigmaY2();
4222 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4223 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4224 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4225 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4226 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4227 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4229 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4230 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4231 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4232 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4237 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4238 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4239 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4240 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4241 c[13]=f30*sy1*f40+f32*sy2*f42;
4242 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4244 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4245 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4246 seed->SetPoolID(fLastSeedID);
4247 // Double_t y0,z0,y1,z1, y2,z2;
4248 //seed->GetProlongation(x0[0],y0,z0);
4249 // seed->GetProlongation(x1[0],y1,z1);
4250 //seed->GetProlongation(x2[0],y2,z2);
4252 seed->SetLastPoint(pp2);
4253 seed->SetFirstPoint(pp2);
4260 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4264 //reseed using founded clusters
4266 // Find the number of clusters
4267 Int_t nclusters = 0;
4268 for (Int_t irow=0;irow<160;irow++){
4269 if (track->GetClusterIndex(irow)>0) nclusters++;
4273 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4274 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4275 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4278 Double_t xyz[3][3]={{0}};
4279 Int_t row[3]={0},sec[3]={0,0,0};
4281 // find track row position at given ratio of the length
4283 for (Int_t irow=0;irow<160;irow++){
4284 if (track->GetClusterIndex2(irow)<0) continue;
4286 for (Int_t ipoint=0;ipoint<3;ipoint++){
4287 if (index<=ipos[ipoint]) row[ipoint] = irow;
4291 //Get cluster and sector position
4292 for (Int_t ipoint=0;ipoint<3;ipoint++){
4293 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4294 AliTPCclusterMI * cl = GetClusterMI(clindex);
4297 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4300 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4301 xyz[ipoint][0] = GetXrow(row[ipoint]);
4302 xyz[ipoint][1] = cl->GetY();
4303 xyz[ipoint][2] = cl->GetZ();
4307 // Calculate seed state vector and covariance matrix
4309 Double_t alpha, cs,sn, xx2,yy2;
4311 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4312 cs = TMath::Cos(alpha);
4313 sn = TMath::Sin(alpha);
4314 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4315 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4319 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4320 cs = TMath::Cos(alpha);
4321 sn = TMath::Sin(alpha);
4322 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4323 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4329 Double_t x[5],c[15];
4333 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4334 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4335 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4337 Double_t sy =0.1, sz =0.1;
4339 Double_t sy1=0.2, sz1=0.2;
4340 Double_t sy2=0.2, sz2=0.2;
4343 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;
4344 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;
4345 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;
4346 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;
4347 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;
4348 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;
4350 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;
4351 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;
4352 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;
4353 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;
4358 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4359 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4360 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4361 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4362 c[13]=f30*sy1*f40+f32*sy2*f42;
4363 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4365 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4366 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4367 seed->SetPoolID(fLastSeedID);
4368 seed->SetLastPoint(row[2]);
4369 seed->SetFirstPoint(row[2]);
4374 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4378 //reseed using founded clusters
4381 Int_t row[3]={0,0,0};
4382 Int_t sec[3]={0,0,0};
4384 // forward direction
4386 for (Int_t irow=r0;irow<160;irow++){
4387 if (track->GetClusterIndex(irow)>0){
4392 for (Int_t irow=160;irow>r0;irow--){
4393 if (track->GetClusterIndex(irow)>0){
4398 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4399 if (track->GetClusterIndex(irow)>0){
4407 for (Int_t irow=0;irow<r0;irow++){
4408 if (track->GetClusterIndex(irow)>0){
4413 for (Int_t irow=r0;irow>0;irow--){
4414 if (track->GetClusterIndex(irow)>0){
4419 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4420 if (track->GetClusterIndex(irow)>0){
4427 if ((row[2]-row[0])<20) return 0;
4428 if (row[1]==0) return 0;
4431 //Get cluster and sector position
4432 for (Int_t ipoint=0;ipoint<3;ipoint++){
4433 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4434 AliTPCclusterMI * cl = GetClusterMI(clindex);
4437 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4440 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4441 xyz[ipoint][0] = GetXrow(row[ipoint]);
4442 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4443 if (point&&ipoint<2){
4445 xyz[ipoint][1] = point->GetY();
4446 xyz[ipoint][2] = point->GetZ();
4449 xyz[ipoint][1] = cl->GetY();
4450 xyz[ipoint][2] = cl->GetZ();
4457 // Calculate seed state vector and covariance matrix
4459 Double_t alpha, cs,sn, xx2,yy2;
4461 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4462 cs = TMath::Cos(alpha);
4463 sn = TMath::Sin(alpha);
4464 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4465 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4469 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4470 cs = TMath::Cos(alpha);
4471 sn = TMath::Sin(alpha);
4472 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4473 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4479 Double_t x[5],c[15];
4483 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4484 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4485 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4487 Double_t sy =0.1, sz =0.1;
4489 Double_t sy1=0.2, sz1=0.2;
4490 Double_t sy2=0.2, sz2=0.2;
4493 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;
4494 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;
4495 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;
4496 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;
4497 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;
4498 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;
4500 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;
4501 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;
4502 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;
4503 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;
4508 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4509 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4510 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4511 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4512 c[13]=f30*sy1*f40+f32*sy2*f42;
4513 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4515 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4516 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4517 seed->SetPoolID(fLastSeedID);
4518 seed->SetLastPoint(row[2]);
4519 seed->SetFirstPoint(row[2]);
4520 for (Int_t i=row[0];i<row[2];i++){
4521 seed->SetClusterIndex(i, track->GetClusterIndex(i));
4529 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4532 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4534 // Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4536 // Two reasons to have multiple find tracks
4537 // 1. Curling tracks can be find more than once
4538 // 2. Splitted tracks
4539 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
4540 // b.) Edge effect on the sector boundaries
4543 // Algorithm done in 2 phases - because of CPU consumption
4544 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4546 // Algorihm for curling tracks sign:
4547 // 1 phase -makes a very rough fast cuts to minimize combinatorics
4548 // a.) opposite sign
4549 // b.) one of the tracks - not pointing to the primary vertex -
4550 // c.) delta tan(theta)
4552 // 2 phase - calculates DCA between tracks - time consument
4557 // General cuts - for splitted tracks and for curling tracks
4559 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
4561 // Curling tracks cuts
4566 Int_t nentries = array->GetEntriesFast();
4567 AliHelix *helixes = new AliHelix[nentries];
4568 Float_t *xm = new Float_t[nentries];
4569 Float_t *dz0 = new Float_t[nentries];
4570 Float_t *dz1 = new Float_t[nentries];
4576 // Find track COG in x direction - point with best defined parameters
4578 for (Int_t i=0;i<nentries;i++){
4579 AliTPCseed* track = (AliTPCseed*)array->At(i);
4580 if (!track) continue;
4581 track->SetCircular(0);
4582 new (&helixes[i]) AliHelix(*track);
4586 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4589 for (Int_t icl=0; icl<160; icl++){
4590 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
4596 if (ncl>0) xm[i]/=Float_t(ncl);
4599 for (Int_t i0=0;i0<nentries;i0++){
4600 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4601 if (!track0) continue;
4602 Float_t xc0 = helixes[i0].GetHelix(6);
4603 Float_t yc0 = helixes[i0].GetHelix(7);
4604 Float_t r0 = helixes[i0].GetHelix(8);
4605 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4606 Float_t fi0 = TMath::ATan2(yc0,xc0);
4608 for (Int_t i1=i0+1;i1<nentries;i1++){
4609 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4610 if (!track1) continue;
4611 Int_t lab0=track0->GetLabel();
4612 Int_t lab1=track1->GetLabel();
4613 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4615 Float_t xc1 = helixes[i1].GetHelix(6);
4616 Float_t yc1 = helixes[i1].GetHelix(7);
4617 Float_t r1 = helixes[i1].GetHelix(8);
4618 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4619 Float_t fi1 = TMath::ATan2(yc1,xc1);
4621 Float_t dfi = fi0-fi1;
4624 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4625 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4626 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4628 // if short tracks with undefined sign
4629 fi1 = -TMath::ATan2(yc1,-xc1);
4632 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4635 // debug stream to tune "fast cuts"
4637 Double_t dist[3]; // distance at X
4638 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
4639 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4640 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4641 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4642 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4643 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4644 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4645 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4649 for (Int_t icl=0; icl<160; icl++){
4650 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
4651 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
4654 if (cl0==cl1) sums++;
4658 if (AliTPCReconstructor::StreamLevel()>5) {
4659 TTreeSRedirector &cstream = *fDebugStreamer;
4664 "Tr0.="<<track0<< // seed0
4665 "Tr1.="<<track1<< // seed1
4666 "h0.="<<&helixes[i0]<<
4667 "h1.="<<&helixes[i1]<<
4669 "sum="<<sum<< //the sum of rows with cl in both
4670 "sums="<<sums<< //the sum of shared clusters
4671 "xm0="<<xm[i0]<< // the center of track
4672 "xm1="<<xm[i1]<< // the x center of track
4673 // General cut variables
4674 "dfi="<<dfi<< // distance in fi angle
4675 "dtheta="<<dtheta<< // distance int theta angle
4681 "dist0="<<dist[0]<< //distance x
4682 "dist1="<<dist[1]<< //distance y
4683 "dist2="<<dist[2]<< //distance z
4684 "mdist0="<<mdist[0]<< //distance x
4685 "mdist1="<<mdist[1]<< //distance y
4686 "mdist2="<<mdist[2]<< //distance z
4702 if (AliTPCReconstructor::StreamLevel()>1) {
4703 AliInfo("Time for curling tracks removal DEBUGGING MC");
4710 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
4712 // Find Splitted tracks and remove the one with worst quality
4713 // Corresponding debug streamer to tune selections - "Splitted2"
4715 // 0. Sort tracks according quility
4716 // 1. Propagate the tracks to the reference radius
4717 // 2. Double_t loop to select close tracks (only to speed up process)
4718 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
4719 // 4. Delete temporary parameters
4721 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
4723 const Double_t kCutP1=10; // delta Z cut 10 cm
4724 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
4725 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
4726 const Double_t kCutAlpha=0.15; // delta alpha cut
4727 Int_t firstpoint = 0;
4728 Int_t lastpoint = 160;
4730 Int_t nentries = array->GetEntriesFast();
4731 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
4737 //0. Sort tracks according quality
4738 //1. Propagate the ext. param to reference radius
4739 Int_t nseed = array->GetEntriesFast();
4740 if (nseed<=0) return;
4741 Float_t * quality = new Float_t[nseed];
4742 Int_t * indexes = new Int_t[nseed];
4743 for (Int_t i=0; i<nseed; i++) {
4744 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
4749 pt->UpdatePoints(); //select first last max dens points
4750 Float_t * points = pt->GetPoints();
4751 if (points[3]<0.8) quality[i] =-1;
4752 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4753 //prefer high momenta tracks if overlaps
4754 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
4756 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
4757 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
4759 TMath::Sort(nseed,quality,indexes);
4761 // 3. Loop over pair of tracks
4763 for (Int_t i0=0; i0<nseed; i0++) {
4764 Int_t index0=indexes[i0];
4765 if (!(array->UncheckedAt(index0))) continue;
4766 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
4767 if (!s1->IsActive()) continue;
4768 AliExternalTrackParam &par0=params[index0];
4769 for (Int_t i1=i0+1; i1<nseed; i1++) {
4770 Int_t index1=indexes[i1];
4771 if (!(array->UncheckedAt(index1))) continue;
4772 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
4773 if (!s2->IsActive()) continue;
4774 if (s2->GetKinkIndexes()[0]!=0)
4775 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
4776 AliExternalTrackParam &par1=params[index1];
4777 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
4778 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
4779 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
4780 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
4781 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
4782 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
4787 Int_t firstShared=lastpoint, lastShared=firstpoint;
4788 Int_t firstRow=lastpoint, lastRow=firstpoint;
4790 for (Int_t i=firstpoint;i<lastpoint;i++){
4791 if (s1->GetClusterIndex2(i)>0) nall0++;
4792 if (s2->GetClusterIndex2(i)>0) nall1++;
4793 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
4794 if (i<firstRow) firstRow=i;
4795 if (i>lastRow) lastRow=i;
4797 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
4798 if (i<firstShared) firstShared=i;
4799 if (i>lastShared) lastShared=i;
4803 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
4804 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
4806 if( AliTPCReconstructor::StreamLevel()>1){
4807 TTreeSRedirector &cstream = *fDebugStreamer;
4808 Int_t n0=s1->GetNumberOfClusters();
4809 Int_t n1=s2->GetNumberOfClusters();
4810 Int_t n0F=s1->GetNFoundable();
4811 Int_t n1F=s2->GetNFoundable();
4812 Int_t lab0=s1->GetLabel();
4813 Int_t lab1=s2->GetLabel();
4815 cstream<<"Splitted2"<<
4816 "iter="<<fIteration<<
4817 "lab0="<<lab0<< // MC label if exist
4818 "lab1="<<lab1<< // MC label if exist
4821 "ratio0="<<ratio0<< // shared ratio
4822 "ratio1="<<ratio1<< // shared ratio
4823 "p0.="<<&par0<< // track parameters
4825 "s0.="<<s1<< // full seed
4827 "n0="<<n0<< // number of clusters track 0
4828 "n1="<<n1<< // number of clusters track 1
4829 "nall0="<<nall0<< // number of clusters track 0
4830 "nall1="<<nall1<< // number of clusters track 1
4831 "n0F="<<n0F<< // number of findable
4832 "n1F="<<n1F<< // number of findable
4833 "shared="<<sumShared<< // number of shared clusters
4834 "firstS="<<firstShared<< // first and the last shared row
4835 "lastS="<<lastShared<<
4836 "firstRow="<<firstRow<< // first and the last row with cluster
4837 "lastRow="<<lastRow<< //
4841 // remove track with lower quality
4843 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
4844 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
4848 MarkSeedFree( array->RemoveAt(index1) );
4853 // 4. Delete temporary array
4863 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4866 // find Curling tracks
4867 // Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4870 // Algorithm done in 2 phases - because of CPU consumption
4871 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4872 // see detal in MC part what can be used to cut
4876 const Float_t kMaxC = 400; // maximal curvature to of the track
4877 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
4878 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
4879 const Float_t kPtRatio = 0.3; // ratio between pt
4880 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
4883 // Curling tracks cuts
4886 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
4887 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
4888 const Float_t kMinAngle = 2.9; // angle between tracks
4889 const Float_t kMaxDist = 5; // biggest distance
4891 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4894 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4895 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4896 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4897 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4898 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
4900 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4901 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4903 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
4904 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4906 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4912 Int_t nentries = array->GetEntriesFast();
4913 AliHelix *helixes = new AliHelix[nentries];
4914 for (Int_t i=0;i<nentries;i++){
4915 AliTPCseed* track = (AliTPCseed*)array->At(i);
4916 if (!track) continue;
4917 track->SetCircular(0);
4918 new (&helixes[i]) AliHelix(*track);
4924 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4930 for (Int_t i0=0;i0<nentries;i0++){
4931 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4932 if (!track0) continue;
4933 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4934 Float_t xc0 = helixes[i0].GetHelix(6);
4935 Float_t yc0 = helixes[i0].GetHelix(7);
4936 Float_t r0 = helixes[i0].GetHelix(8);
4937 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4938 Float_t fi0 = TMath::ATan2(yc0,xc0);
4940 for (Int_t i1=i0+1;i1<nentries;i1++){
4941 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4942 if (!track1) continue;
4943 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
4944 Float_t xc1 = helixes[i1].GetHelix(6);
4945 Float_t yc1 = helixes[i1].GetHelix(7);
4946 Float_t r1 = helixes[i1].GetHelix(8);
4947 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4948 Float_t fi1 = TMath::ATan2(yc1,xc1);
4950 Float_t dfi = fi0-fi1;
4953 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4954 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4955 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4959 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
4960 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
4961 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4962 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
4963 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4965 Float_t pt0 = track0->GetSignedPt();
4966 Float_t pt1 = track1->GetSignedPt();
4967 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
4968 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4969 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
4970 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
4973 // Now find closest approach
4977 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4978 if (npoints==0) continue;
4979 helixes[i0].GetClosestPhases(helixes[i1], phase);
4983 Double_t hangles[3];
4984 helixes[i0].Evaluate(phase[0][0],xyz0);
4985 helixes[i1].Evaluate(phase[0][1],xyz1);
4987 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4988 Double_t deltah[2],deltabest;
4989 if (TMath::Abs(hangles[2])<kMinAngle) continue;
4993 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
4995 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
4996 if (deltah[1]<deltah[0]) ibest=1;
4998 deltabest = TMath::Sqrt(deltah[ibest]);
4999 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5000 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5001 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5002 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5004 if (deltabest>kMaxDist) continue;
5005 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5006 Bool_t sign =kFALSE;
5007 if (hangles[2]>kMinAngle) sign =kTRUE;
5010 // circular[i0] = kTRUE;
5011 // circular[i1] = kTRUE;
5012 if (track0->OneOverPt()<track1->OneOverPt()){
5013 track0->SetCircular(track0->GetCircular()+1);
5014 track1->SetCircular(track1->GetCircular()+2);
5017 track1->SetCircular(track1->GetCircular()+1);
5018 track0->SetCircular(track0->GetCircular()+2);
5021 if (AliTPCReconstructor::StreamLevel()>2){
5023 //debug stream to tune "fine" cuts
5024 Int_t lab0=track0->GetLabel();
5025 Int_t lab1=track1->GetLabel();
5026 TTreeSRedirector &cstream = *fDebugStreamer;
5027 cstream<<"Curling2"<<
5043 "npoints="<<npoints<<
5044 "hangles0="<<hangles[0]<<
5045 "hangles1="<<hangles[1]<<
5046 "hangles2="<<hangles[2]<<
5049 "radius="<<radiusbest<<
5050 "deltabest="<<deltabest<<
5051 "phase0="<<phase[ibest][0]<<
5052 "phase1="<<phase[ibest][1]<<
5060 if (AliTPCReconstructor::StreamLevel()>1) {
5061 AliInfo("Time for curling tracks removal");
5067 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5073 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5076 TObjArray *kinks= new TObjArray(10000);
5077 // TObjArray *v0s= new TObjArray(10000);
5078 Int_t nentries = array->GetEntriesFast();
5079 AliHelix *helixes = new AliHelix[nentries];
5080 Int_t *sign = new Int_t[nentries];
5081 Int_t *nclusters = new Int_t[nentries];
5082 Float_t *alpha = new Float_t[nentries];
5083 AliKink *kink = new AliKink();
5084 Int_t * usage = new Int_t[nentries];
5085 Float_t *zm = new Float_t[nentries];
5086 Float_t *z0 = new Float_t[nentries];
5087 Float_t *fim = new Float_t[nentries];
5088 Float_t *shared = new Float_t[nentries];
5089 Bool_t *circular = new Bool_t[nentries];
5090 Float_t *dca = new Float_t[nentries];
5091 //const AliESDVertex * primvertex = esd->GetVertex();
5093 // nentries = array->GetEntriesFast();
5098 for (Int_t i=0;i<nentries;i++){
5101 AliTPCseed* track = (AliTPCseed*)array->At(i);
5102 if (!track) continue;
5103 track->SetCircular(0);
5105 track->UpdatePoints();
5106 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5108 nclusters[i]=track->GetNumberOfClusters();
5109 alpha[i] = track->GetAlpha();
5110 new (&helixes[i]) AliHelix(*track);
5112 helixes[i].Evaluate(0,xyz);
5113 sign[i] = (track->GetC()>0) ? -1:1;
5116 if (track->GetProlongation(x,y,z)){
5118 fim[i] = alpha[i]+TMath::ATan2(y,x);
5121 zm[i] = track->GetZ();
5125 circular[i]= kFALSE;
5126 if (track->GetProlongation(0,y,z)) z0[i] = z;
5127 dca[i] = track->GetD(0,0);
5133 Int_t ncandidates =0;
5136 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5139 // Find circling track
5141 for (Int_t i0=0;i0<nentries;i0++){
5142 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5143 if (!track0) continue;
5144 if (track0->GetNumberOfClusters()<40) continue;
5145 if (TMath::Abs(1./track0->GetC())>200) continue;
5146 for (Int_t i1=i0+1;i1<nentries;i1++){
5147 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5148 if (!track1) continue;
5149 if (track1->GetNumberOfClusters()<40) continue;
5150 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5151 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5152 if (TMath::Abs(1./track1->GetC())>200) continue;
5153 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5154 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5155 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5156 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5157 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5159 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5160 if (mindcar<5) continue;
5161 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5162 if (mindcaz<5) continue;
5163 if (mindcar+mindcaz<20) continue;
5166 Float_t xc0 = helixes[i0].GetHelix(6);
5167 Float_t yc0 = helixes[i0].GetHelix(7);
5168 Float_t r0 = helixes[i0].GetHelix(8);
5169 Float_t xc1 = helixes[i1].GetHelix(6);
5170 Float_t yc1 = helixes[i1].GetHelix(7);
5171 Float_t r1 = helixes[i1].GetHelix(8);
5173 Float_t rmean = (r0+r1)*0.5;
5174 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5175 //if (delta>30) continue;
5176 if (delta>rmean*0.25) continue;
5177 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5179 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5180 if (npoints==0) continue;
5181 helixes[i0].GetClosestPhases(helixes[i1], phase);
5185 Double_t hangles[3];
5186 helixes[i0].Evaluate(phase[0][0],xyz0);
5187 helixes[i1].Evaluate(phase[0][1],xyz1);
5189 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5190 Double_t deltah[2],deltabest;
5191 if (hangles[2]<2.8) continue;
5194 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5196 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5197 if (deltah[1]<deltah[0]) ibest=1;
5199 deltabest = TMath::Sqrt(deltah[ibest]);
5200 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5201 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5202 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5203 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5205 if (deltabest>6) continue;
5206 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5207 Bool_t lsign =kFALSE;
5208 if (hangles[2]>3.06) lsign =kTRUE;
5211 circular[i0] = kTRUE;
5212 circular[i1] = kTRUE;
5213 if (track0->OneOverPt()<track1->OneOverPt()){
5214 track0->SetCircular(track0->GetCircular()+1);
5215 track1->SetCircular(track1->GetCircular()+2);
5218 track1->SetCircular(track1->GetCircular()+1);
5219 track0->SetCircular(track0->GetCircular()+2);
5222 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5224 Int_t lab0=track0->GetLabel();
5225 Int_t lab1=track1->GetLabel();
5226 TTreeSRedirector &cstream = *fDebugStreamer;
5227 cstream<<"Curling"<<
5234 "mindcar="<<mindcar<<
5235 "mindcaz="<<mindcaz<<
5238 "npoints="<<npoints<<
5239 "hangles0="<<hangles[0]<<
5240 "hangles2="<<hangles[2]<<
5245 "radius="<<radiusbest<<
5246 "deltabest="<<deltabest<<
5247 "phase0="<<phase[ibest][0]<<
5248 "phase1="<<phase[ibest][1]<<
5258 for (Int_t i =0;i<nentries;i++){
5259 if (sign[i]==0) continue;
5260 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5267 Double_t cradius0 = 40*40;
5268 Double_t cradius1 = 270*270;
5271 Double_t cdist3=0.55;
5272 for (Int_t j =i+1;j<nentries;j++){
5274 if (sign[j]*sign[i]<1) continue;
5275 if ( (nclusters[i]+nclusters[j])>200) continue;
5276 if ( (nclusters[i]+nclusters[j])<80) continue;
5277 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5278 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5279 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5280 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5281 if (npoints<1) continue;
5284 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5287 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5290 Double_t delta1=10000,delta2=10000;
5291 // cuts on the intersection radius
5292 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5293 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5294 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5296 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5297 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5298 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5301 Double_t distance1 = TMath::Min(delta1,delta2);
5302 if (distance1>cdist1) continue; // cut on DCA linear approximation
5304 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5305 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5306 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5307 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5310 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5311 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5312 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5314 distance1 = TMath::Min(delta1,delta2);
5317 rkink = TMath::Sqrt(radius[0]);
5320 rkink = TMath::Sqrt(radius[1]);
5322 if (distance1>cdist2) continue;
5325 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5328 Int_t row0 = GetRowNumber(rkink);
5329 if (row0<10) continue;
5330 if (row0>150) continue;
5333 Float_t dens00=-1,dens01=-1;
5334 Float_t dens10=-1,dens11=-1;
5336 Int_t found,foundable,ishared;
5337 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5338 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5339 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5340 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5342 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5343 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5344 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5345 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5347 if (dens00<dens10 && dens01<dens11) continue;
5348 if (dens00>dens10 && dens01>dens11) continue;
5349 if (TMath::Max(dens00,dens10)<0.1) continue;
5350 if (TMath::Max(dens01,dens11)<0.3) continue;
5352 if (TMath::Min(dens00,dens10)>0.6) continue;
5353 if (TMath::Min(dens01,dens11)>0.6) continue;
5356 AliTPCseed * ktrack0, *ktrack1;
5365 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5366 AliExternalTrackParam paramm(*ktrack0);
5367 AliExternalTrackParam paramd(*ktrack1);
5368 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5371 kink->SetMother(paramm);
5372 kink->SetDaughter(paramd);
5375 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
5377 fkParam->Transform0to1(x,index);
5378 fkParam->Transform1to2(x,index);
5379 row0 = GetRowNumber(x[0]);
5381 if (kink->GetR()<100) continue;
5382 if (kink->GetR()>240) continue;
5383 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5384 if (kink->GetDistance()>cdist3) continue;
5385 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5386 if (dird<0) continue;
5388 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5389 if (dirm<0) continue;
5390 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5391 if (mpt<0.2) continue;
5394 //for high momenta momentum not defined well in first iteration
5395 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5396 if (qt>0.35) continue;
5399 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5400 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5402 kink->SetTPCDensity(dens00,0,0);
5403 kink->SetTPCDensity(dens01,0,1);
5404 kink->SetTPCDensity(dens10,1,0);
5405 kink->SetTPCDensity(dens11,1,1);
5406 kink->SetIndex(i,0);
5407 kink->SetIndex(j,1);
5410 kink->SetTPCDensity(dens10,0,0);
5411 kink->SetTPCDensity(dens11,0,1);
5412 kink->SetTPCDensity(dens00,1,0);
5413 kink->SetTPCDensity(dens01,1,1);
5414 kink->SetIndex(j,0);
5415 kink->SetIndex(i,1);
5418 if (mpt<1||kink->GetAngle(2)>0.1){
5419 // angle and densities not defined yet
5420 if (kink->GetTPCDensityFactor()<0.8) continue;
5421 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5422 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5423 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5424 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5426 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5427 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5428 criticalangle= 3*TMath::Sqrt(criticalangle);
5429 if (criticalangle>0.02) criticalangle=0.02;
5430 if (kink->GetAngle(2)<criticalangle) continue;
5433 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5434 Float_t shapesum =0;
5436 for ( Int_t row = row0-drow; row<row0+drow;row++){
5437 if (row<0) continue;
5438 if (row>155) continue;
5439 if (ktrack0->GetClusterPointer(row)){
5440 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5441 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5444 if (ktrack1->GetClusterPointer(row)){
5445 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5446 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5451 kink->SetShapeFactor(-1.);
5454 kink->SetShapeFactor(shapesum/sum);
5456 // esd->AddKink(kink);
5458 // kink->SetMother(paramm);
5459 //kink->SetDaughter(paramd);
5461 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5463 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5464 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5466 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5468 if (AliTPCReconstructor::StreamLevel()>1) {
5469 (*fDebugStreamer)<<"kinkLpt"<<
5477 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5481 kinks->AddLast(kink);
5487 // sort the kinks according quality - and refit them towards vertex
5489 Int_t nkinks = kinks->GetEntriesFast();
5490 Float_t *quality = new Float_t[nkinks];
5491 Int_t *indexes = new Int_t[nkinks];
5492 AliTPCseed *mothers = new AliTPCseed[nkinks];
5493 AliTPCseed *daughters = new AliTPCseed[nkinks];
5496 for (Int_t i=0;i<nkinks;i++){
5498 AliKink *kinkl = (AliKink*)kinks->At(i);
5500 // refit kinks towards vertex
5502 Int_t index0 = kinkl->GetIndex(0);
5503 Int_t index1 = kinkl->GetIndex(1);
5504 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5505 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5507 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5509 // Refit Kink under if too small angle
5511 if (kinkl->GetAngle(2)<0.05){
5512 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5513 Int_t row0 = kinkl->GetTPCRow0();
5514 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5517 Int_t last = row0-drow;
5518 if (last<40) last=40;
5519 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5520 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5523 Int_t first = row0+drow;
5524 if (first>130) first=130;
5525 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5526 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5528 if (seed0 && seed1){
5529 kinkl->SetStatus(1,8);
5530 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5531 row0 = GetRowNumber(kinkl->GetR());
5532 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5533 mothers[i] = *seed0;
5534 daughters[i] = *seed1;
5537 delete kinks->RemoveAt(i);
5538 if (seed0) MarkSeedFree( seed0 );
5539 if (seed1) MarkSeedFree( seed1 );
5542 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
5543 delete kinks->RemoveAt(i);
5544 if (seed0) MarkSeedFree( seed0 );
5545 if (seed1) MarkSeedFree( seed1 );
5549 MarkSeedFree( seed0 );
5550 MarkSeedFree( seed1 );
5553 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
5555 TMath::Sort(nkinks,quality,indexes,kFALSE);
5557 //remove double find kinks
5559 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5560 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5561 if (!kink0) continue;
5563 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5564 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5565 if (!kink0) continue;
5566 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5567 if (!kink1) continue;
5568 // if not close kink continue
5569 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5570 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5571 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5573 AliTPCseed &mother0 = mothers[indexes[ikink0]];
5574 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5575 AliTPCseed &mother1 = mothers[indexes[ikink1]];
5576 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5577 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5586 for (Int_t i=0;i<row0;i++){
5587 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5590 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5597 for (Int_t i=row0;i<158;i++){
5598 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
5599 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
5602 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5608 Float_t ratio = Float_t(same+1)/Float_t(both+1);
5609 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5610 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5611 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5612 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5613 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5615 shared[kink0->GetIndex(0)]= kTRUE;
5616 shared[kink0->GetIndex(1)]= kTRUE;
5617 delete kinks->RemoveAt(indexes[ikink0]);
5621 shared[kink1->GetIndex(0)]= kTRUE;
5622 shared[kink1->GetIndex(1)]= kTRUE;
5623 delete kinks->RemoveAt(indexes[ikink1]);
5630 for (Int_t i=0;i<nkinks;i++){
5631 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
5632 if (!kinkl) continue;
5633 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5634 Int_t index0 = kinkl->GetIndex(0);
5635 Int_t index1 = kinkl->GetIndex(1);
5636 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
5637 kinkl->SetMultiple(usage[index0],0);
5638 kinkl->SetMultiple(usage[index1],1);
5639 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
5640 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5641 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
5642 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
5644 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5645 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5646 if (!ktrack0 || !ktrack1) continue;
5647 Int_t index = esd->AddKink(kinkl);
5650 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
5651 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5652 *ktrack0 = mothers[indexes[i]];
5653 *ktrack1 = daughters[indexes[i]];
5657 ktrack0->SetKinkIndex(usage[index0],-(index+1));
5658 ktrack1->SetKinkIndex(usage[index1], (index+1));
5663 // Remove tracks corresponding to shared kink's
5665 for (Int_t i=0;i<nentries;i++){
5666 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5667 if (!track0) continue;
5668 if (track0->GetKinkIndex(0)!=0) continue;
5669 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
5674 RemoveUsed2(array,0.5,0.4,30);
5676 for (Int_t i=0;i<nentries;i++){
5677 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5678 if (!track0) continue;
5679 track0->CookdEdx(0.02,0.6);
5683 for (Int_t i=0;i<nentries;i++){
5684 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5685 if (!track0) continue;
5686 if (track0->Pt()<1.4) continue;
5687 //remove double high momenta tracks - overlapped with kink candidates
5690 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5691 if (track0->GetClusterPointer(icl)!=0){
5693 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
5696 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
5697 MarkSeedFree( array->RemoveAt(i) );
5701 if (track0->GetKinkIndex(0)!=0) continue;
5702 if (track0->GetNumberOfClusters()<80) continue;
5704 AliTPCseed *pmother = new AliTPCseed();
5705 AliTPCseed *pdaughter = new AliTPCseed();
5706 AliKink *pkink = new AliKink;
5708 AliTPCseed & mother = *pmother;
5709 AliTPCseed & daughter = *pdaughter;
5710 AliKink & kinkl = *pkink;
5711 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
5712 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5716 continue; //too short tracks
5718 if (mother.Pt()<1.4) {
5724 Int_t row0= kinkl.GetTPCRow0();
5725 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
5732 Int_t index = esd->AddKink(&kinkl);
5733 mother.SetKinkIndex(0,-(index+1));
5734 daughter.SetKinkIndex(0,index+1);
5735 if (mother.GetNumberOfClusters()>50) {
5736 MarkSeedFree( array->RemoveAt(i) );
5737 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5738 mtc->SetPoolID(fLastSeedID);
5739 array->AddAt(mtc,i);
5742 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5743 mtc->SetPoolID(fLastSeedID);
5744 array->AddLast(mtc);
5746 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
5747 dtc->SetPoolID(fLastSeedID);
5748 array->AddLast(dtc);
5749 for (Int_t icl=0;icl<row0;icl++) {
5750 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5753 for (Int_t icl=row0;icl<158;icl++) {
5754 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5763 delete [] daughters;
5785 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
5791 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5798 TObjArray *kinks= new TObjArray(10000);
5799 // TObjArray *v0s= new TObjArray(10000);
5800 Int_t nentries = array->GetEntriesFast();
5801 AliHelix *helixes = new AliHelix[nentries];
5802 Int_t *sign = new Int_t[nentries];
5803 Int_t *nclusters = new Int_t[nentries];
5804 Float_t *alpha = new Float_t[nentries];
5805 AliKink *kink = new AliKink();
5806 Int_t * usage = new Int_t[nentries];
5807 Float_t *zm = new Float_t[nentries];
5808 Float_t *z0 = new Float_t[nentries];
5809 Float_t *fim = new Float_t[nentries];
5810 Float_t *shared = new Float_t[nentries];
5811 Bool_t *circular = new Bool_t[nentries];
5812 Float_t *dca = new Float_t[nentries];
5813 //const AliESDVertex * primvertex = esd->GetVertex();
5815 // nentries = array->GetEntriesFast();
5820 for (Int_t i=0;i<nentries;i++){
5823 AliTPCseed* track = (AliTPCseed*)array->At(i);
5824 if (!track) continue;
5825 track->SetCircular(0);
5827 track->UpdatePoints();
5828 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5830 nclusters[i]=track->GetNumberOfClusters();
5831 alpha[i] = track->GetAlpha();
5832 new (&helixes[i]) AliHelix(*track);
5834 helixes[i].Evaluate(0,xyz);
5835 sign[i] = (track->GetC()>0) ? -1:1;
5838 if (track->GetProlongation(x,y,z)){
5840 fim[i] = alpha[i]+TMath::ATan2(y,x);
5843 zm[i] = track->GetZ();
5847 circular[i]= kFALSE;
5848 if (track->GetProlongation(0,y,z)) z0[i] = z;
5849 dca[i] = track->GetD(0,0);
5855 Int_t ncandidates =0;
5858 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5861 // Find circling track
5863 for (Int_t i0=0;i0<nentries;i0++){
5864 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5865 if (!track0) continue;
5866 if (track0->GetNumberOfClusters()<40) continue;
5867 if (TMath::Abs(1./track0->GetC())>200) continue;
5868 for (Int_t i1=i0+1;i1<nentries;i1++){
5869 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5870 if (!track1) continue;
5871 if (track1->GetNumberOfClusters()<40) continue;
5872 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5873 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5874 if (TMath::Abs(1./track1->GetC())>200) continue;
5875 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5876 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5877 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5878 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5879 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5881 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5882 if (mindcar<5) continue;
5883 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5884 if (mindcaz<5) continue;
5885 if (mindcar+mindcaz<20) continue;
5888 Float_t xc0 = helixes[i0].GetHelix(6);
5889 Float_t yc0 = helixes[i0].GetHelix(7);
5890 Float_t r0 = helixes[i0].GetHelix(8);
5891 Float_t xc1 = helixes[i1].GetHelix(6);
5892 Float_t yc1 = helixes[i1].GetHelix(7);
5893 Float_t r1 = helixes[i1].GetHelix(8);
5895 Float_t rmean = (r0+r1)*0.5;
5896 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5897 //if (delta>30) continue;
5898 if (delta>rmean*0.25) continue;
5899 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5901 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5902 if (npoints==0) continue;
5903 helixes[i0].GetClosestPhases(helixes[i1], phase);
5907 Double_t hangles[3];
5908 helixes[i0].Evaluate(phase[0][0],xyz0);
5909 helixes[i1].Evaluate(phase[0][1],xyz1);
5911 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5912 Double_t deltah[2],deltabest;
5913 if (hangles[2]<2.8) continue;
5916 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5918 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5919 if (deltah[1]<deltah[0]) ibest=1;
5921 deltabest = TMath::Sqrt(deltah[ibest]);
5922 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5923 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5924 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5925 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5927 if (deltabest>6) continue;
5928 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5929 Bool_t lsign =kFALSE;
5930 if (hangles[2]>3.06) lsign =kTRUE;
5933 circular[i0] = kTRUE;
5934 circular[i1] = kTRUE;
5935 if (track0->OneOverPt()<track1->OneOverPt()){
5936 track0->SetCircular(track0->GetCircular()+1);
5937 track1->SetCircular(track1->GetCircular()+2);
5940 track1->SetCircular(track1->GetCircular()+1);
5941 track0->SetCircular(track0->GetCircular()+2);
5944 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5946 Int_t lab0=track0->GetLabel();
5947 Int_t lab1=track1->GetLabel();
5948 TTreeSRedirector &cstream = *fDebugStreamer;
5949 cstream<<"Curling"<<
5956 "mindcar="<<mindcar<<
5957 "mindcaz="<<mindcaz<<
5960 "npoints="<<npoints<<
5961 "hangles0="<<hangles[0]<<
5962 "hangles2="<<hangles[2]<<
5967 "radius="<<radiusbest<<
5968 "deltabest="<<deltabest<<
5969 "phase0="<<phase[ibest][0]<<
5970 "phase1="<<phase[ibest][1]<<
5980 for (Int_t i =0;i<nentries;i++){
5981 if (sign[i]==0) continue;
5982 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5989 Double_t cradius0 = 40*40;
5990 Double_t cradius1 = 270*270;
5993 Double_t cdist3=0.55;
5994 for (Int_t j =i+1;j<nentries;j++){
5996 if (sign[j]*sign[i]<1) continue;
5997 if ( (nclusters[i]+nclusters[j])>200) continue;
5998 if ( (nclusters[i]+nclusters[j])<80) continue;
5999 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6000 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6001 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6002 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6003 if (npoints<1) continue;
6006 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6009 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6012 Double_t delta1=10000,delta2=10000;
6013 // cuts on the intersection radius
6014 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6015 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6016 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6018 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6019 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6020 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6023 Double_t distance1 = TMath::Min(delta1,delta2);
6024 if (distance1>cdist1) continue; // cut on DCA linear approximation
6026 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6027 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6028 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6029 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6032 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6033 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6034 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6036 distance1 = TMath::Min(delta1,delta2);
6039 rkink = TMath::Sqrt(radius[0]);
6042 rkink = TMath::Sqrt(radius[1]);
6044 if (distance1>cdist2) continue;
6047 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6050 Int_t row0 = GetRowNumber(rkink);
6051 if (row0<10) continue;
6052 if (row0>150) continue;
6055 Float_t dens00=-1,dens01=-1;
6056 Float_t dens10=-1,dens11=-1;
6058 Int_t found,foundable,ishared;
6059 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6060 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6061 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6062 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6064 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6065 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6066 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6067 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6069 if (dens00<dens10 && dens01<dens11) continue;
6070 if (dens00>dens10 && dens01>dens11) continue;
6071 if (TMath::Max(dens00,dens10)<0.1) continue;
6072 if (TMath::Max(dens01,dens11)<0.3) continue;
6074 if (TMath::Min(dens00,dens10)>0.6) continue;
6075 if (TMath::Min(dens01,dens11)>0.6) continue;
6078 AliTPCseed * ktrack0, *ktrack1;
6087 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6088 AliExternalTrackParam paramm(*ktrack0);
6089 AliExternalTrackParam paramd(*ktrack1);
6090 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6093 kink->SetMother(paramm);
6094 kink->SetDaughter(paramd);
6097 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
6099 fkParam->Transform0to1(x,index);
6100 fkParam->Transform1to2(x,index);
6101 row0 = GetRowNumber(x[0]);
6103 if (kink->GetR()<100) continue;
6104 if (kink->GetR()>240) continue;
6105 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6106 if (kink->GetDistance()>cdist3) continue;
6107 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6108 if (dird<0) continue;
6110 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6111 if (dirm<0) continue;
6112 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6113 if (mpt<0.2) continue;
6116 //for high momenta momentum not defined well in first iteration
6117 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6118 if (qt>0.35) continue;
6121 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6122 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6124 kink->SetTPCDensity(dens00,0,0);
6125 kink->SetTPCDensity(dens01,0,1);
6126 kink->SetTPCDensity(dens10,1,0);
6127 kink->SetTPCDensity(dens11,1,1);
6128 kink->SetIndex(i,0);
6129 kink->SetIndex(j,1);
6132 kink->SetTPCDensity(dens10,0,0);
6133 kink->SetTPCDensity(dens11,0,1);
6134 kink->SetTPCDensity(dens00,1,0);
6135 kink->SetTPCDensity(dens01,1,1);
6136 kink->SetIndex(j,0);
6137 kink->SetIndex(i,1);
6140 if (mpt<1||kink->GetAngle(2)>0.1){
6141 // angle and densities not defined yet
6142 if (kink->GetTPCDensityFactor()<0.8) continue;
6143 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6144 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6145 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6146 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6148 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6149 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6150 criticalangle= 3*TMath::Sqrt(criticalangle);
6151 if (criticalangle>0.02) criticalangle=0.02;
6152 if (kink->GetAngle(2)<criticalangle) continue;
6155 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6156 Float_t shapesum =0;
6158 for ( Int_t row = row0-drow; row<row0+drow;row++){
6159 if (row<0) continue;
6160 if (row>155) continue;
6161 if (ktrack0->GetClusterPointer(row)){
6162 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6163 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6166 if (ktrack1->GetClusterPointer(row)){
6167 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6168 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6173 kink->SetShapeFactor(-1.);
6176 kink->SetShapeFactor(shapesum/sum);
6178 // esd->AddKink(kink);
6180 // kink->SetMother(paramm);
6181 //kink->SetDaughter(paramd);
6183 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6185 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6186 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6188 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6190 if (AliTPCReconstructor::StreamLevel()>1) {
6191 (*fDebugStreamer)<<"kinkLpt"<<
6199 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6203 kinks->AddLast(kink);
6209 // sort the kinks according quality - and refit them towards vertex
6211 Int_t nkinks = kinks->GetEntriesFast();
6212 Float_t *quality = new Float_t[nkinks];
6213 Int_t *indexes = new Int_t[nkinks];
6214 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6215 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6218 for (Int_t i=0;i<nkinks;i++){
6220 AliKink *kinkl = (AliKink*)kinks->At(i);
6222 // refit kinks towards vertex
6224 Int_t index0 = kinkl->GetIndex(0);
6225 Int_t index1 = kinkl->GetIndex(1);
6226 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6227 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6229 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6231 // Refit Kink under if too small angle
6233 if (kinkl->GetAngle(2)<0.05){
6234 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6235 Int_t row0 = kinkl->GetTPCRow0();
6236 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6239 Int_t last = row0-drow;
6240 if (last<40) last=40;
6241 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6242 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6245 Int_t first = row0+drow;
6246 if (first>130) first=130;
6247 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6248 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6250 if (seed0 && seed1){
6251 kinkl->SetStatus(1,8);
6252 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6253 row0 = GetRowNumber(kinkl->GetR());
6254 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6255 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6256 mothers[i]->SetPoolID(fLastSeedID);
6257 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6258 daughters[i]->SetPoolID(fLastSeedID);
6261 delete kinks->RemoveAt(i);
6262 if (seed0) MarkSeedFree( seed0 );
6263 if (seed1) MarkSeedFree( seed1 );
6266 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6267 delete kinks->RemoveAt(i);
6268 if (seed0) MarkSeedFree( seed0 );
6269 if (seed1) MarkSeedFree( seed1 );
6273 MarkSeedFree( seed0 );
6274 MarkSeedFree( seed1 );
6277 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6279 TMath::Sort(nkinks,quality,indexes,kFALSE);
6281 //remove double find kinks
6283 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6284 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6285 if (!kink0) continue;
6287 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6288 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6289 if (!kink0) continue;
6290 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6291 if (!kink1) continue;
6292 // if not close kink continue
6293 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6294 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6295 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6297 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6298 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6299 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6300 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6301 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6310 for (Int_t i=0;i<row0;i++){
6311 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6314 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6321 for (Int_t i=row0;i<158;i++){
6322 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6323 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6326 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6332 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6333 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6334 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6335 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6336 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6337 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6339 shared[kink0->GetIndex(0)]= kTRUE;
6340 shared[kink0->GetIndex(1)]= kTRUE;
6341 delete kinks->RemoveAt(indexes[ikink0]);
6345 shared[kink1->GetIndex(0)]= kTRUE;
6346 shared[kink1->GetIndex(1)]= kTRUE;
6347 delete kinks->RemoveAt(indexes[ikink1]);
6354 for (Int_t i=0;i<nkinks;i++){
6355 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6356 if (!kinkl) continue;
6357 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6358 Int_t index0 = kinkl->GetIndex(0);
6359 Int_t index1 = kinkl->GetIndex(1);
6360 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6361 kinkl->SetMultiple(usage[index0],0);
6362 kinkl->SetMultiple(usage[index1],1);
6363 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6364 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6365 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6366 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6368 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6369 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6370 if (!ktrack0 || !ktrack1) continue;
6371 Int_t index = esd->AddKink(kinkl);
6374 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6375 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6376 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6377 *ktrack0 = *mothers[indexes[i]];
6378 *ktrack1 = *daughters[indexes[i]];
6382 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6383 ktrack1->SetKinkIndex(usage[index1], (index+1));
6388 // Remove tracks corresponding to shared kink's
6390 for (Int_t i=0;i<nentries;i++){
6391 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6392 if (!track0) continue;
6393 if (track0->GetKinkIndex(0)!=0) continue;
6394 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6399 RemoveUsed2(array,0.5,0.4,30);
6401 for (Int_t i=0;i<nentries;i++){
6402 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6403 if (!track0) continue;
6404 track0->CookdEdx(0.02,0.6);
6408 for (Int_t i=0;i<nentries;i++){
6409 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6410 if (!track0) continue;
6411 if (track0->Pt()<1.4) continue;
6412 //remove double high momenta tracks - overlapped with kink candidates
6415 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6416 if (track0->GetClusterPointer(icl)!=0){
6418 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6421 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6422 MarkSeedFree( array->RemoveAt(i) );
6426 if (track0->GetKinkIndex(0)!=0) continue;
6427 if (track0->GetNumberOfClusters()<80) continue;
6429 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6430 pmother->SetPoolID(fLastSeedID);
6431 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6432 pdaughter->SetPoolID(fLastSeedID);
6433 AliKink *pkink = new AliKink;
6435 AliTPCseed & mother = *pmother;
6436 AliTPCseed & daughter = *pdaughter;
6437 AliKink & kinkl = *pkink;
6438 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6439 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6440 MarkSeedFree( pmother );
6441 MarkSeedFree( pdaughter );
6443 continue; //too short tracks
6445 if (mother.Pt()<1.4) {
6446 MarkSeedFree( pmother );
6447 MarkSeedFree( pdaughter );
6451 Int_t row0= kinkl.GetTPCRow0();
6452 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6453 MarkSeedFree( pmother );
6454 MarkSeedFree( pdaughter );
6459 Int_t index = esd->AddKink(&kinkl);
6460 mother.SetKinkIndex(0,-(index+1));
6461 daughter.SetKinkIndex(0,index+1);
6462 if (mother.GetNumberOfClusters()>50) {
6463 MarkSeedFree( array->RemoveAt(i) );
6464 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6465 mtc->SetPoolID(fLastSeedID);
6466 array->AddAt(mtc,i);
6469 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6470 mtc->SetPoolID(fLastSeedID);
6471 array->AddLast(mtc);
6473 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6474 dtc->SetPoolID(fLastSeedID);
6475 array->AddLast(dtc);
6476 for (Int_t icl=0;icl<row0;icl++) {
6477 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6480 for (Int_t icl=row0;icl<158;icl++) {
6481 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6485 MarkSeedFree( pmother );
6486 MarkSeedFree( pdaughter );
6490 delete [] daughters;
6512 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6517 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6520 // refit kink towards to the vertex
6523 AliKink &kink=(AliKink &)knk;
6525 Int_t row0 = GetRowNumber(kink.GetR());
6526 FollowProlongation(mother,0);
6527 mother.Reset(kFALSE);
6529 FollowProlongation(daughter,row0);
6530 daughter.Reset(kFALSE);
6531 FollowBackProlongation(daughter,158);
6532 daughter.Reset(kFALSE);
6533 Int_t first = TMath::Max(row0-20,30);
6534 Int_t last = TMath::Min(row0+20,140);
6536 const Int_t kNdiv =5;
6537 AliTPCseed param0[kNdiv]; // parameters along the track
6538 AliTPCseed param1[kNdiv]; // parameters along the track
6539 AliKink kinks[kNdiv]; // corresponding kink parameters
6542 for (Int_t irow=0; irow<kNdiv;irow++){
6543 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
6545 // store parameters along the track
6547 for (Int_t irow=0;irow<kNdiv;irow++){
6548 FollowBackProlongation(mother, rows[irow]);
6549 FollowProlongation(daughter,rows[kNdiv-1-irow]);
6550 param0[irow] = mother;
6551 param1[kNdiv-1-irow] = daughter;
6555 for (Int_t irow=0; irow<kNdiv-1;irow++){
6556 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
6557 kinks[irow].SetMother(param0[irow]);
6558 kinks[irow].SetDaughter(param1[irow]);
6559 kinks[irow].Update();
6562 // choose kink with best "quality"
6564 Double_t mindist = 10000;
6565 for (Int_t irow=0;irow<kNdiv;irow++){
6566 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
6567 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6568 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
6570 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
6571 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
6572 if (normdist < mindist){
6578 if (index==-1) return 0;
6581 param0[index].Reset(kTRUE);
6582 FollowProlongation(param0[index],0);
6584 mother = param0[index];
6585 daughter = param1[index]; // daughter in vertex
6587 kink.SetMother(mother);
6588 kink.SetDaughter(daughter);
6590 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
6591 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6592 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6593 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
6594 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
6595 mother.SetLabel(kink.GetLabel(0));
6596 daughter.SetLabel(kink.GetLabel(1));
6602 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
6604 // update Kink quality information for mother after back propagation
6606 if (seed->GetKinkIndex(0)>=0) return;
6607 for (Int_t ikink=0;ikink<3;ikink++){
6608 Int_t index = seed->GetKinkIndex(ikink);
6609 if (index>=0) break;
6610 index = TMath::Abs(index)-1;
6611 AliESDkink * kink = fEvent->GetKink(index);
6612 kink->SetTPCDensity(-1,0,0);
6613 kink->SetTPCDensity(1,0,1);
6615 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6616 if (row0<15) row0=15;
6618 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6619 if (row1>145) row1=145;
6621 Int_t found,foundable,shared;
6622 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6623 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
6624 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6625 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
6630 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
6632 // update Kink quality information for daughter after refit
6634 if (seed->GetKinkIndex(0)<=0) return;
6635 for (Int_t ikink=0;ikink<3;ikink++){
6636 Int_t index = seed->GetKinkIndex(ikink);
6637 if (index<=0) break;
6638 index = TMath::Abs(index)-1;
6639 AliESDkink * kink = fEvent->GetKink(index);
6640 kink->SetTPCDensity(-1,1,0);
6641 kink->SetTPCDensity(-1,1,1);
6643 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6644 if (row0<15) row0=15;
6646 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6647 if (row1>145) row1=145;
6649 Int_t found,foundable,shared;
6650 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6651 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
6652 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6653 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
6659 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6662 // check kink point for given track
6663 // if return value=0 kink point not found
6664 // otherwise seed0 correspond to mother particle
6665 // seed1 correspond to daughter particle
6666 // kink parameter of kink point
6667 AliKink &kink=(AliKink &)knk;
6669 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
6670 Int_t first = seed->GetFirstPoint();
6671 Int_t last = seed->GetLastPoint();
6672 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
6675 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
6676 if (!seed1) return 0;
6677 FollowProlongation(*seed1,seed->GetLastPoint()-20);
6678 seed1->Reset(kTRUE);
6679 FollowProlongation(*seed1,158);
6680 seed1->Reset(kTRUE);
6681 last = seed1->GetLastPoint();
6683 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
6684 seed0->SetPoolID(fLastSeedID);
6685 seed0->Reset(kFALSE);
6688 AliTPCseed param0[20]; // parameters along the track
6689 AliTPCseed param1[20]; // parameters along the track
6690 AliKink kinks[20]; // corresponding kink parameters
6692 for (Int_t irow=0; irow<20;irow++){
6693 rows[irow] = first +((last-first)*irow)/19;
6695 // store parameters along the track
6697 for (Int_t irow=0;irow<20;irow++){
6698 FollowBackProlongation(*seed0, rows[irow]);
6699 FollowProlongation(*seed1,rows[19-irow]);
6700 param0[irow] = *seed0;
6701 param1[19-irow] = *seed1;
6705 for (Int_t irow=0; irow<19;irow++){
6706 kinks[irow].SetMother(param0[irow]);
6707 kinks[irow].SetDaughter(param1[irow]);
6708 kinks[irow].Update();
6711 // choose kink with biggest change of angle
6713 Double_t maxchange= 0;
6714 for (Int_t irow=1;irow<19;irow++){
6715 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6716 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
6717 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6718 if ( quality > maxchange){
6719 maxchange = quality;
6724 MarkSeedFree( seed0 );
6725 MarkSeedFree( seed1 );
6726 if (index<0) return 0;
6728 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
6729 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
6730 seed0->SetPoolID(fLastSeedID);
6731 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
6732 seed1->SetPoolID(fLastSeedID);
6733 seed0->Reset(kFALSE);
6734 seed1->Reset(kFALSE);
6735 seed0->ResetCovariance(10.);
6736 seed1->ResetCovariance(10.);
6737 FollowProlongation(*seed0,0);
6738 FollowBackProlongation(*seed1,158);
6739 mother = *seed0; // backup mother at position 0
6740 seed0->Reset(kFALSE);
6741 seed1->Reset(kFALSE);
6742 seed0->ResetCovariance(10.);
6743 seed1->ResetCovariance(10.);
6745 first = TMath::Max(row0-20,0);
6746 last = TMath::Min(row0+20,158);
6748 for (Int_t irow=0; irow<20;irow++){
6749 rows[irow] = first +((last-first)*irow)/19;
6751 // store parameters along the track
6753 for (Int_t irow=0;irow<20;irow++){
6754 FollowBackProlongation(*seed0, rows[irow]);
6755 FollowProlongation(*seed1,rows[19-irow]);
6756 param0[irow] = *seed0;
6757 param1[19-irow] = *seed1;
6761 for (Int_t irow=0; irow<19;irow++){
6762 kinks[irow].SetMother(param0[irow]);
6763 kinks[irow].SetDaughter(param1[irow]);
6764 // param0[irow].Dump();
6765 //param1[irow].Dump();
6766 kinks[irow].Update();
6769 // choose kink with biggest change of angle
6772 for (Int_t irow=0;irow<20;irow++){
6773 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
6774 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
6775 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6776 if ( quality > maxchange){
6777 maxchange = quality;
6784 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
6785 MarkSeedFree( seed0 );
6786 MarkSeedFree( seed1 );
6790 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
6792 kink.SetMother(param0[index]);
6793 kink.SetDaughter(param1[index]);
6796 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
6798 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
6799 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
6801 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
6803 if (AliTPCReconstructor::StreamLevel()>1) {
6804 (*fDebugStreamer)<<"kinkHpt"<<
6807 "p0.="<<¶m0[index]<<
6808 "p1.="<<¶m1[index]<<
6812 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6813 MarkSeedFree( seed0 );
6814 MarkSeedFree( seed1 );
6819 row0 = GetRowNumber(kink.GetR());
6820 kink.SetTPCRow0(row0);
6821 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
6822 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
6823 kink.SetIndex(-10,0);
6824 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
6825 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6826 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6829 // new (&mother) AliTPCseed(param0[index]);
6830 daughter = param1[index];
6831 daughter.SetLabel(kink.GetLabel(1));
6832 param0[index].Reset(kTRUE);
6833 FollowProlongation(param0[index],0);
6834 mother = param0[index];
6835 mother.SetLabel(kink.GetLabel(0));
6836 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
6839 MarkSeedFree( seed0 );
6840 MarkSeedFree( seed1 );
6848 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
6851 // reseed - refit - track
6854 // Int_t last = fSectors->GetNRows()-1;
6856 if (fSectors == fOuterSec){
6857 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
6861 first = t->GetFirstPoint();
6863 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
6864 FollowBackProlongation(*t,fSectors->GetNRows()-1);
6866 FollowProlongation(*t,first);
6876 //_____________________________________________________________________________
6877 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
6878 //-----------------------------------------------------------------
6879 // This function reades track seeds.
6880 //-----------------------------------------------------------------
6881 TDirectory *savedir=gDirectory;
6883 TFile *in=(TFile*)inp;
6884 if (!in->IsOpen()) {
6885 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
6890 TTree *seedTree=(TTree*)in->Get("Seeds");
6892 cerr<<"AliTPCtracker::ReadSeeds(): ";
6893 cerr<<"can't get a tree with track seeds !\n";
6896 AliTPCtrack *seed=new AliTPCtrack;
6897 seedTree->SetBranchAddress("tracks",&seed);
6899 if (fSeeds==0) fSeeds=new TObjArray(15000);
6901 Int_t n=(Int_t)seedTree->GetEntries();
6902 for (Int_t i=0; i<n; i++) {
6903 seedTree->GetEvent(i);
6904 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
6905 sdc->SetPoolID(fLastSeedID);
6906 fSeeds->AddLast(sdc);
6909 delete seed; // RS: this seed is not from the pool, delete it !!!
6915 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
6918 // clusters to tracks
6919 if (fSeeds) DeleteSeeds();
6920 else ResetSeedsPool();
6922 fEventHLT = hltEvent;
6924 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
6925 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
6926 transform->SetCurrentRun(esd->GetRunNumber());
6930 if (!fSeeds) return 1;
6932 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(0,fSeeds);
6937 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
6940 // clusters to tracks
6941 return Clusters2TracksHLT( esd, 0);
6944 //_____________________________________________________________________________
6945 Int_t AliTPCtracker::Clusters2Tracks() {
6946 //-----------------------------------------------------------------
6947 // This is a track finder.
6948 //-----------------------------------------------------------------
6949 TDirectory *savedir=gDirectory;
6953 fSeeds = Tracking();
6956 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6958 //activate again some tracks
6959 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6960 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6962 Int_t nc=t.GetNumberOfClusters();
6964 MarkSeedFree( fSeeds->RemoveAt(i) );
6968 if (pt->GetRemoval()==10) {
6969 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6970 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
6972 pt->Desactivate(20);
6973 MarkSeedFree( fSeeds->RemoveAt(i) );
6978 RemoveUsed2(fSeeds,0.85,0.85,0);
6979 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
6980 //FindCurling(fSeeds, fEvent,0);
6981 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
6982 RemoveUsed2(fSeeds,0.5,0.4,20);
6983 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
6984 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
6987 // // refit short tracks
6989 Int_t nseed=fSeeds->GetEntriesFast();
6992 for (Int_t i=0; i<nseed; i++) {
6993 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6995 Int_t nc=t.GetNumberOfClusters();
6997 MarkSeedFree( fSeeds->RemoveAt(i) );
7000 CookLabel(pt,0.1); //For comparison only
7001 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7002 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7004 if (fDebug>0) cerr<<found<<'\r';
7008 MarkSeedFree( fSeeds->RemoveAt(i) );
7012 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7014 //RemoveUsed(fSeeds,0.9,0.9,6);
7016 nseed=fSeeds->GetEntriesFast();
7018 for (Int_t i=0; i<nseed; i++) {
7019 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7021 Int_t nc=t.GetNumberOfClusters();
7023 MarkSeedFree( fSeeds->RemoveAt(i) );
7027 t.CookdEdx(0.02,0.6);
7028 // CheckKinkPoint(&t,0.05);
7029 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7030 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7038 MarkSeedFree( fSeeds->RemoveAt(i) );
7039 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7041 // FollowProlongation(*seed1,0);
7042 // Int_t n = seed1->GetNumberOfClusters();
7043 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7044 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7047 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7051 SortTracks(fSeeds, 1);
7055 PrepareForBackProlongation(fSeeds,5.);
7056 PropagateBack(fSeeds);
7057 printf("Time for back propagation: \t");timer.Print();timer.Start();
7061 PrepareForProlongation(fSeeds,5.);
7062 PropagateForard2(fSeeds);
7064 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7065 // RemoveUsed(fSeeds,0.7,0.7,6);
7066 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7068 nseed=fSeeds->GetEntriesFast();
7070 for (Int_t i=0; i<nseed; i++) {
7071 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7073 Int_t nc=t.GetNumberOfClusters();
7075 MarkSeedFree( fSeeds->RemoveAt(i) );
7078 t.CookdEdx(0.02,0.6);
7079 // CookLabel(pt,0.1); //For comparison only
7080 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7081 if ((pt->IsActive() || (pt->fRemoval==10) )){
7082 cerr<<found++<<'\r';
7085 MarkSeedFree( fSeeds->RemoveAt(i) );
7090 // fNTracks = found;
7092 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7095 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7096 Info("Clusters2Tracks","Number of found tracks %d",found);
7098 // UnloadClusters();
7103 void AliTPCtracker::Tracking(TObjArray * arr)
7106 // tracking of the seeds
7109 fSectors = fOuterSec;
7110 ParallelTracking(arr,150,63);
7111 fSectors = fOuterSec;
7112 ParallelTracking(arr,63,0);
7115 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7120 static TObjArray arrTracks;
7121 TObjArray * arr = &arrTracks;
7123 fSectors = fOuterSec;
7126 for (Int_t sec=0;sec<fkNOS;sec++){
7127 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7128 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7129 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7132 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7144 TObjArray * AliTPCtracker::Tracking()
7148 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7151 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7153 TObjArray * seeds = new TObjArray;
7155 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7156 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7157 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7165 Float_t fnumber = 3.0;
7166 Float_t fdensity = 3.0;
7169 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7170 arr = MakeSeedsHLT( fEventHLT );
7172 SumTracks(seeds,arr);
7175 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7176 //SignClusters(seeds,fnumber,fdensity);
7183 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7187 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7188 SumTracks(seeds,arr);
7189 SignClusters(seeds,fnumber,fdensity);
7191 for (Int_t i=2;i<6;i+=2){
7192 // seed high pt tracks
7195 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7196 SumTracks(seeds,arr);
7197 SignClusters(seeds,fnumber,fdensity);
7202 // RemoveUsed(seeds,0.9,0.9,1);
7203 // UnsignClusters();
7204 // SignClusters(seeds,fnumber,fdensity);
7208 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7210 // seed high pt tracks
7214 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7215 SumTracks(seeds,arr);
7216 SignClusters(seeds,fnumber,fdensity);
7221 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7222 SumTracks(seeds,arr);
7223 SignClusters(seeds,fnumber,fdensity);
7234 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7238 // RemoveUsed(seeds,0.75,0.75,1);
7240 //SignClusters(seeds,fnumber,fdensity);
7249 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7250 SumTracks(seeds,arr);
7251 SignClusters(seeds,fnumber,fdensity);
7253 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7254 SumTracks(seeds,arr);
7255 SignClusters(seeds,fnumber,fdensity);
7257 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7258 SumTracks(seeds,arr);
7259 SignClusters(seeds,fnumber,fdensity);
7261 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7262 SumTracks(seeds,arr);
7263 SignClusters(seeds,fnumber,fdensity);
7265 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7266 SumTracks(seeds,arr);
7267 SignClusters(seeds,fnumber,fdensity);
7270 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7271 SumTracks(seeds,arr);
7272 SignClusters(seeds,fnumber,fdensity);
7276 for (Int_t delta = 9; delta<30; delta+=gapSec){
7282 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7283 SumTracks(seeds,arr);
7284 SignClusters(seeds,fnumber,fdensity);
7286 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7287 SumTracks(seeds,arr);
7288 SignClusters(seeds,fnumber,fdensity);
7301 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7307 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7308 SumTracks(seeds,arr);
7309 SignClusters(seeds,fnumber,fdensity);
7311 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7312 SumTracks(seeds,arr);
7313 SignClusters(seeds,fnumber,fdensity);
7317 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7328 TObjArray * AliTPCtracker::TrackingSpecial()
7331 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7332 // no primary vertex seeding tried
7336 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7338 TObjArray * seeds = new TObjArray;
7343 Float_t fnumber = 3.0;
7344 Float_t fdensity = 3.0;
7347 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7348 cuts[1] = 3.5; // max tan(phi) angle for seeding
7349 cuts[2] = 3.; // not used (cut on z primary vertex)
7350 cuts[3] = 3.5; // max tan(theta) angle for seeding
7352 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7354 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7355 SumTracks(seeds,arr);
7356 SignClusters(seeds,fnumber,fdensity);
7360 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7371 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7374 //sum tracks to common container
7375 //remove suspicious tracks
7376 // RS: Attention: supplied tracks come in the static array, don't delete them
7377 Int_t nseed = arr2->GetEntriesFast();
7378 for (Int_t i=0;i<nseed;i++){
7379 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7382 // remove tracks with too big curvature
7384 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7385 MarkSeedFree( arr2->RemoveAt(i) );
7388 // REMOVE VERY SHORT TRACKS
7389 if (pt->GetNumberOfClusters()<20){
7390 MarkSeedFree( arr2->RemoveAt(i) );
7393 // NORMAL ACTIVE TRACK
7394 if (pt->IsActive()){
7395 arr1->AddLast(arr2->RemoveAt(i));
7398 //remove not usable tracks
7399 if (pt->GetRemoval()!=10){
7400 MarkSeedFree( arr2->RemoveAt(i) );
7404 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7405 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7406 arr1->AddLast(arr2->RemoveAt(i));
7408 MarkSeedFree( arr2->RemoveAt(i) );
7412 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7417 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7420 // try to track in parralel
7422 Int_t nseed=arr->GetEntriesFast();
7423 //prepare seeds for tracking
7424 for (Int_t i=0; i<nseed; i++) {
7425 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7427 if (!t.IsActive()) continue;
7428 // follow prolongation to the first layer
7429 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7430 FollowProlongation(t, rfirst+1);
7435 for (Int_t nr=rfirst; nr>=rlast; nr--){
7436 if (nr<fInnerSec->GetNRows())
7437 fSectors = fInnerSec;
7439 fSectors = fOuterSec;
7440 // make indexes with the cluster tracks for given
7442 // find nearest cluster
7443 for (Int_t i=0; i<nseed; i++) {
7444 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7446 if (nr==80) pt->UpdateReference();
7447 if (!pt->IsActive()) continue;
7448 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7449 if (pt->GetRelativeSector()>17) {
7452 UpdateClusters(t,nr);
7454 // prolonagate to the nearest cluster - if founded
7455 for (Int_t i=0; i<nseed; i++) {
7456 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7458 if (!pt->IsActive()) continue;
7459 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7460 if (pt->GetRelativeSector()>17) {
7463 FollowToNextCluster(*pt,nr);
7468 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7472 // if we use TPC track itself we have to "update" covariance
7474 Int_t nseed= arr->GetEntriesFast();
7475 for (Int_t i=0;i<nseed;i++){
7476 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7480 //rotate to current local system at first accepted point
7481 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
7482 Int_t sec = (index&0xff000000)>>24;
7484 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
7485 if (angle1>TMath::Pi())
7486 angle1-=2.*TMath::Pi();
7487 Float_t angle2 = pt->GetAlpha();
7489 if (TMath::Abs(angle1-angle2)>0.001){
7490 if (!pt->Rotate(angle1-angle2)) return;
7491 //angle2 = pt->GetAlpha();
7492 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
7493 //if (pt->GetAlpha()<0)
7494 // pt->fRelativeSector+=18;
7495 //sec = pt->fRelativeSector;
7504 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
7508 // if we use TPC track itself we have to "update" covariance
7510 Int_t nseed= arr->GetEntriesFast();
7511 for (Int_t i=0;i<nseed;i++){
7512 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7515 pt->SetFirstPoint(pt->GetLastPoint());
7523 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
7526 // make back propagation
7528 Int_t nseed= arr->GetEntriesFast();
7529 for (Int_t i=0;i<nseed;i++){
7530 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7531 if (pt&& pt->GetKinkIndex(0)<=0) {
7532 //AliTPCseed *pt2 = new AliTPCseed(*pt);
7533 fSectors = fInnerSec;
7534 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
7535 //fSectors = fOuterSec;
7536 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7537 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
7538 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
7539 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
7542 if (pt&& pt->GetKinkIndex(0)>0) {
7543 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
7544 pt->SetFirstPoint(kink->GetTPCRow0());
7545 fSectors = fInnerSec;
7546 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7554 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
7557 // make forward propagation
7559 Int_t nseed= arr->GetEntriesFast();
7561 for (Int_t i=0;i<nseed;i++){
7562 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7564 FollowProlongation(*pt,0,1,1);
7573 Int_t AliTPCtracker::PropagateForward()
7576 // propagate track forward
7578 Int_t nseed = fSeeds->GetEntriesFast();
7579 for (Int_t i=0;i<nseed;i++){
7580 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
7582 AliTPCseed &t = *pt;
7583 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
7584 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
7585 if (alpha < 0. ) alpha += 2.*TMath::Pi();
7586 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
7590 fSectors = fOuterSec;
7591 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
7592 fSectors = fInnerSec;
7593 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
7602 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
7605 // make back propagation, in between row0 and row1
7609 fSectors = fInnerSec;
7612 if (row1<fSectors->GetNRows())
7615 r1 = fSectors->GetNRows()-1;
7617 if (row0<fSectors->GetNRows()&& r1>0 )
7618 FollowBackProlongation(*pt,r1);
7619 if (row1<=fSectors->GetNRows())
7622 r1 = row1 - fSectors->GetNRows();
7623 if (r1<=0) return 0;
7624 if (r1>=fOuterSec->GetNRows()) return 0;
7625 fSectors = fOuterSec;
7626 return FollowBackProlongation(*pt,r1);
7634 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
7636 // gets cluster shape
7638 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
7639 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
7640 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
7641 Double_t angulary = seed->GetSnp();
7643 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
7644 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
7647 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
7648 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
7650 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
7651 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
7652 seed->SetCurrentSigmaY2(sigmay*sigmay);
7653 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
7654 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
7655 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
7656 // Float_t padlength = GetPadPitchLength(row);
7658 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
7659 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
7661 // Float_t sresz = fkParam->GetZSigma();
7662 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
7664 Float_t wy = GetSigmaY(seed);
7665 Float_t wz = GetSigmaZ(seed);
7668 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
7669 printf("problem\n");
7676 //__________________________________________________________________________
7677 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
7678 //--------------------------------------------------------------------
7679 //This function "cooks" a track label. If label<0, this track is fake.
7680 //--------------------------------------------------------------------
7681 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
7683 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
7687 Int_t noc=t->GetNumberOfClusters();
7689 //printf("\nnot founded prolongation\n\n\n");
7695 AliTPCclusterMI *clusters[160];
7697 for (Int_t i=0;i<160;i++) {
7704 for (i=0; i<160 && current<noc; i++) {
7706 Int_t index=t->GetClusterIndex2(i);
7707 if (index<=0) continue;
7708 if (index&0x8000) continue;
7710 //clusters[current]=GetClusterMI(index);
7711 if (t->GetClusterPointer(i)){
7712 clusters[current]=t->GetClusterPointer(i);
7718 Int_t lab=123456789;
7719 for (i=0; i<noc; i++) {
7720 AliTPCclusterMI *c=clusters[i];
7722 lab=TMath::Abs(c->GetLabel(0));
7724 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7730 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7732 for (i=0; i<noc; i++) {
7733 AliTPCclusterMI *c=clusters[i];
7735 if (TMath::Abs(c->GetLabel(1)) == lab ||
7736 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7738 if (noc<=0) { lab=-1; return;}
7739 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7742 Int_t tail=Int_t(0.10*noc);
7745 for (i=1; i<160&&ind<tail; i++) {
7746 // AliTPCclusterMI *c=clusters[noc-i];
7747 AliTPCclusterMI *c=clusters[i];
7749 if (lab == TMath::Abs(c->GetLabel(0)) ||
7750 lab == TMath::Abs(c->GetLabel(1)) ||
7751 lab == TMath::Abs(c->GetLabel(2))) max++;
7754 if (max < Int_t(0.5*tail)) lab=-lab;
7761 //delete[] clusters;
7765 //__________________________________________________________________________
7766 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
7767 //--------------------------------------------------------------------
7768 //This function "cooks" a track label. If label<0, this track is fake.
7769 //--------------------------------------------------------------------
7770 Int_t noc=t->GetNumberOfClusters();
7772 //printf("\nnot founded prolongation\n\n\n");
7778 AliTPCclusterMI *clusters[160];
7780 for (Int_t i=0;i<160;i++) {
7787 for (i=0; i<160 && current<noc; i++) {
7788 if (i<first) continue;
7789 if (i>last) continue;
7790 Int_t index=t->GetClusterIndex2(i);
7791 if (index<=0) continue;
7792 if (index&0x8000) continue;
7794 //clusters[current]=GetClusterMI(index);
7795 if (t->GetClusterPointer(i)){
7796 clusters[current]=t->GetClusterPointer(i);
7801 //if (noc<5) return -1;
7802 Int_t lab=123456789;
7803 for (i=0; i<noc; i++) {
7804 AliTPCclusterMI *c=clusters[i];
7806 lab=TMath::Abs(c->GetLabel(0));
7808 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7814 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7816 for (i=0; i<noc; i++) {
7817 AliTPCclusterMI *c=clusters[i];
7819 if (TMath::Abs(c->GetLabel(1)) == lab ||
7820 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7822 if (noc<=0) { lab=-1; return -1;}
7823 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7826 Int_t tail=Int_t(0.10*noc);
7829 for (i=1; i<160&&ind<tail; i++) {
7830 // AliTPCclusterMI *c=clusters[noc-i];
7831 AliTPCclusterMI *c=clusters[i];
7833 if (lab == TMath::Abs(c->GetLabel(0)) ||
7834 lab == TMath::Abs(c->GetLabel(1)) ||
7835 lab == TMath::Abs(c->GetLabel(2))) max++;
7838 if (max < Int_t(0.5*tail)) lab=-lab;
7841 // t->SetLabel(lab);
7845 //delete[] clusters;
7849 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
7851 //return pad row number for given x vector
7852 Float_t phi = TMath::ATan2(x[1],x[0]);
7853 if(phi<0) phi=2.*TMath::Pi()+phi;
7854 // Get the local angle in the sector philoc
7855 const Float_t kRaddeg = 180/3.14159265358979312;
7856 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
7857 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
7858 return GetRowNumber(localx);
7863 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
7865 //-----------------------------------------------------------------------
7866 // Fill the cluster and sharing bitmaps of the track
7867 //-----------------------------------------------------------------------
7869 Int_t firstpoint = 0;
7870 Int_t lastpoint = 159;
7871 AliTPCTrackerPoint *point;
7872 AliTPCclusterMI *cluster;
7875 TBits clusterMap(159);
7876 TBits sharedMap(159);
7878 for (int iter=firstpoint; iter<lastpoint; iter++) {
7879 // Change to cluster pointers to see if we have a cluster at given padrow
7881 cluster = t->GetClusterPointer(iter);
7883 clusterMap.SetBitNumber(iter, kTRUE);
7884 point = t->GetTrackPoint(iter);
7885 if (point->IsShared())
7886 sharedMap.SetBitNumber(iter,kTRUE);
7888 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
7889 fitMap.SetBitNumber(iter, kTRUE);
7893 esd->SetTPCClusterMap(clusterMap);
7894 esd->SetTPCSharedMap(sharedMap);
7895 esd->SetTPCFitMap(fitMap);
7896 if (nclsf != t->GetNumberOfClusters())
7897 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
7900 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
7902 // return flag if there is findable cluster at given position
7905 Float_t z = track.GetZ();
7907 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
7908 TMath::Abs(z)<fkParam->GetZLength(0) &&
7909 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
7915 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
7917 // Adding systematic error estimate to the covariance matrix
7918 // !!!! the systematic error for element 4 is in 1/GeV
7919 // 03.03.2012 MI changed in respect to the previous versions
7920 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7922 // use only the diagonal part if not specified otherwise
7923 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
7925 Double_t *covarS= (Double_t*)seed->GetCovariance();
7926 Double_t factor[5]={1,1,1,1,1};
7927 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
7928 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
7929 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
7930 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
7931 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
7933 factor[0]=factor[2];
7934 factor[4]=factor[2];
7940 for (Int_t i=0; i<5; i++){
7941 for (Int_t j=i; j<5; j++){
7942 Int_t index=seed->GetIndex(i,j);
7943 covarS[index]*=factor[i]*factor[j];
7949 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
7951 // Adding systematic error - as additive factor without correlation
7953 // !!!! the systematic error for element 4 is in 1/GeV
7954 // 03.03.2012 MI changed in respect to the previous versions
7956 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7957 Double_t *covarIn= (Double_t*)seed->GetCovariance();
7959 for (Int_t i=0;i<15;i++) covar[i]=0;
7965 covar[0] = param[0]*param[0];
7966 covar[2] = param[1]*param[1];
7967 covar[5] = param[2]*param[2];
7968 covar[9] = param[3]*param[3];
7969 covar[14]= param[4]*param[4];
7971 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
7973 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
7974 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
7976 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
7977 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
7978 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
7980 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
7981 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
7982 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
7983 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
7985 seed->AddCovariance(covar);
7988 //_____________________________________________________________________________
7989 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
7992 // check events affected by TPC HV dip
7994 if(!esdEvent) return kFALSE;
7997 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
7998 if(!db) return kFALSE;
7999 db->SetRun(esdEvent->GetRunNumber());
8001 // maximum allowed voltage before an event is identified as a dip event
8002 // and scanning period
8003 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8004 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8005 const Double_t tevSec = esdEvent->GetTimeStamp();
8007 for(Int_t sector=0; sector<72; sector++)
8009 // don't use excluded chambers, since the state is not defined at all
8010 if (!db->GetChamberHVStatus(sector)) continue;
8012 // get hv sensor of the chamber
8013 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8014 if (!sensor) continue;
8015 TGraph *grSensor=sensor->GetGraph();
8016 if (!grSensor) continue;
8017 if (grSensor->GetN()<1) continue;
8020 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8021 if(median < 1.) continue;
8023 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8024 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8025 if (tevSec-dipEventScanPeriod>nextTime) continue;
8026 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8027 if (deltaV>kTPCHVdip) {
8028 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8031 if (nextTime>tevSec+dipEventScanPeriod) break;
8038 //________________________________________
8039 void AliTPCtracker::MarkSeedFree(TObject *sd)
8041 // account that this seed is "deleted"
8042 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8044 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8047 int id = seed->GetPoolID();
8049 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8052 // AliInfo(Form("%d %p",id, seed));
8053 fSeedsPool->RemoveAt(id);
8054 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8055 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8058 //________________________________________
8059 TObject *&AliTPCtracker::NextFreeSeed()
8061 // return next free slot where the seed can be created
8062 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8063 // AliInfo(Form("%d",fLastSeedID));
8064 return (*fSeedsPool)[ fLastSeedID ];
8068 //________________________________________
8069 void AliTPCtracker::ResetSeedsPool()
8071 // mark all seeds in the pool as unused
8072 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8074 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8077 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8080 Double_t x= GetXrow(nrow);
8081 Double_t ymax= GetMaxY(nrow);
8087 if (!t.PropagateTo(x) ){
8088 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8094 Double_t y = t.GetY();
8096 if( rotate!=-1 ) rotate=1;
8097 } else if (y <-ymax) {
8098 if( rotate!=1 ) rotate = -1;
8100 if( rotate==0 ) break;
8101 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8102 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8103 //cout<<"can't rotate "<<endl;
8107 nRotations+= rotate;
8109 if( nRotations!=0 ){
8110 int newSec= t.GetRelativeSector()+nRotations;
8111 if( newSec>=fN ) newSec-=fN;
8112 else if( newSec<0 ) newSec +=fN;
8113 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8114 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8115 t.SetRelativeSector(newSec);
8120 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8123 // try to track in parralel
8125 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8128 Int_t nseed=arr->GetEntriesFast();
8129 //cout<<"Parallel tracking My.."<<endl;
8130 double shapeY2[160], shapeZ2[160];
8131 Int_t clusterIndex[160];
8133 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8134 //if( iSeed!=1 ) continue;
8135 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8139 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8143 for( int iter=0; iter<3; iter++ ){
8146 t.SetLastPoint(0); // first cluster in track position
8147 t.SetFirstPoint(nRows-1);
8148 t.ResetCovariance(.1);
8149 t.SetNumberOfClusters(0);
8150 for( int i=0; i<nRows; i++ ){
8154 t.SetClusterIndex2(i,-1);
8155 t.SetClusterIndex(i,-1);
8158 // pick up the clusters
8160 Double_t roady = 20.;
8161 Double_t roadz = 20.;
8168 t0.SetRelativeSector(t.GetRelativeSector());
8169 t0.SetLastPoint(0); // first cluster in track position
8170 t0.SetFirstPoint(159);
8171 for (Int_t nr=0; nr<nRows; nr++){
8172 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8173 else fSectors=fOuterSec;
8175 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8176 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8177 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8180 if (!IsActive(t0.GetRelativeSector(),nr)) {
8186 shapeY2[nr]=t0.GetCurrentSigmaY2();
8187 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8190 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8191 if( !krow ) continue;
8193 t.SetClusterIndex2(nr,-3); // foundable
8194 t.SetClusterIndex(nr,-3);
8196 AliTPCclusterMI *cl=0;
8198 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8200 double dy = cl->GetY()-t0.GetY();
8201 double dz = cl->GetZ()-t0.GetZ();
8202 double dr = sqrt(dy*dy+dz*dz);
8204 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8207 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8209 t0.SetClusterPointer(nr, cl);
8210 clusterIndex[nr] = krow.GetIndex(uindex);
8211 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8212 t0.SetLastPoint(nr);
8218 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8221 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8225 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8227 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8228 if( !t0.GetClusterPointer(nr) ) continue;
8229 int d = TMath::Abs(nr-midRow);
8237 // first fit 3 base points
8239 //cout<<"Fit3: "<<endl;
8240 for( int icl=0; icl<3; icl++){
8241 int nr = basePoints[icl];
8243 if( nr>=fInnerSec->GetNRows()){
8244 lr = nr - fInnerSec->GetNRows();
8246 } else fSectors=fInnerSec;
8248 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8250 //cout<<"WRONG!!!!"<<endl;
8253 int iSec = cl->GetDetector() %fkNIS;
8254 int rotate = iSec - t.GetRelativeSector();
8256 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8257 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8258 //cout<<"can't rotate "<<endl;
8261 t.SetRelativeSector(iSec);
8263 Double_t x= cl->GetX();
8264 if (!t.PropagateTo(x)){
8265 //cout<<"can't propagate to x="<<x<<endl;
8269 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8270 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8273 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8275 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8276 t.SetCurrentCluster(cl);
8279 t.SetErrorY2(shapeY2[nr]);
8280 t.SetErrorZ2(shapeZ2[nr]);
8283 for( int j=0; j<15; j++ ) cov[j]=0;
8289 t.AliExternalTrackParam::AddCovariance(cov);
8291 if( !UpdateTrack(&t,0) ){
8292 //cout<<"Can not update"<<endl;
8294 t.SetClusterIndex2(nr,-1);
8295 t.SetClusterIndex(nr,-1);
8296 t.SetClusterPointer(nr,0);
8299 //t.SetClusterPointer(nr, cl);
8302 //t.SetLastPoint(t0.GetLastPoint());
8303 //t.SetFirstPoint(t0.GetFirstPoint());
8305 //cout<<"Fit: "<<endl;
8306 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8308 if( nr>=fInnerSec->GetNRows()){
8309 lr = nr - fInnerSec->GetNRows();
8311 } else fSectors=fInnerSec;
8314 if( nr == basePoints[0] ) continue;
8315 if( nr == basePoints[1] ) continue;
8316 if( nr == basePoints[2] ) continue;
8318 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8321 int iSec = cl->GetDetector() %fkNIS;
8322 int rotate = iSec - t.GetRelativeSector();
8324 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8325 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8326 //cout<<"can't rotate "<<endl;
8329 t.SetRelativeSector(iSec);
8331 Double_t x= cl->GetX();
8332 if (!t.PropagateTo(x)){
8333 //cout<<"can't propagate to x="<<x<<endl;
8336 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8337 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8341 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8343 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8344 t.SetCurrentCluster(cl);
8346 t.SetErrorY2(shapeY2[nr]);
8347 t.SetErrorZ2(shapeZ2[nr]);
8349 if( !UpdateTrack(&t,0) ){
8350 //cout<<"Can not update"<<endl;
8352 t.SetClusterIndex2(nr,-1);
8353 t.SetClusterIndex(nr,-1);
8356 //t.SetClusterPointer(nr, cl);
8359 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8362 //cout<<"fitted track"<<iSeed<<endl;
8364 //cout<<"Statistics: "<<endl;
8365 Int_t foundable,found,shared;
8366 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8367 t.SetNFoundable(foundable);
8368 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8374 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8379 if( !hltEvent ) return 0;
8382 Int_t nentr=hltEvent->GetNumberOfTracks();
8384 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8386 TObjArray * seeds = new TObjArray(nentr);
8388 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8391 Int_t nTr=hltEvent->GetNumberOfTracks();
8393 for( int itr=0; itr<nTr; itr++ ){
8394 //if( itr!=97 ) continue;
8395 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8396 if( !param ) continue;
8397 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8398 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8400 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8401 tr.SetNumberOfClusters(0);
8402 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8404 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8405 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8406 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8408 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8409 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8411 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8412 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8414 seed->Rotate(alphaSec - alpha);
8416 seed->SetPoolID(fLastSeedID);
8417 seed->SetIsSeeding(kTRUE);
8418 seed->SetSeed1(nup-1);
8419 seed->SetSeed2(nup-2);
8420 seed->SetSeedType(0);
8421 seed->SetFirstPoint(-1);
8422 seed->SetLastPoint(-1);
8423 seeds->AddLast(seed); // note, track is seed, don't free the seed
8425 //if( index>3 ) break;
8429 fSectors = fOuterSec;
8431 TrackFollowingHLT(seeds );
8433 nTr = seeds->GetEntriesFast();
8434 for( int itr=0; itr<nTr; itr++ ){
8435 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8436 if( !seed ) continue;
8437 //FollowBackProlongation(*seed,0);
8438 // cout<<seed->GetNumberOfClusters()<<endl;
8439 Int_t foundable,found,shared;
8440 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8441 seed->SetNFoundable(foundable);
8442 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8443 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8444 //MarkSeedFree(seeds->RemoveAt(itr));
8447 if (seed->GetNumberOfClusters()<30 ||
8448 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8449 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8450 MarkSeedFree(seeds->RemoveAt(itr));
8454 for( int ir=0; ir<nup; ir++){
8455 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8459 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8463 void AliTPCtracker::FillClusterOccupancyInfo()
8465 //fill the cluster occupancy info into the ESD friend
8466 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8467 if (!esdFriend) return;
8469 for (Int_t isector=0; isector<18; isector++){
8470 AliTPCtrackerSector &iroc = fInnerSec[isector];
8471 AliTPCtrackerSector &oroc = fOuterSec[isector];
8473 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
8474 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
8475 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
8476 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
8477 //clusters used in tracking
8478 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
8479 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
8480 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
8481 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));