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
25 // The track finding steps:
26 // 1. Seeding - with and without vertex constraint
27 // - seeding with vertex constain done at first n^2 proble
28 // - seeding without vertex constraint n^3 problem
29 // 2. Tracking - follow prolongation road - find cluster - update kalman track
30 // The seeding and tracking is repeated several times, in different seeding region.
31 // This approach enables to find the track which cannot be seeded in some region of TPC
32 // 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) ...
34 // With this approach we reach almost 100 % efficiency also for high occupancy events.
35 // (If the seeding efficiency in a region is about 90 % than with logical or of several
36 // regions we will reach 100% (in theory - supposing independence)
38 // Repeating several seeding - tracking procedures some of the tracks can be find
41 // The procedures to remove multi find tacks are impremented:
42 // RemoveUsed2 - fast procedure n problem -
43 // Algorithm - Sorting tracks according quality
44 // remove tracks with some shared fraction
45 // Sharing in respect to all tacks
46 // Signing clusters in gold region
47 // FindSplitted - slower algorithm n^2
48 // Sort the tracks according quality
49 // Loop over pair of tracks
50 // If overlap with other track bigger than threshold - remove track
52 // FindCurling - Finds the pair of tracks which are curling
53 // - About 10% of tracks can be find with this procedure
54 // The combinatorial background is too big to be used in High
55 // multiplicity environment
56 // - n^2 problem - Slow procedure - currently it is disabled because of
59 // The number of splitted tracks can be reduced disabling the sharing of the cluster.
60 // tpcRecoParam-> SetClusterSharing(kFALSE);
61 // IT IS HIGHLY non recomended to use it in high flux enviroonment
62 // Even using this switch some tracks can be found more than once
63 // (because of multiple seeding and low quality tracks which will not cross full chamber)
66 // The tracker itself can be debugged - the information about tracks can be stored in several // phases of the reconstruction
67 // To enable storage of the TPC tracks in the ESD friend track
68 // use AliTPCReconstructor::SetStreamLevel(n);
70 // The debug level - different procedure produce tree for numerical debugging of code and data (see comments foEStreamFlags in AliTPCtracker.h )
74 // Adding systematic errors to the covariance:
76 // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
77 // of the tracks (not to the clusters as they are dependent):
78 // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
79 // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
80 // The default values are 0.
82 // The systematic errors are added to the covariance matrix in following places:
84 // 1. During fisrt itteration - AliTPCtracker::FillESD
85 // 2. Second iteration -
86 // 2.a ITS->TPC - AliTPCtracker::ReadSeeds
87 // 2.b TPC->TRD - AliTPCtracker::PropagateBack
88 // 3. Third iteration -
89 // 3.a TRD->TPC - AliTPCtracker::ReadSeeds
90 // 3.b TPC->ITS - AliTPCtracker::RefitInward
95 #include "Riostream.h"
96 #include <TClonesArray.h>
98 #include <TObjArray.h>
100 #include <TMatrixD.h>
101 #include <TGraphErrors.h>
102 #include <TTimeStamp.h>
104 #include "AliComplexCluster.h"
105 #include "AliESDEvent.h"
106 #include "AliESDtrack.h"
107 #include "AliESDVertex.h"
110 #include "AliHelix.h"
111 #include "AliRunLoader.h"
112 #include "AliTPCClustersRow.h"
113 #include "AliTPCParam.h"
114 #include "AliTPCReconstructor.h"
115 #include "AliTPCpolyTrack.h"
116 #include "AliTPCreco.h"
117 #include "AliTPCseed.h"
119 #include "AliTPCtrackerSector.h"
120 #include "AliTPCtracker.h"
121 #include "TStopwatch.h"
122 #include "AliTPCReconstructor.h"
123 #include "AliAlignObj.h"
124 #include "AliTrackPointArray.h"
126 #include "AliTPCcalibDB.h"
127 #include "AliTPCcalibDButil.h"
128 #include "AliTPCTransform.h"
129 #include "AliTPCClusterParam.h"
130 #include "AliTPCdEdxInfo.h"
131 #include "AliDCSSensorArray.h"
132 #include "AliDCSSensor.h"
134 #include "AliCosmicTracker.h"
135 #include "AliTPCROC.h"
136 #include "AliMathBase.h"
141 ClassImp(AliTPCtracker)
145 class AliTPCFastMath {
148 static Double_t FastAsin(Double_t x);
150 static Double_t fgFastAsin[20000]; //lookup table for fast asin computation
153 Double_t AliTPCFastMath::fgFastAsin[20000];
154 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
156 AliTPCFastMath::AliTPCFastMath(){
158 // initialized lookup table;
159 for (Int_t i=0;i<10000;i++){
160 fgFastAsin[2*i] = TMath::ASin(i/10000.);
161 fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
165 Double_t AliTPCFastMath::FastAsin(Double_t x){
167 // return asin using lookup table
169 Int_t index = int(x*10000);
170 return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
173 Int_t index = int(x*10000);
174 return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
176 //__________________________________________________________________
177 AliTPCtracker::AliTPCtracker()
199 fCrossTalkSignalArray(0),
206 // default constructor
208 for (Int_t irow=0; irow<200; irow++){
214 //_____________________________________________________________________
218 Int_t AliTPCtracker::UpdateTrack(AliTPCseed * track, Int_t accept){
220 //update track information using current cluster - track->fCurrentCluster
223 AliTPCclusterMI* c =track->GetCurrentCluster();
224 if (accept > 0) //sign not accepted clusters
225 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);
226 else // unsign accpeted clusters
227 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);
228 UInt_t i = track->GetCurrentClusterIndex1();
230 Int_t sec=(i&0xff000000)>>24;
231 //Int_t row = (i&0x00ff0000)>>16;
232 track->SetRow((i&0x00ff0000)>>16);
233 track->SetSector(sec);
234 // Int_t index = i&0xFFFF;
235 if (sec>=fkParam->GetNInnerSector()) track->SetRow(track->GetRow()+fkParam->GetNRowLow());
236 track->SetClusterIndex2(track->GetRow(), i);
237 //track->fFirstPoint = row;
238 //if ( track->fLastPoint<row) track->fLastPoint =row;
239 // if (track->fRow<0 || track->fRow>160) {
240 // printf("problem\n");
242 if (track->GetFirstPoint()>track->GetRow())
243 track->SetFirstPoint(track->GetRow());
244 if (track->GetLastPoint()<track->GetRow())
245 track->SetLastPoint(track->GetRow());
248 track->SetClusterPointer(track->GetRow(),c);
251 Double_t angle2 = track->GetSnp()*track->GetSnp();
253 //SET NEW Track Point
255 if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
257 angle2 = TMath::Sqrt(angle2/(1-angle2));
258 AliTPCTrackerPoint &point =*(track->GetTrackPoint(track->GetRow()));
260 point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
261 point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
262 point.SetErrY(sqrt(track->GetErrorY2()));
263 point.SetErrZ(sqrt(track->GetErrorZ2()));
265 point.SetX(track->GetX());
266 point.SetY(track->GetY());
267 point.SetZ(track->GetZ());
268 point.SetAngleY(angle2);
269 point.SetAngleZ(track->GetTgl());
270 if (point.IsShared()){
271 track->SetErrorY2(track->GetErrorY2()*4);
272 track->SetErrorZ2(track->GetErrorZ2()*4);
276 Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
278 // track->SetErrorY2(track->GetErrorY2()*1.3);
279 // track->SetErrorY2(track->GetErrorY2()+0.01);
280 // track->SetErrorZ2(track->GetErrorZ2()*1.3);
281 // track->SetErrorZ2(track->GetErrorZ2()+0.005);
283 if (accept>0) return 0;
284 if (track->GetNumberOfClusters()%20==0){
285 // if (track->fHelixIn){
286 // TClonesArray & larr = *(track->fHelixIn);
287 // Int_t ihelix = larr.GetEntriesFast();
288 // new(larr[ihelix]) AliHelix(*track) ;
291 if (AliTPCReconstructor::StreamLevel()&kStreamUpdateTrack) {
292 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
293 AliExternalTrackParam param(*track);
294 TTreeSRedirector &cstream = *fDebugStreamer;
295 cstream<<"UpdateTrack"<<
301 track->SetNoCluster(0);
302 return track->Update(c,chi2,i);
307 Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
310 // decide according desired precision to accept given
311 // cluster for tracking
313 seed->GetProlongation(cluster->GetX(),yt,zt);
314 Double_t sy2=ErrY2(seed,cluster);
315 Double_t sz2=ErrZ2(seed,cluster);
317 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
318 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
319 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
320 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
321 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
322 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
323 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
324 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
326 Double_t rdistance2 = rdistancey2+rdistancez2;
329 if (AliTPCReconstructor::StreamLevel()>2 && ( (fIteration>0)|| (seed->GetNumberOfClusters()>20))) {
330 // if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
331 Float_t rmsy2 = seed->GetCurrentSigmaY2();
332 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
333 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
334 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
335 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
336 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
337 AliExternalTrackParam param(*seed);
338 static TVectorD gcl(3),gtr(3);
340 param.GetXYZ(gcl.GetMatrixArray());
341 cluster->GetGlobalXYZ(gclf);
342 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
343 Int_t nclSeed=seed->GetNumberOfClusters();
345 if (AliTPCReconstructor::StreamLevel()&kStreamErrParam) { // flag:stream in debug mode cluster and track extrapolation at given row together with error nad shape estimate
346 Int_t eventNr = fEvent->GetEventNumberInFile();
348 (*fDebugStreamer)<<"ErrParam"<<
349 "iter="<<fIteration<<
350 "eventNr="<<eventNr<<
352 "nclSeed="<<nclSeed<<
364 "rmsy2p30="<<rmsy2p30<<
365 "rmsz2p30="<<rmsz2p30<<
366 "rmsy2p30R="<<rmsy2p30R<<
367 "rmsz2p30R="<<rmsz2p30R<<
368 // normalize distance -
369 "rdisty="<<rdistancey2<<
370 "rdistz="<<rdistancez2<<
371 "rdist="<<rdistance2<< //
375 //return 0; // temporary
376 if (rdistance2>32) return 3;
379 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
380 return 2; //suspisiouce - will be changed
382 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
383 // strict cut on overlaped cluster
384 return 2; //suspisiouce - will be changed
386 if ( (rdistancey2>1. || rdistancez2>6.25 )
387 && cluster->GetType()<0){
388 seed->SetNFoundable(seed->GetNFoundable()-1);
392 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
394 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
395 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
408 //_____________________________________________________________________________
409 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
411 fkNIS(par->GetNInnerSector()/2),
413 fkNOS(par->GetNOuterSector()/2),
431 fCrossTalkSignalArray(0),
437 //---------------------------------------------------------------------
438 // The main TPC tracker constructor
439 //---------------------------------------------------------------------
440 fInnerSec=new AliTPCtrackerSector[fkNIS];
441 fOuterSec=new AliTPCtrackerSector[fkNOS];
444 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
445 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
448 Int_t nrowlow = par->GetNRowLow();
449 Int_t nrowup = par->GetNRowUp();
452 for (i=0;i<nrowlow;i++){
453 fXRow[i] = par->GetPadRowRadiiLow(i);
454 fPadLength[i]= par->GetPadPitchLength(0,i);
455 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
459 for (i=0;i<nrowup;i++){
460 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
461 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
462 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
465 if (AliTPCReconstructor::StreamLevel()>0) {
466 fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
469 fSeedsPool = new TClonesArray("AliTPCseed",1000);
471 // crosstalk array and matrix initialization
473 Int_t nTimeBinsAll = par->GetMaxTBin();
474 Int_t nWireSegments = 11;
475 fCrossTalkSignalArray = new TObjArray(nROCs*4); //
476 fCrossTalkSignalArray->SetOwner(kTRUE);
477 for (Int_t isector=0; isector<4*nROCs; isector++){
478 TMatrixD * crossTalkSignal = new TMatrixD(nWireSegments,nTimeBinsAll);
479 for (Int_t imatrix = 0; imatrix<11; imatrix++)
480 for (Int_t jmatrix = 0; jmatrix<nTimeBinsAll; jmatrix++){
481 (*crossTalkSignal)[imatrix][jmatrix]=0.;
483 fCrossTalkSignalArray->AddAt(crossTalkSignal,isector);
487 //________________________________________________________________________
488 AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
510 fCrossTalkSignalArray(0),
516 //------------------------------------
517 // dummy copy constructor
518 //------------------------------------------------------------------
520 for (Int_t irow=0; irow<200; irow++){
527 AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
529 //------------------------------
531 //--------------------------------------------------------------
534 //_____________________________________________________________________________
535 AliTPCtracker::~AliTPCtracker() {
536 //------------------------------------------------------------------
537 // TPC tracker destructor
538 //------------------------------------------------------------------
545 if (fCrossTalkSignalArray) delete fCrossTalkSignalArray;
546 if (fDebugStreamer) delete fDebugStreamer;
547 if (fSeedsPool) delete fSeedsPool;
551 void AliTPCtracker::FillESD(const TObjArray* arr)
555 //fill esds using updated tracks
561 // write tracks to the event
562 // store index of the track
563 Int_t nseed=arr->GetEntriesFast();
564 //FindKinks(arr,fEvent);
565 for (Int_t i=0; i<nseed; i++) {
566 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
570 if (AliTPCReconstructor::StreamLevel()&kStreamFillESD) {
571 (*fDebugStreamer)<<"FillESD"<< // flag: stream track information in FillESD function (after track Iteration 0)
575 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
576 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
577 pt->PropagateTo(fkParam->GetInnerRadiusLow());
580 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
581 iotrack.~AliESDtrack();
582 new(&iotrack) AliESDtrack;
583 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
584 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
585 iotrack.SetTPCPoints(pt->GetPoints());
586 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
587 iotrack.SetV0Indexes(pt->GetV0Indexes());
588 // iotrack.SetTPCpid(pt->fTPCr);
589 //iotrack.SetTPCindex(i);
590 MakeESDBitmaps(pt, &iotrack);
591 fEvent->AddTrack(&iotrack);
595 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
596 iotrack.~AliESDtrack();
597 new(&iotrack) AliESDtrack;
598 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
599 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
600 iotrack.SetTPCPoints(pt->GetPoints());
601 //iotrack.SetTPCindex(i);
602 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
603 iotrack.SetV0Indexes(pt->GetV0Indexes());
604 MakeESDBitmaps(pt, &iotrack);
605 // iotrack.SetTPCpid(pt->fTPCr);
606 fEvent->AddTrack(&iotrack);
610 // short tracks - maybe decays
612 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
613 Int_t found,foundable,shared;
614 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
615 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
616 iotrack.~AliESDtrack();
617 new(&iotrack) AliESDtrack;
618 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
619 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
620 //iotrack.SetTPCindex(i);
621 iotrack.SetTPCPoints(pt->GetPoints());
622 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
623 iotrack.SetV0Indexes(pt->GetV0Indexes());
624 MakeESDBitmaps(pt, &iotrack);
625 //iotrack.SetTPCpid(pt->fTPCr);
626 fEvent->AddTrack(&iotrack);
631 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
632 Int_t found,foundable,shared;
633 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
634 if (found<20) continue;
635 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
637 iotrack.~AliESDtrack();
638 new(&iotrack) AliESDtrack;
639 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
640 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
641 iotrack.SetTPCPoints(pt->GetPoints());
642 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
643 iotrack.SetV0Indexes(pt->GetV0Indexes());
644 MakeESDBitmaps(pt, &iotrack);
645 //iotrack.SetTPCpid(pt->fTPCr);
646 //iotrack.SetTPCindex(i);
647 fEvent->AddTrack(&iotrack);
650 // short tracks - secondaties
652 if ( (pt->GetNumberOfClusters()>30) ) {
653 Int_t found,foundable,shared;
654 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
655 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
656 iotrack.~AliESDtrack();
657 new(&iotrack) AliESDtrack;
658 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
659 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
660 iotrack.SetTPCPoints(pt->GetPoints());
661 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
662 iotrack.SetV0Indexes(pt->GetV0Indexes());
663 MakeESDBitmaps(pt, &iotrack);
664 //iotrack.SetTPCpid(pt->fTPCr);
665 //iotrack.SetTPCindex(i);
666 fEvent->AddTrack(&iotrack);
671 if ( (pt->GetNumberOfClusters()>15)) {
672 Int_t found,foundable,shared;
673 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
674 if (found<15) continue;
675 if (foundable<=0) continue;
676 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
677 if (float(found)/float(foundable)<0.8) continue;
679 iotrack.~AliESDtrack();
680 new(&iotrack) AliESDtrack;
681 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
682 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
683 iotrack.SetTPCPoints(pt->GetPoints());
684 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
685 iotrack.SetV0Indexes(pt->GetV0Indexes());
686 MakeESDBitmaps(pt, &iotrack);
687 // iotrack.SetTPCpid(pt->fTPCr);
688 //iotrack.SetTPCindex(i);
689 fEvent->AddTrack(&iotrack);
693 // >> account for suppressed tracks in the kink indices (RS)
694 int nESDtracks = fEvent->GetNumberOfTracks();
695 for (int it=nESDtracks;it--;) {
696 AliESDtrack* esdTr = fEvent->GetTrack(it);
697 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
698 for (int ik=0;ik<3;ik++) {
700 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
701 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
703 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
706 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
710 // << account for suppressed tracks in the kink indices (RS)
711 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
719 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
722 // Use calibrated cluster error from OCDB
724 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
726 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
727 Int_t ctype = cl->GetType();
728 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
729 Double_t angle = seed->GetSnp()*seed->GetSnp();
730 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
731 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
733 erry2+=0.5; // edge cluster
737 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
738 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
739 erry2+=addErr*addErr;
740 const Double_t *errCluster = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorCluster();
741 erry2+=errCluster[0]*errCluster[0];
742 seed->SetErrorY2(erry2);
746 //calculate look-up table at the beginning
747 // static Bool_t ginit = kFALSE;
748 // static Float_t gnoise1,gnoise2,gnoise3;
749 // static Float_t ggg1[10000];
750 // static Float_t ggg2[10000];
751 // static Float_t ggg3[10000];
752 // static Float_t glandau1[10000];
753 // static Float_t glandau2[10000];
754 // static Float_t glandau3[10000];
756 // static Float_t gcor01[500];
757 // static Float_t gcor02[500];
758 // static Float_t gcorp[500];
762 // if (ginit==kFALSE){
763 // for (Int_t i=1;i<500;i++){
764 // Float_t rsigma = float(i)/100.;
765 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
766 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
767 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
771 // for (Int_t i=3;i<10000;i++){
775 // Float_t amp = float(i);
776 // Float_t padlength =0.75;
777 // gnoise1 = 0.0004/padlength;
778 // Float_t nel = 0.268*amp;
779 // Float_t nprim = 0.155*amp;
780 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
781 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
782 // if (glandau1[i]>1) glandau1[i]=1;
783 // glandau1[i]*=padlength*padlength/12.;
787 // gnoise2 = 0.0004/padlength;
789 // nprim = 0.133*amp;
790 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
791 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
792 // if (glandau2[i]>1) glandau2[i]=1;
793 // glandau2[i]*=padlength*padlength/12.;
798 // gnoise3 = 0.0004/padlength;
800 // nprim = 0.133*amp;
801 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
802 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
803 // if (glandau3[i]>1) glandau3[i]=1;
804 // glandau3[i]*=padlength*padlength/12.;
812 // Int_t amp = int(TMath::Abs(cl->GetQ()));
814 // seed->SetErrorY2(1.);
818 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
819 // Int_t ctype = cl->GetType();
820 // Float_t padlength= GetPadPitchLength(seed->GetRow());
821 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
822 // angle2 = angle2/(1-angle2);
824 // //cluster "quality"
825 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
828 // if (fSectors==fInnerSec){
829 // snoise2 = gnoise1;
830 // res = ggg1[amp]*z+glandau1[amp]*angle2;
831 // if (ctype==0) res *= gcor01[rsigmay];
834 // res*= gcorp[rsigmay];
838 // if (padlength<1.1){
839 // snoise2 = gnoise2;
840 // res = ggg2[amp]*z+glandau2[amp]*angle2;
841 // if (ctype==0) res *= gcor02[rsigmay];
844 // res*= gcorp[rsigmay];
848 // snoise2 = gnoise3;
849 // res = ggg3[amp]*z+glandau3[amp]*angle2;
850 // if (ctype==0) res *= gcor02[rsigmay];
853 // res*= gcorp[rsigmay];
860 // res*=2.4; // overestimate error 2 times
864 // if (res<2*snoise2)
867 // seed->SetErrorY2(res);
875 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
878 // Use calibrated cluster error from OCDB
880 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
882 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
883 Int_t ctype = cl->GetType();
884 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
886 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
887 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
888 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
889 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
891 errz2+=0.5; // edge cluster
895 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
896 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
897 errz2+=addErr*addErr;
898 const Double_t *errCluster = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorCluster();
899 errz2+=errCluster[1]*errCluster[1];
900 seed->SetErrorZ2(errz2);
906 // //seed->SetErrorY2(0.1);
908 // //calculate look-up table at the beginning
909 // static Bool_t ginit = kFALSE;
910 // static Float_t gnoise1,gnoise2,gnoise3;
911 // static Float_t ggg1[10000];
912 // static Float_t ggg2[10000];
913 // static Float_t ggg3[10000];
914 // static Float_t glandau1[10000];
915 // static Float_t glandau2[10000];
916 // static Float_t glandau3[10000];
918 // static Float_t gcor01[1000];
919 // static Float_t gcor02[1000];
920 // static Float_t gcorp[1000];
924 // if (ginit==kFALSE){
925 // for (Int_t i=1;i<1000;i++){
926 // Float_t rsigma = float(i)/100.;
927 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
928 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
929 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
933 // for (Int_t i=3;i<10000;i++){
937 // Float_t amp = float(i);
938 // Float_t padlength =0.75;
939 // gnoise1 = 0.0004/padlength;
940 // Float_t nel = 0.268*amp;
941 // Float_t nprim = 0.155*amp;
942 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
943 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
944 // if (glandau1[i]>1) glandau1[i]=1;
945 // glandau1[i]*=padlength*padlength/12.;
949 // gnoise2 = 0.0004/padlength;
951 // nprim = 0.133*amp;
952 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
953 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
954 // if (glandau2[i]>1) glandau2[i]=1;
955 // glandau2[i]*=padlength*padlength/12.;
960 // gnoise3 = 0.0004/padlength;
962 // nprim = 0.133*amp;
963 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
964 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
965 // if (glandau3[i]>1) glandau3[i]=1;
966 // glandau3[i]*=padlength*padlength/12.;
974 // Int_t amp = int(TMath::Abs(cl->GetQ()));
976 // seed->SetErrorY2(1.);
980 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
981 // Int_t ctype = cl->GetType();
982 // Float_t padlength= GetPadPitchLength(seed->GetRow());
984 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
985 // // if (angle2<0.6) angle2 = 0.6;
986 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
988 // //cluster "quality"
989 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
992 // if (fSectors==fInnerSec){
993 // snoise2 = gnoise1;
994 // res = ggg1[amp]*z+glandau1[amp]*angle2;
995 // if (ctype==0) res *= gcor01[rsigmaz];
998 // res*= gcorp[rsigmaz];
1002 // if (padlength<1.1){
1003 // snoise2 = gnoise2;
1004 // res = ggg2[amp]*z+glandau2[amp]*angle2;
1005 // if (ctype==0) res *= gcor02[rsigmaz];
1008 // res*= gcorp[rsigmaz];
1012 // snoise2 = gnoise3;
1013 // res = ggg3[amp]*z+glandau3[amp]*angle2;
1014 // if (ctype==0) res *= gcor02[rsigmaz];
1017 // res*= gcorp[rsigmaz];
1026 // if ((ctype<0) &&<70){
1031 // if (res<2*snoise2)
1033 // if (res>3) res =3;
1034 // seed->SetErrorZ2(res);
1042 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1044 //rotate to track "local coordinata
1045 Float_t x = seed->GetX();
1046 Float_t y = seed->GetY();
1047 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1050 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1051 if (!seed->Rotate(fSectors->GetAlpha()))
1053 } else if (y <-ymax) {
1054 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1055 if (!seed->Rotate(-fSectors->GetAlpha()))
1063 //_____________________________________________________________________________
1064 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1065 Double_t x2,Double_t y2,
1066 Double_t x3,Double_t y3) const
1068 //-----------------------------------------------------------------
1069 // Initial approximation of the track curvature
1070 //-----------------------------------------------------------------
1071 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1072 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1073 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1074 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1075 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1077 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1078 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1079 return -xr*yr/sqrt(xr*xr+yr*yr);
1084 //_____________________________________________________________________________
1085 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1086 Double_t x2,Double_t y2,
1087 Double_t x3,Double_t y3) const
1089 //-----------------------------------------------------------------
1090 // Initial approximation of the track curvature
1091 //-----------------------------------------------------------------
1097 Double_t det = x3*y2-x2*y3;
1098 if (TMath::Abs(det)<1e-10){
1102 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1103 Double_t x0 = x3*0.5-y3*u;
1104 Double_t y0 = y3*0.5+x3*u;
1105 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1111 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1112 Double_t x2,Double_t y2,
1113 Double_t x3,Double_t y3) const
1115 //-----------------------------------------------------------------
1116 // Initial approximation of the track curvature
1117 //-----------------------------------------------------------------
1123 Double_t det = x3*y2-x2*y3;
1124 if (TMath::Abs(det)<1e-10) {
1128 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1129 Double_t x0 = x3*0.5-y3*u;
1130 Double_t y0 = y3*0.5+x3*u;
1131 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1140 //_____________________________________________________________________________
1141 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1142 Double_t x2,Double_t y2,
1143 Double_t x3,Double_t y3) const
1145 //-----------------------------------------------------------------
1146 // Initial approximation of the track curvature times center of curvature
1147 //-----------------------------------------------------------------
1148 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1149 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1150 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1151 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1152 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1154 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1156 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1159 //_____________________________________________________________________________
1160 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1161 Double_t x2,Double_t y2,
1162 Double_t z1,Double_t z2) const
1164 //-----------------------------------------------------------------
1165 // Initial approximation of the tangent of the track dip angle
1166 //-----------------------------------------------------------------
1167 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1171 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1172 Double_t x2,Double_t y2,
1173 Double_t z1,Double_t z2, Double_t c) const
1175 //-----------------------------------------------------------------
1176 // Initial approximation of the tangent of the track dip angle
1177 //-----------------------------------------------------------------
1181 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1183 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1184 if (TMath::Abs(d*c*0.5)>1) return 0;
1185 // Double_t angle2 = TMath::ASin(d*c*0.5);
1186 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1187 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1189 angle2 = (z1-z2)*c/(angle2*2.);
1193 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1194 {//-----------------------------------------------------------------
1195 // This function find proloncation of a track to a reference plane x=x2.
1196 //-----------------------------------------------------------------
1200 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1204 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1205 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1209 Double_t dy = dx*(c1+c2)/(r1+r2);
1212 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1214 if (TMath::Abs(delta)>0.01){
1215 dz = x[3]*TMath::ASin(delta)/x[4];
1217 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1220 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1228 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1233 return LoadClusters();
1237 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1240 // load clusters to the memory
1241 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1242 Int_t lower = arr->LowerBound();
1243 Int_t entries = arr->GetEntriesFast();
1245 for (Int_t i=lower; i<entries; i++) {
1246 clrow = (AliTPCClustersRow*) arr->At(i);
1247 if(!clrow) continue;
1248 if(!clrow->GetArray()) continue;
1252 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1254 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1255 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1258 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1259 AliTPCtrackerRow * tpcrow=0;
1262 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1266 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1267 left = (sec-fkNIS*2)/fkNOS;
1270 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1271 for (Int_t j=0;j<tpcrow->GetN1();++j)
1272 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1275 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1276 for (Int_t j=0;j<tpcrow->GetN2();++j)
1277 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1279 clrow->GetArray()->Clear("C");
1288 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1291 // load clusters to the memory from one
1294 AliTPCclusterMI *clust=0;
1295 Int_t count[72][96] = { {0} , {0} };
1297 // loop over clusters
1298 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1299 clust = (AliTPCclusterMI*)arr->At(icl);
1300 if(!clust) continue;
1301 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1303 // transform clusters
1306 // count clusters per pad row
1307 count[clust->GetDetector()][clust->GetRow()]++;
1310 // insert clusters to sectors
1311 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1312 clust = (AliTPCclusterMI*)arr->At(icl);
1313 if(!clust) continue;
1315 Int_t sec = clust->GetDetector();
1316 Int_t row = clust->GetRow();
1318 // filter overlapping pad rows needed by HLT
1319 if(sec<fkNIS*2) { //IROCs
1320 if(row == 30) continue;
1323 if(row == 27 || row == 76) continue;
1328 // left = sec/fkNIS;
1329 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1332 // left = (sec-fkNIS*2)/fkNOS;
1333 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1337 // Load functions must be called behind LoadCluster(TClonesArray*)
1339 //LoadOuterSectors();
1340 //LoadInnerSectors();
1346 Int_t AliTPCtracker::LoadClusters()
1349 // load clusters to the memory
1350 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1352 // TTree * tree = fClustersArray.GetTree();
1353 AliInfo("LoadClusters()\n");
1355 TTree * tree = fInput;
1356 TBranch * br = tree->GetBranch("Segment");
1357 br->SetAddress(&clrow);
1359 // Conversion of pad, row coordinates in local tracking coords.
1360 // Could be skipped here; is already done in clusterfinder
1362 Int_t j=Int_t(tree->GetEntries());
1363 for (Int_t i=0; i<j; i++) {
1367 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1368 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1369 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1372 AliTPCtrackerRow * tpcrow=0;
1375 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1379 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1380 left = (sec-fkNIS*2)/fkNOS;
1383 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1384 for (Int_t k=0;k<tpcrow->GetN1();++k)
1385 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1388 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1389 for (Int_t k=0;k<tpcrow->GetN2();++k)
1390 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1398 cout << " =================================================================================================================================== " << endl;
1399 cout << " AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection() = " << AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection() << endl;
1400 cout << " AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection() = " << AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection() << endl;
1401 cout << " =================================================================================================================================== " << endl;
1403 if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1404 if (AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()!=0.) CalculateXtalkCorrection();
1405 if (AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()!=0.) ApplyXtalkCorrection();
1406 //if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();
1411 void AliTPCtracker::CalculateXtalkCorrection(){
1413 // Calculate crosstalk estimate
1415 const Int_t nROCs = 72;
1416 const Int_t nIterations=3; //
1417 // 0.) reset crosstalk matrix
1419 for (Int_t isector=0; isector<nROCs*4; isector++){ //set all ellemts of crosstalk matrix to 0
1420 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1421 if (crossTalkMatrix)(*crossTalkMatrix)*=0;
1425 // 1.) Filling part -- loop over clusters
1427 Double_t missingChargeFactor= AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrectionMissingCharge();
1428 for (Int_t iter=0; iter<nIterations;iter++){
1429 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1430 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1431 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1432 Int_t nrows = sector.GetNRows();
1434 if (isector<18) sec=isector+18*iside;
1435 if (isector>=18) sec=18+isector+18*iside;
1436 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1439 Int_t wireSegmentID = fkParam->GetWireSegment(sec,row);
1440 Float_t nPadsPerSegment = (Float_t)(fkParam->GetNPadsPerSegment(wireSegmentID));
1441 TMatrixD &crossTalkSignal = *((TMatrixD*)fCrossTalkSignalArray->At(sec));
1442 TMatrixD &crossTalkSignalCache = *((TMatrixD*)fCrossTalkSignalArray->At(sec+nROCs*2)); // this is the cache value of the crosstalk from previous iteration
1443 TMatrixD &crossTalkSignalBelow = *((TMatrixD*)fCrossTalkSignalArray->At(sec+nROCs));
1444 Int_t nCols=crossTalkSignal.GetNcols();
1446 AliTPCtrackerRow& tpcrow = sector[row];
1447 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1448 if (iside>0) ncl=tpcrow.GetN2();
1449 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1450 AliTPCclusterMI *clXtalk= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1452 Int_t timeBinXtalk = clXtalk->GetTimeBin();
1453 Double_t rmsPadMin2=0.5*0.5+(fkParam->GetDiffT()*fkParam->GetDiffT())*(TMath::Abs((clXtalk->GetZ()-fkParam->GetZLength())))/(fkParam->GetPadPitchWidth(sec)*fkParam->GetPadPitchWidth(sec)); // minimal PRF width - 0.5 is the PRF in the pad units - we should et it from fkparam getters
1454 Double_t rmsTimeMin2=1+(fkParam->GetDiffL()*fkParam->GetDiffL())*(TMath::Abs((clXtalk->GetZ()-fkParam->GetZLength())))/(fkParam->GetZWidth()*fkParam->GetZWidth()); // minimal PRF width - 1 is the TRF in the time bin units - we should et it from fkParam getters
1455 Double_t rmsTime2 = clXtalk->GetSigmaZ2()/(fkParam->GetZWidth()*fkParam->GetZWidth());
1456 Double_t rmsPad2 = clXtalk->GetSigmaY2()/(fkParam->GetPadPitchWidth(sec)*fkParam->GetPadPitchWidth(sec));
1457 if (rmsPadMin2>rmsPad2){
1460 if (rmsTimeMin2>rmsTime2){
1461 rmsTime2=rmsTimeMin2;
1464 Double_t norm= 2.*TMath::Exp(-1.0/(2.*rmsTime2))+2.*TMath::Exp(-4.0/(2.*rmsTime2))+1.;
1465 Double_t qTotXtalk = 0.;
1466 Double_t qTotXtalkMissing = 0.;
1467 for (Int_t itb=timeBinXtalk-2, idelta=-2; itb<=timeBinXtalk+2; itb++,idelta++) {
1468 if (itb<0 || itb>=nCols) continue;
1469 Double_t missingCharge=0;
1470 Double_t trf= TMath::Exp(-idelta*idelta/(2.*rmsTime2));
1471 if (missingChargeFactor>0) {
1472 for (Int_t dpad=-2; dpad<=2; dpad++){
1473 Double_t qPad = clXtalk->GetMax()*TMath::Exp(-dpad*dpad/(2.*rmsPad2))*trf;
1474 if (TMath::Nint(qPad-crossTalkSignalCache[wireSegmentID][itb])<=fkParam->GetZeroSup()){
1475 missingCharge+=qPad+crossTalkSignalCache[wireSegmentID][itb];
1477 missingCharge+=crossTalkSignalCache[wireSegmentID][itb];
1481 qTotXtalk = clXtalk->GetQ()*trf/norm+missingCharge*missingChargeFactor;
1482 qTotXtalkMissing = missingCharge;
1483 crossTalkSignal[wireSegmentID][itb]+= qTotXtalk/nPadsPerSegment;
1484 crossTalkSignalBelow[wireSegmentID][itb]+= qTotXtalkMissing/nPadsPerSegment;
1485 } // end of time bin loop
1486 } // end of cluster loop
1487 } // end of rows loop
1488 } // end of side loop
1489 } // end of sector loop
1491 // copy crosstalk matrix to cached used for next itteration
1494 // 2.) dump the crosstalk matrices to tree for further investigation
1495 // a.) to estimate fluctuation of pedestal in indiviula wire segments
1496 // b.) to check correlation between regions
1497 // c.) to check relative conribution of signal below threshold to crosstalk
1499 if (AliTPCReconstructor::StreamLevel()&kStreamCrosstalkMatrix) {
1500 for (Int_t isector=0; isector<nROCs; isector++){ //set all ellemts of crosstalk matrix to 0
1501 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1502 TMatrixD * crossTalkMatrixBelow = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs);
1503 TMatrixD * crossTalkMatrixCache = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs*2);
1504 TVectorD vecAll(crossTalkMatrix->GetNrows());
1505 TVectorD vecBelow(crossTalkMatrix->GetNrows());
1506 TVectorD vecCache(crossTalkMatrixCache->GetNrows());
1508 for (Int_t itime=0; itime<crossTalkMatrix->GetNcols(); itime++){
1509 for (Int_t iwire=0; iwire<crossTalkMatrix->GetNrows(); iwire++){
1510 vecAll[iwire]=(*crossTalkMatrix)(iwire,itime);
1511 vecBelow[iwire]=(*crossTalkMatrixBelow)(iwire,itime);
1512 vecCache[iwire]=(*crossTalkMatrixCache)(iwire,itime);
1514 (*fDebugStreamer)<<"crosstalkMatrix"<<
1515 "iter="<<iter<< //iteration
1516 "sector="<<isector<< // sector
1517 "itime="<<itime<< // time bin index
1518 "vecAll.="<<&vecAll<< // crosstalk charge + charge below threshold
1519 "vecCache.="<<&vecCache<< // crosstalk charge + charge below threshold
1520 "vecBelow.="<<&vecBelow<< // crosstalk contribution from signal below threshold
1525 if (iter<nIterations-1) for (Int_t isector=0; isector<nROCs*2; isector++){ //set all ellemts of crosstalk matrix to 0
1526 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1527 TMatrixD * crossTalkMatrixCache = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs*2);
1528 if (crossTalkMatrix){
1529 (*crossTalkMatrixCache)*=0;
1530 (*crossTalkMatrixCache)+=(*crossTalkMatrix);
1531 (*crossTalkMatrix)*=0;
1542 void AliTPCtracker::FilterOutlierClusters(){
1544 // filter outlier clusters
1547 1.)..... booking part
1549 nTimeBins=fParam->Get....
1550 TH2F hisTime("","", sector,0,sector, nTimeBins,0,nTimeBins);
1551 TH2F hisPadRow("","", sector,0,sector, nPadRows,0,nPadRows);
1552 2.) .... filling part
1553 .... cluster loop { hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin()); }
1555 3.) ...filtering part
1556 sector loop { calculate median,mean80 and rms80 of the nclusters per time bin; calculate median,mean80 and rms80 of the nclusters per par row; .... export values to the debug streamers - to decide which threshold to be used... }
1559 { disable clusters in time bins > mean+ n rms80+ offsetTime disable clusters in padRow > mean+ n rms80+ offsetPadRow // how to dislable clusters? - new bit to introduce }
1561 4. Disabling clusters
1568 // AliTPCcalibDB *db=AliTPCcalibDB::Instance();
1569 Int_t nSectors=AliTPCROC::Instance()->GetNSectors();
1570 Int_t nTimeBins= 1100; // *Bug here - we should get NTimeBins from ALTRO - Parameters not relyable
1571 Int_t nPadRows=(AliTPCROC::Instance()->GetNRows(0) + AliTPCROC::Instance()->GetNRows(36));
1572 // parameters for filtering
1573 const Double_t nSigmaCut=9.; // should be in recoParam ?
1574 const Double_t offsetTime=100; // should be in RecoParam ? -
1575 const Double_t offsetPadRow=300; // should be in RecoParam ?
1576 const Double_t offsetTimeAccept=8; // should be in RecoParam ? - obtained as mean +1 rms in high IR pp
1577 TH2F hisTime("hisSectorTime","hisSectorTime", nSectors,0,nSectors, nTimeBins,0,nTimeBins);
1578 TH2F hisPadRow("hisSectorRow","hisSectorRow", nSectors,0,nSectors, nPadRows,0,nPadRows);
1580 // 2.) Filling part -- loop over clusters
1582 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1583 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1584 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1585 Int_t nrows = sector.GetNRows();
1586 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1587 AliTPCtrackerRow& tpcrow = sector[row];
1588 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1589 if (iside>0) ncl=tpcrow.GetN2();
1590 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1591 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1592 hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin());
1593 hisPadRow.Fill(cluster->GetDetector(),cluster->GetRow());
1600 // 3. Filtering part
1602 TVectorD vecTime(nTimeBins);
1603 TVectorD vecPadRow(nPadRows);
1604 TVectorD vecMedianSectorTime(nSectors);
1605 TVectorD vecRMSSectorTime(nSectors);
1606 TVectorD vecMedianSectorTimeOut6(nSectors);
1607 TVectorD vecMedianSectorTimeOut9(nSectors);//
1608 TVectorD vecMedianSectorTimeOut(nSectors);//
1609 TVectorD vecMedianSectorPadRow(nSectors);
1610 TVectorD vecRMSSectorPadRow(nSectors);
1611 TVectorD vecMedianSectorPadRowOut6(nSectors);
1612 TVectorD vecMedianSectorPadRowOut9(nSectors);
1613 TVectorD vecMedianSectorPadRowOut(nSectors);
1614 TVectorD vecSectorOut6(nSectors);
1615 TVectorD vecSectorOut9(nSectors);
1616 TMatrixD matSectorCluster(nSectors,2);
1618 // 3.a) median, rms calculations for hisTime
1620 for (Int_t isec=0; isec<nSectors; isec++){
1621 vecMedianSectorTimeOut6[isec]=0;
1622 vecMedianSectorTimeOut9[isec]=0;
1623 for (Int_t itime=0; itime<nTimeBins; itime++){
1624 vecTime[itime]=hisTime.GetBinContent(isec+1, itime+1);
1626 Double_t median= TMath::Mean(nTimeBins,vecTime.GetMatrixArray());
1627 Double_t rms= TMath::RMS(nTimeBins,vecTime.GetMatrixArray());
1628 vecMedianSectorTime[isec]=median;
1629 vecRMSSectorTime[isec]=rms;
1630 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector TimeStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
1633 for (Int_t itime=0; itime<nTimeBins; itime++){
1634 Double_t entries= hisTime.GetBinContent(isec+1, itime+1);
1635 if (entries>median+6.*rms+offsetTime) {
1636 vecMedianSectorTimeOut6[isec]+=1;
1638 if (entries>median+9.*rms+offsetTime) {
1639 vecMedianSectorTimeOut9[isec]+=1;
1644 // 3.b) median, rms calculations for hisPadRow
1646 for (Int_t isec=0; isec<nSectors; isec++){
1647 vecMedianSectorPadRowOut6[isec]=0;
1648 vecMedianSectorPadRowOut9[isec]=0;
1649 for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
1650 vecPadRow[ipadrow]=hisPadRow.GetBinContent(isec+1, ipadrow+1);
1652 Int_t nPadRowsSector= AliTPCROC::Instance()->GetNRows(isec);
1653 Double_t median= TMath::Mean(nPadRowsSector,vecPadRow.GetMatrixArray());
1654 Double_t rms= TMath::RMS(nPadRowsSector,vecPadRow.GetMatrixArray());
1655 vecMedianSectorPadRow[isec]=median;
1656 vecRMSSectorPadRow[isec]=rms;
1657 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector PadRowStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
1660 for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
1661 Double_t entries= hisPadRow.GetBinContent(isec+1, ipadrow+1);
1662 if (entries>median+6.*rms+offsetPadRow) {
1663 vecMedianSectorPadRowOut6[isec]+=1;
1665 if (entries>median+9.*rms+offsetPadRow) {
1666 vecMedianSectorPadRowOut9[isec]+=1;
1671 // 3.c) filter outlier sectors
1673 Double_t medianSectorTime = TMath::Median(nSectors, vecTime.GetMatrixArray());
1674 Double_t mean69SectorTime, rms69SectorTime=0;
1675 AliMathBase::EvaluateUni(nSectors, vecTime.GetMatrixArray(), mean69SectorTime,rms69SectorTime,69);
1676 for (Int_t isec=0; isec<nSectors; isec++){
1677 vecSectorOut6[isec]=0;
1678 vecSectorOut9[isec]=0;
1679 matSectorCluster(isec,0)=0;
1680 matSectorCluster(isec,1)=0;
1681 if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+6.*(rms69SectorTime+ offsetTimeAccept))) {
1682 vecSectorOut6[isec]=1;
1684 if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+9.*(rms69SectorTime+ offsetTimeAccept))){
1685 vecSectorOut9[isec]=1;
1688 // light version of export variable
1689 Int_t filteredSector= vecSectorOut9.Sum(); // light version of export variable
1690 Int_t filteredSectorTime= vecMedianSectorTimeOut9.Sum();
1691 Int_t filteredSectorPadRow= vecMedianSectorPadRowOut9.Sum();
1692 if (fEvent) if (fEvent->GetHeader()){
1693 fEvent->GetHeader()->SetTPCNoiseFilterCounter(0,TMath::Min(filteredSector,255));
1694 fEvent->GetHeader()->SetTPCNoiseFilterCounter(1,TMath::Min(filteredSectorTime,255));
1695 fEvent->GetHeader()->SetTPCNoiseFilterCounter(2,TMath::Min(filteredSectorPadRow,255));
1699 // 4. Disabling clusters in outlier layers
1703 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1704 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1705 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1706 Int_t nrows = sector.GetNRows();
1707 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1708 AliTPCtrackerRow& tpcrow = sector[row];
1709 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1710 if (iside>0) ncl=tpcrow.GetN2();
1711 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1712 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1713 Double_t medianTime=vecMedianSectorTime[cluster->GetDetector()];
1714 Double_t medianPadRow=vecMedianSectorPadRow[cluster->GetDetector()];
1715 Double_t rmsTime=vecRMSSectorTime[cluster->GetDetector()];
1716 Double_t rmsPadRow=vecRMSSectorPadRow[cluster->GetDetector()];
1717 Int_t entriesPadRow=hisPadRow.GetBinContent(cluster->GetDetector()+1, cluster->GetRow()+1);
1718 Int_t entriesTime=hisTime.GetBinContent(cluster->GetDetector()+1, cluster->GetTimeBin()+1);
1719 Bool_t isOut=kFALSE;
1720 if (vecSectorOut9[cluster->GetDetector()]>0.5) {
1724 if (entriesTime>medianTime+nSigmaCut*rmsTime+offsetTime) {
1726 vecMedianSectorTimeOut[cluster->GetDetector()]++;
1728 if (entriesPadRow>medianPadRow+nSigmaCut*rmsPadRow+offsetPadRow) {
1730 vecMedianSectorPadRowOut[cluster->GetDetector()]++;
1733 matSectorCluster(cluster->GetDetector(),0)+=1;
1737 matSectorCluster(cluster->GetDetector(),1)+=1;
1743 for (Int_t isec=0; isec<nSectors; isec++){
1744 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector Stat: %d\t%8.0f\t%8.0f",isec,matSectorCluster(isec,1),matSectorCluster(isec,0)).Data());
1747 // dump info to streamer - for later tuning of cuts
1749 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) { // stream TPC data ouliers filtering infomation
1751 AliInfo(TString::Format("Cluster counter: (%d/%d) (Filtered/All)",counterOut,counterAll).Data());
1752 for (Int_t iSec=0; iSec<nSectors; iSec++){
1753 if (vecSectorOut9[iSec]>0 || matSectorCluster(iSec,1)>0) {
1754 AliInfo(TString::Format("Filtered sector\t%d",iSec).Data());
1755 Double_t vecMedTime =TMath::Median(72,vecMedianSectorTime.GetMatrixArray());
1756 Double_t vecMedPadRow =TMath::Median(72,vecMedianSectorPadRow.GetMatrixArray());
1757 Double_t vecMedCluster=(counterAll-counterOut)/72;
1758 AliInfo(TString::Format("VecMedianSectorTime\t(%4.4f/%4.4f/%4.4f)", vecMedianSectorTimeOut[iSec],vecMedianSectorTime[iSec],vecMedTime).Data());
1759 AliInfo(TString::Format("VecMedianSectorPadRow\t(%4.4f/%4.4f/%4.4f)", vecMedianSectorPadRowOut[iSec],vecMedianSectorPadRow[iSec],vecMedPadRow).Data());
1760 AliInfo(TString::Format("MatSectorCluster\t(%4.4f/%4.4f/%4.4f)\n", matSectorCluster(iSec,1), matSectorCluster(iSec,0), vecMedCluster).Data());
1765 Int_t eventNr = fEvent->GetEventNumberInFile();
1766 (*fDebugStreamer)<<"filterClusterInfo"<<
1767 // minimal set variables for the ESDevent
1768 "eventNr="<<eventNr<<
1769 "counterAll="<<counterAll<<
1770 "counterOut="<<counterOut<<
1771 "matSectotCluster.="<<&matSectorCluster<< //
1773 "filteredSector="<<filteredSector<< // counter filtered sectors
1774 "filteredSectorTime="<<filteredSectorTime<< // counter filtered time bins
1775 "filteredSectorPadRow="<<filteredSectorPadRow<< // counter filtered pad-rows
1776 // per sector outlier information
1777 "medianSectorTime="<<medianSectorTime<< // median number of clusters per sector/timebin
1778 "mean69SectorTime="<<mean69SectorTime<< // LTM statistic mean of clusters per sector/timebin
1779 "rms69SectorTime="<<rms69SectorTime<< // LTM statistic RMS of clusters per sector/timebin
1780 "vecSectorOut6.="<<&vecSectorOut6<< // flag array sector - 6 sigma +accept margin outlier
1781 "vecSectorOut9.="<<&vecSectorOut9<< // flag array sector - 9 sigma + accept margin outlier
1782 // per sector/timebin outlier detection
1783 "vecMedianSectorTime.="<<&vecMedianSectorTime<<
1784 "vecRMSSectorTime.="<<&vecRMSSectorTime<<
1785 "vecMedianSectorTimeOut6.="<<&vecMedianSectorTimeOut6<<
1786 "vecMedianSectorTimeOut9.="<<&vecMedianSectorTimeOut9<<
1787 "vecMedianSectorTimeOut0.="<<&vecMedianSectorTimeOut<<
1788 // per sector/pad-row outlier detection
1789 "vecMedianSectorPadRow.="<<&vecMedianSectorPadRow<<
1790 "vecRMSSectorPadRow.="<<&vecRMSSectorPadRow<<
1791 "vecMedianSectorPadRowOut6.="<<&vecMedianSectorPadRowOut6<<
1792 "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut9<<
1793 "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut<<
1795 ((*fDebugStreamer)<<"filterClusterInfo").GetTree()->Write();
1796 fDebugStreamer->GetFile()->Flush();
1800 void AliTPCtracker::UnloadClusters()
1803 // unload clusters from the memory
1805 Int_t nrows = fOuterSec->GetNRows();
1806 for (Int_t sec = 0;sec<fkNOS;sec++)
1807 for (Int_t row = 0;row<nrows;row++){
1808 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1810 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1811 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1813 tpcrow->ResetClusters();
1816 nrows = fInnerSec->GetNRows();
1817 for (Int_t sec = 0;sec<fkNIS;sec++)
1818 for (Int_t row = 0;row<nrows;row++){
1819 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1821 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1822 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1824 tpcrow->ResetClusters();
1830 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1832 // Filling cluster to the array - For visualization purposes
1835 nrows = fOuterSec->GetNRows();
1836 for (Int_t sec = 0;sec<fkNOS;sec++)
1837 for (Int_t row = 0;row<nrows;row++){
1838 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1839 if (!tpcrow) continue;
1840 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1841 array->AddLast((TObject*)((*tpcrow)[icl]));
1844 nrows = fInnerSec->GetNRows();
1845 for (Int_t sec = 0;sec<fkNIS;sec++)
1846 for (Int_t row = 0;row<nrows;row++){
1847 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1848 if (!tpcrow) continue;
1849 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1850 array->AddLast((TObject*)(*tpcrow)[icl]);
1856 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1860 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1861 AliTPCTransform *transform = calibDB->GetTransform() ;
1863 AliFatal("Tranformations not in calibDB");
1866 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1867 Double_t x[3]={static_cast<Double_t>(cluster->GetRow()),static_cast<Double_t>(cluster->GetPad()),static_cast<Double_t>(cluster->GetTimeBin())};
1868 Int_t i[1]={cluster->GetDetector()};
1869 transform->Transform(x,i,0,1);
1870 // if (cluster->GetDetector()%36>17){
1875 // in debug mode check the transformation
1877 if ((AliTPCReconstructor::StreamLevel()&kStreamTransform)>0) {
1879 cluster->GetGlobalXYZ(gx);
1880 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1881 TTreeSRedirector &cstream = *fDebugStreamer;
1882 cstream<<"Transform"<< // needed for debugging of the cluster transformation, resp. used for later visualization
1893 cluster->SetX(x[0]);
1894 cluster->SetY(x[1]);
1895 cluster->SetZ(x[2]);
1900 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1901 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1902 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1904 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1905 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1906 if (mat) mat->LocalToMaster(pos,posC);
1908 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1910 cluster->SetX(posC[0]);
1911 cluster->SetY(posC[1]);
1912 cluster->SetZ(posC[2]);
1916 void AliTPCtracker::ApplyXtalkCorrection(){
1918 // ApplyXtalk correction
1919 // Loop over all clusters
1920 // add to each cluster signal corresponding to common Xtalk mode for given time bin at given wire segment
1922 for (Int_t isector=0; isector<36; isector++){ //loop tracking sectors
1923 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1924 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1925 Int_t nrows = sector.GetNRows();
1926 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1927 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1928 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1929 if (iside>0) ncl=tpcrow.GetN2();
1930 Int_t xSector=0; // sector number in the TPC convention 0-72
1931 if (isector<18){ //if IROC
1932 xSector=isector+(iside>0)*18;
1934 xSector=isector+18; // isector -18 +36
1935 if (iside>0) xSector+=18;
1937 TMatrixD &crossTalkMatrix= *((TMatrixD*)fCrossTalkSignalArray->At(xSector));
1938 Int_t wireSegmentID = fkParam->GetWireSegment(xSector,row);
1939 for (Int_t i=0;i<ncl;i++) {
1940 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1941 Int_t iTimeBin=TMath::Nint(cluster->GetTimeBin());
1942 Double_t xTalk= crossTalkMatrix[wireSegmentID][iTimeBin];
1943 cluster->SetMax(cluster->GetMax()+xTalk);
1944 const Double_t kDummy=4;
1945 Double_t sumxTalk=xTalk*kDummy; // should be calculated via time response function
1946 cluster->SetQ(cluster->GetQ()+sumxTalk);
1949 if ((AliTPCReconstructor::StreamLevel()&kStreamXtalk)>0) { // flag: stream crosstalk correctio as applied to cluster
1950 TTreeSRedirector &cstream = *fDebugStreamer;
1951 if (gRandom->Rndm() > 0.){
1953 "isector=" << isector << // sector [0,36]
1954 "iside=" << iside << // side A or C
1955 "row=" << row << // padrow
1956 "i=" << i << // index of the cluster
1957 "xSector=" << xSector << // sector [0,72]
1958 "wireSegmentID=" << wireSegmentID << // anode wire segment id [0,10]
1959 "iTimeBin=" << iTimeBin << // timebin of the corrected cluster
1960 "xTalk=" << xTalk << // Xtalk contribution added to Qmax
1961 "sumxTalk=" << sumxTalk << // Xtalk contribution added to Qtot (roughly 3*Xtalk)
1962 "cluster.=" << cluster << // corrected cluster object
1965 }// dump the results to the debug streamer if in debug mode
1977 void AliTPCtracker::ApplyTailCancellation(){
1979 // Correct the cluster charge for the ion tail effect
1980 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1984 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1985 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1986 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1987 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1988 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1989 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1991 // find the number of clusters for the whole TPC (nclALL)
1993 for (Int_t isector=0; isector<36; isector++){
1994 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1995 nclALL += sector.GetNClInSector(0);
1996 nclALL += sector.GetNClInSector(1);
1999 // start looping over all clusters
2000 for (Int_t iside=0; iside<2; iside++){ // loop over sides
2003 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
2004 // cache experimantal tuning factor for the different chamber type
2005 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
2006 std::cout << " ampfactor = " << ampfactor << std::endl;
2008 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
2011 // Cache time response functions and their positons to COG of the cluster
2012 TGraphErrors ** graphRes = new TGraphErrors *[20];
2013 Float_t * indexAmpGraphs = new Float_t[20];
2014 for (Int_t icache=0; icache<20; icache++)
2016 graphRes[icache] = NULL;
2017 indexAmpGraphs[icache] = 0;
2019 ///////////////////////////// --> position fo sie loop
2020 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
2025 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
2026 Int_t nrows = sector.GetNRows(); // number of rows
2027 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
2029 for (Int_t row = 0;row<nrows;row++){ // loop over rows
2031 AliTPCtrackerRow& tpcrow = sector[row]; // row object
2032 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
2033 if (iside>0) ncl=tpcrow.GetN2();
2035 // Order clusters in time for the proper correction of ion tail
2036 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
2037 Float_t qMaxArray[ncl];
2038 Int_t sortedClusterIndex[ncl];
2039 Float_t sortedClusterTimeBin[ncl];
2040 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
2041 for (Int_t i=0;i<ncl;i++)
2045 sortedClusterIndex[i]=i;
2046 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
2048 rowClusterArray->AddAt(rowcl,i);
2050 rowClusterArray->RemoveAt(i);
2052 // Fill the timebin info to the array in order to sort wrt tb
2054 sortedClusterTimeBin[i]=0.0;
2056 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
2060 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
2062 // Main cluster correction loops over clusters
2063 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
2065 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
2069 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
2070 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
2072 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
2073 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
2074 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
2076 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
2078 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
2079 Double_t ionTailMax=0.;
2080 Double_t ionTailTotal=0.;
2081 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
2082 ionTailMax=TMath::Abs(ionTailMax);
2083 ionTailTotal=TMath::Abs(ionTailTotal);
2084 qTotArray[icl0]+=ionTailTotal;
2085 qMaxArray[icl0]+=ionTailMax;
2087 // Dump some info for debugging while clusters are being corrected
2088 if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) { // flag: stream ion tail correction as applied to cluster
2089 TTreeSRedirector &cstream = *fDebugStreamer;
2090 if (gRandom->Rndm() > 0.999){
2091 cstream<<"IonTail"<<
2092 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
2093 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
2094 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
2095 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
2098 }// dump the results to the debug streamer if in debug mode
2100 }//end of second loop over clusters
2102 // Set corrected values of the corrected cluster
2103 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
2104 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
2106 // Dump some info for debugging after clusters are corrected
2107 if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) {
2108 TTreeSRedirector &cstream = *fDebugStreamer;
2109 if (gRandom->Rndm() > 0.999){
2110 cstream<<"IonTailCorrected"<<
2111 "cl0.=" << cl0 << // cluster 0 with huge Qmax
2112 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
2113 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
2114 "nclALL=" << nclALL <<
2115 "nclSector=" << nclSector <<
2117 "nclPad=" << nclPad <<
2123 }// dump the results to the debug streamer if in debug mode
2125 }//end of first loop over cluster
2126 delete rowClusterArray;
2127 }//end of loop over rows
2128 for (int i=0; i<20; i++) delete graphRes[i];
2130 delete [] indexAmpGraphs;
2132 }//end of loop over sectors
2133 }//end of loop over IROC/OROC
2134 }// end of side loop
2136 //_____________________________________________________________________________
2137 void AliTPCtracker::GetTailValue(Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
2140 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
2142 // cl0 - cluster to be modified
2143 // cl1 - source cluster ion tail of this cluster will be added to the cl0 (accroding time and pad response function)
2145 const Double_t kMinPRF = 0.5; // minimal PRF width
2146 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
2147 ionTailMax = 0.; // correction value to be added to Qmax of cl0
2149 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
2150 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
2151 Int_t sectorPad = cl1->GetDetector(); // sector number
2152 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
2153 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
2154 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
2155 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
2156 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
2157 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
2161 Double_t sumAmp1=0.;
2162 for (Int_t idelta =-2; idelta<=2;idelta++){
2163 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
2166 Double_t sumAmp0=0.;
2167 for (Int_t idelta =-2; idelta<=2;idelta++){
2168 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
2171 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
2172 Int_t padScan=2; // +-2 pad-timebin window will be scanned
2173 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
2176 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
2177 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
2178 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
2180 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
2182 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
2183 for (Int_t j=0;j<20;j++) {
2184 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
2186 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
2190 if (!graphRes[ampIndex]) continue;
2191 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
2192 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
2194 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
2197 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
2199 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
2200 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
2201 Float_t qMaxPad0 = amp0*qTot0;
2203 // Add 5 timebin range contribution around the max peak (-+2 tb window)
2204 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
2206 if (itb<0) continue;
2207 if (itb>=graphRes[ampIndex]->GetN()) continue;
2209 // calculate contribution to qTot
2210 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
2211 if (ipad1!=padcl0) {
2212 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
2214 ionTailTotal += tailCorr; // for center pad
2216 // calculate contribution to qMax
2217 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
2219 } // end of tb correction loop which is applied over 5 tb range
2221 } // end of cl0 loop
2222 } // end of cl1 loop
2226 //_____________________________________________________________________________
2227 Int_t AliTPCtracker::LoadOuterSectors() {
2228 //-----------------------------------------------------------------
2229 // This function fills outer TPC sectors with clusters.
2230 //-----------------------------------------------------------------
2231 Int_t nrows = fOuterSec->GetNRows();
2233 for (Int_t sec = 0;sec<fkNOS;sec++)
2234 for (Int_t row = 0;row<nrows;row++){
2235 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
2236 Int_t sec2 = sec+2*fkNIS;
2238 Int_t ncl = tpcrow->GetN1();
2240 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
2241 index=(((sec2<<8)+row)<<16)+ncl;
2242 tpcrow->InsertCluster(c,index);
2245 ncl = tpcrow->GetN2();
2247 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
2248 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
2249 tpcrow->InsertCluster(c,index);
2252 // write indexes for fast acces
2254 for (Int_t i=0;i<510;i++)
2255 tpcrow->SetFastCluster(i,-1);
2256 for (Int_t i=0;i<tpcrow->GetN();i++){
2257 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
2258 tpcrow->SetFastCluster(zi,i); // write index
2261 for (Int_t i=0;i<510;i++){
2262 if (tpcrow->GetFastCluster(i)<0)
2263 tpcrow->SetFastCluster(i,last);
2265 last = tpcrow->GetFastCluster(i);
2274 //_____________________________________________________________________________
2275 Int_t AliTPCtracker::LoadInnerSectors() {
2276 //-----------------------------------------------------------------
2277 // This function fills inner TPC sectors with clusters.
2278 //-----------------------------------------------------------------
2279 Int_t nrows = fInnerSec->GetNRows();
2281 for (Int_t sec = 0;sec<fkNIS;sec++)
2282 for (Int_t row = 0;row<nrows;row++){
2283 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
2286 Int_t ncl = tpcrow->GetN1();
2288 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
2289 index=(((sec<<8)+row)<<16)+ncl;
2290 tpcrow->InsertCluster(c,index);
2293 ncl = tpcrow->GetN2();
2295 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
2296 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
2297 tpcrow->InsertCluster(c,index);
2300 // write indexes for fast acces
2302 for (Int_t i=0;i<510;i++)
2303 tpcrow->SetFastCluster(i,-1);
2304 for (Int_t i=0;i<tpcrow->GetN();i++){
2305 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
2306 tpcrow->SetFastCluster(zi,i); // write index
2309 for (Int_t i=0;i<510;i++){
2310 if (tpcrow->GetFastCluster(i)<0)
2311 tpcrow->SetFastCluster(i,last);
2313 last = tpcrow->GetFastCluster(i);
2325 //_________________________________________________________________________
2326 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
2327 //--------------------------------------------------------------------
2328 // Return pointer to a given cluster
2329 //--------------------------------------------------------------------
2330 if (index<0) return 0; // no cluster
2331 Int_t sec=(index&0xff000000)>>24;
2332 Int_t row=(index&0x00ff0000)>>16;
2333 Int_t ncl=(index&0x00007fff)>>00;
2335 const AliTPCtrackerRow * tpcrow=0;
2336 TClonesArray * clrow =0;
2338 if (sec<0 || sec>=fkNIS*4) {
2339 AliWarning(Form("Wrong sector %d",sec));
2344 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
2345 if (tracksec.GetNRows()<=row) return 0;
2346 tpcrow = &(tracksec[row]);
2347 if (tpcrow==0) return 0;
2350 if (tpcrow->GetN1()<=ncl) return 0;
2351 clrow = tpcrow->GetClusters1();
2354 if (tpcrow->GetN2()<=ncl) return 0;
2355 clrow = tpcrow->GetClusters2();
2359 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
2360 if (tracksec.GetNRows()<=row) return 0;
2361 tpcrow = &(tracksec[row]);
2362 if (tpcrow==0) return 0;
2364 if (sec-2*fkNIS<fkNOS) {
2365 if (tpcrow->GetN1()<=ncl) return 0;
2366 clrow = tpcrow->GetClusters1();
2369 if (tpcrow->GetN2()<=ncl) return 0;
2370 clrow = tpcrow->GetClusters2();
2374 return (AliTPCclusterMI*)clrow->At(ncl);
2380 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
2381 //-----------------------------------------------------------------
2382 // This function tries to find a track prolongation to next pad row
2383 //-----------------------------------------------------------------
2385 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
2388 AliTPCclusterMI *cl=0;
2389 Int_t tpcindex= t.GetClusterIndex2(nr);
2391 // update current shape info every 5 pad-row
2392 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
2396 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
2398 if (tpcindex==-1) return 0; //track in dead zone
2399 if (tpcindex >= 0){ //
2400 cl = t.GetClusterPointer(nr);
2401 //if (cl==0) cl = GetClusterMI(tpcindex);
2402 if (!cl) cl = GetClusterMI(tpcindex);
2403 t.SetCurrentClusterIndex1(tpcindex);
2406 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
2407 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
2409 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
2410 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
2412 if (TMath::Abs(angle-t.GetAlpha())>0.001){
2413 Double_t rotation = angle-t.GetAlpha();
2414 t.SetRelativeSector(relativesector);
2415 if (!t.Rotate(rotation)) {
2416 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
2420 if (!t.PropagateTo(x)) {
2421 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
2425 t.SetCurrentCluster(cl);
2427 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2428 if ((tpcindex&0x8000)==0) accept =0;
2430 //if founded cluster is acceptible
2431 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
2432 t.SetErrorY2(t.GetErrorY2()+0.03);
2433 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2434 t.SetErrorY2(t.GetErrorY2()*3);
2435 t.SetErrorZ2(t.GetErrorZ2()*3);
2437 t.SetNFoundable(t.GetNFoundable()+1);
2438 UpdateTrack(&t,accept);
2441 else { // Remove old cluster from track
2442 t.SetClusterIndex(nr, -3);
2443 t.SetClusterPointer(nr, 0);
2447 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
2448 if (fIteration>1 && IsFindable(t)){
2449 // not look for new cluster during refitting
2450 t.SetNFoundable(t.GetNFoundable()+1);
2455 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
2456 if (!t.PropagateTo(x)) {
2457 if (fIteration==0) t.SetRemoval(10);
2460 Double_t y = t.GetY();
2461 if (TMath::Abs(y)>ymax){
2463 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2464 if (!t.Rotate(fSectors->GetAlpha()))
2466 } else if (y <-ymax) {
2467 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2468 if (!t.Rotate(-fSectors->GetAlpha()))
2471 if (!t.PropagateTo(x)) {
2472 if (fIteration==0) t.SetRemoval(10);
2478 Double_t z=t.GetZ();
2481 if (!IsActive(t.GetRelativeSector(),nr)) {
2483 t.SetClusterIndex2(nr,-1);
2486 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2487 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
2488 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
2490 if (!isActive || !isActive2) return 0;
2492 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2493 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
2495 Double_t roadz = 1.;
2497 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2499 t.SetClusterIndex2(nr,-1);
2505 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2506 t.SetNFoundable(t.GetNFoundable()+1);
2512 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2513 cl = krow.FindNearest2(y,z,roady,roadz,index);
2514 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2517 t.SetCurrentCluster(cl);
2519 if (fIteration==2&&cl->IsUsed(10)) return 0;
2520 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2521 if (fIteration==2&&cl->IsUsed(11)) {
2522 t.SetErrorY2(t.GetErrorY2()+0.03);
2523 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2524 t.SetErrorY2(t.GetErrorY2()*3);
2525 t.SetErrorZ2(t.GetErrorZ2()*3);
2528 if (t.fCurrentCluster->IsUsed(10)){
2533 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2539 if (accept<3) UpdateTrack(&t,accept);
2542 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2550 //_________________________________________________________________________
2551 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2553 // Get track space point by index
2554 // return false in case the cluster doesn't exist
2555 AliTPCclusterMI *cl = GetClusterMI(index);
2556 if (!cl) return kFALSE;
2557 Int_t sector = (index&0xff000000)>>24;
2558 // Int_t row = (index&0x00ff0000)>>16;
2560 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2561 xyz[0] = cl->GetX();
2562 xyz[1] = cl->GetY();
2563 xyz[2] = cl->GetZ();
2565 fkParam->AdjustCosSin(sector,cos,sin);
2566 Float_t x = cos*xyz[0]-sin*xyz[1];
2567 Float_t y = cos*xyz[1]+sin*xyz[0];
2569 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2570 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2571 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2572 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2573 cov[0] = sin*sin*sigmaY2;
2574 cov[1] = -sin*cos*sigmaY2;
2576 cov[3] = cos*cos*sigmaY2;
2579 p.SetXYZ(x,y,xyz[2],cov);
2580 AliGeomManager::ELayerID iLayer;
2582 if (sector < fkParam->GetNInnerSector()) {
2583 iLayer = AliGeomManager::kTPC1;
2587 iLayer = AliGeomManager::kTPC2;
2588 idet = sector - fkParam->GetNInnerSector();
2590 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2591 p.SetVolumeID(volid);
2597 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2598 //-----------------------------------------------------------------
2599 // This function tries to find a track prolongation to next pad row
2600 //-----------------------------------------------------------------
2601 t.SetCurrentCluster(0);
2602 t.SetCurrentClusterIndex1(-3);
2604 Double_t xt=t.GetX();
2605 Int_t row = GetRowNumber(xt)-1;
2606 Double_t ymax= GetMaxY(nr);
2608 if (row < nr) return 1; // don't prolongate if not information until now -
2609 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2611 // return 0; // not prolongate strongly inclined tracks
2613 // if (TMath::Abs(t.GetSnp())>0.95) {
2615 // return 0; // not prolongate strongly inclined tracks
2616 // }// patch 28 fev 06
2618 Double_t x= GetXrow(nr);
2620 //t.PropagateTo(x+0.02);
2621 //t.PropagateTo(x+0.01);
2622 if (!t.PropagateTo(x)){
2629 if (TMath::Abs(y)>ymax){
2631 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2632 if (!t.Rotate(fSectors->GetAlpha()))
2634 } else if (y <-ymax) {
2635 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2636 if (!t.Rotate(-fSectors->GetAlpha()))
2639 // if (!t.PropagateTo(x)){
2646 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2648 if (!IsActive(t.GetRelativeSector(),nr)) {
2650 t.SetClusterIndex2(nr,-1);
2653 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2655 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2657 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2659 t.SetClusterIndex2(nr,-1);
2665 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2666 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2672 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2673 // t.fCurrentSigmaY = GetSigmaY(&t);
2674 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2678 AliTPCclusterMI *cl=0;
2681 Double_t roady = 1.;
2682 Double_t roadz = 1.;
2686 index = t.GetClusterIndex2(nr);
2687 if ( (index >= 0) && (index&0x8000)==0){
2688 cl = t.GetClusterPointer(nr);
2689 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2690 t.SetCurrentClusterIndex1(index);
2692 t.SetCurrentCluster(cl);
2698 // if (index<0) return 0;
2699 UInt_t uindex = TMath::Abs(index);
2702 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2703 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2706 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2707 t.SetCurrentCluster(cl);
2713 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2714 //-----------------------------------------------------------------
2715 // This function tries to find a track prolongation to next pad row
2716 //-----------------------------------------------------------------
2718 //update error according neighborhoud
2720 if (t.GetCurrentCluster()) {
2722 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2724 if (t.GetCurrentCluster()->IsUsed(10)){
2729 t.SetNShared(t.GetNShared()+1);
2730 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2735 if (fIteration>0) accept = 0;
2736 if (accept<3) UpdateTrack(&t,accept);
2740 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2741 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2743 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2751 //_____________________________________________________________________________
2752 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2753 //-----------------------------------------------------------------
2754 // This function tries to find a track prolongation.
2755 //-----------------------------------------------------------------
2756 Double_t xt=t.GetX();
2758 Double_t alpha=t.GetAlpha();
2759 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2760 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2762 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2764 Int_t first = GetRowNumber(xt);
2769 for (Int_t nr= first; nr>=rf; nr-=step) {
2771 if (t.GetKinkIndexes()[0]>0){
2772 for (Int_t i=0;i<3;i++){
2773 Int_t index = t.GetKinkIndexes()[i];
2774 if (index==0) break;
2775 if (index<0) continue;
2777 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2779 printf("PROBLEM\n");
2782 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2784 AliExternalTrackParam paramd(t);
2785 kink->SetDaughter(paramd);
2786 kink->SetStatus(2,5);
2793 if (nr==80) t.UpdateReference();
2794 if (nr<fInnerSec->GetNRows())
2795 fSectors = fInnerSec;
2797 fSectors = fOuterSec;
2798 if (FollowToNext(t,nr)==0)
2811 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2812 //-----------------------------------------------------------------
2813 // This function tries to find a track prolongation.
2814 //-----------------------------------------------------------------
2816 Double_t xt=t.GetX();
2817 Double_t alpha=t.GetAlpha();
2818 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2819 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2820 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2822 Int_t first = t.GetFirstPoint();
2823 Int_t ri = GetRowNumber(xt);
2827 if (first<ri) first = ri;
2829 if (first<0) first=0;
2830 for (Int_t nr=first; nr<=rf; nr++) {
2831 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2832 if (t.GetKinkIndexes()[0]<0){
2833 for (Int_t i=0;i<3;i++){
2834 Int_t index = t.GetKinkIndexes()[i];
2835 if (index==0) break;
2836 if (index>0) continue;
2837 index = TMath::Abs(index);
2838 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2840 printf("PROBLEM\n");
2843 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2845 AliExternalTrackParam paramm(t);
2846 kink->SetMother(paramm);
2847 kink->SetStatus(2,1);
2854 if (nr<fInnerSec->GetNRows())
2855 fSectors = fInnerSec;
2857 fSectors = fOuterSec;
2868 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2870 // overlapping factor
2876 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2879 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2881 Float_t distance = TMath::Sqrt(dz2+dy2);
2882 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2885 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2886 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2891 if (firstpoint>lastpoint) {
2892 firstpoint =lastpoint;
2897 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2898 if (s1->GetClusterIndex2(i)>0) sum1++;
2899 if (s2->GetClusterIndex2(i)>0) sum2++;
2900 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2904 if (sum<5) return 0;
2906 Float_t summin = TMath::Min(sum1+1,sum2+1);
2907 Float_t ratio = (sum+1)/Float_t(summin);
2911 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2915 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2916 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2917 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2918 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2923 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2924 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2925 Int_t firstpoint = 0;
2926 Int_t lastpoint = 160;
2928 // if (firstpoint>=lastpoint-5) return;;
2930 for (Int_t i=firstpoint;i<lastpoint;i++){
2931 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2932 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2936 if (sumshared>cutN0){
2939 for (Int_t i=firstpoint;i<lastpoint;i++){
2940 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2941 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2942 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2943 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2944 if (s1->IsActive()&&s2->IsActive()){
2945 p1->SetShared(kTRUE);
2946 p2->SetShared(kTRUE);
2952 if (sumshared>cutN0){
2953 for (Int_t i=0;i<4;i++){
2954 if (s1->GetOverlapLabel(3*i)==0){
2955 s1->SetOverlapLabel(3*i, s2->GetLabel());
2956 s1->SetOverlapLabel(3*i+1,sumshared);
2957 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2961 for (Int_t i=0;i<4;i++){
2962 if (s2->GetOverlapLabel(3*i)==0){
2963 s2->SetOverlapLabel(3*i, s1->GetLabel());
2964 s2->SetOverlapLabel(3*i+1,sumshared);
2965 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2972 void AliTPCtracker::SignShared(TObjArray * arr)
2975 //sort trackss according sectors
2977 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2978 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2980 //if (pt) RotateToLocal(pt);
2984 arr->Sort(); // sorting according relative sectors
2985 arr->Expand(arr->GetEntries());
2988 Int_t nseed=arr->GetEntriesFast();
2989 for (Int_t i=0; i<nseed; i++) {
2990 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2992 for (Int_t j=0;j<12;j++){
2993 pt->SetOverlapLabel(j,0);
2996 for (Int_t i=0; i<nseed; i++) {
2997 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2999 if (pt->GetRemoval()>10) continue;
3000 for (Int_t j=i+1; j<nseed; j++){
3001 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
3002 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
3004 if (pt2->GetRemoval()<=10) {
3005 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
3013 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
3016 //sort tracks in array according mode criteria
3017 Int_t nseed = arr->GetEntriesFast();
3018 for (Int_t i=0; i<nseed; i++) {
3019 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3030 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
3033 // Loop over all tracks and remove overlaped tracks (with lower quality)
3035 // 1. Unsign clusters
3036 // 2. Sort tracks according quality
3037 // Quality is defined by the number of cluster between first and last points
3039 // 3. Loop over tracks - decreasing quality order
3040 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
3041 // b.) remove - If the minimal number of clusters less than minimal and not ITS
3042 // c.) if track accepted - sign clusters
3044 //Called in - AliTPCtracker::Clusters2Tracks()
3045 // - AliTPCtracker::PropagateBack()
3046 // - AliTPCtracker::RefitInward()
3049 // factor1 - factor for constrained
3050 // factor2 - for non constrained tracks
3051 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
3055 Int_t nseed = arr->GetEntriesFast();
3056 Float_t * quality = new Float_t[nseed];
3057 Int_t * indexes = new Int_t[nseed];
3061 for (Int_t i=0; i<nseed; i++) {
3062 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3067 pt->UpdatePoints(); //select first last max dens points
3068 Float_t * points = pt->GetPoints();
3069 if (points[3]<0.8) quality[i] =-1;
3070 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
3071 //prefer high momenta tracks if overlaps
3072 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
3074 TMath::Sort(nseed,quality,indexes);
3077 for (Int_t itrack=0; itrack<nseed; itrack++) {
3078 Int_t trackindex = indexes[itrack];
3079 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
3082 if (quality[trackindex]<0){
3083 MarkSeedFree( arr->RemoveAt(trackindex) );
3088 Int_t first = Int_t(pt->GetPoints()[0]);
3089 Int_t last = Int_t(pt->GetPoints()[2]);
3090 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
3092 Int_t found,foundable,shared;
3093 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
3094 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
3095 Bool_t itsgold =kFALSE;
3098 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
3102 if (Float_t(shared+1)/Float_t(found+1)>factor){
3103 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
3104 if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveUsed)>0){ // flag:stream information about TPC tracks which were descarded (double track removal)
3105 TTreeSRedirector &cstream = *fDebugStreamer;
3106 cstream<<"RemoveUsed"<<
3107 "iter="<<fIteration<<
3111 MarkSeedFree( arr->RemoveAt(trackindex) );
3114 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
3115 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
3116 if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveShort)>0){ // flag:stream information about TPC tracks which were discarded (short track removal)
3117 TTreeSRedirector &cstream = *fDebugStreamer;
3118 cstream<<"RemoveShort"<<
3119 "iter="<<fIteration<<
3123 MarkSeedFree( arr->RemoveAt(trackindex) );
3129 //if (sharedfactor>0.4) continue;
3130 if (pt->GetKinkIndexes()[0]>0) continue;
3131 //Remove tracks with undefined properties - seems
3132 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
3134 for (Int_t i=first; i<last; i++) {
3135 Int_t index=pt->GetClusterIndex2(i);
3136 // if (index<0 || index&0x8000 ) continue;
3137 if (index<0 || index&0x8000 ) continue;
3138 AliTPCclusterMI *c= pt->GetClusterPointer(i);
3145 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
3151 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
3154 // Dump clusters after reco
3155 // signed and unsigned cluster can be visualized
3156 // 1. Unsign all cluster
3157 // 2. Sign all used clusters
3160 Int_t nseed = trackArray->GetEntries();
3161 for (Int_t i=0; i<nseed; i++){
3162 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
3166 Bool_t isKink=pt->GetKinkIndex(0)!=0;
3167 for (Int_t j=0; j<160; ++j) {
3168 Int_t index=pt->GetClusterIndex2(j);
3169 if (index<0) continue;
3170 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3172 if (isKink) c->Use(100); // kink
3173 c->Use(10); // by default usage 10
3177 Int_t eventNr = fEvent->GetEventNumberInFile();
3179 for (Int_t sec=0;sec<fkNIS;sec++){
3180 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
3181 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
3182 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
3183 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
3184 Float_t gx[3]; cl->GetGlobalXYZ(gx);
3185 (*fDebugStreamer)<<"clDump"<<
3186 "eventNr="<<eventNr<<
3194 cla = fInnerSec[sec][row].GetClusters2();
3195 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
3196 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
3197 Float_t gx[3]; cl->GetGlobalXYZ(gx);
3198 (*fDebugStreamer)<<"clDump"<<
3199 "eventNr="<<eventNr<<
3210 for (Int_t sec=0;sec<fkNOS;sec++){
3211 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
3212 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
3213 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
3215 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
3216 cl->GetGlobalXYZ(gx);
3217 (*fDebugStreamer)<<"clDump"<<
3218 "eventNr="<<eventNr<<
3226 cla = fOuterSec[sec][row].GetClusters2();
3227 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
3229 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
3230 cl->GetGlobalXYZ(gx);
3231 (*fDebugStreamer)<<"clDump"<<
3232 "eventNr="<<eventNr<<
3244 void AliTPCtracker::UnsignClusters()
3247 // loop over all clusters and unsign them
3250 for (Int_t sec=0;sec<fkNIS;sec++){
3251 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
3252 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
3253 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
3254 // if (cl[icl].IsUsed(10))
3255 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3256 cla = fInnerSec[sec][row].GetClusters2();
3257 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
3258 //if (cl[icl].IsUsed(10))
3259 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3263 for (Int_t sec=0;sec<fkNOS;sec++){
3264 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
3265 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
3266 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
3267 //if (cl[icl].IsUsed(10))
3268 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3269 cla = fOuterSec[sec][row].GetClusters2();
3270 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
3271 //if (cl[icl].IsUsed(10))
3272 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3280 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
3283 //sign clusters to be "used"
3285 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
3286 // loop over "primaries"
3300 Int_t nseed = arr->GetEntriesFast();
3301 for (Int_t i=0; i<nseed; i++) {
3302 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3306 if (!(pt->IsActive())) continue;
3307 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
3308 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
3310 sumdens2+= dens*dens;
3311 sumn += pt->GetNumberOfClusters();
3312 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
3313 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
3316 sumchi2 +=chi2*chi2;
3321 Float_t mdensity = 0.9;
3322 Float_t meann = 130;
3323 Float_t meanchi = 1;
3324 Float_t sdensity = 0.1;
3325 Float_t smeann = 10;
3326 Float_t smeanchi =0.4;
3330 mdensity = sumdens/sum;
3332 meanchi = sumchi/sum;
3334 sdensity = sumdens2/sum-mdensity*mdensity;
3336 sdensity = TMath::Sqrt(sdensity);
3340 smeann = sumn2/sum-meann*meann;
3342 smeann = TMath::Sqrt(smeann);
3346 smeanchi = sumchi2/sum - meanchi*meanchi;
3348 smeanchi = TMath::Sqrt(smeanchi);
3354 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
3356 for (Int_t i=0; i<nseed; i++) {
3357 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3361 if (pt->GetBSigned()) continue;
3362 if (pt->GetBConstrain()) continue;
3363 //if (!(pt->IsActive())) continue;
3365 Int_t found,foundable,shared;
3366 pt->GetClusterStatistic(0,160,found, foundable,shared);
3367 if (shared/float(found)>0.3) {
3368 if (shared/float(found)>0.9 ){
3369 //MarkSeedFree( arr->RemoveAt(i) );
3374 Bool_t isok =kFALSE;
3375 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
3377 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
3379 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
3381 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
3385 for (Int_t j=0; j<160; ++j) {
3386 Int_t index=pt->GetClusterIndex2(j);
3387 if (index<0) continue;
3388 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3390 //if (!(c->IsUsed(10))) c->Use();
3397 Double_t maxchi = meanchi+2.*smeanchi;
3399 for (Int_t i=0; i<nseed; i++) {
3400 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3404 //if (!(pt->IsActive())) continue;
3405 if (pt->GetBSigned()) continue;
3406 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
3407 if (chi>maxchi) continue;
3410 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
3412 //sign only tracks with enoug big density at the beginning
3414 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
3417 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
3418 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
3420 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
3421 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
3424 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
3425 //Int_t noc=pt->GetNumberOfClusters();
3426 pt->SetBSigned(kTRUE);
3427 for (Int_t j=0; j<160; ++j) {
3429 Int_t index=pt->GetClusterIndex2(j);
3430 if (index<0) continue;
3431 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3433 // if (!(c->IsUsed(10))) c->Use();
3438 // gLastCheck = nseed;
3447 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
3450 // back propagation of ESD tracks
3453 if (!event) return 0;
3454 const Int_t kMaxFriendTracks=2000;
3457 // extract correction object for multiplicity dependence of dEdx
3458 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
3460 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
3462 AliFatal("Tranformations not in RefitInward");
3465 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
3466 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
3467 Int_t nContribut = event->GetNumberOfTracks();
3468 TGraphErrors * graphMultDependenceDeDx = 0x0;
3469 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
3470 if (recoParam->GetUseTotCharge()) {
3471 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
3473 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
3479 //PrepareForProlongation(fSeeds,1);
3480 PropagateForward2(fSeeds);
3481 RemoveUsed2(fSeeds,0.4,0.4,20);
3483 Int_t entriesSeed=fSeeds->GetEntries();
3484 TObjArray arraySeed(entriesSeed);
3485 for (Int_t i=0;i<entriesSeed;i++) {
3486 arraySeed.AddAt(fSeeds->At(i),i);
3488 SignShared(&arraySeed);
3489 // FindCurling(fSeeds, event,2); // find multi found tracks
3490 FindSplitted(fSeeds, event,2); // find multi found tracks
3491 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) FindMultiMC(fSeeds, fEvent,2); // flag: stream MC infomation about the multiple find track (ONLY for MC data)
3494 Int_t nseed = fSeeds->GetEntriesFast();
3495 for (Int_t i=0;i<nseed;i++){
3496 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3497 if (!seed) continue;
3498 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
3499 AliESDtrack *esd=event->GetTrack(i);
3501 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3502 AliExternalTrackParam paramIn;
3503 AliExternalTrackParam paramOut;
3504 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3505 if ((AliTPCReconstructor::StreamLevel() & kStreamRecoverIn)>0) { // flag: stream track information for track failing in RefitInward function and recovered back
3506 (*fDebugStreamer)<<"RecoverIn"<<
3510 "pout.="<<¶mOut<<
3515 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3516 seed->SetNumberOfClusters(ncl);
3520 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3521 seed->UpdatePoints();
3522 AddCovariance(seed);
3523 MakeESDBitmaps(seed, esd);
3524 seed->CookdEdx(0.02,0.6);
3525 CookLabel(seed,0.1); //For comparison only
3527 if (((AliTPCReconstructor::StreamLevel()&kStreamRefitInward)>0) && seed!=0) {
3528 TTreeSRedirector &cstream = *fDebugStreamer;
3529 cstream<<"RefitInward"<< // flag: stream track information in RefitInward function (after tracking Iteration 2)
3535 if (seed->GetNumberOfClusters()>15){
3536 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3537 esd->SetTPCPoints(seed->GetPoints());
3538 esd->SetTPCPointsF(seed->GetNFoundable());
3539 Int_t ndedx = seed->GetNCDEDX(0);
3540 Float_t sdedx = seed->GetSDEDX(0);
3541 Float_t dedx = seed->GetdEdx();
3542 // apply mutliplicity dependent dEdx correction if available
3543 if (graphMultDependenceDeDx) {
3544 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3545 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3547 esd->SetTPCsignal(dedx, sdedx, ndedx);
3549 // fill new dEdx information
3551 Double32_t signal[4];
3552 Double32_t signalMax[4];
3556 for(Int_t iarr=0;iarr<3;iarr++) {
3557 signal[iarr] = seed->GetDEDXregion(iarr+1);
3558 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3559 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3560 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3562 signal[3] = seed->GetDEDXregion(4);
3563 signalMax[3] = seed->GetDEDXregion(8);
3566 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3567 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3568 infoTpcPid->SetTPCSignalsQmax(signalMax);
3569 esd->SetTPCdEdxInfo(infoTpcPid);
3571 // add seed to the esd track in Calib level
3573 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3574 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3575 // RS: this is the only place where the seed is created not in the pool,
3576 // since it should belong to ESDevent
3577 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3578 esd->AddCalibObject(seedCopy);
3583 //printf("problem\n");
3586 //FindKinks(fSeeds,event);
3587 if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0) DumpClusters(2,fSeeds); // dump clusters at the end of process (signed with useage flags)
3588 Info("RefitInward","Number of refitted tracks %d",ntracks);
3590 AliCosmicTracker::FindCosmic(event, kTRUE);
3592 FillClusterOccupancyInfo();
3598 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3601 // back propagation of ESD tracks
3603 if (!event) return 0;
3608 PropagateBack(fSeeds);
3609 RemoveUsed2(fSeeds,0.4,0.4,20);
3610 //FindCurling(fSeeds, fEvent,1);
3611 FindSplitted(fSeeds, event,1); // find multi found tracks
3612 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3615 Int_t nseed = fSeeds->GetEntriesFast();
3617 for (Int_t i=0;i<nseed;i++){
3618 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3619 if (!seed) continue;
3620 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3621 seed->UpdatePoints();
3622 AddCovariance(seed);
3623 AliESDtrack *esd=event->GetTrack(i);
3624 if (!esd) continue; //never happen
3625 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3626 AliExternalTrackParam paramIn;
3627 AliExternalTrackParam paramOut;
3628 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3629 if ((AliTPCReconstructor::StreamLevel()&kStreamRecoverBack)>0) { // flag: stream track information for track faling PropagateBack function and recovered back (RefitTrack)
3630 (*fDebugStreamer)<<"RecoverBack"<<
3634 "pout.="<<¶mOut<<
3639 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3640 seed->SetNumberOfClusters(ncl);
3643 seed->CookdEdx(0.02,0.6);
3644 CookLabel(seed,0.1); //For comparison only
3645 if (seed->GetNumberOfClusters()>15){
3646 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3647 esd->SetTPCPoints(seed->GetPoints());
3648 esd->SetTPCPointsF(seed->GetNFoundable());
3649 Int_t ndedx = seed->GetNCDEDX(0);
3650 Float_t sdedx = seed->GetSDEDX(0);
3651 Float_t dedx = seed->GetdEdx();
3652 esd->SetTPCsignal(dedx, sdedx, ndedx);
3654 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3655 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3656 if (((AliTPCReconstructor::StreamLevel()&kStreamCPropagateBack)>0) && esd) {
3657 (*fDebugStreamer)<<"PropagateBack"<< // flag: stream track information in PropagateBack function (after tracking Iteration 1)
3660 "EventNrInFile="<<eventnumber<<
3665 if (AliTPCReconstructor::StreamLevel()&kStreamClDump) DumpClusters(1,fSeeds); // flag:stream clusters at the end of process (signed with usage flag)
3666 //FindKinks(fSeeds,event);
3667 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3675 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3678 // Post process events
3680 if (!event) return 0;
3683 // Set TPC event status
3686 // event affected by HV dip
3688 if(IsTPCHVDipEvent(event)) {
3689 event->ResetDetectorStatus(AliDAQ::kTPC);
3692 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3698 void AliTPCtracker::DeleteSeeds()
3707 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3710 //read seeds from the event
3712 Int_t nentr=event->GetNumberOfTracks();
3714 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3719 fSeeds = new TObjArray(nentr);
3723 for (Int_t i=0; i<nentr; i++) {
3724 AliESDtrack *esd=event->GetTrack(i);
3725 ULong_t status=esd->GetStatus();
3726 if (!(status&AliESDtrack::kTPCin)) continue;
3727 AliTPCtrack t(*esd);
3728 t.SetNumberOfClusters(0);
3729 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3730 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3731 seed->SetPoolID(fLastSeedID);
3732 seed->SetUniqueID(esd->GetID());
3733 AddCovariance(seed); //add systematic ucertainty
3734 for (Int_t ikink=0;ikink<3;ikink++) {
3735 Int_t index = esd->GetKinkIndex(ikink);
3736 seed->GetKinkIndexes()[ikink] = index;
3737 if (index==0) continue;
3738 index = TMath::Abs(index);
3739 AliESDkink * kink = fEvent->GetKink(index-1);
3740 if (kink&&esd->GetKinkIndex(ikink)<0){
3741 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3742 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3744 if (kink&&esd->GetKinkIndex(ikink)>0){
3745 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3746 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3750 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3751 //RS if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3752 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3753 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3754 // fSeeds->AddAt(0,i);
3755 // MarkSeedFree( seed );
3761 // rotate to the local coordinate system
3763 fSectors=fInnerSec; fN=fkNIS;
3764 Double_t alpha=seed->GetAlpha();
3765 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3766 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3767 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3768 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3769 alpha-=seed->GetAlpha();
3770 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3771 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3772 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3773 AliWarning(Form("Rotating track over %f",alpha));
3774 if (!seed->Rotate(alpha)) {
3775 MarkSeedFree( seed );
3781 if (esd->GetKinkIndex(0)<=0){
3782 for (Int_t irow=0;irow<160;irow++){
3783 Int_t index = seed->GetClusterIndex2(irow);
3786 AliTPCclusterMI * cl = GetClusterMI(index);
3787 seed->SetClusterPointer(irow,cl);
3789 if ((index & 0x8000)==0){
3790 cl->Use(10); // accepted cluster
3792 cl->Use(6); // close cluster not accepted
3795 Info("ReadSeeds","Not found cluster");
3800 fSeeds->AddAt(seed,i);
3806 //_____________________________________________________________________________
3807 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3808 Float_t deltay, Int_t ddsec) {
3809 //-----------------------------------------------------------------
3810 // This function creates track seeds.
3811 // SEEDING WITH VERTEX CONSTRAIN
3812 //-----------------------------------------------------------------
3813 // cuts[0] - fP4 cut
3814 // cuts[1] - tan(phi) cut
3815 // cuts[2] - zvertex cut
3816 // cuts[3] - fP3 cut
3824 Double_t x[5], c[15];
3825 // Int_t di = i1-i2;
3827 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3828 seed->SetPoolID(fLastSeedID);
3829 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3830 Double_t cs=cos(alpha), sn=sin(alpha);
3832 // Double_t x1 =fOuterSec->GetX(i1);
3833 //Double_t xx2=fOuterSec->GetX(i2);
3835 Double_t x1 =GetXrow(i1);
3836 Double_t xx2=GetXrow(i2);
3838 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3840 Int_t imiddle = (i2+i1)/2; //middle pad row index
3841 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3842 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3846 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3847 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3848 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3851 // change cut on curvature if it can't reach this layer
3852 // maximal curvature set to reach it
3853 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3854 if (dvertexmax*0.5*cuts[0]>0.85){
3855 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3857 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3860 if (deltay>0) ddsec = 0;
3861 // loop over clusters
3862 for (Int_t is=0; is < kr1; is++) {
3864 if (kr1[is]->IsUsed(10)) continue;
3865 if (kr1[is]->IsDisabled()) {
3869 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3870 //if (TMath::Abs(y1)>ymax) continue;
3872 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3874 // find possible directions
3875 Float_t anglez = (z1-z3)/(x1-x3);
3876 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3879 //find rotation angles relative to line given by vertex and point 1
3880 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3881 Double_t dvertex = TMath::Sqrt(dvertex2);
3882 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3883 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3886 // loop over 2 sectors
3892 Double_t dddz1=0; // direction of delta inclination in z axis
3899 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3900 Int_t sec2 = sec + dsec;
3902 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3903 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3904 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3905 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3906 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3907 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3909 // rotation angles to p1-p3
3910 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3911 Double_t x2, y2, z2;
3913 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3916 Double_t dxx0 = (xx2-x3)*cs13r;
3917 Double_t dyy0 = (xx2-x3)*sn13r;
3918 for (Int_t js=index1; js < index2; js++) {
3919 const AliTPCclusterMI *kcl = kr2[js];
3920 if (kcl->IsUsed(10)) continue;
3921 if (kcl->IsDisabled()) {
3925 //calcutate parameters
3927 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3929 if (TMath::Abs(yy0)<0.000001) continue;
3930 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3931 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3932 Double_t r02 = (0.25+y0*y0)*dvertex2;
3933 //curvature (radius) cut
3934 if (r02<r2min) continue;
3938 Double_t c0 = 1/TMath::Sqrt(r02);
3942 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3943 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3944 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3945 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3948 Double_t z0 = kcl->GetZ();
3949 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3950 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3953 Double_t dip = (z1-z0)*c0/dfi1;
3954 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3965 x2= xx2*cs-y2*sn*dsec;
3966 y2=+xx2*sn*dsec+y2*cs;
3976 // do we have cluster at the middle ?
3978 GetProlongation(x1,xm,x,ym,zm);
3980 AliTPCclusterMI * cm=0;
3981 if (TMath::Abs(ym)-ymaxm<0){
3982 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3983 if ((!cm) || (cm->IsUsed(10))) {
3988 // rotate y1 to system 0
3989 // get state vector in rotated system
3990 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3991 Double_t xr2 = x0*cs+yr1*sn*dsec;
3992 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3994 GetProlongation(xx2,xm,xr,ym,zm);
3995 if (TMath::Abs(ym)-ymaxm<0){
3996 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3997 if ((!cm) || (cm->IsUsed(10))) {
4004 // Double_t dym = 0;
4005 // Double_t dzm = 0;
4007 // dym = ym - cm->GetY();
4008 // dzm = zm - cm->GetZ();
4015 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
4016 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
4017 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
4018 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4019 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
4021 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4022 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4023 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4024 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4025 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4026 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4028 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4029 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4030 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4031 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4035 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4036 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4037 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4038 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4039 c[13]=f30*sy1*f40+f32*sy2*f42;
4040 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4042 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4044 UInt_t index=kr1.GetIndex(is);
4045 if (seed) {MarkSeedFree(seed); seed = 0;}
4046 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
4047 seed->SetPoolID(fLastSeedID);
4048 track->SetIsSeeding(kTRUE);
4049 track->SetSeed1(i1);
4050 track->SetSeed2(i2);
4051 track->SetSeedType(3);
4055 FollowProlongation(*track, (i1+i2)/2,1);
4056 Int_t foundable,found,shared;
4057 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
4058 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
4059 MarkSeedFree(seed); seed = 0;
4065 FollowProlongation(*track, i2,1);
4069 track->SetBConstrain(1);
4070 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
4071 track->SetLastPoint(i1); // first cluster in track position
4072 track->SetFirstPoint(track->GetLastPoint());
4074 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4075 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4076 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
4077 MarkSeedFree(seed); seed = 0;
4081 // Z VERTEX CONDITION
4082 Double_t zv, bz=GetBz();
4083 if ( !track->GetZAt(0.,bz,zv) ) continue;
4084 if (TMath::Abs(zv-z3)>cuts[2]) {
4085 FollowProlongation(*track, TMath::Max(i2-20,0));
4086 if ( !track->GetZAt(0.,bz,zv) ) continue;
4087 if (TMath::Abs(zv-z3)>cuts[2]){
4088 FollowProlongation(*track, TMath::Max(i2-40,0));
4089 if ( !track->GetZAt(0.,bz,zv) ) continue;
4090 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
4091 // make seed without constrain
4092 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
4093 FollowProlongation(*track2, i2,1);
4094 track2->SetBConstrain(kFALSE);
4095 track2->SetSeedType(1);
4096 arr->AddLast(track2);
4097 MarkSeedFree( seed ); seed = 0;
4101 MarkSeedFree( seed ); seed = 0;
4108 track->SetSeedType(0);
4109 arr->AddLast(track); // note, track is seed, don't free the seed
4110 seed = new( NextFreeSeed() ) AliTPCseed;
4111 seed->SetPoolID(fLastSeedID);
4113 // don't consider other combinations
4114 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
4120 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
4122 if (seed) MarkSeedFree( seed );
4126 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
4131 //-----------------------------------------------------------------
4132 // This function creates track seeds.
4133 //-----------------------------------------------------------------
4134 // cuts[0] - fP4 cut
4135 // cuts[1] - tan(phi) cut
4136 // cuts[2] - zvertex cut
4137 // cuts[3] - fP3 cut
4147 Double_t x[5], c[15];
4149 // make temporary seed
4150 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4151 seed->SetPoolID(fLastSeedID);
4152 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4153 // Double_t cs=cos(alpha), sn=sin(alpha);
4158 Double_t x1 = GetXrow(i1-1);
4159 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
4160 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
4162 Double_t x1p = GetXrow(i1);
4163 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
4165 Double_t x1m = GetXrow(i1-2);
4166 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
4169 //last 3 padrow for seeding
4170 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
4171 Double_t x3 = GetXrow(i1-7);
4172 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
4174 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
4175 Double_t x3p = GetXrow(i1-6);
4177 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
4178 Double_t x3m = GetXrow(i1-8);
4183 Int_t im = i1-4; //middle pad row index
4184 Double_t xm = GetXrow(im); // radius of middle pad-row
4185 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
4186 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
4189 Double_t deltax = x1-x3;
4190 Double_t dymax = deltax*cuts[1];
4191 Double_t dzmax = deltax*cuts[3];
4193 // loop over clusters
4194 for (Int_t is=0; is < kr1; is++) {
4196 if (kr1[is]->IsUsed(10)) continue;
4197 if (kr1[is]->IsDisabled()) {
4201 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
4203 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
4205 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
4206 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
4212 for (Int_t js=index1; js < index2; js++) {
4213 const AliTPCclusterMI *kcl = kr3[js];
4214 if (kcl->IsDisabled()) {
4218 if (kcl->IsUsed(10)) continue;
4220 // apply angular cuts
4221 if (TMath::Abs(y1-y3)>dymax) continue;
4224 if (TMath::Abs(z1-z3)>dzmax) continue;
4226 Double_t angley = (y1-y3)/(x1-x3);
4227 Double_t anglez = (z1-z3)/(x1-x3);
4229 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
4230 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
4232 Double_t yyym = angley*(xm-x1)+y1;
4233 Double_t zzzm = anglez*(xm-x1)+z1;
4235 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
4237 if (kcm->IsUsed(10)) continue;
4238 if (kcm->IsDisabled()) {
4242 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
4243 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
4250 // look around first
4251 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
4257 if (kc1m->IsUsed(10)) used++;
4259 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
4265 if (kc1p->IsUsed(10)) used++;
4267 if (used>1) continue;
4268 if (found<1) continue;
4272 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
4278 if (kc3m->IsUsed(10)) used++;
4282 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
4288 if (kc3p->IsUsed(10)) used++;
4292 if (used>1) continue;
4293 if (found<3) continue;
4303 x[4]=F1(x1,y1,x2,y2,x3,y3);
4304 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
4307 x[2]=F2(x1,y1,x2,y2,x3,y3);
4310 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
4311 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4315 Double_t sy1=0.1, sz1=0.1;
4316 Double_t sy2=0.1, sz2=0.1;
4317 Double_t sy3=0.1, sy=0.1, sz=0.1;
4319 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4320 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4321 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4322 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4323 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4324 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4326 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4327 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4328 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4329 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4333 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4334 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4335 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4336 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4337 c[13]=f30*sy1*f40+f32*sy2*f42;
4338 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4340 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4342 index=kr1.GetIndex(is);
4343 if (seed) {MarkSeedFree( seed ); seed = 0;}
4344 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
4345 seed->SetPoolID(fLastSeedID);
4347 track->SetIsSeeding(kTRUE);
4350 FollowProlongation(*track, i1-7,1);
4351 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
4352 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
4353 MarkSeedFree( seed ); seed = 0;
4359 FollowProlongation(*track, i2,1);
4360 track->SetBConstrain(0);
4361 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
4362 track->SetFirstPoint(track->GetLastPoint());
4364 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4365 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
4366 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
4367 MarkSeedFree( seed ); seed = 0;
4372 FollowProlongation(*track, TMath::Max(i2-10,0),1);
4373 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
4374 FollowProlongation(*track2, i2,1);
4375 track2->SetBConstrain(kFALSE);
4376 track2->SetSeedType(4);
4377 arr->AddLast(track2);
4378 MarkSeedFree( seed ); seed = 0;
4382 //arr->AddLast(track);
4383 //seed = new AliTPCseed;
4389 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);
4391 if (seed) MarkSeedFree(seed);
4395 //_____________________________________________________________________________
4396 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
4397 Float_t deltay, Bool_t /*bconstrain*/) {
4398 //-----------------------------------------------------------------
4399 // This function creates track seeds - without vertex constraint
4400 //-----------------------------------------------------------------
4401 // cuts[0] - fP4 cut - not applied
4402 // cuts[1] - tan(phi) cut
4403 // cuts[2] - zvertex cut - not applied
4404 // cuts[3] - fP3 cut
4414 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4415 // Double_t cs=cos(alpha), sn=sin(alpha);
4416 Int_t row0 = (i1+i2)/2;
4417 Int_t drow = (i1-i2)/2;
4418 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
4419 AliTPCtrackerRow * kr=0;
4421 AliTPCpolyTrack polytrack;
4422 Int_t nclusters=fSectors[sec][row0];
4423 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4424 seed->SetPoolID(fLastSeedID);
4429 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
4431 Int_t nfoundable =0;
4432 for (Int_t iter =1; iter<2; iter++){ //iterations
4433 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
4434 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
4435 const AliTPCclusterMI * cl= kr0[is];
4436 if (cl->IsDisabled()) {
4440 if (cl->IsUsed(10)) {
4446 Double_t x = kr0.GetX();
4447 // Initialization of the polytrack
4452 Double_t y0= cl->GetY();
4453 Double_t z0= cl->GetZ();
4457 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
4458 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
4460 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
4461 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
4462 polytrack.AddPoint(x,y0,z0,erry, errz);
4465 if (cl->IsUsed(10)) sumused++;
4468 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
4469 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
4472 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
4473 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
4474 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
4475 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
4476 if (cl1->IsUsed(10)) sumused++;
4477 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
4481 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
4483 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
4484 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
4485 if (cl2->IsUsed(10)) sumused++;
4486 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
4489 if (sumused>0) continue;
4491 polytrack.UpdateParameters();
4497 nfoundable = polytrack.GetN();
4498 nfound = nfoundable;
4500 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
4501 Float_t maxdist = 0.8*(1.+3./(ddrow));
4502 for (Int_t delta = -1;delta<=1;delta+=2){
4503 Int_t row = row0+ddrow*delta;
4504 kr = &(fSectors[sec][row]);
4505 Double_t xn = kr->GetX();
4506 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
4507 polytrack.GetFitPoint(xn,yn,zn);
4508 if (TMath::Abs(yn)>ymax1) continue;
4510 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
4512 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
4515 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4516 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4517 if (cln->IsUsed(10)) {
4518 // printf("used\n");
4526 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4531 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4532 polytrack.UpdateParameters();
4535 if ( (sumused>3) || (sumused>0.5*nfound)) {
4536 //printf("sumused %d\n",sumused);
4541 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4542 AliTPCpolyTrack track2;
4544 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4545 if (track2.GetN()<0.5*nfoundable) continue;
4548 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4550 // test seed with and without constrain
4551 for (Int_t constrain=0; constrain<=0;constrain++){
4552 // add polytrack candidate
4554 Double_t x[5], c[15];
4555 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4556 track2.GetBoundaries(x3,x1);
4558 track2.GetFitPoint(x1,y1,z1);
4559 track2.GetFitPoint(x2,y2,z2);
4560 track2.GetFitPoint(x3,y3,z3);
4562 //is track pointing to the vertex ?
4565 polytrack.GetFitPoint(x0,y0,z0);
4578 x[4]=F1(x1,y1,x2,y2,x3,y3);
4580 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4581 x[2]=F2(x1,y1,x2,y2,x3,y3);
4583 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4584 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4585 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4586 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4589 Double_t sy =0.1, sz =0.1;
4590 Double_t sy1=0.02, sz1=0.02;
4591 Double_t sy2=0.02, sz2=0.02;
4595 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4598 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4599 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4600 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4601 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4602 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4603 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4605 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4606 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4607 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4608 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4613 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4614 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4615 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4616 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4617 c[13]=f30*sy1*f40+f32*sy2*f42;
4618 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4620 //Int_t row1 = fSectors->GetRowNumber(x1);
4621 Int_t row1 = GetRowNumber(x1);
4625 if (seed) {MarkSeedFree( seed ); seed = 0;}
4626 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4627 seed->SetPoolID(fLastSeedID);
4628 track->SetIsSeeding(kTRUE);
4629 Int_t rc=FollowProlongation(*track, i2);
4630 if (constrain) track->SetBConstrain(1);
4632 track->SetBConstrain(0);
4633 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4634 track->SetFirstPoint(track->GetLastPoint());
4636 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4637 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4638 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4639 MarkSeedFree( seed ); seed = 0;
4642 arr->AddLast(track); // track IS seed, don't free seed
4643 seed = new( NextFreeSeed() ) AliTPCseed;
4644 seed->SetPoolID(fLastSeedID);
4648 } // if accepted seed
4651 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4653 if (seed) MarkSeedFree( seed );
4657 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4661 //reseed using track points
4662 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4663 Int_t p1 = int(r1*track->GetNumberOfClusters());
4664 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4666 Double_t x0[3],x1[3],x2[3];
4667 for (Int_t i=0;i<3;i++){
4673 // find track position at given ratio of the length
4674 Int_t sec0=0, sec1=0, sec2=0;
4677 for (Int_t i=0;i<160;i++){
4678 if (track->GetClusterPointer(i)){
4680 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4681 if ( (index<p0) || x0[0]<0 ){
4682 if (trpoint->GetX()>1){
4683 clindex = track->GetClusterIndex2(i);
4685 x0[0] = trpoint->GetX();
4686 x0[1] = trpoint->GetY();
4687 x0[2] = trpoint->GetZ();
4688 sec0 = ((clindex&0xff000000)>>24)%18;
4693 if ( (index<p1) &&(trpoint->GetX()>1)){
4694 clindex = track->GetClusterIndex2(i);
4696 x1[0] = trpoint->GetX();
4697 x1[1] = trpoint->GetY();
4698 x1[2] = trpoint->GetZ();
4699 sec1 = ((clindex&0xff000000)>>24)%18;
4702 if ( (index<p2) &&(trpoint->GetX()>1)){
4703 clindex = track->GetClusterIndex2(i);
4705 x2[0] = trpoint->GetX();
4706 x2[1] = trpoint->GetY();
4707 x2[2] = trpoint->GetZ();
4708 sec2 = ((clindex&0xff000000)>>24)%18;
4715 Double_t alpha, cs,sn, xx2,yy2;
4717 alpha = (sec1-sec2)*fSectors->GetAlpha();
4718 cs = TMath::Cos(alpha);
4719 sn = TMath::Sin(alpha);
4720 xx2= x1[0]*cs-x1[1]*sn;
4721 yy2= x1[0]*sn+x1[1]*cs;
4725 alpha = (sec0-sec2)*fSectors->GetAlpha();
4726 cs = TMath::Cos(alpha);
4727 sn = TMath::Sin(alpha);
4728 xx2= x0[0]*cs-x0[1]*sn;
4729 yy2= x0[0]*sn+x0[1]*cs;
4735 Double_t x[5],c[15];
4739 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4740 // if (x[4]>1) return 0;
4741 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4742 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4743 //if (TMath::Abs(x[3]) > 2.2) return 0;
4744 //if (TMath::Abs(x[2]) > 1.99) return 0;
4746 Double_t sy =0.1, sz =0.1;
4748 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4749 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4750 Double_t sy3=0.01+track->GetSigmaY2();
4752 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4753 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4754 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4755 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4756 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4757 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4759 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4760 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4761 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4762 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4767 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4768 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4769 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4770 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4771 c[13]=f30*sy1*f40+f32*sy2*f42;
4772 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4774 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4775 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4776 seed->SetPoolID(fLastSeedID);
4777 // Double_t y0,z0,y1,z1, y2,z2;
4778 //seed->GetProlongation(x0[0],y0,z0);
4779 // seed->GetProlongation(x1[0],y1,z1);
4780 //seed->GetProlongation(x2[0],y2,z2);
4782 seed->SetLastPoint(pp2);
4783 seed->SetFirstPoint(pp2);
4790 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4794 //reseed using founded clusters
4796 // Find the number of clusters
4797 Int_t nclusters = 0;
4798 for (Int_t irow=0;irow<160;irow++){
4799 if (track->GetClusterIndex(irow)>0) nclusters++;
4803 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4804 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4805 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4808 Double_t xyz[3][3]={{0}};
4809 Int_t row[3]={0},sec[3]={0,0,0};
4811 // find track row position at given ratio of the length
4813 for (Int_t irow=0;irow<160;irow++){
4814 if (track->GetClusterIndex2(irow)<0) continue;
4816 for (Int_t ipoint=0;ipoint<3;ipoint++){
4817 if (index<=ipos[ipoint]) row[ipoint] = irow;
4821 //Get cluster and sector position
4822 for (Int_t ipoint=0;ipoint<3;ipoint++){
4823 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4824 AliTPCclusterMI * cl = GetClusterMI(clindex);
4827 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4830 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4831 xyz[ipoint][0] = GetXrow(row[ipoint]);
4832 xyz[ipoint][1] = cl->GetY();
4833 xyz[ipoint][2] = cl->GetZ();
4837 // Calculate seed state vector and covariance matrix
4839 Double_t alpha, cs,sn, xx2,yy2;
4841 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4842 cs = TMath::Cos(alpha);
4843 sn = TMath::Sin(alpha);
4844 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4845 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4849 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4850 cs = TMath::Cos(alpha);
4851 sn = TMath::Sin(alpha);
4852 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4853 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4859 Double_t x[5],c[15];
4863 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4864 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4865 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4867 Double_t sy =0.1, sz =0.1;
4869 Double_t sy1=0.2, sz1=0.2;
4870 Double_t sy2=0.2, sz2=0.2;
4873 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;
4874 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;
4875 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;
4876 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;
4877 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;
4878 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;
4880 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;
4881 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;
4882 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;
4883 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;
4888 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4889 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4890 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4891 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4892 c[13]=f30*sy1*f40+f32*sy2*f42;
4893 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4895 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4896 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4897 seed->SetPoolID(fLastSeedID);
4898 seed->SetLastPoint(row[2]);
4899 seed->SetFirstPoint(row[2]);
4904 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4908 //reseed using founded clusters
4911 Int_t row[3]={0,0,0};
4912 Int_t sec[3]={0,0,0};
4914 // forward direction
4916 for (Int_t irow=r0;irow<160;irow++){
4917 if (track->GetClusterIndex(irow)>0){
4922 for (Int_t irow=160;irow>r0;irow--){
4923 if (track->GetClusterIndex(irow)>0){
4928 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4929 if (track->GetClusterIndex(irow)>0){
4937 for (Int_t irow=0;irow<r0;irow++){
4938 if (track->GetClusterIndex(irow)>0){
4943 for (Int_t irow=r0;irow>0;irow--){
4944 if (track->GetClusterIndex(irow)>0){
4949 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4950 if (track->GetClusterIndex(irow)>0){
4957 if ((row[2]-row[0])<20) return 0;
4958 if (row[1]==0) return 0;
4961 //Get cluster and sector position
4962 for (Int_t ipoint=0;ipoint<3;ipoint++){
4963 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4964 AliTPCclusterMI * cl = GetClusterMI(clindex);
4967 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4970 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4971 xyz[ipoint][0] = GetXrow(row[ipoint]);
4972 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4973 if (point&&ipoint<2){
4975 xyz[ipoint][1] = point->GetY();
4976 xyz[ipoint][2] = point->GetZ();
4979 xyz[ipoint][1] = cl->GetY();
4980 xyz[ipoint][2] = cl->GetZ();
4987 // Calculate seed state vector and covariance matrix
4989 Double_t alpha, cs,sn, xx2,yy2;
4991 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4992 cs = TMath::Cos(alpha);
4993 sn = TMath::Sin(alpha);
4994 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4995 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4999 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
5000 cs = TMath::Cos(alpha);
5001 sn = TMath::Sin(alpha);
5002 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
5003 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
5009 Double_t x[5],c[15];
5013 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5014 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5015 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
5017 Double_t sy =0.1, sz =0.1;
5019 Double_t sy1=0.2, sz1=0.2;
5020 Double_t sy2=0.2, sz2=0.2;
5023 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;
5024 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;
5025 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;
5026 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;
5027 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;
5028 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;
5030 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;
5031 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;
5032 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;
5033 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;
5038 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
5039 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
5040 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
5041 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
5042 c[13]=f30*sy1*f40+f32*sy2*f42;
5043 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
5045 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
5046 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
5047 seed->SetPoolID(fLastSeedID);
5048 seed->SetLastPoint(row[2]);
5049 seed->SetFirstPoint(row[2]);
5050 for (Int_t i=row[0];i<row[2];i++){
5051 seed->SetClusterIndex(i, track->GetClusterIndex(i));
5059 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5062 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
5064 // Use AliTPCReconstructor::StreamLevel()& kStreamFindMultiMC if you want to tune parameters - cuts
5066 // Two reasons to have multiple find tracks
5067 // 1. Curling tracks can be find more than once
5068 // 2. Splitted tracks
5069 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
5070 // b.) Edge effect on the sector boundaries
5073 // Algorithm done in 2 phases - because of CPU consumption
5074 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
5076 // Algorihm for curling tracks sign:
5077 // 1 phase -makes a very rough fast cuts to minimize combinatorics
5078 // a.) opposite sign
5079 // b.) one of the tracks - not pointing to the primary vertex -
5080 // c.) delta tan(theta)
5082 // 2 phase - calculates DCA between tracks - time consument
5087 // General cuts - for splitted tracks and for curling tracks
5089 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
5091 // Curling tracks cuts
5096 Int_t nentries = array->GetEntriesFast();
5097 AliHelix *helixes = new AliHelix[nentries];
5098 Float_t *xm = new Float_t[nentries];
5099 Float_t *dz0 = new Float_t[nentries];
5100 Float_t *dz1 = new Float_t[nentries];
5106 // Find track COG in x direction - point with best defined parameters
5108 for (Int_t i=0;i<nentries;i++){
5109 AliTPCseed* track = (AliTPCseed*)array->At(i);
5110 if (!track) continue;
5111 track->SetCircular(0);
5112 new (&helixes[i]) AliHelix(*track);
5116 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
5119 for (Int_t icl=0; icl<160; icl++){
5120 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
5126 if (ncl>0) xm[i]/=Float_t(ncl);
5129 for (Int_t i0=0;i0<nentries;i0++){
5130 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5131 if (!track0) continue;
5132 Float_t xc0 = helixes[i0].GetHelix(6);
5133 Float_t yc0 = helixes[i0].GetHelix(7);
5134 Float_t r0 = helixes[i0].GetHelix(8);
5135 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5136 Float_t fi0 = TMath::ATan2(yc0,xc0);
5138 for (Int_t i1=i0+1;i1<nentries;i1++){
5139 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5140 if (!track1) continue;
5141 Int_t lab0=track0->GetLabel();
5142 Int_t lab1=track1->GetLabel();
5143 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
5145 Float_t xc1 = helixes[i1].GetHelix(6);
5146 Float_t yc1 = helixes[i1].GetHelix(7);
5147 Float_t r1 = helixes[i1].GetHelix(8);
5148 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5149 Float_t fi1 = TMath::ATan2(yc1,xc1);
5151 Float_t dfi = fi0-fi1;
5154 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
5155 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
5156 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
5158 // if short tracks with undefined sign
5159 fi1 = -TMath::ATan2(yc1,-xc1);
5162 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5165 // debug stream to tune "fast cuts"
5167 Double_t dist[3]; // distance at X
5168 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
5169 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
5170 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5171 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
5172 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5173 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
5174 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5175 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
5179 for (Int_t icl=0; icl<160; icl++){
5180 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
5181 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
5184 if (cl0==cl1) sums++;
5188 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) { // flag: stream MC infomation about the multiple find track (ONLY for MC data)
5189 TTreeSRedirector &cstream = *fDebugStreamer;
5194 "Tr0.="<<track0<< // seed0
5195 "Tr1.="<<track1<< // seed1
5196 "h0.="<<&helixes[i0]<<
5197 "h1.="<<&helixes[i1]<<
5199 "sum="<<sum<< //the sum of rows with cl in both
5200 "sums="<<sums<< //the sum of shared clusters
5201 "xm0="<<xm[i0]<< // the center of track
5202 "xm1="<<xm[i1]<< // the x center of track
5203 // General cut variables
5204 "dfi="<<dfi<< // distance in fi angle
5205 "dtheta="<<dtheta<< // distance int theta angle
5211 "dist0="<<dist[0]<< //distance x
5212 "dist1="<<dist[1]<< //distance y
5213 "dist2="<<dist[2]<< //distance z
5214 "mdist0="<<mdist[0]<< //distance x
5215 "mdist1="<<mdist[1]<< //distance y
5216 "mdist2="<<mdist[2]<< //distance z
5232 if (AliTPCReconstructor::StreamLevel()>0) {
5233 AliInfo("Time for curling tracks removal DEBUGGING MC");
5240 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
5242 // Find Splitted tracks and remove the one with worst quality
5243 // Corresponding debug streamer to tune selections - "Splitted2"
5245 // 0. Sort tracks according quality
5246 // 1. Propagate the tracks to the reference radius
5247 // 2. Double_t loop to select close tracks (only to speed up process)
5248 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
5249 // 4. Delete temporary parameters
5251 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
5253 const Double_t kCutP1=10; // delta Z cut 10 cm
5254 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
5255 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
5256 const Double_t kCutAlpha=0.15; // delta alpha cut
5257 Int_t firstpoint = 0;
5258 Int_t lastpoint = 160;
5260 Int_t nentries = array->GetEntriesFast();
5261 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
5267 //0. Sort tracks according quality
5268 //1. Propagate the ext. param to reference radius
5269 Int_t nseed = array->GetEntriesFast();
5270 if (nseed<=0) return;
5271 Float_t * quality = new Float_t[nseed];
5272 Int_t * indexes = new Int_t[nseed];
5273 for (Int_t i=0; i<nseed; i++) {
5274 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
5279 pt->UpdatePoints(); //select first last max dens points
5280 Float_t * points = pt->GetPoints();
5281 if (points[3]<0.8) quality[i] =-1;
5282 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
5283 //prefer high momenta tracks if overlaps
5284 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
5286 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
5287 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
5289 TMath::Sort(nseed,quality,indexes);
5291 // 3. Loop over pair of tracks
5293 for (Int_t i0=0; i0<nseed; i0++) {
5294 Int_t index0=indexes[i0];
5295 if (!(array->UncheckedAt(index0))) continue;
5296 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
5297 if (!s1->IsActive()) continue;
5298 AliExternalTrackParam &par0=params[index0];
5299 for (Int_t i1=i0+1; i1<nseed; i1++) {
5300 Int_t index1=indexes[i1];
5301 if (!(array->UncheckedAt(index1))) continue;
5302 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
5303 if (!s2->IsActive()) continue;
5304 if (s2->GetKinkIndexes()[0]!=0)
5305 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
5306 AliExternalTrackParam &par1=params[index1];
5307 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
5308 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
5309 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
5310 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
5311 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
5312 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
5317 Int_t firstShared=lastpoint, lastShared=firstpoint;
5318 Int_t firstRow=lastpoint, lastRow=firstpoint;
5320 for (Int_t i=firstpoint;i<lastpoint;i++){
5321 if (s1->GetClusterIndex2(i)>0) nall0++;
5322 if (s2->GetClusterIndex2(i)>0) nall1++;
5323 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
5324 if (i<firstRow) firstRow=i;
5325 if (i>lastRow) lastRow=i;
5327 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
5328 if (i<firstShared) firstShared=i;
5329 if (i>lastShared) lastShared=i;
5333 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
5334 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
5336 if ((AliTPCReconstructor::StreamLevel()&kStreamSplitted2)>0){ // flag:stream information about discarded TPC tracks pair algorithm
5337 TTreeSRedirector &cstream = *fDebugStreamer;
5338 Int_t n0=s1->GetNumberOfClusters();
5339 Int_t n1=s2->GetNumberOfClusters();
5340 Int_t n0F=s1->GetNFoundable();
5341 Int_t n1F=s2->GetNFoundable();
5342 Int_t lab0=s1->GetLabel();
5343 Int_t lab1=s2->GetLabel();
5345 cstream<<"Splitted2"<< // flag:stream information about discarded TPC tracks pair algorithm
5346 "iter="<<fIteration<<
5347 "lab0="<<lab0<< // MC label if exist
5348 "lab1="<<lab1<< // MC label if exist
5351 "ratio0="<<ratio0<< // shared ratio
5352 "ratio1="<<ratio1<< // shared ratio
5353 "p0.="<<&par0<< // track parameters
5355 "s0.="<<s1<< // full seed
5357 "n0="<<n0<< // number of clusters track 0
5358 "n1="<<n1<< // number of clusters track 1
5359 "nall0="<<nall0<< // number of clusters track 0
5360 "nall1="<<nall1<< // number of clusters track 1
5361 "n0F="<<n0F<< // number of findable
5362 "n1F="<<n1F<< // number of findable
5363 "shared="<<sumShared<< // number of shared clusters
5364 "firstS="<<firstShared<< // first and the last shared row
5365 "lastS="<<lastShared<<
5366 "firstRow="<<firstRow<< // first and the last row with cluster
5367 "lastRow="<<lastRow<< //
5371 // remove track with lower quality
5373 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
5374 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
5378 MarkSeedFree( array->RemoveAt(index1) );
5383 // 4. Delete temporary array
5393 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5396 // find Curling tracks
5397 // Use AliTPCReconstructor::StreamLevel()&kStreamFindCurling if you want to tune parameters - cuts
5400 // Algorithm done in 2 phases - because of CPU consumption
5401 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
5402 // see detal in MC part what can be used to cut
5406 const Float_t kMaxC = 400; // maximal curvature to of the track
5407 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
5408 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
5409 const Float_t kPtRatio = 0.3; // ratio between pt
5410 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
5413 // Curling tracks cuts
5416 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
5417 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
5418 const Float_t kMinAngle = 2.9; // angle between tracks
5419 const Float_t kMaxDist = 5; // biggest distance
5421 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
5424 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
5425 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
5426 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
5427 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
5428 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
5430 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
5431 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
5433 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
5434 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
5436 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
5442 Int_t nentries = array->GetEntriesFast();
5443 AliHelix *helixes = new AliHelix[nentries];
5444 for (Int_t i=0;i<nentries;i++){
5445 AliTPCseed* track = (AliTPCseed*)array->At(i);
5446 if (!track) continue;
5447 track->SetCircular(0);
5448 new (&helixes[i]) AliHelix(*track);
5454 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5460 for (Int_t i0=0;i0<nentries;i0++){
5461 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5462 if (!track0) continue;
5463 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
5464 Float_t xc0 = helixes[i0].GetHelix(6);
5465 Float_t yc0 = helixes[i0].GetHelix(7);
5466 Float_t r0 = helixes[i0].GetHelix(8);
5467 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5468 Float_t fi0 = TMath::ATan2(yc0,xc0);
5470 for (Int_t i1=i0+1;i1<nentries;i1++){
5471 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5472 if (!track1) continue;
5473 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
5474 Float_t xc1 = helixes[i1].GetHelix(6);
5475 Float_t yc1 = helixes[i1].GetHelix(7);
5476 Float_t r1 = helixes[i1].GetHelix(8);
5477 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5478 Float_t fi1 = TMath::ATan2(yc1,xc1);
5480 Float_t dfi = fi0-fi1;
5483 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
5484 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
5485 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5489 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
5490 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
5491 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
5492 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
5493 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
5495 Float_t pt0 = track0->GetSignedPt();
5496 Float_t pt1 = track1->GetSignedPt();
5497 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
5498 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
5499 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
5500 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
5503 // Now find closest approach
5507 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5508 if (npoints==0) continue;
5509 helixes[i0].GetClosestPhases(helixes[i1], phase);
5513 Double_t hangles[3];
5514 helixes[i0].Evaluate(phase[0][0],xyz0);
5515 helixes[i1].Evaluate(phase[0][1],xyz1);
5517 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5518 Double_t deltah[2],deltabest;
5519 if (TMath::Abs(hangles[2])<kMinAngle) continue;
5523 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5525 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5526 if (deltah[1]<deltah[0]) ibest=1;
5528 deltabest = TMath::Sqrt(deltah[ibest]);
5529 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5530 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5531 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5532 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5534 if (deltabest>kMaxDist) continue;
5535 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5536 Bool_t sign =kFALSE;
5537 if (hangles[2]>kMinAngle) sign =kTRUE;
5540 // circular[i0] = kTRUE;
5541 // circular[i1] = kTRUE;
5542 if (track0->OneOverPt()<track1->OneOverPt()){
5543 track0->SetCircular(track0->GetCircular()+1);
5544 track1->SetCircular(track1->GetCircular()+2);
5547 track1->SetCircular(track1->GetCircular()+1);
5548 track0->SetCircular(track0->GetCircular()+2);
5551 if ((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0){ // flag: stream track infroamtion if the FindCurling tracks method
5553 //debug stream to tune "fine" cuts
5554 Int_t lab0=track0->GetLabel();
5555 Int_t lab1=track1->GetLabel();
5556 TTreeSRedirector &cstream = *fDebugStreamer;
5557 cstream<<"Curling2"<<
5573 "npoints="<<npoints<<
5574 "hangles0="<<hangles[0]<<
5575 "hangles1="<<hangles[1]<<
5576 "hangles2="<<hangles[2]<<
5579 "radius="<<radiusbest<<
5580 "deltabest="<<deltabest<<
5581 "phase0="<<phase[ibest][0]<<
5582 "phase1="<<phase[ibest][1]<<
5590 if (AliTPCReconstructor::StreamLevel()>1) {
5591 AliInfo("Time for curling tracks removal");
5597 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5603 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5606 TObjArray *kinks= new TObjArray(10000);
5607 // TObjArray *v0s= new TObjArray(10000);
5608 Int_t nentries = array->GetEntriesFast();
5609 AliHelix *helixes = new AliHelix[nentries];
5610 Int_t *sign = new Int_t[nentries];
5611 Int_t *nclusters = new Int_t[nentries];
5612 Float_t *alpha = new Float_t[nentries];
5613 AliKink *kink = new AliKink();
5614 Int_t * usage = new Int_t[nentries];
5615 Float_t *zm = new Float_t[nentries];
5616 Float_t *z0 = new Float_t[nentries];
5617 Float_t *fim = new Float_t[nentries];
5618 Float_t *shared = new Float_t[nentries];
5619 Bool_t *circular = new Bool_t[nentries];
5620 Float_t *dca = new Float_t[nentries];
5621 //const AliESDVertex * primvertex = esd->GetVertex();
5623 // nentries = array->GetEntriesFast();
5628 for (Int_t i=0;i<nentries;i++){
5631 AliTPCseed* track = (AliTPCseed*)array->At(i);
5632 if (!track) continue;
5633 track->SetCircular(0);
5635 track->UpdatePoints();
5636 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5638 nclusters[i]=track->GetNumberOfClusters();
5639 alpha[i] = track->GetAlpha();
5640 new (&helixes[i]) AliHelix(*track);
5642 helixes[i].Evaluate(0,xyz);
5643 sign[i] = (track->GetC()>0) ? -1:1;
5646 if (track->GetProlongation(x,y,z)){
5648 fim[i] = alpha[i]+TMath::ATan2(y,x);
5651 zm[i] = track->GetZ();
5655 circular[i]= kFALSE;
5656 if (track->GetProlongation(0,y,z)) z0[i] = z;
5657 dca[i] = track->GetD(0,0);
5663 Int_t ncandidates =0;
5666 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5669 // Find circling track
5671 for (Int_t i0=0;i0<nentries;i0++){
5672 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5673 if (!track0) continue;
5674 if (track0->GetNumberOfClusters()<40) continue;
5675 if (TMath::Abs(1./track0->GetC())>200) continue;
5676 for (Int_t i1=i0+1;i1<nentries;i1++){
5677 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5678 if (!track1) continue;
5679 if (track1->GetNumberOfClusters()<40) continue;
5680 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5681 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5682 if (TMath::Abs(1./track1->GetC())>200) continue;
5683 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5684 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5685 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5686 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5687 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5689 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5690 if (mindcar<5) continue;
5691 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5692 if (mindcaz<5) continue;
5693 if (mindcar+mindcaz<20) continue;
5696 Float_t xc0 = helixes[i0].GetHelix(6);
5697 Float_t yc0 = helixes[i0].GetHelix(7);
5698 Float_t r0 = helixes[i0].GetHelix(8);
5699 Float_t xc1 = helixes[i1].GetHelix(6);
5700 Float_t yc1 = helixes[i1].GetHelix(7);
5701 Float_t r1 = helixes[i1].GetHelix(8);
5703 Float_t rmean = (r0+r1)*0.5;
5704 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5705 //if (delta>30) continue;
5706 if (delta>rmean*0.25) continue;
5707 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5709 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5710 if (npoints==0) continue;
5711 helixes[i0].GetClosestPhases(helixes[i1], phase);
5715 Double_t hangles[3];
5716 helixes[i0].Evaluate(phase[0][0],xyz0);
5717 helixes[i1].Evaluate(phase[0][1],xyz1);
5719 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5720 Double_t deltah[2],deltabest;
5721 if (hangles[2]<2.8) continue;
5724 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5726 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5727 if (deltah[1]<deltah[0]) ibest=1;
5729 deltabest = TMath::Sqrt(deltah[ibest]);
5730 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5731 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5732 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5733 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5735 if (deltabest>6) continue;
5736 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5737 Bool_t lsign =kFALSE;
5738 if (hangles[2]>3.06) lsign =kTRUE;
5741 circular[i0] = kTRUE;
5742 circular[i1] = kTRUE;
5743 if (track0->OneOverPt()<track1->OneOverPt()){
5744 track0->SetCircular(track0->GetCircular()+1);
5745 track1->SetCircular(track1->GetCircular()+2);
5748 track1->SetCircular(track1->GetCircular()+1);
5749 track0->SetCircular(track0->GetCircular()+2);
5752 if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0)){
5754 Int_t lab0=track0->GetLabel();
5755 Int_t lab1=track1->GetLabel();
5756 TTreeSRedirector &cstream = *fDebugStreamer;
5757 cstream<<"Curling"<<
5764 "mindcar="<<mindcar<<
5765 "mindcaz="<<mindcaz<<
5768 "npoints="<<npoints<<
5769 "hangles0="<<hangles[0]<<
5770 "hangles2="<<hangles[2]<<
5775 "radius="<<radiusbest<<
5776 "deltabest="<<deltabest<<
5777 "phase0="<<phase[ibest][0]<<
5778 "phase1="<<phase[ibest][1]<<
5788 for (Int_t i =0;i<nentries;i++){
5789 if (sign[i]==0) continue;
5790 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5797 Double_t cradius0 = 40*40;
5798 Double_t cradius1 = 270*270;
5801 Double_t cdist3=0.55;
5802 for (Int_t j =i+1;j<nentries;j++){
5804 if (sign[j]*sign[i]<1) continue;
5805 if ( (nclusters[i]+nclusters[j])>200) continue;
5806 if ( (nclusters[i]+nclusters[j])<80) continue;
5807 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5808 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5809 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5810 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5811 if (npoints<1) continue;
5814 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5817 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5820 Double_t delta1=10000,delta2=10000;
5821 // cuts on the intersection radius
5822 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5823 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5824 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5826 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5827 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5828 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5831 Double_t distance1 = TMath::Min(delta1,delta2);
5832 if (distance1>cdist1) continue; // cut on DCA linear approximation
5834 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5835 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5836 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5837 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5840 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5841 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5842 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5844 distance1 = TMath::Min(delta1,delta2);
5847 rkink = TMath::Sqrt(radius[0]);
5850 rkink = TMath::Sqrt(radius[1]);
5852 if (distance1>cdist2) continue;
5855 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5858 Int_t row0 = GetRowNumber(rkink);
5859 if (row0<10) continue;
5860 if (row0>150) continue;
5863 Float_t dens00=-1,dens01=-1;
5864 Float_t dens10=-1,dens11=-1;
5866 Int_t found,foundable,ishared;
5867 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5868 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5869 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5870 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5872 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5873 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5874 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5875 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5877 if (dens00<dens10 && dens01<dens11) continue;
5878 if (dens00>dens10 && dens01>dens11) continue;
5879 if (TMath::Max(dens00,dens10)<0.1) continue;
5880 if (TMath::Max(dens01,dens11)<0.3) continue;
5882 if (TMath::Min(dens00,dens10)>0.6) continue;
5883 if (TMath::Min(dens01,dens11)>0.6) continue;
5886 AliTPCseed * ktrack0, *ktrack1;
5895 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5896 AliExternalTrackParam paramm(*ktrack0);
5897 AliExternalTrackParam paramd(*ktrack1);
5898 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5901 kink->SetMother(paramm);
5902 kink->SetDaughter(paramd);
5905 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])};
5907 fkParam->Transform0to1(x,index);
5908 fkParam->Transform1to2(x,index);
5909 row0 = GetRowNumber(x[0]);
5911 if (kink->GetR()<100) continue;
5912 if (kink->GetR()>240) continue;
5913 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5914 if (kink->GetDistance()>cdist3) continue;
5915 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5916 if (dird<0) continue;
5918 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5919 if (dirm<0) continue;
5920 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5921 if (mpt<0.2) continue;
5924 //for high momenta momentum not defined well in first iteration
5925 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5926 if (qt>0.35) continue;
5929 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5930 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5932 kink->SetTPCDensity(dens00,0,0);
5933 kink->SetTPCDensity(dens01,0,1);
5934 kink->SetTPCDensity(dens10,1,0);
5935 kink->SetTPCDensity(dens11,1,1);
5936 kink->SetIndex(i,0);
5937 kink->SetIndex(j,1);
5940 kink->SetTPCDensity(dens10,0,0);
5941 kink->SetTPCDensity(dens11,0,1);
5942 kink->SetTPCDensity(dens00,1,0);
5943 kink->SetTPCDensity(dens01,1,1);
5944 kink->SetIndex(j,0);
5945 kink->SetIndex(i,1);
5948 if (mpt<1||kink->GetAngle(2)>0.1){
5949 // angle and densities not defined yet
5950 if (kink->GetTPCDensityFactor()<0.8) continue;
5951 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5952 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5953 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5954 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5956 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5957 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5958 criticalangle= 3*TMath::Sqrt(criticalangle);
5959 if (criticalangle>0.02) criticalangle=0.02;
5960 if (kink->GetAngle(2)<criticalangle) continue;
5963 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5964 Float_t shapesum =0;
5966 for ( Int_t row = row0-drow; row<row0+drow;row++){
5967 if (row<0) continue;
5968 if (row>155) continue;
5969 if (ktrack0->GetClusterPointer(row)){
5970 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5971 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5974 if (ktrack1->GetClusterPointer(row)){
5975 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5976 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5981 kink->SetShapeFactor(-1.);
5984 kink->SetShapeFactor(shapesum/sum);
5986 // esd->AddKink(kink);
5988 // kink->SetMother(paramm);
5989 //kink->SetDaughter(paramd);
5991 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5993 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5994 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5996 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5998 if ((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0) { // flag: stream track infroamtion in the FindKinks method
5999 (*fDebugStreamer)<<"kinkLpt"<<
6007 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6011 kinks->AddLast(kink);
6017 // sort the kinks according quality - and refit them towards vertex
6019 Int_t nkinks = kinks->GetEntriesFast();
6020 Float_t *quality = new Float_t[nkinks];
6021 Int_t *indexes = new Int_t[nkinks];
6022 AliTPCseed *mothers = new AliTPCseed[nkinks];
6023 AliTPCseed *daughters = new AliTPCseed[nkinks];
6026 for (Int_t i=0;i<nkinks;i++){
6028 AliKink *kinkl = (AliKink*)kinks->At(i);
6030 // refit kinks towards vertex
6032 Int_t index0 = kinkl->GetIndex(0);
6033 Int_t index1 = kinkl->GetIndex(1);
6034 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6035 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6037 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6039 // Refit Kink under if too small angle
6041 if (kinkl->GetAngle(2)<0.05){
6042 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6043 Int_t row0 = kinkl->GetTPCRow0();
6044 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6047 Int_t last = row0-drow;
6048 if (last<40) last=40;
6049 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6050 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6053 Int_t first = row0+drow;
6054 if (first>130) first=130;
6055 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6056 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6058 if (seed0 && seed1){
6059 kinkl->SetStatus(1,8);
6060 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6061 row0 = GetRowNumber(kinkl->GetR());
6062 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6063 mothers[i] = *seed0;
6064 daughters[i] = *seed1;
6067 delete kinks->RemoveAt(i);
6068 if (seed0) MarkSeedFree( seed0 );
6069 if (seed1) MarkSeedFree( seed1 );
6072 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6073 delete kinks->RemoveAt(i);
6074 if (seed0) MarkSeedFree( seed0 );
6075 if (seed1) MarkSeedFree( seed1 );
6079 MarkSeedFree( seed0 );
6080 MarkSeedFree( seed1 );
6083 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6085 TMath::Sort(nkinks,quality,indexes,kFALSE);
6087 //remove double find kinks
6089 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6090 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6091 if (!kink0) continue;
6093 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6094 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6095 if (!kink0) continue;
6096 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6097 if (!kink1) continue;
6098 // if not close kink continue
6099 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6100 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6101 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6103 AliTPCseed &mother0 = mothers[indexes[ikink0]];
6104 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
6105 AliTPCseed &mother1 = mothers[indexes[ikink1]];
6106 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
6107 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6116 for (Int_t i=0;i<row0;i++){
6117 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6120 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6127 for (Int_t i=row0;i<158;i++){
6128 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6129 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6132 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6138 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6139 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6140 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6141 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6142 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6143 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6145 shared[kink0->GetIndex(0)]= kTRUE;
6146 shared[kink0->GetIndex(1)]= kTRUE;
6147 delete kinks->RemoveAt(indexes[ikink0]);
6151 shared[kink1->GetIndex(0)]= kTRUE;
6152 shared[kink1->GetIndex(1)]= kTRUE;
6153 delete kinks->RemoveAt(indexes[ikink1]);
6160 for (Int_t i=0;i<nkinks;i++){
6161 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6162 if (!kinkl) continue;
6163 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6164 Int_t index0 = kinkl->GetIndex(0);
6165 Int_t index1 = kinkl->GetIndex(1);
6166 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6167 kinkl->SetMultiple(usage[index0],0);
6168 kinkl->SetMultiple(usage[index1],1);
6169 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6170 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6171 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6172 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6174 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6175 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6176 if (!ktrack0 || !ktrack1) continue;
6177 Int_t index = esd->AddKink(kinkl);
6180 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6181 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
6182 *ktrack0 = mothers[indexes[i]];
6183 *ktrack1 = daughters[indexes[i]];
6187 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6188 ktrack1->SetKinkIndex(usage[index1], (index+1));
6193 // Remove tracks corresponding to shared kink's
6195 for (Int_t i=0;i<nentries;i++){
6196 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6197 if (!track0) continue;
6198 if (track0->GetKinkIndex(0)!=0) continue;
6199 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6204 RemoveUsed2(array,0.5,0.4,30);
6206 for (Int_t i=0;i<nentries;i++){
6207 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6208 if (!track0) continue;
6209 track0->CookdEdx(0.02,0.6);
6213 for (Int_t i=0;i<nentries;i++){
6214 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6215 if (!track0) continue;
6216 if (track0->Pt()<1.4) continue;
6217 //remove double high momenta tracks - overlapped with kink candidates
6220 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6221 if (track0->GetClusterPointer(icl)!=0){
6223 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6226 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6227 MarkSeedFree( array->RemoveAt(i) );
6231 if (track0->GetKinkIndex(0)!=0) continue;
6232 if (track0->GetNumberOfClusters()<80) continue;
6234 AliTPCseed *pmother = new AliTPCseed();
6235 AliTPCseed *pdaughter = new AliTPCseed();
6236 AliKink *pkink = new AliKink;
6238 AliTPCseed & mother = *pmother;
6239 AliTPCseed & daughter = *pdaughter;
6240 AliKink & kinkl = *pkink;
6241 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6242 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6246 continue; //too short tracks
6248 if (mother.Pt()<1.4) {
6254 Int_t row0= kinkl.GetTPCRow0();
6255 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6262 Int_t index = esd->AddKink(&kinkl);
6263 mother.SetKinkIndex(0,-(index+1));
6264 daughter.SetKinkIndex(0,index+1);
6265 if (mother.GetNumberOfClusters()>50) {
6266 MarkSeedFree( array->RemoveAt(i) );
6267 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6268 mtc->SetPoolID(fLastSeedID);
6269 array->AddAt(mtc,i);
6272 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6273 mtc->SetPoolID(fLastSeedID);
6274 array->AddLast(mtc);
6276 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6277 dtc->SetPoolID(fLastSeedID);
6278 array->AddLast(dtc);
6279 for (Int_t icl=0;icl<row0;icl++) {
6280 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6283 for (Int_t icl=row0;icl<158;icl++) {
6284 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6293 delete [] daughters;
6315 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6321 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
6328 TObjArray *kinks= new TObjArray(10000);
6329 // TObjArray *v0s= new TObjArray(10000);
6330 Int_t nentries = array->GetEntriesFast();
6331 AliHelix *helixes = new AliHelix[nentries];
6332 Int_t *sign = new Int_t[nentries];
6333 Int_t *nclusters = new Int_t[nentries];
6334 Float_t *alpha = new Float_t[nentries];
6335 AliKink *kink = new AliKink();
6336 Int_t * usage = new Int_t[nentries];
6337 Float_t *zm = new Float_t[nentries];
6338 Float_t *z0 = new Float_t[nentries];
6339 Float_t *fim = new Float_t[nentries];
6340 Float_t *shared = new Float_t[nentries];
6341 Bool_t *circular = new Bool_t[nentries];
6342 Float_t *dca = new Float_t[nentries];
6343 //const AliESDVertex * primvertex = esd->GetVertex();
6345 // nentries = array->GetEntriesFast();
6350 for (Int_t i=0;i<nentries;i++){
6353 AliTPCseed* track = (AliTPCseed*)array->At(i);
6354 if (!track) continue;
6355 track->SetCircular(0);
6357 track->UpdatePoints();
6358 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
6360 nclusters[i]=track->GetNumberOfClusters();
6361 alpha[i] = track->GetAlpha();
6362 new (&helixes[i]) AliHelix(*track);
6364 helixes[i].Evaluate(0,xyz);
6365 sign[i] = (track->GetC()>0) ? -1:1;
6368 if (track->GetProlongation(x,y,z)){
6370 fim[i] = alpha[i]+TMath::ATan2(y,x);
6373 zm[i] = track->GetZ();
6377 circular[i]= kFALSE;
6378 if (track->GetProlongation(0,y,z)) z0[i] = z;
6379 dca[i] = track->GetD(0,0);
6385 Int_t ncandidates =0;
6388 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
6391 // Find circling track
6393 for (Int_t i0=0;i0<nentries;i0++){
6394 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
6395 if (!track0) continue;
6396 if (track0->GetNumberOfClusters()<40) continue;
6397 if (TMath::Abs(1./track0->GetC())>200) continue;
6398 for (Int_t i1=i0+1;i1<nentries;i1++){
6399 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
6400 if (!track1) continue;
6401 if (track1->GetNumberOfClusters()<40) continue;
6402 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
6403 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
6404 if (TMath::Abs(1./track1->GetC())>200) continue;
6405 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
6406 if (track1->GetTgl()*track0->GetTgl()>0) continue;
6407 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
6408 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
6409 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
6411 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
6412 if (mindcar<5) continue;
6413 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
6414 if (mindcaz<5) continue;
6415 if (mindcar+mindcaz<20) continue;
6418 Float_t xc0 = helixes[i0].GetHelix(6);
6419 Float_t yc0 = helixes[i0].GetHelix(7);
6420 Float_t r0 = helixes[i0].GetHelix(8);
6421 Float_t xc1 = helixes[i1].GetHelix(6);
6422 Float_t yc1 = helixes[i1].GetHelix(7);
6423 Float_t r1 = helixes[i1].GetHelix(8);
6425 Float_t rmean = (r0+r1)*0.5;
6426 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
6427 //if (delta>30) continue;
6428 if (delta>rmean*0.25) continue;
6429 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
6431 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
6432 if (npoints==0) continue;
6433 helixes[i0].GetClosestPhases(helixes[i1], phase);
6437 Double_t hangles[3];
6438 helixes[i0].Evaluate(phase[0][0],xyz0);
6439 helixes[i1].Evaluate(phase[0][1],xyz1);
6441 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
6442 Double_t deltah[2],deltabest;
6443 if (hangles[2]<2.8) continue;
6446 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
6448 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
6449 if (deltah[1]<deltah[0]) ibest=1;
6451 deltabest = TMath::Sqrt(deltah[ibest]);
6452 helixes[i0].Evaluate(phase[ibest][0],xyz0);
6453 helixes[i1].Evaluate(phase[ibest][1],xyz1);
6454 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
6455 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
6457 if (deltabest>6) continue;
6458 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
6459 Bool_t lsign =kFALSE;
6460 if (hangles[2]>3.06) lsign =kTRUE;
6463 circular[i0] = kTRUE;
6464 circular[i1] = kTRUE;
6465 if (track0->OneOverPt()<track1->OneOverPt()){
6466 track0->SetCircular(track0->GetCircular()+1);
6467 track1->SetCircular(track1->GetCircular()+2);
6470 track1->SetCircular(track1->GetCircular()+1);
6471 track0->SetCircular(track0->GetCircular()+2);
6474 if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0)){// flag: stream track infroamtion in the FindKinks method
6476 Int_t lab0=track0->GetLabel();
6477 Int_t lab1=track1->GetLabel();
6478 TTreeSRedirector &cstream = *fDebugStreamer;
6479 cstream<<"Curling"<<
6486 "mindcar="<<mindcar<<
6487 "mindcaz="<<mindcaz<<
6490 "npoints="<<npoints<<
6491 "hangles0="<<hangles[0]<<
6492 "hangles2="<<hangles[2]<<
6497 "radius="<<radiusbest<<
6498 "deltabest="<<deltabest<<
6499 "phase0="<<phase[ibest][0]<<
6500 "phase1="<<phase[ibest][1]<<
6510 for (Int_t i =0;i<nentries;i++){
6511 if (sign[i]==0) continue;
6512 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6519 Double_t cradius0 = 40*40;
6520 Double_t cradius1 = 270*270;
6523 Double_t cdist3=0.55;
6524 for (Int_t j =i+1;j<nentries;j++){
6526 if (sign[j]*sign[i]<1) continue;
6527 if ( (nclusters[i]+nclusters[j])>200) continue;
6528 if ( (nclusters[i]+nclusters[j])<80) continue;
6529 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6530 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6531 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6532 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6533 if (npoints<1) continue;
6536 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6539 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6542 Double_t delta1=10000,delta2=10000;
6543 // cuts on the intersection radius
6544 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6545 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6546 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6548 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6549 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6550 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6553 Double_t distance1 = TMath::Min(delta1,delta2);
6554 if (distance1>cdist1) continue; // cut on DCA linear approximation
6556 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6557 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6558 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6559 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6562 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6563 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6564 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6566 distance1 = TMath::Min(delta1,delta2);
6569 rkink = TMath::Sqrt(radius[0]);
6572 rkink = TMath::Sqrt(radius[1]);
6574 if (distance1>cdist2) continue;
6577 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6580 Int_t row0 = GetRowNumber(rkink);
6581 if (row0<10) continue;
6582 if (row0>150) continue;
6585 Float_t dens00=-1,dens01=-1;
6586 Float_t dens10=-1,dens11=-1;
6588 Int_t found,foundable,ishared;
6589 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6590 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6591 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6592 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6594 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6595 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6596 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6597 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6599 if (dens00<dens10 && dens01<dens11) continue;
6600 if (dens00>dens10 && dens01>dens11) continue;
6601 if (TMath::Max(dens00,dens10)<0.1) continue;
6602 if (TMath::Max(dens01,dens11)<0.3) continue;
6604 if (TMath::Min(dens00,dens10)>0.6) continue;
6605 if (TMath::Min(dens01,dens11)>0.6) continue;
6608 AliTPCseed * ktrack0, *ktrack1;
6617 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6618 AliExternalTrackParam paramm(*ktrack0);
6619 AliExternalTrackParam paramd(*ktrack1);
6620 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6623 kink->SetMother(paramm);
6624 kink->SetDaughter(paramd);
6627 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])};
6629 fkParam->Transform0to1(x,index);
6630 fkParam->Transform1to2(x,index);
6631 row0 = GetRowNumber(x[0]);
6633 if (kink->GetR()<100) continue;
6634 if (kink->GetR()>240) continue;
6635 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6636 if (kink->GetDistance()>cdist3) continue;
6637 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6638 if (dird<0) continue;
6640 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6641 if (dirm<0) continue;
6642 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6643 if (mpt<0.2) continue;
6646 //for high momenta momentum not defined well in first iteration
6647 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6648 if (qt>0.35) continue;
6651 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6652 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6654 kink->SetTPCDensity(dens00,0,0);
6655 kink->SetTPCDensity(dens01,0,1);
6656 kink->SetTPCDensity(dens10,1,0);
6657 kink->SetTPCDensity(dens11,1,1);
6658 kink->SetIndex(i,0);
6659 kink->SetIndex(j,1);
6662 kink->SetTPCDensity(dens10,0,0);
6663 kink->SetTPCDensity(dens11,0,1);
6664 kink->SetTPCDensity(dens00,1,0);
6665 kink->SetTPCDensity(dens01,1,1);
6666 kink->SetIndex(j,0);
6667 kink->SetIndex(i,1);
6670 if (mpt<1||kink->GetAngle(2)>0.1){
6671 // angle and densities not defined yet
6672 if (kink->GetTPCDensityFactor()<0.8) continue;
6673 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6674 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6675 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6676 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6678 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6679 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6680 criticalangle= 3*TMath::Sqrt(criticalangle);
6681 if (criticalangle>0.02) criticalangle=0.02;
6682 if (kink->GetAngle(2)<criticalangle) continue;
6685 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6686 Float_t shapesum =0;
6688 for ( Int_t row = row0-drow; row<row0+drow;row++){
6689 if (row<0) continue;
6690 if (row>155) continue;
6691 if (ktrack0->GetClusterPointer(row)){
6692 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6693 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6696 if (ktrack1->GetClusterPointer(row)){
6697 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6698 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6703 kink->SetShapeFactor(-1.);
6706 kink->SetShapeFactor(shapesum/sum);
6708 // esd->AddKink(kink);
6710 // kink->SetMother(paramm);
6711 //kink->SetDaughter(paramd);
6713 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6715 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6716 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6718 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6720 if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) {// flag: stream track infroamtion in the FindKinks method
6721 (*fDebugStreamer)<<"kinkLpt"<<
6729 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6733 kinks->AddLast(kink);
6739 // sort the kinks according quality - and refit them towards vertex
6741 Int_t nkinks = kinks->GetEntriesFast();
6742 Float_t *quality = new Float_t[nkinks];
6743 Int_t *indexes = new Int_t[nkinks];
6744 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6745 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6748 for (Int_t i=0;i<nkinks;i++){
6750 AliKink *kinkl = (AliKink*)kinks->At(i);
6752 // refit kinks towards vertex
6754 Int_t index0 = kinkl->GetIndex(0);
6755 Int_t index1 = kinkl->GetIndex(1);
6756 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6757 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6759 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6761 // Refit Kink under if too small angle
6763 if (kinkl->GetAngle(2)<0.05){
6764 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6765 Int_t row0 = kinkl->GetTPCRow0();
6766 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6769 Int_t last = row0-drow;
6770 if (last<40) last=40;
6771 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6772 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6775 Int_t first = row0+drow;
6776 if (first>130) first=130;
6777 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6778 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6780 if (seed0 && seed1){
6781 kinkl->SetStatus(1,8);
6782 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6783 row0 = GetRowNumber(kinkl->GetR());
6784 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6785 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6786 mothers[i]->SetPoolID(fLastSeedID);
6787 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6788 daughters[i]->SetPoolID(fLastSeedID);
6791 delete kinks->RemoveAt(i);
6792 if (seed0) MarkSeedFree( seed0 );
6793 if (seed1) MarkSeedFree( seed1 );
6796 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6797 delete kinks->RemoveAt(i);
6798 if (seed0) MarkSeedFree( seed0 );
6799 if (seed1) MarkSeedFree( seed1 );
6803 MarkSeedFree( seed0 );
6804 MarkSeedFree( seed1 );
6807 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6809 TMath::Sort(nkinks,quality,indexes,kFALSE);
6811 //remove double find kinks
6813 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6814 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6815 if (!kink0) continue;
6817 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6818 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6819 if (!kink0) continue;
6820 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6821 if (!kink1) continue;
6822 // if not close kink continue
6823 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6824 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6825 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6827 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6828 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6829 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6830 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6831 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6840 for (Int_t i=0;i<row0;i++){
6841 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6844 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6851 for (Int_t i=row0;i<158;i++){
6852 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6853 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6856 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6862 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6863 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6864 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6865 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6866 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6867 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6869 shared[kink0->GetIndex(0)]= kTRUE;
6870 shared[kink0->GetIndex(1)]= kTRUE;
6871 delete kinks->RemoveAt(indexes[ikink0]);
6875 shared[kink1->GetIndex(0)]= kTRUE;
6876 shared[kink1->GetIndex(1)]= kTRUE;
6877 delete kinks->RemoveAt(indexes[ikink1]);
6884 for (Int_t i=0;i<nkinks;i++){
6885 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6886 if (!kinkl) continue;
6887 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6888 Int_t index0 = kinkl->GetIndex(0);
6889 Int_t index1 = kinkl->GetIndex(1);
6890 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6891 kinkl->SetMultiple(usage[index0],0);
6892 kinkl->SetMultiple(usage[index1],1);
6893 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6894 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6895 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6896 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6898 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6899 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6900 if (!ktrack0 || !ktrack1) continue;
6901 Int_t index = esd->AddKink(kinkl);
6904 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6905 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6906 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6907 *ktrack0 = *mothers[indexes[i]];
6908 *ktrack1 = *daughters[indexes[i]];
6912 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6913 ktrack1->SetKinkIndex(usage[index1], (index+1));
6918 // Remove tracks corresponding to shared kink's
6920 for (Int_t i=0;i<nentries;i++){
6921 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6922 if (!track0) continue;
6923 if (track0->GetKinkIndex(0)!=0) continue;
6924 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6929 RemoveUsed2(array,0.5,0.4,30);
6931 for (Int_t i=0;i<nentries;i++){
6932 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6933 if (!track0) continue;
6934 track0->CookdEdx(0.02,0.6);
6938 for (Int_t i=0;i<nentries;i++){
6939 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6940 if (!track0) continue;
6941 if (track0->Pt()<1.4) continue;
6942 //remove double high momenta tracks - overlapped with kink candidates
6945 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6946 if (track0->GetClusterPointer(icl)!=0){
6948 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6951 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6952 MarkSeedFree( array->RemoveAt(i) );
6956 if (track0->GetKinkIndex(0)!=0) continue;
6957 if (track0->GetNumberOfClusters()<80) continue;
6959 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6960 pmother->SetPoolID(fLastSeedID);
6961 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6962 pdaughter->SetPoolID(fLastSeedID);
6963 AliKink *pkink = new AliKink;
6965 AliTPCseed & mother = *pmother;
6966 AliTPCseed & daughter = *pdaughter;
6967 AliKink & kinkl = *pkink;
6968 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6969 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6970 MarkSeedFree( pmother );
6971 MarkSeedFree( pdaughter );
6973 continue; //too short tracks
6975 if (mother.Pt()<1.4) {
6976 MarkSeedFree( pmother );
6977 MarkSeedFree( pdaughter );
6981 Int_t row0= kinkl.GetTPCRow0();
6982 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6983 MarkSeedFree( pmother );
6984 MarkSeedFree( pdaughter );
6989 Int_t index = esd->AddKink(&kinkl);
6990 mother.SetKinkIndex(0,-(index+1));
6991 daughter.SetKinkIndex(0,index+1);
6992 if (mother.GetNumberOfClusters()>50) {
6993 MarkSeedFree( array->RemoveAt(i) );
6994 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6995 mtc->SetPoolID(fLastSeedID);
6996 array->AddAt(mtc,i);
6999 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
7000 mtc->SetPoolID(fLastSeedID);
7001 array->AddLast(mtc);
7003 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
7004 dtc->SetPoolID(fLastSeedID);
7005 array->AddLast(dtc);
7006 for (Int_t icl=0;icl<row0;icl++) {
7007 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
7010 for (Int_t icl=row0;icl<158;icl++) {
7011 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
7015 MarkSeedFree( pmother );
7016 MarkSeedFree( pdaughter );
7020 delete [] daughters;
7042 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
7047 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7050 // refit kink towards to the vertex
7053 AliKink &kink=(AliKink &)knk;
7055 Int_t row0 = GetRowNumber(kink.GetR());
7056 FollowProlongation(mother,0);
7057 mother.Reset(kFALSE);
7059 FollowProlongation(daughter,row0);
7060 daughter.Reset(kFALSE);
7061 FollowBackProlongation(daughter,158);
7062 daughter.Reset(kFALSE);
7063 Int_t first = TMath::Max(row0-20,30);
7064 Int_t last = TMath::Min(row0+20,140);
7066 const Int_t kNdiv =5;
7067 AliTPCseed param0[kNdiv]; // parameters along the track
7068 AliTPCseed param1[kNdiv]; // parameters along the track
7069 AliKink kinks[kNdiv]; // corresponding kink parameters
7072 for (Int_t irow=0; irow<kNdiv;irow++){
7073 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
7075 // store parameters along the track
7077 for (Int_t irow=0;irow<kNdiv;irow++){
7078 FollowBackProlongation(mother, rows[irow]);
7079 FollowProlongation(daughter,rows[kNdiv-1-irow]);
7080 param0[irow] = mother;
7081 param1[kNdiv-1-irow] = daughter;
7085 for (Int_t irow=0; irow<kNdiv-1;irow++){
7086 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
7087 kinks[irow].SetMother(param0[irow]);
7088 kinks[irow].SetDaughter(param1[irow]);
7089 kinks[irow].Update();
7092 // choose kink with best "quality"
7094 Double_t mindist = 10000;
7095 for (Int_t irow=0;irow<kNdiv;irow++){
7096 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
7097 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7098 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
7100 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
7101 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
7102 if (normdist < mindist){
7108 if (index==-1) return 0;
7111 param0[index].Reset(kTRUE);
7112 FollowProlongation(param0[index],0);
7114 mother = param0[index];
7115 daughter = param1[index]; // daughter in vertex
7117 kink.SetMother(mother);
7118 kink.SetDaughter(daughter);
7120 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
7121 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7122 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7123 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
7124 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
7125 mother.SetLabel(kink.GetLabel(0));
7126 daughter.SetLabel(kink.GetLabel(1));
7132 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
7134 // update Kink quality information for mother after back propagation
7136 if (seed->GetKinkIndex(0)>=0) return;
7137 for (Int_t ikink=0;ikink<3;ikink++){
7138 Int_t index = seed->GetKinkIndex(ikink);
7139 if (index>=0) break;
7140 index = TMath::Abs(index)-1;
7141 AliESDkink * kink = fEvent->GetKink(index);
7142 kink->SetTPCDensity(-1,0,0);
7143 kink->SetTPCDensity(1,0,1);
7145 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7146 if (row0<15) row0=15;
7148 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7149 if (row1>145) row1=145;
7151 Int_t found,foundable,shared;
7152 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7153 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
7154 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7155 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
7160 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
7162 // update Kink quality information for daughter after refit
7164 if (seed->GetKinkIndex(0)<=0) return;
7165 for (Int_t ikink=0;ikink<3;ikink++){
7166 Int_t index = seed->GetKinkIndex(ikink);
7167 if (index<=0) break;
7168 index = TMath::Abs(index)-1;
7169 AliESDkink * kink = fEvent->GetKink(index);
7170 kink->SetTPCDensity(-1,1,0);
7171 kink->SetTPCDensity(-1,1,1);
7173 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7174 if (row0<15) row0=15;
7176 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7177 if (row1>145) row1=145;
7179 Int_t found,foundable,shared;
7180 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7181 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
7182 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7183 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
7189 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7192 // check kink point for given track
7193 // if return value=0 kink point not found
7194 // otherwise seed0 correspond to mother particle
7195 // seed1 correspond to daughter particle
7196 // kink parameter of kink point
7197 AliKink &kink=(AliKink &)knk;
7199 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
7200 Int_t first = seed->GetFirstPoint();
7201 Int_t last = seed->GetLastPoint();
7202 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
7205 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
7206 if (!seed1) return 0;
7207 FollowProlongation(*seed1,seed->GetLastPoint()-20);
7208 seed1->Reset(kTRUE);
7209 FollowProlongation(*seed1,158);
7210 seed1->Reset(kTRUE);
7211 last = seed1->GetLastPoint();
7213 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
7214 seed0->SetPoolID(fLastSeedID);
7215 seed0->Reset(kFALSE);
7218 AliTPCseed param0[20]; // parameters along the track
7219 AliTPCseed param1[20]; // parameters along the track
7220 AliKink kinks[20]; // corresponding kink parameters
7222 for (Int_t irow=0; irow<20;irow++){
7223 rows[irow] = first +((last-first)*irow)/19;
7225 // store parameters along the track
7227 for (Int_t irow=0;irow<20;irow++){
7228 FollowBackProlongation(*seed0, rows[irow]);
7229 FollowProlongation(*seed1,rows[19-irow]);
7230 param0[irow] = *seed0;
7231 param1[19-irow] = *seed1;
7235 for (Int_t irow=0; irow<19;irow++){
7236 kinks[irow].SetMother(param0[irow]);
7237 kinks[irow].SetDaughter(param1[irow]);
7238 kinks[irow].Update();
7241 // choose kink with biggest change of angle
7243 Double_t maxchange= 0;
7244 for (Int_t irow=1;irow<19;irow++){
7245 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7246 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
7247 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7248 if ( quality > maxchange){
7249 maxchange = quality;
7254 MarkSeedFree( seed0 );
7255 MarkSeedFree( seed1 );
7256 if (index<0) return 0;
7258 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
7259 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
7260 seed0->SetPoolID(fLastSeedID);
7261 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
7262 seed1->SetPoolID(fLastSeedID);
7263 seed0->Reset(kFALSE);
7264 seed1->Reset(kFALSE);
7265 seed0->ResetCovariance(10.);
7266 seed1->ResetCovariance(10.);
7267 FollowProlongation(*seed0,0);
7268 FollowBackProlongation(*seed1,158);
7269 mother = *seed0; // backup mother at position 0
7270 seed0->Reset(kFALSE);
7271 seed1->Reset(kFALSE);
7272 seed0->ResetCovariance(10.);
7273 seed1->ResetCovariance(10.);
7275 first = TMath::Max(row0-20,0);
7276 last = TMath::Min(row0+20,158);
7278 for (Int_t irow=0; irow<20;irow++){
7279 rows[irow] = first +((last-first)*irow)/19;
7281 // store parameters along the track
7283 for (Int_t irow=0;irow<20;irow++){
7284 FollowBackProlongation(*seed0, rows[irow]);
7285 FollowProlongation(*seed1,rows[19-irow]);
7286 param0[irow] = *seed0;
7287 param1[19-irow] = *seed1;
7291 for (Int_t irow=0; irow<19;irow++){
7292 kinks[irow].SetMother(param0[irow]);
7293 kinks[irow].SetDaughter(param1[irow]);
7294 // param0[irow].Dump();
7295 //param1[irow].Dump();
7296 kinks[irow].Update();
7299 // choose kink with biggest change of angle
7302 for (Int_t irow=0;irow<20;irow++){
7303 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
7304 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
7305 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7306 if ( quality > maxchange){
7307 maxchange = quality;
7314 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
7315 MarkSeedFree( seed0 );
7316 MarkSeedFree( seed1 );
7320 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
7322 kink.SetMother(param0[index]);
7323 kink.SetDaughter(param1[index]);
7326 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
7328 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
7329 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
7331 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
7333 if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) { // flag: stream track infroamtion in the FindKinks method
7334 (*fDebugStreamer)<<"kinkHpt"<<
7337 "p0.="<<¶m0[index]<<
7338 "p1.="<<¶m1[index]<<
7342 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
7343 MarkSeedFree( seed0 );
7344 MarkSeedFree( seed1 );
7349 row0 = GetRowNumber(kink.GetR());
7350 kink.SetTPCRow0(row0);
7351 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
7352 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
7353 kink.SetIndex(-10,0);
7354 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
7355 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7356 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7359 // new (&mother) AliTPCseed(param0[index]);
7360 daughter = param1[index];
7361 daughter.SetLabel(kink.GetLabel(1));
7362 param0[index].Reset(kTRUE);
7363 FollowProlongation(param0[index],0);
7364 mother = param0[index];
7365 mother.SetLabel(kink.GetLabel(0));
7366 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
7369 MarkSeedFree( seed0 );
7370 MarkSeedFree( seed1 );
7378 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
7381 // reseed - refit - track
7384 // Int_t last = fSectors->GetNRows()-1;
7386 if (fSectors == fOuterSec){
7387 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
7391 first = t->GetFirstPoint();
7393 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
7394 FollowBackProlongation(*t,fSectors->GetNRows()-1);
7396 FollowProlongation(*t,first);
7406 //_____________________________________________________________________________
7407 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
7408 //-----------------------------------------------------------------
7409 // This function reades track seeds.
7410 //-----------------------------------------------------------------
7411 TDirectory *savedir=gDirectory;
7413 TFile *in=(TFile*)inp;
7414 if (!in->IsOpen()) {
7415 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
7420 TTree *seedTree=(TTree*)in->Get("Seeds");
7422 cerr<<"AliTPCtracker::ReadSeeds(): ";
7423 cerr<<"can't get a tree with track seeds !\n";
7426 AliTPCtrack *seed=new AliTPCtrack;
7427 seedTree->SetBranchAddress("tracks",&seed);
7429 if (fSeeds==0) fSeeds=new TObjArray(15000);
7431 Int_t n=(Int_t)seedTree->GetEntries();
7432 for (Int_t i=0; i<n; i++) {
7433 seedTree->GetEvent(i);
7434 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
7435 sdc->SetPoolID(fLastSeedID);
7436 fSeeds->AddLast(sdc);
7439 delete seed; // RS: this seed is not from the pool, delete it !!!
7445 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
7448 // clusters to tracks
7449 if (fSeeds) DeleteSeeds();
7450 else ResetSeedsPool();
7452 fEventHLT = hltEvent;
7453 if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();
7454 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
7455 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
7456 transform->SetCurrentRun(esd->GetRunNumber());
7461 if (!fSeeds) return 1;
7463 if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0) DumpClusters(0,fSeeds);
7468 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
7471 // clusters to tracks
7472 return Clusters2TracksHLT( esd, 0);
7475 //_____________________________________________________________________________
7476 Int_t AliTPCtracker::Clusters2Tracks() {
7477 //-----------------------------------------------------------------
7478 // This is a track finder.
7479 //-----------------------------------------------------------------
7480 TDirectory *savedir=gDirectory;
7484 fSeeds = Tracking();
7487 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
7489 //activate again some tracks
7490 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
7491 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7493 Int_t nc=t.GetNumberOfClusters();
7495 MarkSeedFree( fSeeds->RemoveAt(i) );
7499 if (pt->GetRemoval()==10) {
7500 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7501 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
7503 pt->Desactivate(20);
7504 MarkSeedFree( fSeeds->RemoveAt(i) );
7509 RemoveUsed2(fSeeds,0.85,0.85,0);
7510 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
7511 //FindCurling(fSeeds, fEvent,0);
7512 if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
7513 RemoveUsed2(fSeeds,0.5,0.4,20);
7514 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
7515 if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
7518 // // refit short tracks
7520 Int_t nseed=fSeeds->GetEntriesFast();
7523 for (Int_t i=0; i<nseed; i++) {
7524 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7526 Int_t nc=t.GetNumberOfClusters();
7528 MarkSeedFree( fSeeds->RemoveAt(i) );
7531 CookLabel(pt,0.1); //For comparison only
7532 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7533 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7535 if (fDebug>0) cerr<<found<<'\r';
7539 MarkSeedFree( fSeeds->RemoveAt(i) );
7543 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7545 //RemoveUsed(fSeeds,0.9,0.9,6);
7547 nseed=fSeeds->GetEntriesFast();
7549 for (Int_t i=0; i<nseed; i++) {
7550 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7552 Int_t nc=t.GetNumberOfClusters();
7554 MarkSeedFree( fSeeds->RemoveAt(i) );
7558 t.CookdEdx(0.02,0.6);
7559 // CheckKinkPoint(&t,0.05);
7560 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7561 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7569 MarkSeedFree( fSeeds->RemoveAt(i) );
7570 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7572 // FollowProlongation(*seed1,0);
7573 // Int_t n = seed1->GetNumberOfClusters();
7574 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7575 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7578 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7582 SortTracks(fSeeds, 1);
7586 PrepareForBackProlongation(fSeeds,5.);
7587 PropagateBack(fSeeds);
7588 printf("Time for back propagation: \t");timer.Print();timer.Start();
7592 PrepareForProlongation(fSeeds,5.);
7593 PropagateForard2(fSeeds);
7595 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7596 // RemoveUsed(fSeeds,0.7,0.7,6);
7597 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7599 nseed=fSeeds->GetEntriesFast();
7601 for (Int_t i=0; i<nseed; i++) {
7602 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7604 Int_t nc=t.GetNumberOfClusters();
7606 MarkSeedFree( fSeeds->RemoveAt(i) );
7609 t.CookdEdx(0.02,0.6);
7610 // CookLabel(pt,0.1); //For comparison only
7611 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7612 if ((pt->IsActive() || (pt->fRemoval==10) )){
7613 cerr<<found++<<'\r';
7616 MarkSeedFree( fSeeds->RemoveAt(i) );
7621 // fNTracks = found;
7623 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7626 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7627 Info("Clusters2Tracks","Number of found tracks %d",found);
7629 // UnloadClusters();
7634 void AliTPCtracker::Tracking(TObjArray * arr)
7637 // tracking of the seeds
7640 fSectors = fOuterSec;
7641 ParallelTracking(arr,150,63);
7642 fSectors = fOuterSec;
7643 ParallelTracking(arr,63,0);
7646 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7651 static TObjArray arrTracks;
7652 TObjArray * arr = &arrTracks;
7654 fSectors = fOuterSec;
7657 for (Int_t sec=0;sec<fkNOS;sec++){
7658 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7659 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7660 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7663 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7675 TObjArray * AliTPCtracker::Tracking()
7679 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7682 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7684 TObjArray * seeds = new TObjArray;
7686 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7687 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7688 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7696 Float_t fnumber = 3.0;
7697 Float_t fdensity = 3.0;
7700 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7701 arr = MakeSeedsHLT( fEventHLT );
7703 SumTracks(seeds,arr);
7706 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7707 //SignClusters(seeds,fnumber,fdensity);
7714 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7718 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7719 SumTracks(seeds,arr);
7720 SignClusters(seeds,fnumber,fdensity);
7722 for (Int_t i=2;i<6;i+=2){
7723 // seed high pt tracks
7726 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7727 SumTracks(seeds,arr);
7728 SignClusters(seeds,fnumber,fdensity);
7733 // RemoveUsed(seeds,0.9,0.9,1);
7734 // UnsignClusters();
7735 // SignClusters(seeds,fnumber,fdensity);
7739 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7741 // seed high pt tracks
7745 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7746 SumTracks(seeds,arr);
7747 SignClusters(seeds,fnumber,fdensity);
7752 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7753 SumTracks(seeds,arr);
7754 SignClusters(seeds,fnumber,fdensity);
7765 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7769 // RemoveUsed(seeds,0.75,0.75,1);
7771 //SignClusters(seeds,fnumber,fdensity);
7780 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7781 SumTracks(seeds,arr);
7782 SignClusters(seeds,fnumber,fdensity);
7784 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7785 SumTracks(seeds,arr);
7786 SignClusters(seeds,fnumber,fdensity);
7788 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7789 SumTracks(seeds,arr);
7790 SignClusters(seeds,fnumber,fdensity);
7792 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7793 SumTracks(seeds,arr);
7794 SignClusters(seeds,fnumber,fdensity);
7796 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7797 SumTracks(seeds,arr);
7798 SignClusters(seeds,fnumber,fdensity);
7801 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7802 SumTracks(seeds,arr);
7803 SignClusters(seeds,fnumber,fdensity);
7807 for (Int_t delta = 9; delta<30; delta+=gapSec){
7813 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7814 SumTracks(seeds,arr);
7815 SignClusters(seeds,fnumber,fdensity);
7817 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7818 SumTracks(seeds,arr);
7819 SignClusters(seeds,fnumber,fdensity);
7832 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7838 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7839 SumTracks(seeds,arr);
7840 SignClusters(seeds,fnumber,fdensity);
7842 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7843 SumTracks(seeds,arr);
7844 SignClusters(seeds,fnumber,fdensity);
7848 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7859 TObjArray * AliTPCtracker::TrackingSpecial()
7862 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7863 // no primary vertex seeding tried
7867 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7869 TObjArray * seeds = new TObjArray;
7874 Float_t fnumber = 3.0;
7875 Float_t fdensity = 3.0;
7878 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7879 cuts[1] = 3.5; // max tan(phi) angle for seeding
7880 cuts[2] = 3.; // not used (cut on z primary vertex)
7881 cuts[3] = 3.5; // max tan(theta) angle for seeding
7883 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7885 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7886 SumTracks(seeds,arr);
7887 SignClusters(seeds,fnumber,fdensity);
7891 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7902 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7905 //sum tracks to common container
7906 //remove suspicious tracks
7907 // RS: Attention: supplied tracks come in the static array, don't delete them
7908 Int_t nseed = arr2->GetEntriesFast();
7909 for (Int_t i=0;i<nseed;i++){
7910 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7913 // remove tracks with too big curvature
7915 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7916 MarkSeedFree( arr2->RemoveAt(i) );
7919 // REMOVE VERY SHORT TRACKS
7920 if (pt->GetNumberOfClusters()<20){
7921 MarkSeedFree( arr2->RemoveAt(i) );
7924 // NORMAL ACTIVE TRACK
7925 if (pt->IsActive()){
7926 arr1->AddLast(arr2->RemoveAt(i));
7929 //remove not usable tracks
7930 if (pt->GetRemoval()!=10){
7931 MarkSeedFree( arr2->RemoveAt(i) );
7935 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7936 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7937 arr1->AddLast(arr2->RemoveAt(i));
7939 MarkSeedFree( arr2->RemoveAt(i) );
7943 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7948 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7951 // try to track in parralel
7953 Int_t nseed=arr->GetEntriesFast();
7954 //prepare seeds for tracking
7955 for (Int_t i=0; i<nseed; i++) {
7956 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7958 if (!t.IsActive()) continue;
7959 // follow prolongation to the first layer
7960 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7961 FollowProlongation(t, rfirst+1);
7966 for (Int_t nr=rfirst; nr>=rlast; nr--){
7967 if (nr<fInnerSec->GetNRows())
7968 fSectors = fInnerSec;
7970 fSectors = fOuterSec;
7971 // make indexes with the cluster tracks for given
7973 // find nearest cluster
7974 for (Int_t i=0; i<nseed; i++) {
7975 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7977 if (nr==80) pt->UpdateReference();
7978 if (!pt->IsActive()) continue;
7979 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7980 if (pt->GetRelativeSector()>17) {
7983 UpdateClusters(t,nr);
7985 // prolonagate to the nearest cluster - if founded
7986 for (Int_t i=0; i<nseed; i++) {
7987 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7989 if (!pt->IsActive()) continue;
7990 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7991 if (pt->GetRelativeSector()>17) {
7994 FollowToNextCluster(*pt,nr);
7999 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
8003 // if we use TPC track itself we have to "update" covariance
8005 Int_t nseed= arr->GetEntriesFast();
8006 for (Int_t i=0;i<nseed;i++){
8007 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8011 //rotate to current local system at first accepted point
8012 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
8013 Int_t sec = (index&0xff000000)>>24;
8015 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
8016 if (angle1>TMath::Pi())
8017 angle1-=2.*TMath::Pi();
8018 Float_t angle2 = pt->GetAlpha();
8020 if (TMath::Abs(angle1-angle2)>0.001){
8021 if (!pt->Rotate(angle1-angle2)) return;
8022 //angle2 = pt->GetAlpha();
8023 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
8024 //if (pt->GetAlpha()<0)
8025 // pt->fRelativeSector+=18;
8026 //sec = pt->fRelativeSector;
8035 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
8039 // if we use TPC track itself we have to "update" covariance
8041 Int_t nseed= arr->GetEntriesFast();
8042 for (Int_t i=0;i<nseed;i++){
8043 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8046 pt->SetFirstPoint(pt->GetLastPoint());
8054 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
8057 // make back propagation
8059 Int_t nseed= arr->GetEntriesFast();
8060 for (Int_t i=0;i<nseed;i++){
8061 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8062 if (pt&& pt->GetKinkIndex(0)<=0) {
8063 //AliTPCseed *pt2 = new AliTPCseed(*pt);
8064 fSectors = fInnerSec;
8065 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
8066 //fSectors = fOuterSec;
8067 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
8068 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
8069 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
8070 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
8073 if (pt&& pt->GetKinkIndex(0)>0) {
8074 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
8075 pt->SetFirstPoint(kink->GetTPCRow0());
8076 fSectors = fInnerSec;
8077 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
8085 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
8088 // make forward propagation
8090 Int_t nseed= arr->GetEntriesFast();
8092 for (Int_t i=0;i<nseed;i++){
8093 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8095 FollowProlongation(*pt,0,1,1);
8104 Int_t AliTPCtracker::PropagateForward()
8107 // propagate track forward
8109 Int_t nseed = fSeeds->GetEntriesFast();
8110 for (Int_t i=0;i<nseed;i++){
8111 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
8113 AliTPCseed &t = *pt;
8114 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
8115 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8116 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8117 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8121 fSectors = fOuterSec;
8122 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
8123 fSectors = fInnerSec;
8124 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
8133 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
8136 // make back propagation, in between row0 and row1
8140 fSectors = fInnerSec;
8143 if (row1<fSectors->GetNRows())
8146 r1 = fSectors->GetNRows()-1;
8148 if (row0<fSectors->GetNRows()&& r1>0 )
8149 FollowBackProlongation(*pt,r1);
8150 if (row1<=fSectors->GetNRows())
8153 r1 = row1 - fSectors->GetNRows();
8154 if (r1<=0) return 0;
8155 if (r1>=fOuterSec->GetNRows()) return 0;
8156 fSectors = fOuterSec;
8157 return FollowBackProlongation(*pt,r1);
8165 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
8167 // gets cluster shape
8169 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
8170 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
8171 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
8172 Double_t angulary = seed->GetSnp();
8174 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
8175 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
8178 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
8179 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
8181 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
8182 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
8183 seed->SetCurrentSigmaY2(sigmay*sigmay);
8184 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
8185 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
8186 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
8187 // Float_t padlength = GetPadPitchLength(row);
8189 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
8190 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
8192 // Float_t sresz = fkParam->GetZSigma();
8193 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
8195 Float_t wy = GetSigmaY(seed);
8196 Float_t wz = GetSigmaZ(seed);
8199 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
8200 printf("problem\n");
8207 //__________________________________________________________________________
8208 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
8209 //--------------------------------------------------------------------
8210 //This function "cooks" a track label. If label<0, this track is fake.
8211 //--------------------------------------------------------------------
8212 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
8214 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
8218 Int_t noc=t->GetNumberOfClusters();
8220 //printf("\nnot founded prolongation\n\n\n");
8226 AliTPCclusterMI *clusters[160];
8228 for (Int_t i=0;i<160;i++) {
8235 for (i=0; i<160 && current<noc; i++) {
8237 Int_t index=t->GetClusterIndex2(i);
8238 if (index<=0) continue;
8239 if (index&0x8000) continue;
8241 //clusters[current]=GetClusterMI(index);
8242 if (t->GetClusterPointer(i)){
8243 clusters[current]=t->GetClusterPointer(i);
8249 Int_t lab=123456789;
8250 for (i=0; i<noc; i++) {
8251 AliTPCclusterMI *c=clusters[i];
8253 lab=TMath::Abs(c->GetLabel(0));
8255 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8261 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8263 for (i=0; i<noc; i++) {
8264 AliTPCclusterMI *c=clusters[i];
8266 if (TMath::Abs(c->GetLabel(1)) == lab ||
8267 TMath::Abs(c->GetLabel(2)) == lab ) max++;
8269 if (noc<=0) { lab=-1; return;}
8270 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8273 Int_t tail=Int_t(0.10*noc);
8276 for (i=1; i<160&&ind<tail; i++) {
8277 // AliTPCclusterMI *c=clusters[noc-i];
8278 AliTPCclusterMI *c=clusters[i];
8280 if (lab == TMath::Abs(c->GetLabel(0)) ||
8281 lab == TMath::Abs(c->GetLabel(1)) ||
8282 lab == TMath::Abs(c->GetLabel(2))) max++;
8285 if (max < Int_t(0.5*tail)) lab=-lab;
8292 //delete[] clusters;
8296 //__________________________________________________________________________
8297 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
8298 //--------------------------------------------------------------------
8299 //This function "cooks" a track label. If label<0, this track is fake.
8300 //--------------------------------------------------------------------
8301 Int_t noc=t->GetNumberOfClusters();
8303 //printf("\nnot founded prolongation\n\n\n");
8309 AliTPCclusterMI *clusters[160];
8311 for (Int_t i=0;i<160;i++) {
8318 for (i=0; i<160 && current<noc; i++) {
8319 if (i<first) continue;
8320 if (i>last) continue;
8321 Int_t index=t->GetClusterIndex2(i);
8322 if (index<=0) continue;
8323 if (index&0x8000) continue;
8325 //clusters[current]=GetClusterMI(index);
8326 if (t->GetClusterPointer(i)){
8327 clusters[current]=t->GetClusterPointer(i);
8332 //if (noc<5) return -1;
8333 Int_t lab=123456789;
8334 for (i=0; i<noc; i++) {
8335 AliTPCclusterMI *c=clusters[i];
8337 lab=TMath::Abs(c->GetLabel(0));
8339 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8345 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8347 for (i=0; i<noc; i++) {
8348 AliTPCclusterMI *c=clusters[i];
8350 if (TMath::Abs(c->GetLabel(1)) == lab ||
8351 TMath::Abs(c->GetLabel(2)) == lab ) max++;
8353 if (noc<=0) { lab=-1; return -1;}
8354 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8357 Int_t tail=Int_t(0.10*noc);
8360 for (i=1; i<160&&ind<tail; i++) {
8361 // AliTPCclusterMI *c=clusters[noc-i];
8362 AliTPCclusterMI *c=clusters[i];
8364 if (lab == TMath::Abs(c->GetLabel(0)) ||
8365 lab == TMath::Abs(c->GetLabel(1)) ||
8366 lab == TMath::Abs(c->GetLabel(2))) max++;
8369 if (max < Int_t(0.5*tail)) lab=-lab;
8372 // t->SetLabel(lab);
8376 //delete[] clusters;
8380 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
8382 //return pad row number for given x vector
8383 Float_t phi = TMath::ATan2(x[1],x[0]);
8384 if(phi<0) phi=2.*TMath::Pi()+phi;
8385 // Get the local angle in the sector philoc
8386 const Float_t kRaddeg = 180/3.14159265358979312;
8387 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
8388 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
8389 return GetRowNumber(localx);
8394 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
8396 //-----------------------------------------------------------------------
8397 // Fill the cluster and sharing bitmaps of the track
8398 //-----------------------------------------------------------------------
8400 Int_t firstpoint = 0;
8401 Int_t lastpoint = 159;
8402 AliTPCTrackerPoint *point;
8403 AliTPCclusterMI *cluster;
8406 TBits clusterMap(159);
8407 TBits sharedMap(159);
8409 for (int iter=firstpoint; iter<lastpoint; iter++) {
8410 // Change to cluster pointers to see if we have a cluster at given padrow
8412 cluster = t->GetClusterPointer(iter);
8414 clusterMap.SetBitNumber(iter, kTRUE);
8415 point = t->GetTrackPoint(iter);
8416 if (point->IsShared())
8417 sharedMap.SetBitNumber(iter,kTRUE);
8419 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
8420 fitMap.SetBitNumber(iter, kTRUE);
8424 esd->SetTPCClusterMap(clusterMap);
8425 esd->SetTPCSharedMap(sharedMap);
8426 esd->SetTPCFitMap(fitMap);
8427 if (nclsf != t->GetNumberOfClusters())
8428 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
8431 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
8433 // return flag if there is findable cluster at given position
8436 Float_t z = track.GetZ();
8438 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
8439 TMath::Abs(z)<fkParam->GetZLength(0) &&
8440 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
8446 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
8448 // Adding systematic error estimate to the covariance matrix
8449 // !!!! the systematic error for element 4 is in 1/GeV
8450 // 03.03.2012 MI changed in respect to the previous versions
8451 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8453 // use only the diagonal part if not specified otherwise
8454 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
8456 Double_t *covarS= (Double_t*)seed->GetCovariance();
8457 Double_t factor[5]={1,1,1,1,1};
8458 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
8459 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
8460 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
8461 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
8462 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
8464 factor[0]=factor[2];
8465 factor[4]=factor[2];
8471 for (Int_t i=0; i<5; i++){
8472 for (Int_t j=i; j<5; j++){
8473 Int_t index=seed->GetIndex(i,j);
8474 covarS[index]*=factor[i]*factor[j];
8480 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
8482 // Adding systematic error - as additive factor without correlation
8484 // !!!! the systematic error for element 4 is in 1/GeV
8485 // 03.03.2012 MI changed in respect to the previous versions
8487 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8488 Double_t *covarIn= (Double_t*)seed->GetCovariance();
8490 for (Int_t i=0;i<15;i++) covar[i]=0;
8496 covar[0] = param[0]*param[0];
8497 covar[2] = param[1]*param[1];
8498 covar[5] = param[2]*param[2];
8499 covar[9] = param[3]*param[3];
8500 covar[14]= param[4]*param[4];
8502 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
8504 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
8505 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
8507 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
8508 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
8509 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
8511 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
8512 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
8513 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
8514 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
8516 seed->AddCovariance(covar);
8519 //_____________________________________________________________________________
8520 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8523 // check events affected by TPC HV dip
8525 if(!esdEvent) return kFALSE;
8528 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8529 if(!db) return kFALSE;
8530 db->SetRun(esdEvent->GetRunNumber());
8532 // maximum allowed voltage before an event is identified as a dip event
8533 // and scanning period
8534 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8535 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8536 const Double_t tevSec = esdEvent->GetTimeStamp();
8538 for(Int_t sector=0; sector<72; sector++)
8540 // don't use excluded chambers, since the state is not defined at all
8541 if (!db->GetChamberHVStatus(sector)) continue;
8543 // get hv sensor of the chamber
8544 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8545 if (!sensor) continue;
8546 TGraph *grSensor=sensor->GetGraph();
8547 if (!grSensor) continue;
8548 if (grSensor->GetN()<1) continue;
8551 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8552 if(median < 1.) continue;
8554 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8555 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8556 if (tevSec-dipEventScanPeriod>nextTime) continue;
8557 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8558 if (deltaV>kTPCHVdip) {
8559 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8562 if (nextTime>tevSec+dipEventScanPeriod) break;
8569 //________________________________________
8570 void AliTPCtracker::MarkSeedFree(TObject *sd)
8572 // account that this seed is "deleted"
8573 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8575 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8578 int id = seed->GetPoolID();
8580 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8583 // AliInfo(Form("%d %p",id, seed));
8584 fSeedsPool->RemoveAt(id);
8585 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8586 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8589 //________________________________________
8590 TObject *&AliTPCtracker::NextFreeSeed()
8592 // return next free slot where the seed can be created
8593 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8594 // AliInfo(Form("%d",fLastSeedID));
8595 return (*fSeedsPool)[ fLastSeedID ];
8599 //________________________________________
8600 void AliTPCtracker::ResetSeedsPool()
8602 // mark all seeds in the pool as unused
8603 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8605 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8608 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8611 Double_t x= GetXrow(nrow);
8612 Double_t ymax= GetMaxY(nrow);
8618 if (!t.PropagateTo(x) ){
8619 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8625 Double_t y = t.GetY();
8627 if( rotate!=-1 ) rotate=1;
8628 } else if (y <-ymax) {
8629 if( rotate!=1 ) rotate = -1;
8631 if( rotate==0 ) break;
8632 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8633 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8634 //cout<<"can't rotate "<<endl;
8638 nRotations+= rotate;
8640 if( nRotations!=0 ){
8641 int newSec= t.GetRelativeSector()+nRotations;
8642 if( newSec>=fN ) newSec-=fN;
8643 else if( newSec<0 ) newSec +=fN;
8644 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8645 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8646 t.SetRelativeSector(newSec);
8651 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8654 // try to track in parralel
8656 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8659 Int_t nseed=arr->GetEntriesFast();
8660 //cout<<"Parallel tracking My.."<<endl;
8661 double shapeY2[160], shapeZ2[160];
8662 Int_t clusterIndex[160];
8664 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8665 //if( iSeed!=1 ) continue;
8666 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8670 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8674 for( int iter=0; iter<3; iter++ ){
8677 t.SetLastPoint(0); // first cluster in track position
8678 t.SetFirstPoint(nRows-1);
8679 t.ResetCovariance(.1);
8680 t.SetNumberOfClusters(0);
8681 for( int i=0; i<nRows; i++ ){
8685 t.SetClusterIndex2(i,-1);
8686 t.SetClusterIndex(i,-1);
8689 // pick up the clusters
8691 Double_t roady = 20.;
8692 Double_t roadz = 20.;
8699 t0.SetRelativeSector(t.GetRelativeSector());
8700 t0.SetLastPoint(0); // first cluster in track position
8701 t0.SetFirstPoint(159);
8702 for (Int_t nr=0; nr<nRows; nr++){
8703 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8704 else fSectors=fOuterSec;
8706 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8707 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8708 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8711 if (!IsActive(t0.GetRelativeSector(),nr)) {
8717 shapeY2[nr]=t0.GetCurrentSigmaY2();
8718 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8721 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8722 if( !krow ) continue;
8724 t.SetClusterIndex2(nr,-3); // foundable
8725 t.SetClusterIndex(nr,-3);
8727 AliTPCclusterMI *cl=0;
8729 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8731 double dy = cl->GetY()-t0.GetY();
8732 double dz = cl->GetZ()-t0.GetZ();
8733 double dr = sqrt(dy*dy+dz*dz);
8735 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8738 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8740 t0.SetClusterPointer(nr, cl);
8741 clusterIndex[nr] = krow.GetIndex(uindex);
8742 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8743 t0.SetLastPoint(nr);
8749 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8752 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8756 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8758 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8759 if( !t0.GetClusterPointer(nr) ) continue;
8760 int d = TMath::Abs(nr-midRow);
8768 // first fit 3 base points
8770 //cout<<"Fit3: "<<endl;
8771 for( int icl=0; icl<3; icl++){
8772 int nr = basePoints[icl];
8774 if( nr>=fInnerSec->GetNRows()){
8775 lr = nr - fInnerSec->GetNRows();
8777 } else fSectors=fInnerSec;
8779 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8781 //cout<<"WRONG!!!!"<<endl;
8784 int iSec = cl->GetDetector() %fkNIS;
8785 int rotate = iSec - t.GetRelativeSector();
8787 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8788 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8789 //cout<<"can't rotate "<<endl;
8792 t.SetRelativeSector(iSec);
8794 Double_t x= cl->GetX();
8795 if (!t.PropagateTo(x)){
8796 //cout<<"can't propagate to x="<<x<<endl;
8800 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8801 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8804 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8806 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8807 t.SetCurrentCluster(cl);
8810 t.SetErrorY2(shapeY2[nr]);
8811 t.SetErrorZ2(shapeZ2[nr]);
8814 for( int j=0; j<15; j++ ) cov[j]=0;
8820 t.AliExternalTrackParam::AddCovariance(cov);
8822 if( !UpdateTrack(&t,0) ){
8823 //cout<<"Can not update"<<endl;
8825 t.SetClusterIndex2(nr,-1);
8826 t.SetClusterIndex(nr,-1);
8827 t.SetClusterPointer(nr,0);
8830 //t.SetClusterPointer(nr, cl);
8833 //t.SetLastPoint(t0.GetLastPoint());
8834 //t.SetFirstPoint(t0.GetFirstPoint());
8836 //cout<<"Fit: "<<endl;
8837 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8839 if( nr>=fInnerSec->GetNRows()){
8840 lr = nr - fInnerSec->GetNRows();
8842 } else fSectors=fInnerSec;
8845 if( nr == basePoints[0] ) continue;
8846 if( nr == basePoints[1] ) continue;
8847 if( nr == basePoints[2] ) continue;
8849 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8852 int iSec = cl->GetDetector() %fkNIS;
8853 int rotate = iSec - t.GetRelativeSector();
8855 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8856 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8857 //cout<<"can't rotate "<<endl;
8860 t.SetRelativeSector(iSec);
8862 Double_t x= cl->GetX();
8863 if (!t.PropagateTo(x)){
8864 //cout<<"can't propagate to x="<<x<<endl;
8867 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8868 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8872 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8874 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8875 t.SetCurrentCluster(cl);
8877 t.SetErrorY2(shapeY2[nr]);
8878 t.SetErrorZ2(shapeZ2[nr]);
8880 if( !UpdateTrack(&t,0) ){
8881 //cout<<"Can not update"<<endl;
8883 t.SetClusterIndex2(nr,-1);
8884 t.SetClusterIndex(nr,-1);
8887 //t.SetClusterPointer(nr, cl);
8890 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8893 //cout<<"fitted track"<<iSeed<<endl;
8895 //cout<<"Statistics: "<<endl;
8896 Int_t foundable,found,shared;
8897 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8898 t.SetNFoundable(foundable);
8899 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8905 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8910 if( !hltEvent ) return 0;
8913 Int_t nentr=hltEvent->GetNumberOfTracks();
8915 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8917 TObjArray * seeds = new TObjArray(nentr);
8919 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8922 Int_t nTr=hltEvent->GetNumberOfTracks();
8924 for( int itr=0; itr<nTr; itr++ ){
8925 //if( itr!=97 ) continue;
8926 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8927 if( !param ) continue;
8928 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8929 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8931 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8932 tr.SetNumberOfClusters(0);
8933 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8935 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8936 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8937 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8939 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8940 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8942 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8943 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8945 seed->Rotate(alphaSec - alpha);
8947 seed->SetPoolID(fLastSeedID);
8948 seed->SetIsSeeding(kTRUE);
8949 seed->SetSeed1(nup-1);
8950 seed->SetSeed2(nup-2);
8951 seed->SetSeedType(0);
8952 seed->SetFirstPoint(-1);
8953 seed->SetLastPoint(-1);
8954 seeds->AddLast(seed); // note, track is seed, don't free the seed
8956 //if( index>3 ) break;
8960 fSectors = fOuterSec;
8962 TrackFollowingHLT(seeds );
8964 nTr = seeds->GetEntriesFast();
8965 for( int itr=0; itr<nTr; itr++ ){
8966 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8967 if( !seed ) continue;
8968 //FollowBackProlongation(*seed,0);
8969 // cout<<seed->GetNumberOfClusters()<<endl;
8970 Int_t foundable,found,shared;
8971 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8972 seed->SetNFoundable(foundable);
8973 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8974 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8975 //MarkSeedFree(seeds->RemoveAt(itr));
8978 if (seed->GetNumberOfClusters()<30 ||
8979 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8980 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8981 MarkSeedFree(seeds->RemoveAt(itr));
8985 for( int ir=0; ir<nup; ir++){
8986 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8990 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8994 void AliTPCtracker::FillClusterOccupancyInfo()
8996 //fill the cluster occupancy info into the ESD friend
8997 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8998 if (!esdFriend) return;
9000 for (Int_t isector=0; isector<18; isector++){
9001 AliTPCtrackerSector &iroc = fInnerSec[isector];
9002 AliTPCtrackerSector &oroc = fOuterSec[isector];
9004 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
9005 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
9006 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
9007 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
9008 //clusters used in tracking
9009 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
9010 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
9011 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
9012 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));