1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 //-------------------------------------------------------
18 // Implementation of the TPC tracker
20 // Origin: Marian Ivanov Marian.Ivanov@cern.ch
22 // AliTPC parallel tracker
24 // The track fitting is based on Kalman filtering approach
26 // The track finding steps:
27 // 1. Seeding - with and without vertex constraint
28 // - seeding with vertex constain done at first n^2 proble
29 // - seeding without vertex constraint n^3 problem
30 // 2. Tracking - follow prolongation road - find cluster - update kalman track
32 // The seeding and tracking is repeated several times, in different seeding region.
33 // This approach enables to find the track which cannot be seeded in some region of TPC
34 // This can happen because of low momenta (track do not reach outer radius), or track is currently in the ded region between sectors, or the track is for the moment overlapped with other track (seed quality is poor) ...
36 // With this approach we reach almost 100 % efficiency also for high occupancy events.
37 // (If the seeding efficiency in a region is about 90 % than with logical or of several
38 // regions we will reach 100% (in theory - supposing independence)
40 // Repeating several seeding - tracking procedures some of the tracks can be find
43 // The procedures to remove multi find tacks are impremented:
44 // RemoveUsed2 - fast procedure n problem -
45 // Algorithm - Sorting tracks according quality
46 // remove tracks with some shared fraction
47 // Sharing in respect to all tacks
48 // Signing clusters in gold region
49 // FindSplitted - slower algorithm n^2
50 // Sort the tracks according quality
51 // Loop over pair of tracks
52 // If overlap with other track bigger than threshold - remove track
54 // FindCurling - Finds the pair of tracks which are curling
55 // - About 10% of tracks can be find with this procedure
56 // The combinatorial background is too big to be used in High
57 // multiplicity environment
58 // - n^2 problem - Slow procedure - currently it is disabled because of
61 // The number of splitted tracks can be reduced disabling the sharing of the cluster.
62 // tpcRecoParam-> SetClusterSharing(kFALSE);
63 // IT IS HIGHLY non recomended to use it in high flux enviroonment
64 // Even using this switch some tracks can be found more than once
65 // (because of multiple seeding and low quality tracks which will not cross full chamber)
68 // The tracker itself can be debugged - the information about tracks can be stored in several // phases of the reconstruction
69 // To enable storage of the TPC tracks in the ESD friend track
70 // use AliTPCReconstructor::SetStreamLevel(n);
72 // The debug level - different procedure produce tree for numerical debugging
73 // To enable them set AliTPCReconstructor::SetStreamLevel(n); where nis bigger 1
77 // Adding systematic errors to the covariance:
79 // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
80 // of the tracks (not to the clusters as they are dependent):
81 // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
82 // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
83 // The default values are 0.
85 // The sytematic errors are added to the covariance matrix in following places:
87 // 1. During fisrt itteration - AliTPCtracker::FillESD
88 // 2. Second iteration -
89 // 2.a ITS->TPC - AliTPCtracker::ReadSeeds
90 // 2.b TPC->TRD - AliTPCtracker::PropagateBack
91 // 3. Third iteration -
92 // 3.a TRD->TPC - AliTPCtracker::ReadSeeds
93 // 3.b TPC->ITS - AliTPCtracker::RefitInward
95 // There are several places in the code which can be numerically debuged
96 // This code is keeped in order to enable code development and to check the calibration implementtion
98 // 1. ErrParam stream - dump information about
100 // 2.a) cluster error estimate
101 // 3.a) cluster shape estimate
104 // Debug streamer levels:
106 //-------------------------------------------------------
111 #include "Riostream.h"
112 #include <TClonesArray.h>
114 #include <TObjArray.h>
116 #include <TGraphErrors.h>
117 #include <TTimeStamp.h>
119 #include "AliComplexCluster.h"
120 #include "AliESDEvent.h"
121 #include "AliESDtrack.h"
122 #include "AliESDVertex.h"
125 #include "AliHelix.h"
126 #include "AliRunLoader.h"
127 #include "AliTPCClustersRow.h"
128 #include "AliTPCParam.h"
129 #include "AliTPCReconstructor.h"
130 #include "AliTPCpolyTrack.h"
131 #include "AliTPCreco.h"
132 #include "AliTPCseed.h"
134 #include "AliTPCtrackerSector.h"
135 #include "AliTPCtracker.h"
136 #include "TStopwatch.h"
137 #include "AliTPCReconstructor.h"
138 #include "AliAlignObj.h"
139 #include "AliTrackPointArray.h"
141 #include "AliTPCcalibDB.h"
142 #include "AliTPCcalibDButil.h"
143 #include "AliTPCTransform.h"
144 #include "AliTPCClusterParam.h"
145 #include "AliTPCdEdxInfo.h"
146 #include "AliDCSSensorArray.h"
147 #include "AliDCSSensor.h"
149 #include "AliCosmicTracker.h"
155 ClassImp(AliTPCtracker)
159 class AliTPCFastMath {
162 static Double_t FastAsin(Double_t x);
164 static Double_t fgFastAsin[20000]; //lookup table for fast asin computation
167 Double_t AliTPCFastMath::fgFastAsin[20000];
168 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
170 AliTPCFastMath::AliTPCFastMath(){
172 // initialized lookup table;
173 for (Int_t i=0;i<10000;i++){
174 fgFastAsin[2*i] = TMath::ASin(i/10000.);
175 fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
179 Double_t AliTPCFastMath::FastAsin(Double_t x){
181 // return asin using lookup table
183 Int_t index = int(x*10000);
184 return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
187 Int_t index = int(x*10000);
188 return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
190 //__________________________________________________________________
191 AliTPCtracker::AliTPCtracker()
219 // default constructor
221 for (Int_t irow=0; irow<200; irow++){
228 //_____________________________________________________________________
232 Int_t AliTPCtracker::UpdateTrack(AliTPCseed * track, Int_t accept){
234 //update track information using current cluster - track->fCurrentCluster
237 AliTPCclusterMI* c =track->GetCurrentCluster();
238 if (accept > 0) //sign not accepted clusters
239 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);
240 else // unsign accpeted clusters
241 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);
242 UInt_t i = track->GetCurrentClusterIndex1();
244 Int_t sec=(i&0xff000000)>>24;
245 //Int_t row = (i&0x00ff0000)>>16;
246 track->SetRow((i&0x00ff0000)>>16);
247 track->SetSector(sec);
248 // Int_t index = i&0xFFFF;
249 if (sec>=fkParam->GetNInnerSector()) track->SetRow(track->GetRow()+fkParam->GetNRowLow());
250 track->SetClusterIndex2(track->GetRow(), i);
251 //track->fFirstPoint = row;
252 //if ( track->fLastPoint<row) track->fLastPoint =row;
253 // if (track->fRow<0 || track->fRow>160) {
254 // printf("problem\n");
256 if (track->GetFirstPoint()>track->GetRow())
257 track->SetFirstPoint(track->GetRow());
258 if (track->GetLastPoint()<track->GetRow())
259 track->SetLastPoint(track->GetRow());
262 track->SetClusterPointer(track->GetRow(),c);
265 Double_t angle2 = track->GetSnp()*track->GetSnp();
267 //SET NEW Track Point
269 if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
271 angle2 = TMath::Sqrt(angle2/(1-angle2));
272 AliTPCTrackerPoint &point =*(track->GetTrackPoint(track->GetRow()));
274 point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
275 point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
276 point.SetErrY(sqrt(track->GetErrorY2()));
277 point.SetErrZ(sqrt(track->GetErrorZ2()));
279 point.SetX(track->GetX());
280 point.SetY(track->GetY());
281 point.SetZ(track->GetZ());
282 point.SetAngleY(angle2);
283 point.SetAngleZ(track->GetTgl());
284 if (point.IsShared()){
285 track->SetErrorY2(track->GetErrorY2()*4);
286 track->SetErrorZ2(track->GetErrorZ2()*4);
290 Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
292 // track->SetErrorY2(track->GetErrorY2()*1.3);
293 // track->SetErrorY2(track->GetErrorY2()+0.01);
294 // track->SetErrorZ2(track->GetErrorZ2()*1.3);
295 // track->SetErrorZ2(track->GetErrorZ2()+0.005);
297 if (accept>0) return 0;
298 if (track->GetNumberOfClusters()%20==0){
299 // if (track->fHelixIn){
300 // TClonesArray & larr = *(track->fHelixIn);
301 // Int_t ihelix = larr.GetEntriesFast();
302 // new(larr[ihelix]) AliHelix(*track) ;
305 if (AliTPCReconstructor::StreamLevel()>5) {
306 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
307 AliExternalTrackParam param(*track);
308 TTreeSRedirector &cstream = *fDebugStreamer;
314 track->SetNoCluster(0);
315 return track->Update(c,chi2,i);
320 Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
323 // decide according desired precision to accept given
324 // cluster for tracking
326 seed->GetProlongation(cluster->GetX(),yt,zt);
327 Double_t sy2=ErrY2(seed,cluster);
328 Double_t sz2=ErrZ2(seed,cluster);
330 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
331 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
332 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
333 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
334 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
335 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
336 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
337 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
339 Double_t rdistance2 = rdistancey2+rdistancez2;
342 if (AliTPCReconstructor::StreamLevel()>2 && ( (fIteration>0)|| (seed->GetNumberOfClusters()>20))) {
343 // if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
344 Float_t rmsy2 = seed->GetCurrentSigmaY2();
345 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
346 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
347 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
348 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
349 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
350 AliExternalTrackParam param(*seed);
351 static TVectorD gcl(3),gtr(3);
353 param.GetXYZ(gcl.GetMatrixArray());
354 cluster->GetGlobalXYZ(gclf);
355 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
356 Int_t nclSeed=seed->GetNumberOfClusters();
358 if (AliTPCReconstructor::StreamLevel()>2) {
359 (*fDebugStreamer)<<"ErrParam"<<
360 "iter="<<fIteration<<
362 "nclSeed="<<nclSeed<<
374 "rmsy2p30="<<rmsy2p30<<
375 "rmsz2p30="<<rmsz2p30<<
376 "rmsy2p30R="<<rmsy2p30R<<
377 "rmsz2p30R="<<rmsz2p30R<<
378 // normalize distance -
379 "rdisty="<<rdistancey2<<
380 "rdistz="<<rdistancez2<<
381 "rdist="<<rdistance2<< //
385 //return 0; // temporary
386 if (rdistance2>32) return 3;
389 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
390 return 2; //suspisiouce - will be changed
392 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
393 // strict cut on overlaped cluster
394 return 2; //suspisiouce - will be changed
396 if ( (rdistancey2>1. || rdistancez2>6.25 )
397 && cluster->GetType()<0){
398 seed->SetNFoundable(seed->GetNFoundable()-1);
402 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
404 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
405 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
418 //_____________________________________________________________________________
419 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
421 fkNIS(par->GetNInnerSector()/2),
423 fkNOS(par->GetNOuterSector()/2),
446 //---------------------------------------------------------------------
447 // The main TPC tracker constructor
448 //---------------------------------------------------------------------
449 fInnerSec=new AliTPCtrackerSector[fkNIS];
450 fOuterSec=new AliTPCtrackerSector[fkNOS];
453 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
454 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
457 Int_t nrowlow = par->GetNRowLow();
458 Int_t nrowup = par->GetNRowUp();
461 for (i=0;i<nrowlow;i++){
462 fXRow[i] = par->GetPadRowRadiiLow(i);
463 fPadLength[i]= par->GetPadPitchLength(0,i);
464 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
468 for (i=0;i<nrowup;i++){
469 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
470 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
471 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
474 if (AliTPCReconstructor::StreamLevel()>0) {
475 fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
478 fSeedsPool = new TClonesArray("AliTPCseed",1000);
480 //________________________________________________________________________
481 AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
508 //------------------------------------
509 // dummy copy constructor
510 //------------------------------------------------------------------
512 for (Int_t irow=0; irow<200; irow++){
519 AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
521 //------------------------------
523 //--------------------------------------------------------------
526 //_____________________________________________________________________________
527 AliTPCtracker::~AliTPCtracker() {
528 //------------------------------------------------------------------
529 // TPC tracker destructor
530 //------------------------------------------------------------------
537 if (fDebugStreamer) delete fDebugStreamer;
538 if (fSeedsPool) delete fSeedsPool;
542 void AliTPCtracker::FillESD(const TObjArray* arr)
546 //fill esds using updated tracks
552 // write tracks to the event
553 // store index of the track
554 Int_t nseed=arr->GetEntriesFast();
555 //FindKinks(arr,fEvent);
556 for (Int_t i=0; i<nseed; i++) {
557 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
561 if (AliTPCReconstructor::StreamLevel()>1) {
562 (*fDebugStreamer)<<"Track0"<<
566 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
567 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
568 pt->PropagateTo(fkParam->GetInnerRadiusLow());
571 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
572 iotrack.~AliESDtrack();
573 new(&iotrack) AliESDtrack;
574 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
575 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
576 iotrack.SetTPCPoints(pt->GetPoints());
577 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
578 iotrack.SetV0Indexes(pt->GetV0Indexes());
579 // iotrack.SetTPCpid(pt->fTPCr);
580 //iotrack.SetTPCindex(i);
581 MakeESDBitmaps(pt, &iotrack);
582 fEvent->AddTrack(&iotrack);
586 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
587 iotrack.~AliESDtrack();
588 new(&iotrack) AliESDtrack;
589 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
590 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
591 iotrack.SetTPCPoints(pt->GetPoints());
592 //iotrack.SetTPCindex(i);
593 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
594 iotrack.SetV0Indexes(pt->GetV0Indexes());
595 MakeESDBitmaps(pt, &iotrack);
596 // iotrack.SetTPCpid(pt->fTPCr);
597 fEvent->AddTrack(&iotrack);
601 // short tracks - maybe decays
603 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
604 Int_t found,foundable,shared;
605 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
606 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
607 iotrack.~AliESDtrack();
608 new(&iotrack) AliESDtrack;
609 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
610 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
611 //iotrack.SetTPCindex(i);
612 iotrack.SetTPCPoints(pt->GetPoints());
613 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
614 iotrack.SetV0Indexes(pt->GetV0Indexes());
615 MakeESDBitmaps(pt, &iotrack);
616 //iotrack.SetTPCpid(pt->fTPCr);
617 fEvent->AddTrack(&iotrack);
622 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
623 Int_t found,foundable,shared;
624 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
625 if (found<20) continue;
626 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
628 iotrack.~AliESDtrack();
629 new(&iotrack) AliESDtrack;
630 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
631 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
632 iotrack.SetTPCPoints(pt->GetPoints());
633 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
634 iotrack.SetV0Indexes(pt->GetV0Indexes());
635 MakeESDBitmaps(pt, &iotrack);
636 //iotrack.SetTPCpid(pt->fTPCr);
637 //iotrack.SetTPCindex(i);
638 fEvent->AddTrack(&iotrack);
641 // short tracks - secondaties
643 if ( (pt->GetNumberOfClusters()>30) ) {
644 Int_t found,foundable,shared;
645 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
646 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
647 iotrack.~AliESDtrack();
648 new(&iotrack) AliESDtrack;
649 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
650 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
651 iotrack.SetTPCPoints(pt->GetPoints());
652 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
653 iotrack.SetV0Indexes(pt->GetV0Indexes());
654 MakeESDBitmaps(pt, &iotrack);
655 //iotrack.SetTPCpid(pt->fTPCr);
656 //iotrack.SetTPCindex(i);
657 fEvent->AddTrack(&iotrack);
662 if ( (pt->GetNumberOfClusters()>15)) {
663 Int_t found,foundable,shared;
664 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
665 if (found<15) continue;
666 if (foundable<=0) continue;
667 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
668 if (float(found)/float(foundable)<0.8) continue;
670 iotrack.~AliESDtrack();
671 new(&iotrack) AliESDtrack;
672 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
673 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
674 iotrack.SetTPCPoints(pt->GetPoints());
675 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
676 iotrack.SetV0Indexes(pt->GetV0Indexes());
677 MakeESDBitmaps(pt, &iotrack);
678 // iotrack.SetTPCpid(pt->fTPCr);
679 //iotrack.SetTPCindex(i);
680 fEvent->AddTrack(&iotrack);
684 // >> account for suppressed tracks in the kink indices (RS)
685 int nESDtracks = fEvent->GetNumberOfTracks();
686 for (int it=nESDtracks;it--;) {
687 AliESDtrack* esdTr = fEvent->GetTrack(it);
688 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
689 for (int ik=0;ik<3;ik++) {
691 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
692 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
694 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
697 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
701 // << account for suppressed tracks in the kink indices (RS)
702 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
710 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
713 // Use calibrated cluster error from OCDB
715 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
717 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
718 Int_t ctype = cl->GetType();
719 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
720 Double_t angle = seed->GetSnp()*seed->GetSnp();
721 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
722 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
724 erry2+=0.5; // edge cluster
728 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
729 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
730 erry2+=addErr*addErr;
731 seed->SetErrorY2(erry2);
735 //calculate look-up table at the beginning
736 // static Bool_t ginit = kFALSE;
737 // static Float_t gnoise1,gnoise2,gnoise3;
738 // static Float_t ggg1[10000];
739 // static Float_t ggg2[10000];
740 // static Float_t ggg3[10000];
741 // static Float_t glandau1[10000];
742 // static Float_t glandau2[10000];
743 // static Float_t glandau3[10000];
745 // static Float_t gcor01[500];
746 // static Float_t gcor02[500];
747 // static Float_t gcorp[500];
751 // if (ginit==kFALSE){
752 // for (Int_t i=1;i<500;i++){
753 // Float_t rsigma = float(i)/100.;
754 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
755 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
756 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
760 // for (Int_t i=3;i<10000;i++){
764 // Float_t amp = float(i);
765 // Float_t padlength =0.75;
766 // gnoise1 = 0.0004/padlength;
767 // Float_t nel = 0.268*amp;
768 // Float_t nprim = 0.155*amp;
769 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
770 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
771 // if (glandau1[i]>1) glandau1[i]=1;
772 // glandau1[i]*=padlength*padlength/12.;
776 // gnoise2 = 0.0004/padlength;
778 // nprim = 0.133*amp;
779 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
780 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
781 // if (glandau2[i]>1) glandau2[i]=1;
782 // glandau2[i]*=padlength*padlength/12.;
787 // gnoise3 = 0.0004/padlength;
789 // nprim = 0.133*amp;
790 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
791 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
792 // if (glandau3[i]>1) glandau3[i]=1;
793 // glandau3[i]*=padlength*padlength/12.;
801 // Int_t amp = int(TMath::Abs(cl->GetQ()));
803 // seed->SetErrorY2(1.);
807 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
808 // Int_t ctype = cl->GetType();
809 // Float_t padlength= GetPadPitchLength(seed->GetRow());
810 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
811 // angle2 = angle2/(1-angle2);
813 // //cluster "quality"
814 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
817 // if (fSectors==fInnerSec){
818 // snoise2 = gnoise1;
819 // res = ggg1[amp]*z+glandau1[amp]*angle2;
820 // if (ctype==0) res *= gcor01[rsigmay];
823 // res*= gcorp[rsigmay];
827 // if (padlength<1.1){
828 // snoise2 = gnoise2;
829 // res = ggg2[amp]*z+glandau2[amp]*angle2;
830 // if (ctype==0) res *= gcor02[rsigmay];
833 // res*= gcorp[rsigmay];
837 // snoise2 = gnoise3;
838 // res = ggg3[amp]*z+glandau3[amp]*angle2;
839 // if (ctype==0) res *= gcor02[rsigmay];
842 // res*= gcorp[rsigmay];
849 // res*=2.4; // overestimate error 2 times
853 // if (res<2*snoise2)
856 // seed->SetErrorY2(res);
864 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
867 // Use calibrated cluster error from OCDB
869 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
871 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
872 Int_t ctype = cl->GetType();
873 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
875 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
876 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
877 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
878 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
880 errz2+=0.5; // edge cluster
884 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
885 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
886 errz2+=addErr*addErr;
887 seed->SetErrorZ2(errz2);
893 // //seed->SetErrorY2(0.1);
895 // //calculate look-up table at the beginning
896 // static Bool_t ginit = kFALSE;
897 // static Float_t gnoise1,gnoise2,gnoise3;
898 // static Float_t ggg1[10000];
899 // static Float_t ggg2[10000];
900 // static Float_t ggg3[10000];
901 // static Float_t glandau1[10000];
902 // static Float_t glandau2[10000];
903 // static Float_t glandau3[10000];
905 // static Float_t gcor01[1000];
906 // static Float_t gcor02[1000];
907 // static Float_t gcorp[1000];
911 // if (ginit==kFALSE){
912 // for (Int_t i=1;i<1000;i++){
913 // Float_t rsigma = float(i)/100.;
914 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
915 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
916 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
920 // for (Int_t i=3;i<10000;i++){
924 // Float_t amp = float(i);
925 // Float_t padlength =0.75;
926 // gnoise1 = 0.0004/padlength;
927 // Float_t nel = 0.268*amp;
928 // Float_t nprim = 0.155*amp;
929 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
930 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
931 // if (glandau1[i]>1) glandau1[i]=1;
932 // glandau1[i]*=padlength*padlength/12.;
936 // gnoise2 = 0.0004/padlength;
938 // nprim = 0.133*amp;
939 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
940 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
941 // if (glandau2[i]>1) glandau2[i]=1;
942 // glandau2[i]*=padlength*padlength/12.;
947 // gnoise3 = 0.0004/padlength;
949 // nprim = 0.133*amp;
950 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
951 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
952 // if (glandau3[i]>1) glandau3[i]=1;
953 // glandau3[i]*=padlength*padlength/12.;
961 // Int_t amp = int(TMath::Abs(cl->GetQ()));
963 // seed->SetErrorY2(1.);
967 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
968 // Int_t ctype = cl->GetType();
969 // Float_t padlength= GetPadPitchLength(seed->GetRow());
971 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
972 // // if (angle2<0.6) angle2 = 0.6;
973 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
975 // //cluster "quality"
976 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
979 // if (fSectors==fInnerSec){
980 // snoise2 = gnoise1;
981 // res = ggg1[amp]*z+glandau1[amp]*angle2;
982 // if (ctype==0) res *= gcor01[rsigmaz];
985 // res*= gcorp[rsigmaz];
989 // if (padlength<1.1){
990 // snoise2 = gnoise2;
991 // res = ggg2[amp]*z+glandau2[amp]*angle2;
992 // if (ctype==0) res *= gcor02[rsigmaz];
995 // res*= gcorp[rsigmaz];
999 // snoise2 = gnoise3;
1000 // res = ggg3[amp]*z+glandau3[amp]*angle2;
1001 // if (ctype==0) res *= gcor02[rsigmaz];
1004 // res*= gcorp[rsigmaz];
1013 // if ((ctype<0) &&<70){
1018 // if (res<2*snoise2)
1020 // if (res>3) res =3;
1021 // seed->SetErrorZ2(res);
1029 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1031 //rotate to track "local coordinata
1032 Float_t x = seed->GetX();
1033 Float_t y = seed->GetY();
1034 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1037 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1038 if (!seed->Rotate(fSectors->GetAlpha()))
1040 } else if (y <-ymax) {
1041 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1042 if (!seed->Rotate(-fSectors->GetAlpha()))
1050 //_____________________________________________________________________________
1051 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1052 Double_t x2,Double_t y2,
1053 Double_t x3,Double_t y3) const
1055 //-----------------------------------------------------------------
1056 // Initial approximation of the track curvature
1057 //-----------------------------------------------------------------
1058 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1059 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1060 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1061 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1062 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1064 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1065 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1066 return -xr*yr/sqrt(xr*xr+yr*yr);
1071 //_____________________________________________________________________________
1072 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1073 Double_t x2,Double_t y2,
1074 Double_t x3,Double_t y3) const
1076 //-----------------------------------------------------------------
1077 // Initial approximation of the track curvature
1078 //-----------------------------------------------------------------
1084 Double_t det = x3*y2-x2*y3;
1085 if (TMath::Abs(det)<1e-10){
1089 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1090 Double_t x0 = x3*0.5-y3*u;
1091 Double_t y0 = y3*0.5+x3*u;
1092 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1098 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1099 Double_t x2,Double_t y2,
1100 Double_t x3,Double_t y3) const
1102 //-----------------------------------------------------------------
1103 // Initial approximation of the track curvature
1104 //-----------------------------------------------------------------
1110 Double_t det = x3*y2-x2*y3;
1111 if (TMath::Abs(det)<1e-10) {
1115 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1116 Double_t x0 = x3*0.5-y3*u;
1117 Double_t y0 = y3*0.5+x3*u;
1118 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1127 //_____________________________________________________________________________
1128 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1129 Double_t x2,Double_t y2,
1130 Double_t x3,Double_t y3) const
1132 //-----------------------------------------------------------------
1133 // Initial approximation of the track curvature times center of curvature
1134 //-----------------------------------------------------------------
1135 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1136 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1137 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1138 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1139 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1141 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1143 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1146 //_____________________________________________________________________________
1147 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1148 Double_t x2,Double_t y2,
1149 Double_t z1,Double_t z2) const
1151 //-----------------------------------------------------------------
1152 // Initial approximation of the tangent of the track dip angle
1153 //-----------------------------------------------------------------
1154 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1158 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1159 Double_t x2,Double_t y2,
1160 Double_t z1,Double_t z2, Double_t c) const
1162 //-----------------------------------------------------------------
1163 // Initial approximation of the tangent of the track dip angle
1164 //-----------------------------------------------------------------
1168 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1170 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1171 if (TMath::Abs(d*c*0.5)>1) return 0;
1172 // Double_t angle2 = TMath::ASin(d*c*0.5);
1173 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1174 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1176 angle2 = (z1-z2)*c/(angle2*2.);
1180 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1181 {//-----------------------------------------------------------------
1182 // This function find proloncation of a track to a reference plane x=x2.
1183 //-----------------------------------------------------------------
1187 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1191 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1192 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1196 Double_t dy = dx*(c1+c2)/(r1+r2);
1199 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1201 if (TMath::Abs(delta)>0.01){
1202 dz = x[3]*TMath::ASin(delta)/x[4];
1204 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1207 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1215 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1220 return LoadClusters();
1224 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1227 // load clusters to the memory
1228 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1229 Int_t lower = arr->LowerBound();
1230 Int_t entries = arr->GetEntriesFast();
1232 for (Int_t i=lower; i<entries; i++) {
1233 clrow = (AliTPCClustersRow*) arr->At(i);
1234 if(!clrow) continue;
1235 if(!clrow->GetArray()) continue;
1239 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1241 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1242 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1245 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1246 AliTPCtrackerRow * tpcrow=0;
1249 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1253 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1254 left = (sec-fkNIS*2)/fkNOS;
1257 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1258 for (Int_t j=0;j<tpcrow->GetN1();++j)
1259 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1262 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1263 for (Int_t j=0;j<tpcrow->GetN2();++j)
1264 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1266 clrow->GetArray()->Clear("C");
1275 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1278 // load clusters to the memory from one
1281 AliTPCclusterMI *clust=0;
1282 Int_t count[72][96] = { {0} , {0} };
1284 // loop over clusters
1285 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1286 clust = (AliTPCclusterMI*)arr->At(icl);
1287 if(!clust) continue;
1288 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1290 // transform clusters
1293 // count clusters per pad row
1294 count[clust->GetDetector()][clust->GetRow()]++;
1297 // insert clusters to sectors
1298 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1299 clust = (AliTPCclusterMI*)arr->At(icl);
1300 if(!clust) continue;
1302 Int_t sec = clust->GetDetector();
1303 Int_t row = clust->GetRow();
1305 // filter overlapping pad rows needed by HLT
1306 if(sec<fkNIS*2) { //IROCs
1307 if(row == 30) continue;
1310 if(row == 27 || row == 76) continue;
1315 // left = sec/fkNIS;
1316 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1319 // left = (sec-fkNIS*2)/fkNOS;
1320 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1324 // Load functions must be called behind LoadCluster(TClonesArray*)
1326 //LoadOuterSectors();
1327 //LoadInnerSectors();
1333 Int_t AliTPCtracker::LoadClusters()
1336 // load clusters to the memory
1337 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1339 // TTree * tree = fClustersArray.GetTree();
1340 AliInfo("LoadClusters()\n");
1342 TTree * tree = fInput;
1343 TBranch * br = tree->GetBranch("Segment");
1344 br->SetAddress(&clrow);
1346 // Conversion of pad, row coordinates in local tracking coords.
1347 // Could be skipped here; is already done in clusterfinder
1349 Int_t j=Int_t(tree->GetEntries());
1350 for (Int_t i=0; i<j; i++) {
1354 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1355 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1356 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1359 AliTPCtrackerRow * tpcrow=0;
1362 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1366 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1367 left = (sec-fkNIS*2)/fkNOS;
1370 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1371 for (Int_t k=0;k<tpcrow->GetN1();++k)
1372 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1375 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1376 for (Int_t k=0;k<tpcrow->GetN2();++k)
1377 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1384 if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1389 void AliTPCtracker::UnloadClusters()
1392 // unload clusters from the memory
1394 Int_t nrows = fOuterSec->GetNRows();
1395 for (Int_t sec = 0;sec<fkNOS;sec++)
1396 for (Int_t row = 0;row<nrows;row++){
1397 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1399 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1400 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1402 tpcrow->ResetClusters();
1405 nrows = fInnerSec->GetNRows();
1406 for (Int_t sec = 0;sec<fkNIS;sec++)
1407 for (Int_t row = 0;row<nrows;row++){
1408 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1410 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1411 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1413 tpcrow->ResetClusters();
1419 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1421 // Filling cluster to the array - For visualization purposes
1424 nrows = fOuterSec->GetNRows();
1425 for (Int_t sec = 0;sec<fkNOS;sec++)
1426 for (Int_t row = 0;row<nrows;row++){
1427 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1428 if (!tpcrow) continue;
1429 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1430 array->AddLast((TObject*)((*tpcrow)[icl]));
1433 nrows = fInnerSec->GetNRows();
1434 for (Int_t sec = 0;sec<fkNIS;sec++)
1435 for (Int_t row = 0;row<nrows;row++){
1436 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1437 if (!tpcrow) continue;
1438 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1439 array->AddLast((TObject*)(*tpcrow)[icl]);
1445 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1449 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1450 AliTPCTransform *transform = calibDB->GetTransform() ;
1452 AliFatal("Tranformations not in calibDB");
1455 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1456 Double_t x[3]={static_cast<Double_t>(cluster->GetRow()),static_cast<Double_t>(cluster->GetPad()),static_cast<Double_t>(cluster->GetTimeBin())};
1457 Int_t i[1]={cluster->GetDetector()};
1458 transform->Transform(x,i,0,1);
1459 // if (cluster->GetDetector()%36>17){
1464 // in debug mode check the transformation
1466 if (AliTPCReconstructor::StreamLevel()>2) {
1468 cluster->GetGlobalXYZ(gx);
1469 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1470 TTreeSRedirector &cstream = *fDebugStreamer;
1471 cstream<<"Transform"<<
1482 cluster->SetX(x[0]);
1483 cluster->SetY(x[1]);
1484 cluster->SetZ(x[2]);
1489 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1490 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1491 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1493 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1494 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1495 if (mat) mat->LocalToMaster(pos,posC);
1497 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1499 cluster->SetX(posC[0]);
1500 cluster->SetY(posC[1]);
1501 cluster->SetZ(posC[2]);
1505 void AliTPCtracker::ApplyTailCancellation(){
1507 // Correct the cluster charge for the ion tail effect
1508 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1512 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1513 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1514 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1515 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1516 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1517 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1519 // find the number of clusters for the whole TPC (nclALL)
1521 for (Int_t isector=0; isector<36; isector++){
1522 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1523 nclALL += sector.GetNClInSector(0);
1524 nclALL += sector.GetNClInSector(1);
1527 // start looping over all clusters
1528 for (Int_t iside=0; iside<2; iside++){ // loop over sides
1531 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
1532 // cache experimantal tuning factor for the different chamber type
1533 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
1534 std::cout << " ampfactor = " << ampfactor << std::endl;
1536 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
1539 // Cache time response functions and their positons to COG of the cluster
1540 TGraphErrors ** graphRes = new TGraphErrors *[20];
1541 Float_t * indexAmpGraphs = new Float_t[20];
1542 for (Int_t icache=0; icache<20; icache++)
1544 graphRes[icache] = NULL;
1545 indexAmpGraphs[icache] = 0;
1547 ///////////////////////////// --> position fo sie loop
1548 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
1553 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
1554 Int_t nrows = sector.GetNRows(); // number of rows
1555 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
1557 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1559 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1560 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1561 if (iside>0) ncl=tpcrow.GetN2();
1563 // Order clusters in time for the proper correction of ion tail
1564 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
1565 Float_t qMaxArray[ncl];
1566 Int_t sortedClusterIndex[ncl];
1567 Float_t sortedClusterTimeBin[ncl];
1568 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
1569 for (Int_t i=0;i<ncl;i++)
1573 sortedClusterIndex[i]=i;
1574 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1576 rowClusterArray->AddAt(rowcl,i);
1578 rowClusterArray->RemoveAt(i);
1580 // Fill the timebin info to the array in order to sort wrt tb
1582 sortedClusterTimeBin[i]=0.0;
1584 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
1588 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
1590 // Main cluster correction loops over clusters
1591 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
1593 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
1597 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
1599 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
1601 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
1602 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
1603 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
1605 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
1607 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
1608 Double_t ionTailMax=0.;
1609 Double_t ionTailTotal=0.;
1610 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
1611 ionTailMax=TMath::Abs(ionTailMax);
1612 ionTailTotal=TMath::Abs(ionTailTotal);
1613 qTotArray[icl0]+=ionTailTotal;
1614 qMaxArray[icl0]+=ionTailMax;
1616 // Dump some info for debugging while clusters are being corrected
1617 if (AliTPCReconstructor::StreamLevel()>2) {
1618 TTreeSRedirector &cstream = *fDebugStreamer;
1619 if (gRandom->Rndm() > 0.999){
1620 cstream<<"IonTail"<<
1621 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
1622 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
1623 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
1624 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
1627 }// dump the results to the debug streamer if in debug mode
1629 }//end of second loop over clusters
1631 // Set corrected values of the corrected cluster
1632 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
1633 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
1635 // Dump some info for debugging after clusters are corrected
1636 if (AliTPCReconstructor::StreamLevel()>2) {
1637 TTreeSRedirector &cstream = *fDebugStreamer;
1638 if (gRandom->Rndm() > 0.999){
1639 cstream<<"IonTailCorrected"<<
1640 "cl0.=" << cl0 << // cluster 0 with huge Qmax
1641 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
1642 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
1643 "nclALL=" << nclALL <<
1644 "nclSector=" << nclSector <<
1646 "nclPad=" << nclPad <<
1652 }// dump the results to the debug streamer if in debug mode
1654 }//end of first loop over cluster
1655 delete rowClusterArray;
1656 }//end of loop over rows
1657 for (int i=0; i<20; i++) delete graphRes[i];
1659 delete [] indexAmpGraphs;
1661 }//end of loop over sectors
1662 }//end of loop over IROC/OROC
1663 }// end of side loop
1665 //_____________________________________________________________________________
1666 void AliTPCtracker::GetTailValue(Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
1669 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
1672 const Double_t kMinPRF = 0.5; // minimal PRF width
1673 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
1674 ionTailMax = 0.; // correction value to be added to Qmax of cl0
1676 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
1677 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
1678 Int_t sectorPad = cl1->GetDetector(); // sector number
1679 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
1680 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
1681 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
1682 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
1683 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
1684 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
1687 Double_t sumAmp1=0.;
1688 for (Int_t idelta =-2; idelta<=2;idelta++){
1689 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
1692 Double_t sumAmp0=0.;
1693 for (Int_t idelta =-2; idelta<=2;idelta++){
1694 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
1697 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
1698 Int_t padScan=2; // +-2 pad-timebin window will be scanned
1699 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
1702 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
1703 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
1704 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
1706 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
1708 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
1709 for (Int_t j=0;j<20;j++) {
1710 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
1712 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
1716 if (!graphRes[ampIndex]) continue;
1717 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
1718 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
1720 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
1723 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
1725 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
1726 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
1727 Float_t qMaxPad0 = amp0*qTot0;
1729 // Add 5 timebin range contribution around the max peak (-+2 tb window)
1730 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
1732 if (itb<0) continue;
1733 if (itb>=graphRes[ampIndex]->GetN()) continue;
1735 // calculate contribution to qTot
1736 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
1737 if (ipad1!=padcl0) {
1738 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
1740 ionTailTotal += tailCorr; // for center pad
1742 // calculate contribution to qMax
1743 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
1745 } // end of tb correction loop which is applied over 5 tb range
1747 } // end of cl0 loop
1748 } // end of cl1 loop
1752 //_____________________________________________________________________________
1753 Int_t AliTPCtracker::LoadOuterSectors() {
1754 //-----------------------------------------------------------------
1755 // This function fills outer TPC sectors with clusters.
1756 //-----------------------------------------------------------------
1757 Int_t nrows = fOuterSec->GetNRows();
1759 for (Int_t sec = 0;sec<fkNOS;sec++)
1760 for (Int_t row = 0;row<nrows;row++){
1761 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1762 Int_t sec2 = sec+2*fkNIS;
1764 Int_t ncl = tpcrow->GetN1();
1766 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1767 index=(((sec2<<8)+row)<<16)+ncl;
1768 tpcrow->InsertCluster(c,index);
1771 ncl = tpcrow->GetN2();
1773 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1774 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1775 tpcrow->InsertCluster(c,index);
1778 // write indexes for fast acces
1780 for (Int_t i=0;i<510;i++)
1781 tpcrow->SetFastCluster(i,-1);
1782 for (Int_t i=0;i<tpcrow->GetN();i++){
1783 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1784 tpcrow->SetFastCluster(zi,i); // write index
1787 for (Int_t i=0;i<510;i++){
1788 if (tpcrow->GetFastCluster(i)<0)
1789 tpcrow->SetFastCluster(i,last);
1791 last = tpcrow->GetFastCluster(i);
1800 //_____________________________________________________________________________
1801 Int_t AliTPCtracker::LoadInnerSectors() {
1802 //-----------------------------------------------------------------
1803 // This function fills inner TPC sectors with clusters.
1804 //-----------------------------------------------------------------
1805 Int_t nrows = fInnerSec->GetNRows();
1807 for (Int_t sec = 0;sec<fkNIS;sec++)
1808 for (Int_t row = 0;row<nrows;row++){
1809 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1812 Int_t ncl = tpcrow->GetN1();
1814 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1815 index=(((sec<<8)+row)<<16)+ncl;
1816 tpcrow->InsertCluster(c,index);
1819 ncl = tpcrow->GetN2();
1821 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1822 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1823 tpcrow->InsertCluster(c,index);
1826 // write indexes for fast acces
1828 for (Int_t i=0;i<510;i++)
1829 tpcrow->SetFastCluster(i,-1);
1830 for (Int_t i=0;i<tpcrow->GetN();i++){
1831 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1832 tpcrow->SetFastCluster(zi,i); // write index
1835 for (Int_t i=0;i<510;i++){
1836 if (tpcrow->GetFastCluster(i)<0)
1837 tpcrow->SetFastCluster(i,last);
1839 last = tpcrow->GetFastCluster(i);
1851 //_________________________________________________________________________
1852 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
1853 //--------------------------------------------------------------------
1854 // Return pointer to a given cluster
1855 //--------------------------------------------------------------------
1856 if (index<0) return 0; // no cluster
1857 Int_t sec=(index&0xff000000)>>24;
1858 Int_t row=(index&0x00ff0000)>>16;
1859 Int_t ncl=(index&0x00007fff)>>00;
1861 const AliTPCtrackerRow * tpcrow=0;
1862 TClonesArray * clrow =0;
1864 if (sec<0 || sec>=fkNIS*4) {
1865 AliWarning(Form("Wrong sector %d",sec));
1870 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
1871 if (tracksec.GetNRows()<=row) return 0;
1872 tpcrow = &(tracksec[row]);
1873 if (tpcrow==0) return 0;
1876 if (tpcrow->GetN1()<=ncl) return 0;
1877 clrow = tpcrow->GetClusters1();
1880 if (tpcrow->GetN2()<=ncl) return 0;
1881 clrow = tpcrow->GetClusters2();
1885 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
1886 if (tracksec.GetNRows()<=row) return 0;
1887 tpcrow = &(tracksec[row]);
1888 if (tpcrow==0) return 0;
1890 if (sec-2*fkNIS<fkNOS) {
1891 if (tpcrow->GetN1()<=ncl) return 0;
1892 clrow = tpcrow->GetClusters1();
1895 if (tpcrow->GetN2()<=ncl) return 0;
1896 clrow = tpcrow->GetClusters2();
1900 return (AliTPCclusterMI*)clrow->At(ncl);
1906 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
1907 //-----------------------------------------------------------------
1908 // This function tries to find a track prolongation to next pad row
1909 //-----------------------------------------------------------------
1911 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
1914 AliTPCclusterMI *cl=0;
1915 Int_t tpcindex= t.GetClusterIndex2(nr);
1917 // update current shape info every 5 pad-row
1918 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1922 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
1924 if (tpcindex==-1) return 0; //track in dead zone
1925 if (tpcindex >= 0){ //
1926 cl = t.GetClusterPointer(nr);
1927 //if (cl==0) cl = GetClusterMI(tpcindex);
1928 if (!cl) cl = GetClusterMI(tpcindex);
1929 t.SetCurrentClusterIndex1(tpcindex);
1932 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
1933 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1935 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1936 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1938 if (TMath::Abs(angle-t.GetAlpha())>0.001){
1939 Double_t rotation = angle-t.GetAlpha();
1940 t.SetRelativeSector(relativesector);
1941 if (!t.Rotate(rotation)) {
1942 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1946 if (!t.PropagateTo(x)) {
1947 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1951 t.SetCurrentCluster(cl);
1953 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1954 if ((tpcindex&0x8000)==0) accept =0;
1956 //if founded cluster is acceptible
1957 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
1958 t.SetErrorY2(t.GetErrorY2()+0.03);
1959 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1960 t.SetErrorY2(t.GetErrorY2()*3);
1961 t.SetErrorZ2(t.GetErrorZ2()*3);
1963 t.SetNFoundable(t.GetNFoundable()+1);
1964 UpdateTrack(&t,accept);
1967 else { // Remove old cluster from track
1968 t.SetClusterIndex(nr, -3);
1969 t.SetClusterPointer(nr, 0);
1973 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
1974 if (fIteration>1 && IsFindable(t)){
1975 // not look for new cluster during refitting
1976 t.SetNFoundable(t.GetNFoundable()+1);
1981 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1982 if (!t.PropagateTo(x)) {
1983 if (fIteration==0) t.SetRemoval(10);
1986 Double_t y = t.GetY();
1987 if (TMath::Abs(y)>ymax){
1989 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1990 if (!t.Rotate(fSectors->GetAlpha()))
1992 } else if (y <-ymax) {
1993 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1994 if (!t.Rotate(-fSectors->GetAlpha()))
1997 if (!t.PropagateTo(x)) {
1998 if (fIteration==0) t.SetRemoval(10);
2004 Double_t z=t.GetZ();
2007 if (!IsActive(t.GetRelativeSector(),nr)) {
2009 t.SetClusterIndex2(nr,-1);
2012 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2013 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
2014 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
2016 if (!isActive || !isActive2) return 0;
2018 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2019 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
2021 Double_t roadz = 1.;
2023 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2025 t.SetClusterIndex2(nr,-1);
2031 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2032 t.SetNFoundable(t.GetNFoundable()+1);
2038 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2039 cl = krow.FindNearest2(y,z,roady,roadz,index);
2040 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2043 t.SetCurrentCluster(cl);
2045 if (fIteration==2&&cl->IsUsed(10)) return 0;
2046 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2047 if (fIteration==2&&cl->IsUsed(11)) {
2048 t.SetErrorY2(t.GetErrorY2()+0.03);
2049 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2050 t.SetErrorY2(t.GetErrorY2()*3);
2051 t.SetErrorZ2(t.GetErrorZ2()*3);
2054 if (t.fCurrentCluster->IsUsed(10)){
2059 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2065 if (accept<3) UpdateTrack(&t,accept);
2068 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2076 //_________________________________________________________________________
2077 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2079 // Get track space point by index
2080 // return false in case the cluster doesn't exist
2081 AliTPCclusterMI *cl = GetClusterMI(index);
2082 if (!cl) return kFALSE;
2083 Int_t sector = (index&0xff000000)>>24;
2084 // Int_t row = (index&0x00ff0000)>>16;
2086 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2087 xyz[0] = cl->GetX();
2088 xyz[1] = cl->GetY();
2089 xyz[2] = cl->GetZ();
2091 fkParam->AdjustCosSin(sector,cos,sin);
2092 Float_t x = cos*xyz[0]-sin*xyz[1];
2093 Float_t y = cos*xyz[1]+sin*xyz[0];
2095 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2096 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2097 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2098 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2099 cov[0] = sin*sin*sigmaY2;
2100 cov[1] = -sin*cos*sigmaY2;
2102 cov[3] = cos*cos*sigmaY2;
2105 p.SetXYZ(x,y,xyz[2],cov);
2106 AliGeomManager::ELayerID iLayer;
2108 if (sector < fkParam->GetNInnerSector()) {
2109 iLayer = AliGeomManager::kTPC1;
2113 iLayer = AliGeomManager::kTPC2;
2114 idet = sector - fkParam->GetNInnerSector();
2116 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2117 p.SetVolumeID(volid);
2123 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2124 //-----------------------------------------------------------------
2125 // This function tries to find a track prolongation to next pad row
2126 //-----------------------------------------------------------------
2127 t.SetCurrentCluster(0);
2128 t.SetCurrentClusterIndex1(-3);
2130 Double_t xt=t.GetX();
2131 Int_t row = GetRowNumber(xt)-1;
2132 Double_t ymax= GetMaxY(nr);
2134 if (row < nr) return 1; // don't prolongate if not information until now -
2135 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2137 // return 0; // not prolongate strongly inclined tracks
2139 // if (TMath::Abs(t.GetSnp())>0.95) {
2141 // return 0; // not prolongate strongly inclined tracks
2142 // }// patch 28 fev 06
2144 Double_t x= GetXrow(nr);
2146 //t.PropagateTo(x+0.02);
2147 //t.PropagateTo(x+0.01);
2148 if (!t.PropagateTo(x)){
2155 if (TMath::Abs(y)>ymax){
2157 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2158 if (!t.Rotate(fSectors->GetAlpha()))
2160 } else if (y <-ymax) {
2161 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2162 if (!t.Rotate(-fSectors->GetAlpha()))
2165 // if (!t.PropagateTo(x)){
2172 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2174 if (!IsActive(t.GetRelativeSector(),nr)) {
2176 t.SetClusterIndex2(nr,-1);
2179 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2181 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2183 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2185 t.SetClusterIndex2(nr,-1);
2191 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2192 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2198 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2199 // t.fCurrentSigmaY = GetSigmaY(&t);
2200 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2204 AliTPCclusterMI *cl=0;
2207 Double_t roady = 1.;
2208 Double_t roadz = 1.;
2212 index = t.GetClusterIndex2(nr);
2213 if ( (index >= 0) && (index&0x8000)==0){
2214 cl = t.GetClusterPointer(nr);
2215 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2216 t.SetCurrentClusterIndex1(index);
2218 t.SetCurrentCluster(cl);
2224 // if (index<0) return 0;
2225 UInt_t uindex = TMath::Abs(index);
2228 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2229 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2232 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2233 t.SetCurrentCluster(cl);
2239 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2240 //-----------------------------------------------------------------
2241 // This function tries to find a track prolongation to next pad row
2242 //-----------------------------------------------------------------
2244 //update error according neighborhoud
2246 if (t.GetCurrentCluster()) {
2248 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2250 if (t.GetCurrentCluster()->IsUsed(10)){
2255 t.SetNShared(t.GetNShared()+1);
2256 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2261 if (fIteration>0) accept = 0;
2262 if (accept<3) UpdateTrack(&t,accept);
2266 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2267 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2269 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2277 //_____________________________________________________________________________
2278 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2279 //-----------------------------------------------------------------
2280 // This function tries to find a track prolongation.
2281 //-----------------------------------------------------------------
2282 Double_t xt=t.GetX();
2284 Double_t alpha=t.GetAlpha();
2285 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2286 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2288 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2290 Int_t first = GetRowNumber(xt);
2295 for (Int_t nr= first; nr>=rf; nr-=step) {
2297 if (t.GetKinkIndexes()[0]>0){
2298 for (Int_t i=0;i<3;i++){
2299 Int_t index = t.GetKinkIndexes()[i];
2300 if (index==0) break;
2301 if (index<0) continue;
2303 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2305 printf("PROBLEM\n");
2308 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2310 AliExternalTrackParam paramd(t);
2311 kink->SetDaughter(paramd);
2312 kink->SetStatus(2,5);
2319 if (nr==80) t.UpdateReference();
2320 if (nr<fInnerSec->GetNRows())
2321 fSectors = fInnerSec;
2323 fSectors = fOuterSec;
2324 if (FollowToNext(t,nr)==0)
2337 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2338 //-----------------------------------------------------------------
2339 // This function tries to find a track prolongation.
2340 //-----------------------------------------------------------------
2342 Double_t xt=t.GetX();
2343 Double_t alpha=t.GetAlpha();
2344 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2345 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2346 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2348 Int_t first = t.GetFirstPoint();
2349 Int_t ri = GetRowNumber(xt);
2353 if (first<ri) first = ri;
2355 if (first<0) first=0;
2356 for (Int_t nr=first; nr<=rf; nr++) {
2357 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2358 if (t.GetKinkIndexes()[0]<0){
2359 for (Int_t i=0;i<3;i++){
2360 Int_t index = t.GetKinkIndexes()[i];
2361 if (index==0) break;
2362 if (index>0) continue;
2363 index = TMath::Abs(index);
2364 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2366 printf("PROBLEM\n");
2369 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2371 AliExternalTrackParam paramm(t);
2372 kink->SetMother(paramm);
2373 kink->SetStatus(2,1);
2380 if (nr<fInnerSec->GetNRows())
2381 fSectors = fInnerSec;
2383 fSectors = fOuterSec;
2394 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2396 // overlapping factor
2402 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2405 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2407 Float_t distance = TMath::Sqrt(dz2+dy2);
2408 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2411 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2412 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2417 if (firstpoint>lastpoint) {
2418 firstpoint =lastpoint;
2423 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2424 if (s1->GetClusterIndex2(i)>0) sum1++;
2425 if (s2->GetClusterIndex2(i)>0) sum2++;
2426 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2430 if (sum<5) return 0;
2432 Float_t summin = TMath::Min(sum1+1,sum2+1);
2433 Float_t ratio = (sum+1)/Float_t(summin);
2437 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2441 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2442 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2443 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2444 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2449 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2450 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2451 Int_t firstpoint = 0;
2452 Int_t lastpoint = 160;
2454 // if (firstpoint>=lastpoint-5) return;;
2456 for (Int_t i=firstpoint;i<lastpoint;i++){
2457 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2458 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2462 if (sumshared>cutN0){
2465 for (Int_t i=firstpoint;i<lastpoint;i++){
2466 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2467 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2468 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2469 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2470 if (s1->IsActive()&&s2->IsActive()){
2471 p1->SetShared(kTRUE);
2472 p2->SetShared(kTRUE);
2478 if (sumshared>cutN0){
2479 for (Int_t i=0;i<4;i++){
2480 if (s1->GetOverlapLabel(3*i)==0){
2481 s1->SetOverlapLabel(3*i, s2->GetLabel());
2482 s1->SetOverlapLabel(3*i+1,sumshared);
2483 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2487 for (Int_t i=0;i<4;i++){
2488 if (s2->GetOverlapLabel(3*i)==0){
2489 s2->SetOverlapLabel(3*i, s1->GetLabel());
2490 s2->SetOverlapLabel(3*i+1,sumshared);
2491 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2498 void AliTPCtracker::SignShared(TObjArray * arr)
2501 //sort trackss according sectors
2503 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2504 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2506 //if (pt) RotateToLocal(pt);
2510 arr->Sort(); // sorting according relative sectors
2511 arr->Expand(arr->GetEntries());
2514 Int_t nseed=arr->GetEntriesFast();
2515 for (Int_t i=0; i<nseed; i++) {
2516 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2518 for (Int_t j=0;j<12;j++){
2519 pt->SetOverlapLabel(j,0);
2522 for (Int_t i=0; i<nseed; i++) {
2523 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2525 if (pt->GetRemoval()>10) continue;
2526 for (Int_t j=i+1; j<nseed; j++){
2527 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2528 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2530 if (pt2->GetRemoval()<=10) {
2531 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2539 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
2542 //sort tracks in array according mode criteria
2543 Int_t nseed = arr->GetEntriesFast();
2544 for (Int_t i=0; i<nseed; i++) {
2545 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2556 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
2559 // Loop over all tracks and remove overlaped tracks (with lower quality)
2561 // 1. Unsign clusters
2562 // 2. Sort tracks according quality
2563 // Quality is defined by the number of cluster between first and last points
2565 // 3. Loop over tracks - decreasing quality order
2566 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
2567 // b.) remove - If the minimal number of clusters less than minimal and not ITS
2568 // c.) if track accepted - sign clusters
2570 //Called in - AliTPCtracker::Clusters2Tracks()
2571 // - AliTPCtracker::PropagateBack()
2572 // - AliTPCtracker::RefitInward()
2575 // factor1 - factor for constrained
2576 // factor2 - for non constrained tracks
2577 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
2581 Int_t nseed = arr->GetEntriesFast();
2582 Float_t * quality = new Float_t[nseed];
2583 Int_t * indexes = new Int_t[nseed];
2587 for (Int_t i=0; i<nseed; i++) {
2588 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2593 pt->UpdatePoints(); //select first last max dens points
2594 Float_t * points = pt->GetPoints();
2595 if (points[3]<0.8) quality[i] =-1;
2596 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2597 //prefer high momenta tracks if overlaps
2598 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
2600 TMath::Sort(nseed,quality,indexes);
2603 for (Int_t itrack=0; itrack<nseed; itrack++) {
2604 Int_t trackindex = indexes[itrack];
2605 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
2608 if (quality[trackindex]<0){
2609 MarkSeedFree( arr->RemoveAt(trackindex) );
2614 Int_t first = Int_t(pt->GetPoints()[0]);
2615 Int_t last = Int_t(pt->GetPoints()[2]);
2616 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2618 Int_t found,foundable,shared;
2619 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
2620 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2621 Bool_t itsgold =kFALSE;
2624 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2628 if (Float_t(shared+1)/Float_t(found+1)>factor){
2629 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2630 if( AliTPCReconstructor::StreamLevel()>3){
2631 TTreeSRedirector &cstream = *fDebugStreamer;
2632 cstream<<"RemoveUsed"<<
2633 "iter="<<fIteration<<
2637 MarkSeedFree( arr->RemoveAt(trackindex) );
2640 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
2641 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2642 if( AliTPCReconstructor::StreamLevel()>3){
2643 TTreeSRedirector &cstream = *fDebugStreamer;
2644 cstream<<"RemoveShort"<<
2645 "iter="<<fIteration<<
2649 MarkSeedFree( arr->RemoveAt(trackindex) );
2655 //if (sharedfactor>0.4) continue;
2656 if (pt->GetKinkIndexes()[0]>0) continue;
2657 //Remove tracks with undefined properties - seems
2658 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
2660 for (Int_t i=first; i<last; i++) {
2661 Int_t index=pt->GetClusterIndex2(i);
2662 // if (index<0 || index&0x8000 ) continue;
2663 if (index<0 || index&0x8000 ) continue;
2664 AliTPCclusterMI *c= pt->GetClusterPointer(i);
2671 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2677 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
2680 // Dump clusters after reco
2681 // signed and unsigned cluster can be visualized
2682 // 1. Unsign all cluster
2683 // 2. Sign all used clusters
2686 Int_t nseed = trackArray->GetEntries();
2687 for (Int_t i=0; i<nseed; i++){
2688 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
2692 Bool_t isKink=pt->GetKinkIndex(0)!=0;
2693 for (Int_t j=0; j<160; ++j) {
2694 Int_t index=pt->GetClusterIndex2(j);
2695 if (index<0) continue;
2696 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2698 if (isKink) c->Use(100); // kink
2699 c->Use(10); // by default usage 10
2704 for (Int_t sec=0;sec<fkNIS;sec++){
2705 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2706 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2707 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
2708 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2709 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2710 (*fDebugStreamer)<<"clDump"<<
2718 cla = fInnerSec[sec][row].GetClusters2();
2719 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
2720 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2721 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2722 (*fDebugStreamer)<<"clDump"<<
2733 for (Int_t sec=0;sec<fkNOS;sec++){
2734 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2735 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2736 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
2738 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2739 cl->GetGlobalXYZ(gx);
2740 (*fDebugStreamer)<<"clDump"<<
2748 cla = fOuterSec[sec][row].GetClusters2();
2749 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
2751 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2752 cl->GetGlobalXYZ(gx);
2753 (*fDebugStreamer)<<"clDump"<<
2765 void AliTPCtracker::UnsignClusters()
2768 // loop over all clusters and unsign them
2771 for (Int_t sec=0;sec<fkNIS;sec++){
2772 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2773 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2774 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2775 // if (cl[icl].IsUsed(10))
2776 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2777 cla = fInnerSec[sec][row].GetClusters2();
2778 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2779 //if (cl[icl].IsUsed(10))
2780 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2784 for (Int_t sec=0;sec<fkNOS;sec++){
2785 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2786 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2787 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2788 //if (cl[icl].IsUsed(10))
2789 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2790 cla = fOuterSec[sec][row].GetClusters2();
2791 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2792 //if (cl[icl].IsUsed(10))
2793 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2801 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
2804 //sign clusters to be "used"
2806 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2807 // loop over "primaries"
2821 Int_t nseed = arr->GetEntriesFast();
2822 for (Int_t i=0; i<nseed; i++) {
2823 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2827 if (!(pt->IsActive())) continue;
2828 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2829 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2831 sumdens2+= dens*dens;
2832 sumn += pt->GetNumberOfClusters();
2833 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2834 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2837 sumchi2 +=chi2*chi2;
2842 Float_t mdensity = 0.9;
2843 Float_t meann = 130;
2844 Float_t meanchi = 1;
2845 Float_t sdensity = 0.1;
2846 Float_t smeann = 10;
2847 Float_t smeanchi =0.4;
2851 mdensity = sumdens/sum;
2853 meanchi = sumchi/sum;
2855 sdensity = sumdens2/sum-mdensity*mdensity;
2857 sdensity = TMath::Sqrt(sdensity);
2861 smeann = sumn2/sum-meann*meann;
2863 smeann = TMath::Sqrt(smeann);
2867 smeanchi = sumchi2/sum - meanchi*meanchi;
2869 smeanchi = TMath::Sqrt(smeanchi);
2875 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
2877 for (Int_t i=0; i<nseed; i++) {
2878 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2882 if (pt->GetBSigned()) continue;
2883 if (pt->GetBConstrain()) continue;
2884 //if (!(pt->IsActive())) continue;
2886 Int_t found,foundable,shared;
2887 pt->GetClusterStatistic(0,160,found, foundable,shared);
2888 if (shared/float(found)>0.3) {
2889 if (shared/float(found)>0.9 ){
2890 //MarkSeedFree( arr->RemoveAt(i) );
2895 Bool_t isok =kFALSE;
2896 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2898 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2900 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2902 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2906 for (Int_t j=0; j<160; ++j) {
2907 Int_t index=pt->GetClusterIndex2(j);
2908 if (index<0) continue;
2909 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2911 //if (!(c->IsUsed(10))) c->Use();
2918 Double_t maxchi = meanchi+2.*smeanchi;
2920 for (Int_t i=0; i<nseed; i++) {
2921 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2925 //if (!(pt->IsActive())) continue;
2926 if (pt->GetBSigned()) continue;
2927 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
2928 if (chi>maxchi) continue;
2931 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2933 //sign only tracks with enoug big density at the beginning
2935 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
2938 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2939 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2941 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2942 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2945 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2946 //Int_t noc=pt->GetNumberOfClusters();
2947 pt->SetBSigned(kTRUE);
2948 for (Int_t j=0; j<160; ++j) {
2950 Int_t index=pt->GetClusterIndex2(j);
2951 if (index<0) continue;
2952 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2954 // if (!(c->IsUsed(10))) c->Use();
2959 // gLastCheck = nseed;
2968 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
2971 // back propagation of ESD tracks
2974 if (!event) return 0;
2975 const Int_t kMaxFriendTracks=2000;
2978 // extract correction object for multiplicity dependence of dEdx
2979 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
2981 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
2983 AliFatal("Tranformations not in RefitInward");
2986 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
2987 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
2988 Int_t nContribut = event->GetNumberOfTracks();
2989 TGraphErrors * graphMultDependenceDeDx = 0x0;
2990 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
2991 if (recoParam->GetUseTotCharge()) {
2992 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2994 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
3000 //PrepareForProlongation(fSeeds,1);
3001 PropagateForward2(fSeeds);
3002 RemoveUsed2(fSeeds,0.4,0.4,20);
3004 Int_t entriesSeed=fSeeds->GetEntries();
3005 TObjArray arraySeed(entriesSeed);
3006 for (Int_t i=0;i<entriesSeed;i++) {
3007 arraySeed.AddAt(fSeeds->At(i),i);
3009 SignShared(&arraySeed);
3010 // FindCurling(fSeeds, event,2); // find multi found tracks
3011 FindSplitted(fSeeds, event,2); // find multi found tracks
3012 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,2); // find multi found tracks
3015 Int_t nseed = fSeeds->GetEntriesFast();
3016 for (Int_t i=0;i<nseed;i++){
3017 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3018 if (!seed) continue;
3019 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
3020 AliESDtrack *esd=event->GetTrack(i);
3022 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3023 AliExternalTrackParam paramIn;
3024 AliExternalTrackParam paramOut;
3025 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3026 if (AliTPCReconstructor::StreamLevel()>2) {
3027 (*fDebugStreamer)<<"RecoverIn"<<
3031 "pout.="<<¶mOut<<
3036 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3037 seed->SetNumberOfClusters(ncl);
3041 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3042 seed->UpdatePoints();
3043 AddCovariance(seed);
3044 MakeESDBitmaps(seed, esd);
3045 seed->CookdEdx(0.02,0.6);
3046 CookLabel(seed,0.1); //For comparison only
3048 if (AliTPCReconstructor::StreamLevel()>1 && seed!=0) {
3049 TTreeSRedirector &cstream = *fDebugStreamer;
3056 if (seed->GetNumberOfClusters()>15){
3057 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3058 esd->SetTPCPoints(seed->GetPoints());
3059 esd->SetTPCPointsF(seed->GetNFoundable());
3060 Int_t ndedx = seed->GetNCDEDX(0);
3061 Float_t sdedx = seed->GetSDEDX(0);
3062 Float_t dedx = seed->GetdEdx();
3063 // apply mutliplicity dependent dEdx correction if available
3064 if (graphMultDependenceDeDx) {
3065 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3066 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3068 esd->SetTPCsignal(dedx, sdedx, ndedx);
3070 // fill new dEdx information
3072 Double32_t signal[4];
3073 Double32_t signalMax[4];
3077 for(Int_t iarr=0;iarr<3;iarr++) {
3078 signal[iarr] = seed->GetDEDXregion(iarr+1);
3079 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3080 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3081 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3083 signal[3] = seed->GetDEDXregion(4);
3084 signalMax[3] = seed->GetDEDXregion(8);
3087 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3088 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3089 infoTpcPid->SetTPCSignalsQmax(signalMax);
3090 esd->SetTPCdEdxInfo(infoTpcPid);
3092 // add seed to the esd track in Calib level
3094 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3095 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3096 // RS: this is the only place where the seed is created not in the pool,
3097 // since it should belong to ESDevent
3098 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3099 esd->AddCalibObject(seedCopy);
3104 //printf("problem\n");
3107 //FindKinks(fSeeds,event);
3108 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(2,fSeeds);
3109 Info("RefitInward","Number of refitted tracks %d",ntracks);
3111 AliCosmicTracker::FindCosmic(event, kTRUE);
3113 FillClusterOccupancyInfo();
3119 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3122 // back propagation of ESD tracks
3124 if (!event) return 0;
3129 PropagateBack(fSeeds);
3130 RemoveUsed2(fSeeds,0.4,0.4,20);
3131 //FindCurling(fSeeds, fEvent,1);
3132 FindSplitted(fSeeds, event,1); // find multi found tracks
3133 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3136 Int_t nseed = fSeeds->GetEntriesFast();
3138 for (Int_t i=0;i<nseed;i++){
3139 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3140 if (!seed) continue;
3141 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3142 seed->UpdatePoints();
3143 AddCovariance(seed);
3144 AliESDtrack *esd=event->GetTrack(i);
3145 if (!esd) continue; //never happen
3146 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3147 AliExternalTrackParam paramIn;
3148 AliExternalTrackParam paramOut;
3149 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3150 if (AliTPCReconstructor::StreamLevel()>2) {
3151 (*fDebugStreamer)<<"RecoverBack"<<
3155 "pout.="<<¶mOut<<
3160 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3161 seed->SetNumberOfClusters(ncl);
3164 seed->CookdEdx(0.02,0.6);
3165 CookLabel(seed,0.1); //For comparison only
3166 if (seed->GetNumberOfClusters()>15){
3167 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3168 esd->SetTPCPoints(seed->GetPoints());
3169 esd->SetTPCPointsF(seed->GetNFoundable());
3170 Int_t ndedx = seed->GetNCDEDX(0);
3171 Float_t sdedx = seed->GetSDEDX(0);
3172 Float_t dedx = seed->GetdEdx();
3173 esd->SetTPCsignal(dedx, sdedx, ndedx);
3175 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3176 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3177 if (AliTPCReconstructor::StreamLevel()>1 && esd) {
3178 (*fDebugStreamer)<<"Cback"<<
3181 "EventNrInFile="<<eventnumber<<
3186 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(1,fSeeds);
3187 //FindKinks(fSeeds,event);
3188 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3196 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3199 // Post process events
3201 if (!event) return 0;
3204 // Set TPC event status
3207 // event affected by HV dip
3209 if(IsTPCHVDipEvent(event)) {
3210 event->ResetDetectorStatus(AliDAQ::kTPC);
3213 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3219 void AliTPCtracker::DeleteSeeds()
3228 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3231 //read seeds from the event
3233 Int_t nentr=event->GetNumberOfTracks();
3235 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3240 fSeeds = new TObjArray(nentr);
3244 for (Int_t i=0; i<nentr; i++) {
3245 AliESDtrack *esd=event->GetTrack(i);
3246 ULong_t status=esd->GetStatus();
3247 if (!(status&AliESDtrack::kTPCin)) continue;
3248 AliTPCtrack t(*esd);
3249 t.SetNumberOfClusters(0);
3250 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3251 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3252 seed->SetPoolID(fLastSeedID);
3253 seed->SetUniqueID(esd->GetID());
3254 AddCovariance(seed); //add systematic ucertainty
3255 for (Int_t ikink=0;ikink<3;ikink++) {
3256 Int_t index = esd->GetKinkIndex(ikink);
3257 seed->GetKinkIndexes()[ikink] = index;
3258 if (index==0) continue;
3259 index = TMath::Abs(index);
3260 AliESDkink * kink = fEvent->GetKink(index-1);
3261 if (kink&&esd->GetKinkIndex(ikink)<0){
3262 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3263 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3265 if (kink&&esd->GetKinkIndex(ikink)>0){
3266 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3267 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3271 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3272 //RS if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3273 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3274 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3275 // fSeeds->AddAt(0,i);
3276 // MarkSeedFree( seed );
3282 // rotate to the local coordinate system
3284 fSectors=fInnerSec; fN=fkNIS;
3285 Double_t alpha=seed->GetAlpha();
3286 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3287 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3288 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3289 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3290 alpha-=seed->GetAlpha();
3291 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3292 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3293 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3294 AliWarning(Form("Rotating track over %f",alpha));
3295 if (!seed->Rotate(alpha)) {
3296 MarkSeedFree( seed );
3302 if (esd->GetKinkIndex(0)<=0){
3303 for (Int_t irow=0;irow<160;irow++){
3304 Int_t index = seed->GetClusterIndex2(irow);
3307 AliTPCclusterMI * cl = GetClusterMI(index);
3308 seed->SetClusterPointer(irow,cl);
3310 if ((index & 0x8000)==0){
3311 cl->Use(10); // accepted cluster
3313 cl->Use(6); // close cluster not accepted
3316 Info("ReadSeeds","Not found cluster");
3321 fSeeds->AddAt(seed,i);
3327 //_____________________________________________________________________________
3328 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3329 Float_t deltay, Int_t ddsec) {
3330 //-----------------------------------------------------------------
3331 // This function creates track seeds.
3332 // SEEDING WITH VERTEX CONSTRAIN
3333 //-----------------------------------------------------------------
3334 // cuts[0] - fP4 cut
3335 // cuts[1] - tan(phi) cut
3336 // cuts[2] - zvertex cut
3337 // cuts[3] - fP3 cut
3345 Double_t x[5], c[15];
3346 // Int_t di = i1-i2;
3348 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3349 seed->SetPoolID(fLastSeedID);
3350 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3351 Double_t cs=cos(alpha), sn=sin(alpha);
3353 // Double_t x1 =fOuterSec->GetX(i1);
3354 //Double_t xx2=fOuterSec->GetX(i2);
3356 Double_t x1 =GetXrow(i1);
3357 Double_t xx2=GetXrow(i2);
3359 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3361 Int_t imiddle = (i2+i1)/2; //middle pad row index
3362 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3363 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3367 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3368 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3369 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3372 // change cut on curvature if it can't reach this layer
3373 // maximal curvature set to reach it
3374 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3375 if (dvertexmax*0.5*cuts[0]>0.85){
3376 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3378 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3381 if (deltay>0) ddsec = 0;
3382 // loop over clusters
3383 for (Int_t is=0; is < kr1; is++) {
3385 if (kr1[is]->IsUsed(10)) continue;
3386 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3387 //if (TMath::Abs(y1)>ymax) continue;
3389 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3391 // find possible directions
3392 Float_t anglez = (z1-z3)/(x1-x3);
3393 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3396 //find rotation angles relative to line given by vertex and point 1
3397 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3398 Double_t dvertex = TMath::Sqrt(dvertex2);
3399 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3400 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3403 // loop over 2 sectors
3409 Double_t dddz1=0; // direction of delta inclination in z axis
3416 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3417 Int_t sec2 = sec + dsec;
3419 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3420 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3421 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3422 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3423 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3424 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3426 // rotation angles to p1-p3
3427 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3428 Double_t x2, y2, z2;
3430 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3433 Double_t dxx0 = (xx2-x3)*cs13r;
3434 Double_t dyy0 = (xx2-x3)*sn13r;
3435 for (Int_t js=index1; js < index2; js++) {
3436 const AliTPCclusterMI *kcl = kr2[js];
3437 if (kcl->IsUsed(10)) continue;
3439 //calcutate parameters
3441 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3443 if (TMath::Abs(yy0)<0.000001) continue;
3444 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3445 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3446 Double_t r02 = (0.25+y0*y0)*dvertex2;
3447 //curvature (radius) cut
3448 if (r02<r2min) continue;
3452 Double_t c0 = 1/TMath::Sqrt(r02);
3456 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3457 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3458 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3459 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3462 Double_t z0 = kcl->GetZ();
3463 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3464 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3467 Double_t dip = (z1-z0)*c0/dfi1;
3468 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3479 x2= xx2*cs-y2*sn*dsec;
3480 y2=+xx2*sn*dsec+y2*cs;
3490 // do we have cluster at the middle ?
3492 GetProlongation(x1,xm,x,ym,zm);
3494 AliTPCclusterMI * cm=0;
3495 if (TMath::Abs(ym)-ymaxm<0){
3496 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3497 if ((!cm) || (cm->IsUsed(10))) {
3502 // rotate y1 to system 0
3503 // get state vector in rotated system
3504 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3505 Double_t xr2 = x0*cs+yr1*sn*dsec;
3506 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3508 GetProlongation(xx2,xm,xr,ym,zm);
3509 if (TMath::Abs(ym)-ymaxm<0){
3510 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3511 if ((!cm) || (cm->IsUsed(10))) {
3518 // Double_t dym = 0;
3519 // Double_t dzm = 0;
3521 // dym = ym - cm->GetY();
3522 // dzm = zm - cm->GetZ();
3529 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3530 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
3531 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3532 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3533 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3535 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3536 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3537 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3538 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3539 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3540 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3542 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3543 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3544 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3545 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3549 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3550 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3551 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3552 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3553 c[13]=f30*sy1*f40+f32*sy2*f42;
3554 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3556 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3558 UInt_t index=kr1.GetIndex(is);
3559 if (seed) {MarkSeedFree(seed); seed = 0;}
3560 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3561 seed->SetPoolID(fLastSeedID);
3562 track->SetIsSeeding(kTRUE);
3563 track->SetSeed1(i1);
3564 track->SetSeed2(i2);
3565 track->SetSeedType(3);
3569 FollowProlongation(*track, (i1+i2)/2,1);
3570 Int_t foundable,found,shared;
3571 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3572 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3573 MarkSeedFree(seed); seed = 0;
3579 FollowProlongation(*track, i2,1);
3583 track->SetBConstrain(1);
3584 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
3585 track->SetLastPoint(i1); // first cluster in track position
3586 track->SetFirstPoint(track->GetLastPoint());
3588 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3589 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3590 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3591 MarkSeedFree(seed); seed = 0;
3595 // Z VERTEX CONDITION
3596 Double_t zv, bz=GetBz();
3597 if ( !track->GetZAt(0.,bz,zv) ) continue;
3598 if (TMath::Abs(zv-z3)>cuts[2]) {
3599 FollowProlongation(*track, TMath::Max(i2-20,0));
3600 if ( !track->GetZAt(0.,bz,zv) ) continue;
3601 if (TMath::Abs(zv-z3)>cuts[2]){
3602 FollowProlongation(*track, TMath::Max(i2-40,0));
3603 if ( !track->GetZAt(0.,bz,zv) ) continue;
3604 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3605 // make seed without constrain
3606 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3607 FollowProlongation(*track2, i2,1);
3608 track2->SetBConstrain(kFALSE);
3609 track2->SetSeedType(1);
3610 arr->AddLast(track2);
3611 MarkSeedFree( seed ); seed = 0;
3615 MarkSeedFree( seed ); seed = 0;
3622 track->SetSeedType(0);
3623 arr->AddLast(track); // note, track is seed, don't free the seed
3624 seed = new( NextFreeSeed() ) AliTPCseed;
3625 seed->SetPoolID(fLastSeedID);
3627 // don't consider other combinations
3628 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3634 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3636 if (seed) MarkSeedFree( seed );
3640 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3645 //-----------------------------------------------------------------
3646 // This function creates track seeds.
3647 //-----------------------------------------------------------------
3648 // cuts[0] - fP4 cut
3649 // cuts[1] - tan(phi) cut
3650 // cuts[2] - zvertex cut
3651 // cuts[3] - fP3 cut
3661 Double_t x[5], c[15];
3663 // make temporary seed
3664 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3665 seed->SetPoolID(fLastSeedID);
3666 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3667 // Double_t cs=cos(alpha), sn=sin(alpha);
3672 Double_t x1 = GetXrow(i1-1);
3673 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3674 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
3676 Double_t x1p = GetXrow(i1);
3677 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3679 Double_t x1m = GetXrow(i1-2);
3680 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3683 //last 3 padrow for seeding
3684 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
3685 Double_t x3 = GetXrow(i1-7);
3686 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
3688 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
3689 Double_t x3p = GetXrow(i1-6);
3691 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
3692 Double_t x3m = GetXrow(i1-8);
3697 Int_t im = i1-4; //middle pad row index
3698 Double_t xm = GetXrow(im); // radius of middle pad-row
3699 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
3700 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
3703 Double_t deltax = x1-x3;
3704 Double_t dymax = deltax*cuts[1];
3705 Double_t dzmax = deltax*cuts[3];
3707 // loop over clusters
3708 for (Int_t is=0; is < kr1; is++) {
3710 if (kr1[is]->IsUsed(10)) continue;
3711 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3713 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3715 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3716 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3722 for (Int_t js=index1; js < index2; js++) {
3723 const AliTPCclusterMI *kcl = kr3[js];
3724 if (kcl->IsUsed(10)) continue;
3726 // apply angular cuts
3727 if (TMath::Abs(y1-y3)>dymax) continue;
3730 if (TMath::Abs(z1-z3)>dzmax) continue;
3732 Double_t angley = (y1-y3)/(x1-x3);
3733 Double_t anglez = (z1-z3)/(x1-x3);
3735 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3736 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3738 Double_t yyym = angley*(xm-x1)+y1;
3739 Double_t zzzm = anglez*(xm-x1)+z1;
3741 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3743 if (kcm->IsUsed(10)) continue;
3745 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3746 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3753 // look around first
3754 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3760 if (kc1m->IsUsed(10)) used++;
3762 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3768 if (kc1p->IsUsed(10)) used++;
3770 if (used>1) continue;
3771 if (found<1) continue;
3775 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3781 if (kc3m->IsUsed(10)) used++;
3785 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3791 if (kc3p->IsUsed(10)) used++;
3795 if (used>1) continue;
3796 if (found<3) continue;
3806 x[4]=F1(x1,y1,x2,y2,x3,y3);
3807 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3810 x[2]=F2(x1,y1,x2,y2,x3,y3);
3813 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3814 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3818 Double_t sy1=0.1, sz1=0.1;
3819 Double_t sy2=0.1, sz2=0.1;
3820 Double_t sy3=0.1, sy=0.1, sz=0.1;
3822 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3823 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3824 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3825 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3826 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3827 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3829 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3830 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3831 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3832 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3836 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3837 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3838 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3839 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3840 c[13]=f30*sy1*f40+f32*sy2*f42;
3841 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3843 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3845 index=kr1.GetIndex(is);
3846 if (seed) {MarkSeedFree( seed ); seed = 0;}
3847 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3848 seed->SetPoolID(fLastSeedID);
3850 track->SetIsSeeding(kTRUE);
3853 FollowProlongation(*track, i1-7,1);
3854 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
3855 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3856 MarkSeedFree( seed ); seed = 0;
3862 FollowProlongation(*track, i2,1);
3863 track->SetBConstrain(0);
3864 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
3865 track->SetFirstPoint(track->GetLastPoint());
3867 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3868 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
3869 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3870 MarkSeedFree( seed ); seed = 0;
3875 FollowProlongation(*track, TMath::Max(i2-10,0),1);
3876 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3877 FollowProlongation(*track2, i2,1);
3878 track2->SetBConstrain(kFALSE);
3879 track2->SetSeedType(4);
3880 arr->AddLast(track2);
3881 MarkSeedFree( seed ); seed = 0;
3885 //arr->AddLast(track);
3886 //seed = new AliTPCseed;
3892 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);
3894 if (seed) MarkSeedFree(seed);
3898 //_____________________________________________________________________________
3899 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3900 Float_t deltay, Bool_t /*bconstrain*/) {
3901 //-----------------------------------------------------------------
3902 // This function creates track seeds - without vertex constraint
3903 //-----------------------------------------------------------------
3904 // cuts[0] - fP4 cut - not applied
3905 // cuts[1] - tan(phi) cut
3906 // cuts[2] - zvertex cut - not applied
3907 // cuts[3] - fP3 cut
3917 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3918 // Double_t cs=cos(alpha), sn=sin(alpha);
3919 Int_t row0 = (i1+i2)/2;
3920 Int_t drow = (i1-i2)/2;
3921 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3922 AliTPCtrackerRow * kr=0;
3924 AliTPCpolyTrack polytrack;
3925 Int_t nclusters=fSectors[sec][row0];
3926 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3927 seed->SetPoolID(fLastSeedID);
3932 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
3934 Int_t nfoundable =0;
3935 for (Int_t iter =1; iter<2; iter++){ //iterations
3936 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3937 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
3938 const AliTPCclusterMI * cl= kr0[is];
3940 if (cl->IsUsed(10)) {
3946 Double_t x = kr0.GetX();
3947 // Initialization of the polytrack
3952 Double_t y0= cl->GetY();
3953 Double_t z0= cl->GetZ();
3957 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3958 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
3960 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
3961 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
3962 polytrack.AddPoint(x,y0,z0,erry, errz);
3965 if (cl->IsUsed(10)) sumused++;
3968 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3969 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3972 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3973 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3974 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
3975 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3976 if (cl1->IsUsed(10)) sumused++;
3977 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3981 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3983 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
3984 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3985 if (cl2->IsUsed(10)) sumused++;
3986 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3989 if (sumused>0) continue;
3991 polytrack.UpdateParameters();
3997 nfoundable = polytrack.GetN();
3998 nfound = nfoundable;
4000 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
4001 Float_t maxdist = 0.8*(1.+3./(ddrow));
4002 for (Int_t delta = -1;delta<=1;delta+=2){
4003 Int_t row = row0+ddrow*delta;
4004 kr = &(fSectors[sec][row]);
4005 Double_t xn = kr->GetX();
4006 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
4007 polytrack.GetFitPoint(xn,yn,zn);
4008 if (TMath::Abs(yn)>ymax1) continue;
4010 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
4012 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
4015 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4016 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4017 if (cln->IsUsed(10)) {
4018 // printf("used\n");
4026 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4031 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4032 polytrack.UpdateParameters();
4035 if ( (sumused>3) || (sumused>0.5*nfound)) {
4036 //printf("sumused %d\n",sumused);
4041 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4042 AliTPCpolyTrack track2;
4044 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4045 if (track2.GetN()<0.5*nfoundable) continue;
4048 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4050 // test seed with and without constrain
4051 for (Int_t constrain=0; constrain<=0;constrain++){
4052 // add polytrack candidate
4054 Double_t x[5], c[15];
4055 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4056 track2.GetBoundaries(x3,x1);
4058 track2.GetFitPoint(x1,y1,z1);
4059 track2.GetFitPoint(x2,y2,z2);
4060 track2.GetFitPoint(x3,y3,z3);
4062 //is track pointing to the vertex ?
4065 polytrack.GetFitPoint(x0,y0,z0);
4078 x[4]=F1(x1,y1,x2,y2,x3,y3);
4080 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4081 x[2]=F2(x1,y1,x2,y2,x3,y3);
4083 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4084 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4085 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4086 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4089 Double_t sy =0.1, sz =0.1;
4090 Double_t sy1=0.02, sz1=0.02;
4091 Double_t sy2=0.02, sz2=0.02;
4095 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4098 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4099 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4100 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4101 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4102 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4103 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4105 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4106 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4107 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4108 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4113 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4114 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4115 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4116 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4117 c[13]=f30*sy1*f40+f32*sy2*f42;
4118 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4120 //Int_t row1 = fSectors->GetRowNumber(x1);
4121 Int_t row1 = GetRowNumber(x1);
4125 if (seed) {MarkSeedFree( seed ); seed = 0;}
4126 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4127 seed->SetPoolID(fLastSeedID);
4128 track->SetIsSeeding(kTRUE);
4129 Int_t rc=FollowProlongation(*track, i2);
4130 if (constrain) track->SetBConstrain(1);
4132 track->SetBConstrain(0);
4133 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4134 track->SetFirstPoint(track->GetLastPoint());
4136 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4137 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4138 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4139 MarkSeedFree( seed ); seed = 0;
4142 arr->AddLast(track); // track IS seed, don't free seed
4143 seed = new( NextFreeSeed() ) AliTPCseed;
4144 seed->SetPoolID(fLastSeedID);
4148 } // if accepted seed
4151 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4153 if (seed) MarkSeedFree( seed );
4157 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4161 //reseed using track points
4162 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4163 Int_t p1 = int(r1*track->GetNumberOfClusters());
4164 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4166 Double_t x0[3],x1[3],x2[3];
4167 for (Int_t i=0;i<3;i++){
4173 // find track position at given ratio of the length
4174 Int_t sec0=0, sec1=0, sec2=0;
4177 for (Int_t i=0;i<160;i++){
4178 if (track->GetClusterPointer(i)){
4180 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4181 if ( (index<p0) || x0[0]<0 ){
4182 if (trpoint->GetX()>1){
4183 clindex = track->GetClusterIndex2(i);
4185 x0[0] = trpoint->GetX();
4186 x0[1] = trpoint->GetY();
4187 x0[2] = trpoint->GetZ();
4188 sec0 = ((clindex&0xff000000)>>24)%18;
4193 if ( (index<p1) &&(trpoint->GetX()>1)){
4194 clindex = track->GetClusterIndex2(i);
4196 x1[0] = trpoint->GetX();
4197 x1[1] = trpoint->GetY();
4198 x1[2] = trpoint->GetZ();
4199 sec1 = ((clindex&0xff000000)>>24)%18;
4202 if ( (index<p2) &&(trpoint->GetX()>1)){
4203 clindex = track->GetClusterIndex2(i);
4205 x2[0] = trpoint->GetX();
4206 x2[1] = trpoint->GetY();
4207 x2[2] = trpoint->GetZ();
4208 sec2 = ((clindex&0xff000000)>>24)%18;
4215 Double_t alpha, cs,sn, xx2,yy2;
4217 alpha = (sec1-sec2)*fSectors->GetAlpha();
4218 cs = TMath::Cos(alpha);
4219 sn = TMath::Sin(alpha);
4220 xx2= x1[0]*cs-x1[1]*sn;
4221 yy2= x1[0]*sn+x1[1]*cs;
4225 alpha = (sec0-sec2)*fSectors->GetAlpha();
4226 cs = TMath::Cos(alpha);
4227 sn = TMath::Sin(alpha);
4228 xx2= x0[0]*cs-x0[1]*sn;
4229 yy2= x0[0]*sn+x0[1]*cs;
4235 Double_t x[5],c[15];
4239 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4240 // if (x[4]>1) return 0;
4241 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4242 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4243 //if (TMath::Abs(x[3]) > 2.2) return 0;
4244 //if (TMath::Abs(x[2]) > 1.99) return 0;
4246 Double_t sy =0.1, sz =0.1;
4248 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4249 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4250 Double_t sy3=0.01+track->GetSigmaY2();
4252 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4253 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4254 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4255 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4256 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4257 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4259 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4260 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4261 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4262 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4267 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4268 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4269 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4270 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4271 c[13]=f30*sy1*f40+f32*sy2*f42;
4272 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4274 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4275 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4276 seed->SetPoolID(fLastSeedID);
4277 // Double_t y0,z0,y1,z1, y2,z2;
4278 //seed->GetProlongation(x0[0],y0,z0);
4279 // seed->GetProlongation(x1[0],y1,z1);
4280 //seed->GetProlongation(x2[0],y2,z2);
4282 seed->SetLastPoint(pp2);
4283 seed->SetFirstPoint(pp2);
4290 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4294 //reseed using founded clusters
4296 // Find the number of clusters
4297 Int_t nclusters = 0;
4298 for (Int_t irow=0;irow<160;irow++){
4299 if (track->GetClusterIndex(irow)>0) nclusters++;
4303 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4304 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4305 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4308 Double_t xyz[3][3]={{0}};
4309 Int_t row[3]={0},sec[3]={0,0,0};
4311 // find track row position at given ratio of the length
4313 for (Int_t irow=0;irow<160;irow++){
4314 if (track->GetClusterIndex2(irow)<0) continue;
4316 for (Int_t ipoint=0;ipoint<3;ipoint++){
4317 if (index<=ipos[ipoint]) row[ipoint] = irow;
4321 //Get cluster and sector position
4322 for (Int_t ipoint=0;ipoint<3;ipoint++){
4323 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4324 AliTPCclusterMI * cl = GetClusterMI(clindex);
4327 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4330 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4331 xyz[ipoint][0] = GetXrow(row[ipoint]);
4332 xyz[ipoint][1] = cl->GetY();
4333 xyz[ipoint][2] = cl->GetZ();
4337 // Calculate seed state vector and covariance matrix
4339 Double_t alpha, cs,sn, xx2,yy2;
4341 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4342 cs = TMath::Cos(alpha);
4343 sn = TMath::Sin(alpha);
4344 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4345 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4349 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4350 cs = TMath::Cos(alpha);
4351 sn = TMath::Sin(alpha);
4352 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4353 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4359 Double_t x[5],c[15];
4363 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4364 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4365 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4367 Double_t sy =0.1, sz =0.1;
4369 Double_t sy1=0.2, sz1=0.2;
4370 Double_t sy2=0.2, sz2=0.2;
4373 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;
4374 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;
4375 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;
4376 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;
4377 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;
4378 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;
4380 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;
4381 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;
4382 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;
4383 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;
4388 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4389 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4390 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4391 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4392 c[13]=f30*sy1*f40+f32*sy2*f42;
4393 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4395 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4396 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4397 seed->SetPoolID(fLastSeedID);
4398 seed->SetLastPoint(row[2]);
4399 seed->SetFirstPoint(row[2]);
4404 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4408 //reseed using founded clusters
4411 Int_t row[3]={0,0,0};
4412 Int_t sec[3]={0,0,0};
4414 // forward direction
4416 for (Int_t irow=r0;irow<160;irow++){
4417 if (track->GetClusterIndex(irow)>0){
4422 for (Int_t irow=160;irow>r0;irow--){
4423 if (track->GetClusterIndex(irow)>0){
4428 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4429 if (track->GetClusterIndex(irow)>0){
4437 for (Int_t irow=0;irow<r0;irow++){
4438 if (track->GetClusterIndex(irow)>0){
4443 for (Int_t irow=r0;irow>0;irow--){
4444 if (track->GetClusterIndex(irow)>0){
4449 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4450 if (track->GetClusterIndex(irow)>0){
4457 if ((row[2]-row[0])<20) return 0;
4458 if (row[1]==0) return 0;
4461 //Get cluster and sector position
4462 for (Int_t ipoint=0;ipoint<3;ipoint++){
4463 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4464 AliTPCclusterMI * cl = GetClusterMI(clindex);
4467 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4470 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4471 xyz[ipoint][0] = GetXrow(row[ipoint]);
4472 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4473 if (point&&ipoint<2){
4475 xyz[ipoint][1] = point->GetY();
4476 xyz[ipoint][2] = point->GetZ();
4479 xyz[ipoint][1] = cl->GetY();
4480 xyz[ipoint][2] = cl->GetZ();
4487 // Calculate seed state vector and covariance matrix
4489 Double_t alpha, cs,sn, xx2,yy2;
4491 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4492 cs = TMath::Cos(alpha);
4493 sn = TMath::Sin(alpha);
4494 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4495 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4499 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4500 cs = TMath::Cos(alpha);
4501 sn = TMath::Sin(alpha);
4502 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4503 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4509 Double_t x[5],c[15];
4513 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4514 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4515 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4517 Double_t sy =0.1, sz =0.1;
4519 Double_t sy1=0.2, sz1=0.2;
4520 Double_t sy2=0.2, sz2=0.2;
4523 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;
4524 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;
4525 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;
4526 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;
4527 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;
4528 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;
4530 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;
4531 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;
4532 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;
4533 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;
4538 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4539 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4540 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4541 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4542 c[13]=f30*sy1*f40+f32*sy2*f42;
4543 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4545 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4546 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4547 seed->SetPoolID(fLastSeedID);
4548 seed->SetLastPoint(row[2]);
4549 seed->SetFirstPoint(row[2]);
4550 for (Int_t i=row[0];i<row[2];i++){
4551 seed->SetClusterIndex(i, track->GetClusterIndex(i));
4559 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4562 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4564 // Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4566 // Two reasons to have multiple find tracks
4567 // 1. Curling tracks can be find more than once
4568 // 2. Splitted tracks
4569 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
4570 // b.) Edge effect on the sector boundaries
4573 // Algorithm done in 2 phases - because of CPU consumption
4574 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4576 // Algorihm for curling tracks sign:
4577 // 1 phase -makes a very rough fast cuts to minimize combinatorics
4578 // a.) opposite sign
4579 // b.) one of the tracks - not pointing to the primary vertex -
4580 // c.) delta tan(theta)
4582 // 2 phase - calculates DCA between tracks - time consument
4587 // General cuts - for splitted tracks and for curling tracks
4589 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
4591 // Curling tracks cuts
4596 Int_t nentries = array->GetEntriesFast();
4597 AliHelix *helixes = new AliHelix[nentries];
4598 Float_t *xm = new Float_t[nentries];
4599 Float_t *dz0 = new Float_t[nentries];
4600 Float_t *dz1 = new Float_t[nentries];
4606 // Find track COG in x direction - point with best defined parameters
4608 for (Int_t i=0;i<nentries;i++){
4609 AliTPCseed* track = (AliTPCseed*)array->At(i);
4610 if (!track) continue;
4611 track->SetCircular(0);
4612 new (&helixes[i]) AliHelix(*track);
4616 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4619 for (Int_t icl=0; icl<160; icl++){
4620 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
4626 if (ncl>0) xm[i]/=Float_t(ncl);
4629 for (Int_t i0=0;i0<nentries;i0++){
4630 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4631 if (!track0) continue;
4632 Float_t xc0 = helixes[i0].GetHelix(6);
4633 Float_t yc0 = helixes[i0].GetHelix(7);
4634 Float_t r0 = helixes[i0].GetHelix(8);
4635 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4636 Float_t fi0 = TMath::ATan2(yc0,xc0);
4638 for (Int_t i1=i0+1;i1<nentries;i1++){
4639 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4640 if (!track1) continue;
4641 Int_t lab0=track0->GetLabel();
4642 Int_t lab1=track1->GetLabel();
4643 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4645 Float_t xc1 = helixes[i1].GetHelix(6);
4646 Float_t yc1 = helixes[i1].GetHelix(7);
4647 Float_t r1 = helixes[i1].GetHelix(8);
4648 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4649 Float_t fi1 = TMath::ATan2(yc1,xc1);
4651 Float_t dfi = fi0-fi1;
4654 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4655 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4656 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4658 // if short tracks with undefined sign
4659 fi1 = -TMath::ATan2(yc1,-xc1);
4662 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4665 // debug stream to tune "fast cuts"
4667 Double_t dist[3]; // distance at X
4668 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
4669 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4670 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4671 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4672 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4673 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4674 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4675 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4679 for (Int_t icl=0; icl<160; icl++){
4680 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
4681 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
4684 if (cl0==cl1) sums++;
4688 if (AliTPCReconstructor::StreamLevel()>5) {
4689 TTreeSRedirector &cstream = *fDebugStreamer;
4694 "Tr0.="<<track0<< // seed0
4695 "Tr1.="<<track1<< // seed1
4696 "h0.="<<&helixes[i0]<<
4697 "h1.="<<&helixes[i1]<<
4699 "sum="<<sum<< //the sum of rows with cl in both
4700 "sums="<<sums<< //the sum of shared clusters
4701 "xm0="<<xm[i0]<< // the center of track
4702 "xm1="<<xm[i1]<< // the x center of track
4703 // General cut variables
4704 "dfi="<<dfi<< // distance in fi angle
4705 "dtheta="<<dtheta<< // distance int theta angle
4711 "dist0="<<dist[0]<< //distance x
4712 "dist1="<<dist[1]<< //distance y
4713 "dist2="<<dist[2]<< //distance z
4714 "mdist0="<<mdist[0]<< //distance x
4715 "mdist1="<<mdist[1]<< //distance y
4716 "mdist2="<<mdist[2]<< //distance z
4732 if (AliTPCReconstructor::StreamLevel()>1) {
4733 AliInfo("Time for curling tracks removal DEBUGGING MC");
4740 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
4742 // Find Splitted tracks and remove the one with worst quality
4743 // Corresponding debug streamer to tune selections - "Splitted2"
4745 // 0. Sort tracks according quility
4746 // 1. Propagate the tracks to the reference radius
4747 // 2. Double_t loop to select close tracks (only to speed up process)
4748 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
4749 // 4. Delete temporary parameters
4751 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
4753 const Double_t kCutP1=10; // delta Z cut 10 cm
4754 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
4755 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
4756 const Double_t kCutAlpha=0.15; // delta alpha cut
4757 Int_t firstpoint = 0;
4758 Int_t lastpoint = 160;
4760 Int_t nentries = array->GetEntriesFast();
4761 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
4767 //0. Sort tracks according quality
4768 //1. Propagate the ext. param to reference radius
4769 Int_t nseed = array->GetEntriesFast();
4770 if (nseed<=0) return;
4771 Float_t * quality = new Float_t[nseed];
4772 Int_t * indexes = new Int_t[nseed];
4773 for (Int_t i=0; i<nseed; i++) {
4774 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
4779 pt->UpdatePoints(); //select first last max dens points
4780 Float_t * points = pt->GetPoints();
4781 if (points[3]<0.8) quality[i] =-1;
4782 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4783 //prefer high momenta tracks if overlaps
4784 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
4786 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
4787 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
4789 TMath::Sort(nseed,quality,indexes);
4791 // 3. Loop over pair of tracks
4793 for (Int_t i0=0; i0<nseed; i0++) {
4794 Int_t index0=indexes[i0];
4795 if (!(array->UncheckedAt(index0))) continue;
4796 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
4797 if (!s1->IsActive()) continue;
4798 AliExternalTrackParam &par0=params[index0];
4799 for (Int_t i1=i0+1; i1<nseed; i1++) {
4800 Int_t index1=indexes[i1];
4801 if (!(array->UncheckedAt(index1))) continue;
4802 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
4803 if (!s2->IsActive()) continue;
4804 if (s2->GetKinkIndexes()[0]!=0)
4805 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
4806 AliExternalTrackParam &par1=params[index1];
4807 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
4808 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
4809 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
4810 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
4811 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
4812 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
4817 Int_t firstShared=lastpoint, lastShared=firstpoint;
4818 Int_t firstRow=lastpoint, lastRow=firstpoint;
4820 for (Int_t i=firstpoint;i<lastpoint;i++){
4821 if (s1->GetClusterIndex2(i)>0) nall0++;
4822 if (s2->GetClusterIndex2(i)>0) nall1++;
4823 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
4824 if (i<firstRow) firstRow=i;
4825 if (i>lastRow) lastRow=i;
4827 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
4828 if (i<firstShared) firstShared=i;
4829 if (i>lastShared) lastShared=i;
4833 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
4834 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
4836 if( AliTPCReconstructor::StreamLevel()>1){
4837 TTreeSRedirector &cstream = *fDebugStreamer;
4838 Int_t n0=s1->GetNumberOfClusters();
4839 Int_t n1=s2->GetNumberOfClusters();
4840 Int_t n0F=s1->GetNFoundable();
4841 Int_t n1F=s2->GetNFoundable();
4842 Int_t lab0=s1->GetLabel();
4843 Int_t lab1=s2->GetLabel();
4845 cstream<<"Splitted2"<<
4846 "iter="<<fIteration<<
4847 "lab0="<<lab0<< // MC label if exist
4848 "lab1="<<lab1<< // MC label if exist
4851 "ratio0="<<ratio0<< // shared ratio
4852 "ratio1="<<ratio1<< // shared ratio
4853 "p0.="<<&par0<< // track parameters
4855 "s0.="<<s1<< // full seed
4857 "n0="<<n0<< // number of clusters track 0
4858 "n1="<<n1<< // number of clusters track 1
4859 "nall0="<<nall0<< // number of clusters track 0
4860 "nall1="<<nall1<< // number of clusters track 1
4861 "n0F="<<n0F<< // number of findable
4862 "n1F="<<n1F<< // number of findable
4863 "shared="<<sumShared<< // number of shared clusters
4864 "firstS="<<firstShared<< // first and the last shared row
4865 "lastS="<<lastShared<<
4866 "firstRow="<<firstRow<< // first and the last row with cluster
4867 "lastRow="<<lastRow<< //
4871 // remove track with lower quality
4873 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
4874 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
4878 MarkSeedFree( array->RemoveAt(index1) );
4883 // 4. Delete temporary array
4893 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4896 // find Curling tracks
4897 // Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4900 // Algorithm done in 2 phases - because of CPU consumption
4901 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4902 // see detal in MC part what can be used to cut
4906 const Float_t kMaxC = 400; // maximal curvature to of the track
4907 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
4908 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
4909 const Float_t kPtRatio = 0.3; // ratio between pt
4910 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
4913 // Curling tracks cuts
4916 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
4917 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
4918 const Float_t kMinAngle = 2.9; // angle between tracks
4919 const Float_t kMaxDist = 5; // biggest distance
4921 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4924 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4925 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4926 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4927 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4928 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
4930 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4931 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4933 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
4934 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4936 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4942 Int_t nentries = array->GetEntriesFast();
4943 AliHelix *helixes = new AliHelix[nentries];
4944 for (Int_t i=0;i<nentries;i++){
4945 AliTPCseed* track = (AliTPCseed*)array->At(i);
4946 if (!track) continue;
4947 track->SetCircular(0);
4948 new (&helixes[i]) AliHelix(*track);
4954 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4960 for (Int_t i0=0;i0<nentries;i0++){
4961 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4962 if (!track0) continue;
4963 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4964 Float_t xc0 = helixes[i0].GetHelix(6);
4965 Float_t yc0 = helixes[i0].GetHelix(7);
4966 Float_t r0 = helixes[i0].GetHelix(8);
4967 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4968 Float_t fi0 = TMath::ATan2(yc0,xc0);
4970 for (Int_t i1=i0+1;i1<nentries;i1++){
4971 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4972 if (!track1) continue;
4973 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
4974 Float_t xc1 = helixes[i1].GetHelix(6);
4975 Float_t yc1 = helixes[i1].GetHelix(7);
4976 Float_t r1 = helixes[i1].GetHelix(8);
4977 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4978 Float_t fi1 = TMath::ATan2(yc1,xc1);
4980 Float_t dfi = fi0-fi1;
4983 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4984 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4985 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4989 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
4990 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
4991 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4992 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
4993 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4995 Float_t pt0 = track0->GetSignedPt();
4996 Float_t pt1 = track1->GetSignedPt();
4997 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
4998 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4999 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
5000 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
5003 // Now find closest approach
5007 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5008 if (npoints==0) continue;
5009 helixes[i0].GetClosestPhases(helixes[i1], phase);
5013 Double_t hangles[3];
5014 helixes[i0].Evaluate(phase[0][0],xyz0);
5015 helixes[i1].Evaluate(phase[0][1],xyz1);
5017 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5018 Double_t deltah[2],deltabest;
5019 if (TMath::Abs(hangles[2])<kMinAngle) continue;
5023 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5025 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5026 if (deltah[1]<deltah[0]) ibest=1;
5028 deltabest = TMath::Sqrt(deltah[ibest]);
5029 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5030 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5031 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5032 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5034 if (deltabest>kMaxDist) continue;
5035 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5036 Bool_t sign =kFALSE;
5037 if (hangles[2]>kMinAngle) sign =kTRUE;
5040 // circular[i0] = kTRUE;
5041 // circular[i1] = kTRUE;
5042 if (track0->OneOverPt()<track1->OneOverPt()){
5043 track0->SetCircular(track0->GetCircular()+1);
5044 track1->SetCircular(track1->GetCircular()+2);
5047 track1->SetCircular(track1->GetCircular()+1);
5048 track0->SetCircular(track0->GetCircular()+2);
5051 if (AliTPCReconstructor::StreamLevel()>2){
5053 //debug stream to tune "fine" cuts
5054 Int_t lab0=track0->GetLabel();
5055 Int_t lab1=track1->GetLabel();
5056 TTreeSRedirector &cstream = *fDebugStreamer;
5057 cstream<<"Curling2"<<
5073 "npoints="<<npoints<<
5074 "hangles0="<<hangles[0]<<
5075 "hangles1="<<hangles[1]<<
5076 "hangles2="<<hangles[2]<<
5079 "radius="<<radiusbest<<
5080 "deltabest="<<deltabest<<
5081 "phase0="<<phase[ibest][0]<<
5082 "phase1="<<phase[ibest][1]<<
5090 if (AliTPCReconstructor::StreamLevel()>1) {
5091 AliInfo("Time for curling tracks removal");
5097 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5103 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5106 TObjArray *kinks= new TObjArray(10000);
5107 // TObjArray *v0s= new TObjArray(10000);
5108 Int_t nentries = array->GetEntriesFast();
5109 AliHelix *helixes = new AliHelix[nentries];
5110 Int_t *sign = new Int_t[nentries];
5111 Int_t *nclusters = new Int_t[nentries];
5112 Float_t *alpha = new Float_t[nentries];
5113 AliKink *kink = new AliKink();
5114 Int_t * usage = new Int_t[nentries];
5115 Float_t *zm = new Float_t[nentries];
5116 Float_t *z0 = new Float_t[nentries];
5117 Float_t *fim = new Float_t[nentries];
5118 Float_t *shared = new Float_t[nentries];
5119 Bool_t *circular = new Bool_t[nentries];
5120 Float_t *dca = new Float_t[nentries];
5121 //const AliESDVertex * primvertex = esd->GetVertex();
5123 // nentries = array->GetEntriesFast();
5128 for (Int_t i=0;i<nentries;i++){
5131 AliTPCseed* track = (AliTPCseed*)array->At(i);
5132 if (!track) continue;
5133 track->SetCircular(0);
5135 track->UpdatePoints();
5136 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5138 nclusters[i]=track->GetNumberOfClusters();
5139 alpha[i] = track->GetAlpha();
5140 new (&helixes[i]) AliHelix(*track);
5142 helixes[i].Evaluate(0,xyz);
5143 sign[i] = (track->GetC()>0) ? -1:1;
5146 if (track->GetProlongation(x,y,z)){
5148 fim[i] = alpha[i]+TMath::ATan2(y,x);
5151 zm[i] = track->GetZ();
5155 circular[i]= kFALSE;
5156 if (track->GetProlongation(0,y,z)) z0[i] = z;
5157 dca[i] = track->GetD(0,0);
5163 Int_t ncandidates =0;
5166 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5169 // Find circling track
5171 for (Int_t i0=0;i0<nentries;i0++){
5172 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5173 if (!track0) continue;
5174 if (track0->GetNumberOfClusters()<40) continue;
5175 if (TMath::Abs(1./track0->GetC())>200) continue;
5176 for (Int_t i1=i0+1;i1<nentries;i1++){
5177 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5178 if (!track1) continue;
5179 if (track1->GetNumberOfClusters()<40) continue;
5180 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5181 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5182 if (TMath::Abs(1./track1->GetC())>200) continue;
5183 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5184 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5185 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5186 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5187 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5189 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5190 if (mindcar<5) continue;
5191 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5192 if (mindcaz<5) continue;
5193 if (mindcar+mindcaz<20) continue;
5196 Float_t xc0 = helixes[i0].GetHelix(6);
5197 Float_t yc0 = helixes[i0].GetHelix(7);
5198 Float_t r0 = helixes[i0].GetHelix(8);
5199 Float_t xc1 = helixes[i1].GetHelix(6);
5200 Float_t yc1 = helixes[i1].GetHelix(7);
5201 Float_t r1 = helixes[i1].GetHelix(8);
5203 Float_t rmean = (r0+r1)*0.5;
5204 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5205 //if (delta>30) continue;
5206 if (delta>rmean*0.25) continue;
5207 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5209 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5210 if (npoints==0) continue;
5211 helixes[i0].GetClosestPhases(helixes[i1], phase);
5215 Double_t hangles[3];
5216 helixes[i0].Evaluate(phase[0][0],xyz0);
5217 helixes[i1].Evaluate(phase[0][1],xyz1);
5219 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5220 Double_t deltah[2],deltabest;
5221 if (hangles[2]<2.8) continue;
5224 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5226 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5227 if (deltah[1]<deltah[0]) ibest=1;
5229 deltabest = TMath::Sqrt(deltah[ibest]);
5230 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5231 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5232 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5233 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5235 if (deltabest>6) continue;
5236 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5237 Bool_t lsign =kFALSE;
5238 if (hangles[2]>3.06) lsign =kTRUE;
5241 circular[i0] = kTRUE;
5242 circular[i1] = kTRUE;
5243 if (track0->OneOverPt()<track1->OneOverPt()){
5244 track0->SetCircular(track0->GetCircular()+1);
5245 track1->SetCircular(track1->GetCircular()+2);
5248 track1->SetCircular(track1->GetCircular()+1);
5249 track0->SetCircular(track0->GetCircular()+2);
5252 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5254 Int_t lab0=track0->GetLabel();
5255 Int_t lab1=track1->GetLabel();
5256 TTreeSRedirector &cstream = *fDebugStreamer;
5257 cstream<<"Curling"<<
5264 "mindcar="<<mindcar<<
5265 "mindcaz="<<mindcaz<<
5268 "npoints="<<npoints<<
5269 "hangles0="<<hangles[0]<<
5270 "hangles2="<<hangles[2]<<
5275 "radius="<<radiusbest<<
5276 "deltabest="<<deltabest<<
5277 "phase0="<<phase[ibest][0]<<
5278 "phase1="<<phase[ibest][1]<<
5288 for (Int_t i =0;i<nentries;i++){
5289 if (sign[i]==0) continue;
5290 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5297 Double_t cradius0 = 40*40;
5298 Double_t cradius1 = 270*270;
5301 Double_t cdist3=0.55;
5302 for (Int_t j =i+1;j<nentries;j++){
5304 if (sign[j]*sign[i]<1) continue;
5305 if ( (nclusters[i]+nclusters[j])>200) continue;
5306 if ( (nclusters[i]+nclusters[j])<80) continue;
5307 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5308 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5309 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5310 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5311 if (npoints<1) continue;
5314 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5317 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5320 Double_t delta1=10000,delta2=10000;
5321 // cuts on the intersection radius
5322 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5323 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5324 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5326 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5327 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5328 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5331 Double_t distance1 = TMath::Min(delta1,delta2);
5332 if (distance1>cdist1) continue; // cut on DCA linear approximation
5334 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5335 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5336 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5337 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5340 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5341 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5342 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5344 distance1 = TMath::Min(delta1,delta2);
5347 rkink = TMath::Sqrt(radius[0]);
5350 rkink = TMath::Sqrt(radius[1]);
5352 if (distance1>cdist2) continue;
5355 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5358 Int_t row0 = GetRowNumber(rkink);
5359 if (row0<10) continue;
5360 if (row0>150) continue;
5363 Float_t dens00=-1,dens01=-1;
5364 Float_t dens10=-1,dens11=-1;
5366 Int_t found,foundable,ishared;
5367 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5368 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5369 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5370 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5372 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5373 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5374 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5375 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5377 if (dens00<dens10 && dens01<dens11) continue;
5378 if (dens00>dens10 && dens01>dens11) continue;
5379 if (TMath::Max(dens00,dens10)<0.1) continue;
5380 if (TMath::Max(dens01,dens11)<0.3) continue;
5382 if (TMath::Min(dens00,dens10)>0.6) continue;
5383 if (TMath::Min(dens01,dens11)>0.6) continue;
5386 AliTPCseed * ktrack0, *ktrack1;
5395 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5396 AliExternalTrackParam paramm(*ktrack0);
5397 AliExternalTrackParam paramd(*ktrack1);
5398 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5401 kink->SetMother(paramm);
5402 kink->SetDaughter(paramd);
5405 Float_t x[3] = { static_cast<Float_t>(kink->GetPosition()[0]),static_cast<Float_t>(kink->GetPosition()[1]),static_cast<Float_t>(kink->GetPosition()[2])};
5407 fkParam->Transform0to1(x,index);
5408 fkParam->Transform1to2(x,index);
5409 row0 = GetRowNumber(x[0]);
5411 if (kink->GetR()<100) continue;
5412 if (kink->GetR()>240) continue;
5413 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5414 if (kink->GetDistance()>cdist3) continue;
5415 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5416 if (dird<0) continue;
5418 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5419 if (dirm<0) continue;
5420 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5421 if (mpt<0.2) continue;
5424 //for high momenta momentum not defined well in first iteration
5425 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5426 if (qt>0.35) continue;
5429 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5430 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5432 kink->SetTPCDensity(dens00,0,0);
5433 kink->SetTPCDensity(dens01,0,1);
5434 kink->SetTPCDensity(dens10,1,0);
5435 kink->SetTPCDensity(dens11,1,1);
5436 kink->SetIndex(i,0);
5437 kink->SetIndex(j,1);
5440 kink->SetTPCDensity(dens10,0,0);
5441 kink->SetTPCDensity(dens11,0,1);
5442 kink->SetTPCDensity(dens00,1,0);
5443 kink->SetTPCDensity(dens01,1,1);
5444 kink->SetIndex(j,0);
5445 kink->SetIndex(i,1);
5448 if (mpt<1||kink->GetAngle(2)>0.1){
5449 // angle and densities not defined yet
5450 if (kink->GetTPCDensityFactor()<0.8) continue;
5451 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5452 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5453 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5454 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5456 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5457 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5458 criticalangle= 3*TMath::Sqrt(criticalangle);
5459 if (criticalangle>0.02) criticalangle=0.02;
5460 if (kink->GetAngle(2)<criticalangle) continue;
5463 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5464 Float_t shapesum =0;
5466 for ( Int_t row = row0-drow; row<row0+drow;row++){
5467 if (row<0) continue;
5468 if (row>155) continue;
5469 if (ktrack0->GetClusterPointer(row)){
5470 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5471 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5474 if (ktrack1->GetClusterPointer(row)){
5475 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5476 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5481 kink->SetShapeFactor(-1.);
5484 kink->SetShapeFactor(shapesum/sum);
5486 // esd->AddKink(kink);
5488 // kink->SetMother(paramm);
5489 //kink->SetDaughter(paramd);
5491 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5493 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5494 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5496 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5498 if (AliTPCReconstructor::StreamLevel()>1) {
5499 (*fDebugStreamer)<<"kinkLpt"<<
5507 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5511 kinks->AddLast(kink);
5517 // sort the kinks according quality - and refit them towards vertex
5519 Int_t nkinks = kinks->GetEntriesFast();
5520 Float_t *quality = new Float_t[nkinks];
5521 Int_t *indexes = new Int_t[nkinks];
5522 AliTPCseed *mothers = new AliTPCseed[nkinks];
5523 AliTPCseed *daughters = new AliTPCseed[nkinks];
5526 for (Int_t i=0;i<nkinks;i++){
5528 AliKink *kinkl = (AliKink*)kinks->At(i);
5530 // refit kinks towards vertex
5532 Int_t index0 = kinkl->GetIndex(0);
5533 Int_t index1 = kinkl->GetIndex(1);
5534 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5535 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5537 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5539 // Refit Kink under if too small angle
5541 if (kinkl->GetAngle(2)<0.05){
5542 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5543 Int_t row0 = kinkl->GetTPCRow0();
5544 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5547 Int_t last = row0-drow;
5548 if (last<40) last=40;
5549 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5550 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5553 Int_t first = row0+drow;
5554 if (first>130) first=130;
5555 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5556 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5558 if (seed0 && seed1){
5559 kinkl->SetStatus(1,8);
5560 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5561 row0 = GetRowNumber(kinkl->GetR());
5562 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5563 mothers[i] = *seed0;
5564 daughters[i] = *seed1;
5567 delete kinks->RemoveAt(i);
5568 if (seed0) MarkSeedFree( seed0 );
5569 if (seed1) MarkSeedFree( seed1 );
5572 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
5573 delete kinks->RemoveAt(i);
5574 if (seed0) MarkSeedFree( seed0 );
5575 if (seed1) MarkSeedFree( seed1 );
5579 MarkSeedFree( seed0 );
5580 MarkSeedFree( seed1 );
5583 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
5585 TMath::Sort(nkinks,quality,indexes,kFALSE);
5587 //remove double find kinks
5589 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5590 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5591 if (!kink0) continue;
5593 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5594 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5595 if (!kink0) continue;
5596 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5597 if (!kink1) continue;
5598 // if not close kink continue
5599 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5600 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5601 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5603 AliTPCseed &mother0 = mothers[indexes[ikink0]];
5604 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5605 AliTPCseed &mother1 = mothers[indexes[ikink1]];
5606 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5607 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5616 for (Int_t i=0;i<row0;i++){
5617 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5620 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5627 for (Int_t i=row0;i<158;i++){
5628 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
5629 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
5632 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5638 Float_t ratio = Float_t(same+1)/Float_t(both+1);
5639 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5640 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5641 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5642 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5643 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5645 shared[kink0->GetIndex(0)]= kTRUE;
5646 shared[kink0->GetIndex(1)]= kTRUE;
5647 delete kinks->RemoveAt(indexes[ikink0]);
5651 shared[kink1->GetIndex(0)]= kTRUE;
5652 shared[kink1->GetIndex(1)]= kTRUE;
5653 delete kinks->RemoveAt(indexes[ikink1]);
5660 for (Int_t i=0;i<nkinks;i++){
5661 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
5662 if (!kinkl) continue;
5663 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5664 Int_t index0 = kinkl->GetIndex(0);
5665 Int_t index1 = kinkl->GetIndex(1);
5666 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
5667 kinkl->SetMultiple(usage[index0],0);
5668 kinkl->SetMultiple(usage[index1],1);
5669 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
5670 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5671 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
5672 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
5674 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5675 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5676 if (!ktrack0 || !ktrack1) continue;
5677 Int_t index = esd->AddKink(kinkl);
5680 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
5681 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5682 *ktrack0 = mothers[indexes[i]];
5683 *ktrack1 = daughters[indexes[i]];
5687 ktrack0->SetKinkIndex(usage[index0],-(index+1));
5688 ktrack1->SetKinkIndex(usage[index1], (index+1));
5693 // Remove tracks corresponding to shared kink's
5695 for (Int_t i=0;i<nentries;i++){
5696 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5697 if (!track0) continue;
5698 if (track0->GetKinkIndex(0)!=0) continue;
5699 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
5704 RemoveUsed2(array,0.5,0.4,30);
5706 for (Int_t i=0;i<nentries;i++){
5707 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5708 if (!track0) continue;
5709 track0->CookdEdx(0.02,0.6);
5713 for (Int_t i=0;i<nentries;i++){
5714 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5715 if (!track0) continue;
5716 if (track0->Pt()<1.4) continue;
5717 //remove double high momenta tracks - overlapped with kink candidates
5720 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5721 if (track0->GetClusterPointer(icl)!=0){
5723 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
5726 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
5727 MarkSeedFree( array->RemoveAt(i) );
5731 if (track0->GetKinkIndex(0)!=0) continue;
5732 if (track0->GetNumberOfClusters()<80) continue;
5734 AliTPCseed *pmother = new AliTPCseed();
5735 AliTPCseed *pdaughter = new AliTPCseed();
5736 AliKink *pkink = new AliKink;
5738 AliTPCseed & mother = *pmother;
5739 AliTPCseed & daughter = *pdaughter;
5740 AliKink & kinkl = *pkink;
5741 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
5742 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5746 continue; //too short tracks
5748 if (mother.Pt()<1.4) {
5754 Int_t row0= kinkl.GetTPCRow0();
5755 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
5762 Int_t index = esd->AddKink(&kinkl);
5763 mother.SetKinkIndex(0,-(index+1));
5764 daughter.SetKinkIndex(0,index+1);
5765 if (mother.GetNumberOfClusters()>50) {
5766 MarkSeedFree( array->RemoveAt(i) );
5767 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5768 mtc->SetPoolID(fLastSeedID);
5769 array->AddAt(mtc,i);
5772 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5773 mtc->SetPoolID(fLastSeedID);
5774 array->AddLast(mtc);
5776 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
5777 dtc->SetPoolID(fLastSeedID);
5778 array->AddLast(dtc);
5779 for (Int_t icl=0;icl<row0;icl++) {
5780 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5783 for (Int_t icl=row0;icl<158;icl++) {
5784 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5793 delete [] daughters;
5815 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
5821 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5828 TObjArray *kinks= new TObjArray(10000);
5829 // TObjArray *v0s= new TObjArray(10000);
5830 Int_t nentries = array->GetEntriesFast();
5831 AliHelix *helixes = new AliHelix[nentries];
5832 Int_t *sign = new Int_t[nentries];
5833 Int_t *nclusters = new Int_t[nentries];
5834 Float_t *alpha = new Float_t[nentries];
5835 AliKink *kink = new AliKink();
5836 Int_t * usage = new Int_t[nentries];
5837 Float_t *zm = new Float_t[nentries];
5838 Float_t *z0 = new Float_t[nentries];
5839 Float_t *fim = new Float_t[nentries];
5840 Float_t *shared = new Float_t[nentries];
5841 Bool_t *circular = new Bool_t[nentries];
5842 Float_t *dca = new Float_t[nentries];
5843 //const AliESDVertex * primvertex = esd->GetVertex();
5845 // nentries = array->GetEntriesFast();
5850 for (Int_t i=0;i<nentries;i++){
5853 AliTPCseed* track = (AliTPCseed*)array->At(i);
5854 if (!track) continue;
5855 track->SetCircular(0);
5857 track->UpdatePoints();
5858 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5860 nclusters[i]=track->GetNumberOfClusters();
5861 alpha[i] = track->GetAlpha();
5862 new (&helixes[i]) AliHelix(*track);
5864 helixes[i].Evaluate(0,xyz);
5865 sign[i] = (track->GetC()>0) ? -1:1;
5868 if (track->GetProlongation(x,y,z)){
5870 fim[i] = alpha[i]+TMath::ATan2(y,x);
5873 zm[i] = track->GetZ();
5877 circular[i]= kFALSE;
5878 if (track->GetProlongation(0,y,z)) z0[i] = z;
5879 dca[i] = track->GetD(0,0);
5885 Int_t ncandidates =0;
5888 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5891 // Find circling track
5893 for (Int_t i0=0;i0<nentries;i0++){
5894 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5895 if (!track0) continue;
5896 if (track0->GetNumberOfClusters()<40) continue;
5897 if (TMath::Abs(1./track0->GetC())>200) continue;
5898 for (Int_t i1=i0+1;i1<nentries;i1++){
5899 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5900 if (!track1) continue;
5901 if (track1->GetNumberOfClusters()<40) continue;
5902 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5903 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5904 if (TMath::Abs(1./track1->GetC())>200) continue;
5905 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5906 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5907 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5908 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5909 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5911 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5912 if (mindcar<5) continue;
5913 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5914 if (mindcaz<5) continue;
5915 if (mindcar+mindcaz<20) continue;
5918 Float_t xc0 = helixes[i0].GetHelix(6);
5919 Float_t yc0 = helixes[i0].GetHelix(7);
5920 Float_t r0 = helixes[i0].GetHelix(8);
5921 Float_t xc1 = helixes[i1].GetHelix(6);
5922 Float_t yc1 = helixes[i1].GetHelix(7);
5923 Float_t r1 = helixes[i1].GetHelix(8);
5925 Float_t rmean = (r0+r1)*0.5;
5926 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5927 //if (delta>30) continue;
5928 if (delta>rmean*0.25) continue;
5929 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5931 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5932 if (npoints==0) continue;
5933 helixes[i0].GetClosestPhases(helixes[i1], phase);
5937 Double_t hangles[3];
5938 helixes[i0].Evaluate(phase[0][0],xyz0);
5939 helixes[i1].Evaluate(phase[0][1],xyz1);
5941 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5942 Double_t deltah[2],deltabest;
5943 if (hangles[2]<2.8) continue;
5946 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5948 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5949 if (deltah[1]<deltah[0]) ibest=1;
5951 deltabest = TMath::Sqrt(deltah[ibest]);
5952 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5953 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5954 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5955 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5957 if (deltabest>6) continue;
5958 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5959 Bool_t lsign =kFALSE;
5960 if (hangles[2]>3.06) lsign =kTRUE;
5963 circular[i0] = kTRUE;
5964 circular[i1] = kTRUE;
5965 if (track0->OneOverPt()<track1->OneOverPt()){
5966 track0->SetCircular(track0->GetCircular()+1);
5967 track1->SetCircular(track1->GetCircular()+2);
5970 track1->SetCircular(track1->GetCircular()+1);
5971 track0->SetCircular(track0->GetCircular()+2);
5974 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5976 Int_t lab0=track0->GetLabel();
5977 Int_t lab1=track1->GetLabel();
5978 TTreeSRedirector &cstream = *fDebugStreamer;
5979 cstream<<"Curling"<<
5986 "mindcar="<<mindcar<<
5987 "mindcaz="<<mindcaz<<
5990 "npoints="<<npoints<<
5991 "hangles0="<<hangles[0]<<
5992 "hangles2="<<hangles[2]<<
5997 "radius="<<radiusbest<<
5998 "deltabest="<<deltabest<<
5999 "phase0="<<phase[ibest][0]<<
6000 "phase1="<<phase[ibest][1]<<
6010 for (Int_t i =0;i<nentries;i++){
6011 if (sign[i]==0) continue;
6012 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6019 Double_t cradius0 = 40*40;
6020 Double_t cradius1 = 270*270;
6023 Double_t cdist3=0.55;
6024 for (Int_t j =i+1;j<nentries;j++){
6026 if (sign[j]*sign[i]<1) continue;
6027 if ( (nclusters[i]+nclusters[j])>200) continue;
6028 if ( (nclusters[i]+nclusters[j])<80) continue;
6029 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6030 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6031 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6032 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6033 if (npoints<1) continue;
6036 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6039 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6042 Double_t delta1=10000,delta2=10000;
6043 // cuts on the intersection radius
6044 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6045 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6046 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6048 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6049 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6050 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6053 Double_t distance1 = TMath::Min(delta1,delta2);
6054 if (distance1>cdist1) continue; // cut on DCA linear approximation
6056 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6057 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6058 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6059 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6062 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6063 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6064 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6066 distance1 = TMath::Min(delta1,delta2);
6069 rkink = TMath::Sqrt(radius[0]);
6072 rkink = TMath::Sqrt(radius[1]);
6074 if (distance1>cdist2) continue;
6077 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6080 Int_t row0 = GetRowNumber(rkink);
6081 if (row0<10) continue;
6082 if (row0>150) continue;
6085 Float_t dens00=-1,dens01=-1;
6086 Float_t dens10=-1,dens11=-1;
6088 Int_t found,foundable,ishared;
6089 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6090 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6091 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6092 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6094 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6095 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6096 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6097 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6099 if (dens00<dens10 && dens01<dens11) continue;
6100 if (dens00>dens10 && dens01>dens11) continue;
6101 if (TMath::Max(dens00,dens10)<0.1) continue;
6102 if (TMath::Max(dens01,dens11)<0.3) continue;
6104 if (TMath::Min(dens00,dens10)>0.6) continue;
6105 if (TMath::Min(dens01,dens11)>0.6) continue;
6108 AliTPCseed * ktrack0, *ktrack1;
6117 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6118 AliExternalTrackParam paramm(*ktrack0);
6119 AliExternalTrackParam paramd(*ktrack1);
6120 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6123 kink->SetMother(paramm);
6124 kink->SetDaughter(paramd);
6127 Float_t x[3] = { static_cast<Float_t>(kink->GetPosition()[0]),static_cast<Float_t>(kink->GetPosition()[1]),static_cast<Float_t>(kink->GetPosition()[2])};
6129 fkParam->Transform0to1(x,index);
6130 fkParam->Transform1to2(x,index);
6131 row0 = GetRowNumber(x[0]);
6133 if (kink->GetR()<100) continue;
6134 if (kink->GetR()>240) continue;
6135 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6136 if (kink->GetDistance()>cdist3) continue;
6137 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6138 if (dird<0) continue;
6140 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6141 if (dirm<0) continue;
6142 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6143 if (mpt<0.2) continue;
6146 //for high momenta momentum not defined well in first iteration
6147 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6148 if (qt>0.35) continue;
6151 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6152 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6154 kink->SetTPCDensity(dens00,0,0);
6155 kink->SetTPCDensity(dens01,0,1);
6156 kink->SetTPCDensity(dens10,1,0);
6157 kink->SetTPCDensity(dens11,1,1);
6158 kink->SetIndex(i,0);
6159 kink->SetIndex(j,1);
6162 kink->SetTPCDensity(dens10,0,0);
6163 kink->SetTPCDensity(dens11,0,1);
6164 kink->SetTPCDensity(dens00,1,0);
6165 kink->SetTPCDensity(dens01,1,1);
6166 kink->SetIndex(j,0);
6167 kink->SetIndex(i,1);
6170 if (mpt<1||kink->GetAngle(2)>0.1){
6171 // angle and densities not defined yet
6172 if (kink->GetTPCDensityFactor()<0.8) continue;
6173 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6174 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6175 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6176 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6178 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6179 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6180 criticalangle= 3*TMath::Sqrt(criticalangle);
6181 if (criticalangle>0.02) criticalangle=0.02;
6182 if (kink->GetAngle(2)<criticalangle) continue;
6185 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6186 Float_t shapesum =0;
6188 for ( Int_t row = row0-drow; row<row0+drow;row++){
6189 if (row<0) continue;
6190 if (row>155) continue;
6191 if (ktrack0->GetClusterPointer(row)){
6192 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6193 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6196 if (ktrack1->GetClusterPointer(row)){
6197 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6198 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6203 kink->SetShapeFactor(-1.);
6206 kink->SetShapeFactor(shapesum/sum);
6208 // esd->AddKink(kink);
6210 // kink->SetMother(paramm);
6211 //kink->SetDaughter(paramd);
6213 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6215 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6216 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6218 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6220 if (AliTPCReconstructor::StreamLevel()>1) {
6221 (*fDebugStreamer)<<"kinkLpt"<<
6229 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6233 kinks->AddLast(kink);
6239 // sort the kinks according quality - and refit them towards vertex
6241 Int_t nkinks = kinks->GetEntriesFast();
6242 Float_t *quality = new Float_t[nkinks];
6243 Int_t *indexes = new Int_t[nkinks];
6244 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6245 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6248 for (Int_t i=0;i<nkinks;i++){
6250 AliKink *kinkl = (AliKink*)kinks->At(i);
6252 // refit kinks towards vertex
6254 Int_t index0 = kinkl->GetIndex(0);
6255 Int_t index1 = kinkl->GetIndex(1);
6256 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6257 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6259 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6261 // Refit Kink under if too small angle
6263 if (kinkl->GetAngle(2)<0.05){
6264 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6265 Int_t row0 = kinkl->GetTPCRow0();
6266 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6269 Int_t last = row0-drow;
6270 if (last<40) last=40;
6271 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6272 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6275 Int_t first = row0+drow;
6276 if (first>130) first=130;
6277 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6278 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6280 if (seed0 && seed1){
6281 kinkl->SetStatus(1,8);
6282 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6283 row0 = GetRowNumber(kinkl->GetR());
6284 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6285 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6286 mothers[i]->SetPoolID(fLastSeedID);
6287 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6288 daughters[i]->SetPoolID(fLastSeedID);
6291 delete kinks->RemoveAt(i);
6292 if (seed0) MarkSeedFree( seed0 );
6293 if (seed1) MarkSeedFree( seed1 );
6296 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6297 delete kinks->RemoveAt(i);
6298 if (seed0) MarkSeedFree( seed0 );
6299 if (seed1) MarkSeedFree( seed1 );
6303 MarkSeedFree( seed0 );
6304 MarkSeedFree( seed1 );
6307 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6309 TMath::Sort(nkinks,quality,indexes,kFALSE);
6311 //remove double find kinks
6313 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6314 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6315 if (!kink0) continue;
6317 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6318 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6319 if (!kink0) continue;
6320 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6321 if (!kink1) continue;
6322 // if not close kink continue
6323 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6324 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6325 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6327 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6328 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6329 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6330 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6331 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6340 for (Int_t i=0;i<row0;i++){
6341 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6344 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6351 for (Int_t i=row0;i<158;i++){
6352 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6353 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6356 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6362 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6363 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6364 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6365 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6366 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6367 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6369 shared[kink0->GetIndex(0)]= kTRUE;
6370 shared[kink0->GetIndex(1)]= kTRUE;
6371 delete kinks->RemoveAt(indexes[ikink0]);
6375 shared[kink1->GetIndex(0)]= kTRUE;
6376 shared[kink1->GetIndex(1)]= kTRUE;
6377 delete kinks->RemoveAt(indexes[ikink1]);
6384 for (Int_t i=0;i<nkinks;i++){
6385 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6386 if (!kinkl) continue;
6387 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6388 Int_t index0 = kinkl->GetIndex(0);
6389 Int_t index1 = kinkl->GetIndex(1);
6390 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6391 kinkl->SetMultiple(usage[index0],0);
6392 kinkl->SetMultiple(usage[index1],1);
6393 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6394 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6395 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6396 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6398 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6399 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6400 if (!ktrack0 || !ktrack1) continue;
6401 Int_t index = esd->AddKink(kinkl);
6404 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6405 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6406 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6407 *ktrack0 = *mothers[indexes[i]];
6408 *ktrack1 = *daughters[indexes[i]];
6412 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6413 ktrack1->SetKinkIndex(usage[index1], (index+1));
6418 // Remove tracks corresponding to shared kink's
6420 for (Int_t i=0;i<nentries;i++){
6421 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6422 if (!track0) continue;
6423 if (track0->GetKinkIndex(0)!=0) continue;
6424 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6429 RemoveUsed2(array,0.5,0.4,30);
6431 for (Int_t i=0;i<nentries;i++){
6432 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6433 if (!track0) continue;
6434 track0->CookdEdx(0.02,0.6);
6438 for (Int_t i=0;i<nentries;i++){
6439 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6440 if (!track0) continue;
6441 if (track0->Pt()<1.4) continue;
6442 //remove double high momenta tracks - overlapped with kink candidates
6445 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6446 if (track0->GetClusterPointer(icl)!=0){
6448 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6451 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6452 MarkSeedFree( array->RemoveAt(i) );
6456 if (track0->GetKinkIndex(0)!=0) continue;
6457 if (track0->GetNumberOfClusters()<80) continue;
6459 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6460 pmother->SetPoolID(fLastSeedID);
6461 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6462 pdaughter->SetPoolID(fLastSeedID);
6463 AliKink *pkink = new AliKink;
6465 AliTPCseed & mother = *pmother;
6466 AliTPCseed & daughter = *pdaughter;
6467 AliKink & kinkl = *pkink;
6468 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6469 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6470 MarkSeedFree( pmother );
6471 MarkSeedFree( pdaughter );
6473 continue; //too short tracks
6475 if (mother.Pt()<1.4) {
6476 MarkSeedFree( pmother );
6477 MarkSeedFree( pdaughter );
6481 Int_t row0= kinkl.GetTPCRow0();
6482 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6483 MarkSeedFree( pmother );
6484 MarkSeedFree( pdaughter );
6489 Int_t index = esd->AddKink(&kinkl);
6490 mother.SetKinkIndex(0,-(index+1));
6491 daughter.SetKinkIndex(0,index+1);
6492 if (mother.GetNumberOfClusters()>50) {
6493 MarkSeedFree( array->RemoveAt(i) );
6494 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6495 mtc->SetPoolID(fLastSeedID);
6496 array->AddAt(mtc,i);
6499 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6500 mtc->SetPoolID(fLastSeedID);
6501 array->AddLast(mtc);
6503 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6504 dtc->SetPoolID(fLastSeedID);
6505 array->AddLast(dtc);
6506 for (Int_t icl=0;icl<row0;icl++) {
6507 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6510 for (Int_t icl=row0;icl<158;icl++) {
6511 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6515 MarkSeedFree( pmother );
6516 MarkSeedFree( pdaughter );
6520 delete [] daughters;
6542 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6547 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6550 // refit kink towards to the vertex
6553 AliKink &kink=(AliKink &)knk;
6555 Int_t row0 = GetRowNumber(kink.GetR());
6556 FollowProlongation(mother,0);
6557 mother.Reset(kFALSE);
6559 FollowProlongation(daughter,row0);
6560 daughter.Reset(kFALSE);
6561 FollowBackProlongation(daughter,158);
6562 daughter.Reset(kFALSE);
6563 Int_t first = TMath::Max(row0-20,30);
6564 Int_t last = TMath::Min(row0+20,140);
6566 const Int_t kNdiv =5;
6567 AliTPCseed param0[kNdiv]; // parameters along the track
6568 AliTPCseed param1[kNdiv]; // parameters along the track
6569 AliKink kinks[kNdiv]; // corresponding kink parameters
6572 for (Int_t irow=0; irow<kNdiv;irow++){
6573 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
6575 // store parameters along the track
6577 for (Int_t irow=0;irow<kNdiv;irow++){
6578 FollowBackProlongation(mother, rows[irow]);
6579 FollowProlongation(daughter,rows[kNdiv-1-irow]);
6580 param0[irow] = mother;
6581 param1[kNdiv-1-irow] = daughter;
6585 for (Int_t irow=0; irow<kNdiv-1;irow++){
6586 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
6587 kinks[irow].SetMother(param0[irow]);
6588 kinks[irow].SetDaughter(param1[irow]);
6589 kinks[irow].Update();
6592 // choose kink with best "quality"
6594 Double_t mindist = 10000;
6595 for (Int_t irow=0;irow<kNdiv;irow++){
6596 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
6597 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6598 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
6600 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
6601 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
6602 if (normdist < mindist){
6608 if (index==-1) return 0;
6611 param0[index].Reset(kTRUE);
6612 FollowProlongation(param0[index],0);
6614 mother = param0[index];
6615 daughter = param1[index]; // daughter in vertex
6617 kink.SetMother(mother);
6618 kink.SetDaughter(daughter);
6620 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
6621 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6622 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6623 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
6624 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
6625 mother.SetLabel(kink.GetLabel(0));
6626 daughter.SetLabel(kink.GetLabel(1));
6632 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
6634 // update Kink quality information for mother after back propagation
6636 if (seed->GetKinkIndex(0)>=0) return;
6637 for (Int_t ikink=0;ikink<3;ikink++){
6638 Int_t index = seed->GetKinkIndex(ikink);
6639 if (index>=0) break;
6640 index = TMath::Abs(index)-1;
6641 AliESDkink * kink = fEvent->GetKink(index);
6642 kink->SetTPCDensity(-1,0,0);
6643 kink->SetTPCDensity(1,0,1);
6645 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6646 if (row0<15) row0=15;
6648 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6649 if (row1>145) row1=145;
6651 Int_t found,foundable,shared;
6652 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6653 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
6654 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6655 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
6660 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
6662 // update Kink quality information for daughter after refit
6664 if (seed->GetKinkIndex(0)<=0) return;
6665 for (Int_t ikink=0;ikink<3;ikink++){
6666 Int_t index = seed->GetKinkIndex(ikink);
6667 if (index<=0) break;
6668 index = TMath::Abs(index)-1;
6669 AliESDkink * kink = fEvent->GetKink(index);
6670 kink->SetTPCDensity(-1,1,0);
6671 kink->SetTPCDensity(-1,1,1);
6673 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6674 if (row0<15) row0=15;
6676 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6677 if (row1>145) row1=145;
6679 Int_t found,foundable,shared;
6680 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6681 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
6682 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6683 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
6689 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6692 // check kink point for given track
6693 // if return value=0 kink point not found
6694 // otherwise seed0 correspond to mother particle
6695 // seed1 correspond to daughter particle
6696 // kink parameter of kink point
6697 AliKink &kink=(AliKink &)knk;
6699 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
6700 Int_t first = seed->GetFirstPoint();
6701 Int_t last = seed->GetLastPoint();
6702 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
6705 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
6706 if (!seed1) return 0;
6707 FollowProlongation(*seed1,seed->GetLastPoint()-20);
6708 seed1->Reset(kTRUE);
6709 FollowProlongation(*seed1,158);
6710 seed1->Reset(kTRUE);
6711 last = seed1->GetLastPoint();
6713 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
6714 seed0->SetPoolID(fLastSeedID);
6715 seed0->Reset(kFALSE);
6718 AliTPCseed param0[20]; // parameters along the track
6719 AliTPCseed param1[20]; // parameters along the track
6720 AliKink kinks[20]; // corresponding kink parameters
6722 for (Int_t irow=0; irow<20;irow++){
6723 rows[irow] = first +((last-first)*irow)/19;
6725 // store parameters along the track
6727 for (Int_t irow=0;irow<20;irow++){
6728 FollowBackProlongation(*seed0, rows[irow]);
6729 FollowProlongation(*seed1,rows[19-irow]);
6730 param0[irow] = *seed0;
6731 param1[19-irow] = *seed1;
6735 for (Int_t irow=0; irow<19;irow++){
6736 kinks[irow].SetMother(param0[irow]);
6737 kinks[irow].SetDaughter(param1[irow]);
6738 kinks[irow].Update();
6741 // choose kink with biggest change of angle
6743 Double_t maxchange= 0;
6744 for (Int_t irow=1;irow<19;irow++){
6745 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6746 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
6747 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6748 if ( quality > maxchange){
6749 maxchange = quality;
6754 MarkSeedFree( seed0 );
6755 MarkSeedFree( seed1 );
6756 if (index<0) return 0;
6758 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
6759 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
6760 seed0->SetPoolID(fLastSeedID);
6761 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
6762 seed1->SetPoolID(fLastSeedID);
6763 seed0->Reset(kFALSE);
6764 seed1->Reset(kFALSE);
6765 seed0->ResetCovariance(10.);
6766 seed1->ResetCovariance(10.);
6767 FollowProlongation(*seed0,0);
6768 FollowBackProlongation(*seed1,158);
6769 mother = *seed0; // backup mother at position 0
6770 seed0->Reset(kFALSE);
6771 seed1->Reset(kFALSE);
6772 seed0->ResetCovariance(10.);
6773 seed1->ResetCovariance(10.);
6775 first = TMath::Max(row0-20,0);
6776 last = TMath::Min(row0+20,158);
6778 for (Int_t irow=0; irow<20;irow++){
6779 rows[irow] = first +((last-first)*irow)/19;
6781 // store parameters along the track
6783 for (Int_t irow=0;irow<20;irow++){
6784 FollowBackProlongation(*seed0, rows[irow]);
6785 FollowProlongation(*seed1,rows[19-irow]);
6786 param0[irow] = *seed0;
6787 param1[19-irow] = *seed1;
6791 for (Int_t irow=0; irow<19;irow++){
6792 kinks[irow].SetMother(param0[irow]);
6793 kinks[irow].SetDaughter(param1[irow]);
6794 // param0[irow].Dump();
6795 //param1[irow].Dump();
6796 kinks[irow].Update();
6799 // choose kink with biggest change of angle
6802 for (Int_t irow=0;irow<20;irow++){
6803 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
6804 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
6805 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6806 if ( quality > maxchange){
6807 maxchange = quality;
6814 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
6815 MarkSeedFree( seed0 );
6816 MarkSeedFree( seed1 );
6820 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
6822 kink.SetMother(param0[index]);
6823 kink.SetDaughter(param1[index]);
6826 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
6828 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
6829 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
6831 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
6833 if (AliTPCReconstructor::StreamLevel()>1) {
6834 (*fDebugStreamer)<<"kinkHpt"<<
6837 "p0.="<<¶m0[index]<<
6838 "p1.="<<¶m1[index]<<
6842 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6843 MarkSeedFree( seed0 );
6844 MarkSeedFree( seed1 );
6849 row0 = GetRowNumber(kink.GetR());
6850 kink.SetTPCRow0(row0);
6851 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
6852 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
6853 kink.SetIndex(-10,0);
6854 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
6855 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6856 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6859 // new (&mother) AliTPCseed(param0[index]);
6860 daughter = param1[index];
6861 daughter.SetLabel(kink.GetLabel(1));
6862 param0[index].Reset(kTRUE);
6863 FollowProlongation(param0[index],0);
6864 mother = param0[index];
6865 mother.SetLabel(kink.GetLabel(0));
6866 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
6869 MarkSeedFree( seed0 );
6870 MarkSeedFree( seed1 );
6878 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
6881 // reseed - refit - track
6884 // Int_t last = fSectors->GetNRows()-1;
6886 if (fSectors == fOuterSec){
6887 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
6891 first = t->GetFirstPoint();
6893 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
6894 FollowBackProlongation(*t,fSectors->GetNRows()-1);
6896 FollowProlongation(*t,first);
6906 //_____________________________________________________________________________
6907 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
6908 //-----------------------------------------------------------------
6909 // This function reades track seeds.
6910 //-----------------------------------------------------------------
6911 TDirectory *savedir=gDirectory;
6913 TFile *in=(TFile*)inp;
6914 if (!in->IsOpen()) {
6915 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
6920 TTree *seedTree=(TTree*)in->Get("Seeds");
6922 cerr<<"AliTPCtracker::ReadSeeds(): ";
6923 cerr<<"can't get a tree with track seeds !\n";
6926 AliTPCtrack *seed=new AliTPCtrack;
6927 seedTree->SetBranchAddress("tracks",&seed);
6929 if (fSeeds==0) fSeeds=new TObjArray(15000);
6931 Int_t n=(Int_t)seedTree->GetEntries();
6932 for (Int_t i=0; i<n; i++) {
6933 seedTree->GetEvent(i);
6934 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
6935 sdc->SetPoolID(fLastSeedID);
6936 fSeeds->AddLast(sdc);
6939 delete seed; // RS: this seed is not from the pool, delete it !!!
6945 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
6948 // clusters to tracks
6949 if (fSeeds) DeleteSeeds();
6950 else ResetSeedsPool();
6952 fEventHLT = hltEvent;
6954 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
6955 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
6956 transform->SetCurrentRun(esd->GetRunNumber());
6960 if (!fSeeds) return 1;
6962 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(0,fSeeds);
6967 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
6970 // clusters to tracks
6971 return Clusters2TracksHLT( esd, 0);
6974 //_____________________________________________________________________________
6975 Int_t AliTPCtracker::Clusters2Tracks() {
6976 //-----------------------------------------------------------------
6977 // This is a track finder.
6978 //-----------------------------------------------------------------
6979 TDirectory *savedir=gDirectory;
6983 fSeeds = Tracking();
6986 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6988 //activate again some tracks
6989 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6990 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6992 Int_t nc=t.GetNumberOfClusters();
6994 MarkSeedFree( fSeeds->RemoveAt(i) );
6998 if (pt->GetRemoval()==10) {
6999 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7000 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
7002 pt->Desactivate(20);
7003 MarkSeedFree( fSeeds->RemoveAt(i) );
7008 RemoveUsed2(fSeeds,0.85,0.85,0);
7009 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
7010 //FindCurling(fSeeds, fEvent,0);
7011 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
7012 RemoveUsed2(fSeeds,0.5,0.4,20);
7013 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
7014 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
7017 // // refit short tracks
7019 Int_t nseed=fSeeds->GetEntriesFast();
7022 for (Int_t i=0; i<nseed; i++) {
7023 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7025 Int_t nc=t.GetNumberOfClusters();
7027 MarkSeedFree( fSeeds->RemoveAt(i) );
7030 CookLabel(pt,0.1); //For comparison only
7031 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7032 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7034 if (fDebug>0) cerr<<found<<'\r';
7038 MarkSeedFree( fSeeds->RemoveAt(i) );
7042 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7044 //RemoveUsed(fSeeds,0.9,0.9,6);
7046 nseed=fSeeds->GetEntriesFast();
7048 for (Int_t i=0; i<nseed; i++) {
7049 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7051 Int_t nc=t.GetNumberOfClusters();
7053 MarkSeedFree( fSeeds->RemoveAt(i) );
7057 t.CookdEdx(0.02,0.6);
7058 // CheckKinkPoint(&t,0.05);
7059 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7060 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7068 MarkSeedFree( fSeeds->RemoveAt(i) );
7069 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7071 // FollowProlongation(*seed1,0);
7072 // Int_t n = seed1->GetNumberOfClusters();
7073 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7074 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7077 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7081 SortTracks(fSeeds, 1);
7085 PrepareForBackProlongation(fSeeds,5.);
7086 PropagateBack(fSeeds);
7087 printf("Time for back propagation: \t");timer.Print();timer.Start();
7091 PrepareForProlongation(fSeeds,5.);
7092 PropagateForard2(fSeeds);
7094 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7095 // RemoveUsed(fSeeds,0.7,0.7,6);
7096 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7098 nseed=fSeeds->GetEntriesFast();
7100 for (Int_t i=0; i<nseed; i++) {
7101 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7103 Int_t nc=t.GetNumberOfClusters();
7105 MarkSeedFree( fSeeds->RemoveAt(i) );
7108 t.CookdEdx(0.02,0.6);
7109 // CookLabel(pt,0.1); //For comparison only
7110 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7111 if ((pt->IsActive() || (pt->fRemoval==10) )){
7112 cerr<<found++<<'\r';
7115 MarkSeedFree( fSeeds->RemoveAt(i) );
7120 // fNTracks = found;
7122 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7125 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7126 Info("Clusters2Tracks","Number of found tracks %d",found);
7128 // UnloadClusters();
7133 void AliTPCtracker::Tracking(TObjArray * arr)
7136 // tracking of the seeds
7139 fSectors = fOuterSec;
7140 ParallelTracking(arr,150,63);
7141 fSectors = fOuterSec;
7142 ParallelTracking(arr,63,0);
7145 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7150 static TObjArray arrTracks;
7151 TObjArray * arr = &arrTracks;
7153 fSectors = fOuterSec;
7156 for (Int_t sec=0;sec<fkNOS;sec++){
7157 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7158 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7159 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7162 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7174 TObjArray * AliTPCtracker::Tracking()
7178 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7181 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7183 TObjArray * seeds = new TObjArray;
7185 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7186 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7187 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7195 Float_t fnumber = 3.0;
7196 Float_t fdensity = 3.0;
7199 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7200 arr = MakeSeedsHLT( fEventHLT );
7202 SumTracks(seeds,arr);
7205 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7206 //SignClusters(seeds,fnumber,fdensity);
7213 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7217 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7218 SumTracks(seeds,arr);
7219 SignClusters(seeds,fnumber,fdensity);
7221 for (Int_t i=2;i<6;i+=2){
7222 // seed high pt tracks
7225 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7226 SumTracks(seeds,arr);
7227 SignClusters(seeds,fnumber,fdensity);
7232 // RemoveUsed(seeds,0.9,0.9,1);
7233 // UnsignClusters();
7234 // SignClusters(seeds,fnumber,fdensity);
7238 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7240 // seed high pt tracks
7244 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7245 SumTracks(seeds,arr);
7246 SignClusters(seeds,fnumber,fdensity);
7251 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7252 SumTracks(seeds,arr);
7253 SignClusters(seeds,fnumber,fdensity);
7264 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7268 // RemoveUsed(seeds,0.75,0.75,1);
7270 //SignClusters(seeds,fnumber,fdensity);
7279 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7280 SumTracks(seeds,arr);
7281 SignClusters(seeds,fnumber,fdensity);
7283 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7284 SumTracks(seeds,arr);
7285 SignClusters(seeds,fnumber,fdensity);
7287 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7288 SumTracks(seeds,arr);
7289 SignClusters(seeds,fnumber,fdensity);
7291 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7292 SumTracks(seeds,arr);
7293 SignClusters(seeds,fnumber,fdensity);
7295 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7296 SumTracks(seeds,arr);
7297 SignClusters(seeds,fnumber,fdensity);
7300 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7301 SumTracks(seeds,arr);
7302 SignClusters(seeds,fnumber,fdensity);
7306 for (Int_t delta = 9; delta<30; delta+=gapSec){
7312 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7313 SumTracks(seeds,arr);
7314 SignClusters(seeds,fnumber,fdensity);
7316 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7317 SumTracks(seeds,arr);
7318 SignClusters(seeds,fnumber,fdensity);
7331 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7337 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7338 SumTracks(seeds,arr);
7339 SignClusters(seeds,fnumber,fdensity);
7341 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7342 SumTracks(seeds,arr);
7343 SignClusters(seeds,fnumber,fdensity);
7347 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7358 TObjArray * AliTPCtracker::TrackingSpecial()
7361 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7362 // no primary vertex seeding tried
7366 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7368 TObjArray * seeds = new TObjArray;
7373 Float_t fnumber = 3.0;
7374 Float_t fdensity = 3.0;
7377 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7378 cuts[1] = 3.5; // max tan(phi) angle for seeding
7379 cuts[2] = 3.; // not used (cut on z primary vertex)
7380 cuts[3] = 3.5; // max tan(theta) angle for seeding
7382 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7384 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7385 SumTracks(seeds,arr);
7386 SignClusters(seeds,fnumber,fdensity);
7390 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7401 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7404 //sum tracks to common container
7405 //remove suspicious tracks
7406 // RS: Attention: supplied tracks come in the static array, don't delete them
7407 Int_t nseed = arr2->GetEntriesFast();
7408 for (Int_t i=0;i<nseed;i++){
7409 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7412 // remove tracks with too big curvature
7414 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7415 MarkSeedFree( arr2->RemoveAt(i) );
7418 // REMOVE VERY SHORT TRACKS
7419 if (pt->GetNumberOfClusters()<20){
7420 MarkSeedFree( arr2->RemoveAt(i) );
7423 // NORMAL ACTIVE TRACK
7424 if (pt->IsActive()){
7425 arr1->AddLast(arr2->RemoveAt(i));
7428 //remove not usable tracks
7429 if (pt->GetRemoval()!=10){
7430 MarkSeedFree( arr2->RemoveAt(i) );
7434 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7435 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7436 arr1->AddLast(arr2->RemoveAt(i));
7438 MarkSeedFree( arr2->RemoveAt(i) );
7442 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7447 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7450 // try to track in parralel
7452 Int_t nseed=arr->GetEntriesFast();
7453 //prepare seeds for tracking
7454 for (Int_t i=0; i<nseed; i++) {
7455 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7457 if (!t.IsActive()) continue;
7458 // follow prolongation to the first layer
7459 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7460 FollowProlongation(t, rfirst+1);
7465 for (Int_t nr=rfirst; nr>=rlast; nr--){
7466 if (nr<fInnerSec->GetNRows())
7467 fSectors = fInnerSec;
7469 fSectors = fOuterSec;
7470 // make indexes with the cluster tracks for given
7472 // find nearest cluster
7473 for (Int_t i=0; i<nseed; i++) {
7474 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7476 if (nr==80) pt->UpdateReference();
7477 if (!pt->IsActive()) continue;
7478 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7479 if (pt->GetRelativeSector()>17) {
7482 UpdateClusters(t,nr);
7484 // prolonagate to the nearest cluster - if founded
7485 for (Int_t i=0; i<nseed; i++) {
7486 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7488 if (!pt->IsActive()) continue;
7489 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7490 if (pt->GetRelativeSector()>17) {
7493 FollowToNextCluster(*pt,nr);
7498 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7502 // if we use TPC track itself we have to "update" covariance
7504 Int_t nseed= arr->GetEntriesFast();
7505 for (Int_t i=0;i<nseed;i++){
7506 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7510 //rotate to current local system at first accepted point
7511 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
7512 Int_t sec = (index&0xff000000)>>24;
7514 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
7515 if (angle1>TMath::Pi())
7516 angle1-=2.*TMath::Pi();
7517 Float_t angle2 = pt->GetAlpha();
7519 if (TMath::Abs(angle1-angle2)>0.001){
7520 if (!pt->Rotate(angle1-angle2)) return;
7521 //angle2 = pt->GetAlpha();
7522 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
7523 //if (pt->GetAlpha()<0)
7524 // pt->fRelativeSector+=18;
7525 //sec = pt->fRelativeSector;
7534 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
7538 // if we use TPC track itself we have to "update" covariance
7540 Int_t nseed= arr->GetEntriesFast();
7541 for (Int_t i=0;i<nseed;i++){
7542 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7545 pt->SetFirstPoint(pt->GetLastPoint());
7553 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
7556 // make back propagation
7558 Int_t nseed= arr->GetEntriesFast();
7559 for (Int_t i=0;i<nseed;i++){
7560 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7561 if (pt&& pt->GetKinkIndex(0)<=0) {
7562 //AliTPCseed *pt2 = new AliTPCseed(*pt);
7563 fSectors = fInnerSec;
7564 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
7565 //fSectors = fOuterSec;
7566 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7567 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
7568 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
7569 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
7572 if (pt&& pt->GetKinkIndex(0)>0) {
7573 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
7574 pt->SetFirstPoint(kink->GetTPCRow0());
7575 fSectors = fInnerSec;
7576 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7584 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
7587 // make forward propagation
7589 Int_t nseed= arr->GetEntriesFast();
7591 for (Int_t i=0;i<nseed;i++){
7592 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7594 FollowProlongation(*pt,0,1,1);
7603 Int_t AliTPCtracker::PropagateForward()
7606 // propagate track forward
7608 Int_t nseed = fSeeds->GetEntriesFast();
7609 for (Int_t i=0;i<nseed;i++){
7610 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
7612 AliTPCseed &t = *pt;
7613 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
7614 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
7615 if (alpha < 0. ) alpha += 2.*TMath::Pi();
7616 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
7620 fSectors = fOuterSec;
7621 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
7622 fSectors = fInnerSec;
7623 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
7632 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
7635 // make back propagation, in between row0 and row1
7639 fSectors = fInnerSec;
7642 if (row1<fSectors->GetNRows())
7645 r1 = fSectors->GetNRows()-1;
7647 if (row0<fSectors->GetNRows()&& r1>0 )
7648 FollowBackProlongation(*pt,r1);
7649 if (row1<=fSectors->GetNRows())
7652 r1 = row1 - fSectors->GetNRows();
7653 if (r1<=0) return 0;
7654 if (r1>=fOuterSec->GetNRows()) return 0;
7655 fSectors = fOuterSec;
7656 return FollowBackProlongation(*pt,r1);
7664 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
7666 // gets cluster shape
7668 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
7669 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
7670 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
7671 Double_t angulary = seed->GetSnp();
7673 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
7674 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
7677 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
7678 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
7680 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
7681 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
7682 seed->SetCurrentSigmaY2(sigmay*sigmay);
7683 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
7684 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
7685 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
7686 // Float_t padlength = GetPadPitchLength(row);
7688 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
7689 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
7691 // Float_t sresz = fkParam->GetZSigma();
7692 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
7694 Float_t wy = GetSigmaY(seed);
7695 Float_t wz = GetSigmaZ(seed);
7698 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
7699 printf("problem\n");
7706 //__________________________________________________________________________
7707 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
7708 //--------------------------------------------------------------------
7709 //This function "cooks" a track label. If label<0, this track is fake.
7710 //--------------------------------------------------------------------
7711 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
7713 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
7717 Int_t noc=t->GetNumberOfClusters();
7719 //printf("\nnot founded prolongation\n\n\n");
7725 AliTPCclusterMI *clusters[160];
7727 for (Int_t i=0;i<160;i++) {
7734 for (i=0; i<160 && current<noc; i++) {
7736 Int_t index=t->GetClusterIndex2(i);
7737 if (index<=0) continue;
7738 if (index&0x8000) continue;
7740 //clusters[current]=GetClusterMI(index);
7741 if (t->GetClusterPointer(i)){
7742 clusters[current]=t->GetClusterPointer(i);
7748 Int_t lab=123456789;
7749 for (i=0; i<noc; i++) {
7750 AliTPCclusterMI *c=clusters[i];
7752 lab=TMath::Abs(c->GetLabel(0));
7754 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7760 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7762 for (i=0; i<noc; i++) {
7763 AliTPCclusterMI *c=clusters[i];
7765 if (TMath::Abs(c->GetLabel(1)) == lab ||
7766 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7768 if (noc<=0) { lab=-1; return;}
7769 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7772 Int_t tail=Int_t(0.10*noc);
7775 for (i=1; i<160&&ind<tail; i++) {
7776 // AliTPCclusterMI *c=clusters[noc-i];
7777 AliTPCclusterMI *c=clusters[i];
7779 if (lab == TMath::Abs(c->GetLabel(0)) ||
7780 lab == TMath::Abs(c->GetLabel(1)) ||
7781 lab == TMath::Abs(c->GetLabel(2))) max++;
7784 if (max < Int_t(0.5*tail)) lab=-lab;
7791 //delete[] clusters;
7795 //__________________________________________________________________________
7796 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
7797 //--------------------------------------------------------------------
7798 //This function "cooks" a track label. If label<0, this track is fake.
7799 //--------------------------------------------------------------------
7800 Int_t noc=t->GetNumberOfClusters();
7802 //printf("\nnot founded prolongation\n\n\n");
7808 AliTPCclusterMI *clusters[160];
7810 for (Int_t i=0;i<160;i++) {
7817 for (i=0; i<160 && current<noc; i++) {
7818 if (i<first) continue;
7819 if (i>last) continue;
7820 Int_t index=t->GetClusterIndex2(i);
7821 if (index<=0) continue;
7822 if (index&0x8000) continue;
7824 //clusters[current]=GetClusterMI(index);
7825 if (t->GetClusterPointer(i)){
7826 clusters[current]=t->GetClusterPointer(i);
7831 //if (noc<5) return -1;
7832 Int_t lab=123456789;
7833 for (i=0; i<noc; i++) {
7834 AliTPCclusterMI *c=clusters[i];
7836 lab=TMath::Abs(c->GetLabel(0));
7838 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7844 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7846 for (i=0; i<noc; i++) {
7847 AliTPCclusterMI *c=clusters[i];
7849 if (TMath::Abs(c->GetLabel(1)) == lab ||
7850 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7852 if (noc<=0) { lab=-1; return -1;}
7853 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7856 Int_t tail=Int_t(0.10*noc);
7859 for (i=1; i<160&&ind<tail; i++) {
7860 // AliTPCclusterMI *c=clusters[noc-i];
7861 AliTPCclusterMI *c=clusters[i];
7863 if (lab == TMath::Abs(c->GetLabel(0)) ||
7864 lab == TMath::Abs(c->GetLabel(1)) ||
7865 lab == TMath::Abs(c->GetLabel(2))) max++;
7868 if (max < Int_t(0.5*tail)) lab=-lab;
7871 // t->SetLabel(lab);
7875 //delete[] clusters;
7879 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
7881 //return pad row number for given x vector
7882 Float_t phi = TMath::ATan2(x[1],x[0]);
7883 if(phi<0) phi=2.*TMath::Pi()+phi;
7884 // Get the local angle in the sector philoc
7885 const Float_t kRaddeg = 180/3.14159265358979312;
7886 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
7887 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
7888 return GetRowNumber(localx);
7893 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
7895 //-----------------------------------------------------------------------
7896 // Fill the cluster and sharing bitmaps of the track
7897 //-----------------------------------------------------------------------
7899 Int_t firstpoint = 0;
7900 Int_t lastpoint = 159;
7901 AliTPCTrackerPoint *point;
7902 AliTPCclusterMI *cluster;
7905 TBits clusterMap(159);
7906 TBits sharedMap(159);
7908 for (int iter=firstpoint; iter<lastpoint; iter++) {
7909 // Change to cluster pointers to see if we have a cluster at given padrow
7911 cluster = t->GetClusterPointer(iter);
7913 clusterMap.SetBitNumber(iter, kTRUE);
7914 point = t->GetTrackPoint(iter);
7915 if (point->IsShared())
7916 sharedMap.SetBitNumber(iter,kTRUE);
7918 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
7919 fitMap.SetBitNumber(iter, kTRUE);
7923 esd->SetTPCClusterMap(clusterMap);
7924 esd->SetTPCSharedMap(sharedMap);
7925 esd->SetTPCFitMap(fitMap);
7926 if (nclsf != t->GetNumberOfClusters())
7927 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
7930 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
7932 // return flag if there is findable cluster at given position
7935 Float_t z = track.GetZ();
7937 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
7938 TMath::Abs(z)<fkParam->GetZLength(0) &&
7939 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
7945 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
7947 // Adding systematic error estimate to the covariance matrix
7948 // !!!! the systematic error for element 4 is in 1/GeV
7949 // 03.03.2012 MI changed in respect to the previous versions
7950 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7952 // use only the diagonal part if not specified otherwise
7953 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
7955 Double_t *covarS= (Double_t*)seed->GetCovariance();
7956 Double_t factor[5]={1,1,1,1,1};
7957 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
7958 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
7959 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
7960 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
7961 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
7963 factor[0]=factor[2];
7964 factor[4]=factor[2];
7970 for (Int_t i=0; i<5; i++){
7971 for (Int_t j=i; j<5; j++){
7972 Int_t index=seed->GetIndex(i,j);
7973 covarS[index]*=factor[i]*factor[j];
7979 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
7981 // Adding systematic error - as additive factor without correlation
7983 // !!!! the systematic error for element 4 is in 1/GeV
7984 // 03.03.2012 MI changed in respect to the previous versions
7986 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7987 Double_t *covarIn= (Double_t*)seed->GetCovariance();
7989 for (Int_t i=0;i<15;i++) covar[i]=0;
7995 covar[0] = param[0]*param[0];
7996 covar[2] = param[1]*param[1];
7997 covar[5] = param[2]*param[2];
7998 covar[9] = param[3]*param[3];
7999 covar[14]= param[4]*param[4];
8001 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
8003 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
8004 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
8006 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
8007 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
8008 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
8010 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
8011 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
8012 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
8013 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
8015 seed->AddCovariance(covar);
8018 //_____________________________________________________________________________
8019 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8022 // check events affected by TPC HV dip
8024 if(!esdEvent) return kFALSE;
8027 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8028 if(!db) return kFALSE;
8029 db->SetRun(esdEvent->GetRunNumber());
8031 // maximum allowed voltage before an event is identified as a dip event
8032 // and scanning period
8033 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8034 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8035 const Double_t tevSec = esdEvent->GetTimeStamp();
8037 for(Int_t sector=0; sector<72; sector++)
8039 // don't use excluded chambers, since the state is not defined at all
8040 if (!db->GetChamberHVStatus(sector)) continue;
8042 // get hv sensor of the chamber
8043 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8044 if (!sensor) continue;
8045 TGraph *grSensor=sensor->GetGraph();
8046 if (!grSensor) continue;
8047 if (grSensor->GetN()<1) continue;
8050 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8051 if(median < 1.) continue;
8053 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8054 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8055 if (tevSec-dipEventScanPeriod>nextTime) continue;
8056 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8057 if (deltaV>kTPCHVdip) {
8058 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8061 if (nextTime>tevSec+dipEventScanPeriod) break;
8068 //________________________________________
8069 void AliTPCtracker::MarkSeedFree(TObject *sd)
8071 // account that this seed is "deleted"
8072 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8074 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8077 int id = seed->GetPoolID();
8079 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8082 // AliInfo(Form("%d %p",id, seed));
8083 fSeedsPool->RemoveAt(id);
8084 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8085 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8088 //________________________________________
8089 TObject *&AliTPCtracker::NextFreeSeed()
8091 // return next free slot where the seed can be created
8092 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8093 // AliInfo(Form("%d",fLastSeedID));
8094 return (*fSeedsPool)[ fLastSeedID ];
8098 //________________________________________
8099 void AliTPCtracker::ResetSeedsPool()
8101 // mark all seeds in the pool as unused
8102 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8104 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8107 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8110 Double_t x= GetXrow(nrow);
8111 Double_t ymax= GetMaxY(nrow);
8117 if (!t.PropagateTo(x) ){
8118 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8124 Double_t y = t.GetY();
8126 if( rotate!=-1 ) rotate=1;
8127 } else if (y <-ymax) {
8128 if( rotate!=1 ) rotate = -1;
8130 if( rotate==0 ) break;
8131 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8132 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8133 //cout<<"can't rotate "<<endl;
8137 nRotations+= rotate;
8139 if( nRotations!=0 ){
8140 int newSec= t.GetRelativeSector()+nRotations;
8141 if( newSec>=fN ) newSec-=fN;
8142 else if( newSec<0 ) newSec +=fN;
8143 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8144 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8145 t.SetRelativeSector(newSec);
8150 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8153 // try to track in parralel
8155 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8158 Int_t nseed=arr->GetEntriesFast();
8159 //cout<<"Parallel tracking My.."<<endl;
8160 double shapeY2[160], shapeZ2[160];
8161 Int_t clusterIndex[160];
8163 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8164 //if( iSeed!=1 ) continue;
8165 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8169 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8173 for( int iter=0; iter<3; iter++ ){
8176 t.SetLastPoint(0); // first cluster in track position
8177 t.SetFirstPoint(nRows-1);
8178 t.ResetCovariance(.1);
8179 t.SetNumberOfClusters(0);
8180 for( int i=0; i<nRows; i++ ){
8184 t.SetClusterIndex2(i,-1);
8185 t.SetClusterIndex(i,-1);
8188 // pick up the clusters
8190 Double_t roady = 20.;
8191 Double_t roadz = 20.;
8198 t0.SetRelativeSector(t.GetRelativeSector());
8199 t0.SetLastPoint(0); // first cluster in track position
8200 t0.SetFirstPoint(159);
8201 for (Int_t nr=0; nr<nRows; nr++){
8202 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8203 else fSectors=fOuterSec;
8205 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8206 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8207 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8210 if (!IsActive(t0.GetRelativeSector(),nr)) {
8216 shapeY2[nr]=t0.GetCurrentSigmaY2();
8217 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8220 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8221 if( !krow ) continue;
8223 t.SetClusterIndex2(nr,-3); // foundable
8224 t.SetClusterIndex(nr,-3);
8226 AliTPCclusterMI *cl=0;
8228 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8230 double dy = cl->GetY()-t0.GetY();
8231 double dz = cl->GetZ()-t0.GetZ();
8232 double dr = sqrt(dy*dy+dz*dz);
8234 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8237 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8239 t0.SetClusterPointer(nr, cl);
8240 clusterIndex[nr] = krow.GetIndex(uindex);
8241 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8242 t0.SetLastPoint(nr);
8248 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8251 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8255 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8257 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8258 if( !t0.GetClusterPointer(nr) ) continue;
8259 int d = TMath::Abs(nr-midRow);
8267 // first fit 3 base points
8269 //cout<<"Fit3: "<<endl;
8270 for( int icl=0; icl<3; icl++){
8271 int nr = basePoints[icl];
8273 if( nr>=fInnerSec->GetNRows()){
8274 lr = nr - fInnerSec->GetNRows();
8276 } else fSectors=fInnerSec;
8278 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8280 //cout<<"WRONG!!!!"<<endl;
8283 int iSec = cl->GetDetector() %fkNIS;
8284 int rotate = iSec - t.GetRelativeSector();
8286 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8287 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8288 //cout<<"can't rotate "<<endl;
8291 t.SetRelativeSector(iSec);
8293 Double_t x= cl->GetX();
8294 if (!t.PropagateTo(x)){
8295 //cout<<"can't propagate to x="<<x<<endl;
8299 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8300 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8303 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8305 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8306 t.SetCurrentCluster(cl);
8309 t.SetErrorY2(shapeY2[nr]);
8310 t.SetErrorZ2(shapeZ2[nr]);
8313 for( int j=0; j<15; j++ ) cov[j]=0;
8319 t.AliExternalTrackParam::AddCovariance(cov);
8321 if( !UpdateTrack(&t,0) ){
8322 //cout<<"Can not update"<<endl;
8324 t.SetClusterIndex2(nr,-1);
8325 t.SetClusterIndex(nr,-1);
8326 t.SetClusterPointer(nr,0);
8329 //t.SetClusterPointer(nr, cl);
8332 //t.SetLastPoint(t0.GetLastPoint());
8333 //t.SetFirstPoint(t0.GetFirstPoint());
8335 //cout<<"Fit: "<<endl;
8336 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8338 if( nr>=fInnerSec->GetNRows()){
8339 lr = nr - fInnerSec->GetNRows();
8341 } else fSectors=fInnerSec;
8344 if( nr == basePoints[0] ) continue;
8345 if( nr == basePoints[1] ) continue;
8346 if( nr == basePoints[2] ) continue;
8348 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8351 int iSec = cl->GetDetector() %fkNIS;
8352 int rotate = iSec - t.GetRelativeSector();
8354 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8355 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8356 //cout<<"can't rotate "<<endl;
8359 t.SetRelativeSector(iSec);
8361 Double_t x= cl->GetX();
8362 if (!t.PropagateTo(x)){
8363 //cout<<"can't propagate to x="<<x<<endl;
8366 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8367 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8371 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8373 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8374 t.SetCurrentCluster(cl);
8376 t.SetErrorY2(shapeY2[nr]);
8377 t.SetErrorZ2(shapeZ2[nr]);
8379 if( !UpdateTrack(&t,0) ){
8380 //cout<<"Can not update"<<endl;
8382 t.SetClusterIndex2(nr,-1);
8383 t.SetClusterIndex(nr,-1);
8386 //t.SetClusterPointer(nr, cl);
8389 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8392 //cout<<"fitted track"<<iSeed<<endl;
8394 //cout<<"Statistics: "<<endl;
8395 Int_t foundable,found,shared;
8396 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8397 t.SetNFoundable(foundable);
8398 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8404 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8409 if( !hltEvent ) return 0;
8412 Int_t nentr=hltEvent->GetNumberOfTracks();
8414 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8416 TObjArray * seeds = new TObjArray(nentr);
8418 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8421 Int_t nTr=hltEvent->GetNumberOfTracks();
8423 for( int itr=0; itr<nTr; itr++ ){
8424 //if( itr!=97 ) continue;
8425 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8426 if( !param ) continue;
8427 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8428 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8430 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8431 tr.SetNumberOfClusters(0);
8432 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8434 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8435 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8436 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8438 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8439 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8441 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8442 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8444 seed->Rotate(alphaSec - alpha);
8446 seed->SetPoolID(fLastSeedID);
8447 seed->SetIsSeeding(kTRUE);
8448 seed->SetSeed1(nup-1);
8449 seed->SetSeed2(nup-2);
8450 seed->SetSeedType(0);
8451 seed->SetFirstPoint(-1);
8452 seed->SetLastPoint(-1);
8453 seeds->AddLast(seed); // note, track is seed, don't free the seed
8455 //if( index>3 ) break;
8459 fSectors = fOuterSec;
8461 TrackFollowingHLT(seeds );
8463 nTr = seeds->GetEntriesFast();
8464 for( int itr=0; itr<nTr; itr++ ){
8465 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8466 if( !seed ) continue;
8467 //FollowBackProlongation(*seed,0);
8468 // cout<<seed->GetNumberOfClusters()<<endl;
8469 Int_t foundable,found,shared;
8470 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8471 seed->SetNFoundable(foundable);
8472 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8473 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8474 //MarkSeedFree(seeds->RemoveAt(itr));
8477 if (seed->GetNumberOfClusters()<30 ||
8478 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8479 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8480 MarkSeedFree(seeds->RemoveAt(itr));
8484 for( int ir=0; ir<nup; ir++){
8485 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8489 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8493 void AliTPCtracker::FillClusterOccupancyInfo()
8495 //fill the cluster occupancy info into the ESD friend
8496 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8497 if (!esdFriend) return;
8499 for (Int_t isector=0; isector<18; isector++){
8500 AliTPCtrackerSector &iroc = fInnerSec[isector];
8501 AliTPCtrackerSector &oroc = fOuterSec[isector];
8503 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
8504 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
8505 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
8506 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
8507 //clusters used in tracking
8508 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
8509 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
8510 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
8511 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));