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
540 // write tracks to the event
541 // store index of the track
542 Int_t nseed=arr->GetEntriesFast();
543 //FindKinks(arr,fEvent);
544 for (Int_t i=0; i<nseed; i++) {
545 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
549 if (AliTPCReconstructor::StreamLevel()>1) {
550 (*fDebugStreamer)<<"Track0"<<
554 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
555 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
556 pt->PropagateTo(fkParam->GetInnerRadiusLow());
559 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
560 iotrack.~AliESDtrack();
561 new(&iotrack) AliESDtrack;
562 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
563 iotrack.SetTPCPoints(pt->GetPoints());
564 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
565 iotrack.SetV0Indexes(pt->GetV0Indexes());
566 // iotrack.SetTPCpid(pt->fTPCr);
567 //iotrack.SetTPCindex(i);
568 MakeESDBitmaps(pt, &iotrack);
569 fEvent->AddTrack(&iotrack);
573 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
574 iotrack.~AliESDtrack();
575 new(&iotrack) AliESDtrack;
576 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
577 iotrack.SetTPCPoints(pt->GetPoints());
578 //iotrack.SetTPCindex(i);
579 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
580 iotrack.SetV0Indexes(pt->GetV0Indexes());
581 MakeESDBitmaps(pt, &iotrack);
582 // iotrack.SetTPCpid(pt->fTPCr);
583 fEvent->AddTrack(&iotrack);
587 // short tracks - maybe decays
589 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
590 Int_t found,foundable,shared;
591 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
592 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
593 iotrack.~AliESDtrack();
594 new(&iotrack) AliESDtrack;
595 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
596 //iotrack.SetTPCindex(i);
597 iotrack.SetTPCPoints(pt->GetPoints());
598 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
599 iotrack.SetV0Indexes(pt->GetV0Indexes());
600 MakeESDBitmaps(pt, &iotrack);
601 //iotrack.SetTPCpid(pt->fTPCr);
602 fEvent->AddTrack(&iotrack);
607 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
608 Int_t found,foundable,shared;
609 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
610 if (found<20) continue;
611 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
613 iotrack.~AliESDtrack();
614 new(&iotrack) AliESDtrack;
615 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
616 iotrack.SetTPCPoints(pt->GetPoints());
617 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
618 iotrack.SetV0Indexes(pt->GetV0Indexes());
619 MakeESDBitmaps(pt, &iotrack);
620 //iotrack.SetTPCpid(pt->fTPCr);
621 //iotrack.SetTPCindex(i);
622 fEvent->AddTrack(&iotrack);
625 // short tracks - secondaties
627 if ( (pt->GetNumberOfClusters()>30) ) {
628 Int_t found,foundable,shared;
629 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
630 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
631 iotrack.~AliESDtrack();
632 new(&iotrack) AliESDtrack;
633 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
634 iotrack.SetTPCPoints(pt->GetPoints());
635 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
636 iotrack.SetV0Indexes(pt->GetV0Indexes());
637 MakeESDBitmaps(pt, &iotrack);
638 //iotrack.SetTPCpid(pt->fTPCr);
639 //iotrack.SetTPCindex(i);
640 fEvent->AddTrack(&iotrack);
645 if ( (pt->GetNumberOfClusters()>15)) {
646 Int_t found,foundable,shared;
647 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
648 if (found<15) continue;
649 if (foundable<=0) continue;
650 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
651 if (float(found)/float(foundable)<0.8) continue;
653 iotrack.~AliESDtrack();
654 new(&iotrack) AliESDtrack;
655 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
656 iotrack.SetTPCPoints(pt->GetPoints());
657 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
658 iotrack.SetV0Indexes(pt->GetV0Indexes());
659 MakeESDBitmaps(pt, &iotrack);
660 // iotrack.SetTPCpid(pt->fTPCr);
661 //iotrack.SetTPCindex(i);
662 fEvent->AddTrack(&iotrack);
666 // >> account for suppressed tracks in the kink indices (RS)
667 int nESDtracks = fEvent->GetNumberOfTracks();
668 for (int it=nESDtracks;it--;) {
669 AliESDtrack* esdTr = fEvent->GetTrack(it);
670 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
671 for (int ik=0;ik<3;ik++) {
673 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
674 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
676 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
679 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
683 // << account for suppressed tracks in the kink indices (RS)
684 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
692 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
695 // Use calibrated cluster error from OCDB
697 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
699 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
700 Int_t ctype = cl->GetType();
701 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
702 Double_t angle = seed->GetSnp()*seed->GetSnp();
703 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
704 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
706 erry2+=0.5; // edge cluster
710 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
711 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
712 erry2+=addErr*addErr;
713 seed->SetErrorY2(erry2);
717 //calculate look-up table at the beginning
718 // static Bool_t ginit = kFALSE;
719 // static Float_t gnoise1,gnoise2,gnoise3;
720 // static Float_t ggg1[10000];
721 // static Float_t ggg2[10000];
722 // static Float_t ggg3[10000];
723 // static Float_t glandau1[10000];
724 // static Float_t glandau2[10000];
725 // static Float_t glandau3[10000];
727 // static Float_t gcor01[500];
728 // static Float_t gcor02[500];
729 // static Float_t gcorp[500];
733 // if (ginit==kFALSE){
734 // for (Int_t i=1;i<500;i++){
735 // Float_t rsigma = float(i)/100.;
736 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
737 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
738 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
742 // for (Int_t i=3;i<10000;i++){
746 // Float_t amp = float(i);
747 // Float_t padlength =0.75;
748 // gnoise1 = 0.0004/padlength;
749 // Float_t nel = 0.268*amp;
750 // Float_t nprim = 0.155*amp;
751 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
752 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
753 // if (glandau1[i]>1) glandau1[i]=1;
754 // glandau1[i]*=padlength*padlength/12.;
758 // gnoise2 = 0.0004/padlength;
760 // nprim = 0.133*amp;
761 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
762 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
763 // if (glandau2[i]>1) glandau2[i]=1;
764 // glandau2[i]*=padlength*padlength/12.;
769 // gnoise3 = 0.0004/padlength;
771 // nprim = 0.133*amp;
772 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
773 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
774 // if (glandau3[i]>1) glandau3[i]=1;
775 // glandau3[i]*=padlength*padlength/12.;
783 // Int_t amp = int(TMath::Abs(cl->GetQ()));
785 // seed->SetErrorY2(1.);
789 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
790 // Int_t ctype = cl->GetType();
791 // Float_t padlength= GetPadPitchLength(seed->GetRow());
792 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
793 // angle2 = angle2/(1-angle2);
795 // //cluster "quality"
796 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
799 // if (fSectors==fInnerSec){
800 // snoise2 = gnoise1;
801 // res = ggg1[amp]*z+glandau1[amp]*angle2;
802 // if (ctype==0) res *= gcor01[rsigmay];
805 // res*= gcorp[rsigmay];
809 // if (padlength<1.1){
810 // snoise2 = gnoise2;
811 // res = ggg2[amp]*z+glandau2[amp]*angle2;
812 // if (ctype==0) res *= gcor02[rsigmay];
815 // res*= gcorp[rsigmay];
819 // snoise2 = gnoise3;
820 // res = ggg3[amp]*z+glandau3[amp]*angle2;
821 // if (ctype==0) res *= gcor02[rsigmay];
824 // res*= gcorp[rsigmay];
831 // res*=2.4; // overestimate error 2 times
835 // if (res<2*snoise2)
838 // seed->SetErrorY2(res);
846 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
849 // Use calibrated cluster error from OCDB
851 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
853 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
854 Int_t ctype = cl->GetType();
855 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
857 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
858 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
859 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
860 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
862 errz2+=0.5; // edge cluster
866 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
867 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
868 errz2+=addErr*addErr;
869 seed->SetErrorZ2(errz2);
875 // //seed->SetErrorY2(0.1);
877 // //calculate look-up table at the beginning
878 // static Bool_t ginit = kFALSE;
879 // static Float_t gnoise1,gnoise2,gnoise3;
880 // static Float_t ggg1[10000];
881 // static Float_t ggg2[10000];
882 // static Float_t ggg3[10000];
883 // static Float_t glandau1[10000];
884 // static Float_t glandau2[10000];
885 // static Float_t glandau3[10000];
887 // static Float_t gcor01[1000];
888 // static Float_t gcor02[1000];
889 // static Float_t gcorp[1000];
893 // if (ginit==kFALSE){
894 // for (Int_t i=1;i<1000;i++){
895 // Float_t rsigma = float(i)/100.;
896 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
897 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
898 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
902 // for (Int_t i=3;i<10000;i++){
906 // Float_t amp = float(i);
907 // Float_t padlength =0.75;
908 // gnoise1 = 0.0004/padlength;
909 // Float_t nel = 0.268*amp;
910 // Float_t nprim = 0.155*amp;
911 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
912 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
913 // if (glandau1[i]>1) glandau1[i]=1;
914 // glandau1[i]*=padlength*padlength/12.;
918 // gnoise2 = 0.0004/padlength;
920 // nprim = 0.133*amp;
921 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
922 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
923 // if (glandau2[i]>1) glandau2[i]=1;
924 // glandau2[i]*=padlength*padlength/12.;
929 // gnoise3 = 0.0004/padlength;
931 // nprim = 0.133*amp;
932 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
933 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
934 // if (glandau3[i]>1) glandau3[i]=1;
935 // glandau3[i]*=padlength*padlength/12.;
943 // Int_t amp = int(TMath::Abs(cl->GetQ()));
945 // seed->SetErrorY2(1.);
949 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
950 // Int_t ctype = cl->GetType();
951 // Float_t padlength= GetPadPitchLength(seed->GetRow());
953 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
954 // // if (angle2<0.6) angle2 = 0.6;
955 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
957 // //cluster "quality"
958 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
961 // if (fSectors==fInnerSec){
962 // snoise2 = gnoise1;
963 // res = ggg1[amp]*z+glandau1[amp]*angle2;
964 // if (ctype==0) res *= gcor01[rsigmaz];
967 // res*= gcorp[rsigmaz];
971 // if (padlength<1.1){
972 // snoise2 = gnoise2;
973 // res = ggg2[amp]*z+glandau2[amp]*angle2;
974 // if (ctype==0) res *= gcor02[rsigmaz];
977 // res*= gcorp[rsigmaz];
981 // snoise2 = gnoise3;
982 // res = ggg3[amp]*z+glandau3[amp]*angle2;
983 // if (ctype==0) res *= gcor02[rsigmaz];
986 // res*= gcorp[rsigmaz];
995 // if ((ctype<0) &&<70){
1000 // if (res<2*snoise2)
1002 // if (res>3) res =3;
1003 // seed->SetErrorZ2(res);
1011 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1013 //rotate to track "local coordinata
1014 Float_t x = seed->GetX();
1015 Float_t y = seed->GetY();
1016 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1019 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1020 if (!seed->Rotate(fSectors->GetAlpha()))
1022 } else if (y <-ymax) {
1023 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1024 if (!seed->Rotate(-fSectors->GetAlpha()))
1032 //_____________________________________________________________________________
1033 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1034 Double_t x2,Double_t y2,
1035 Double_t x3,Double_t y3) const
1037 //-----------------------------------------------------------------
1038 // Initial approximation of the track curvature
1039 //-----------------------------------------------------------------
1040 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1041 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1042 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1043 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1044 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1046 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1047 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1048 return -xr*yr/sqrt(xr*xr+yr*yr);
1053 //_____________________________________________________________________________
1054 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1055 Double_t x2,Double_t y2,
1056 Double_t x3,Double_t y3) const
1058 //-----------------------------------------------------------------
1059 // Initial approximation of the track curvature
1060 //-----------------------------------------------------------------
1066 Double_t det = x3*y2-x2*y3;
1067 if (TMath::Abs(det)<1e-10){
1071 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1072 Double_t x0 = x3*0.5-y3*u;
1073 Double_t y0 = y3*0.5+x3*u;
1074 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1080 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1081 Double_t x2,Double_t y2,
1082 Double_t x3,Double_t y3) const
1084 //-----------------------------------------------------------------
1085 // Initial approximation of the track curvature
1086 //-----------------------------------------------------------------
1092 Double_t det = x3*y2-x2*y3;
1093 if (TMath::Abs(det)<1e-10) {
1097 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1098 Double_t x0 = x3*0.5-y3*u;
1099 Double_t y0 = y3*0.5+x3*u;
1100 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1109 //_____________________________________________________________________________
1110 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1111 Double_t x2,Double_t y2,
1112 Double_t x3,Double_t y3) const
1114 //-----------------------------------------------------------------
1115 // Initial approximation of the track curvature times center of curvature
1116 //-----------------------------------------------------------------
1117 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1118 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1119 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1120 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1121 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1123 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1125 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1128 //_____________________________________________________________________________
1129 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1130 Double_t x2,Double_t y2,
1131 Double_t z1,Double_t z2) const
1133 //-----------------------------------------------------------------
1134 // Initial approximation of the tangent of the track dip angle
1135 //-----------------------------------------------------------------
1136 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1140 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1141 Double_t x2,Double_t y2,
1142 Double_t z1,Double_t z2, Double_t c) const
1144 //-----------------------------------------------------------------
1145 // Initial approximation of the tangent of the track dip angle
1146 //-----------------------------------------------------------------
1150 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1152 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1153 if (TMath::Abs(d*c*0.5)>1) return 0;
1154 // Double_t angle2 = TMath::ASin(d*c*0.5);
1155 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1156 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1158 angle2 = (z1-z2)*c/(angle2*2.);
1162 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1163 {//-----------------------------------------------------------------
1164 // This function find proloncation of a track to a reference plane x=x2.
1165 //-----------------------------------------------------------------
1169 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1173 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1174 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1178 Double_t dy = dx*(c1+c2)/(r1+r2);
1181 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1183 if (TMath::Abs(delta)>0.01){
1184 dz = x[3]*TMath::ASin(delta)/x[4];
1186 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1189 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1197 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1202 return LoadClusters();
1206 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1209 // load clusters to the memory
1210 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1211 Int_t lower = arr->LowerBound();
1212 Int_t entries = arr->GetEntriesFast();
1214 for (Int_t i=lower; i<entries; i++) {
1215 clrow = (AliTPCClustersRow*) arr->At(i);
1216 if(!clrow) continue;
1217 if(!clrow->GetArray()) continue;
1221 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1223 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1224 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1227 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1228 AliTPCtrackerRow * tpcrow=0;
1231 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1235 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1236 left = (sec-fkNIS*2)/fkNOS;
1239 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1240 for (Int_t j=0;j<tpcrow->GetN1();++j)
1241 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1244 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1245 for (Int_t j=0;j<tpcrow->GetN2();++j)
1246 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1248 clrow->GetArray()->Clear("C");
1257 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1260 // load clusters to the memory from one
1263 AliTPCclusterMI *clust=0;
1264 Int_t count[72][96] = { {0} , {0} };
1266 // loop over clusters
1267 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1268 clust = (AliTPCclusterMI*)arr->At(icl);
1269 if(!clust) continue;
1270 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1272 // transform clusters
1275 // count clusters per pad row
1276 count[clust->GetDetector()][clust->GetRow()]++;
1279 // insert clusters to sectors
1280 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1281 clust = (AliTPCclusterMI*)arr->At(icl);
1282 if(!clust) continue;
1284 Int_t sec = clust->GetDetector();
1285 Int_t row = clust->GetRow();
1287 // filter overlapping pad rows needed by HLT
1288 if(sec<fkNIS*2) { //IROCs
1289 if(row == 30) continue;
1292 if(row == 27 || row == 76) continue;
1297 // left = sec/fkNIS;
1298 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1301 // left = (sec-fkNIS*2)/fkNOS;
1302 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1306 // Load functions must be called behind LoadCluster(TClonesArray*)
1308 //LoadOuterSectors();
1309 //LoadInnerSectors();
1315 Int_t AliTPCtracker::LoadClusters()
1318 // load clusters to the memory
1319 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1321 // TTree * tree = fClustersArray.GetTree();
1322 AliInfo("LoadClusters()\n");
1324 TTree * tree = fInput;
1325 TBranch * br = tree->GetBranch("Segment");
1326 br->SetAddress(&clrow);
1328 // Conversion of pad, row coordinates in local tracking coords.
1329 // Could be skipped here; is already done in clusterfinder
1331 Int_t j=Int_t(tree->GetEntries());
1332 for (Int_t i=0; i<j; i++) {
1336 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1337 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1338 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1341 AliTPCtrackerRow * tpcrow=0;
1344 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1348 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1349 left = (sec-fkNIS*2)/fkNOS;
1352 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1353 for (Int_t k=0;k<tpcrow->GetN1();++k)
1354 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1357 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1358 for (Int_t k=0;k<tpcrow->GetN2();++k)
1359 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1366 if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1371 void AliTPCtracker::UnloadClusters()
1374 // unload clusters from the memory
1376 Int_t nrows = fOuterSec->GetNRows();
1377 for (Int_t sec = 0;sec<fkNOS;sec++)
1378 for (Int_t row = 0;row<nrows;row++){
1379 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1381 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1382 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1384 tpcrow->ResetClusters();
1387 nrows = fInnerSec->GetNRows();
1388 for (Int_t sec = 0;sec<fkNIS;sec++)
1389 for (Int_t row = 0;row<nrows;row++){
1390 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1392 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1393 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1395 tpcrow->ResetClusters();
1401 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1403 // Filling cluster to the array - For visualization purposes
1406 nrows = fOuterSec->GetNRows();
1407 for (Int_t sec = 0;sec<fkNOS;sec++)
1408 for (Int_t row = 0;row<nrows;row++){
1409 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1410 if (!tpcrow) continue;
1411 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1412 array->AddLast((TObject*)((*tpcrow)[icl]));
1415 nrows = fInnerSec->GetNRows();
1416 for (Int_t sec = 0;sec<fkNIS;sec++)
1417 for (Int_t row = 0;row<nrows;row++){
1418 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1419 if (!tpcrow) continue;
1420 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1421 array->AddLast((TObject*)(*tpcrow)[icl]);
1427 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1431 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1432 AliTPCTransform *transform = calibDB->GetTransform() ;
1434 AliFatal("Tranformations not in calibDB");
1437 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1438 Double_t x[3]={cluster->GetRow(),cluster->GetPad(),cluster->GetTimeBin()};
1439 Int_t i[1]={cluster->GetDetector()};
1440 transform->Transform(x,i,0,1);
1441 // if (cluster->GetDetector()%36>17){
1446 // in debug mode check the transformation
1448 if (AliTPCReconstructor::StreamLevel()>2) {
1450 cluster->GetGlobalXYZ(gx);
1451 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1452 TTreeSRedirector &cstream = *fDebugStreamer;
1453 cstream<<"Transform"<<
1464 cluster->SetX(x[0]);
1465 cluster->SetY(x[1]);
1466 cluster->SetZ(x[2]);
1471 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1472 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1473 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1475 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1476 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1477 if (mat) mat->LocalToMaster(pos,posC);
1479 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1481 cluster->SetX(posC[0]);
1482 cluster->SetY(posC[1]);
1483 cluster->SetZ(posC[2]);
1487 void AliTPCtracker::ApplyTailCancellation(){
1489 // Correct the cluster charge for the ion tail effect
1490 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1494 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1495 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1496 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1497 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1498 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1499 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1501 // find the number of clusters for the whole TPC (nclALL)
1503 for (Int_t isector=0; isector<36; isector++){
1504 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1505 nclALL += sector.GetNClInSector(0);
1506 nclALL += sector.GetNClInSector(1);
1509 // start looping over all clusters
1510 for (Int_t iside=0; iside<2; iside++){ // loop over sides
1513 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
1514 // cache experimantal tuning factor for the different chamber type
1515 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
1516 std::cout << " ampfactor = " << ampfactor << std::endl;
1518 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
1521 // Cache time response functions and their positons to COG of the cluster
1522 TGraphErrors ** graphRes = new TGraphErrors *[20];
1523 Float_t * indexAmpGraphs = new Float_t[20];
1524 for (Int_t icache=0; icache<20; icache++)
1526 graphRes[icache] = NULL;
1527 indexAmpGraphs[icache] = 0;
1529 ///////////////////////////// --> position fo sie loop
1530 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
1535 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
1536 Int_t nrows = sector.GetNRows(); // number of rows
1537 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
1539 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1541 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1542 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1543 if (iside>0) ncl=tpcrow.GetN2();
1545 // Order clusters in time for the proper correction of ion tail
1546 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
1547 Float_t qMaxArray[ncl];
1548 Int_t sortedClusterIndex[ncl];
1549 Float_t sortedClusterTimeBin[ncl];
1550 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
1551 for (Int_t i=0;i<ncl;i++)
1555 sortedClusterIndex[i]=i;
1556 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1558 rowClusterArray->AddAt(rowcl,i);
1560 rowClusterArray->RemoveAt(i);
1562 // Fill the timebin info to the array in order to sort wrt tb
1564 sortedClusterTimeBin[i]=0.0;
1566 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
1570 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
1572 // Main cluster correction loops over clusters
1573 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
1575 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
1579 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
1581 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
1583 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
1584 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
1585 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
1587 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
1589 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
1590 Double_t ionTailMax=0.;
1591 Double_t ionTailTotal=0.;
1592 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
1593 ionTailMax=TMath::Abs(ionTailMax);
1594 ionTailTotal=TMath::Abs(ionTailTotal);
1595 qTotArray[icl0]+=ionTailTotal;
1596 qMaxArray[icl0]+=ionTailMax;
1598 // Dump some info for debugging while clusters are being corrected
1599 if (AliTPCReconstructor::StreamLevel()==1) {
1600 TTreeSRedirector &cstream = *fDebugStreamer;
1601 if (gRandom->Rndm() > 0.999){
1602 cstream<<"IonTail"<<
1603 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
1604 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
1605 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
1606 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
1609 }// dump the results to the debug streamer if in debug mode
1611 }//end of second loop over clusters
1613 // Set corrected values of the corrected cluster
1614 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
1615 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
1617 // Dump some info for debugging after clusters are corrected
1618 if (AliTPCReconstructor::StreamLevel()==1) {
1619 TTreeSRedirector &cstream = *fDebugStreamer;
1620 if (gRandom->Rndm() > 0.999){
1621 cstream<<"IonTailCorrected"<<
1622 "cl0.=" << cl0 << // cluster 0 with huge Qmax
1623 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
1624 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
1625 "nclALL=" << nclALL <<
1626 "nclSector=" << nclSector <<
1628 "nclPad=" << nclPad <<
1634 }// dump the results to the debug streamer if in debug mode
1636 }//end of first loop over cluster
1637 delete rowClusterArray;
1638 }//end of loop over rows
1639 for (int i=0; i<20; i++) delete graphRes[i];
1641 delete [] indexAmpGraphs;
1643 }//end of loop over sectors
1644 }//end of loop over IROC/OROC
1645 }// end of side loop
1647 //_____________________________________________________________________________
1648 void AliTPCtracker::GetTailValue(const Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
1651 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
1654 const Double_t kMinPRF = 0.5; // minimal PRF width
1655 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
1656 ionTailMax = 0.; // correction value to be added to Qmax of cl0
1658 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
1659 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
1660 Int_t sectorPad = cl1->GetDetector(); // sector number
1661 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
1662 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
1663 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
1664 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
1665 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
1666 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
1669 Double_t sumAmp1=0.;
1670 for (Int_t idelta =-2; idelta<=2;idelta++){
1671 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
1674 Double_t sumAmp0=0.;
1675 for (Int_t idelta =-2; idelta<=2;idelta++){
1676 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
1679 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
1680 Int_t padScan=2; // +-2 pad-timebin window will be scanned
1681 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
1684 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
1685 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
1686 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
1688 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
1690 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
1691 for (Int_t j=0;j<20;j++) {
1692 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
1694 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
1698 if (!graphRes[ampIndex]) continue;
1699 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
1700 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
1702 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
1705 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
1707 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
1708 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
1709 Float_t qMaxPad0 = amp0*qTot0;
1711 // Add 5 timebin range contribution around the max peak (-+2 tb window)
1712 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
1714 if (itb<0) continue;
1715 if (itb>=graphRes[ampIndex]->GetN()) continue;
1717 // calculate contribution to qTot
1718 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
1719 if (ipad1!=padcl0) {
1720 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
1722 ionTailTotal += tailCorr; // for center pad
1724 // calculate contribution to qMax
1725 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
1727 } // end of tb correction loop which is applied over 5 tb range
1729 } // end of cl0 loop
1730 } // end of cl1 loop
1734 //_____________________________________________________________________________
1735 Int_t AliTPCtracker::LoadOuterSectors() {
1736 //-----------------------------------------------------------------
1737 // This function fills outer TPC sectors with clusters.
1738 //-----------------------------------------------------------------
1739 Int_t nrows = fOuterSec->GetNRows();
1741 for (Int_t sec = 0;sec<fkNOS;sec++)
1742 for (Int_t row = 0;row<nrows;row++){
1743 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1744 Int_t sec2 = sec+2*fkNIS;
1746 Int_t ncl = tpcrow->GetN1();
1748 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1749 index=(((sec2<<8)+row)<<16)+ncl;
1750 tpcrow->InsertCluster(c,index);
1753 ncl = tpcrow->GetN2();
1755 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1756 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1757 tpcrow->InsertCluster(c,index);
1760 // write indexes for fast acces
1762 for (Int_t i=0;i<510;i++)
1763 tpcrow->SetFastCluster(i,-1);
1764 for (Int_t i=0;i<tpcrow->GetN();i++){
1765 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1766 tpcrow->SetFastCluster(zi,i); // write index
1769 for (Int_t i=0;i<510;i++){
1770 if (tpcrow->GetFastCluster(i)<0)
1771 tpcrow->SetFastCluster(i,last);
1773 last = tpcrow->GetFastCluster(i);
1782 //_____________________________________________________________________________
1783 Int_t AliTPCtracker::LoadInnerSectors() {
1784 //-----------------------------------------------------------------
1785 // This function fills inner TPC sectors with clusters.
1786 //-----------------------------------------------------------------
1787 Int_t nrows = fInnerSec->GetNRows();
1789 for (Int_t sec = 0;sec<fkNIS;sec++)
1790 for (Int_t row = 0;row<nrows;row++){
1791 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1794 Int_t ncl = tpcrow->GetN1();
1796 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1797 index=(((sec<<8)+row)<<16)+ncl;
1798 tpcrow->InsertCluster(c,index);
1801 ncl = tpcrow->GetN2();
1803 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1804 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1805 tpcrow->InsertCluster(c,index);
1808 // write indexes for fast acces
1810 for (Int_t i=0;i<510;i++)
1811 tpcrow->SetFastCluster(i,-1);
1812 for (Int_t i=0;i<tpcrow->GetN();i++){
1813 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1814 tpcrow->SetFastCluster(zi,i); // write index
1817 for (Int_t i=0;i<510;i++){
1818 if (tpcrow->GetFastCluster(i)<0)
1819 tpcrow->SetFastCluster(i,last);
1821 last = tpcrow->GetFastCluster(i);
1833 //_________________________________________________________________________
1834 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
1835 //--------------------------------------------------------------------
1836 // Return pointer to a given cluster
1837 //--------------------------------------------------------------------
1838 if (index<0) return 0; // no cluster
1839 Int_t sec=(index&0xff000000)>>24;
1840 Int_t row=(index&0x00ff0000)>>16;
1841 Int_t ncl=(index&0x00007fff)>>00;
1843 const AliTPCtrackerRow * tpcrow=0;
1844 TClonesArray * clrow =0;
1846 if (sec<0 || sec>=fkNIS*4) {
1847 AliWarning(Form("Wrong sector %d",sec));
1852 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
1853 if (tracksec.GetNRows()<=row) return 0;
1854 tpcrow = &(tracksec[row]);
1855 if (tpcrow==0) return 0;
1858 if (tpcrow->GetN1()<=ncl) return 0;
1859 clrow = tpcrow->GetClusters1();
1862 if (tpcrow->GetN2()<=ncl) return 0;
1863 clrow = tpcrow->GetClusters2();
1867 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
1868 if (tracksec.GetNRows()<=row) return 0;
1869 tpcrow = &(tracksec[row]);
1870 if (tpcrow==0) return 0;
1872 if (sec-2*fkNIS<fkNOS) {
1873 if (tpcrow->GetN1()<=ncl) return 0;
1874 clrow = tpcrow->GetClusters1();
1877 if (tpcrow->GetN2()<=ncl) return 0;
1878 clrow = tpcrow->GetClusters2();
1882 return (AliTPCclusterMI*)clrow->At(ncl);
1888 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
1889 //-----------------------------------------------------------------
1890 // This function tries to find a track prolongation to next pad row
1891 //-----------------------------------------------------------------
1893 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
1896 AliTPCclusterMI *cl=0;
1897 Int_t tpcindex= t.GetClusterIndex2(nr);
1899 // update current shape info every 5 pad-row
1900 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1904 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
1906 if (tpcindex==-1) return 0; //track in dead zone
1907 if (tpcindex >= 0){ //
1908 cl = t.GetClusterPointer(nr);
1909 //if (cl==0) cl = GetClusterMI(tpcindex);
1910 if (!cl) cl = GetClusterMI(tpcindex);
1911 t.SetCurrentClusterIndex1(tpcindex);
1914 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
1915 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1917 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1918 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1920 if (TMath::Abs(angle-t.GetAlpha())>0.001){
1921 Double_t rotation = angle-t.GetAlpha();
1922 t.SetRelativeSector(relativesector);
1923 if (!t.Rotate(rotation)) {
1924 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1928 if (!t.PropagateTo(x)) {
1929 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1933 t.SetCurrentCluster(cl);
1935 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1936 if ((tpcindex&0x8000)==0) accept =0;
1938 //if founded cluster is acceptible
1939 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
1940 t.SetErrorY2(t.GetErrorY2()+0.03);
1941 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1942 t.SetErrorY2(t.GetErrorY2()*3);
1943 t.SetErrorZ2(t.GetErrorZ2()*3);
1945 t.SetNFoundable(t.GetNFoundable()+1);
1946 UpdateTrack(&t,accept);
1949 else { // Remove old cluster from track
1950 t.SetClusterIndex(nr, -3);
1951 t.SetClusterPointer(nr, 0);
1955 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
1956 if (fIteration>1 && IsFindable(t)){
1957 // not look for new cluster during refitting
1958 t.SetNFoundable(t.GetNFoundable()+1);
1963 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1964 if (!t.PropagateTo(x)) {
1965 if (fIteration==0) t.SetRemoval(10);
1968 Double_t y = t.GetY();
1969 if (TMath::Abs(y)>ymax){
1971 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1972 if (!t.Rotate(fSectors->GetAlpha()))
1974 } else if (y <-ymax) {
1975 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1976 if (!t.Rotate(-fSectors->GetAlpha()))
1979 if (!t.PropagateTo(x)) {
1980 if (fIteration==0) t.SetRemoval(10);
1986 Double_t z=t.GetZ();
1989 if (!IsActive(t.GetRelativeSector(),nr)) {
1991 t.SetClusterIndex2(nr,-1);
1994 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1995 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
1996 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
1998 if (!isActive || !isActive2) return 0;
2000 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2001 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
2003 Double_t roadz = 1.;
2005 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2007 t.SetClusterIndex2(nr,-1);
2013 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2014 t.SetNFoundable(t.GetNFoundable()+1);
2020 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2021 cl = krow.FindNearest2(y,z,roady,roadz,index);
2022 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2025 t.SetCurrentCluster(cl);
2027 if (fIteration==2&&cl->IsUsed(10)) return 0;
2028 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2029 if (fIteration==2&&cl->IsUsed(11)) {
2030 t.SetErrorY2(t.GetErrorY2()+0.03);
2031 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2032 t.SetErrorY2(t.GetErrorY2()*3);
2033 t.SetErrorZ2(t.GetErrorZ2()*3);
2036 if (t.fCurrentCluster->IsUsed(10)){
2041 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2047 if (accept<3) UpdateTrack(&t,accept);
2050 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2058 //_________________________________________________________________________
2059 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2061 // Get track space point by index
2062 // return false in case the cluster doesn't exist
2063 AliTPCclusterMI *cl = GetClusterMI(index);
2064 if (!cl) return kFALSE;
2065 Int_t sector = (index&0xff000000)>>24;
2066 // Int_t row = (index&0x00ff0000)>>16;
2068 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2069 xyz[0] = cl->GetX();
2070 xyz[1] = cl->GetY();
2071 xyz[2] = cl->GetZ();
2073 fkParam->AdjustCosSin(sector,cos,sin);
2074 Float_t x = cos*xyz[0]-sin*xyz[1];
2075 Float_t y = cos*xyz[1]+sin*xyz[0];
2077 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2078 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2079 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2080 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2081 cov[0] = sin*sin*sigmaY2;
2082 cov[1] = -sin*cos*sigmaY2;
2084 cov[3] = cos*cos*sigmaY2;
2087 p.SetXYZ(x,y,xyz[2],cov);
2088 AliGeomManager::ELayerID iLayer;
2090 if (sector < fkParam->GetNInnerSector()) {
2091 iLayer = AliGeomManager::kTPC1;
2095 iLayer = AliGeomManager::kTPC2;
2096 idet = sector - fkParam->GetNInnerSector();
2098 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2099 p.SetVolumeID(volid);
2105 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2106 //-----------------------------------------------------------------
2107 // This function tries to find a track prolongation to next pad row
2108 //-----------------------------------------------------------------
2109 t.SetCurrentCluster(0);
2110 t.SetCurrentClusterIndex1(-3);
2112 Double_t xt=t.GetX();
2113 Int_t row = GetRowNumber(xt)-1;
2114 Double_t ymax= GetMaxY(nr);
2116 if (row < nr) return 1; // don't prolongate if not information until now -
2117 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2119 // return 0; // not prolongate strongly inclined tracks
2121 // if (TMath::Abs(t.GetSnp())>0.95) {
2123 // return 0; // not prolongate strongly inclined tracks
2124 // }// patch 28 fev 06
2126 Double_t x= GetXrow(nr);
2128 //t.PropagateTo(x+0.02);
2129 //t.PropagateTo(x+0.01);
2130 if (!t.PropagateTo(x)){
2137 if (TMath::Abs(y)>ymax){
2139 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2140 if (!t.Rotate(fSectors->GetAlpha()))
2142 } else if (y <-ymax) {
2143 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2144 if (!t.Rotate(-fSectors->GetAlpha()))
2147 // if (!t.PropagateTo(x)){
2154 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2156 if (!IsActive(t.GetRelativeSector(),nr)) {
2158 t.SetClusterIndex2(nr,-1);
2161 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2163 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2165 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2167 t.SetClusterIndex2(nr,-1);
2173 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2174 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2180 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2181 // t.fCurrentSigmaY = GetSigmaY(&t);
2182 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2186 AliTPCclusterMI *cl=0;
2189 Double_t roady = 1.;
2190 Double_t roadz = 1.;
2194 index = t.GetClusterIndex2(nr);
2195 if ( (index >= 0) && (index&0x8000)==0){
2196 cl = t.GetClusterPointer(nr);
2197 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2198 t.SetCurrentClusterIndex1(index);
2200 t.SetCurrentCluster(cl);
2206 // if (index<0) return 0;
2207 UInt_t uindex = TMath::Abs(index);
2210 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2211 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2214 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2215 t.SetCurrentCluster(cl);
2221 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2222 //-----------------------------------------------------------------
2223 // This function tries to find a track prolongation to next pad row
2224 //-----------------------------------------------------------------
2226 //update error according neighborhoud
2228 if (t.GetCurrentCluster()) {
2230 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2232 if (t.GetCurrentCluster()->IsUsed(10)){
2237 t.SetNShared(t.GetNShared()+1);
2238 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2243 if (fIteration>0) accept = 0;
2244 if (accept<3) UpdateTrack(&t,accept);
2248 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2249 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2251 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2259 //_____________________________________________________________________________
2260 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2261 //-----------------------------------------------------------------
2262 // This function tries to find a track prolongation.
2263 //-----------------------------------------------------------------
2264 Double_t xt=t.GetX();
2266 Double_t alpha=t.GetAlpha();
2267 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2268 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2270 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2272 Int_t first = GetRowNumber(xt);
2277 for (Int_t nr= first; nr>=rf; nr-=step) {
2279 if (t.GetKinkIndexes()[0]>0){
2280 for (Int_t i=0;i<3;i++){
2281 Int_t index = t.GetKinkIndexes()[i];
2282 if (index==0) break;
2283 if (index<0) continue;
2285 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2287 printf("PROBLEM\n");
2290 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2292 AliExternalTrackParam paramd(t);
2293 kink->SetDaughter(paramd);
2294 kink->SetStatus(2,5);
2301 if (nr==80) t.UpdateReference();
2302 if (nr<fInnerSec->GetNRows())
2303 fSectors = fInnerSec;
2305 fSectors = fOuterSec;
2306 if (FollowToNext(t,nr)==0)
2319 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2320 //-----------------------------------------------------------------
2321 // This function tries to find a track prolongation.
2322 //-----------------------------------------------------------------
2324 Double_t xt=t.GetX();
2325 Double_t alpha=t.GetAlpha();
2326 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2327 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2328 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2330 Int_t first = t.GetFirstPoint();
2331 Int_t ri = GetRowNumber(xt);
2335 if (first<ri) first = ri;
2337 if (first<0) first=0;
2338 for (Int_t nr=first; nr<=rf; nr++) {
2339 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2340 if (t.GetKinkIndexes()[0]<0){
2341 for (Int_t i=0;i<3;i++){
2342 Int_t index = t.GetKinkIndexes()[i];
2343 if (index==0) break;
2344 if (index>0) continue;
2345 index = TMath::Abs(index);
2346 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2348 printf("PROBLEM\n");
2351 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2353 AliExternalTrackParam paramm(t);
2354 kink->SetMother(paramm);
2355 kink->SetStatus(2,1);
2362 if (nr<fInnerSec->GetNRows())
2363 fSectors = fInnerSec;
2365 fSectors = fOuterSec;
2376 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2378 // overlapping factor
2384 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2387 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2389 Float_t distance = TMath::Sqrt(dz2+dy2);
2390 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2393 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2394 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2399 if (firstpoint>lastpoint) {
2400 firstpoint =lastpoint;
2405 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2406 if (s1->GetClusterIndex2(i)>0) sum1++;
2407 if (s2->GetClusterIndex2(i)>0) sum2++;
2408 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2412 if (sum<5) return 0;
2414 Float_t summin = TMath::Min(sum1+1,sum2+1);
2415 Float_t ratio = (sum+1)/Float_t(summin);
2419 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2423 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2424 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2425 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2426 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2431 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2432 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2433 Int_t firstpoint = 0;
2434 Int_t lastpoint = 160;
2436 // if (firstpoint>=lastpoint-5) return;;
2438 for (Int_t i=firstpoint;i<lastpoint;i++){
2439 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2440 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2444 if (sumshared>cutN0){
2447 for (Int_t i=firstpoint;i<lastpoint;i++){
2448 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2449 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2450 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2451 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2452 if (s1->IsActive()&&s2->IsActive()){
2453 p1->SetShared(kTRUE);
2454 p2->SetShared(kTRUE);
2460 if (sumshared>cutN0){
2461 for (Int_t i=0;i<4;i++){
2462 if (s1->GetOverlapLabel(3*i)==0){
2463 s1->SetOverlapLabel(3*i, s2->GetLabel());
2464 s1->SetOverlapLabel(3*i+1,sumshared);
2465 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2469 for (Int_t i=0;i<4;i++){
2470 if (s2->GetOverlapLabel(3*i)==0){
2471 s2->SetOverlapLabel(3*i, s1->GetLabel());
2472 s2->SetOverlapLabel(3*i+1,sumshared);
2473 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2480 void AliTPCtracker::SignShared(TObjArray * arr)
2483 //sort trackss according sectors
2485 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2486 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2488 //if (pt) RotateToLocal(pt);
2492 arr->Sort(); // sorting according relative sectors
2493 arr->Expand(arr->GetEntries());
2496 Int_t nseed=arr->GetEntriesFast();
2497 for (Int_t i=0; i<nseed; i++) {
2498 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2500 for (Int_t j=0;j<12;j++){
2501 pt->SetOverlapLabel(j,0);
2504 for (Int_t i=0; i<nseed; i++) {
2505 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2507 if (pt->GetRemoval()>10) continue;
2508 for (Int_t j=i+1; j<nseed; j++){
2509 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2510 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2512 if (pt2->GetRemoval()<=10) {
2513 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2521 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
2524 //sort tracks in array according mode criteria
2525 Int_t nseed = arr->GetEntriesFast();
2526 for (Int_t i=0; i<nseed; i++) {
2527 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2538 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
2541 // Loop over all tracks and remove overlaped tracks (with lower quality)
2543 // 1. Unsign clusters
2544 // 2. Sort tracks according quality
2545 // Quality is defined by the number of cluster between first and last points
2547 // 3. Loop over tracks - decreasing quality order
2548 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
2549 // b.) remove - If the minimal number of clusters less than minimal and not ITS
2550 // c.) if track accepted - sign clusters
2552 //Called in - AliTPCtracker::Clusters2Tracks()
2553 // - AliTPCtracker::PropagateBack()
2554 // - AliTPCtracker::RefitInward()
2557 // factor1 - factor for constrained
2558 // factor2 - for non constrained tracks
2559 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
2563 Int_t nseed = arr->GetEntriesFast();
2564 Float_t * quality = new Float_t[nseed];
2565 Int_t * indexes = new Int_t[nseed];
2569 for (Int_t i=0; i<nseed; i++) {
2570 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2575 pt->UpdatePoints(); //select first last max dens points
2576 Float_t * points = pt->GetPoints();
2577 if (points[3]<0.8) quality[i] =-1;
2578 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2579 //prefer high momenta tracks if overlaps
2580 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
2582 TMath::Sort(nseed,quality,indexes);
2585 for (Int_t itrack=0; itrack<nseed; itrack++) {
2586 Int_t trackindex = indexes[itrack];
2587 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
2590 if (quality[trackindex]<0){
2591 MarkSeedFree( arr->RemoveAt(trackindex) );
2596 Int_t first = Int_t(pt->GetPoints()[0]);
2597 Int_t last = Int_t(pt->GetPoints()[2]);
2598 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2600 Int_t found,foundable,shared;
2601 pt->GetClusterStatistic(first,last, found, foundable,shared,kFALSE); // better to get statistic in "high-dens" region do't use full track as in line bellow
2602 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2603 Bool_t itsgold =kFALSE;
2606 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2610 if (Float_t(shared+1)/Float_t(found+1)>factor){
2611 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2612 if( AliTPCReconstructor::StreamLevel()>3){
2613 TTreeSRedirector &cstream = *fDebugStreamer;
2614 cstream<<"RemoveUsed"<<
2615 "iter="<<fIteration<<
2619 MarkSeedFree( arr->RemoveAt(trackindex) );
2622 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
2623 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2624 if( AliTPCReconstructor::StreamLevel()>3){
2625 TTreeSRedirector &cstream = *fDebugStreamer;
2626 cstream<<"RemoveShort"<<
2627 "iter="<<fIteration<<
2631 MarkSeedFree( arr->RemoveAt(trackindex) );
2637 //if (sharedfactor>0.4) continue;
2638 if (pt->GetKinkIndexes()[0]>0) continue;
2639 //Remove tracks with undefined properties - seems
2640 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
2642 for (Int_t i=first; i<last; i++) {
2643 Int_t index=pt->GetClusterIndex2(i);
2644 // if (index<0 || index&0x8000 ) continue;
2645 if (index<0 || index&0x8000 ) continue;
2646 AliTPCclusterMI *c= pt->GetClusterPointer(i);
2653 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2659 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
2662 // Dump clusters after reco
2663 // signed and unsigned cluster can be visualized
2664 // 1. Unsign all cluster
2665 // 2. Sign all used clusters
2668 Int_t nseed = trackArray->GetEntries();
2669 for (Int_t i=0; i<nseed; i++){
2670 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
2674 Bool_t isKink=pt->GetKinkIndex(0)!=0;
2675 for (Int_t j=0; j<160; ++j) {
2676 Int_t index=pt->GetClusterIndex2(j);
2677 if (index<0) continue;
2678 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2680 if (isKink) c->Use(100); // kink
2681 c->Use(10); // by default usage 10
2686 for (Int_t sec=0;sec<fkNIS;sec++){
2687 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2688 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2689 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
2690 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2691 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2692 (*fDebugStreamer)<<"clDump"<<
2700 cla = fInnerSec[sec][row].GetClusters2();
2701 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
2702 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2703 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2704 (*fDebugStreamer)<<"clDump"<<
2715 for (Int_t sec=0;sec<fkNOS;sec++){
2716 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2717 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2718 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
2720 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2721 cl->GetGlobalXYZ(gx);
2722 (*fDebugStreamer)<<"clDump"<<
2730 cla = fOuterSec[sec][row].GetClusters2();
2731 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
2733 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2734 cl->GetGlobalXYZ(gx);
2735 (*fDebugStreamer)<<"clDump"<<
2747 void AliTPCtracker::UnsignClusters()
2750 // loop over all clusters and unsign them
2753 for (Int_t sec=0;sec<fkNIS;sec++){
2754 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2755 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2756 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2757 // if (cl[icl].IsUsed(10))
2758 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2759 cla = fInnerSec[sec][row].GetClusters2();
2760 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2761 //if (cl[icl].IsUsed(10))
2762 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2766 for (Int_t sec=0;sec<fkNOS;sec++){
2767 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2768 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2769 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2770 //if (cl[icl].IsUsed(10))
2771 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2772 cla = fOuterSec[sec][row].GetClusters2();
2773 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2774 //if (cl[icl].IsUsed(10))
2775 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2783 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
2786 //sign clusters to be "used"
2788 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2789 // loop over "primaries"
2803 Int_t nseed = arr->GetEntriesFast();
2804 for (Int_t i=0; i<nseed; i++) {
2805 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2809 if (!(pt->IsActive())) continue;
2810 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2811 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2813 sumdens2+= dens*dens;
2814 sumn += pt->GetNumberOfClusters();
2815 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2816 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2819 sumchi2 +=chi2*chi2;
2824 Float_t mdensity = 0.9;
2825 Float_t meann = 130;
2826 Float_t meanchi = 1;
2827 Float_t sdensity = 0.1;
2828 Float_t smeann = 10;
2829 Float_t smeanchi =0.4;
2833 mdensity = sumdens/sum;
2835 meanchi = sumchi/sum;
2837 sdensity = sumdens2/sum-mdensity*mdensity;
2839 sdensity = TMath::Sqrt(sdensity);
2843 smeann = sumn2/sum-meann*meann;
2845 smeann = TMath::Sqrt(smeann);
2849 smeanchi = sumchi2/sum - meanchi*meanchi;
2851 smeanchi = TMath::Sqrt(smeanchi);
2857 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
2859 for (Int_t i=0; i<nseed; i++) {
2860 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2864 if (pt->GetBSigned()) continue;
2865 if (pt->GetBConstrain()) continue;
2866 //if (!(pt->IsActive())) continue;
2868 Int_t found,foundable,shared;
2869 pt->GetClusterStatistic(0,160,found, foundable,shared);
2870 if (shared/float(found)>0.3) {
2871 if (shared/float(found)>0.9 ){
2872 //MarkSeedFree( arr->RemoveAt(i) );
2877 Bool_t isok =kFALSE;
2878 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2880 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2882 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2884 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2888 for (Int_t j=0; j<160; ++j) {
2889 Int_t index=pt->GetClusterIndex2(j);
2890 if (index<0) continue;
2891 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2893 //if (!(c->IsUsed(10))) c->Use();
2900 Double_t maxchi = meanchi+2.*smeanchi;
2902 for (Int_t i=0; i<nseed; i++) {
2903 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2907 //if (!(pt->IsActive())) continue;
2908 if (pt->GetBSigned()) continue;
2909 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
2910 if (chi>maxchi) continue;
2913 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2915 //sign only tracks with enoug big density at the beginning
2917 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
2920 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2921 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2923 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2924 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2927 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2928 //Int_t noc=pt->GetNumberOfClusters();
2929 pt->SetBSigned(kTRUE);
2930 for (Int_t j=0; j<160; ++j) {
2932 Int_t index=pt->GetClusterIndex2(j);
2933 if (index<0) continue;
2934 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2936 // if (!(c->IsUsed(10))) c->Use();
2941 // gLastCheck = nseed;
2950 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
2953 // back propagation of ESD tracks
2956 if (!event) return 0;
2957 const Int_t kMaxFriendTracks=2000;
2960 // extract correction object for multiplicity dependence of dEdx
2961 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
2963 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
2965 AliFatal("Tranformations not in RefitInward");
2968 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
2969 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
2970 Int_t nContribut = event->GetNumberOfTracks();
2971 TGraphErrors * graphMultDependenceDeDx = 0x0;
2972 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
2973 if (recoParam->GetUseTotCharge()) {
2974 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2976 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2982 //PrepareForProlongation(fSeeds,1);
2983 PropagateForward2(fSeeds);
2984 RemoveUsed2(fSeeds,0.4,0.4,20);
2986 TObjArray arraySeed(fSeeds->GetEntries());
2987 for (Int_t i=0;i<fSeeds->GetEntries();i++) {
2988 arraySeed.AddAt(fSeeds->At(i),i);
2990 SignShared(&arraySeed);
2991 // FindCurling(fSeeds, event,2); // find multi found tracks
2992 FindSplitted(fSeeds, event,2); // find multi found tracks
2993 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,2); // find multi found tracks
2996 Int_t nseed = fSeeds->GetEntriesFast();
2997 for (Int_t i=0;i<nseed;i++){
2998 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2999 if (!seed) continue;
3000 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
3001 AliESDtrack *esd=event->GetTrack(i);
3003 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3004 AliExternalTrackParam paramIn;
3005 AliExternalTrackParam paramOut;
3006 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3007 if (AliTPCReconstructor::StreamLevel()>2) {
3008 (*fDebugStreamer)<<"RecoverIn"<<
3012 "pout.="<<¶mOut<<
3017 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3018 seed->SetNumberOfClusters(ncl);
3022 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3023 seed->UpdatePoints();
3024 AddCovariance(seed);
3025 MakeESDBitmaps(seed, esd);
3026 seed->CookdEdx(0.02,0.6);
3027 CookLabel(seed,0.1); //For comparison only
3029 if (AliTPCReconstructor::StreamLevel()>1 && seed!=0) {
3030 TTreeSRedirector &cstream = *fDebugStreamer;
3037 if (seed->GetNumberOfClusters()>15){
3038 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3039 esd->SetTPCPoints(seed->GetPoints());
3040 esd->SetTPCPointsF(seed->GetNFoundable());
3041 Int_t ndedx = seed->GetNCDEDX(0);
3042 Float_t sdedx = seed->GetSDEDX(0);
3043 Float_t dedx = seed->GetdEdx();
3044 // apply mutliplicity dependent dEdx correction if available
3045 if (graphMultDependenceDeDx) {
3046 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3047 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3049 esd->SetTPCsignal(dedx, sdedx, ndedx);
3051 // fill new dEdx information
3053 Double32_t signal[4];
3054 Double32_t signalMax[4];
3058 for(Int_t iarr=0;iarr<3;iarr++) {
3059 signal[iarr] = seed->GetDEDXregion(iarr+1);
3060 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3061 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3062 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3064 signal[3] = seed->GetDEDXregion(4);
3065 signalMax[3] = seed->GetDEDXregion(8);
3068 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3069 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3070 infoTpcPid->SetTPCSignalsQmax(signalMax);
3071 esd->SetTPCdEdxInfo(infoTpcPid);
3073 // add seed to the esd track in Calib level
3075 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3076 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3077 // RS: this is the only place where the seed is created not in the pool,
3078 // since it should belong to ESDevent
3079 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3080 esd->AddCalibObject(seedCopy);
3085 //printf("problem\n");
3088 //FindKinks(fSeeds,event);
3089 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(2,fSeeds);
3090 Info("RefitInward","Number of refitted tracks %d",ntracks);
3092 AliCosmicTracker::FindCosmic(event, kTRUE);
3094 FillClusterOccupancyInfo();
3100 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3103 // back propagation of ESD tracks
3105 if (!event) return 0;
3110 PropagateBack(fSeeds);
3111 RemoveUsed2(fSeeds,0.4,0.4,20);
3112 //FindCurling(fSeeds, fEvent,1);
3113 FindSplitted(fSeeds, event,1); // find multi found tracks
3114 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3117 Int_t nseed = fSeeds->GetEntriesFast();
3119 for (Int_t i=0;i<nseed;i++){
3120 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3121 if (!seed) continue;
3122 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3123 seed->UpdatePoints();
3124 AddCovariance(seed);
3125 AliESDtrack *esd=event->GetTrack(i);
3126 if (!esd) continue; //never happen
3127 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3128 AliExternalTrackParam paramIn;
3129 AliExternalTrackParam paramOut;
3130 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3131 if (AliTPCReconstructor::StreamLevel()>2) {
3132 (*fDebugStreamer)<<"RecoverBack"<<
3136 "pout.="<<¶mOut<<
3141 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3142 seed->SetNumberOfClusters(ncl);
3145 seed->CookdEdx(0.02,0.6);
3146 CookLabel(seed,0.1); //For comparison only
3147 if (seed->GetNumberOfClusters()>15){
3148 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3149 esd->SetTPCPoints(seed->GetPoints());
3150 esd->SetTPCPointsF(seed->GetNFoundable());
3151 Int_t ndedx = seed->GetNCDEDX(0);
3152 Float_t sdedx = seed->GetSDEDX(0);
3153 Float_t dedx = seed->GetdEdx();
3154 esd->SetTPCsignal(dedx, sdedx, ndedx);
3156 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3157 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3158 if (AliTPCReconstructor::StreamLevel()>1 && esd) {
3159 (*fDebugStreamer)<<"Cback"<<
3162 "EventNrInFile="<<eventnumber<<
3167 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(1,fSeeds);
3168 //FindKinks(fSeeds,event);
3169 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3177 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3180 // Post process events
3182 if (!event) return 0;
3185 // Set TPC event status
3188 // event affected by HV dip
3190 if(IsTPCHVDipEvent(event)) {
3191 event->ResetDetectorStatus(AliDAQ::kTPC);
3194 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3200 void AliTPCtracker::DeleteSeeds()
3209 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3212 //read seeds from the event
3214 Int_t nentr=event->GetNumberOfTracks();
3216 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3221 fSeeds = new TObjArray(nentr);
3225 for (Int_t i=0; i<nentr; i++) {
3226 AliESDtrack *esd=event->GetTrack(i);
3227 ULong_t status=esd->GetStatus();
3228 if (!(status&AliESDtrack::kTPCin)) continue;
3229 AliTPCtrack t(*esd);
3230 t.SetNumberOfClusters(0);
3231 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3232 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3233 seed->SetPoolID(fLastSeedID);
3234 seed->SetUniqueID(esd->GetID());
3235 AddCovariance(seed); //add systematic ucertainty
3236 for (Int_t ikink=0;ikink<3;ikink++) {
3237 Int_t index = esd->GetKinkIndex(ikink);
3238 seed->GetKinkIndexes()[ikink] = index;
3239 if (index==0) continue;
3240 index = TMath::Abs(index);
3241 AliESDkink * kink = fEvent->GetKink(index-1);
3242 if (kink&&esd->GetKinkIndex(ikink)<0){
3243 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3244 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3246 if (kink&&esd->GetKinkIndex(ikink)>0){
3247 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3248 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3252 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3253 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3254 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3255 // fSeeds->AddAt(0,i);
3256 // MarkSeedFree( seed );
3262 // rotate to the local coordinate system
3264 fSectors=fInnerSec; fN=fkNIS;
3265 Double_t alpha=seed->GetAlpha();
3266 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3267 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3268 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3269 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3270 alpha-=seed->GetAlpha();
3271 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3272 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3273 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3274 AliWarning(Form("Rotating track over %f",alpha));
3275 if (!seed->Rotate(alpha)) {
3276 MarkSeedFree( seed );
3282 if (esd->GetKinkIndex(0)<=0){
3283 for (Int_t irow=0;irow<160;irow++){
3284 Int_t index = seed->GetClusterIndex2(irow);
3287 AliTPCclusterMI * cl = GetClusterMI(index);
3288 seed->SetClusterPointer(irow,cl);
3290 if ((index & 0x8000)==0){
3291 cl->Use(10); // accepted cluster
3293 cl->Use(6); // close cluster not accepted
3296 Info("ReadSeeds","Not found cluster");
3301 fSeeds->AddAt(seed,i);
3307 //_____________________________________________________________________________
3308 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3309 Float_t deltay, Int_t ddsec) {
3310 //-----------------------------------------------------------------
3311 // This function creates track seeds.
3312 // SEEDING WITH VERTEX CONSTRAIN
3313 //-----------------------------------------------------------------
3314 // cuts[0] - fP4 cut
3315 // cuts[1] - tan(phi) cut
3316 // cuts[2] - zvertex cut
3317 // cuts[3] - fP3 cut
3325 Double_t x[5], c[15];
3326 // Int_t di = i1-i2;
3328 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3329 seed->SetPoolID(fLastSeedID);
3330 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3331 Double_t cs=cos(alpha), sn=sin(alpha);
3333 // Double_t x1 =fOuterSec->GetX(i1);
3334 //Double_t xx2=fOuterSec->GetX(i2);
3336 Double_t x1 =GetXrow(i1);
3337 Double_t xx2=GetXrow(i2);
3339 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3341 Int_t imiddle = (i2+i1)/2; //middle pad row index
3342 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3343 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3347 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3348 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3349 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3352 // change cut on curvature if it can't reach this layer
3353 // maximal curvature set to reach it
3354 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3355 if (dvertexmax*0.5*cuts[0]>0.85){
3356 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3358 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3361 if (deltay>0) ddsec = 0;
3362 // loop over clusters
3363 for (Int_t is=0; is < kr1; is++) {
3365 if (kr1[is]->IsUsed(10)) continue;
3366 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3367 //if (TMath::Abs(y1)>ymax) continue;
3369 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3371 // find possible directions
3372 Float_t anglez = (z1-z3)/(x1-x3);
3373 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3376 //find rotation angles relative to line given by vertex and point 1
3377 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3378 Double_t dvertex = TMath::Sqrt(dvertex2);
3379 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3380 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3383 // loop over 2 sectors
3389 Double_t dddz1=0; // direction of delta inclination in z axis
3396 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3397 Int_t sec2 = sec + dsec;
3399 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3400 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3401 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3402 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3403 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3404 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3406 // rotation angles to p1-p3
3407 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3408 Double_t x2, y2, z2;
3410 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3413 Double_t dxx0 = (xx2-x3)*cs13r;
3414 Double_t dyy0 = (xx2-x3)*sn13r;
3415 for (Int_t js=index1; js < index2; js++) {
3416 const AliTPCclusterMI *kcl = kr2[js];
3417 if (kcl->IsUsed(10)) continue;
3419 //calcutate parameters
3421 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3423 if (TMath::Abs(yy0)<0.000001) continue;
3424 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3425 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3426 Double_t r02 = (0.25+y0*y0)*dvertex2;
3427 //curvature (radius) cut
3428 if (r02<r2min) continue;
3432 Double_t c0 = 1/TMath::Sqrt(r02);
3436 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3437 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3438 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3439 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3442 Double_t z0 = kcl->GetZ();
3443 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3444 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3447 Double_t dip = (z1-z0)*c0/dfi1;
3448 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3459 x2= xx2*cs-y2*sn*dsec;
3460 y2=+xx2*sn*dsec+y2*cs;
3470 // do we have cluster at the middle ?
3472 GetProlongation(x1,xm,x,ym,zm);
3474 AliTPCclusterMI * cm=0;
3475 if (TMath::Abs(ym)-ymaxm<0){
3476 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3477 if ((!cm) || (cm->IsUsed(10))) {
3482 // rotate y1 to system 0
3483 // get state vector in rotated system
3484 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3485 Double_t xr2 = x0*cs+yr1*sn*dsec;
3486 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3488 GetProlongation(xx2,xm,xr,ym,zm);
3489 if (TMath::Abs(ym)-ymaxm<0){
3490 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3491 if ((!cm) || (cm->IsUsed(10))) {
3498 // Double_t dym = 0;
3499 // Double_t dzm = 0;
3501 // dym = ym - cm->GetY();
3502 // dzm = zm - cm->GetZ();
3509 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3510 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
3511 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3512 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3513 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3515 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3516 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3517 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3518 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3519 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3520 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3522 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3523 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3524 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3525 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3529 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3530 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3531 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3532 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3533 c[13]=f30*sy1*f40+f32*sy2*f42;
3534 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3536 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3538 UInt_t index=kr1.GetIndex(is);
3539 if (seed) {MarkSeedFree(seed); seed = 0;}
3540 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3541 seed->SetPoolID(fLastSeedID);
3542 track->SetIsSeeding(kTRUE);
3543 track->SetSeed1(i1);
3544 track->SetSeed2(i2);
3545 track->SetSeedType(3);
3549 FollowProlongation(*track, (i1+i2)/2,1);
3550 Int_t foundable,found,shared;
3551 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3552 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3553 MarkSeedFree(seed); seed = 0;
3559 FollowProlongation(*track, i2,1);
3563 track->SetBConstrain(1);
3564 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
3565 track->SetLastPoint(i1); // first cluster in track position
3566 track->SetFirstPoint(track->GetLastPoint());
3568 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3569 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3570 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3571 MarkSeedFree(seed); seed = 0;
3575 // Z VERTEX CONDITION
3576 Double_t zv, bz=GetBz();
3577 if ( !track->GetZAt(0.,bz,zv) ) continue;
3578 if (TMath::Abs(zv-z3)>cuts[2]) {
3579 FollowProlongation(*track, TMath::Max(i2-20,0));
3580 if ( !track->GetZAt(0.,bz,zv) ) continue;
3581 if (TMath::Abs(zv-z3)>cuts[2]){
3582 FollowProlongation(*track, TMath::Max(i2-40,0));
3583 if ( !track->GetZAt(0.,bz,zv) ) continue;
3584 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3585 // make seed without constrain
3586 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3587 FollowProlongation(*track2, i2,1);
3588 track2->SetBConstrain(kFALSE);
3589 track2->SetSeedType(1);
3590 arr->AddLast(track2);
3591 MarkSeedFree( seed ); seed = 0;
3595 MarkSeedFree( seed ); seed = 0;
3602 track->SetSeedType(0);
3603 arr->AddLast(track); // note, track is seed, don't free the seed
3604 seed = new( NextFreeSeed() ) AliTPCseed;
3605 seed->SetPoolID(fLastSeedID);
3607 // don't consider other combinations
3608 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3614 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3616 if (seed) MarkSeedFree( seed );
3620 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3625 //-----------------------------------------------------------------
3626 // This function creates track seeds.
3627 //-----------------------------------------------------------------
3628 // cuts[0] - fP4 cut
3629 // cuts[1] - tan(phi) cut
3630 // cuts[2] - zvertex cut
3631 // cuts[3] - fP3 cut
3641 Double_t x[5], c[15];
3643 // make temporary seed
3644 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3645 seed->SetPoolID(fLastSeedID);
3646 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3647 // Double_t cs=cos(alpha), sn=sin(alpha);
3652 Double_t x1 = GetXrow(i1-1);
3653 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3654 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
3656 Double_t x1p = GetXrow(i1);
3657 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3659 Double_t x1m = GetXrow(i1-2);
3660 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3663 //last 3 padrow for seeding
3664 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
3665 Double_t x3 = GetXrow(i1-7);
3666 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
3668 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
3669 Double_t x3p = GetXrow(i1-6);
3671 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
3672 Double_t x3m = GetXrow(i1-8);
3677 Int_t im = i1-4; //middle pad row index
3678 Double_t xm = GetXrow(im); // radius of middle pad-row
3679 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
3680 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
3683 Double_t deltax = x1-x3;
3684 Double_t dymax = deltax*cuts[1];
3685 Double_t dzmax = deltax*cuts[3];
3687 // loop over clusters
3688 for (Int_t is=0; is < kr1; is++) {
3690 if (kr1[is]->IsUsed(10)) continue;
3691 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3693 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3695 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3696 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3702 for (Int_t js=index1; js < index2; js++) {
3703 const AliTPCclusterMI *kcl = kr3[js];
3704 if (kcl->IsUsed(10)) continue;
3706 // apply angular cuts
3707 if (TMath::Abs(y1-y3)>dymax) continue;
3710 if (TMath::Abs(z1-z3)>dzmax) continue;
3712 Double_t angley = (y1-y3)/(x1-x3);
3713 Double_t anglez = (z1-z3)/(x1-x3);
3715 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3716 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3718 Double_t yyym = angley*(xm-x1)+y1;
3719 Double_t zzzm = anglez*(xm-x1)+z1;
3721 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3723 if (kcm->IsUsed(10)) continue;
3725 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3726 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3733 // look around first
3734 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3740 if (kc1m->IsUsed(10)) used++;
3742 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3748 if (kc1p->IsUsed(10)) used++;
3750 if (used>1) continue;
3751 if (found<1) continue;
3755 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3761 if (kc3m->IsUsed(10)) used++;
3765 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3771 if (kc3p->IsUsed(10)) used++;
3775 if (used>1) continue;
3776 if (found<3) continue;
3786 x[4]=F1(x1,y1,x2,y2,x3,y3);
3787 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3790 x[2]=F2(x1,y1,x2,y2,x3,y3);
3793 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3794 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3798 Double_t sy1=0.1, sz1=0.1;
3799 Double_t sy2=0.1, sz2=0.1;
3800 Double_t sy3=0.1, sy=0.1, sz=0.1;
3802 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3803 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3804 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3805 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3806 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3807 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3809 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3810 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3811 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3812 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3816 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3817 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3818 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3819 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3820 c[13]=f30*sy1*f40+f32*sy2*f42;
3821 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3823 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3825 index=kr1.GetIndex(is);
3826 if (seed) {MarkSeedFree( seed ); seed = 0;}
3827 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3828 seed->SetPoolID(fLastSeedID);
3830 track->SetIsSeeding(kTRUE);
3833 FollowProlongation(*track, i1-7,1);
3834 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
3835 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3836 MarkSeedFree( seed ); seed = 0;
3842 FollowProlongation(*track, i2,1);
3843 track->SetBConstrain(0);
3844 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
3845 track->SetFirstPoint(track->GetLastPoint());
3847 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3848 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
3849 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3850 MarkSeedFree( seed ); seed = 0;
3855 FollowProlongation(*track, TMath::Max(i2-10,0),1);
3856 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3857 FollowProlongation(*track2, i2,1);
3858 track2->SetBConstrain(kFALSE);
3859 track2->SetSeedType(4);
3860 arr->AddLast(track2);
3861 MarkSeedFree( seed ); seed = 0;
3865 //arr->AddLast(track);
3866 //seed = new AliTPCseed;
3872 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);
3874 if (seed) MarkSeedFree(seed);
3878 //_____________________________________________________________________________
3879 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3880 Float_t deltay, Bool_t /*bconstrain*/) {
3881 //-----------------------------------------------------------------
3882 // This function creates track seeds - without vertex constraint
3883 //-----------------------------------------------------------------
3884 // cuts[0] - fP4 cut - not applied
3885 // cuts[1] - tan(phi) cut
3886 // cuts[2] - zvertex cut - not applied
3887 // cuts[3] - fP3 cut
3897 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3898 // Double_t cs=cos(alpha), sn=sin(alpha);
3899 Int_t row0 = (i1+i2)/2;
3900 Int_t drow = (i1-i2)/2;
3901 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3902 AliTPCtrackerRow * kr=0;
3904 AliTPCpolyTrack polytrack;
3905 Int_t nclusters=fSectors[sec][row0];
3906 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3907 seed->SetPoolID(fLastSeedID);
3912 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
3914 Int_t nfoundable =0;
3915 for (Int_t iter =1; iter<2; iter++){ //iterations
3916 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3917 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
3918 const AliTPCclusterMI * cl= kr0[is];
3920 if (cl->IsUsed(10)) {
3926 Double_t x = kr0.GetX();
3927 // Initialization of the polytrack
3932 Double_t y0= cl->GetY();
3933 Double_t z0= cl->GetZ();
3937 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3938 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
3940 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
3941 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
3942 polytrack.AddPoint(x,y0,z0,erry, errz);
3945 if (cl->IsUsed(10)) sumused++;
3948 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3949 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3952 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3953 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3954 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
3955 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3956 if (cl1->IsUsed(10)) sumused++;
3957 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3961 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3963 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
3964 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3965 if (cl2->IsUsed(10)) sumused++;
3966 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3969 if (sumused>0) continue;
3971 polytrack.UpdateParameters();
3977 nfoundable = polytrack.GetN();
3978 nfound = nfoundable;
3980 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3981 Float_t maxdist = 0.8*(1.+3./(ddrow));
3982 for (Int_t delta = -1;delta<=1;delta+=2){
3983 Int_t row = row0+ddrow*delta;
3984 kr = &(fSectors[sec][row]);
3985 Double_t xn = kr->GetX();
3986 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3987 polytrack.GetFitPoint(xn,yn,zn);
3988 if (TMath::Abs(yn)>ymax1) continue;
3990 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3992 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3995 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3996 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3997 if (cln->IsUsed(10)) {
3998 // printf("used\n");
4006 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4011 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4012 polytrack.UpdateParameters();
4015 if ( (sumused>3) || (sumused>0.5*nfound)) {
4016 //printf("sumused %d\n",sumused);
4021 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4022 AliTPCpolyTrack track2;
4024 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4025 if (track2.GetN()<0.5*nfoundable) continue;
4028 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4030 // test seed with and without constrain
4031 for (Int_t constrain=0; constrain<=0;constrain++){
4032 // add polytrack candidate
4034 Double_t x[5], c[15];
4035 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4036 track2.GetBoundaries(x3,x1);
4038 track2.GetFitPoint(x1,y1,z1);
4039 track2.GetFitPoint(x2,y2,z2);
4040 track2.GetFitPoint(x3,y3,z3);
4042 //is track pointing to the vertex ?
4045 polytrack.GetFitPoint(x0,y0,z0);
4058 x[4]=F1(x1,y1,x2,y2,x3,y3);
4060 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4061 x[2]=F2(x1,y1,x2,y2,x3,y3);
4063 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4064 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4065 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4066 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4069 Double_t sy =0.1, sz =0.1;
4070 Double_t sy1=0.02, sz1=0.02;
4071 Double_t sy2=0.02, sz2=0.02;
4075 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4078 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4079 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4080 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4081 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4082 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4083 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4085 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4086 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4087 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4088 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4093 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4094 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4095 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4096 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4097 c[13]=f30*sy1*f40+f32*sy2*f42;
4098 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4100 //Int_t row1 = fSectors->GetRowNumber(x1);
4101 Int_t row1 = GetRowNumber(x1);
4105 if (seed) {MarkSeedFree( seed ); seed = 0;}
4106 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4107 seed->SetPoolID(fLastSeedID);
4108 track->SetIsSeeding(kTRUE);
4109 Int_t rc=FollowProlongation(*track, i2);
4110 if (constrain) track->SetBConstrain(1);
4112 track->SetBConstrain(0);
4113 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4114 track->SetFirstPoint(track->GetLastPoint());
4116 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4117 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4118 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4119 MarkSeedFree( seed ); seed = 0;
4122 arr->AddLast(track); // track IS seed, don't free seed
4123 seed = new( NextFreeSeed() ) AliTPCseed;
4124 seed->SetPoolID(fLastSeedID);
4128 } // if accepted seed
4131 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4133 if (seed) MarkSeedFree( seed );
4137 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4141 //reseed using track points
4142 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4143 Int_t p1 = int(r1*track->GetNumberOfClusters());
4144 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4146 Double_t x0[3],x1[3],x2[3];
4147 for (Int_t i=0;i<3;i++){
4153 // find track position at given ratio of the length
4154 Int_t sec0=0, sec1=0, sec2=0;
4157 for (Int_t i=0;i<160;i++){
4158 if (track->GetClusterPointer(i)){
4160 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4161 if ( (index<p0) || x0[0]<0 ){
4162 if (trpoint->GetX()>1){
4163 clindex = track->GetClusterIndex2(i);
4165 x0[0] = trpoint->GetX();
4166 x0[1] = trpoint->GetY();
4167 x0[2] = trpoint->GetZ();
4168 sec0 = ((clindex&0xff000000)>>24)%18;
4173 if ( (index<p1) &&(trpoint->GetX()>1)){
4174 clindex = track->GetClusterIndex2(i);
4176 x1[0] = trpoint->GetX();
4177 x1[1] = trpoint->GetY();
4178 x1[2] = trpoint->GetZ();
4179 sec1 = ((clindex&0xff000000)>>24)%18;
4182 if ( (index<p2) &&(trpoint->GetX()>1)){
4183 clindex = track->GetClusterIndex2(i);
4185 x2[0] = trpoint->GetX();
4186 x2[1] = trpoint->GetY();
4187 x2[2] = trpoint->GetZ();
4188 sec2 = ((clindex&0xff000000)>>24)%18;
4195 Double_t alpha, cs,sn, xx2,yy2;
4197 alpha = (sec1-sec2)*fSectors->GetAlpha();
4198 cs = TMath::Cos(alpha);
4199 sn = TMath::Sin(alpha);
4200 xx2= x1[0]*cs-x1[1]*sn;
4201 yy2= x1[0]*sn+x1[1]*cs;
4205 alpha = (sec0-sec2)*fSectors->GetAlpha();
4206 cs = TMath::Cos(alpha);
4207 sn = TMath::Sin(alpha);
4208 xx2= x0[0]*cs-x0[1]*sn;
4209 yy2= x0[0]*sn+x0[1]*cs;
4215 Double_t x[5],c[15];
4219 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4220 // if (x[4]>1) return 0;
4221 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4222 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4223 //if (TMath::Abs(x[3]) > 2.2) return 0;
4224 //if (TMath::Abs(x[2]) > 1.99) return 0;
4226 Double_t sy =0.1, sz =0.1;
4228 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4229 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4230 Double_t sy3=0.01+track->GetSigmaY2();
4232 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4233 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4234 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4235 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4236 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4237 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4239 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4240 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4241 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4242 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4247 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4248 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4249 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4250 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4251 c[13]=f30*sy1*f40+f32*sy2*f42;
4252 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4254 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4255 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4256 seed->SetPoolID(fLastSeedID);
4257 // Double_t y0,z0,y1,z1, y2,z2;
4258 //seed->GetProlongation(x0[0],y0,z0);
4259 // seed->GetProlongation(x1[0],y1,z1);
4260 //seed->GetProlongation(x2[0],y2,z2);
4262 seed->SetLastPoint(pp2);
4263 seed->SetFirstPoint(pp2);
4270 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4274 //reseed using founded clusters
4276 // Find the number of clusters
4277 Int_t nclusters = 0;
4278 for (Int_t irow=0;irow<160;irow++){
4279 if (track->GetClusterIndex(irow)>0) nclusters++;
4283 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4284 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4285 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4288 Double_t xyz[3][3]={{0}};
4289 Int_t row[3]={0},sec[3]={0,0,0};
4291 // find track row position at given ratio of the length
4293 for (Int_t irow=0;irow<160;irow++){
4294 if (track->GetClusterIndex2(irow)<0) continue;
4296 for (Int_t ipoint=0;ipoint<3;ipoint++){
4297 if (index<=ipos[ipoint]) row[ipoint] = irow;
4301 //Get cluster and sector position
4302 for (Int_t ipoint=0;ipoint<3;ipoint++){
4303 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4304 AliTPCclusterMI * cl = GetClusterMI(clindex);
4307 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4310 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4311 xyz[ipoint][0] = GetXrow(row[ipoint]);
4312 xyz[ipoint][1] = cl->GetY();
4313 xyz[ipoint][2] = cl->GetZ();
4317 // Calculate seed state vector and covariance matrix
4319 Double_t alpha, cs,sn, xx2,yy2;
4321 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4322 cs = TMath::Cos(alpha);
4323 sn = TMath::Sin(alpha);
4324 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4325 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4329 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4330 cs = TMath::Cos(alpha);
4331 sn = TMath::Sin(alpha);
4332 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4333 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4339 Double_t x[5],c[15];
4343 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4344 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4345 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4347 Double_t sy =0.1, sz =0.1;
4349 Double_t sy1=0.2, sz1=0.2;
4350 Double_t sy2=0.2, sz2=0.2;
4353 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;
4354 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;
4355 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;
4356 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;
4357 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;
4358 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;
4360 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;
4361 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;
4362 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;
4363 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;
4368 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4369 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4370 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4371 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4372 c[13]=f30*sy1*f40+f32*sy2*f42;
4373 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4375 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4376 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4377 seed->SetPoolID(fLastSeedID);
4378 seed->SetLastPoint(row[2]);
4379 seed->SetFirstPoint(row[2]);
4384 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4388 //reseed using founded clusters
4391 Int_t row[3]={0,0,0};
4392 Int_t sec[3]={0,0,0};
4394 // forward direction
4396 for (Int_t irow=r0;irow<160;irow++){
4397 if (track->GetClusterIndex(irow)>0){
4402 for (Int_t irow=160;irow>r0;irow--){
4403 if (track->GetClusterIndex(irow)>0){
4408 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4409 if (track->GetClusterIndex(irow)>0){
4417 for (Int_t irow=0;irow<r0;irow++){
4418 if (track->GetClusterIndex(irow)>0){
4423 for (Int_t irow=r0;irow>0;irow--){
4424 if (track->GetClusterIndex(irow)>0){
4429 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4430 if (track->GetClusterIndex(irow)>0){
4437 if ((row[2]-row[0])<20) return 0;
4438 if (row[1]==0) return 0;
4441 //Get cluster and sector position
4442 for (Int_t ipoint=0;ipoint<3;ipoint++){
4443 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4444 AliTPCclusterMI * cl = GetClusterMI(clindex);
4447 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4450 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4451 xyz[ipoint][0] = GetXrow(row[ipoint]);
4452 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4453 if (point&&ipoint<2){
4455 xyz[ipoint][1] = point->GetY();
4456 xyz[ipoint][2] = point->GetZ();
4459 xyz[ipoint][1] = cl->GetY();
4460 xyz[ipoint][2] = cl->GetZ();
4467 // Calculate seed state vector and covariance matrix
4469 Double_t alpha, cs,sn, xx2,yy2;
4471 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4472 cs = TMath::Cos(alpha);
4473 sn = TMath::Sin(alpha);
4474 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4475 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4479 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4480 cs = TMath::Cos(alpha);
4481 sn = TMath::Sin(alpha);
4482 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4483 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4489 Double_t x[5],c[15];
4493 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4494 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4495 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4497 Double_t sy =0.1, sz =0.1;
4499 Double_t sy1=0.2, sz1=0.2;
4500 Double_t sy2=0.2, sz2=0.2;
4503 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;
4504 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;
4505 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;
4506 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;
4507 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;
4508 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;
4510 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;
4511 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;
4512 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;
4513 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;
4518 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4519 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4520 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4521 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4522 c[13]=f30*sy1*f40+f32*sy2*f42;
4523 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4525 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4526 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4527 seed->SetPoolID(fLastSeedID);
4528 seed->SetLastPoint(row[2]);
4529 seed->SetFirstPoint(row[2]);
4530 for (Int_t i=row[0];i<row[2];i++){
4531 seed->SetClusterIndex(i, track->GetClusterIndex(i));
4539 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4542 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4544 // Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4546 // Two reasons to have multiple find tracks
4547 // 1. Curling tracks can be find more than once
4548 // 2. Splitted tracks
4549 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
4550 // b.) Edge effect on the sector boundaries
4553 // Algorithm done in 2 phases - because of CPU consumption
4554 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4556 // Algorihm for curling tracks sign:
4557 // 1 phase -makes a very rough fast cuts to minimize combinatorics
4558 // a.) opposite sign
4559 // b.) one of the tracks - not pointing to the primary vertex -
4560 // c.) delta tan(theta)
4562 // 2 phase - calculates DCA between tracks - time consument
4567 // General cuts - for splitted tracks and for curling tracks
4569 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
4571 // Curling tracks cuts
4576 Int_t nentries = array->GetEntriesFast();
4577 AliHelix *helixes = new AliHelix[nentries];
4578 Float_t *xm = new Float_t[nentries];
4579 Float_t *dz0 = new Float_t[nentries];
4580 Float_t *dz1 = new Float_t[nentries];
4586 // Find track COG in x direction - point with best defined parameters
4588 for (Int_t i=0;i<nentries;i++){
4589 AliTPCseed* track = (AliTPCseed*)array->At(i);
4590 if (!track) continue;
4591 track->SetCircular(0);
4592 new (&helixes[i]) AliHelix(*track);
4596 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4599 for (Int_t icl=0; icl<160; icl++){
4600 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
4606 if (ncl>0) xm[i]/=Float_t(ncl);
4609 for (Int_t i0=0;i0<nentries;i0++){
4610 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4611 if (!track0) continue;
4612 Float_t xc0 = helixes[i0].GetHelix(6);
4613 Float_t yc0 = helixes[i0].GetHelix(7);
4614 Float_t r0 = helixes[i0].GetHelix(8);
4615 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4616 Float_t fi0 = TMath::ATan2(yc0,xc0);
4618 for (Int_t i1=i0+1;i1<nentries;i1++){
4619 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4620 if (!track1) continue;
4621 Int_t lab0=track0->GetLabel();
4622 Int_t lab1=track1->GetLabel();
4623 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4625 Float_t xc1 = helixes[i1].GetHelix(6);
4626 Float_t yc1 = helixes[i1].GetHelix(7);
4627 Float_t r1 = helixes[i1].GetHelix(8);
4628 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4629 Float_t fi1 = TMath::ATan2(yc1,xc1);
4631 Float_t dfi = fi0-fi1;
4634 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4635 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4636 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4638 // if short tracks with undefined sign
4639 fi1 = -TMath::ATan2(yc1,-xc1);
4642 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4645 // debug stream to tune "fast cuts"
4647 Double_t dist[3]; // distance at X
4648 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
4649 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4650 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4651 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4652 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4653 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4654 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4655 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4659 for (Int_t icl=0; icl<160; icl++){
4660 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
4661 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
4664 if (cl0==cl1) sums++;
4668 if (AliTPCReconstructor::StreamLevel()>5) {
4669 TTreeSRedirector &cstream = *fDebugStreamer;
4674 "Tr0.="<<track0<< // seed0
4675 "Tr1.="<<track1<< // seed1
4676 "h0.="<<&helixes[i0]<<
4677 "h1.="<<&helixes[i1]<<
4679 "sum="<<sum<< //the sum of rows with cl in both
4680 "sums="<<sums<< //the sum of shared clusters
4681 "xm0="<<xm[i0]<< // the center of track
4682 "xm1="<<xm[i1]<< // the x center of track
4683 // General cut variables
4684 "dfi="<<dfi<< // distance in fi angle
4685 "dtheta="<<dtheta<< // distance int theta angle
4691 "dist0="<<dist[0]<< //distance x
4692 "dist1="<<dist[1]<< //distance y
4693 "dist2="<<dist[2]<< //distance z
4694 "mdist0="<<mdist[0]<< //distance x
4695 "mdist1="<<mdist[1]<< //distance y
4696 "mdist2="<<mdist[2]<< //distance z
4712 if (AliTPCReconstructor::StreamLevel()>1) {
4713 AliInfo("Time for curling tracks removal DEBUGGING MC");
4720 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
4722 // Find Splitted tracks and remove the one with worst quality
4723 // Corresponding debug streamer to tune selections - "Splitted2"
4725 // 0. Sort tracks according quility
4726 // 1. Propagate the tracks to the reference radius
4727 // 2. Double_t loop to select close tracks (only to speed up process)
4728 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
4729 // 4. Delete temporary parameters
4731 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
4733 const Double_t kCutP1=10; // delta Z cut 10 cm
4734 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
4735 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
4736 const Double_t kCutAlpha=0.15; // delta alpha cut
4737 Int_t firstpoint = 0;
4738 Int_t lastpoint = 160;
4740 Int_t nentries = array->GetEntriesFast();
4741 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
4747 //0. Sort tracks according quality
4748 //1. Propagate the ext. param to reference radius
4749 Int_t nseed = array->GetEntriesFast();
4750 if (nseed<=0) return;
4751 Float_t * quality = new Float_t[nseed];
4752 Int_t * indexes = new Int_t[nseed];
4753 for (Int_t i=0; i<nseed; i++) {
4754 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
4759 pt->UpdatePoints(); //select first last max dens points
4760 Float_t * points = pt->GetPoints();
4761 if (points[3]<0.8) quality[i] =-1;
4762 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4763 //prefer high momenta tracks if overlaps
4764 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
4766 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
4767 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
4769 TMath::Sort(nseed,quality,indexes);
4771 // 3. Loop over pair of tracks
4773 for (Int_t i0=0; i0<nseed; i0++) {
4774 Int_t index0=indexes[i0];
4775 if (!(array->UncheckedAt(index0))) continue;
4776 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
4777 if (!s1->IsActive()) continue;
4778 AliExternalTrackParam &par0=params[index0];
4779 for (Int_t i1=i0+1; i1<nseed; i1++) {
4780 Int_t index1=indexes[i1];
4781 if (!(array->UncheckedAt(index1))) continue;
4782 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
4783 if (!s2->IsActive()) continue;
4784 if (s2->GetKinkIndexes()[0]!=0)
4785 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
4786 AliExternalTrackParam &par1=params[index1];
4787 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
4788 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
4789 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
4790 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
4791 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
4792 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
4797 Int_t firstShared=lastpoint, lastShared=firstpoint;
4798 Int_t firstRow=lastpoint, lastRow=firstpoint;
4800 for (Int_t i=firstpoint;i<lastpoint;i++){
4801 if (s1->GetClusterIndex2(i)>0) nall0++;
4802 if (s2->GetClusterIndex2(i)>0) nall1++;
4803 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
4804 if (i<firstRow) firstRow=i;
4805 if (i>lastRow) lastRow=i;
4807 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
4808 if (i<firstShared) firstShared=i;
4809 if (i>lastShared) lastShared=i;
4813 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
4814 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
4816 if( AliTPCReconstructor::StreamLevel()>1){
4817 TTreeSRedirector &cstream = *fDebugStreamer;
4818 Int_t n0=s1->GetNumberOfClusters();
4819 Int_t n1=s2->GetNumberOfClusters();
4820 Int_t n0F=s1->GetNFoundable();
4821 Int_t n1F=s2->GetNFoundable();
4822 Int_t lab0=s1->GetLabel();
4823 Int_t lab1=s2->GetLabel();
4825 cstream<<"Splitted2"<<
4826 "iter="<<fIteration<<
4827 "lab0="<<lab0<< // MC label if exist
4828 "lab1="<<lab1<< // MC label if exist
4831 "ratio0="<<ratio0<< // shared ratio
4832 "ratio1="<<ratio1<< // shared ratio
4833 "p0.="<<&par0<< // track parameters
4835 "s0.="<<s1<< // full seed
4837 "n0="<<n0<< // number of clusters track 0
4838 "n1="<<n1<< // number of clusters track 1
4839 "nall0="<<nall0<< // number of clusters track 0
4840 "nall1="<<nall1<< // number of clusters track 1
4841 "n0F="<<n0F<< // number of findable
4842 "n1F="<<n1F<< // number of findable
4843 "shared="<<sumShared<< // number of shared clusters
4844 "firstS="<<firstShared<< // first and the last shared row
4845 "lastS="<<lastShared<<
4846 "firstRow="<<firstRow<< // first and the last row with cluster
4847 "lastRow="<<lastRow<< //
4851 // remove track with lower quality
4853 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
4854 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
4858 MarkSeedFree( array->RemoveAt(index1) );
4863 // 4. Delete temporary array
4873 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4876 // find Curling tracks
4877 // Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4880 // Algorithm done in 2 phases - because of CPU consumption
4881 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4882 // see detal in MC part what can be used to cut
4886 const Float_t kMaxC = 400; // maximal curvature to of the track
4887 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
4888 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
4889 const Float_t kPtRatio = 0.3; // ratio between pt
4890 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
4893 // Curling tracks cuts
4896 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
4897 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
4898 const Float_t kMinAngle = 2.9; // angle between tracks
4899 const Float_t kMaxDist = 5; // biggest distance
4901 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4904 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4905 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4906 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4907 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4908 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
4910 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4911 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4913 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
4914 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4916 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4922 Int_t nentries = array->GetEntriesFast();
4923 AliHelix *helixes = new AliHelix[nentries];
4924 for (Int_t i=0;i<nentries;i++){
4925 AliTPCseed* track = (AliTPCseed*)array->At(i);
4926 if (!track) continue;
4927 track->SetCircular(0);
4928 new (&helixes[i]) AliHelix(*track);
4934 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4940 for (Int_t i0=0;i0<nentries;i0++){
4941 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4942 if (!track0) continue;
4943 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4944 Float_t xc0 = helixes[i0].GetHelix(6);
4945 Float_t yc0 = helixes[i0].GetHelix(7);
4946 Float_t r0 = helixes[i0].GetHelix(8);
4947 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4948 Float_t fi0 = TMath::ATan2(yc0,xc0);
4950 for (Int_t i1=i0+1;i1<nentries;i1++){
4951 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4952 if (!track1) continue;
4953 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
4954 Float_t xc1 = helixes[i1].GetHelix(6);
4955 Float_t yc1 = helixes[i1].GetHelix(7);
4956 Float_t r1 = helixes[i1].GetHelix(8);
4957 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4958 Float_t fi1 = TMath::ATan2(yc1,xc1);
4960 Float_t dfi = fi0-fi1;
4963 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4964 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4965 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4969 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
4970 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
4971 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4972 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
4973 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4975 Float_t pt0 = track0->GetSignedPt();
4976 Float_t pt1 = track1->GetSignedPt();
4977 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
4978 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4979 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
4980 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
4983 // Now find closest approach
4987 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4988 if (npoints==0) continue;
4989 helixes[i0].GetClosestPhases(helixes[i1], phase);
4993 Double_t hangles[3];
4994 helixes[i0].Evaluate(phase[0][0],xyz0);
4995 helixes[i1].Evaluate(phase[0][1],xyz1);
4997 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4998 Double_t deltah[2],deltabest;
4999 if (TMath::Abs(hangles[2])<kMinAngle) continue;
5003 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5005 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5006 if (deltah[1]<deltah[0]) ibest=1;
5008 deltabest = TMath::Sqrt(deltah[ibest]);
5009 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5010 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5011 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5012 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5014 if (deltabest>kMaxDist) continue;
5015 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5016 Bool_t sign =kFALSE;
5017 if (hangles[2]>kMinAngle) sign =kTRUE;
5020 // circular[i0] = kTRUE;
5021 // circular[i1] = kTRUE;
5022 if (track0->OneOverPt()<track1->OneOverPt()){
5023 track0->SetCircular(track0->GetCircular()+1);
5024 track1->SetCircular(track1->GetCircular()+2);
5027 track1->SetCircular(track1->GetCircular()+1);
5028 track0->SetCircular(track0->GetCircular()+2);
5031 if (AliTPCReconstructor::StreamLevel()>2){
5033 //debug stream to tune "fine" cuts
5034 Int_t lab0=track0->GetLabel();
5035 Int_t lab1=track1->GetLabel();
5036 TTreeSRedirector &cstream = *fDebugStreamer;
5037 cstream<<"Curling2"<<
5053 "npoints="<<npoints<<
5054 "hangles0="<<hangles[0]<<
5055 "hangles1="<<hangles[1]<<
5056 "hangles2="<<hangles[2]<<
5059 "radius="<<radiusbest<<
5060 "deltabest="<<deltabest<<
5061 "phase0="<<phase[ibest][0]<<
5062 "phase1="<<phase[ibest][1]<<
5070 if (AliTPCReconstructor::StreamLevel()>1) {
5071 AliInfo("Time for curling tracks removal");
5077 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5083 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5086 TObjArray *kinks= new TObjArray(10000);
5087 // TObjArray *v0s= new TObjArray(10000);
5088 Int_t nentries = array->GetEntriesFast();
5089 AliHelix *helixes = new AliHelix[nentries];
5090 Int_t *sign = new Int_t[nentries];
5091 Int_t *nclusters = new Int_t[nentries];
5092 Float_t *alpha = new Float_t[nentries];
5093 AliKink *kink = new AliKink();
5094 Int_t * usage = new Int_t[nentries];
5095 Float_t *zm = new Float_t[nentries];
5096 Float_t *z0 = new Float_t[nentries];
5097 Float_t *fim = new Float_t[nentries];
5098 Float_t *shared = new Float_t[nentries];
5099 Bool_t *circular = new Bool_t[nentries];
5100 Float_t *dca = new Float_t[nentries];
5101 //const AliESDVertex * primvertex = esd->GetVertex();
5103 // nentries = array->GetEntriesFast();
5108 for (Int_t i=0;i<nentries;i++){
5111 AliTPCseed* track = (AliTPCseed*)array->At(i);
5112 if (!track) continue;
5113 track->SetCircular(0);
5115 track->UpdatePoints();
5116 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5118 nclusters[i]=track->GetNumberOfClusters();
5119 alpha[i] = track->GetAlpha();
5120 new (&helixes[i]) AliHelix(*track);
5122 helixes[i].Evaluate(0,xyz);
5123 sign[i] = (track->GetC()>0) ? -1:1;
5126 if (track->GetProlongation(x,y,z)){
5128 fim[i] = alpha[i]+TMath::ATan2(y,x);
5131 zm[i] = track->GetZ();
5135 circular[i]= kFALSE;
5136 if (track->GetProlongation(0,y,z)) z0[i] = z;
5137 dca[i] = track->GetD(0,0);
5143 Int_t ncandidates =0;
5146 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5149 // Find circling track
5151 for (Int_t i0=0;i0<nentries;i0++){
5152 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5153 if (!track0) continue;
5154 if (track0->GetNumberOfClusters()<40) continue;
5155 if (TMath::Abs(1./track0->GetC())>200) continue;
5156 for (Int_t i1=i0+1;i1<nentries;i1++){
5157 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5158 if (!track1) continue;
5159 if (track1->GetNumberOfClusters()<40) continue;
5160 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5161 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5162 if (TMath::Abs(1./track1->GetC())>200) continue;
5163 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5164 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5165 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5166 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5167 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5169 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5170 if (mindcar<5) continue;
5171 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5172 if (mindcaz<5) continue;
5173 if (mindcar+mindcaz<20) continue;
5176 Float_t xc0 = helixes[i0].GetHelix(6);
5177 Float_t yc0 = helixes[i0].GetHelix(7);
5178 Float_t r0 = helixes[i0].GetHelix(8);
5179 Float_t xc1 = helixes[i1].GetHelix(6);
5180 Float_t yc1 = helixes[i1].GetHelix(7);
5181 Float_t r1 = helixes[i1].GetHelix(8);
5183 Float_t rmean = (r0+r1)*0.5;
5184 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5185 //if (delta>30) continue;
5186 if (delta>rmean*0.25) continue;
5187 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5189 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5190 if (npoints==0) continue;
5191 helixes[i0].GetClosestPhases(helixes[i1], phase);
5195 Double_t hangles[3];
5196 helixes[i0].Evaluate(phase[0][0],xyz0);
5197 helixes[i1].Evaluate(phase[0][1],xyz1);
5199 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5200 Double_t deltah[2],deltabest;
5201 if (hangles[2]<2.8) continue;
5204 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5206 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5207 if (deltah[1]<deltah[0]) ibest=1;
5209 deltabest = TMath::Sqrt(deltah[ibest]);
5210 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5211 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5212 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5213 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5215 if (deltabest>6) continue;
5216 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5217 Bool_t lsign =kFALSE;
5218 if (hangles[2]>3.06) lsign =kTRUE;
5221 circular[i0] = kTRUE;
5222 circular[i1] = kTRUE;
5223 if (track0->OneOverPt()<track1->OneOverPt()){
5224 track0->SetCircular(track0->GetCircular()+1);
5225 track1->SetCircular(track1->GetCircular()+2);
5228 track1->SetCircular(track1->GetCircular()+1);
5229 track0->SetCircular(track0->GetCircular()+2);
5232 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5234 Int_t lab0=track0->GetLabel();
5235 Int_t lab1=track1->GetLabel();
5236 TTreeSRedirector &cstream = *fDebugStreamer;
5237 cstream<<"Curling"<<
5244 "mindcar="<<mindcar<<
5245 "mindcaz="<<mindcaz<<
5248 "npoints="<<npoints<<
5249 "hangles0="<<hangles[0]<<
5250 "hangles2="<<hangles[2]<<
5255 "radius="<<radiusbest<<
5256 "deltabest="<<deltabest<<
5257 "phase0="<<phase[ibest][0]<<
5258 "phase1="<<phase[ibest][1]<<
5268 for (Int_t i =0;i<nentries;i++){
5269 if (sign[i]==0) continue;
5270 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5277 Double_t cradius0 = 40*40;
5278 Double_t cradius1 = 270*270;
5281 Double_t cdist3=0.55;
5282 for (Int_t j =i+1;j<nentries;j++){
5284 if (sign[j]*sign[i]<1) continue;
5285 if ( (nclusters[i]+nclusters[j])>200) continue;
5286 if ( (nclusters[i]+nclusters[j])<80) continue;
5287 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5288 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5289 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5290 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5291 if (npoints<1) continue;
5294 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5297 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5300 Double_t delta1=10000,delta2=10000;
5301 // cuts on the intersection radius
5302 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5303 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5304 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5306 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5307 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5308 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5311 Double_t distance1 = TMath::Min(delta1,delta2);
5312 if (distance1>cdist1) continue; // cut on DCA linear approximation
5314 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5315 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5316 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5317 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5320 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5321 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5322 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5324 distance1 = TMath::Min(delta1,delta2);
5327 rkink = TMath::Sqrt(radius[0]);
5330 rkink = TMath::Sqrt(radius[1]);
5332 if (distance1>cdist2) continue;
5335 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5338 Int_t row0 = GetRowNumber(rkink);
5339 if (row0<10) continue;
5340 if (row0>150) continue;
5343 Float_t dens00=-1,dens01=-1;
5344 Float_t dens10=-1,dens11=-1;
5346 Int_t found,foundable,ishared;
5347 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5348 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5349 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5350 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5352 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5353 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5354 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5355 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5357 if (dens00<dens10 && dens01<dens11) continue;
5358 if (dens00>dens10 && dens01>dens11) continue;
5359 if (TMath::Max(dens00,dens10)<0.1) continue;
5360 if (TMath::Max(dens01,dens11)<0.3) continue;
5362 if (TMath::Min(dens00,dens10)>0.6) continue;
5363 if (TMath::Min(dens01,dens11)>0.6) continue;
5366 AliTPCseed * ktrack0, *ktrack1;
5375 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5376 AliExternalTrackParam paramm(*ktrack0);
5377 AliExternalTrackParam paramd(*ktrack1);
5378 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5381 kink->SetMother(paramm);
5382 kink->SetDaughter(paramd);
5385 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
5387 fkParam->Transform0to1(x,index);
5388 fkParam->Transform1to2(x,index);
5389 row0 = GetRowNumber(x[0]);
5391 if (kink->GetR()<100) continue;
5392 if (kink->GetR()>240) continue;
5393 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5394 if (kink->GetDistance()>cdist3) continue;
5395 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5396 if (dird<0) continue;
5398 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5399 if (dirm<0) continue;
5400 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5401 if (mpt<0.2) continue;
5404 //for high momenta momentum not defined well in first iteration
5405 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5406 if (qt>0.35) continue;
5409 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5410 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5412 kink->SetTPCDensity(dens00,0,0);
5413 kink->SetTPCDensity(dens01,0,1);
5414 kink->SetTPCDensity(dens10,1,0);
5415 kink->SetTPCDensity(dens11,1,1);
5416 kink->SetIndex(i,0);
5417 kink->SetIndex(j,1);
5420 kink->SetTPCDensity(dens10,0,0);
5421 kink->SetTPCDensity(dens11,0,1);
5422 kink->SetTPCDensity(dens00,1,0);
5423 kink->SetTPCDensity(dens01,1,1);
5424 kink->SetIndex(j,0);
5425 kink->SetIndex(i,1);
5428 if (mpt<1||kink->GetAngle(2)>0.1){
5429 // angle and densities not defined yet
5430 if (kink->GetTPCDensityFactor()<0.8) continue;
5431 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5432 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5433 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5434 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5436 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5437 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5438 criticalangle= 3*TMath::Sqrt(criticalangle);
5439 if (criticalangle>0.02) criticalangle=0.02;
5440 if (kink->GetAngle(2)<criticalangle) continue;
5443 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5444 Float_t shapesum =0;
5446 for ( Int_t row = row0-drow; row<row0+drow;row++){
5447 if (row<0) continue;
5448 if (row>155) continue;
5449 if (ktrack0->GetClusterPointer(row)){
5450 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5451 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5454 if (ktrack1->GetClusterPointer(row)){
5455 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5456 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5461 kink->SetShapeFactor(-1.);
5464 kink->SetShapeFactor(shapesum/sum);
5466 // esd->AddKink(kink);
5468 // kink->SetMother(paramm);
5469 //kink->SetDaughter(paramd);
5471 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5473 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5474 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5476 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5478 if (AliTPCReconstructor::StreamLevel()>1) {
5479 (*fDebugStreamer)<<"kinkLpt"<<
5487 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5491 kinks->AddLast(kink);
5497 // sort the kinks according quality - and refit them towards vertex
5499 Int_t nkinks = kinks->GetEntriesFast();
5500 Float_t *quality = new Float_t[nkinks];
5501 Int_t *indexes = new Int_t[nkinks];
5502 AliTPCseed *mothers = new AliTPCseed[nkinks];
5503 AliTPCseed *daughters = new AliTPCseed[nkinks];
5506 for (Int_t i=0;i<nkinks;i++){
5508 AliKink *kinkl = (AliKink*)kinks->At(i);
5510 // refit kinks towards vertex
5512 Int_t index0 = kinkl->GetIndex(0);
5513 Int_t index1 = kinkl->GetIndex(1);
5514 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5515 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5517 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5519 // Refit Kink under if too small angle
5521 if (kinkl->GetAngle(2)<0.05){
5522 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5523 Int_t row0 = kinkl->GetTPCRow0();
5524 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5527 Int_t last = row0-drow;
5528 if (last<40) last=40;
5529 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5530 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5533 Int_t first = row0+drow;
5534 if (first>130) first=130;
5535 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5536 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5538 if (seed0 && seed1){
5539 kinkl->SetStatus(1,8);
5540 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5541 row0 = GetRowNumber(kinkl->GetR());
5542 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5543 mothers[i] = *seed0;
5544 daughters[i] = *seed1;
5547 delete kinks->RemoveAt(i);
5548 if (seed0) MarkSeedFree( seed0 );
5549 if (seed1) MarkSeedFree( seed1 );
5552 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
5553 delete kinks->RemoveAt(i);
5554 if (seed0) MarkSeedFree( seed0 );
5555 if (seed1) MarkSeedFree( seed1 );
5559 MarkSeedFree( seed0 );
5560 MarkSeedFree( seed1 );
5563 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
5565 TMath::Sort(nkinks,quality,indexes,kFALSE);
5567 //remove double find kinks
5569 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5570 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5571 if (!kink0) continue;
5573 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5574 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5575 if (!kink0) continue;
5576 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5577 if (!kink1) continue;
5578 // if not close kink continue
5579 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5580 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5581 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5583 AliTPCseed &mother0 = mothers[indexes[ikink0]];
5584 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5585 AliTPCseed &mother1 = mothers[indexes[ikink1]];
5586 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5587 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5596 for (Int_t i=0;i<row0;i++){
5597 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5600 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5607 for (Int_t i=row0;i<158;i++){
5608 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
5609 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
5612 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5618 Float_t ratio = Float_t(same+1)/Float_t(both+1);
5619 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5620 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5621 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5622 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5623 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5625 shared[kink0->GetIndex(0)]= kTRUE;
5626 shared[kink0->GetIndex(1)]= kTRUE;
5627 delete kinks->RemoveAt(indexes[ikink0]);
5631 shared[kink1->GetIndex(0)]= kTRUE;
5632 shared[kink1->GetIndex(1)]= kTRUE;
5633 delete kinks->RemoveAt(indexes[ikink1]);
5640 for (Int_t i=0;i<nkinks;i++){
5641 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
5642 if (!kinkl) continue;
5643 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5644 Int_t index0 = kinkl->GetIndex(0);
5645 Int_t index1 = kinkl->GetIndex(1);
5646 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
5647 kinkl->SetMultiple(usage[index0],0);
5648 kinkl->SetMultiple(usage[index1],1);
5649 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
5650 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5651 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
5652 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
5654 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5655 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5656 if (!ktrack0 || !ktrack1) continue;
5657 Int_t index = esd->AddKink(kinkl);
5660 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
5661 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5662 *ktrack0 = mothers[indexes[i]];
5663 *ktrack1 = daughters[indexes[i]];
5667 ktrack0->SetKinkIndex(usage[index0],-(index+1));
5668 ktrack1->SetKinkIndex(usage[index1], (index+1));
5673 // Remove tracks corresponding to shared kink's
5675 for (Int_t i=0;i<nentries;i++){
5676 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5677 if (!track0) continue;
5678 if (track0->GetKinkIndex(0)!=0) continue;
5679 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
5684 RemoveUsed2(array,0.5,0.4,30);
5686 for (Int_t i=0;i<nentries;i++){
5687 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5688 if (!track0) continue;
5689 track0->CookdEdx(0.02,0.6);
5693 for (Int_t i=0;i<nentries;i++){
5694 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5695 if (!track0) continue;
5696 if (track0->Pt()<1.4) continue;
5697 //remove double high momenta tracks - overlapped with kink candidates
5700 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5701 if (track0->GetClusterPointer(icl)!=0){
5703 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
5706 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
5707 MarkSeedFree( array->RemoveAt(i) );
5711 if (track0->GetKinkIndex(0)!=0) continue;
5712 if (track0->GetNumberOfClusters()<80) continue;
5714 AliTPCseed *pmother = new AliTPCseed();
5715 AliTPCseed *pdaughter = new AliTPCseed();
5716 AliKink *pkink = new AliKink;
5718 AliTPCseed & mother = *pmother;
5719 AliTPCseed & daughter = *pdaughter;
5720 AliKink & kinkl = *pkink;
5721 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
5722 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5726 continue; //too short tracks
5728 if (mother.Pt()<1.4) {
5734 Int_t row0= kinkl.GetTPCRow0();
5735 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
5742 Int_t index = esd->AddKink(&kinkl);
5743 mother.SetKinkIndex(0,-(index+1));
5744 daughter.SetKinkIndex(0,index+1);
5745 if (mother.GetNumberOfClusters()>50) {
5746 MarkSeedFree( array->RemoveAt(i) );
5747 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5748 mtc->SetPoolID(fLastSeedID);
5749 array->AddAt(mtc,i);
5752 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5753 mtc->SetPoolID(fLastSeedID);
5754 array->AddLast(mtc);
5756 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
5757 dtc->SetPoolID(fLastSeedID);
5758 array->AddLast(dtc);
5759 for (Int_t icl=0;icl<row0;icl++) {
5760 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5763 for (Int_t icl=row0;icl<158;icl++) {
5764 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5773 delete [] daughters;
5795 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
5801 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5808 TObjArray *kinks= new TObjArray(10000);
5809 // TObjArray *v0s= new TObjArray(10000);
5810 Int_t nentries = array->GetEntriesFast();
5811 AliHelix *helixes = new AliHelix[nentries];
5812 Int_t *sign = new Int_t[nentries];
5813 Int_t *nclusters = new Int_t[nentries];
5814 Float_t *alpha = new Float_t[nentries];
5815 AliKink *kink = new AliKink();
5816 Int_t * usage = new Int_t[nentries];
5817 Float_t *zm = new Float_t[nentries];
5818 Float_t *z0 = new Float_t[nentries];
5819 Float_t *fim = new Float_t[nentries];
5820 Float_t *shared = new Float_t[nentries];
5821 Bool_t *circular = new Bool_t[nentries];
5822 Float_t *dca = new Float_t[nentries];
5823 //const AliESDVertex * primvertex = esd->GetVertex();
5825 // nentries = array->GetEntriesFast();
5830 for (Int_t i=0;i<nentries;i++){
5833 AliTPCseed* track = (AliTPCseed*)array->At(i);
5834 if (!track) continue;
5835 track->SetCircular(0);
5837 track->UpdatePoints();
5838 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5840 nclusters[i]=track->GetNumberOfClusters();
5841 alpha[i] = track->GetAlpha();
5842 new (&helixes[i]) AliHelix(*track);
5844 helixes[i].Evaluate(0,xyz);
5845 sign[i] = (track->GetC()>0) ? -1:1;
5848 if (track->GetProlongation(x,y,z)){
5850 fim[i] = alpha[i]+TMath::ATan2(y,x);
5853 zm[i] = track->GetZ();
5857 circular[i]= kFALSE;
5858 if (track->GetProlongation(0,y,z)) z0[i] = z;
5859 dca[i] = track->GetD(0,0);
5865 Int_t ncandidates =0;
5868 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5871 // Find circling track
5873 for (Int_t i0=0;i0<nentries;i0++){
5874 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5875 if (!track0) continue;
5876 if (track0->GetNumberOfClusters()<40) continue;
5877 if (TMath::Abs(1./track0->GetC())>200) continue;
5878 for (Int_t i1=i0+1;i1<nentries;i1++){
5879 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5880 if (!track1) continue;
5881 if (track1->GetNumberOfClusters()<40) continue;
5882 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5883 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5884 if (TMath::Abs(1./track1->GetC())>200) continue;
5885 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5886 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5887 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5888 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5889 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5891 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5892 if (mindcar<5) continue;
5893 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5894 if (mindcaz<5) continue;
5895 if (mindcar+mindcaz<20) continue;
5898 Float_t xc0 = helixes[i0].GetHelix(6);
5899 Float_t yc0 = helixes[i0].GetHelix(7);
5900 Float_t r0 = helixes[i0].GetHelix(8);
5901 Float_t xc1 = helixes[i1].GetHelix(6);
5902 Float_t yc1 = helixes[i1].GetHelix(7);
5903 Float_t r1 = helixes[i1].GetHelix(8);
5905 Float_t rmean = (r0+r1)*0.5;
5906 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5907 //if (delta>30) continue;
5908 if (delta>rmean*0.25) continue;
5909 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5911 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5912 if (npoints==0) continue;
5913 helixes[i0].GetClosestPhases(helixes[i1], phase);
5917 Double_t hangles[3];
5918 helixes[i0].Evaluate(phase[0][0],xyz0);
5919 helixes[i1].Evaluate(phase[0][1],xyz1);
5921 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5922 Double_t deltah[2],deltabest;
5923 if (hangles[2]<2.8) continue;
5926 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5928 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5929 if (deltah[1]<deltah[0]) ibest=1;
5931 deltabest = TMath::Sqrt(deltah[ibest]);
5932 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5933 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5934 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5935 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5937 if (deltabest>6) continue;
5938 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5939 Bool_t lsign =kFALSE;
5940 if (hangles[2]>3.06) lsign =kTRUE;
5943 circular[i0] = kTRUE;
5944 circular[i1] = kTRUE;
5945 if (track0->OneOverPt()<track1->OneOverPt()){
5946 track0->SetCircular(track0->GetCircular()+1);
5947 track1->SetCircular(track1->GetCircular()+2);
5950 track1->SetCircular(track1->GetCircular()+1);
5951 track0->SetCircular(track0->GetCircular()+2);
5954 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5956 Int_t lab0=track0->GetLabel();
5957 Int_t lab1=track1->GetLabel();
5958 TTreeSRedirector &cstream = *fDebugStreamer;
5959 cstream<<"Curling"<<
5966 "mindcar="<<mindcar<<
5967 "mindcaz="<<mindcaz<<
5970 "npoints="<<npoints<<
5971 "hangles0="<<hangles[0]<<
5972 "hangles2="<<hangles[2]<<
5977 "radius="<<radiusbest<<
5978 "deltabest="<<deltabest<<
5979 "phase0="<<phase[ibest][0]<<
5980 "phase1="<<phase[ibest][1]<<
5990 for (Int_t i =0;i<nentries;i++){
5991 if (sign[i]==0) continue;
5992 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5999 Double_t cradius0 = 40*40;
6000 Double_t cradius1 = 270*270;
6003 Double_t cdist3=0.55;
6004 for (Int_t j =i+1;j<nentries;j++){
6006 if (sign[j]*sign[i]<1) continue;
6007 if ( (nclusters[i]+nclusters[j])>200) continue;
6008 if ( (nclusters[i]+nclusters[j])<80) continue;
6009 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6010 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6011 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6012 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6013 if (npoints<1) continue;
6016 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6019 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6022 Double_t delta1=10000,delta2=10000;
6023 // cuts on the intersection radius
6024 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6025 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6026 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6028 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6029 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6030 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6033 Double_t distance1 = TMath::Min(delta1,delta2);
6034 if (distance1>cdist1) continue; // cut on DCA linear approximation
6036 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6037 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6038 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6039 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6042 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6043 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6044 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6046 distance1 = TMath::Min(delta1,delta2);
6049 rkink = TMath::Sqrt(radius[0]);
6052 rkink = TMath::Sqrt(radius[1]);
6054 if (distance1>cdist2) continue;
6057 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6060 Int_t row0 = GetRowNumber(rkink);
6061 if (row0<10) continue;
6062 if (row0>150) continue;
6065 Float_t dens00=-1,dens01=-1;
6066 Float_t dens10=-1,dens11=-1;
6068 Int_t found,foundable,ishared;
6069 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6070 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6071 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6072 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6074 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6075 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6076 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6077 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6079 if (dens00<dens10 && dens01<dens11) continue;
6080 if (dens00>dens10 && dens01>dens11) continue;
6081 if (TMath::Max(dens00,dens10)<0.1) continue;
6082 if (TMath::Max(dens01,dens11)<0.3) continue;
6084 if (TMath::Min(dens00,dens10)>0.6) continue;
6085 if (TMath::Min(dens01,dens11)>0.6) continue;
6088 AliTPCseed * ktrack0, *ktrack1;
6097 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6098 AliExternalTrackParam paramm(*ktrack0);
6099 AliExternalTrackParam paramd(*ktrack1);
6100 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6103 kink->SetMother(paramm);
6104 kink->SetDaughter(paramd);
6107 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
6109 fkParam->Transform0to1(x,index);
6110 fkParam->Transform1to2(x,index);
6111 row0 = GetRowNumber(x[0]);
6113 if (kink->GetR()<100) continue;
6114 if (kink->GetR()>240) continue;
6115 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6116 if (kink->GetDistance()>cdist3) continue;
6117 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6118 if (dird<0) continue;
6120 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6121 if (dirm<0) continue;
6122 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6123 if (mpt<0.2) continue;
6126 //for high momenta momentum not defined well in first iteration
6127 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6128 if (qt>0.35) continue;
6131 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6132 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6134 kink->SetTPCDensity(dens00,0,0);
6135 kink->SetTPCDensity(dens01,0,1);
6136 kink->SetTPCDensity(dens10,1,0);
6137 kink->SetTPCDensity(dens11,1,1);
6138 kink->SetIndex(i,0);
6139 kink->SetIndex(j,1);
6142 kink->SetTPCDensity(dens10,0,0);
6143 kink->SetTPCDensity(dens11,0,1);
6144 kink->SetTPCDensity(dens00,1,0);
6145 kink->SetTPCDensity(dens01,1,1);
6146 kink->SetIndex(j,0);
6147 kink->SetIndex(i,1);
6150 if (mpt<1||kink->GetAngle(2)>0.1){
6151 // angle and densities not defined yet
6152 if (kink->GetTPCDensityFactor()<0.8) continue;
6153 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6154 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6155 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6156 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6158 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6159 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6160 criticalangle= 3*TMath::Sqrt(criticalangle);
6161 if (criticalangle>0.02) criticalangle=0.02;
6162 if (kink->GetAngle(2)<criticalangle) continue;
6165 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6166 Float_t shapesum =0;
6168 for ( Int_t row = row0-drow; row<row0+drow;row++){
6169 if (row<0) continue;
6170 if (row>155) continue;
6171 if (ktrack0->GetClusterPointer(row)){
6172 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6173 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6176 if (ktrack1->GetClusterPointer(row)){
6177 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6178 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6183 kink->SetShapeFactor(-1.);
6186 kink->SetShapeFactor(shapesum/sum);
6188 // esd->AddKink(kink);
6190 // kink->SetMother(paramm);
6191 //kink->SetDaughter(paramd);
6193 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6195 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6196 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6198 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6200 if (AliTPCReconstructor::StreamLevel()>1) {
6201 (*fDebugStreamer)<<"kinkLpt"<<
6209 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6213 kinks->AddLast(kink);
6219 // sort the kinks according quality - and refit them towards vertex
6221 Int_t nkinks = kinks->GetEntriesFast();
6222 Float_t *quality = new Float_t[nkinks];
6223 Int_t *indexes = new Int_t[nkinks];
6224 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6225 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6228 for (Int_t i=0;i<nkinks;i++){
6230 AliKink *kinkl = (AliKink*)kinks->At(i);
6232 // refit kinks towards vertex
6234 Int_t index0 = kinkl->GetIndex(0);
6235 Int_t index1 = kinkl->GetIndex(1);
6236 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6237 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6239 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6241 // Refit Kink under if too small angle
6243 if (kinkl->GetAngle(2)<0.05){
6244 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6245 Int_t row0 = kinkl->GetTPCRow0();
6246 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6249 Int_t last = row0-drow;
6250 if (last<40) last=40;
6251 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6252 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6255 Int_t first = row0+drow;
6256 if (first>130) first=130;
6257 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6258 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6260 if (seed0 && seed1){
6261 kinkl->SetStatus(1,8);
6262 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6263 row0 = GetRowNumber(kinkl->GetR());
6264 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6265 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6266 mothers[i]->SetPoolID(fLastSeedID);
6267 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6268 daughters[i]->SetPoolID(fLastSeedID);
6271 delete kinks->RemoveAt(i);
6272 if (seed0) MarkSeedFree( seed0 );
6273 if (seed1) MarkSeedFree( seed1 );
6276 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6277 delete kinks->RemoveAt(i);
6278 if (seed0) MarkSeedFree( seed0 );
6279 if (seed1) MarkSeedFree( seed1 );
6283 MarkSeedFree( seed0 );
6284 MarkSeedFree( seed1 );
6287 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6289 TMath::Sort(nkinks,quality,indexes,kFALSE);
6291 //remove double find kinks
6293 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6294 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6295 if (!kink0) continue;
6297 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6298 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6299 if (!kink0) continue;
6300 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6301 if (!kink1) continue;
6302 // if not close kink continue
6303 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6304 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6305 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6307 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6308 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6309 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6310 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6311 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6320 for (Int_t i=0;i<row0;i++){
6321 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6324 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6331 for (Int_t i=row0;i<158;i++){
6332 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6333 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6336 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6342 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6343 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6344 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6345 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6346 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6347 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6349 shared[kink0->GetIndex(0)]= kTRUE;
6350 shared[kink0->GetIndex(1)]= kTRUE;
6351 delete kinks->RemoveAt(indexes[ikink0]);
6355 shared[kink1->GetIndex(0)]= kTRUE;
6356 shared[kink1->GetIndex(1)]= kTRUE;
6357 delete kinks->RemoveAt(indexes[ikink1]);
6364 for (Int_t i=0;i<nkinks;i++){
6365 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6366 if (!kinkl) continue;
6367 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6368 Int_t index0 = kinkl->GetIndex(0);
6369 Int_t index1 = kinkl->GetIndex(1);
6370 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6371 kinkl->SetMultiple(usage[index0],0);
6372 kinkl->SetMultiple(usage[index1],1);
6373 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6374 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6375 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6376 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6378 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6379 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6380 if (!ktrack0 || !ktrack1) continue;
6381 Int_t index = esd->AddKink(kinkl);
6384 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6385 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6386 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6387 *ktrack0 = *mothers[indexes[i]];
6388 *ktrack1 = *daughters[indexes[i]];
6392 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6393 ktrack1->SetKinkIndex(usage[index1], (index+1));
6398 // Remove tracks corresponding to shared kink's
6400 for (Int_t i=0;i<nentries;i++){
6401 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6402 if (!track0) continue;
6403 if (track0->GetKinkIndex(0)!=0) continue;
6404 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6409 RemoveUsed2(array,0.5,0.4,30);
6411 for (Int_t i=0;i<nentries;i++){
6412 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6413 if (!track0) continue;
6414 track0->CookdEdx(0.02,0.6);
6418 for (Int_t i=0;i<nentries;i++){
6419 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6420 if (!track0) continue;
6421 if (track0->Pt()<1.4) continue;
6422 //remove double high momenta tracks - overlapped with kink candidates
6425 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6426 if (track0->GetClusterPointer(icl)!=0){
6428 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6431 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6432 MarkSeedFree( array->RemoveAt(i) );
6436 if (track0->GetKinkIndex(0)!=0) continue;
6437 if (track0->GetNumberOfClusters()<80) continue;
6439 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6440 pmother->SetPoolID(fLastSeedID);
6441 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6442 pdaughter->SetPoolID(fLastSeedID);
6443 AliKink *pkink = new AliKink;
6445 AliTPCseed & mother = *pmother;
6446 AliTPCseed & daughter = *pdaughter;
6447 AliKink & kinkl = *pkink;
6448 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6449 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6450 MarkSeedFree( pmother );
6451 MarkSeedFree( pdaughter );
6453 continue; //too short tracks
6455 if (mother.Pt()<1.4) {
6456 MarkSeedFree( pmother );
6457 MarkSeedFree( pdaughter );
6461 Int_t row0= kinkl.GetTPCRow0();
6462 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6463 MarkSeedFree( pmother );
6464 MarkSeedFree( pdaughter );
6469 Int_t index = esd->AddKink(&kinkl);
6470 mother.SetKinkIndex(0,-(index+1));
6471 daughter.SetKinkIndex(0,index+1);
6472 if (mother.GetNumberOfClusters()>50) {
6473 MarkSeedFree( array->RemoveAt(i) );
6474 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6475 mtc->SetPoolID(fLastSeedID);
6476 array->AddAt(mtc,i);
6479 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6480 mtc->SetPoolID(fLastSeedID);
6481 array->AddLast(mtc);
6483 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6484 dtc->SetPoolID(fLastSeedID);
6485 array->AddLast(dtc);
6486 for (Int_t icl=0;icl<row0;icl++) {
6487 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6490 for (Int_t icl=row0;icl<158;icl++) {
6491 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6495 MarkSeedFree( pmother );
6496 MarkSeedFree( pdaughter );
6500 delete [] daughters;
6522 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6527 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6530 // refit kink towards to the vertex
6533 AliKink &kink=(AliKink &)knk;
6535 Int_t row0 = GetRowNumber(kink.GetR());
6536 FollowProlongation(mother,0);
6537 mother.Reset(kFALSE);
6539 FollowProlongation(daughter,row0);
6540 daughter.Reset(kFALSE);
6541 FollowBackProlongation(daughter,158);
6542 daughter.Reset(kFALSE);
6543 Int_t first = TMath::Max(row0-20,30);
6544 Int_t last = TMath::Min(row0+20,140);
6546 const Int_t kNdiv =5;
6547 AliTPCseed param0[kNdiv]; // parameters along the track
6548 AliTPCseed param1[kNdiv]; // parameters along the track
6549 AliKink kinks[kNdiv]; // corresponding kink parameters
6552 for (Int_t irow=0; irow<kNdiv;irow++){
6553 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
6555 // store parameters along the track
6557 for (Int_t irow=0;irow<kNdiv;irow++){
6558 FollowBackProlongation(mother, rows[irow]);
6559 FollowProlongation(daughter,rows[kNdiv-1-irow]);
6560 param0[irow] = mother;
6561 param1[kNdiv-1-irow] = daughter;
6565 for (Int_t irow=0; irow<kNdiv-1;irow++){
6566 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
6567 kinks[irow].SetMother(param0[irow]);
6568 kinks[irow].SetDaughter(param1[irow]);
6569 kinks[irow].Update();
6572 // choose kink with best "quality"
6574 Double_t mindist = 10000;
6575 for (Int_t irow=0;irow<kNdiv;irow++){
6576 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
6577 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6578 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
6580 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
6581 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
6582 if (normdist < mindist){
6588 if (index==-1) return 0;
6591 param0[index].Reset(kTRUE);
6592 FollowProlongation(param0[index],0);
6594 mother = param0[index];
6595 daughter = param1[index]; // daughter in vertex
6597 kink.SetMother(mother);
6598 kink.SetDaughter(daughter);
6600 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
6601 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6602 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6603 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
6604 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
6605 mother.SetLabel(kink.GetLabel(0));
6606 daughter.SetLabel(kink.GetLabel(1));
6612 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
6614 // update Kink quality information for mother after back propagation
6616 if (seed->GetKinkIndex(0)>=0) return;
6617 for (Int_t ikink=0;ikink<3;ikink++){
6618 Int_t index = seed->GetKinkIndex(ikink);
6619 if (index>=0) break;
6620 index = TMath::Abs(index)-1;
6621 AliESDkink * kink = fEvent->GetKink(index);
6622 kink->SetTPCDensity(-1,0,0);
6623 kink->SetTPCDensity(1,0,1);
6625 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6626 if (row0<15) row0=15;
6628 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6629 if (row1>145) row1=145;
6631 Int_t found,foundable,shared;
6632 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6633 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
6634 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6635 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
6640 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
6642 // update Kink quality information for daughter after refit
6644 if (seed->GetKinkIndex(0)<=0) return;
6645 for (Int_t ikink=0;ikink<3;ikink++){
6646 Int_t index = seed->GetKinkIndex(ikink);
6647 if (index<=0) break;
6648 index = TMath::Abs(index)-1;
6649 AliESDkink * kink = fEvent->GetKink(index);
6650 kink->SetTPCDensity(-1,1,0);
6651 kink->SetTPCDensity(-1,1,1);
6653 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6654 if (row0<15) row0=15;
6656 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6657 if (row1>145) row1=145;
6659 Int_t found,foundable,shared;
6660 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6661 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
6662 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6663 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
6669 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6672 // check kink point for given track
6673 // if return value=0 kink point not found
6674 // otherwise seed0 correspond to mother particle
6675 // seed1 correspond to daughter particle
6676 // kink parameter of kink point
6677 AliKink &kink=(AliKink &)knk;
6679 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
6680 Int_t first = seed->GetFirstPoint();
6681 Int_t last = seed->GetLastPoint();
6682 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
6685 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
6686 if (!seed1) return 0;
6687 FollowProlongation(*seed1,seed->GetLastPoint()-20);
6688 seed1->Reset(kTRUE);
6689 FollowProlongation(*seed1,158);
6690 seed1->Reset(kTRUE);
6691 last = seed1->GetLastPoint();
6693 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
6694 seed0->SetPoolID(fLastSeedID);
6695 seed0->Reset(kFALSE);
6698 AliTPCseed param0[20]; // parameters along the track
6699 AliTPCseed param1[20]; // parameters along the track
6700 AliKink kinks[20]; // corresponding kink parameters
6702 for (Int_t irow=0; irow<20;irow++){
6703 rows[irow] = first +((last-first)*irow)/19;
6705 // store parameters along the track
6707 for (Int_t irow=0;irow<20;irow++){
6708 FollowBackProlongation(*seed0, rows[irow]);
6709 FollowProlongation(*seed1,rows[19-irow]);
6710 param0[irow] = *seed0;
6711 param1[19-irow] = *seed1;
6715 for (Int_t irow=0; irow<19;irow++){
6716 kinks[irow].SetMother(param0[irow]);
6717 kinks[irow].SetDaughter(param1[irow]);
6718 kinks[irow].Update();
6721 // choose kink with biggest change of angle
6723 Double_t maxchange= 0;
6724 for (Int_t irow=1;irow<19;irow++){
6725 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6726 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
6727 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6728 if ( quality > maxchange){
6729 maxchange = quality;
6734 MarkSeedFree( seed0 );
6735 MarkSeedFree( seed1 );
6736 if (index<0) return 0;
6738 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
6739 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
6740 seed0->SetPoolID(fLastSeedID);
6741 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
6742 seed1->SetPoolID(fLastSeedID);
6743 seed0->Reset(kFALSE);
6744 seed1->Reset(kFALSE);
6745 seed0->ResetCovariance(10.);
6746 seed1->ResetCovariance(10.);
6747 FollowProlongation(*seed0,0);
6748 FollowBackProlongation(*seed1,158);
6749 mother = *seed0; // backup mother at position 0
6750 seed0->Reset(kFALSE);
6751 seed1->Reset(kFALSE);
6752 seed0->ResetCovariance(10.);
6753 seed1->ResetCovariance(10.);
6755 first = TMath::Max(row0-20,0);
6756 last = TMath::Min(row0+20,158);
6758 for (Int_t irow=0; irow<20;irow++){
6759 rows[irow] = first +((last-first)*irow)/19;
6761 // store parameters along the track
6763 for (Int_t irow=0;irow<20;irow++){
6764 FollowBackProlongation(*seed0, rows[irow]);
6765 FollowProlongation(*seed1,rows[19-irow]);
6766 param0[irow] = *seed0;
6767 param1[19-irow] = *seed1;
6771 for (Int_t irow=0; irow<19;irow++){
6772 kinks[irow].SetMother(param0[irow]);
6773 kinks[irow].SetDaughter(param1[irow]);
6774 // param0[irow].Dump();
6775 //param1[irow].Dump();
6776 kinks[irow].Update();
6779 // choose kink with biggest change of angle
6782 for (Int_t irow=0;irow<20;irow++){
6783 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
6784 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
6785 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6786 if ( quality > maxchange){
6787 maxchange = quality;
6794 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
6795 MarkSeedFree( seed0 );
6796 MarkSeedFree( seed1 );
6800 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
6802 kink.SetMother(param0[index]);
6803 kink.SetDaughter(param1[index]);
6806 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
6808 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
6809 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
6811 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
6813 if (AliTPCReconstructor::StreamLevel()>1) {
6814 (*fDebugStreamer)<<"kinkHpt"<<
6817 "p0.="<<¶m0[index]<<
6818 "p1.="<<¶m1[index]<<
6822 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6823 MarkSeedFree( seed0 );
6824 MarkSeedFree( seed1 );
6829 row0 = GetRowNumber(kink.GetR());
6830 kink.SetTPCRow0(row0);
6831 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
6832 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
6833 kink.SetIndex(-10,0);
6834 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
6835 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6836 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6839 // new (&mother) AliTPCseed(param0[index]);
6840 daughter = param1[index];
6841 daughter.SetLabel(kink.GetLabel(1));
6842 param0[index].Reset(kTRUE);
6843 FollowProlongation(param0[index],0);
6844 mother = param0[index];
6845 mother.SetLabel(kink.GetLabel(0));
6846 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
6849 MarkSeedFree( seed0 );
6850 MarkSeedFree( seed1 );
6858 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
6861 // reseed - refit - track
6864 // Int_t last = fSectors->GetNRows()-1;
6866 if (fSectors == fOuterSec){
6867 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
6871 first = t->GetFirstPoint();
6873 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
6874 FollowBackProlongation(*t,fSectors->GetNRows()-1);
6876 FollowProlongation(*t,first);
6886 //_____________________________________________________________________________
6887 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
6888 //-----------------------------------------------------------------
6889 // This function reades track seeds.
6890 //-----------------------------------------------------------------
6891 TDirectory *savedir=gDirectory;
6893 TFile *in=(TFile*)inp;
6894 if (!in->IsOpen()) {
6895 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
6900 TTree *seedTree=(TTree*)in->Get("Seeds");
6902 cerr<<"AliTPCtracker::ReadSeeds(): ";
6903 cerr<<"can't get a tree with track seeds !\n";
6906 AliTPCtrack *seed=new AliTPCtrack;
6907 seedTree->SetBranchAddress("tracks",&seed);
6909 if (fSeeds==0) fSeeds=new TObjArray(15000);
6911 Int_t n=(Int_t)seedTree->GetEntries();
6912 for (Int_t i=0; i<n; i++) {
6913 seedTree->GetEvent(i);
6914 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
6915 sdc->SetPoolID(fLastSeedID);
6916 fSeeds->AddLast(sdc);
6919 delete seed; // RS: this seed is not from the pool, delete it !!!
6925 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
6928 // clusters to tracks
6929 if (fSeeds) DeleteSeeds();
6930 else ResetSeedsPool();
6932 fEventHLT = hltEvent;
6934 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
6935 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
6936 transform->SetCurrentRun(esd->GetRunNumber());
6940 if (!fSeeds) return 1;
6942 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(0,fSeeds);
6947 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
6950 // clusters to tracks
6951 return Clusters2TracksHLT( esd, 0);
6954 //_____________________________________________________________________________
6955 Int_t AliTPCtracker::Clusters2Tracks() {
6956 //-----------------------------------------------------------------
6957 // This is a track finder.
6958 //-----------------------------------------------------------------
6959 TDirectory *savedir=gDirectory;
6963 fSeeds = Tracking();
6966 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6968 //activate again some tracks
6969 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6970 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6972 Int_t nc=t.GetNumberOfClusters();
6974 MarkSeedFree( fSeeds->RemoveAt(i) );
6978 if (pt->GetRemoval()==10) {
6979 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6980 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
6982 pt->Desactivate(20);
6983 MarkSeedFree( fSeeds->RemoveAt(i) );
6988 RemoveUsed2(fSeeds,0.85,0.85,0);
6989 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
6990 //FindCurling(fSeeds, fEvent,0);
6991 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
6992 RemoveUsed2(fSeeds,0.5,0.4,20);
6993 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
6994 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
6997 // // refit short tracks
6999 Int_t nseed=fSeeds->GetEntriesFast();
7002 for (Int_t i=0; i<nseed; i++) {
7003 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7005 Int_t nc=t.GetNumberOfClusters();
7007 MarkSeedFree( fSeeds->RemoveAt(i) );
7010 CookLabel(pt,0.1); //For comparison only
7011 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7012 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7014 if (fDebug>0) cerr<<found<<'\r';
7018 MarkSeedFree( fSeeds->RemoveAt(i) );
7022 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7024 //RemoveUsed(fSeeds,0.9,0.9,6);
7026 nseed=fSeeds->GetEntriesFast();
7028 for (Int_t i=0; i<nseed; i++) {
7029 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7031 Int_t nc=t.GetNumberOfClusters();
7033 MarkSeedFree( fSeeds->RemoveAt(i) );
7037 t.CookdEdx(0.02,0.6);
7038 // CheckKinkPoint(&t,0.05);
7039 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7040 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7048 MarkSeedFree( fSeeds->RemoveAt(i) );
7049 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7051 // FollowProlongation(*seed1,0);
7052 // Int_t n = seed1->GetNumberOfClusters();
7053 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7054 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7057 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7061 SortTracks(fSeeds, 1);
7065 PrepareForBackProlongation(fSeeds,5.);
7066 PropagateBack(fSeeds);
7067 printf("Time for back propagation: \t");timer.Print();timer.Start();
7071 PrepareForProlongation(fSeeds,5.);
7072 PropagateForard2(fSeeds);
7074 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7075 // RemoveUsed(fSeeds,0.7,0.7,6);
7076 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7078 nseed=fSeeds->GetEntriesFast();
7080 for (Int_t i=0; i<nseed; i++) {
7081 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7083 Int_t nc=t.GetNumberOfClusters();
7085 MarkSeedFree( fSeeds->RemoveAt(i) );
7088 t.CookdEdx(0.02,0.6);
7089 // CookLabel(pt,0.1); //For comparison only
7090 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7091 if ((pt->IsActive() || (pt->fRemoval==10) )){
7092 cerr<<found++<<'\r';
7095 MarkSeedFree( fSeeds->RemoveAt(i) );
7100 // fNTracks = found;
7102 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7105 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7106 Info("Clusters2Tracks","Number of found tracks %d",found);
7108 // UnloadClusters();
7113 void AliTPCtracker::Tracking(TObjArray * arr)
7116 // tracking of the seeds
7119 fSectors = fOuterSec;
7120 ParallelTracking(arr,150,63);
7121 fSectors = fOuterSec;
7122 ParallelTracking(arr,63,0);
7125 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7130 static TObjArray arrTracks;
7131 TObjArray * arr = &arrTracks;
7133 fSectors = fOuterSec;
7136 for (Int_t sec=0;sec<fkNOS;sec++){
7137 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7138 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7139 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7142 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7154 TObjArray * AliTPCtracker::Tracking()
7158 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7161 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7163 TObjArray * seeds = new TObjArray;
7165 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7166 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7167 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7175 Float_t fnumber = 3.0;
7176 Float_t fdensity = 3.0;
7179 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7180 arr = MakeSeedsHLT( fEventHLT );
7182 SumTracks(seeds,arr);
7185 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7186 //SignClusters(seeds,fnumber,fdensity);
7193 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7197 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7198 SumTracks(seeds,arr);
7199 SignClusters(seeds,fnumber,fdensity);
7201 for (Int_t i=2;i<6;i+=2){
7202 // seed high pt tracks
7205 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7206 SumTracks(seeds,arr);
7207 SignClusters(seeds,fnumber,fdensity);
7212 // RemoveUsed(seeds,0.9,0.9,1);
7213 // UnsignClusters();
7214 // SignClusters(seeds,fnumber,fdensity);
7218 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7220 // seed high pt tracks
7224 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7225 SumTracks(seeds,arr);
7226 SignClusters(seeds,fnumber,fdensity);
7231 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7232 SumTracks(seeds,arr);
7233 SignClusters(seeds,fnumber,fdensity);
7244 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7248 // RemoveUsed(seeds,0.75,0.75,1);
7250 //SignClusters(seeds,fnumber,fdensity);
7259 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7260 SumTracks(seeds,arr);
7261 SignClusters(seeds,fnumber,fdensity);
7263 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7264 SumTracks(seeds,arr);
7265 SignClusters(seeds,fnumber,fdensity);
7267 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7268 SumTracks(seeds,arr);
7269 SignClusters(seeds,fnumber,fdensity);
7271 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7272 SumTracks(seeds,arr);
7273 SignClusters(seeds,fnumber,fdensity);
7275 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7276 SumTracks(seeds,arr);
7277 SignClusters(seeds,fnumber,fdensity);
7280 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7281 SumTracks(seeds,arr);
7282 SignClusters(seeds,fnumber,fdensity);
7286 for (Int_t delta = 9; delta<30; delta+=gapSec){
7292 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7293 SumTracks(seeds,arr);
7294 SignClusters(seeds,fnumber,fdensity);
7296 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7297 SumTracks(seeds,arr);
7298 SignClusters(seeds,fnumber,fdensity);
7311 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7317 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7318 SumTracks(seeds,arr);
7319 SignClusters(seeds,fnumber,fdensity);
7321 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7322 SumTracks(seeds,arr);
7323 SignClusters(seeds,fnumber,fdensity);
7327 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7338 TObjArray * AliTPCtracker::TrackingSpecial()
7341 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7342 // no primary vertex seeding tried
7346 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7348 TObjArray * seeds = new TObjArray;
7353 Float_t fnumber = 3.0;
7354 Float_t fdensity = 3.0;
7357 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7358 cuts[1] = 3.5; // max tan(phi) angle for seeding
7359 cuts[2] = 3.; // not used (cut on z primary vertex)
7360 cuts[3] = 3.5; // max tan(theta) angle for seeding
7362 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7364 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7365 SumTracks(seeds,arr);
7366 SignClusters(seeds,fnumber,fdensity);
7370 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7381 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7384 //sum tracks to common container
7385 //remove suspicious tracks
7386 // RS: Attention: supplied tracks come in the static array, don't delete them
7387 Int_t nseed = arr2->GetEntriesFast();
7388 for (Int_t i=0;i<nseed;i++){
7389 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7392 // remove tracks with too big curvature
7394 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7395 MarkSeedFree( arr2->RemoveAt(i) );
7398 // REMOVE VERY SHORT TRACKS
7399 if (pt->GetNumberOfClusters()<20){
7400 MarkSeedFree( arr2->RemoveAt(i) );
7403 // NORMAL ACTIVE TRACK
7404 if (pt->IsActive()){
7405 arr1->AddLast(arr2->RemoveAt(i));
7408 //remove not usable tracks
7409 if (pt->GetRemoval()!=10){
7410 MarkSeedFree( arr2->RemoveAt(i) );
7414 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7415 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7416 arr1->AddLast(arr2->RemoveAt(i));
7418 MarkSeedFree( arr2->RemoveAt(i) );
7422 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7427 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7430 // try to track in parralel
7432 Int_t nseed=arr->GetEntriesFast();
7433 //prepare seeds for tracking
7434 for (Int_t i=0; i<nseed; i++) {
7435 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7437 if (!t.IsActive()) continue;
7438 // follow prolongation to the first layer
7439 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7440 FollowProlongation(t, rfirst+1);
7445 for (Int_t nr=rfirst; nr>=rlast; nr--){
7446 if (nr<fInnerSec->GetNRows())
7447 fSectors = fInnerSec;
7449 fSectors = fOuterSec;
7450 // make indexes with the cluster tracks for given
7452 // find nearest cluster
7453 for (Int_t i=0; i<nseed; i++) {
7454 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7456 if (nr==80) pt->UpdateReference();
7457 if (!pt->IsActive()) continue;
7458 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7459 if (pt->GetRelativeSector()>17) {
7462 UpdateClusters(t,nr);
7464 // prolonagate to the nearest cluster - if founded
7465 for (Int_t i=0; i<nseed; i++) {
7466 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7468 if (!pt->IsActive()) continue;
7469 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7470 if (pt->GetRelativeSector()>17) {
7473 FollowToNextCluster(*pt,nr);
7478 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7482 // if we use TPC track itself we have to "update" covariance
7484 Int_t nseed= arr->GetEntriesFast();
7485 for (Int_t i=0;i<nseed;i++){
7486 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7490 //rotate to current local system at first accepted point
7491 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
7492 Int_t sec = (index&0xff000000)>>24;
7494 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
7495 if (angle1>TMath::Pi())
7496 angle1-=2.*TMath::Pi();
7497 Float_t angle2 = pt->GetAlpha();
7499 if (TMath::Abs(angle1-angle2)>0.001){
7500 if (!pt->Rotate(angle1-angle2)) return;
7501 //angle2 = pt->GetAlpha();
7502 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
7503 //if (pt->GetAlpha()<0)
7504 // pt->fRelativeSector+=18;
7505 //sec = pt->fRelativeSector;
7514 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
7518 // if we use TPC track itself we have to "update" covariance
7520 Int_t nseed= arr->GetEntriesFast();
7521 for (Int_t i=0;i<nseed;i++){
7522 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7525 pt->SetFirstPoint(pt->GetLastPoint());
7533 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
7536 // make back propagation
7538 Int_t nseed= arr->GetEntriesFast();
7539 for (Int_t i=0;i<nseed;i++){
7540 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7541 if (pt&& pt->GetKinkIndex(0)<=0) {
7542 //AliTPCseed *pt2 = new AliTPCseed(*pt);
7543 fSectors = fInnerSec;
7544 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
7545 //fSectors = fOuterSec;
7546 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7547 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
7548 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
7549 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
7552 if (pt&& pt->GetKinkIndex(0)>0) {
7553 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
7554 pt->SetFirstPoint(kink->GetTPCRow0());
7555 fSectors = fInnerSec;
7556 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7564 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
7567 // make forward propagation
7569 Int_t nseed= arr->GetEntriesFast();
7571 for (Int_t i=0;i<nseed;i++){
7572 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7574 FollowProlongation(*pt,0,1,1);
7583 Int_t AliTPCtracker::PropagateForward()
7586 // propagate track forward
7588 Int_t nseed = fSeeds->GetEntriesFast();
7589 for (Int_t i=0;i<nseed;i++){
7590 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
7592 AliTPCseed &t = *pt;
7593 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
7594 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
7595 if (alpha < 0. ) alpha += 2.*TMath::Pi();
7596 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
7600 fSectors = fOuterSec;
7601 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
7602 fSectors = fInnerSec;
7603 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
7612 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
7615 // make back propagation, in between row0 and row1
7619 fSectors = fInnerSec;
7622 if (row1<fSectors->GetNRows())
7625 r1 = fSectors->GetNRows()-1;
7627 if (row0<fSectors->GetNRows()&& r1>0 )
7628 FollowBackProlongation(*pt,r1);
7629 if (row1<=fSectors->GetNRows())
7632 r1 = row1 - fSectors->GetNRows();
7633 if (r1<=0) return 0;
7634 if (r1>=fOuterSec->GetNRows()) return 0;
7635 fSectors = fOuterSec;
7636 return FollowBackProlongation(*pt,r1);
7644 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
7646 // gets cluster shape
7648 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
7649 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
7650 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
7651 Double_t angulary = seed->GetSnp();
7653 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
7654 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
7657 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
7658 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
7660 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
7661 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
7662 seed->SetCurrentSigmaY2(sigmay*sigmay);
7663 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
7664 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
7665 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
7666 // Float_t padlength = GetPadPitchLength(row);
7668 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
7669 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
7671 // Float_t sresz = fkParam->GetZSigma();
7672 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
7674 Float_t wy = GetSigmaY(seed);
7675 Float_t wz = GetSigmaZ(seed);
7678 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
7679 printf("problem\n");
7686 //__________________________________________________________________________
7687 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
7688 //--------------------------------------------------------------------
7689 //This function "cooks" a track label. If label<0, this track is fake.
7690 //--------------------------------------------------------------------
7691 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
7693 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
7697 Int_t noc=t->GetNumberOfClusters();
7699 //printf("\nnot founded prolongation\n\n\n");
7705 AliTPCclusterMI *clusters[160];
7707 for (Int_t i=0;i<160;i++) {
7714 for (i=0; i<160 && current<noc; i++) {
7716 Int_t index=t->GetClusterIndex2(i);
7717 if (index<=0) continue;
7718 if (index&0x8000) continue;
7720 //clusters[current]=GetClusterMI(index);
7721 if (t->GetClusterPointer(i)){
7722 clusters[current]=t->GetClusterPointer(i);
7728 Int_t lab=123456789;
7729 for (i=0; i<noc; i++) {
7730 AliTPCclusterMI *c=clusters[i];
7732 lab=TMath::Abs(c->GetLabel(0));
7734 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7740 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7742 for (i=0; i<noc; i++) {
7743 AliTPCclusterMI *c=clusters[i];
7745 if (TMath::Abs(c->GetLabel(1)) == lab ||
7746 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7748 if (noc<=0) { lab=-1; return;}
7749 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7752 Int_t tail=Int_t(0.10*noc);
7755 for (i=1; i<160&&ind<tail; i++) {
7756 // AliTPCclusterMI *c=clusters[noc-i];
7757 AliTPCclusterMI *c=clusters[i];
7759 if (lab == TMath::Abs(c->GetLabel(0)) ||
7760 lab == TMath::Abs(c->GetLabel(1)) ||
7761 lab == TMath::Abs(c->GetLabel(2))) max++;
7764 if (max < Int_t(0.5*tail)) lab=-lab;
7771 //delete[] clusters;
7775 //__________________________________________________________________________
7776 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
7777 //--------------------------------------------------------------------
7778 //This function "cooks" a track label. If label<0, this track is fake.
7779 //--------------------------------------------------------------------
7780 Int_t noc=t->GetNumberOfClusters();
7782 //printf("\nnot founded prolongation\n\n\n");
7788 AliTPCclusterMI *clusters[160];
7790 for (Int_t i=0;i<160;i++) {
7797 for (i=0; i<160 && current<noc; i++) {
7798 if (i<first) continue;
7799 if (i>last) continue;
7800 Int_t index=t->GetClusterIndex2(i);
7801 if (index<=0) continue;
7802 if (index&0x8000) continue;
7804 //clusters[current]=GetClusterMI(index);
7805 if (t->GetClusterPointer(i)){
7806 clusters[current]=t->GetClusterPointer(i);
7811 //if (noc<5) return -1;
7812 Int_t lab=123456789;
7813 for (i=0; i<noc; i++) {
7814 AliTPCclusterMI *c=clusters[i];
7816 lab=TMath::Abs(c->GetLabel(0));
7818 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7824 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7826 for (i=0; i<noc; i++) {
7827 AliTPCclusterMI *c=clusters[i];
7829 if (TMath::Abs(c->GetLabel(1)) == lab ||
7830 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7832 if (noc<=0) { lab=-1; return -1;}
7833 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7836 Int_t tail=Int_t(0.10*noc);
7839 for (i=1; i<160&&ind<tail; i++) {
7840 // AliTPCclusterMI *c=clusters[noc-i];
7841 AliTPCclusterMI *c=clusters[i];
7843 if (lab == TMath::Abs(c->GetLabel(0)) ||
7844 lab == TMath::Abs(c->GetLabel(1)) ||
7845 lab == TMath::Abs(c->GetLabel(2))) max++;
7848 if (max < Int_t(0.5*tail)) lab=-lab;
7851 // t->SetLabel(lab);
7855 //delete[] clusters;
7859 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
7861 //return pad row number for given x vector
7862 Float_t phi = TMath::ATan2(x[1],x[0]);
7863 if(phi<0) phi=2.*TMath::Pi()+phi;
7864 // Get the local angle in the sector philoc
7865 const Float_t kRaddeg = 180/3.14159265358979312;
7866 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
7867 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
7868 return GetRowNumber(localx);
7873 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
7875 //-----------------------------------------------------------------------
7876 // Fill the cluster and sharing bitmaps of the track
7877 //-----------------------------------------------------------------------
7879 Int_t firstpoint = 0;
7880 Int_t lastpoint = 159;
7881 AliTPCTrackerPoint *point;
7882 AliTPCclusterMI *cluster;
7885 TBits clusterMap(159);
7886 TBits sharedMap(159);
7888 for (int iter=firstpoint; iter<lastpoint; iter++) {
7889 // Change to cluster pointers to see if we have a cluster at given padrow
7891 cluster = t->GetClusterPointer(iter);
7893 clusterMap.SetBitNumber(iter, kTRUE);
7894 point = t->GetTrackPoint(iter);
7895 if (point->IsShared())
7896 sharedMap.SetBitNumber(iter,kTRUE);
7898 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
7899 fitMap.SetBitNumber(iter, kTRUE);
7903 esd->SetTPCClusterMap(clusterMap);
7904 esd->SetTPCSharedMap(sharedMap);
7905 esd->SetTPCFitMap(fitMap);
7906 if (nclsf != t->GetNumberOfClusters())
7907 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
7910 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
7912 // return flag if there is findable cluster at given position
7915 Float_t z = track.GetZ();
7917 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
7918 TMath::Abs(z)<fkParam->GetZLength(0) &&
7919 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
7925 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
7927 // Adding systematic error estimate to the covariance matrix
7928 // !!!! the systematic error for element 4 is in 1/GeV
7929 // 03.03.2012 MI changed in respect to the previous versions
7930 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7932 // use only the diagonal part if not specified otherwise
7933 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
7935 Double_t *covarS= (Double_t*)seed->GetCovariance();
7936 Double_t factor[5]={1,1,1,1,1};
7937 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
7938 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
7939 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
7940 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
7941 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
7943 factor[0]=factor[2];
7944 factor[4]=factor[2];
7950 for (Int_t i=0; i<5; i++){
7951 for (Int_t j=i; j<5; j++){
7952 Int_t index=seed->GetIndex(i,j);
7953 covarS[index]*=factor[i]*factor[j];
7959 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
7961 // Adding systematic error - as additive factor without correlation
7963 // !!!! the systematic error for element 4 is in 1/GeV
7964 // 03.03.2012 MI changed in respect to the previous versions
7966 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7967 Double_t *covarIn= (Double_t*)seed->GetCovariance();
7969 for (Int_t i=0;i<15;i++) covar[i]=0;
7975 covar[0] = param[0]*param[0];
7976 covar[2] = param[1]*param[1];
7977 covar[5] = param[2]*param[2];
7978 covar[9] = param[3]*param[3];
7979 covar[14]= param[4]*param[4];
7981 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
7983 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
7984 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
7986 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
7987 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
7988 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
7990 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
7991 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
7992 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
7993 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
7995 seed->AddCovariance(covar);
7998 //_____________________________________________________________________________
7999 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8002 // check events affected by TPC HV dip
8004 if(!esdEvent) return kFALSE;
8007 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8008 if(!db) return kFALSE;
8009 db->SetRun(esdEvent->GetRunNumber());
8011 // maximum allowed voltage before an event is identified as a dip event
8012 // and scanning period
8013 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8014 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8015 const Double_t tevSec = esdEvent->GetTimeStamp();
8017 for(Int_t sector=0; sector<72; sector++)
8019 // don't use excluded chambers, since the state is not defined at all
8020 if (!db->GetChamberHVStatus(sector)) continue;
8022 // get hv sensor of the chamber
8023 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8024 if (!sensor) continue;
8025 TGraph *grSensor=sensor->GetGraph();
8026 if (!grSensor) continue;
8027 if (grSensor->GetN()<1) continue;
8030 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8031 if(median < 1.) continue;
8033 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8034 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8035 if (tevSec-dipEventScanPeriod>nextTime) continue;
8036 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8037 if (deltaV>kTPCHVdip) {
8038 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8041 if (nextTime>tevSec+dipEventScanPeriod) break;
8048 //________________________________________
8049 void AliTPCtracker::MarkSeedFree(TObject *sd)
8051 // account that this seed is "deleted"
8052 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8054 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8057 int id = seed->GetPoolID();
8059 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8062 // AliInfo(Form("%d %p",id, seed));
8063 fSeedsPool->RemoveAt(id);
8064 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8065 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8068 //________________________________________
8069 TObject *&AliTPCtracker::NextFreeSeed()
8071 // return next free slot where the seed can be created
8072 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8073 // AliInfo(Form("%d",fLastSeedID));
8074 return (*fSeedsPool)[ fLastSeedID ];
8078 //________________________________________
8079 void AliTPCtracker::ResetSeedsPool()
8081 // mark all seeds in the pool as unused
8082 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8084 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8087 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8090 Double_t x= GetXrow(nrow);
8091 Double_t ymax= GetMaxY(nrow);
8097 if (!t.PropagateTo(x) ){
8098 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8104 Double_t y = t.GetY();
8106 if( rotate!=-1 ) rotate=1;
8107 } else if (y <-ymax) {
8108 if( rotate!=1 ) rotate = -1;
8110 if( rotate==0 ) break;
8111 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8112 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8113 //cout<<"can't rotate "<<endl;
8117 nRotations+= rotate;
8119 if( nRotations!=0 ){
8120 int newSec= t.GetRelativeSector()+nRotations;
8121 if( newSec>=fN ) newSec-=fN;
8122 else if( newSec<0 ) newSec +=fN;
8123 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8124 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8125 t.SetRelativeSector(newSec);
8130 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8133 // try to track in parralel
8135 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8138 Int_t nseed=arr->GetEntriesFast();
8139 //cout<<"Parallel tracking My.."<<endl;
8140 double shapeY2[160], shapeZ2[160];
8141 Int_t clusterIndex[160];
8143 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8144 //if( iSeed!=1 ) continue;
8145 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8149 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8153 for( int iter=0; iter<3; iter++ ){
8156 t.SetLastPoint(0); // first cluster in track position
8157 t.SetFirstPoint(nRows-1);
8158 t.ResetCovariance(.1);
8159 t.SetNumberOfClusters(0);
8160 for( int i=0; i<nRows; i++ ){
8164 t.SetClusterIndex2(i,-1);
8165 t.SetClusterIndex(i,-1);
8168 // pick up the clusters
8170 Double_t roady = 20.;
8171 Double_t roadz = 20.;
8178 t0.SetRelativeSector(t.GetRelativeSector());
8179 t0.SetLastPoint(0); // first cluster in track position
8180 t0.SetFirstPoint(159);
8181 for (Int_t nr=0; nr<nRows; nr++){
8182 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8183 else fSectors=fOuterSec;
8185 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8186 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8187 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8190 if (!IsActive(t0.GetRelativeSector(),nr)) {
8196 shapeY2[nr]=t0.GetCurrentSigmaY2();
8197 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8200 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8201 if( !krow ) continue;
8203 t.SetClusterIndex2(nr,-3); // foundable
8204 t.SetClusterIndex(nr,-3);
8206 AliTPCclusterMI *cl=0;
8208 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8210 double dy = cl->GetY()-t0.GetY();
8211 double dz = cl->GetZ()-t0.GetZ();
8212 double dr = sqrt(dy*dy+dz*dz);
8214 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8217 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8219 t0.SetClusterPointer(nr, cl);
8220 clusterIndex[nr] = krow.GetIndex(uindex);
8221 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8222 t0.SetLastPoint(nr);
8228 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8231 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8235 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8237 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8238 if( !t0.GetClusterPointer(nr) ) continue;
8239 int d = TMath::Abs(nr-midRow);
8247 // first fit 3 base points
8249 //cout<<"Fit3: "<<endl;
8250 for( int icl=0; icl<3; icl++){
8251 int nr = basePoints[icl];
8253 if( nr>=fInnerSec->GetNRows()){
8254 lr = nr - fInnerSec->GetNRows();
8256 } else fSectors=fInnerSec;
8258 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8260 //cout<<"WRONG!!!!"<<endl;
8263 int iSec = cl->GetDetector() %fkNIS;
8264 int rotate = iSec - t.GetRelativeSector();
8266 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8267 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8268 //cout<<"can't rotate "<<endl;
8271 t.SetRelativeSector(iSec);
8273 Double_t x= cl->GetX();
8274 if (!t.PropagateTo(x)){
8275 //cout<<"can't propagate to x="<<x<<endl;
8279 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8280 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8283 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8285 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8286 t.SetCurrentCluster(cl);
8289 t.SetErrorY2(shapeY2[nr]);
8290 t.SetErrorZ2(shapeZ2[nr]);
8293 for( int j=0; j<15; j++ ) cov[j]=0;
8299 t.AliExternalTrackParam::AddCovariance(cov);
8301 if( !UpdateTrack(&t,0) ){
8302 //cout<<"Can not update"<<endl;
8304 t.SetClusterIndex2(nr,-1);
8305 t.SetClusterIndex(nr,-1);
8306 t.SetClusterPointer(nr,0);
8309 //t.SetClusterPointer(nr, cl);
8312 //t.SetLastPoint(t0.GetLastPoint());
8313 //t.SetFirstPoint(t0.GetFirstPoint());
8315 //cout<<"Fit: "<<endl;
8316 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8318 if( nr>=fInnerSec->GetNRows()){
8319 lr = nr - fInnerSec->GetNRows();
8321 } else fSectors=fInnerSec;
8324 if( nr == basePoints[0] ) continue;
8325 if( nr == basePoints[1] ) continue;
8326 if( nr == basePoints[2] ) continue;
8328 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8331 int iSec = cl->GetDetector() %fkNIS;
8332 int rotate = iSec - t.GetRelativeSector();
8334 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8335 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8336 //cout<<"can't rotate "<<endl;
8339 t.SetRelativeSector(iSec);
8341 Double_t x= cl->GetX();
8342 if (!t.PropagateTo(x)){
8343 //cout<<"can't propagate to x="<<x<<endl;
8346 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8347 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8351 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8353 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8354 t.SetCurrentCluster(cl);
8356 t.SetErrorY2(shapeY2[nr]);
8357 t.SetErrorZ2(shapeZ2[nr]);
8359 if( !UpdateTrack(&t,0) ){
8360 //cout<<"Can not update"<<endl;
8362 t.SetClusterIndex2(nr,-1);
8363 t.SetClusterIndex(nr,-1);
8366 //t.SetClusterPointer(nr, cl);
8369 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8372 //cout<<"fitted track"<<iSeed<<endl;
8374 //cout<<"Statistics: "<<endl;
8375 Int_t foundable,found,shared;
8376 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8377 t.SetNFoundable(foundable);
8378 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8384 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8389 if( !hltEvent ) return 0;
8392 Int_t nentr=hltEvent->GetNumberOfTracks();
8394 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8396 TObjArray * seeds = new TObjArray(nentr);
8398 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8401 Int_t nTr=hltEvent->GetNumberOfTracks();
8403 for( int itr=0; itr<nTr; itr++ ){
8404 //if( itr!=97 ) continue;
8405 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8406 if( !param ) continue;
8407 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8408 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8410 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8411 tr.SetNumberOfClusters(0);
8412 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8414 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8415 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8416 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8418 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8419 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8421 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8422 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8424 seed->Rotate(alphaSec - alpha);
8426 seed->SetPoolID(fLastSeedID);
8427 seed->SetIsSeeding(kTRUE);
8428 seed->SetSeed1(nup-1);
8429 seed->SetSeed2(nup-2);
8430 seed->SetSeedType(0);
8431 seed->SetFirstPoint(-1);
8432 seed->SetLastPoint(-1);
8433 seeds->AddLast(seed); // note, track is seed, don't free the seed
8435 //if( index>3 ) break;
8439 fSectors = fOuterSec;
8441 TrackFollowingHLT(seeds );
8443 nTr = seeds->GetEntriesFast();
8444 for( int itr=0; itr<nTr; itr++ ){
8445 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8446 if( !seed ) continue;
8447 //FollowBackProlongation(*seed,0);
8448 // cout<<seed->GetNumberOfClusters()<<endl;
8449 Int_t foundable,found,shared;
8450 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8451 seed->SetNFoundable(foundable);
8452 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8453 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8454 //MarkSeedFree(seeds->RemoveAt(itr));
8457 if (seed->GetNumberOfClusters()<30 ||
8458 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8459 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8460 MarkSeedFree(seeds->RemoveAt(itr));
8464 for( int ir=0; ir<nup; ir++){
8465 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8469 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8473 void AliTPCtracker::FillClusterOccupancyInfo()
8475 //fill the cluster occupancy info into the ESD friend
8476 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8477 if (!esdFriend) return;
8479 for (Int_t isector=0; isector<18; isector++){
8480 AliTPCtrackerSector &iroc = fInnerSec[isector];
8481 AliTPCtrackerSector &oroc = fOuterSec[isector];
8483 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
8484 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
8485 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
8486 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
8487 //clusters used in tracking
8488 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
8489 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
8490 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
8491 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));