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(){
1415 const Int_t nROCs = 72;
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<2;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=36+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
1493 for (Int_t isector=0; isector<nROCs*4; isector++){ //set all ellemts of crosstalk matrix to 0
1494 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1495 TMatrixD * crossTalkMatrixCache = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs*2);
1496 if (crossTalkMatrix){
1497 (*crossTalkMatrixCache)*=0;
1498 (*crossTalkMatrixCache)+=(*crossTalkMatrix);
1501 } // end of 2 iterations
1504 // 2.) dump the crosstalk matrices to tree for further investigation
1505 // a.) to estimate fluctuation of pedestal in indiviula wire segments
1506 // b.) to check correlation between regions
1507 // c.) to check relative conribution of signal below threshold to crosstalk
1509 if (AliTPCReconstructor::StreamLevel()&kStreamCrosstalkMatrix) {
1510 for (Int_t isector=0; isector<nROCs; isector++){ //set all ellemts of crosstalk matrix to 0
1511 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1512 TMatrixD * crossTalkMatrixBelow = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs);
1513 TVectorD vecAll(crossTalkMatrix->GetNrows());
1514 TVectorD vecBelow(crossTalkMatrix->GetNrows());
1516 for (Int_t itime=0; itime<crossTalkMatrix->GetNcols(); itime++){
1517 for (Int_t iwire=0; iwire<crossTalkMatrix->GetNrows(); iwire++){
1518 vecAll[iwire]=(*crossTalkMatrix)(iwire,itime);
1519 vecBelow[iwire]=(*crossTalkMatrixBelow)(iwire,itime);
1521 (*fDebugStreamer)<<"crosstalkMatrix"<<
1522 "sector="<<isector<<
1524 "vecAll.="<<&vecAll<< // crosstalk charge + charge below threshold
1525 "vecBelow.="<<&vecBelow<< // crosstalk contribution from signal below threshold
1538 void AliTPCtracker::FilterOutlierClusters(){
1540 // filter outlier clusters
1543 1.)..... booking part
1545 nTimeBins=fParam->Get....
1546 TH2F hisTime("","", sector,0,sector, nTimeBins,0,nTimeBins);
1547 TH2F hisPadRow("","", sector,0,sector, nPadRows,0,nPadRows);
1548 2.) .... filling part
1549 .... cluster loop { hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin()); }
1551 3.) ...filtering part
1552 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... }
1555 { 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 }
1557 4. Disabling clusters
1564 // AliTPCcalibDB *db=AliTPCcalibDB::Instance();
1565 Int_t nSectors=AliTPCROC::Instance()->GetNSectors();
1566 Int_t nTimeBins= 1100; // *Bug here - we should get NTimeBins from ALTRO - Parameters not relyable
1567 Int_t nPadRows=(AliTPCROC::Instance()->GetNRows(0) + AliTPCROC::Instance()->GetNRows(36));
1568 // parameters for filtering
1569 const Double_t nSigmaCut=9.; // should be in recoParam ?
1570 const Double_t offsetTime=100; // should be in RecoParam ? -
1571 const Double_t offsetPadRow=300; // should be in RecoParam ?
1572 const Double_t offsetTimeAccept=8; // should be in RecoParam ? - obtained as mean +1 rms in high IR pp
1573 TH2F hisTime("hisSectorTime","hisSectorTime", nSectors,0,nSectors, nTimeBins,0,nTimeBins);
1574 TH2F hisPadRow("hisSectorRow","hisSectorRow", nSectors,0,nSectors, nPadRows,0,nPadRows);
1576 // 2.) Filling part -- loop over clusters
1578 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1579 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1580 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1581 Int_t nrows = sector.GetNRows();
1582 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1583 AliTPCtrackerRow& tpcrow = sector[row];
1584 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1585 if (iside>0) ncl=tpcrow.GetN2();
1586 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1587 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1588 hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin());
1589 hisPadRow.Fill(cluster->GetDetector(),cluster->GetRow());
1596 // 3. Filtering part
1598 TVectorD vecTime(nTimeBins);
1599 TVectorD vecPadRow(nPadRows);
1600 TVectorD vecMedianSectorTime(nSectors);
1601 TVectorD vecRMSSectorTime(nSectors);
1602 TVectorD vecMedianSectorTimeOut6(nSectors);
1603 TVectorD vecMedianSectorTimeOut9(nSectors);//
1604 TVectorD vecMedianSectorTimeOut(nSectors);//
1605 TVectorD vecMedianSectorPadRow(nSectors);
1606 TVectorD vecRMSSectorPadRow(nSectors);
1607 TVectorD vecMedianSectorPadRowOut6(nSectors);
1608 TVectorD vecMedianSectorPadRowOut9(nSectors);
1609 TVectorD vecMedianSectorPadRowOut(nSectors);
1610 TVectorD vecSectorOut6(nSectors);
1611 TVectorD vecSectorOut9(nSectors);
1612 TMatrixD matSectorCluster(nSectors,2);
1614 // 3.a) median, rms calculations for hisTime
1616 for (Int_t isec=0; isec<nSectors; isec++){
1617 vecMedianSectorTimeOut6[isec]=0;
1618 vecMedianSectorTimeOut9[isec]=0;
1619 for (Int_t itime=0; itime<nTimeBins; itime++){
1620 vecTime[itime]=hisTime.GetBinContent(isec+1, itime+1);
1622 Double_t median= TMath::Mean(nTimeBins,vecTime.GetMatrixArray());
1623 Double_t rms= TMath::RMS(nTimeBins,vecTime.GetMatrixArray());
1624 vecMedianSectorTime[isec]=median;
1625 vecRMSSectorTime[isec]=rms;
1626 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector TimeStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
1629 for (Int_t itime=0; itime<nTimeBins; itime++){
1630 Double_t entries= hisTime.GetBinContent(isec+1, itime+1);
1631 if (entries>median+6.*rms+offsetTime) {
1632 vecMedianSectorTimeOut6[isec]+=1;
1634 if (entries>median+9.*rms+offsetTime) {
1635 vecMedianSectorTimeOut9[isec]+=1;
1640 // 3.b) median, rms calculations for hisPadRow
1642 for (Int_t isec=0; isec<nSectors; isec++){
1643 vecMedianSectorPadRowOut6[isec]=0;
1644 vecMedianSectorPadRowOut9[isec]=0;
1645 for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
1646 vecPadRow[ipadrow]=hisPadRow.GetBinContent(isec+1, ipadrow+1);
1648 Int_t nPadRowsSector= AliTPCROC::Instance()->GetNRows(isec);
1649 Double_t median= TMath::Mean(nPadRowsSector,vecPadRow.GetMatrixArray());
1650 Double_t rms= TMath::RMS(nPadRowsSector,vecPadRow.GetMatrixArray());
1651 vecMedianSectorPadRow[isec]=median;
1652 vecRMSSectorPadRow[isec]=rms;
1653 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector PadRowStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
1656 for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
1657 Double_t entries= hisPadRow.GetBinContent(isec+1, ipadrow+1);
1658 if (entries>median+6.*rms+offsetPadRow) {
1659 vecMedianSectorPadRowOut6[isec]+=1;
1661 if (entries>median+9.*rms+offsetPadRow) {
1662 vecMedianSectorPadRowOut9[isec]+=1;
1667 // 3.c) filter outlier sectors
1669 Double_t medianSectorTime = TMath::Median(nSectors, vecTime.GetMatrixArray());
1670 Double_t mean69SectorTime, rms69SectorTime=0;
1671 AliMathBase::EvaluateUni(nSectors, vecTime.GetMatrixArray(), mean69SectorTime,rms69SectorTime,69);
1672 for (Int_t isec=0; isec<nSectors; isec++){
1673 vecSectorOut6[isec]=0;
1674 vecSectorOut9[isec]=0;
1675 matSectorCluster(isec,0)=0;
1676 matSectorCluster(isec,1)=0;
1677 if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+6.*(rms69SectorTime+ offsetTimeAccept))) {
1678 vecSectorOut6[isec]=1;
1680 if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+9.*(rms69SectorTime+ offsetTimeAccept))){
1681 vecSectorOut9[isec]=1;
1684 // light version of export variable
1685 Int_t filteredSector= vecSectorOut9.Sum(); // light version of export variable
1686 Int_t filteredSectorTime= vecMedianSectorTimeOut9.Sum();
1687 Int_t filteredSectorPadRow= vecMedianSectorPadRowOut9.Sum();
1688 if (fEvent) if (fEvent->GetHeader()){
1689 fEvent->GetHeader()->SetTPCNoiseFilterCounter(0,TMath::Min(filteredSector,255));
1690 fEvent->GetHeader()->SetTPCNoiseFilterCounter(1,TMath::Min(filteredSectorTime,255));
1691 fEvent->GetHeader()->SetTPCNoiseFilterCounter(2,TMath::Min(filteredSectorPadRow,255));
1695 // 4. Disabling clusters in outlier layers
1699 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1700 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1701 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1702 Int_t nrows = sector.GetNRows();
1703 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1704 AliTPCtrackerRow& tpcrow = sector[row];
1705 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1706 if (iside>0) ncl=tpcrow.GetN2();
1707 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1708 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1709 Double_t medianTime=vecMedianSectorTime[cluster->GetDetector()];
1710 Double_t medianPadRow=vecMedianSectorPadRow[cluster->GetDetector()];
1711 Double_t rmsTime=vecRMSSectorTime[cluster->GetDetector()];
1712 Double_t rmsPadRow=vecRMSSectorPadRow[cluster->GetDetector()];
1713 Int_t entriesPadRow=hisPadRow.GetBinContent(cluster->GetDetector()+1, cluster->GetRow()+1);
1714 Int_t entriesTime=hisTime.GetBinContent(cluster->GetDetector()+1, cluster->GetTimeBin()+1);
1715 Bool_t isOut=kFALSE;
1716 if (vecSectorOut9[cluster->GetDetector()]>0.5) {
1720 if (entriesTime>medianTime+nSigmaCut*rmsTime+offsetTime) {
1722 vecMedianSectorTimeOut[cluster->GetDetector()]++;
1724 if (entriesPadRow>medianPadRow+nSigmaCut*rmsPadRow+offsetPadRow) {
1726 vecMedianSectorPadRowOut[cluster->GetDetector()]++;
1729 matSectorCluster(cluster->GetDetector(),0)+=1;
1733 matSectorCluster(cluster->GetDetector(),1)+=1;
1739 for (Int_t isec=0; isec<nSectors; isec++){
1740 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());
1743 // dump info to streamer - for later tuning of cuts
1745 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) { // stream TPC data ouliers filtering infomation
1747 AliInfo(TString::Format("Cluster counter: (%d/%d) (Filtered/All)",counterOut,counterAll).Data());
1748 for (Int_t iSec=0; iSec<nSectors; iSec++){
1749 if (vecSectorOut9[iSec]>0 || matSectorCluster(iSec,1)>0) {
1750 AliInfo(TString::Format("Filtered sector\t%d",iSec).Data());
1751 Double_t vecMedTime =TMath::Median(72,vecMedianSectorTime.GetMatrixArray());
1752 Double_t vecMedPadRow =TMath::Median(72,vecMedianSectorPadRow.GetMatrixArray());
1753 Double_t vecMedCluster=(counterAll-counterOut)/72;
1754 AliInfo(TString::Format("VecMedianSectorTime\t(%4.4f/%4.4f/%4.4f)", vecMedianSectorTimeOut[iSec],vecMedianSectorTime[iSec],vecMedTime).Data());
1755 AliInfo(TString::Format("VecMedianSectorPadRow\t(%4.4f/%4.4f/%4.4f)", vecMedianSectorPadRowOut[iSec],vecMedianSectorPadRow[iSec],vecMedPadRow).Data());
1756 AliInfo(TString::Format("MatSectorCluster\t(%4.4f/%4.4f/%4.4f)\n", matSectorCluster(iSec,1), matSectorCluster(iSec,0), vecMedCluster).Data());
1761 Int_t eventNr = fEvent->GetEventNumberInFile();
1762 (*fDebugStreamer)<<"filterClusterInfo"<<
1763 // minimal set variables for the ESDevent
1764 "eventNr="<<eventNr<<
1765 "counterAll="<<counterAll<<
1766 "counterOut="<<counterOut<<
1767 "matSectotCluster.="<<&matSectorCluster<< //
1769 "filteredSector="<<filteredSector<< // counter filtered sectors
1770 "filteredSectorTime="<<filteredSectorTime<< // counter filtered time bins
1771 "filteredSectorPadRow="<<filteredSectorPadRow<< // counter filtered pad-rows
1772 // per sector outlier information
1773 "medianSectorTime="<<medianSectorTime<< // median number of clusters per sector/timebin
1774 "mean69SectorTime="<<mean69SectorTime<< // LTM statistic mean of clusters per sector/timebin
1775 "rms69SectorTime="<<rms69SectorTime<< // LTM statistic RMS of clusters per sector/timebin
1776 "vecSectorOut6.="<<&vecSectorOut6<< // flag array sector - 6 sigma +accept margin outlier
1777 "vecSectorOut9.="<<&vecSectorOut9<< // flag array sector - 9 sigma + accept margin outlier
1778 // per sector/timebin outlier detection
1779 "vecMedianSectorTime.="<<&vecMedianSectorTime<<
1780 "vecRMSSectorTime.="<<&vecRMSSectorTime<<
1781 "vecMedianSectorTimeOut6.="<<&vecMedianSectorTimeOut6<<
1782 "vecMedianSectorTimeOut9.="<<&vecMedianSectorTimeOut9<<
1783 "vecMedianSectorTimeOut0.="<<&vecMedianSectorTimeOut<<
1784 // per sector/pad-row outlier detection
1785 "vecMedianSectorPadRow.="<<&vecMedianSectorPadRow<<
1786 "vecRMSSectorPadRow.="<<&vecRMSSectorPadRow<<
1787 "vecMedianSectorPadRowOut6.="<<&vecMedianSectorPadRowOut6<<
1788 "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut9<<
1789 "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut<<
1791 ((*fDebugStreamer)<<"filterClusterInfo").GetTree()->Write();
1792 fDebugStreamer->GetFile()->Flush();
1796 void AliTPCtracker::UnloadClusters()
1799 // unload clusters from the memory
1801 Int_t nrows = fOuterSec->GetNRows();
1802 for (Int_t sec = 0;sec<fkNOS;sec++)
1803 for (Int_t row = 0;row<nrows;row++){
1804 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1806 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1807 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1809 tpcrow->ResetClusters();
1812 nrows = fInnerSec->GetNRows();
1813 for (Int_t sec = 0;sec<fkNIS;sec++)
1814 for (Int_t row = 0;row<nrows;row++){
1815 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1817 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1818 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1820 tpcrow->ResetClusters();
1826 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1828 // Filling cluster to the array - For visualization purposes
1831 nrows = fOuterSec->GetNRows();
1832 for (Int_t sec = 0;sec<fkNOS;sec++)
1833 for (Int_t row = 0;row<nrows;row++){
1834 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1835 if (!tpcrow) continue;
1836 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1837 array->AddLast((TObject*)((*tpcrow)[icl]));
1840 nrows = fInnerSec->GetNRows();
1841 for (Int_t sec = 0;sec<fkNIS;sec++)
1842 for (Int_t row = 0;row<nrows;row++){
1843 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1844 if (!tpcrow) continue;
1845 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1846 array->AddLast((TObject*)(*tpcrow)[icl]);
1852 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1856 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1857 AliTPCTransform *transform = calibDB->GetTransform() ;
1859 AliFatal("Tranformations not in calibDB");
1862 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1863 Double_t x[3]={static_cast<Double_t>(cluster->GetRow()),static_cast<Double_t>(cluster->GetPad()),static_cast<Double_t>(cluster->GetTimeBin())};
1864 Int_t i[1]={cluster->GetDetector()};
1865 transform->Transform(x,i,0,1);
1866 // if (cluster->GetDetector()%36>17){
1871 // in debug mode check the transformation
1873 if ((AliTPCReconstructor::StreamLevel()&kStreamTransform)>0) {
1875 cluster->GetGlobalXYZ(gx);
1876 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1877 TTreeSRedirector &cstream = *fDebugStreamer;
1878 cstream<<"Transform"<< // needed for debugging of the cluster transformation, resp. used for later visualization
1889 cluster->SetX(x[0]);
1890 cluster->SetY(x[1]);
1891 cluster->SetZ(x[2]);
1896 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1897 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1898 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1900 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1901 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1902 if (mat) mat->LocalToMaster(pos,posC);
1904 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1906 cluster->SetX(posC[0]);
1907 cluster->SetY(posC[1]);
1908 cluster->SetZ(posC[2]);
1912 void AliTPCtracker::ApplyXtalkCorrection(){
1914 // ApplyXtalk correction
1915 // Loop over all clusters
1916 // add to each cluster signal corresponding to common Xtalk mode for given time bin at given wire segment
1918 for (Int_t isector=0; isector<36; isector++){ //loop tracking sectors
1919 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1920 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1921 Int_t nrows = sector.GetNRows();
1922 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1923 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1924 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1925 if (iside>0) ncl=tpcrow.GetN2();
1926 Int_t xSector=0; // sector number in the TPC convention 0-72
1927 if (isector<18){ //if IROC
1928 xSector=isector+(iside>0)*18;
1930 xSector=isector+18; // isector -18 +36
1931 if (iside>0) xSector+=18;
1933 TMatrixD &crossTalkMatrix= *((TMatrixD*)fCrossTalkSignalArray->At(xSector));
1934 Int_t wireSegmentID = fkParam->GetWireSegment(xSector,row);
1935 for (Int_t i=0;i<ncl;i++) {
1936 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1937 Int_t iTimeBin=TMath::Nint(cluster->GetTimeBin());
1938 Double_t xTalk= crossTalkMatrix[wireSegmentID][iTimeBin];
1939 cluster->SetMax(cluster->GetMax()+xTalk);
1940 const Double_t kDummy=4;
1941 Double_t sumxTalk=xTalk*kDummy; // should be calculated via time response function
1942 cluster->SetQ(cluster->GetQ()+sumxTalk);
1945 if ((AliTPCReconstructor::StreamLevel()&kStreamXtalk)>0) { // flag: stream crosstalk correctio as applied to cluster
1946 TTreeSRedirector &cstream = *fDebugStreamer;
1947 if (gRandom->Rndm() > 0.){
1949 "isector=" << isector << // sector [0,36]
1950 "iside=" << iside << // side A or C
1951 "row=" << row << // padrow
1952 "i=" << i << // index of the cluster
1953 "xSector=" << xSector << // sector [0,72]
1954 "wireSegmentID=" << wireSegmentID << // anode wire segment id [0,10]
1955 "iTimeBin=" << iTimeBin << // timebin of the corrected cluster
1956 "xTalk=" << xTalk << // Xtalk contribution added to Qmax
1957 "sumxTalk=" << sumxTalk << // Xtalk contribution added to Qtot (roughly 3*Xtalk)
1958 "cluster.=" << cluster << // corrected cluster object
1961 }// dump the results to the debug streamer if in debug mode
1973 void AliTPCtracker::ApplyTailCancellation(){
1975 // Correct the cluster charge for the ion tail effect
1976 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1980 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1981 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1982 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1983 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1984 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1985 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1987 // find the number of clusters for the whole TPC (nclALL)
1989 for (Int_t isector=0; isector<36; isector++){
1990 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1991 nclALL += sector.GetNClInSector(0);
1992 nclALL += sector.GetNClInSector(1);
1995 // start looping over all clusters
1996 for (Int_t iside=0; iside<2; iside++){ // loop over sides
1999 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
2000 // cache experimantal tuning factor for the different chamber type
2001 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
2002 std::cout << " ampfactor = " << ampfactor << std::endl;
2004 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
2007 // Cache time response functions and their positons to COG of the cluster
2008 TGraphErrors ** graphRes = new TGraphErrors *[20];
2009 Float_t * indexAmpGraphs = new Float_t[20];
2010 for (Int_t icache=0; icache<20; icache++)
2012 graphRes[icache] = NULL;
2013 indexAmpGraphs[icache] = 0;
2015 ///////////////////////////// --> position fo sie loop
2016 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
2021 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
2022 Int_t nrows = sector.GetNRows(); // number of rows
2023 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
2025 for (Int_t row = 0;row<nrows;row++){ // loop over rows
2027 AliTPCtrackerRow& tpcrow = sector[row]; // row object
2028 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
2029 if (iside>0) ncl=tpcrow.GetN2();
2031 // Order clusters in time for the proper correction of ion tail
2032 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
2033 Float_t qMaxArray[ncl];
2034 Int_t sortedClusterIndex[ncl];
2035 Float_t sortedClusterTimeBin[ncl];
2036 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
2037 for (Int_t i=0;i<ncl;i++)
2041 sortedClusterIndex[i]=i;
2042 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
2044 rowClusterArray->AddAt(rowcl,i);
2046 rowClusterArray->RemoveAt(i);
2048 // Fill the timebin info to the array in order to sort wrt tb
2050 sortedClusterTimeBin[i]=0.0;
2052 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
2056 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
2058 // Main cluster correction loops over clusters
2059 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
2061 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
2065 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
2066 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
2068 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
2069 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
2070 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
2072 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
2074 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
2075 Double_t ionTailMax=0.;
2076 Double_t ionTailTotal=0.;
2077 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
2078 ionTailMax=TMath::Abs(ionTailMax);
2079 ionTailTotal=TMath::Abs(ionTailTotal);
2080 qTotArray[icl0]+=ionTailTotal;
2081 qMaxArray[icl0]+=ionTailMax;
2083 // Dump some info for debugging while clusters are being corrected
2084 if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) { // flag: stream ion tail correction as applied to cluster
2085 TTreeSRedirector &cstream = *fDebugStreamer;
2086 if (gRandom->Rndm() > 0.999){
2087 cstream<<"IonTail"<<
2088 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
2089 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
2090 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
2091 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
2094 }// dump the results to the debug streamer if in debug mode
2096 }//end of second loop over clusters
2098 // Set corrected values of the corrected cluster
2099 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
2100 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
2102 // Dump some info for debugging after clusters are corrected
2103 if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) {
2104 TTreeSRedirector &cstream = *fDebugStreamer;
2105 if (gRandom->Rndm() > 0.999){
2106 cstream<<"IonTailCorrected"<<
2107 "cl0.=" << cl0 << // cluster 0 with huge Qmax
2108 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
2109 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
2110 "nclALL=" << nclALL <<
2111 "nclSector=" << nclSector <<
2113 "nclPad=" << nclPad <<
2119 }// dump the results to the debug streamer if in debug mode
2121 }//end of first loop over cluster
2122 delete rowClusterArray;
2123 }//end of loop over rows
2124 for (int i=0; i<20; i++) delete graphRes[i];
2126 delete [] indexAmpGraphs;
2128 }//end of loop over sectors
2129 }//end of loop over IROC/OROC
2130 }// end of side loop
2132 //_____________________________________________________________________________
2133 void AliTPCtracker::GetTailValue(Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
2136 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
2138 // cl0 - cluster to be modified
2139 // cl1 - source cluster ion tail of this cluster will be added to the cl0 (accroding time and pad response function)
2141 const Double_t kMinPRF = 0.5; // minimal PRF width
2142 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
2143 ionTailMax = 0.; // correction value to be added to Qmax of cl0
2145 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
2146 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
2147 Int_t sectorPad = cl1->GetDetector(); // sector number
2148 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
2149 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
2150 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
2151 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
2152 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
2153 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
2157 Double_t sumAmp1=0.;
2158 for (Int_t idelta =-2; idelta<=2;idelta++){
2159 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
2162 Double_t sumAmp0=0.;
2163 for (Int_t idelta =-2; idelta<=2;idelta++){
2164 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
2167 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
2168 Int_t padScan=2; // +-2 pad-timebin window will be scanned
2169 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
2172 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
2173 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
2174 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
2176 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
2178 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
2179 for (Int_t j=0;j<20;j++) {
2180 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
2182 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
2186 if (!graphRes[ampIndex]) continue;
2187 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
2188 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
2190 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
2193 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
2195 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
2196 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
2197 Float_t qMaxPad0 = amp0*qTot0;
2199 // Add 5 timebin range contribution around the max peak (-+2 tb window)
2200 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
2202 if (itb<0) continue;
2203 if (itb>=graphRes[ampIndex]->GetN()) continue;
2205 // calculate contribution to qTot
2206 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
2207 if (ipad1!=padcl0) {
2208 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
2210 ionTailTotal += tailCorr; // for center pad
2212 // calculate contribution to qMax
2213 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
2215 } // end of tb correction loop which is applied over 5 tb range
2217 } // end of cl0 loop
2218 } // end of cl1 loop
2222 //_____________________________________________________________________________
2223 Int_t AliTPCtracker::LoadOuterSectors() {
2224 //-----------------------------------------------------------------
2225 // This function fills outer TPC sectors with clusters.
2226 //-----------------------------------------------------------------
2227 Int_t nrows = fOuterSec->GetNRows();
2229 for (Int_t sec = 0;sec<fkNOS;sec++)
2230 for (Int_t row = 0;row<nrows;row++){
2231 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
2232 Int_t sec2 = sec+2*fkNIS;
2234 Int_t ncl = tpcrow->GetN1();
2236 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
2237 index=(((sec2<<8)+row)<<16)+ncl;
2238 tpcrow->InsertCluster(c,index);
2241 ncl = tpcrow->GetN2();
2243 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
2244 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
2245 tpcrow->InsertCluster(c,index);
2248 // write indexes for fast acces
2250 for (Int_t i=0;i<510;i++)
2251 tpcrow->SetFastCluster(i,-1);
2252 for (Int_t i=0;i<tpcrow->GetN();i++){
2253 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
2254 tpcrow->SetFastCluster(zi,i); // write index
2257 for (Int_t i=0;i<510;i++){
2258 if (tpcrow->GetFastCluster(i)<0)
2259 tpcrow->SetFastCluster(i,last);
2261 last = tpcrow->GetFastCluster(i);
2270 //_____________________________________________________________________________
2271 Int_t AliTPCtracker::LoadInnerSectors() {
2272 //-----------------------------------------------------------------
2273 // This function fills inner TPC sectors with clusters.
2274 //-----------------------------------------------------------------
2275 Int_t nrows = fInnerSec->GetNRows();
2277 for (Int_t sec = 0;sec<fkNIS;sec++)
2278 for (Int_t row = 0;row<nrows;row++){
2279 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
2282 Int_t ncl = tpcrow->GetN1();
2284 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
2285 index=(((sec<<8)+row)<<16)+ncl;
2286 tpcrow->InsertCluster(c,index);
2289 ncl = tpcrow->GetN2();
2291 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
2292 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
2293 tpcrow->InsertCluster(c,index);
2296 // write indexes for fast acces
2298 for (Int_t i=0;i<510;i++)
2299 tpcrow->SetFastCluster(i,-1);
2300 for (Int_t i=0;i<tpcrow->GetN();i++){
2301 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
2302 tpcrow->SetFastCluster(zi,i); // write index
2305 for (Int_t i=0;i<510;i++){
2306 if (tpcrow->GetFastCluster(i)<0)
2307 tpcrow->SetFastCluster(i,last);
2309 last = tpcrow->GetFastCluster(i);
2321 //_________________________________________________________________________
2322 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
2323 //--------------------------------------------------------------------
2324 // Return pointer to a given cluster
2325 //--------------------------------------------------------------------
2326 if (index<0) return 0; // no cluster
2327 Int_t sec=(index&0xff000000)>>24;
2328 Int_t row=(index&0x00ff0000)>>16;
2329 Int_t ncl=(index&0x00007fff)>>00;
2331 const AliTPCtrackerRow * tpcrow=0;
2332 TClonesArray * clrow =0;
2334 if (sec<0 || sec>=fkNIS*4) {
2335 AliWarning(Form("Wrong sector %d",sec));
2340 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
2341 if (tracksec.GetNRows()<=row) return 0;
2342 tpcrow = &(tracksec[row]);
2343 if (tpcrow==0) return 0;
2346 if (tpcrow->GetN1()<=ncl) return 0;
2347 clrow = tpcrow->GetClusters1();
2350 if (tpcrow->GetN2()<=ncl) return 0;
2351 clrow = tpcrow->GetClusters2();
2355 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
2356 if (tracksec.GetNRows()<=row) return 0;
2357 tpcrow = &(tracksec[row]);
2358 if (tpcrow==0) return 0;
2360 if (sec-2*fkNIS<fkNOS) {
2361 if (tpcrow->GetN1()<=ncl) return 0;
2362 clrow = tpcrow->GetClusters1();
2365 if (tpcrow->GetN2()<=ncl) return 0;
2366 clrow = tpcrow->GetClusters2();
2370 return (AliTPCclusterMI*)clrow->At(ncl);
2376 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
2377 //-----------------------------------------------------------------
2378 // This function tries to find a track prolongation to next pad row
2379 //-----------------------------------------------------------------
2381 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
2384 AliTPCclusterMI *cl=0;
2385 Int_t tpcindex= t.GetClusterIndex2(nr);
2387 // update current shape info every 5 pad-row
2388 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
2392 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
2394 if (tpcindex==-1) return 0; //track in dead zone
2395 if (tpcindex >= 0){ //
2396 cl = t.GetClusterPointer(nr);
2397 //if (cl==0) cl = GetClusterMI(tpcindex);
2398 if (!cl) cl = GetClusterMI(tpcindex);
2399 t.SetCurrentClusterIndex1(tpcindex);
2402 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
2403 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
2405 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
2406 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
2408 if (TMath::Abs(angle-t.GetAlpha())>0.001){
2409 Double_t rotation = angle-t.GetAlpha();
2410 t.SetRelativeSector(relativesector);
2411 if (!t.Rotate(rotation)) {
2412 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
2416 if (!t.PropagateTo(x)) {
2417 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
2421 t.SetCurrentCluster(cl);
2423 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2424 if ((tpcindex&0x8000)==0) accept =0;
2426 //if founded cluster is acceptible
2427 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
2428 t.SetErrorY2(t.GetErrorY2()+0.03);
2429 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2430 t.SetErrorY2(t.GetErrorY2()*3);
2431 t.SetErrorZ2(t.GetErrorZ2()*3);
2433 t.SetNFoundable(t.GetNFoundable()+1);
2434 UpdateTrack(&t,accept);
2437 else { // Remove old cluster from track
2438 t.SetClusterIndex(nr, -3);
2439 t.SetClusterPointer(nr, 0);
2443 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
2444 if (fIteration>1 && IsFindable(t)){
2445 // not look for new cluster during refitting
2446 t.SetNFoundable(t.GetNFoundable()+1);
2451 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
2452 if (!t.PropagateTo(x)) {
2453 if (fIteration==0) t.SetRemoval(10);
2456 Double_t y = t.GetY();
2457 if (TMath::Abs(y)>ymax){
2459 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2460 if (!t.Rotate(fSectors->GetAlpha()))
2462 } else if (y <-ymax) {
2463 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2464 if (!t.Rotate(-fSectors->GetAlpha()))
2467 if (!t.PropagateTo(x)) {
2468 if (fIteration==0) t.SetRemoval(10);
2474 Double_t z=t.GetZ();
2477 if (!IsActive(t.GetRelativeSector(),nr)) {
2479 t.SetClusterIndex2(nr,-1);
2482 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2483 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
2484 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
2486 if (!isActive || !isActive2) return 0;
2488 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2489 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
2491 Double_t roadz = 1.;
2493 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2495 t.SetClusterIndex2(nr,-1);
2501 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2502 t.SetNFoundable(t.GetNFoundable()+1);
2508 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2509 cl = krow.FindNearest2(y,z,roady,roadz,index);
2510 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2513 t.SetCurrentCluster(cl);
2515 if (fIteration==2&&cl->IsUsed(10)) return 0;
2516 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2517 if (fIteration==2&&cl->IsUsed(11)) {
2518 t.SetErrorY2(t.GetErrorY2()+0.03);
2519 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2520 t.SetErrorY2(t.GetErrorY2()*3);
2521 t.SetErrorZ2(t.GetErrorZ2()*3);
2524 if (t.fCurrentCluster->IsUsed(10)){
2529 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2535 if (accept<3) UpdateTrack(&t,accept);
2538 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2546 //_________________________________________________________________________
2547 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2549 // Get track space point by index
2550 // return false in case the cluster doesn't exist
2551 AliTPCclusterMI *cl = GetClusterMI(index);
2552 if (!cl) return kFALSE;
2553 Int_t sector = (index&0xff000000)>>24;
2554 // Int_t row = (index&0x00ff0000)>>16;
2556 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2557 xyz[0] = cl->GetX();
2558 xyz[1] = cl->GetY();
2559 xyz[2] = cl->GetZ();
2561 fkParam->AdjustCosSin(sector,cos,sin);
2562 Float_t x = cos*xyz[0]-sin*xyz[1];
2563 Float_t y = cos*xyz[1]+sin*xyz[0];
2565 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2566 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2567 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2568 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2569 cov[0] = sin*sin*sigmaY2;
2570 cov[1] = -sin*cos*sigmaY2;
2572 cov[3] = cos*cos*sigmaY2;
2575 p.SetXYZ(x,y,xyz[2],cov);
2576 AliGeomManager::ELayerID iLayer;
2578 if (sector < fkParam->GetNInnerSector()) {
2579 iLayer = AliGeomManager::kTPC1;
2583 iLayer = AliGeomManager::kTPC2;
2584 idet = sector - fkParam->GetNInnerSector();
2586 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2587 p.SetVolumeID(volid);
2593 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2594 //-----------------------------------------------------------------
2595 // This function tries to find a track prolongation to next pad row
2596 //-----------------------------------------------------------------
2597 t.SetCurrentCluster(0);
2598 t.SetCurrentClusterIndex1(-3);
2600 Double_t xt=t.GetX();
2601 Int_t row = GetRowNumber(xt)-1;
2602 Double_t ymax= GetMaxY(nr);
2604 if (row < nr) return 1; // don't prolongate if not information until now -
2605 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2607 // return 0; // not prolongate strongly inclined tracks
2609 // if (TMath::Abs(t.GetSnp())>0.95) {
2611 // return 0; // not prolongate strongly inclined tracks
2612 // }// patch 28 fev 06
2614 Double_t x= GetXrow(nr);
2616 //t.PropagateTo(x+0.02);
2617 //t.PropagateTo(x+0.01);
2618 if (!t.PropagateTo(x)){
2625 if (TMath::Abs(y)>ymax){
2627 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2628 if (!t.Rotate(fSectors->GetAlpha()))
2630 } else if (y <-ymax) {
2631 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2632 if (!t.Rotate(-fSectors->GetAlpha()))
2635 // if (!t.PropagateTo(x)){
2642 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2644 if (!IsActive(t.GetRelativeSector(),nr)) {
2646 t.SetClusterIndex2(nr,-1);
2649 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2651 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2653 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2655 t.SetClusterIndex2(nr,-1);
2661 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2662 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2668 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2669 // t.fCurrentSigmaY = GetSigmaY(&t);
2670 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2674 AliTPCclusterMI *cl=0;
2677 Double_t roady = 1.;
2678 Double_t roadz = 1.;
2682 index = t.GetClusterIndex2(nr);
2683 if ( (index >= 0) && (index&0x8000)==0){
2684 cl = t.GetClusterPointer(nr);
2685 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2686 t.SetCurrentClusterIndex1(index);
2688 t.SetCurrentCluster(cl);
2694 // if (index<0) return 0;
2695 UInt_t uindex = TMath::Abs(index);
2698 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2699 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2702 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2703 t.SetCurrentCluster(cl);
2709 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2710 //-----------------------------------------------------------------
2711 // This function tries to find a track prolongation to next pad row
2712 //-----------------------------------------------------------------
2714 //update error according neighborhoud
2716 if (t.GetCurrentCluster()) {
2718 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2720 if (t.GetCurrentCluster()->IsUsed(10)){
2725 t.SetNShared(t.GetNShared()+1);
2726 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2731 if (fIteration>0) accept = 0;
2732 if (accept<3) UpdateTrack(&t,accept);
2736 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2737 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2739 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2747 //_____________________________________________________________________________
2748 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2749 //-----------------------------------------------------------------
2750 // This function tries to find a track prolongation.
2751 //-----------------------------------------------------------------
2752 Double_t xt=t.GetX();
2754 Double_t alpha=t.GetAlpha();
2755 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2756 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2758 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2760 Int_t first = GetRowNumber(xt);
2765 for (Int_t nr= first; nr>=rf; nr-=step) {
2767 if (t.GetKinkIndexes()[0]>0){
2768 for (Int_t i=0;i<3;i++){
2769 Int_t index = t.GetKinkIndexes()[i];
2770 if (index==0) break;
2771 if (index<0) continue;
2773 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2775 printf("PROBLEM\n");
2778 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2780 AliExternalTrackParam paramd(t);
2781 kink->SetDaughter(paramd);
2782 kink->SetStatus(2,5);
2789 if (nr==80) t.UpdateReference();
2790 if (nr<fInnerSec->GetNRows())
2791 fSectors = fInnerSec;
2793 fSectors = fOuterSec;
2794 if (FollowToNext(t,nr)==0)
2807 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2808 //-----------------------------------------------------------------
2809 // This function tries to find a track prolongation.
2810 //-----------------------------------------------------------------
2812 Double_t xt=t.GetX();
2813 Double_t alpha=t.GetAlpha();
2814 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2815 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2816 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2818 Int_t first = t.GetFirstPoint();
2819 Int_t ri = GetRowNumber(xt);
2823 if (first<ri) first = ri;
2825 if (first<0) first=0;
2826 for (Int_t nr=first; nr<=rf; nr++) {
2827 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2828 if (t.GetKinkIndexes()[0]<0){
2829 for (Int_t i=0;i<3;i++){
2830 Int_t index = t.GetKinkIndexes()[i];
2831 if (index==0) break;
2832 if (index>0) continue;
2833 index = TMath::Abs(index);
2834 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2836 printf("PROBLEM\n");
2839 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2841 AliExternalTrackParam paramm(t);
2842 kink->SetMother(paramm);
2843 kink->SetStatus(2,1);
2850 if (nr<fInnerSec->GetNRows())
2851 fSectors = fInnerSec;
2853 fSectors = fOuterSec;
2864 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2866 // overlapping factor
2872 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2875 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2877 Float_t distance = TMath::Sqrt(dz2+dy2);
2878 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2881 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2882 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2887 if (firstpoint>lastpoint) {
2888 firstpoint =lastpoint;
2893 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2894 if (s1->GetClusterIndex2(i)>0) sum1++;
2895 if (s2->GetClusterIndex2(i)>0) sum2++;
2896 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2900 if (sum<5) return 0;
2902 Float_t summin = TMath::Min(sum1+1,sum2+1);
2903 Float_t ratio = (sum+1)/Float_t(summin);
2907 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2911 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2912 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2913 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2914 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2919 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2920 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2921 Int_t firstpoint = 0;
2922 Int_t lastpoint = 160;
2924 // if (firstpoint>=lastpoint-5) return;;
2926 for (Int_t i=firstpoint;i<lastpoint;i++){
2927 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2928 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2932 if (sumshared>cutN0){
2935 for (Int_t i=firstpoint;i<lastpoint;i++){
2936 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2937 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2938 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2939 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2940 if (s1->IsActive()&&s2->IsActive()){
2941 p1->SetShared(kTRUE);
2942 p2->SetShared(kTRUE);
2948 if (sumshared>cutN0){
2949 for (Int_t i=0;i<4;i++){
2950 if (s1->GetOverlapLabel(3*i)==0){
2951 s1->SetOverlapLabel(3*i, s2->GetLabel());
2952 s1->SetOverlapLabel(3*i+1,sumshared);
2953 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2957 for (Int_t i=0;i<4;i++){
2958 if (s2->GetOverlapLabel(3*i)==0){
2959 s2->SetOverlapLabel(3*i, s1->GetLabel());
2960 s2->SetOverlapLabel(3*i+1,sumshared);
2961 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2968 void AliTPCtracker::SignShared(TObjArray * arr)
2971 //sort trackss according sectors
2973 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2974 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2976 //if (pt) RotateToLocal(pt);
2980 arr->Sort(); // sorting according relative sectors
2981 arr->Expand(arr->GetEntries());
2984 Int_t nseed=arr->GetEntriesFast();
2985 for (Int_t i=0; i<nseed; i++) {
2986 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2988 for (Int_t j=0;j<12;j++){
2989 pt->SetOverlapLabel(j,0);
2992 for (Int_t i=0; i<nseed; i++) {
2993 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2995 if (pt->GetRemoval()>10) continue;
2996 for (Int_t j=i+1; j<nseed; j++){
2997 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2998 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
3000 if (pt2->GetRemoval()<=10) {
3001 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
3009 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
3012 //sort tracks in array according mode criteria
3013 Int_t nseed = arr->GetEntriesFast();
3014 for (Int_t i=0; i<nseed; i++) {
3015 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3026 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
3029 // Loop over all tracks and remove overlaped tracks (with lower quality)
3031 // 1. Unsign clusters
3032 // 2. Sort tracks according quality
3033 // Quality is defined by the number of cluster between first and last points
3035 // 3. Loop over tracks - decreasing quality order
3036 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
3037 // b.) remove - If the minimal number of clusters less than minimal and not ITS
3038 // c.) if track accepted - sign clusters
3040 //Called in - AliTPCtracker::Clusters2Tracks()
3041 // - AliTPCtracker::PropagateBack()
3042 // - AliTPCtracker::RefitInward()
3045 // factor1 - factor for constrained
3046 // factor2 - for non constrained tracks
3047 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
3051 Int_t nseed = arr->GetEntriesFast();
3052 Float_t * quality = new Float_t[nseed];
3053 Int_t * indexes = new Int_t[nseed];
3057 for (Int_t i=0; i<nseed; i++) {
3058 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3063 pt->UpdatePoints(); //select first last max dens points
3064 Float_t * points = pt->GetPoints();
3065 if (points[3]<0.8) quality[i] =-1;
3066 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
3067 //prefer high momenta tracks if overlaps
3068 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
3070 TMath::Sort(nseed,quality,indexes);
3073 for (Int_t itrack=0; itrack<nseed; itrack++) {
3074 Int_t trackindex = indexes[itrack];
3075 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
3078 if (quality[trackindex]<0){
3079 MarkSeedFree( arr->RemoveAt(trackindex) );
3084 Int_t first = Int_t(pt->GetPoints()[0]);
3085 Int_t last = Int_t(pt->GetPoints()[2]);
3086 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
3088 Int_t found,foundable,shared;
3089 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
3090 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
3091 Bool_t itsgold =kFALSE;
3094 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
3098 if (Float_t(shared+1)/Float_t(found+1)>factor){
3099 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
3100 if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveUsed)>0){ // flag:stream information about TPC tracks which were descarded (double track removal)
3101 TTreeSRedirector &cstream = *fDebugStreamer;
3102 cstream<<"RemoveUsed"<<
3103 "iter="<<fIteration<<
3107 MarkSeedFree( arr->RemoveAt(trackindex) );
3110 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
3111 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
3112 if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveShort)>0){ // flag:stream information about TPC tracks which were discarded (short track removal)
3113 TTreeSRedirector &cstream = *fDebugStreamer;
3114 cstream<<"RemoveShort"<<
3115 "iter="<<fIteration<<
3119 MarkSeedFree( arr->RemoveAt(trackindex) );
3125 //if (sharedfactor>0.4) continue;
3126 if (pt->GetKinkIndexes()[0]>0) continue;
3127 //Remove tracks with undefined properties - seems
3128 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
3130 for (Int_t i=first; i<last; i++) {
3131 Int_t index=pt->GetClusterIndex2(i);
3132 // if (index<0 || index&0x8000 ) continue;
3133 if (index<0 || index&0x8000 ) continue;
3134 AliTPCclusterMI *c= pt->GetClusterPointer(i);
3141 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
3147 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
3150 // Dump clusters after reco
3151 // signed and unsigned cluster can be visualized
3152 // 1. Unsign all cluster
3153 // 2. Sign all used clusters
3156 Int_t nseed = trackArray->GetEntries();
3157 for (Int_t i=0; i<nseed; i++){
3158 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
3162 Bool_t isKink=pt->GetKinkIndex(0)!=0;
3163 for (Int_t j=0; j<160; ++j) {
3164 Int_t index=pt->GetClusterIndex2(j);
3165 if (index<0) continue;
3166 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3168 if (isKink) c->Use(100); // kink
3169 c->Use(10); // by default usage 10
3173 Int_t eventNr = fEvent->GetEventNumberInFile();
3175 for (Int_t sec=0;sec<fkNIS;sec++){
3176 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
3177 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
3178 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
3179 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
3180 Float_t gx[3]; cl->GetGlobalXYZ(gx);
3181 (*fDebugStreamer)<<"clDump"<<
3182 "eventNr="<<eventNr<<
3190 cla = fInnerSec[sec][row].GetClusters2();
3191 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
3192 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
3193 Float_t gx[3]; cl->GetGlobalXYZ(gx);
3194 (*fDebugStreamer)<<"clDump"<<
3195 "eventNr="<<eventNr<<
3206 for (Int_t sec=0;sec<fkNOS;sec++){
3207 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
3208 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
3209 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
3211 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
3212 cl->GetGlobalXYZ(gx);
3213 (*fDebugStreamer)<<"clDump"<<
3214 "eventNr="<<eventNr<<
3222 cla = fOuterSec[sec][row].GetClusters2();
3223 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
3225 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
3226 cl->GetGlobalXYZ(gx);
3227 (*fDebugStreamer)<<"clDump"<<
3228 "eventNr="<<eventNr<<
3240 void AliTPCtracker::UnsignClusters()
3243 // loop over all clusters and unsign them
3246 for (Int_t sec=0;sec<fkNIS;sec++){
3247 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
3248 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
3249 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
3250 // if (cl[icl].IsUsed(10))
3251 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3252 cla = fInnerSec[sec][row].GetClusters2();
3253 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
3254 //if (cl[icl].IsUsed(10))
3255 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3259 for (Int_t sec=0;sec<fkNOS;sec++){
3260 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
3261 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
3262 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
3263 //if (cl[icl].IsUsed(10))
3264 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3265 cla = fOuterSec[sec][row].GetClusters2();
3266 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
3267 //if (cl[icl].IsUsed(10))
3268 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3276 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
3279 //sign clusters to be "used"
3281 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
3282 // loop over "primaries"
3296 Int_t nseed = arr->GetEntriesFast();
3297 for (Int_t i=0; i<nseed; i++) {
3298 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3302 if (!(pt->IsActive())) continue;
3303 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
3304 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
3306 sumdens2+= dens*dens;
3307 sumn += pt->GetNumberOfClusters();
3308 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
3309 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
3312 sumchi2 +=chi2*chi2;
3317 Float_t mdensity = 0.9;
3318 Float_t meann = 130;
3319 Float_t meanchi = 1;
3320 Float_t sdensity = 0.1;
3321 Float_t smeann = 10;
3322 Float_t smeanchi =0.4;
3326 mdensity = sumdens/sum;
3328 meanchi = sumchi/sum;
3330 sdensity = sumdens2/sum-mdensity*mdensity;
3332 sdensity = TMath::Sqrt(sdensity);
3336 smeann = sumn2/sum-meann*meann;
3338 smeann = TMath::Sqrt(smeann);
3342 smeanchi = sumchi2/sum - meanchi*meanchi;
3344 smeanchi = TMath::Sqrt(smeanchi);
3350 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
3352 for (Int_t i=0; i<nseed; i++) {
3353 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3357 if (pt->GetBSigned()) continue;
3358 if (pt->GetBConstrain()) continue;
3359 //if (!(pt->IsActive())) continue;
3361 Int_t found,foundable,shared;
3362 pt->GetClusterStatistic(0,160,found, foundable,shared);
3363 if (shared/float(found)>0.3) {
3364 if (shared/float(found)>0.9 ){
3365 //MarkSeedFree( arr->RemoveAt(i) );
3370 Bool_t isok =kFALSE;
3371 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
3373 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
3375 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
3377 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
3381 for (Int_t j=0; j<160; ++j) {
3382 Int_t index=pt->GetClusterIndex2(j);
3383 if (index<0) continue;
3384 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3386 //if (!(c->IsUsed(10))) c->Use();
3393 Double_t maxchi = meanchi+2.*smeanchi;
3395 for (Int_t i=0; i<nseed; i++) {
3396 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3400 //if (!(pt->IsActive())) continue;
3401 if (pt->GetBSigned()) continue;
3402 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
3403 if (chi>maxchi) continue;
3406 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
3408 //sign only tracks with enoug big density at the beginning
3410 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
3413 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
3414 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
3416 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
3417 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
3420 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
3421 //Int_t noc=pt->GetNumberOfClusters();
3422 pt->SetBSigned(kTRUE);
3423 for (Int_t j=0; j<160; ++j) {
3425 Int_t index=pt->GetClusterIndex2(j);
3426 if (index<0) continue;
3427 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3429 // if (!(c->IsUsed(10))) c->Use();
3434 // gLastCheck = nseed;
3443 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
3446 // back propagation of ESD tracks
3449 if (!event) return 0;
3450 const Int_t kMaxFriendTracks=2000;
3453 // extract correction object for multiplicity dependence of dEdx
3454 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
3456 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
3458 AliFatal("Tranformations not in RefitInward");
3461 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
3462 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
3463 Int_t nContribut = event->GetNumberOfTracks();
3464 TGraphErrors * graphMultDependenceDeDx = 0x0;
3465 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
3466 if (recoParam->GetUseTotCharge()) {
3467 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
3469 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
3475 //PrepareForProlongation(fSeeds,1);
3476 PropagateForward2(fSeeds);
3477 RemoveUsed2(fSeeds,0.4,0.4,20);
3479 Int_t entriesSeed=fSeeds->GetEntries();
3480 TObjArray arraySeed(entriesSeed);
3481 for (Int_t i=0;i<entriesSeed;i++) {
3482 arraySeed.AddAt(fSeeds->At(i),i);
3484 SignShared(&arraySeed);
3485 // FindCurling(fSeeds, event,2); // find multi found tracks
3486 FindSplitted(fSeeds, event,2); // find multi found tracks
3487 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) FindMultiMC(fSeeds, fEvent,2); // flag: stream MC infomation about the multiple find track (ONLY for MC data)
3490 Int_t nseed = fSeeds->GetEntriesFast();
3491 for (Int_t i=0;i<nseed;i++){
3492 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3493 if (!seed) continue;
3494 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
3495 AliESDtrack *esd=event->GetTrack(i);
3497 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3498 AliExternalTrackParam paramIn;
3499 AliExternalTrackParam paramOut;
3500 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3501 if ((AliTPCReconstructor::StreamLevel() & kStreamRecoverIn)>0) { // flag: stream track information for track failing in RefitInward function and recovered back
3502 (*fDebugStreamer)<<"RecoverIn"<<
3506 "pout.="<<¶mOut<<
3511 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3512 seed->SetNumberOfClusters(ncl);
3516 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3517 seed->UpdatePoints();
3518 AddCovariance(seed);
3519 MakeESDBitmaps(seed, esd);
3520 seed->CookdEdx(0.02,0.6);
3521 CookLabel(seed,0.1); //For comparison only
3523 if (((AliTPCReconstructor::StreamLevel()&kStreamRefitInward)>0) && seed!=0) {
3524 TTreeSRedirector &cstream = *fDebugStreamer;
3525 cstream<<"RefitInward"<< // flag: stream track information in RefitInward function (after tracking Iteration 2)
3531 if (seed->GetNumberOfClusters()>15){
3532 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3533 esd->SetTPCPoints(seed->GetPoints());
3534 esd->SetTPCPointsF(seed->GetNFoundable());
3535 Int_t ndedx = seed->GetNCDEDX(0);
3536 Float_t sdedx = seed->GetSDEDX(0);
3537 Float_t dedx = seed->GetdEdx();
3538 // apply mutliplicity dependent dEdx correction if available
3539 if (graphMultDependenceDeDx) {
3540 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3541 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3543 esd->SetTPCsignal(dedx, sdedx, ndedx);
3545 // fill new dEdx information
3547 Double32_t signal[4];
3548 Double32_t signalMax[4];
3552 for(Int_t iarr=0;iarr<3;iarr++) {
3553 signal[iarr] = seed->GetDEDXregion(iarr+1);
3554 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3555 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3556 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3558 signal[3] = seed->GetDEDXregion(4);
3559 signalMax[3] = seed->GetDEDXregion(8);
3562 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3563 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3564 infoTpcPid->SetTPCSignalsQmax(signalMax);
3565 esd->SetTPCdEdxInfo(infoTpcPid);
3567 // add seed to the esd track in Calib level
3569 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3570 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3571 // RS: this is the only place where the seed is created not in the pool,
3572 // since it should belong to ESDevent
3573 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3574 esd->AddCalibObject(seedCopy);
3579 //printf("problem\n");
3582 //FindKinks(fSeeds,event);
3583 if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0) DumpClusters(2,fSeeds); // dump clusters at the end of process (signed with useage flags)
3584 Info("RefitInward","Number of refitted tracks %d",ntracks);
3586 AliCosmicTracker::FindCosmic(event, kTRUE);
3588 FillClusterOccupancyInfo();
3594 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3597 // back propagation of ESD tracks
3599 if (!event) return 0;
3604 PropagateBack(fSeeds);
3605 RemoveUsed2(fSeeds,0.4,0.4,20);
3606 //FindCurling(fSeeds, fEvent,1);
3607 FindSplitted(fSeeds, event,1); // find multi found tracks
3608 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3611 Int_t nseed = fSeeds->GetEntriesFast();
3613 for (Int_t i=0;i<nseed;i++){
3614 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3615 if (!seed) continue;
3616 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3617 seed->UpdatePoints();
3618 AddCovariance(seed);
3619 AliESDtrack *esd=event->GetTrack(i);
3620 if (!esd) continue; //never happen
3621 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3622 AliExternalTrackParam paramIn;
3623 AliExternalTrackParam paramOut;
3624 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3625 if ((AliTPCReconstructor::StreamLevel()&kStreamRecoverBack)>0) { // flag: stream track information for track faling PropagateBack function and recovered back (RefitTrack)
3626 (*fDebugStreamer)<<"RecoverBack"<<
3630 "pout.="<<¶mOut<<
3635 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3636 seed->SetNumberOfClusters(ncl);
3639 seed->CookdEdx(0.02,0.6);
3640 CookLabel(seed,0.1); //For comparison only
3641 if (seed->GetNumberOfClusters()>15){
3642 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3643 esd->SetTPCPoints(seed->GetPoints());
3644 esd->SetTPCPointsF(seed->GetNFoundable());
3645 Int_t ndedx = seed->GetNCDEDX(0);
3646 Float_t sdedx = seed->GetSDEDX(0);
3647 Float_t dedx = seed->GetdEdx();
3648 esd->SetTPCsignal(dedx, sdedx, ndedx);
3650 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3651 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3652 if (((AliTPCReconstructor::StreamLevel()&kStreamCPropagateBack)>0) && esd) {
3653 (*fDebugStreamer)<<"PropagateBack"<< // flag: stream track information in PropagateBack function (after tracking Iteration 1)
3656 "EventNrInFile="<<eventnumber<<
3661 if (AliTPCReconstructor::StreamLevel()&kStreamClDump) DumpClusters(1,fSeeds); // flag:stream clusters at the end of process (signed with usage flag)
3662 //FindKinks(fSeeds,event);
3663 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3671 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3674 // Post process events
3676 if (!event) return 0;
3679 // Set TPC event status
3682 // event affected by HV dip
3684 if(IsTPCHVDipEvent(event)) {
3685 event->ResetDetectorStatus(AliDAQ::kTPC);
3688 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3694 void AliTPCtracker::DeleteSeeds()
3703 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3706 //read seeds from the event
3708 Int_t nentr=event->GetNumberOfTracks();
3710 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3715 fSeeds = new TObjArray(nentr);
3719 for (Int_t i=0; i<nentr; i++) {
3720 AliESDtrack *esd=event->GetTrack(i);
3721 ULong_t status=esd->GetStatus();
3722 if (!(status&AliESDtrack::kTPCin)) continue;
3723 AliTPCtrack t(*esd);
3724 t.SetNumberOfClusters(0);
3725 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3726 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3727 seed->SetPoolID(fLastSeedID);
3728 seed->SetUniqueID(esd->GetID());
3729 AddCovariance(seed); //add systematic ucertainty
3730 for (Int_t ikink=0;ikink<3;ikink++) {
3731 Int_t index = esd->GetKinkIndex(ikink);
3732 seed->GetKinkIndexes()[ikink] = index;
3733 if (index==0) continue;
3734 index = TMath::Abs(index);
3735 AliESDkink * kink = fEvent->GetKink(index-1);
3736 if (kink&&esd->GetKinkIndex(ikink)<0){
3737 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3738 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3740 if (kink&&esd->GetKinkIndex(ikink)>0){
3741 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3742 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3746 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3747 //RS if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3748 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3749 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3750 // fSeeds->AddAt(0,i);
3751 // MarkSeedFree( seed );
3757 // rotate to the local coordinate system
3759 fSectors=fInnerSec; fN=fkNIS;
3760 Double_t alpha=seed->GetAlpha();
3761 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3762 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3763 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3764 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3765 alpha-=seed->GetAlpha();
3766 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3767 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3768 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3769 AliWarning(Form("Rotating track over %f",alpha));
3770 if (!seed->Rotate(alpha)) {
3771 MarkSeedFree( seed );
3777 if (esd->GetKinkIndex(0)<=0){
3778 for (Int_t irow=0;irow<160;irow++){
3779 Int_t index = seed->GetClusterIndex2(irow);
3782 AliTPCclusterMI * cl = GetClusterMI(index);
3783 seed->SetClusterPointer(irow,cl);
3785 if ((index & 0x8000)==0){
3786 cl->Use(10); // accepted cluster
3788 cl->Use(6); // close cluster not accepted
3791 Info("ReadSeeds","Not found cluster");
3796 fSeeds->AddAt(seed,i);
3802 //_____________________________________________________________________________
3803 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3804 Float_t deltay, Int_t ddsec) {
3805 //-----------------------------------------------------------------
3806 // This function creates track seeds.
3807 // SEEDING WITH VERTEX CONSTRAIN
3808 //-----------------------------------------------------------------
3809 // cuts[0] - fP4 cut
3810 // cuts[1] - tan(phi) cut
3811 // cuts[2] - zvertex cut
3812 // cuts[3] - fP3 cut
3820 Double_t x[5], c[15];
3821 // Int_t di = i1-i2;
3823 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3824 seed->SetPoolID(fLastSeedID);
3825 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3826 Double_t cs=cos(alpha), sn=sin(alpha);
3828 // Double_t x1 =fOuterSec->GetX(i1);
3829 //Double_t xx2=fOuterSec->GetX(i2);
3831 Double_t x1 =GetXrow(i1);
3832 Double_t xx2=GetXrow(i2);
3834 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3836 Int_t imiddle = (i2+i1)/2; //middle pad row index
3837 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3838 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3842 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3843 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3844 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3847 // change cut on curvature if it can't reach this layer
3848 // maximal curvature set to reach it
3849 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3850 if (dvertexmax*0.5*cuts[0]>0.85){
3851 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3853 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3856 if (deltay>0) ddsec = 0;
3857 // loop over clusters
3858 for (Int_t is=0; is < kr1; is++) {
3860 if (kr1[is]->IsUsed(10)) continue;
3861 if (kr1[is]->IsDisabled()) {
3865 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3866 //if (TMath::Abs(y1)>ymax) continue;
3868 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3870 // find possible directions
3871 Float_t anglez = (z1-z3)/(x1-x3);
3872 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3875 //find rotation angles relative to line given by vertex and point 1
3876 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3877 Double_t dvertex = TMath::Sqrt(dvertex2);
3878 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3879 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3882 // loop over 2 sectors
3888 Double_t dddz1=0; // direction of delta inclination in z axis
3895 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3896 Int_t sec2 = sec + dsec;
3898 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3899 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3900 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3901 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3902 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3903 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3905 // rotation angles to p1-p3
3906 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3907 Double_t x2, y2, z2;
3909 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3912 Double_t dxx0 = (xx2-x3)*cs13r;
3913 Double_t dyy0 = (xx2-x3)*sn13r;
3914 for (Int_t js=index1; js < index2; js++) {
3915 const AliTPCclusterMI *kcl = kr2[js];
3916 if (kcl->IsUsed(10)) continue;
3917 if (kcl->IsDisabled()) {
3921 //calcutate parameters
3923 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3925 if (TMath::Abs(yy0)<0.000001) continue;
3926 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3927 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3928 Double_t r02 = (0.25+y0*y0)*dvertex2;
3929 //curvature (radius) cut
3930 if (r02<r2min) continue;
3934 Double_t c0 = 1/TMath::Sqrt(r02);
3938 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3939 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3940 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3941 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3944 Double_t z0 = kcl->GetZ();
3945 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3946 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3949 Double_t dip = (z1-z0)*c0/dfi1;
3950 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3961 x2= xx2*cs-y2*sn*dsec;
3962 y2=+xx2*sn*dsec+y2*cs;
3972 // do we have cluster at the middle ?
3974 GetProlongation(x1,xm,x,ym,zm);
3976 AliTPCclusterMI * cm=0;
3977 if (TMath::Abs(ym)-ymaxm<0){
3978 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3979 if ((!cm) || (cm->IsUsed(10))) {
3984 // rotate y1 to system 0
3985 // get state vector in rotated system
3986 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3987 Double_t xr2 = x0*cs+yr1*sn*dsec;
3988 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3990 GetProlongation(xx2,xm,xr,ym,zm);
3991 if (TMath::Abs(ym)-ymaxm<0){
3992 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3993 if ((!cm) || (cm->IsUsed(10))) {
4000 // Double_t dym = 0;
4001 // Double_t dzm = 0;
4003 // dym = ym - cm->GetY();
4004 // dzm = zm - cm->GetZ();
4011 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
4012 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
4013 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
4014 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4015 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
4017 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4018 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4019 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4020 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4021 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4022 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4024 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4025 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4026 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4027 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4031 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4032 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4033 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4034 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4035 c[13]=f30*sy1*f40+f32*sy2*f42;
4036 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4038 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4040 UInt_t index=kr1.GetIndex(is);
4041 if (seed) {MarkSeedFree(seed); seed = 0;}
4042 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
4043 seed->SetPoolID(fLastSeedID);
4044 track->SetIsSeeding(kTRUE);
4045 track->SetSeed1(i1);
4046 track->SetSeed2(i2);
4047 track->SetSeedType(3);
4051 FollowProlongation(*track, (i1+i2)/2,1);
4052 Int_t foundable,found,shared;
4053 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
4054 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
4055 MarkSeedFree(seed); seed = 0;
4061 FollowProlongation(*track, i2,1);
4065 track->SetBConstrain(1);
4066 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
4067 track->SetLastPoint(i1); // first cluster in track position
4068 track->SetFirstPoint(track->GetLastPoint());
4070 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4071 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4072 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
4073 MarkSeedFree(seed); seed = 0;
4077 // Z VERTEX CONDITION
4078 Double_t zv, bz=GetBz();
4079 if ( !track->GetZAt(0.,bz,zv) ) continue;
4080 if (TMath::Abs(zv-z3)>cuts[2]) {
4081 FollowProlongation(*track, TMath::Max(i2-20,0));
4082 if ( !track->GetZAt(0.,bz,zv) ) continue;
4083 if (TMath::Abs(zv-z3)>cuts[2]){
4084 FollowProlongation(*track, TMath::Max(i2-40,0));
4085 if ( !track->GetZAt(0.,bz,zv) ) continue;
4086 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
4087 // make seed without constrain
4088 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
4089 FollowProlongation(*track2, i2,1);
4090 track2->SetBConstrain(kFALSE);
4091 track2->SetSeedType(1);
4092 arr->AddLast(track2);
4093 MarkSeedFree( seed ); seed = 0;
4097 MarkSeedFree( seed ); seed = 0;
4104 track->SetSeedType(0);
4105 arr->AddLast(track); // note, track is seed, don't free the seed
4106 seed = new( NextFreeSeed() ) AliTPCseed;
4107 seed->SetPoolID(fLastSeedID);
4109 // don't consider other combinations
4110 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
4116 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
4118 if (seed) MarkSeedFree( seed );
4122 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
4127 //-----------------------------------------------------------------
4128 // This function creates track seeds.
4129 //-----------------------------------------------------------------
4130 // cuts[0] - fP4 cut
4131 // cuts[1] - tan(phi) cut
4132 // cuts[2] - zvertex cut
4133 // cuts[3] - fP3 cut
4143 Double_t x[5], c[15];
4145 // make temporary seed
4146 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4147 seed->SetPoolID(fLastSeedID);
4148 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4149 // Double_t cs=cos(alpha), sn=sin(alpha);
4154 Double_t x1 = GetXrow(i1-1);
4155 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
4156 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
4158 Double_t x1p = GetXrow(i1);
4159 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
4161 Double_t x1m = GetXrow(i1-2);
4162 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
4165 //last 3 padrow for seeding
4166 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
4167 Double_t x3 = GetXrow(i1-7);
4168 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
4170 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
4171 Double_t x3p = GetXrow(i1-6);
4173 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
4174 Double_t x3m = GetXrow(i1-8);
4179 Int_t im = i1-4; //middle pad row index
4180 Double_t xm = GetXrow(im); // radius of middle pad-row
4181 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
4182 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
4185 Double_t deltax = x1-x3;
4186 Double_t dymax = deltax*cuts[1];
4187 Double_t dzmax = deltax*cuts[3];
4189 // loop over clusters
4190 for (Int_t is=0; is < kr1; is++) {
4192 if (kr1[is]->IsUsed(10)) continue;
4193 if (kr1[is]->IsDisabled()) {
4197 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
4199 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
4201 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
4202 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
4208 for (Int_t js=index1; js < index2; js++) {
4209 const AliTPCclusterMI *kcl = kr3[js];
4210 if (kcl->IsDisabled()) {
4214 if (kcl->IsUsed(10)) continue;
4216 // apply angular cuts
4217 if (TMath::Abs(y1-y3)>dymax) continue;
4220 if (TMath::Abs(z1-z3)>dzmax) continue;
4222 Double_t angley = (y1-y3)/(x1-x3);
4223 Double_t anglez = (z1-z3)/(x1-x3);
4225 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
4226 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
4228 Double_t yyym = angley*(xm-x1)+y1;
4229 Double_t zzzm = anglez*(xm-x1)+z1;
4231 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
4233 if (kcm->IsUsed(10)) continue;
4234 if (kcm->IsDisabled()) {
4238 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
4239 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
4246 // look around first
4247 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
4253 if (kc1m->IsUsed(10)) used++;
4255 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
4261 if (kc1p->IsUsed(10)) used++;
4263 if (used>1) continue;
4264 if (found<1) continue;
4268 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
4274 if (kc3m->IsUsed(10)) used++;
4278 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
4284 if (kc3p->IsUsed(10)) used++;
4288 if (used>1) continue;
4289 if (found<3) continue;
4299 x[4]=F1(x1,y1,x2,y2,x3,y3);
4300 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
4303 x[2]=F2(x1,y1,x2,y2,x3,y3);
4306 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
4307 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4311 Double_t sy1=0.1, sz1=0.1;
4312 Double_t sy2=0.1, sz2=0.1;
4313 Double_t sy3=0.1, sy=0.1, sz=0.1;
4315 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4316 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4317 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4318 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4319 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4320 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4322 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4323 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4324 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4325 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4329 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4330 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4331 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4332 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4333 c[13]=f30*sy1*f40+f32*sy2*f42;
4334 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4336 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4338 index=kr1.GetIndex(is);
4339 if (seed) {MarkSeedFree( seed ); seed = 0;}
4340 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
4341 seed->SetPoolID(fLastSeedID);
4343 track->SetIsSeeding(kTRUE);
4346 FollowProlongation(*track, i1-7,1);
4347 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
4348 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
4349 MarkSeedFree( seed ); seed = 0;
4355 FollowProlongation(*track, i2,1);
4356 track->SetBConstrain(0);
4357 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
4358 track->SetFirstPoint(track->GetLastPoint());
4360 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4361 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
4362 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
4363 MarkSeedFree( seed ); seed = 0;
4368 FollowProlongation(*track, TMath::Max(i2-10,0),1);
4369 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
4370 FollowProlongation(*track2, i2,1);
4371 track2->SetBConstrain(kFALSE);
4372 track2->SetSeedType(4);
4373 arr->AddLast(track2);
4374 MarkSeedFree( seed ); seed = 0;
4378 //arr->AddLast(track);
4379 //seed = new AliTPCseed;
4385 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);
4387 if (seed) MarkSeedFree(seed);
4391 //_____________________________________________________________________________
4392 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
4393 Float_t deltay, Bool_t /*bconstrain*/) {
4394 //-----------------------------------------------------------------
4395 // This function creates track seeds - without vertex constraint
4396 //-----------------------------------------------------------------
4397 // cuts[0] - fP4 cut - not applied
4398 // cuts[1] - tan(phi) cut
4399 // cuts[2] - zvertex cut - not applied
4400 // cuts[3] - fP3 cut
4410 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4411 // Double_t cs=cos(alpha), sn=sin(alpha);
4412 Int_t row0 = (i1+i2)/2;
4413 Int_t drow = (i1-i2)/2;
4414 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
4415 AliTPCtrackerRow * kr=0;
4417 AliTPCpolyTrack polytrack;
4418 Int_t nclusters=fSectors[sec][row0];
4419 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4420 seed->SetPoolID(fLastSeedID);
4425 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
4427 Int_t nfoundable =0;
4428 for (Int_t iter =1; iter<2; iter++){ //iterations
4429 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
4430 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
4431 const AliTPCclusterMI * cl= kr0[is];
4432 if (cl->IsDisabled()) {
4436 if (cl->IsUsed(10)) {
4442 Double_t x = kr0.GetX();
4443 // Initialization of the polytrack
4448 Double_t y0= cl->GetY();
4449 Double_t z0= cl->GetZ();
4453 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
4454 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
4456 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
4457 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
4458 polytrack.AddPoint(x,y0,z0,erry, errz);
4461 if (cl->IsUsed(10)) sumused++;
4464 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
4465 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
4468 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
4469 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
4470 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
4471 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
4472 if (cl1->IsUsed(10)) sumused++;
4473 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
4477 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
4479 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
4480 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
4481 if (cl2->IsUsed(10)) sumused++;
4482 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
4485 if (sumused>0) continue;
4487 polytrack.UpdateParameters();
4493 nfoundable = polytrack.GetN();
4494 nfound = nfoundable;
4496 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
4497 Float_t maxdist = 0.8*(1.+3./(ddrow));
4498 for (Int_t delta = -1;delta<=1;delta+=2){
4499 Int_t row = row0+ddrow*delta;
4500 kr = &(fSectors[sec][row]);
4501 Double_t xn = kr->GetX();
4502 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
4503 polytrack.GetFitPoint(xn,yn,zn);
4504 if (TMath::Abs(yn)>ymax1) continue;
4506 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
4508 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
4511 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4512 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4513 if (cln->IsUsed(10)) {
4514 // printf("used\n");
4522 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4527 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4528 polytrack.UpdateParameters();
4531 if ( (sumused>3) || (sumused>0.5*nfound)) {
4532 //printf("sumused %d\n",sumused);
4537 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4538 AliTPCpolyTrack track2;
4540 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4541 if (track2.GetN()<0.5*nfoundable) continue;
4544 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4546 // test seed with and without constrain
4547 for (Int_t constrain=0; constrain<=0;constrain++){
4548 // add polytrack candidate
4550 Double_t x[5], c[15];
4551 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4552 track2.GetBoundaries(x3,x1);
4554 track2.GetFitPoint(x1,y1,z1);
4555 track2.GetFitPoint(x2,y2,z2);
4556 track2.GetFitPoint(x3,y3,z3);
4558 //is track pointing to the vertex ?
4561 polytrack.GetFitPoint(x0,y0,z0);
4574 x[4]=F1(x1,y1,x2,y2,x3,y3);
4576 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4577 x[2]=F2(x1,y1,x2,y2,x3,y3);
4579 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4580 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4581 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4582 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4585 Double_t sy =0.1, sz =0.1;
4586 Double_t sy1=0.02, sz1=0.02;
4587 Double_t sy2=0.02, sz2=0.02;
4591 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4594 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4595 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4596 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4597 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4598 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4599 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4601 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4602 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4603 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4604 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4609 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4610 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4611 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4612 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4613 c[13]=f30*sy1*f40+f32*sy2*f42;
4614 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4616 //Int_t row1 = fSectors->GetRowNumber(x1);
4617 Int_t row1 = GetRowNumber(x1);
4621 if (seed) {MarkSeedFree( seed ); seed = 0;}
4622 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4623 seed->SetPoolID(fLastSeedID);
4624 track->SetIsSeeding(kTRUE);
4625 Int_t rc=FollowProlongation(*track, i2);
4626 if (constrain) track->SetBConstrain(1);
4628 track->SetBConstrain(0);
4629 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4630 track->SetFirstPoint(track->GetLastPoint());
4632 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4633 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4634 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4635 MarkSeedFree( seed ); seed = 0;
4638 arr->AddLast(track); // track IS seed, don't free seed
4639 seed = new( NextFreeSeed() ) AliTPCseed;
4640 seed->SetPoolID(fLastSeedID);
4644 } // if accepted seed
4647 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4649 if (seed) MarkSeedFree( seed );
4653 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4657 //reseed using track points
4658 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4659 Int_t p1 = int(r1*track->GetNumberOfClusters());
4660 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4662 Double_t x0[3],x1[3],x2[3];
4663 for (Int_t i=0;i<3;i++){
4669 // find track position at given ratio of the length
4670 Int_t sec0=0, sec1=0, sec2=0;
4673 for (Int_t i=0;i<160;i++){
4674 if (track->GetClusterPointer(i)){
4676 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4677 if ( (index<p0) || x0[0]<0 ){
4678 if (trpoint->GetX()>1){
4679 clindex = track->GetClusterIndex2(i);
4681 x0[0] = trpoint->GetX();
4682 x0[1] = trpoint->GetY();
4683 x0[2] = trpoint->GetZ();
4684 sec0 = ((clindex&0xff000000)>>24)%18;
4689 if ( (index<p1) &&(trpoint->GetX()>1)){
4690 clindex = track->GetClusterIndex2(i);
4692 x1[0] = trpoint->GetX();
4693 x1[1] = trpoint->GetY();
4694 x1[2] = trpoint->GetZ();
4695 sec1 = ((clindex&0xff000000)>>24)%18;
4698 if ( (index<p2) &&(trpoint->GetX()>1)){
4699 clindex = track->GetClusterIndex2(i);
4701 x2[0] = trpoint->GetX();
4702 x2[1] = trpoint->GetY();
4703 x2[2] = trpoint->GetZ();
4704 sec2 = ((clindex&0xff000000)>>24)%18;
4711 Double_t alpha, cs,sn, xx2,yy2;
4713 alpha = (sec1-sec2)*fSectors->GetAlpha();
4714 cs = TMath::Cos(alpha);
4715 sn = TMath::Sin(alpha);
4716 xx2= x1[0]*cs-x1[1]*sn;
4717 yy2= x1[0]*sn+x1[1]*cs;
4721 alpha = (sec0-sec2)*fSectors->GetAlpha();
4722 cs = TMath::Cos(alpha);
4723 sn = TMath::Sin(alpha);
4724 xx2= x0[0]*cs-x0[1]*sn;
4725 yy2= x0[0]*sn+x0[1]*cs;
4731 Double_t x[5],c[15];
4735 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4736 // if (x[4]>1) return 0;
4737 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4738 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4739 //if (TMath::Abs(x[3]) > 2.2) return 0;
4740 //if (TMath::Abs(x[2]) > 1.99) return 0;
4742 Double_t sy =0.1, sz =0.1;
4744 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4745 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4746 Double_t sy3=0.01+track->GetSigmaY2();
4748 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4749 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4750 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4751 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4752 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4753 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4755 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4756 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4757 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4758 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4763 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4764 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4765 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4766 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4767 c[13]=f30*sy1*f40+f32*sy2*f42;
4768 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4770 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4771 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4772 seed->SetPoolID(fLastSeedID);
4773 // Double_t y0,z0,y1,z1, y2,z2;
4774 //seed->GetProlongation(x0[0],y0,z0);
4775 // seed->GetProlongation(x1[0],y1,z1);
4776 //seed->GetProlongation(x2[0],y2,z2);
4778 seed->SetLastPoint(pp2);
4779 seed->SetFirstPoint(pp2);
4786 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4790 //reseed using founded clusters
4792 // Find the number of clusters
4793 Int_t nclusters = 0;
4794 for (Int_t irow=0;irow<160;irow++){
4795 if (track->GetClusterIndex(irow)>0) nclusters++;
4799 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4800 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4801 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4804 Double_t xyz[3][3]={{0}};
4805 Int_t row[3]={0},sec[3]={0,0,0};
4807 // find track row position at given ratio of the length
4809 for (Int_t irow=0;irow<160;irow++){
4810 if (track->GetClusterIndex2(irow)<0) continue;
4812 for (Int_t ipoint=0;ipoint<3;ipoint++){
4813 if (index<=ipos[ipoint]) row[ipoint] = irow;
4817 //Get cluster and sector position
4818 for (Int_t ipoint=0;ipoint<3;ipoint++){
4819 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4820 AliTPCclusterMI * cl = GetClusterMI(clindex);
4823 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4826 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4827 xyz[ipoint][0] = GetXrow(row[ipoint]);
4828 xyz[ipoint][1] = cl->GetY();
4829 xyz[ipoint][2] = cl->GetZ();
4833 // Calculate seed state vector and covariance matrix
4835 Double_t alpha, cs,sn, xx2,yy2;
4837 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4838 cs = TMath::Cos(alpha);
4839 sn = TMath::Sin(alpha);
4840 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4841 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4845 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4846 cs = TMath::Cos(alpha);
4847 sn = TMath::Sin(alpha);
4848 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4849 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4855 Double_t x[5],c[15];
4859 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4860 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4861 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4863 Double_t sy =0.1, sz =0.1;
4865 Double_t sy1=0.2, sz1=0.2;
4866 Double_t sy2=0.2, sz2=0.2;
4869 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;
4870 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;
4871 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;
4872 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;
4873 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;
4874 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;
4876 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;
4877 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;
4878 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;
4879 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;
4884 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4885 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4886 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4887 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4888 c[13]=f30*sy1*f40+f32*sy2*f42;
4889 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4891 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4892 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4893 seed->SetPoolID(fLastSeedID);
4894 seed->SetLastPoint(row[2]);
4895 seed->SetFirstPoint(row[2]);
4900 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4904 //reseed using founded clusters
4907 Int_t row[3]={0,0,0};
4908 Int_t sec[3]={0,0,0};
4910 // forward direction
4912 for (Int_t irow=r0;irow<160;irow++){
4913 if (track->GetClusterIndex(irow)>0){
4918 for (Int_t irow=160;irow>r0;irow--){
4919 if (track->GetClusterIndex(irow)>0){
4924 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4925 if (track->GetClusterIndex(irow)>0){
4933 for (Int_t irow=0;irow<r0;irow++){
4934 if (track->GetClusterIndex(irow)>0){
4939 for (Int_t irow=r0;irow>0;irow--){
4940 if (track->GetClusterIndex(irow)>0){
4945 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4946 if (track->GetClusterIndex(irow)>0){
4953 if ((row[2]-row[0])<20) return 0;
4954 if (row[1]==0) return 0;
4957 //Get cluster and sector position
4958 for (Int_t ipoint=0;ipoint<3;ipoint++){
4959 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4960 AliTPCclusterMI * cl = GetClusterMI(clindex);
4963 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4966 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4967 xyz[ipoint][0] = GetXrow(row[ipoint]);
4968 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4969 if (point&&ipoint<2){
4971 xyz[ipoint][1] = point->GetY();
4972 xyz[ipoint][2] = point->GetZ();
4975 xyz[ipoint][1] = cl->GetY();
4976 xyz[ipoint][2] = cl->GetZ();
4983 // Calculate seed state vector and covariance matrix
4985 Double_t alpha, cs,sn, xx2,yy2;
4987 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4988 cs = TMath::Cos(alpha);
4989 sn = TMath::Sin(alpha);
4990 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4991 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4995 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4996 cs = TMath::Cos(alpha);
4997 sn = TMath::Sin(alpha);
4998 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4999 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
5005 Double_t x[5],c[15];
5009 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5010 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5011 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
5013 Double_t sy =0.1, sz =0.1;
5015 Double_t sy1=0.2, sz1=0.2;
5016 Double_t sy2=0.2, sz2=0.2;
5019 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;
5020 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;
5021 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;
5022 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;
5023 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;
5024 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;
5026 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;
5027 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;
5028 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;
5029 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;
5034 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
5035 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
5036 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
5037 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
5038 c[13]=f30*sy1*f40+f32*sy2*f42;
5039 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
5041 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
5042 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
5043 seed->SetPoolID(fLastSeedID);
5044 seed->SetLastPoint(row[2]);
5045 seed->SetFirstPoint(row[2]);
5046 for (Int_t i=row[0];i<row[2];i++){
5047 seed->SetClusterIndex(i, track->GetClusterIndex(i));
5055 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5058 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
5060 // Use AliTPCReconstructor::StreamLevel()& kStreamFindMultiMC if you want to tune parameters - cuts
5062 // Two reasons to have multiple find tracks
5063 // 1. Curling tracks can be find more than once
5064 // 2. Splitted tracks
5065 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
5066 // b.) Edge effect on the sector boundaries
5069 // Algorithm done in 2 phases - because of CPU consumption
5070 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
5072 // Algorihm for curling tracks sign:
5073 // 1 phase -makes a very rough fast cuts to minimize combinatorics
5074 // a.) opposite sign
5075 // b.) one of the tracks - not pointing to the primary vertex -
5076 // c.) delta tan(theta)
5078 // 2 phase - calculates DCA between tracks - time consument
5083 // General cuts - for splitted tracks and for curling tracks
5085 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
5087 // Curling tracks cuts
5092 Int_t nentries = array->GetEntriesFast();
5093 AliHelix *helixes = new AliHelix[nentries];
5094 Float_t *xm = new Float_t[nentries];
5095 Float_t *dz0 = new Float_t[nentries];
5096 Float_t *dz1 = new Float_t[nentries];
5102 // Find track COG in x direction - point with best defined parameters
5104 for (Int_t i=0;i<nentries;i++){
5105 AliTPCseed* track = (AliTPCseed*)array->At(i);
5106 if (!track) continue;
5107 track->SetCircular(0);
5108 new (&helixes[i]) AliHelix(*track);
5112 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
5115 for (Int_t icl=0; icl<160; icl++){
5116 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
5122 if (ncl>0) xm[i]/=Float_t(ncl);
5125 for (Int_t i0=0;i0<nentries;i0++){
5126 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5127 if (!track0) continue;
5128 Float_t xc0 = helixes[i0].GetHelix(6);
5129 Float_t yc0 = helixes[i0].GetHelix(7);
5130 Float_t r0 = helixes[i0].GetHelix(8);
5131 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5132 Float_t fi0 = TMath::ATan2(yc0,xc0);
5134 for (Int_t i1=i0+1;i1<nentries;i1++){
5135 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5136 if (!track1) continue;
5137 Int_t lab0=track0->GetLabel();
5138 Int_t lab1=track1->GetLabel();
5139 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
5141 Float_t xc1 = helixes[i1].GetHelix(6);
5142 Float_t yc1 = helixes[i1].GetHelix(7);
5143 Float_t r1 = helixes[i1].GetHelix(8);
5144 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5145 Float_t fi1 = TMath::ATan2(yc1,xc1);
5147 Float_t dfi = fi0-fi1;
5150 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
5151 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
5152 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
5154 // if short tracks with undefined sign
5155 fi1 = -TMath::ATan2(yc1,-xc1);
5158 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5161 // debug stream to tune "fast cuts"
5163 Double_t dist[3]; // distance at X
5164 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
5165 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
5166 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5167 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
5168 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5169 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
5170 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5171 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
5175 for (Int_t icl=0; icl<160; icl++){
5176 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
5177 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
5180 if (cl0==cl1) sums++;
5184 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) { // flag: stream MC infomation about the multiple find track (ONLY for MC data)
5185 TTreeSRedirector &cstream = *fDebugStreamer;
5190 "Tr0.="<<track0<< // seed0
5191 "Tr1.="<<track1<< // seed1
5192 "h0.="<<&helixes[i0]<<
5193 "h1.="<<&helixes[i1]<<
5195 "sum="<<sum<< //the sum of rows with cl in both
5196 "sums="<<sums<< //the sum of shared clusters
5197 "xm0="<<xm[i0]<< // the center of track
5198 "xm1="<<xm[i1]<< // the x center of track
5199 // General cut variables
5200 "dfi="<<dfi<< // distance in fi angle
5201 "dtheta="<<dtheta<< // distance int theta angle
5207 "dist0="<<dist[0]<< //distance x
5208 "dist1="<<dist[1]<< //distance y
5209 "dist2="<<dist[2]<< //distance z
5210 "mdist0="<<mdist[0]<< //distance x
5211 "mdist1="<<mdist[1]<< //distance y
5212 "mdist2="<<mdist[2]<< //distance z
5228 if (AliTPCReconstructor::StreamLevel()>0) {
5229 AliInfo("Time for curling tracks removal DEBUGGING MC");
5236 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
5238 // Find Splitted tracks and remove the one with worst quality
5239 // Corresponding debug streamer to tune selections - "Splitted2"
5241 // 0. Sort tracks according quality
5242 // 1. Propagate the tracks to the reference radius
5243 // 2. Double_t loop to select close tracks (only to speed up process)
5244 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
5245 // 4. Delete temporary parameters
5247 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
5249 const Double_t kCutP1=10; // delta Z cut 10 cm
5250 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
5251 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
5252 const Double_t kCutAlpha=0.15; // delta alpha cut
5253 Int_t firstpoint = 0;
5254 Int_t lastpoint = 160;
5256 Int_t nentries = array->GetEntriesFast();
5257 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
5263 //0. Sort tracks according quality
5264 //1. Propagate the ext. param to reference radius
5265 Int_t nseed = array->GetEntriesFast();
5266 if (nseed<=0) return;
5267 Float_t * quality = new Float_t[nseed];
5268 Int_t * indexes = new Int_t[nseed];
5269 for (Int_t i=0; i<nseed; i++) {
5270 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
5275 pt->UpdatePoints(); //select first last max dens points
5276 Float_t * points = pt->GetPoints();
5277 if (points[3]<0.8) quality[i] =-1;
5278 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
5279 //prefer high momenta tracks if overlaps
5280 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
5282 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
5283 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
5285 TMath::Sort(nseed,quality,indexes);
5287 // 3. Loop over pair of tracks
5289 for (Int_t i0=0; i0<nseed; i0++) {
5290 Int_t index0=indexes[i0];
5291 if (!(array->UncheckedAt(index0))) continue;
5292 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
5293 if (!s1->IsActive()) continue;
5294 AliExternalTrackParam &par0=params[index0];
5295 for (Int_t i1=i0+1; i1<nseed; i1++) {
5296 Int_t index1=indexes[i1];
5297 if (!(array->UncheckedAt(index1))) continue;
5298 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
5299 if (!s2->IsActive()) continue;
5300 if (s2->GetKinkIndexes()[0]!=0)
5301 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
5302 AliExternalTrackParam &par1=params[index1];
5303 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
5304 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
5305 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
5306 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
5307 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
5308 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
5313 Int_t firstShared=lastpoint, lastShared=firstpoint;
5314 Int_t firstRow=lastpoint, lastRow=firstpoint;
5316 for (Int_t i=firstpoint;i<lastpoint;i++){
5317 if (s1->GetClusterIndex2(i)>0) nall0++;
5318 if (s2->GetClusterIndex2(i)>0) nall1++;
5319 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
5320 if (i<firstRow) firstRow=i;
5321 if (i>lastRow) lastRow=i;
5323 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
5324 if (i<firstShared) firstShared=i;
5325 if (i>lastShared) lastShared=i;
5329 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
5330 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
5332 if ((AliTPCReconstructor::StreamLevel()&kStreamSplitted2)>0){ // flag:stream information about discarded TPC tracks pair algorithm
5333 TTreeSRedirector &cstream = *fDebugStreamer;
5334 Int_t n0=s1->GetNumberOfClusters();
5335 Int_t n1=s2->GetNumberOfClusters();
5336 Int_t n0F=s1->GetNFoundable();
5337 Int_t n1F=s2->GetNFoundable();
5338 Int_t lab0=s1->GetLabel();
5339 Int_t lab1=s2->GetLabel();
5341 cstream<<"Splitted2"<< // flag:stream information about discarded TPC tracks pair algorithm
5342 "iter="<<fIteration<<
5343 "lab0="<<lab0<< // MC label if exist
5344 "lab1="<<lab1<< // MC label if exist
5347 "ratio0="<<ratio0<< // shared ratio
5348 "ratio1="<<ratio1<< // shared ratio
5349 "p0.="<<&par0<< // track parameters
5351 "s0.="<<s1<< // full seed
5353 "n0="<<n0<< // number of clusters track 0
5354 "n1="<<n1<< // number of clusters track 1
5355 "nall0="<<nall0<< // number of clusters track 0
5356 "nall1="<<nall1<< // number of clusters track 1
5357 "n0F="<<n0F<< // number of findable
5358 "n1F="<<n1F<< // number of findable
5359 "shared="<<sumShared<< // number of shared clusters
5360 "firstS="<<firstShared<< // first and the last shared row
5361 "lastS="<<lastShared<<
5362 "firstRow="<<firstRow<< // first and the last row with cluster
5363 "lastRow="<<lastRow<< //
5367 // remove track with lower quality
5369 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
5370 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
5374 MarkSeedFree( array->RemoveAt(index1) );
5379 // 4. Delete temporary array
5389 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5392 // find Curling tracks
5393 // Use AliTPCReconstructor::StreamLevel()&kStreamFindCurling if you want to tune parameters - cuts
5396 // Algorithm done in 2 phases - because of CPU consumption
5397 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
5398 // see detal in MC part what can be used to cut
5402 const Float_t kMaxC = 400; // maximal curvature to of the track
5403 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
5404 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
5405 const Float_t kPtRatio = 0.3; // ratio between pt
5406 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
5409 // Curling tracks cuts
5412 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
5413 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
5414 const Float_t kMinAngle = 2.9; // angle between tracks
5415 const Float_t kMaxDist = 5; // biggest distance
5417 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
5420 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
5421 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
5422 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
5423 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
5424 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
5426 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
5427 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
5429 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
5430 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
5432 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
5438 Int_t nentries = array->GetEntriesFast();
5439 AliHelix *helixes = new AliHelix[nentries];
5440 for (Int_t i=0;i<nentries;i++){
5441 AliTPCseed* track = (AliTPCseed*)array->At(i);
5442 if (!track) continue;
5443 track->SetCircular(0);
5444 new (&helixes[i]) AliHelix(*track);
5450 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5456 for (Int_t i0=0;i0<nentries;i0++){
5457 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5458 if (!track0) continue;
5459 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
5460 Float_t xc0 = helixes[i0].GetHelix(6);
5461 Float_t yc0 = helixes[i0].GetHelix(7);
5462 Float_t r0 = helixes[i0].GetHelix(8);
5463 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5464 Float_t fi0 = TMath::ATan2(yc0,xc0);
5466 for (Int_t i1=i0+1;i1<nentries;i1++){
5467 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5468 if (!track1) continue;
5469 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
5470 Float_t xc1 = helixes[i1].GetHelix(6);
5471 Float_t yc1 = helixes[i1].GetHelix(7);
5472 Float_t r1 = helixes[i1].GetHelix(8);
5473 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5474 Float_t fi1 = TMath::ATan2(yc1,xc1);
5476 Float_t dfi = fi0-fi1;
5479 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
5480 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
5481 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5485 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
5486 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
5487 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
5488 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
5489 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
5491 Float_t pt0 = track0->GetSignedPt();
5492 Float_t pt1 = track1->GetSignedPt();
5493 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
5494 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
5495 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
5496 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
5499 // Now find closest approach
5503 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5504 if (npoints==0) continue;
5505 helixes[i0].GetClosestPhases(helixes[i1], phase);
5509 Double_t hangles[3];
5510 helixes[i0].Evaluate(phase[0][0],xyz0);
5511 helixes[i1].Evaluate(phase[0][1],xyz1);
5513 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5514 Double_t deltah[2],deltabest;
5515 if (TMath::Abs(hangles[2])<kMinAngle) continue;
5519 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5521 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5522 if (deltah[1]<deltah[0]) ibest=1;
5524 deltabest = TMath::Sqrt(deltah[ibest]);
5525 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5526 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5527 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5528 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5530 if (deltabest>kMaxDist) continue;
5531 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5532 Bool_t sign =kFALSE;
5533 if (hangles[2]>kMinAngle) sign =kTRUE;
5536 // circular[i0] = kTRUE;
5537 // circular[i1] = kTRUE;
5538 if (track0->OneOverPt()<track1->OneOverPt()){
5539 track0->SetCircular(track0->GetCircular()+1);
5540 track1->SetCircular(track1->GetCircular()+2);
5543 track1->SetCircular(track1->GetCircular()+1);
5544 track0->SetCircular(track0->GetCircular()+2);
5547 if ((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0){ // flag: stream track infroamtion if the FindCurling tracks method
5549 //debug stream to tune "fine" cuts
5550 Int_t lab0=track0->GetLabel();
5551 Int_t lab1=track1->GetLabel();
5552 TTreeSRedirector &cstream = *fDebugStreamer;
5553 cstream<<"Curling2"<<
5569 "npoints="<<npoints<<
5570 "hangles0="<<hangles[0]<<
5571 "hangles1="<<hangles[1]<<
5572 "hangles2="<<hangles[2]<<
5575 "radius="<<radiusbest<<
5576 "deltabest="<<deltabest<<
5577 "phase0="<<phase[ibest][0]<<
5578 "phase1="<<phase[ibest][1]<<
5586 if (AliTPCReconstructor::StreamLevel()>1) {
5587 AliInfo("Time for curling tracks removal");
5593 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5599 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5602 TObjArray *kinks= new TObjArray(10000);
5603 // TObjArray *v0s= new TObjArray(10000);
5604 Int_t nentries = array->GetEntriesFast();
5605 AliHelix *helixes = new AliHelix[nentries];
5606 Int_t *sign = new Int_t[nentries];
5607 Int_t *nclusters = new Int_t[nentries];
5608 Float_t *alpha = new Float_t[nentries];
5609 AliKink *kink = new AliKink();
5610 Int_t * usage = new Int_t[nentries];
5611 Float_t *zm = new Float_t[nentries];
5612 Float_t *z0 = new Float_t[nentries];
5613 Float_t *fim = new Float_t[nentries];
5614 Float_t *shared = new Float_t[nentries];
5615 Bool_t *circular = new Bool_t[nentries];
5616 Float_t *dca = new Float_t[nentries];
5617 //const AliESDVertex * primvertex = esd->GetVertex();
5619 // nentries = array->GetEntriesFast();
5624 for (Int_t i=0;i<nentries;i++){
5627 AliTPCseed* track = (AliTPCseed*)array->At(i);
5628 if (!track) continue;
5629 track->SetCircular(0);
5631 track->UpdatePoints();
5632 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5634 nclusters[i]=track->GetNumberOfClusters();
5635 alpha[i] = track->GetAlpha();
5636 new (&helixes[i]) AliHelix(*track);
5638 helixes[i].Evaluate(0,xyz);
5639 sign[i] = (track->GetC()>0) ? -1:1;
5642 if (track->GetProlongation(x,y,z)){
5644 fim[i] = alpha[i]+TMath::ATan2(y,x);
5647 zm[i] = track->GetZ();
5651 circular[i]= kFALSE;
5652 if (track->GetProlongation(0,y,z)) z0[i] = z;
5653 dca[i] = track->GetD(0,0);
5659 Int_t ncandidates =0;
5662 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5665 // Find circling track
5667 for (Int_t i0=0;i0<nentries;i0++){
5668 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5669 if (!track0) continue;
5670 if (track0->GetNumberOfClusters()<40) continue;
5671 if (TMath::Abs(1./track0->GetC())>200) continue;
5672 for (Int_t i1=i0+1;i1<nentries;i1++){
5673 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5674 if (!track1) continue;
5675 if (track1->GetNumberOfClusters()<40) continue;
5676 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5677 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5678 if (TMath::Abs(1./track1->GetC())>200) continue;
5679 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5680 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5681 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5682 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5683 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5685 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5686 if (mindcar<5) continue;
5687 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5688 if (mindcaz<5) continue;
5689 if (mindcar+mindcaz<20) continue;
5692 Float_t xc0 = helixes[i0].GetHelix(6);
5693 Float_t yc0 = helixes[i0].GetHelix(7);
5694 Float_t r0 = helixes[i0].GetHelix(8);
5695 Float_t xc1 = helixes[i1].GetHelix(6);
5696 Float_t yc1 = helixes[i1].GetHelix(7);
5697 Float_t r1 = helixes[i1].GetHelix(8);
5699 Float_t rmean = (r0+r1)*0.5;
5700 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5701 //if (delta>30) continue;
5702 if (delta>rmean*0.25) continue;
5703 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5705 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5706 if (npoints==0) continue;
5707 helixes[i0].GetClosestPhases(helixes[i1], phase);
5711 Double_t hangles[3];
5712 helixes[i0].Evaluate(phase[0][0],xyz0);
5713 helixes[i1].Evaluate(phase[0][1],xyz1);
5715 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5716 Double_t deltah[2],deltabest;
5717 if (hangles[2]<2.8) continue;
5720 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5722 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5723 if (deltah[1]<deltah[0]) ibest=1;
5725 deltabest = TMath::Sqrt(deltah[ibest]);
5726 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5727 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5728 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5729 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5731 if (deltabest>6) continue;
5732 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5733 Bool_t lsign =kFALSE;
5734 if (hangles[2]>3.06) lsign =kTRUE;
5737 circular[i0] = kTRUE;
5738 circular[i1] = kTRUE;
5739 if (track0->OneOverPt()<track1->OneOverPt()){
5740 track0->SetCircular(track0->GetCircular()+1);
5741 track1->SetCircular(track1->GetCircular()+2);
5744 track1->SetCircular(track1->GetCircular()+1);
5745 track0->SetCircular(track0->GetCircular()+2);
5748 if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0)){
5750 Int_t lab0=track0->GetLabel();
5751 Int_t lab1=track1->GetLabel();
5752 TTreeSRedirector &cstream = *fDebugStreamer;
5753 cstream<<"Curling"<<
5760 "mindcar="<<mindcar<<
5761 "mindcaz="<<mindcaz<<
5764 "npoints="<<npoints<<
5765 "hangles0="<<hangles[0]<<
5766 "hangles2="<<hangles[2]<<
5771 "radius="<<radiusbest<<
5772 "deltabest="<<deltabest<<
5773 "phase0="<<phase[ibest][0]<<
5774 "phase1="<<phase[ibest][1]<<
5784 for (Int_t i =0;i<nentries;i++){
5785 if (sign[i]==0) continue;
5786 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5793 Double_t cradius0 = 40*40;
5794 Double_t cradius1 = 270*270;
5797 Double_t cdist3=0.55;
5798 for (Int_t j =i+1;j<nentries;j++){
5800 if (sign[j]*sign[i]<1) continue;
5801 if ( (nclusters[i]+nclusters[j])>200) continue;
5802 if ( (nclusters[i]+nclusters[j])<80) continue;
5803 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5804 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5805 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5806 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5807 if (npoints<1) continue;
5810 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5813 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5816 Double_t delta1=10000,delta2=10000;
5817 // cuts on the intersection radius
5818 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5819 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5820 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5822 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5823 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5824 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5827 Double_t distance1 = TMath::Min(delta1,delta2);
5828 if (distance1>cdist1) continue; // cut on DCA linear approximation
5830 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5831 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5832 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5833 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5836 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5837 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5838 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5840 distance1 = TMath::Min(delta1,delta2);
5843 rkink = TMath::Sqrt(radius[0]);
5846 rkink = TMath::Sqrt(radius[1]);
5848 if (distance1>cdist2) continue;
5851 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5854 Int_t row0 = GetRowNumber(rkink);
5855 if (row0<10) continue;
5856 if (row0>150) continue;
5859 Float_t dens00=-1,dens01=-1;
5860 Float_t dens10=-1,dens11=-1;
5862 Int_t found,foundable,ishared;
5863 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5864 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5865 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5866 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5868 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5869 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5870 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5871 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5873 if (dens00<dens10 && dens01<dens11) continue;
5874 if (dens00>dens10 && dens01>dens11) continue;
5875 if (TMath::Max(dens00,dens10)<0.1) continue;
5876 if (TMath::Max(dens01,dens11)<0.3) continue;
5878 if (TMath::Min(dens00,dens10)>0.6) continue;
5879 if (TMath::Min(dens01,dens11)>0.6) continue;
5882 AliTPCseed * ktrack0, *ktrack1;
5891 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5892 AliExternalTrackParam paramm(*ktrack0);
5893 AliExternalTrackParam paramd(*ktrack1);
5894 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5897 kink->SetMother(paramm);
5898 kink->SetDaughter(paramd);
5901 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])};
5903 fkParam->Transform0to1(x,index);
5904 fkParam->Transform1to2(x,index);
5905 row0 = GetRowNumber(x[0]);
5907 if (kink->GetR()<100) continue;
5908 if (kink->GetR()>240) continue;
5909 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5910 if (kink->GetDistance()>cdist3) continue;
5911 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5912 if (dird<0) continue;
5914 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5915 if (dirm<0) continue;
5916 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5917 if (mpt<0.2) continue;
5920 //for high momenta momentum not defined well in first iteration
5921 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5922 if (qt>0.35) continue;
5925 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5926 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5928 kink->SetTPCDensity(dens00,0,0);
5929 kink->SetTPCDensity(dens01,0,1);
5930 kink->SetTPCDensity(dens10,1,0);
5931 kink->SetTPCDensity(dens11,1,1);
5932 kink->SetIndex(i,0);
5933 kink->SetIndex(j,1);
5936 kink->SetTPCDensity(dens10,0,0);
5937 kink->SetTPCDensity(dens11,0,1);
5938 kink->SetTPCDensity(dens00,1,0);
5939 kink->SetTPCDensity(dens01,1,1);
5940 kink->SetIndex(j,0);
5941 kink->SetIndex(i,1);
5944 if (mpt<1||kink->GetAngle(2)>0.1){
5945 // angle and densities not defined yet
5946 if (kink->GetTPCDensityFactor()<0.8) continue;
5947 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5948 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5949 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5950 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5952 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5953 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5954 criticalangle= 3*TMath::Sqrt(criticalangle);
5955 if (criticalangle>0.02) criticalangle=0.02;
5956 if (kink->GetAngle(2)<criticalangle) continue;
5959 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5960 Float_t shapesum =0;
5962 for ( Int_t row = row0-drow; row<row0+drow;row++){
5963 if (row<0) continue;
5964 if (row>155) continue;
5965 if (ktrack0->GetClusterPointer(row)){
5966 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5967 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5970 if (ktrack1->GetClusterPointer(row)){
5971 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5972 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5977 kink->SetShapeFactor(-1.);
5980 kink->SetShapeFactor(shapesum/sum);
5982 // esd->AddKink(kink);
5984 // kink->SetMother(paramm);
5985 //kink->SetDaughter(paramd);
5987 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5989 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5990 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5992 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5994 if ((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0) { // flag: stream track infroamtion in the FindKinks method
5995 (*fDebugStreamer)<<"kinkLpt"<<
6003 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6007 kinks->AddLast(kink);
6013 // sort the kinks according quality - and refit them towards vertex
6015 Int_t nkinks = kinks->GetEntriesFast();
6016 Float_t *quality = new Float_t[nkinks];
6017 Int_t *indexes = new Int_t[nkinks];
6018 AliTPCseed *mothers = new AliTPCseed[nkinks];
6019 AliTPCseed *daughters = new AliTPCseed[nkinks];
6022 for (Int_t i=0;i<nkinks;i++){
6024 AliKink *kinkl = (AliKink*)kinks->At(i);
6026 // refit kinks towards vertex
6028 Int_t index0 = kinkl->GetIndex(0);
6029 Int_t index1 = kinkl->GetIndex(1);
6030 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6031 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6033 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6035 // Refit Kink under if too small angle
6037 if (kinkl->GetAngle(2)<0.05){
6038 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6039 Int_t row0 = kinkl->GetTPCRow0();
6040 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6043 Int_t last = row0-drow;
6044 if (last<40) last=40;
6045 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6046 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6049 Int_t first = row0+drow;
6050 if (first>130) first=130;
6051 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6052 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6054 if (seed0 && seed1){
6055 kinkl->SetStatus(1,8);
6056 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6057 row0 = GetRowNumber(kinkl->GetR());
6058 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6059 mothers[i] = *seed0;
6060 daughters[i] = *seed1;
6063 delete kinks->RemoveAt(i);
6064 if (seed0) MarkSeedFree( seed0 );
6065 if (seed1) MarkSeedFree( seed1 );
6068 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6069 delete kinks->RemoveAt(i);
6070 if (seed0) MarkSeedFree( seed0 );
6071 if (seed1) MarkSeedFree( seed1 );
6075 MarkSeedFree( seed0 );
6076 MarkSeedFree( seed1 );
6079 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6081 TMath::Sort(nkinks,quality,indexes,kFALSE);
6083 //remove double find kinks
6085 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6086 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6087 if (!kink0) continue;
6089 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6090 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6091 if (!kink0) continue;
6092 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6093 if (!kink1) continue;
6094 // if not close kink continue
6095 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6096 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6097 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6099 AliTPCseed &mother0 = mothers[indexes[ikink0]];
6100 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
6101 AliTPCseed &mother1 = mothers[indexes[ikink1]];
6102 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
6103 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6112 for (Int_t i=0;i<row0;i++){
6113 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6116 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6123 for (Int_t i=row0;i<158;i++){
6124 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6125 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6128 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6134 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6135 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6136 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6137 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6138 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6139 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6141 shared[kink0->GetIndex(0)]= kTRUE;
6142 shared[kink0->GetIndex(1)]= kTRUE;
6143 delete kinks->RemoveAt(indexes[ikink0]);
6147 shared[kink1->GetIndex(0)]= kTRUE;
6148 shared[kink1->GetIndex(1)]= kTRUE;
6149 delete kinks->RemoveAt(indexes[ikink1]);
6156 for (Int_t i=0;i<nkinks;i++){
6157 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6158 if (!kinkl) continue;
6159 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6160 Int_t index0 = kinkl->GetIndex(0);
6161 Int_t index1 = kinkl->GetIndex(1);
6162 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6163 kinkl->SetMultiple(usage[index0],0);
6164 kinkl->SetMultiple(usage[index1],1);
6165 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6166 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6167 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6168 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6170 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6171 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6172 if (!ktrack0 || !ktrack1) continue;
6173 Int_t index = esd->AddKink(kinkl);
6176 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6177 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
6178 *ktrack0 = mothers[indexes[i]];
6179 *ktrack1 = daughters[indexes[i]];
6183 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6184 ktrack1->SetKinkIndex(usage[index1], (index+1));
6189 // Remove tracks corresponding to shared kink's
6191 for (Int_t i=0;i<nentries;i++){
6192 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6193 if (!track0) continue;
6194 if (track0->GetKinkIndex(0)!=0) continue;
6195 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6200 RemoveUsed2(array,0.5,0.4,30);
6202 for (Int_t i=0;i<nentries;i++){
6203 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6204 if (!track0) continue;
6205 track0->CookdEdx(0.02,0.6);
6209 for (Int_t i=0;i<nentries;i++){
6210 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6211 if (!track0) continue;
6212 if (track0->Pt()<1.4) continue;
6213 //remove double high momenta tracks - overlapped with kink candidates
6216 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6217 if (track0->GetClusterPointer(icl)!=0){
6219 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6222 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6223 MarkSeedFree( array->RemoveAt(i) );
6227 if (track0->GetKinkIndex(0)!=0) continue;
6228 if (track0->GetNumberOfClusters()<80) continue;
6230 AliTPCseed *pmother = new AliTPCseed();
6231 AliTPCseed *pdaughter = new AliTPCseed();
6232 AliKink *pkink = new AliKink;
6234 AliTPCseed & mother = *pmother;
6235 AliTPCseed & daughter = *pdaughter;
6236 AliKink & kinkl = *pkink;
6237 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6238 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6242 continue; //too short tracks
6244 if (mother.Pt()<1.4) {
6250 Int_t row0= kinkl.GetTPCRow0();
6251 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6258 Int_t index = esd->AddKink(&kinkl);
6259 mother.SetKinkIndex(0,-(index+1));
6260 daughter.SetKinkIndex(0,index+1);
6261 if (mother.GetNumberOfClusters()>50) {
6262 MarkSeedFree( array->RemoveAt(i) );
6263 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6264 mtc->SetPoolID(fLastSeedID);
6265 array->AddAt(mtc,i);
6268 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6269 mtc->SetPoolID(fLastSeedID);
6270 array->AddLast(mtc);
6272 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6273 dtc->SetPoolID(fLastSeedID);
6274 array->AddLast(dtc);
6275 for (Int_t icl=0;icl<row0;icl++) {
6276 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6279 for (Int_t icl=row0;icl<158;icl++) {
6280 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6289 delete [] daughters;
6311 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6317 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
6324 TObjArray *kinks= new TObjArray(10000);
6325 // TObjArray *v0s= new TObjArray(10000);
6326 Int_t nentries = array->GetEntriesFast();
6327 AliHelix *helixes = new AliHelix[nentries];
6328 Int_t *sign = new Int_t[nentries];
6329 Int_t *nclusters = new Int_t[nentries];
6330 Float_t *alpha = new Float_t[nentries];
6331 AliKink *kink = new AliKink();
6332 Int_t * usage = new Int_t[nentries];
6333 Float_t *zm = new Float_t[nentries];
6334 Float_t *z0 = new Float_t[nentries];
6335 Float_t *fim = new Float_t[nentries];
6336 Float_t *shared = new Float_t[nentries];
6337 Bool_t *circular = new Bool_t[nentries];
6338 Float_t *dca = new Float_t[nentries];
6339 //const AliESDVertex * primvertex = esd->GetVertex();
6341 // nentries = array->GetEntriesFast();
6346 for (Int_t i=0;i<nentries;i++){
6349 AliTPCseed* track = (AliTPCseed*)array->At(i);
6350 if (!track) continue;
6351 track->SetCircular(0);
6353 track->UpdatePoints();
6354 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
6356 nclusters[i]=track->GetNumberOfClusters();
6357 alpha[i] = track->GetAlpha();
6358 new (&helixes[i]) AliHelix(*track);
6360 helixes[i].Evaluate(0,xyz);
6361 sign[i] = (track->GetC()>0) ? -1:1;
6364 if (track->GetProlongation(x,y,z)){
6366 fim[i] = alpha[i]+TMath::ATan2(y,x);
6369 zm[i] = track->GetZ();
6373 circular[i]= kFALSE;
6374 if (track->GetProlongation(0,y,z)) z0[i] = z;
6375 dca[i] = track->GetD(0,0);
6381 Int_t ncandidates =0;
6384 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
6387 // Find circling track
6389 for (Int_t i0=0;i0<nentries;i0++){
6390 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
6391 if (!track0) continue;
6392 if (track0->GetNumberOfClusters()<40) continue;
6393 if (TMath::Abs(1./track0->GetC())>200) continue;
6394 for (Int_t i1=i0+1;i1<nentries;i1++){
6395 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
6396 if (!track1) continue;
6397 if (track1->GetNumberOfClusters()<40) continue;
6398 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
6399 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
6400 if (TMath::Abs(1./track1->GetC())>200) continue;
6401 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
6402 if (track1->GetTgl()*track0->GetTgl()>0) continue;
6403 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
6404 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
6405 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
6407 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
6408 if (mindcar<5) continue;
6409 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
6410 if (mindcaz<5) continue;
6411 if (mindcar+mindcaz<20) continue;
6414 Float_t xc0 = helixes[i0].GetHelix(6);
6415 Float_t yc0 = helixes[i0].GetHelix(7);
6416 Float_t r0 = helixes[i0].GetHelix(8);
6417 Float_t xc1 = helixes[i1].GetHelix(6);
6418 Float_t yc1 = helixes[i1].GetHelix(7);
6419 Float_t r1 = helixes[i1].GetHelix(8);
6421 Float_t rmean = (r0+r1)*0.5;
6422 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
6423 //if (delta>30) continue;
6424 if (delta>rmean*0.25) continue;
6425 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
6427 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
6428 if (npoints==0) continue;
6429 helixes[i0].GetClosestPhases(helixes[i1], phase);
6433 Double_t hangles[3];
6434 helixes[i0].Evaluate(phase[0][0],xyz0);
6435 helixes[i1].Evaluate(phase[0][1],xyz1);
6437 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
6438 Double_t deltah[2],deltabest;
6439 if (hangles[2]<2.8) continue;
6442 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
6444 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
6445 if (deltah[1]<deltah[0]) ibest=1;
6447 deltabest = TMath::Sqrt(deltah[ibest]);
6448 helixes[i0].Evaluate(phase[ibest][0],xyz0);
6449 helixes[i1].Evaluate(phase[ibest][1],xyz1);
6450 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
6451 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
6453 if (deltabest>6) continue;
6454 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
6455 Bool_t lsign =kFALSE;
6456 if (hangles[2]>3.06) lsign =kTRUE;
6459 circular[i0] = kTRUE;
6460 circular[i1] = kTRUE;
6461 if (track0->OneOverPt()<track1->OneOverPt()){
6462 track0->SetCircular(track0->GetCircular()+1);
6463 track1->SetCircular(track1->GetCircular()+2);
6466 track1->SetCircular(track1->GetCircular()+1);
6467 track0->SetCircular(track0->GetCircular()+2);
6470 if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0)){// flag: stream track infroamtion in the FindKinks method
6472 Int_t lab0=track0->GetLabel();
6473 Int_t lab1=track1->GetLabel();
6474 TTreeSRedirector &cstream = *fDebugStreamer;
6475 cstream<<"Curling"<<
6482 "mindcar="<<mindcar<<
6483 "mindcaz="<<mindcaz<<
6486 "npoints="<<npoints<<
6487 "hangles0="<<hangles[0]<<
6488 "hangles2="<<hangles[2]<<
6493 "radius="<<radiusbest<<
6494 "deltabest="<<deltabest<<
6495 "phase0="<<phase[ibest][0]<<
6496 "phase1="<<phase[ibest][1]<<
6506 for (Int_t i =0;i<nentries;i++){
6507 if (sign[i]==0) continue;
6508 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6515 Double_t cradius0 = 40*40;
6516 Double_t cradius1 = 270*270;
6519 Double_t cdist3=0.55;
6520 for (Int_t j =i+1;j<nentries;j++){
6522 if (sign[j]*sign[i]<1) continue;
6523 if ( (nclusters[i]+nclusters[j])>200) continue;
6524 if ( (nclusters[i]+nclusters[j])<80) continue;
6525 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6526 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6527 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6528 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6529 if (npoints<1) continue;
6532 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6535 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6538 Double_t delta1=10000,delta2=10000;
6539 // cuts on the intersection radius
6540 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6541 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6542 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6544 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6545 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6546 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6549 Double_t distance1 = TMath::Min(delta1,delta2);
6550 if (distance1>cdist1) continue; // cut on DCA linear approximation
6552 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6553 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6554 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6555 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6558 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6559 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6560 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6562 distance1 = TMath::Min(delta1,delta2);
6565 rkink = TMath::Sqrt(radius[0]);
6568 rkink = TMath::Sqrt(radius[1]);
6570 if (distance1>cdist2) continue;
6573 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6576 Int_t row0 = GetRowNumber(rkink);
6577 if (row0<10) continue;
6578 if (row0>150) continue;
6581 Float_t dens00=-1,dens01=-1;
6582 Float_t dens10=-1,dens11=-1;
6584 Int_t found,foundable,ishared;
6585 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6586 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6587 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6588 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6590 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6591 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6592 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6593 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6595 if (dens00<dens10 && dens01<dens11) continue;
6596 if (dens00>dens10 && dens01>dens11) continue;
6597 if (TMath::Max(dens00,dens10)<0.1) continue;
6598 if (TMath::Max(dens01,dens11)<0.3) continue;
6600 if (TMath::Min(dens00,dens10)>0.6) continue;
6601 if (TMath::Min(dens01,dens11)>0.6) continue;
6604 AliTPCseed * ktrack0, *ktrack1;
6613 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6614 AliExternalTrackParam paramm(*ktrack0);
6615 AliExternalTrackParam paramd(*ktrack1);
6616 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6619 kink->SetMother(paramm);
6620 kink->SetDaughter(paramd);
6623 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])};
6625 fkParam->Transform0to1(x,index);
6626 fkParam->Transform1to2(x,index);
6627 row0 = GetRowNumber(x[0]);
6629 if (kink->GetR()<100) continue;
6630 if (kink->GetR()>240) continue;
6631 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6632 if (kink->GetDistance()>cdist3) continue;
6633 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6634 if (dird<0) continue;
6636 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6637 if (dirm<0) continue;
6638 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6639 if (mpt<0.2) continue;
6642 //for high momenta momentum not defined well in first iteration
6643 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6644 if (qt>0.35) continue;
6647 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6648 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6650 kink->SetTPCDensity(dens00,0,0);
6651 kink->SetTPCDensity(dens01,0,1);
6652 kink->SetTPCDensity(dens10,1,0);
6653 kink->SetTPCDensity(dens11,1,1);
6654 kink->SetIndex(i,0);
6655 kink->SetIndex(j,1);
6658 kink->SetTPCDensity(dens10,0,0);
6659 kink->SetTPCDensity(dens11,0,1);
6660 kink->SetTPCDensity(dens00,1,0);
6661 kink->SetTPCDensity(dens01,1,1);
6662 kink->SetIndex(j,0);
6663 kink->SetIndex(i,1);
6666 if (mpt<1||kink->GetAngle(2)>0.1){
6667 // angle and densities not defined yet
6668 if (kink->GetTPCDensityFactor()<0.8) continue;
6669 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6670 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6671 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6672 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6674 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6675 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6676 criticalangle= 3*TMath::Sqrt(criticalangle);
6677 if (criticalangle>0.02) criticalangle=0.02;
6678 if (kink->GetAngle(2)<criticalangle) continue;
6681 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6682 Float_t shapesum =0;
6684 for ( Int_t row = row0-drow; row<row0+drow;row++){
6685 if (row<0) continue;
6686 if (row>155) continue;
6687 if (ktrack0->GetClusterPointer(row)){
6688 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6689 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6692 if (ktrack1->GetClusterPointer(row)){
6693 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6694 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6699 kink->SetShapeFactor(-1.);
6702 kink->SetShapeFactor(shapesum/sum);
6704 // esd->AddKink(kink);
6706 // kink->SetMother(paramm);
6707 //kink->SetDaughter(paramd);
6709 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6711 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6712 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6714 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6716 if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) {// flag: stream track infroamtion in the FindKinks method
6717 (*fDebugStreamer)<<"kinkLpt"<<
6725 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6729 kinks->AddLast(kink);
6735 // sort the kinks according quality - and refit them towards vertex
6737 Int_t nkinks = kinks->GetEntriesFast();
6738 Float_t *quality = new Float_t[nkinks];
6739 Int_t *indexes = new Int_t[nkinks];
6740 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6741 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6744 for (Int_t i=0;i<nkinks;i++){
6746 AliKink *kinkl = (AliKink*)kinks->At(i);
6748 // refit kinks towards vertex
6750 Int_t index0 = kinkl->GetIndex(0);
6751 Int_t index1 = kinkl->GetIndex(1);
6752 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6753 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6755 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6757 // Refit Kink under if too small angle
6759 if (kinkl->GetAngle(2)<0.05){
6760 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6761 Int_t row0 = kinkl->GetTPCRow0();
6762 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6765 Int_t last = row0-drow;
6766 if (last<40) last=40;
6767 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6768 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6771 Int_t first = row0+drow;
6772 if (first>130) first=130;
6773 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6774 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6776 if (seed0 && seed1){
6777 kinkl->SetStatus(1,8);
6778 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6779 row0 = GetRowNumber(kinkl->GetR());
6780 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6781 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6782 mothers[i]->SetPoolID(fLastSeedID);
6783 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6784 daughters[i]->SetPoolID(fLastSeedID);
6787 delete kinks->RemoveAt(i);
6788 if (seed0) MarkSeedFree( seed0 );
6789 if (seed1) MarkSeedFree( seed1 );
6792 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6793 delete kinks->RemoveAt(i);
6794 if (seed0) MarkSeedFree( seed0 );
6795 if (seed1) MarkSeedFree( seed1 );
6799 MarkSeedFree( seed0 );
6800 MarkSeedFree( seed1 );
6803 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6805 TMath::Sort(nkinks,quality,indexes,kFALSE);
6807 //remove double find kinks
6809 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6810 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6811 if (!kink0) continue;
6813 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6814 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6815 if (!kink0) continue;
6816 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6817 if (!kink1) continue;
6818 // if not close kink continue
6819 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6820 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6821 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6823 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6824 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6825 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6826 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6827 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6836 for (Int_t i=0;i<row0;i++){
6837 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6840 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6847 for (Int_t i=row0;i<158;i++){
6848 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6849 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6852 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6858 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6859 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6860 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6861 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6862 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6863 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6865 shared[kink0->GetIndex(0)]= kTRUE;
6866 shared[kink0->GetIndex(1)]= kTRUE;
6867 delete kinks->RemoveAt(indexes[ikink0]);
6871 shared[kink1->GetIndex(0)]= kTRUE;
6872 shared[kink1->GetIndex(1)]= kTRUE;
6873 delete kinks->RemoveAt(indexes[ikink1]);
6880 for (Int_t i=0;i<nkinks;i++){
6881 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6882 if (!kinkl) continue;
6883 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6884 Int_t index0 = kinkl->GetIndex(0);
6885 Int_t index1 = kinkl->GetIndex(1);
6886 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6887 kinkl->SetMultiple(usage[index0],0);
6888 kinkl->SetMultiple(usage[index1],1);
6889 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6890 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6891 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6892 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6894 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6895 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6896 if (!ktrack0 || !ktrack1) continue;
6897 Int_t index = esd->AddKink(kinkl);
6900 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6901 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6902 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6903 *ktrack0 = *mothers[indexes[i]];
6904 *ktrack1 = *daughters[indexes[i]];
6908 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6909 ktrack1->SetKinkIndex(usage[index1], (index+1));
6914 // Remove tracks corresponding to shared kink's
6916 for (Int_t i=0;i<nentries;i++){
6917 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6918 if (!track0) continue;
6919 if (track0->GetKinkIndex(0)!=0) continue;
6920 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6925 RemoveUsed2(array,0.5,0.4,30);
6927 for (Int_t i=0;i<nentries;i++){
6928 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6929 if (!track0) continue;
6930 track0->CookdEdx(0.02,0.6);
6934 for (Int_t i=0;i<nentries;i++){
6935 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6936 if (!track0) continue;
6937 if (track0->Pt()<1.4) continue;
6938 //remove double high momenta tracks - overlapped with kink candidates
6941 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6942 if (track0->GetClusterPointer(icl)!=0){
6944 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6947 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6948 MarkSeedFree( array->RemoveAt(i) );
6952 if (track0->GetKinkIndex(0)!=0) continue;
6953 if (track0->GetNumberOfClusters()<80) continue;
6955 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6956 pmother->SetPoolID(fLastSeedID);
6957 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6958 pdaughter->SetPoolID(fLastSeedID);
6959 AliKink *pkink = new AliKink;
6961 AliTPCseed & mother = *pmother;
6962 AliTPCseed & daughter = *pdaughter;
6963 AliKink & kinkl = *pkink;
6964 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6965 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6966 MarkSeedFree( pmother );
6967 MarkSeedFree( pdaughter );
6969 continue; //too short tracks
6971 if (mother.Pt()<1.4) {
6972 MarkSeedFree( pmother );
6973 MarkSeedFree( pdaughter );
6977 Int_t row0= kinkl.GetTPCRow0();
6978 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6979 MarkSeedFree( pmother );
6980 MarkSeedFree( pdaughter );
6985 Int_t index = esd->AddKink(&kinkl);
6986 mother.SetKinkIndex(0,-(index+1));
6987 daughter.SetKinkIndex(0,index+1);
6988 if (mother.GetNumberOfClusters()>50) {
6989 MarkSeedFree( array->RemoveAt(i) );
6990 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6991 mtc->SetPoolID(fLastSeedID);
6992 array->AddAt(mtc,i);
6995 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6996 mtc->SetPoolID(fLastSeedID);
6997 array->AddLast(mtc);
6999 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
7000 dtc->SetPoolID(fLastSeedID);
7001 array->AddLast(dtc);
7002 for (Int_t icl=0;icl<row0;icl++) {
7003 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
7006 for (Int_t icl=row0;icl<158;icl++) {
7007 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
7011 MarkSeedFree( pmother );
7012 MarkSeedFree( pdaughter );
7016 delete [] daughters;
7038 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
7043 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7046 // refit kink towards to the vertex
7049 AliKink &kink=(AliKink &)knk;
7051 Int_t row0 = GetRowNumber(kink.GetR());
7052 FollowProlongation(mother,0);
7053 mother.Reset(kFALSE);
7055 FollowProlongation(daughter,row0);
7056 daughter.Reset(kFALSE);
7057 FollowBackProlongation(daughter,158);
7058 daughter.Reset(kFALSE);
7059 Int_t first = TMath::Max(row0-20,30);
7060 Int_t last = TMath::Min(row0+20,140);
7062 const Int_t kNdiv =5;
7063 AliTPCseed param0[kNdiv]; // parameters along the track
7064 AliTPCseed param1[kNdiv]; // parameters along the track
7065 AliKink kinks[kNdiv]; // corresponding kink parameters
7068 for (Int_t irow=0; irow<kNdiv;irow++){
7069 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
7071 // store parameters along the track
7073 for (Int_t irow=0;irow<kNdiv;irow++){
7074 FollowBackProlongation(mother, rows[irow]);
7075 FollowProlongation(daughter,rows[kNdiv-1-irow]);
7076 param0[irow] = mother;
7077 param1[kNdiv-1-irow] = daughter;
7081 for (Int_t irow=0; irow<kNdiv-1;irow++){
7082 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
7083 kinks[irow].SetMother(param0[irow]);
7084 kinks[irow].SetDaughter(param1[irow]);
7085 kinks[irow].Update();
7088 // choose kink with best "quality"
7090 Double_t mindist = 10000;
7091 for (Int_t irow=0;irow<kNdiv;irow++){
7092 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
7093 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7094 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
7096 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
7097 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
7098 if (normdist < mindist){
7104 if (index==-1) return 0;
7107 param0[index].Reset(kTRUE);
7108 FollowProlongation(param0[index],0);
7110 mother = param0[index];
7111 daughter = param1[index]; // daughter in vertex
7113 kink.SetMother(mother);
7114 kink.SetDaughter(daughter);
7116 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
7117 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7118 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7119 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
7120 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
7121 mother.SetLabel(kink.GetLabel(0));
7122 daughter.SetLabel(kink.GetLabel(1));
7128 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
7130 // update Kink quality information for mother after back propagation
7132 if (seed->GetKinkIndex(0)>=0) return;
7133 for (Int_t ikink=0;ikink<3;ikink++){
7134 Int_t index = seed->GetKinkIndex(ikink);
7135 if (index>=0) break;
7136 index = TMath::Abs(index)-1;
7137 AliESDkink * kink = fEvent->GetKink(index);
7138 kink->SetTPCDensity(-1,0,0);
7139 kink->SetTPCDensity(1,0,1);
7141 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7142 if (row0<15) row0=15;
7144 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7145 if (row1>145) row1=145;
7147 Int_t found,foundable,shared;
7148 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7149 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
7150 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7151 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
7156 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
7158 // update Kink quality information for daughter after refit
7160 if (seed->GetKinkIndex(0)<=0) return;
7161 for (Int_t ikink=0;ikink<3;ikink++){
7162 Int_t index = seed->GetKinkIndex(ikink);
7163 if (index<=0) break;
7164 index = TMath::Abs(index)-1;
7165 AliESDkink * kink = fEvent->GetKink(index);
7166 kink->SetTPCDensity(-1,1,0);
7167 kink->SetTPCDensity(-1,1,1);
7169 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7170 if (row0<15) row0=15;
7172 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7173 if (row1>145) row1=145;
7175 Int_t found,foundable,shared;
7176 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7177 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
7178 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7179 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
7185 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7188 // check kink point for given track
7189 // if return value=0 kink point not found
7190 // otherwise seed0 correspond to mother particle
7191 // seed1 correspond to daughter particle
7192 // kink parameter of kink point
7193 AliKink &kink=(AliKink &)knk;
7195 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
7196 Int_t first = seed->GetFirstPoint();
7197 Int_t last = seed->GetLastPoint();
7198 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
7201 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
7202 if (!seed1) return 0;
7203 FollowProlongation(*seed1,seed->GetLastPoint()-20);
7204 seed1->Reset(kTRUE);
7205 FollowProlongation(*seed1,158);
7206 seed1->Reset(kTRUE);
7207 last = seed1->GetLastPoint();
7209 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
7210 seed0->SetPoolID(fLastSeedID);
7211 seed0->Reset(kFALSE);
7214 AliTPCseed param0[20]; // parameters along the track
7215 AliTPCseed param1[20]; // parameters along the track
7216 AliKink kinks[20]; // corresponding kink parameters
7218 for (Int_t irow=0; irow<20;irow++){
7219 rows[irow] = first +((last-first)*irow)/19;
7221 // store parameters along the track
7223 for (Int_t irow=0;irow<20;irow++){
7224 FollowBackProlongation(*seed0, rows[irow]);
7225 FollowProlongation(*seed1,rows[19-irow]);
7226 param0[irow] = *seed0;
7227 param1[19-irow] = *seed1;
7231 for (Int_t irow=0; irow<19;irow++){
7232 kinks[irow].SetMother(param0[irow]);
7233 kinks[irow].SetDaughter(param1[irow]);
7234 kinks[irow].Update();
7237 // choose kink with biggest change of angle
7239 Double_t maxchange= 0;
7240 for (Int_t irow=1;irow<19;irow++){
7241 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7242 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
7243 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7244 if ( quality > maxchange){
7245 maxchange = quality;
7250 MarkSeedFree( seed0 );
7251 MarkSeedFree( seed1 );
7252 if (index<0) return 0;
7254 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
7255 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
7256 seed0->SetPoolID(fLastSeedID);
7257 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
7258 seed1->SetPoolID(fLastSeedID);
7259 seed0->Reset(kFALSE);
7260 seed1->Reset(kFALSE);
7261 seed0->ResetCovariance(10.);
7262 seed1->ResetCovariance(10.);
7263 FollowProlongation(*seed0,0);
7264 FollowBackProlongation(*seed1,158);
7265 mother = *seed0; // backup mother at position 0
7266 seed0->Reset(kFALSE);
7267 seed1->Reset(kFALSE);
7268 seed0->ResetCovariance(10.);
7269 seed1->ResetCovariance(10.);
7271 first = TMath::Max(row0-20,0);
7272 last = TMath::Min(row0+20,158);
7274 for (Int_t irow=0; irow<20;irow++){
7275 rows[irow] = first +((last-first)*irow)/19;
7277 // store parameters along the track
7279 for (Int_t irow=0;irow<20;irow++){
7280 FollowBackProlongation(*seed0, rows[irow]);
7281 FollowProlongation(*seed1,rows[19-irow]);
7282 param0[irow] = *seed0;
7283 param1[19-irow] = *seed1;
7287 for (Int_t irow=0; irow<19;irow++){
7288 kinks[irow].SetMother(param0[irow]);
7289 kinks[irow].SetDaughter(param1[irow]);
7290 // param0[irow].Dump();
7291 //param1[irow].Dump();
7292 kinks[irow].Update();
7295 // choose kink with biggest change of angle
7298 for (Int_t irow=0;irow<20;irow++){
7299 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
7300 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
7301 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7302 if ( quality > maxchange){
7303 maxchange = quality;
7310 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
7311 MarkSeedFree( seed0 );
7312 MarkSeedFree( seed1 );
7316 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
7318 kink.SetMother(param0[index]);
7319 kink.SetDaughter(param1[index]);
7322 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
7324 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
7325 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
7327 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
7329 if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) { // flag: stream track infroamtion in the FindKinks method
7330 (*fDebugStreamer)<<"kinkHpt"<<
7333 "p0.="<<¶m0[index]<<
7334 "p1.="<<¶m1[index]<<
7338 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
7339 MarkSeedFree( seed0 );
7340 MarkSeedFree( seed1 );
7345 row0 = GetRowNumber(kink.GetR());
7346 kink.SetTPCRow0(row0);
7347 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
7348 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
7349 kink.SetIndex(-10,0);
7350 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
7351 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7352 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7355 // new (&mother) AliTPCseed(param0[index]);
7356 daughter = param1[index];
7357 daughter.SetLabel(kink.GetLabel(1));
7358 param0[index].Reset(kTRUE);
7359 FollowProlongation(param0[index],0);
7360 mother = param0[index];
7361 mother.SetLabel(kink.GetLabel(0));
7362 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
7365 MarkSeedFree( seed0 );
7366 MarkSeedFree( seed1 );
7374 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
7377 // reseed - refit - track
7380 // Int_t last = fSectors->GetNRows()-1;
7382 if (fSectors == fOuterSec){
7383 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
7387 first = t->GetFirstPoint();
7389 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
7390 FollowBackProlongation(*t,fSectors->GetNRows()-1);
7392 FollowProlongation(*t,first);
7402 //_____________________________________________________________________________
7403 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
7404 //-----------------------------------------------------------------
7405 // This function reades track seeds.
7406 //-----------------------------------------------------------------
7407 TDirectory *savedir=gDirectory;
7409 TFile *in=(TFile*)inp;
7410 if (!in->IsOpen()) {
7411 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
7416 TTree *seedTree=(TTree*)in->Get("Seeds");
7418 cerr<<"AliTPCtracker::ReadSeeds(): ";
7419 cerr<<"can't get a tree with track seeds !\n";
7422 AliTPCtrack *seed=new AliTPCtrack;
7423 seedTree->SetBranchAddress("tracks",&seed);
7425 if (fSeeds==0) fSeeds=new TObjArray(15000);
7427 Int_t n=(Int_t)seedTree->GetEntries();
7428 for (Int_t i=0; i<n; i++) {
7429 seedTree->GetEvent(i);
7430 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
7431 sdc->SetPoolID(fLastSeedID);
7432 fSeeds->AddLast(sdc);
7435 delete seed; // RS: this seed is not from the pool, delete it !!!
7441 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
7444 // clusters to tracks
7445 if (fSeeds) DeleteSeeds();
7446 else ResetSeedsPool();
7448 fEventHLT = hltEvent;
7449 if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();
7450 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
7451 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
7452 transform->SetCurrentRun(esd->GetRunNumber());
7457 if (!fSeeds) return 1;
7459 if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0) DumpClusters(0,fSeeds);
7464 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
7467 // clusters to tracks
7468 return Clusters2TracksHLT( esd, 0);
7471 //_____________________________________________________________________________
7472 Int_t AliTPCtracker::Clusters2Tracks() {
7473 //-----------------------------------------------------------------
7474 // This is a track finder.
7475 //-----------------------------------------------------------------
7476 TDirectory *savedir=gDirectory;
7480 fSeeds = Tracking();
7483 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
7485 //activate again some tracks
7486 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
7487 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7489 Int_t nc=t.GetNumberOfClusters();
7491 MarkSeedFree( fSeeds->RemoveAt(i) );
7495 if (pt->GetRemoval()==10) {
7496 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7497 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
7499 pt->Desactivate(20);
7500 MarkSeedFree( fSeeds->RemoveAt(i) );
7505 RemoveUsed2(fSeeds,0.85,0.85,0);
7506 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
7507 //FindCurling(fSeeds, fEvent,0);
7508 if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
7509 RemoveUsed2(fSeeds,0.5,0.4,20);
7510 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
7511 if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
7514 // // refit short tracks
7516 Int_t nseed=fSeeds->GetEntriesFast();
7519 for (Int_t i=0; i<nseed; i++) {
7520 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7522 Int_t nc=t.GetNumberOfClusters();
7524 MarkSeedFree( fSeeds->RemoveAt(i) );
7527 CookLabel(pt,0.1); //For comparison only
7528 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7529 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7531 if (fDebug>0) cerr<<found<<'\r';
7535 MarkSeedFree( fSeeds->RemoveAt(i) );
7539 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7541 //RemoveUsed(fSeeds,0.9,0.9,6);
7543 nseed=fSeeds->GetEntriesFast();
7545 for (Int_t i=0; i<nseed; i++) {
7546 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7548 Int_t nc=t.GetNumberOfClusters();
7550 MarkSeedFree( fSeeds->RemoveAt(i) );
7554 t.CookdEdx(0.02,0.6);
7555 // CheckKinkPoint(&t,0.05);
7556 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7557 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7565 MarkSeedFree( fSeeds->RemoveAt(i) );
7566 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7568 // FollowProlongation(*seed1,0);
7569 // Int_t n = seed1->GetNumberOfClusters();
7570 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7571 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7574 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7578 SortTracks(fSeeds, 1);
7582 PrepareForBackProlongation(fSeeds,5.);
7583 PropagateBack(fSeeds);
7584 printf("Time for back propagation: \t");timer.Print();timer.Start();
7588 PrepareForProlongation(fSeeds,5.);
7589 PropagateForard2(fSeeds);
7591 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7592 // RemoveUsed(fSeeds,0.7,0.7,6);
7593 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7595 nseed=fSeeds->GetEntriesFast();
7597 for (Int_t i=0; i<nseed; i++) {
7598 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7600 Int_t nc=t.GetNumberOfClusters();
7602 MarkSeedFree( fSeeds->RemoveAt(i) );
7605 t.CookdEdx(0.02,0.6);
7606 // CookLabel(pt,0.1); //For comparison only
7607 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7608 if ((pt->IsActive() || (pt->fRemoval==10) )){
7609 cerr<<found++<<'\r';
7612 MarkSeedFree( fSeeds->RemoveAt(i) );
7617 // fNTracks = found;
7619 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7622 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7623 Info("Clusters2Tracks","Number of found tracks %d",found);
7625 // UnloadClusters();
7630 void AliTPCtracker::Tracking(TObjArray * arr)
7633 // tracking of the seeds
7636 fSectors = fOuterSec;
7637 ParallelTracking(arr,150,63);
7638 fSectors = fOuterSec;
7639 ParallelTracking(arr,63,0);
7642 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7647 static TObjArray arrTracks;
7648 TObjArray * arr = &arrTracks;
7650 fSectors = fOuterSec;
7653 for (Int_t sec=0;sec<fkNOS;sec++){
7654 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7655 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7656 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7659 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7671 TObjArray * AliTPCtracker::Tracking()
7675 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7678 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7680 TObjArray * seeds = new TObjArray;
7682 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7683 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7684 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7692 Float_t fnumber = 3.0;
7693 Float_t fdensity = 3.0;
7696 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7697 arr = MakeSeedsHLT( fEventHLT );
7699 SumTracks(seeds,arr);
7702 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7703 //SignClusters(seeds,fnumber,fdensity);
7710 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7714 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7715 SumTracks(seeds,arr);
7716 SignClusters(seeds,fnumber,fdensity);
7718 for (Int_t i=2;i<6;i+=2){
7719 // seed high pt tracks
7722 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7723 SumTracks(seeds,arr);
7724 SignClusters(seeds,fnumber,fdensity);
7729 // RemoveUsed(seeds,0.9,0.9,1);
7730 // UnsignClusters();
7731 // SignClusters(seeds,fnumber,fdensity);
7735 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7737 // seed high pt tracks
7741 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7742 SumTracks(seeds,arr);
7743 SignClusters(seeds,fnumber,fdensity);
7748 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7749 SumTracks(seeds,arr);
7750 SignClusters(seeds,fnumber,fdensity);
7761 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7765 // RemoveUsed(seeds,0.75,0.75,1);
7767 //SignClusters(seeds,fnumber,fdensity);
7776 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7777 SumTracks(seeds,arr);
7778 SignClusters(seeds,fnumber,fdensity);
7780 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7781 SumTracks(seeds,arr);
7782 SignClusters(seeds,fnumber,fdensity);
7784 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7785 SumTracks(seeds,arr);
7786 SignClusters(seeds,fnumber,fdensity);
7788 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7789 SumTracks(seeds,arr);
7790 SignClusters(seeds,fnumber,fdensity);
7792 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7793 SumTracks(seeds,arr);
7794 SignClusters(seeds,fnumber,fdensity);
7797 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7798 SumTracks(seeds,arr);
7799 SignClusters(seeds,fnumber,fdensity);
7803 for (Int_t delta = 9; delta<30; delta+=gapSec){
7809 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7810 SumTracks(seeds,arr);
7811 SignClusters(seeds,fnumber,fdensity);
7813 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7814 SumTracks(seeds,arr);
7815 SignClusters(seeds,fnumber,fdensity);
7828 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7834 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7835 SumTracks(seeds,arr);
7836 SignClusters(seeds,fnumber,fdensity);
7838 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7839 SumTracks(seeds,arr);
7840 SignClusters(seeds,fnumber,fdensity);
7844 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7855 TObjArray * AliTPCtracker::TrackingSpecial()
7858 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7859 // no primary vertex seeding tried
7863 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7865 TObjArray * seeds = new TObjArray;
7870 Float_t fnumber = 3.0;
7871 Float_t fdensity = 3.0;
7874 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7875 cuts[1] = 3.5; // max tan(phi) angle for seeding
7876 cuts[2] = 3.; // not used (cut on z primary vertex)
7877 cuts[3] = 3.5; // max tan(theta) angle for seeding
7879 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7881 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7882 SumTracks(seeds,arr);
7883 SignClusters(seeds,fnumber,fdensity);
7887 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7898 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7901 //sum tracks to common container
7902 //remove suspicious tracks
7903 // RS: Attention: supplied tracks come in the static array, don't delete them
7904 Int_t nseed = arr2->GetEntriesFast();
7905 for (Int_t i=0;i<nseed;i++){
7906 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7909 // remove tracks with too big curvature
7911 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7912 MarkSeedFree( arr2->RemoveAt(i) );
7915 // REMOVE VERY SHORT TRACKS
7916 if (pt->GetNumberOfClusters()<20){
7917 MarkSeedFree( arr2->RemoveAt(i) );
7920 // NORMAL ACTIVE TRACK
7921 if (pt->IsActive()){
7922 arr1->AddLast(arr2->RemoveAt(i));
7925 //remove not usable tracks
7926 if (pt->GetRemoval()!=10){
7927 MarkSeedFree( arr2->RemoveAt(i) );
7931 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7932 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7933 arr1->AddLast(arr2->RemoveAt(i));
7935 MarkSeedFree( arr2->RemoveAt(i) );
7939 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7944 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7947 // try to track in parralel
7949 Int_t nseed=arr->GetEntriesFast();
7950 //prepare seeds for tracking
7951 for (Int_t i=0; i<nseed; i++) {
7952 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7954 if (!t.IsActive()) continue;
7955 // follow prolongation to the first layer
7956 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7957 FollowProlongation(t, rfirst+1);
7962 for (Int_t nr=rfirst; nr>=rlast; nr--){
7963 if (nr<fInnerSec->GetNRows())
7964 fSectors = fInnerSec;
7966 fSectors = fOuterSec;
7967 // make indexes with the cluster tracks for given
7969 // find nearest cluster
7970 for (Int_t i=0; i<nseed; i++) {
7971 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7973 if (nr==80) pt->UpdateReference();
7974 if (!pt->IsActive()) continue;
7975 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7976 if (pt->GetRelativeSector()>17) {
7979 UpdateClusters(t,nr);
7981 // prolonagate to the nearest cluster - if founded
7982 for (Int_t i=0; i<nseed; i++) {
7983 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7985 if (!pt->IsActive()) continue;
7986 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7987 if (pt->GetRelativeSector()>17) {
7990 FollowToNextCluster(*pt,nr);
7995 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7999 // if we use TPC track itself we have to "update" covariance
8001 Int_t nseed= arr->GetEntriesFast();
8002 for (Int_t i=0;i<nseed;i++){
8003 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8007 //rotate to current local system at first accepted point
8008 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
8009 Int_t sec = (index&0xff000000)>>24;
8011 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
8012 if (angle1>TMath::Pi())
8013 angle1-=2.*TMath::Pi();
8014 Float_t angle2 = pt->GetAlpha();
8016 if (TMath::Abs(angle1-angle2)>0.001){
8017 if (!pt->Rotate(angle1-angle2)) return;
8018 //angle2 = pt->GetAlpha();
8019 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
8020 //if (pt->GetAlpha()<0)
8021 // pt->fRelativeSector+=18;
8022 //sec = pt->fRelativeSector;
8031 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
8035 // if we use TPC track itself we have to "update" covariance
8037 Int_t nseed= arr->GetEntriesFast();
8038 for (Int_t i=0;i<nseed;i++){
8039 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8042 pt->SetFirstPoint(pt->GetLastPoint());
8050 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
8053 // make back propagation
8055 Int_t nseed= arr->GetEntriesFast();
8056 for (Int_t i=0;i<nseed;i++){
8057 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8058 if (pt&& pt->GetKinkIndex(0)<=0) {
8059 //AliTPCseed *pt2 = new AliTPCseed(*pt);
8060 fSectors = fInnerSec;
8061 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
8062 //fSectors = fOuterSec;
8063 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
8064 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
8065 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
8066 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
8069 if (pt&& pt->GetKinkIndex(0)>0) {
8070 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
8071 pt->SetFirstPoint(kink->GetTPCRow0());
8072 fSectors = fInnerSec;
8073 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
8081 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
8084 // make forward propagation
8086 Int_t nseed= arr->GetEntriesFast();
8088 for (Int_t i=0;i<nseed;i++){
8089 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8091 FollowProlongation(*pt,0,1,1);
8100 Int_t AliTPCtracker::PropagateForward()
8103 // propagate track forward
8105 Int_t nseed = fSeeds->GetEntriesFast();
8106 for (Int_t i=0;i<nseed;i++){
8107 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
8109 AliTPCseed &t = *pt;
8110 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
8111 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8112 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8113 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8117 fSectors = fOuterSec;
8118 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
8119 fSectors = fInnerSec;
8120 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
8129 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
8132 // make back propagation, in between row0 and row1
8136 fSectors = fInnerSec;
8139 if (row1<fSectors->GetNRows())
8142 r1 = fSectors->GetNRows()-1;
8144 if (row0<fSectors->GetNRows()&& r1>0 )
8145 FollowBackProlongation(*pt,r1);
8146 if (row1<=fSectors->GetNRows())
8149 r1 = row1 - fSectors->GetNRows();
8150 if (r1<=0) return 0;
8151 if (r1>=fOuterSec->GetNRows()) return 0;
8152 fSectors = fOuterSec;
8153 return FollowBackProlongation(*pt,r1);
8161 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
8163 // gets cluster shape
8165 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
8166 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
8167 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
8168 Double_t angulary = seed->GetSnp();
8170 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
8171 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
8174 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
8175 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
8177 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
8178 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
8179 seed->SetCurrentSigmaY2(sigmay*sigmay);
8180 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
8181 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
8182 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
8183 // Float_t padlength = GetPadPitchLength(row);
8185 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
8186 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
8188 // Float_t sresz = fkParam->GetZSigma();
8189 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
8191 Float_t wy = GetSigmaY(seed);
8192 Float_t wz = GetSigmaZ(seed);
8195 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
8196 printf("problem\n");
8203 //__________________________________________________________________________
8204 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
8205 //--------------------------------------------------------------------
8206 //This function "cooks" a track label. If label<0, this track is fake.
8207 //--------------------------------------------------------------------
8208 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
8210 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
8214 Int_t noc=t->GetNumberOfClusters();
8216 //printf("\nnot founded prolongation\n\n\n");
8222 AliTPCclusterMI *clusters[160];
8224 for (Int_t i=0;i<160;i++) {
8231 for (i=0; i<160 && current<noc; i++) {
8233 Int_t index=t->GetClusterIndex2(i);
8234 if (index<=0) continue;
8235 if (index&0x8000) continue;
8237 //clusters[current]=GetClusterMI(index);
8238 if (t->GetClusterPointer(i)){
8239 clusters[current]=t->GetClusterPointer(i);
8245 Int_t lab=123456789;
8246 for (i=0; i<noc; i++) {
8247 AliTPCclusterMI *c=clusters[i];
8249 lab=TMath::Abs(c->GetLabel(0));
8251 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8257 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8259 for (i=0; i<noc; i++) {
8260 AliTPCclusterMI *c=clusters[i];
8262 if (TMath::Abs(c->GetLabel(1)) == lab ||
8263 TMath::Abs(c->GetLabel(2)) == lab ) max++;
8265 if (noc<=0) { lab=-1; return;}
8266 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8269 Int_t tail=Int_t(0.10*noc);
8272 for (i=1; i<160&&ind<tail; i++) {
8273 // AliTPCclusterMI *c=clusters[noc-i];
8274 AliTPCclusterMI *c=clusters[i];
8276 if (lab == TMath::Abs(c->GetLabel(0)) ||
8277 lab == TMath::Abs(c->GetLabel(1)) ||
8278 lab == TMath::Abs(c->GetLabel(2))) max++;
8281 if (max < Int_t(0.5*tail)) lab=-lab;
8288 //delete[] clusters;
8292 //__________________________________________________________________________
8293 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
8294 //--------------------------------------------------------------------
8295 //This function "cooks" a track label. If label<0, this track is fake.
8296 //--------------------------------------------------------------------
8297 Int_t noc=t->GetNumberOfClusters();
8299 //printf("\nnot founded prolongation\n\n\n");
8305 AliTPCclusterMI *clusters[160];
8307 for (Int_t i=0;i<160;i++) {
8314 for (i=0; i<160 && current<noc; i++) {
8315 if (i<first) continue;
8316 if (i>last) continue;
8317 Int_t index=t->GetClusterIndex2(i);
8318 if (index<=0) continue;
8319 if (index&0x8000) continue;
8321 //clusters[current]=GetClusterMI(index);
8322 if (t->GetClusterPointer(i)){
8323 clusters[current]=t->GetClusterPointer(i);
8328 //if (noc<5) return -1;
8329 Int_t lab=123456789;
8330 for (i=0; i<noc; i++) {
8331 AliTPCclusterMI *c=clusters[i];
8333 lab=TMath::Abs(c->GetLabel(0));
8335 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8341 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8343 for (i=0; i<noc; i++) {
8344 AliTPCclusterMI *c=clusters[i];
8346 if (TMath::Abs(c->GetLabel(1)) == lab ||
8347 TMath::Abs(c->GetLabel(2)) == lab ) max++;
8349 if (noc<=0) { lab=-1; return -1;}
8350 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8353 Int_t tail=Int_t(0.10*noc);
8356 for (i=1; i<160&&ind<tail; i++) {
8357 // AliTPCclusterMI *c=clusters[noc-i];
8358 AliTPCclusterMI *c=clusters[i];
8360 if (lab == TMath::Abs(c->GetLabel(0)) ||
8361 lab == TMath::Abs(c->GetLabel(1)) ||
8362 lab == TMath::Abs(c->GetLabel(2))) max++;
8365 if (max < Int_t(0.5*tail)) lab=-lab;
8368 // t->SetLabel(lab);
8372 //delete[] clusters;
8376 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
8378 //return pad row number for given x vector
8379 Float_t phi = TMath::ATan2(x[1],x[0]);
8380 if(phi<0) phi=2.*TMath::Pi()+phi;
8381 // Get the local angle in the sector philoc
8382 const Float_t kRaddeg = 180/3.14159265358979312;
8383 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
8384 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
8385 return GetRowNumber(localx);
8390 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
8392 //-----------------------------------------------------------------------
8393 // Fill the cluster and sharing bitmaps of the track
8394 //-----------------------------------------------------------------------
8396 Int_t firstpoint = 0;
8397 Int_t lastpoint = 159;
8398 AliTPCTrackerPoint *point;
8399 AliTPCclusterMI *cluster;
8402 TBits clusterMap(159);
8403 TBits sharedMap(159);
8405 for (int iter=firstpoint; iter<lastpoint; iter++) {
8406 // Change to cluster pointers to see if we have a cluster at given padrow
8408 cluster = t->GetClusterPointer(iter);
8410 clusterMap.SetBitNumber(iter, kTRUE);
8411 point = t->GetTrackPoint(iter);
8412 if (point->IsShared())
8413 sharedMap.SetBitNumber(iter,kTRUE);
8415 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
8416 fitMap.SetBitNumber(iter, kTRUE);
8420 esd->SetTPCClusterMap(clusterMap);
8421 esd->SetTPCSharedMap(sharedMap);
8422 esd->SetTPCFitMap(fitMap);
8423 if (nclsf != t->GetNumberOfClusters())
8424 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
8427 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
8429 // return flag if there is findable cluster at given position
8432 Float_t z = track.GetZ();
8434 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
8435 TMath::Abs(z)<fkParam->GetZLength(0) &&
8436 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
8442 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
8444 // Adding systematic error estimate to the covariance matrix
8445 // !!!! the systematic error for element 4 is in 1/GeV
8446 // 03.03.2012 MI changed in respect to the previous versions
8447 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8449 // use only the diagonal part if not specified otherwise
8450 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
8452 Double_t *covarS= (Double_t*)seed->GetCovariance();
8453 Double_t factor[5]={1,1,1,1,1};
8454 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
8455 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
8456 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
8457 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
8458 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
8460 factor[0]=factor[2];
8461 factor[4]=factor[2];
8467 for (Int_t i=0; i<5; i++){
8468 for (Int_t j=i; j<5; j++){
8469 Int_t index=seed->GetIndex(i,j);
8470 covarS[index]*=factor[i]*factor[j];
8476 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
8478 // Adding systematic error - as additive factor without correlation
8480 // !!!! the systematic error for element 4 is in 1/GeV
8481 // 03.03.2012 MI changed in respect to the previous versions
8483 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8484 Double_t *covarIn= (Double_t*)seed->GetCovariance();
8486 for (Int_t i=0;i<15;i++) covar[i]=0;
8492 covar[0] = param[0]*param[0];
8493 covar[2] = param[1]*param[1];
8494 covar[5] = param[2]*param[2];
8495 covar[9] = param[3]*param[3];
8496 covar[14]= param[4]*param[4];
8498 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
8500 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
8501 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
8503 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
8504 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
8505 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
8507 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
8508 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
8509 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
8510 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
8512 seed->AddCovariance(covar);
8515 //_____________________________________________________________________________
8516 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8519 // check events affected by TPC HV dip
8521 if(!esdEvent) return kFALSE;
8524 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8525 if(!db) return kFALSE;
8526 db->SetRun(esdEvent->GetRunNumber());
8528 // maximum allowed voltage before an event is identified as a dip event
8529 // and scanning period
8530 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8531 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8532 const Double_t tevSec = esdEvent->GetTimeStamp();
8534 for(Int_t sector=0; sector<72; sector++)
8536 // don't use excluded chambers, since the state is not defined at all
8537 if (!db->GetChamberHVStatus(sector)) continue;
8539 // get hv sensor of the chamber
8540 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8541 if (!sensor) continue;
8542 TGraph *grSensor=sensor->GetGraph();
8543 if (!grSensor) continue;
8544 if (grSensor->GetN()<1) continue;
8547 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8548 if(median < 1.) continue;
8550 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8551 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8552 if (tevSec-dipEventScanPeriod>nextTime) continue;
8553 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8554 if (deltaV>kTPCHVdip) {
8555 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8558 if (nextTime>tevSec+dipEventScanPeriod) break;
8565 //________________________________________
8566 void AliTPCtracker::MarkSeedFree(TObject *sd)
8568 // account that this seed is "deleted"
8569 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8571 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8574 int id = seed->GetPoolID();
8576 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8579 // AliInfo(Form("%d %p",id, seed));
8580 fSeedsPool->RemoveAt(id);
8581 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8582 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8585 //________________________________________
8586 TObject *&AliTPCtracker::NextFreeSeed()
8588 // return next free slot where the seed can be created
8589 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8590 // AliInfo(Form("%d",fLastSeedID));
8591 return (*fSeedsPool)[ fLastSeedID ];
8595 //________________________________________
8596 void AliTPCtracker::ResetSeedsPool()
8598 // mark all seeds in the pool as unused
8599 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8601 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8604 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8607 Double_t x= GetXrow(nrow);
8608 Double_t ymax= GetMaxY(nrow);
8614 if (!t.PropagateTo(x) ){
8615 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8621 Double_t y = t.GetY();
8623 if( rotate!=-1 ) rotate=1;
8624 } else if (y <-ymax) {
8625 if( rotate!=1 ) rotate = -1;
8627 if( rotate==0 ) break;
8628 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8629 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8630 //cout<<"can't rotate "<<endl;
8634 nRotations+= rotate;
8636 if( nRotations!=0 ){
8637 int newSec= t.GetRelativeSector()+nRotations;
8638 if( newSec>=fN ) newSec-=fN;
8639 else if( newSec<0 ) newSec +=fN;
8640 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8641 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8642 t.SetRelativeSector(newSec);
8647 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8650 // try to track in parralel
8652 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8655 Int_t nseed=arr->GetEntriesFast();
8656 //cout<<"Parallel tracking My.."<<endl;
8657 double shapeY2[160], shapeZ2[160];
8658 Int_t clusterIndex[160];
8660 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8661 //if( iSeed!=1 ) continue;
8662 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8666 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8670 for( int iter=0; iter<3; iter++ ){
8673 t.SetLastPoint(0); // first cluster in track position
8674 t.SetFirstPoint(nRows-1);
8675 t.ResetCovariance(.1);
8676 t.SetNumberOfClusters(0);
8677 for( int i=0; i<nRows; i++ ){
8681 t.SetClusterIndex2(i,-1);
8682 t.SetClusterIndex(i,-1);
8685 // pick up the clusters
8687 Double_t roady = 20.;
8688 Double_t roadz = 20.;
8695 t0.SetRelativeSector(t.GetRelativeSector());
8696 t0.SetLastPoint(0); // first cluster in track position
8697 t0.SetFirstPoint(159);
8698 for (Int_t nr=0; nr<nRows; nr++){
8699 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8700 else fSectors=fOuterSec;
8702 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8703 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8704 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8707 if (!IsActive(t0.GetRelativeSector(),nr)) {
8713 shapeY2[nr]=t0.GetCurrentSigmaY2();
8714 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8717 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8718 if( !krow ) continue;
8720 t.SetClusterIndex2(nr,-3); // foundable
8721 t.SetClusterIndex(nr,-3);
8723 AliTPCclusterMI *cl=0;
8725 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8727 double dy = cl->GetY()-t0.GetY();
8728 double dz = cl->GetZ()-t0.GetZ();
8729 double dr = sqrt(dy*dy+dz*dz);
8731 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8734 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8736 t0.SetClusterPointer(nr, cl);
8737 clusterIndex[nr] = krow.GetIndex(uindex);
8738 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8739 t0.SetLastPoint(nr);
8745 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8748 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8752 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8754 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8755 if( !t0.GetClusterPointer(nr) ) continue;
8756 int d = TMath::Abs(nr-midRow);
8764 // first fit 3 base points
8766 //cout<<"Fit3: "<<endl;
8767 for( int icl=0; icl<3; icl++){
8768 int nr = basePoints[icl];
8770 if( nr>=fInnerSec->GetNRows()){
8771 lr = nr - fInnerSec->GetNRows();
8773 } else fSectors=fInnerSec;
8775 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8777 //cout<<"WRONG!!!!"<<endl;
8780 int iSec = cl->GetDetector() %fkNIS;
8781 int rotate = iSec - t.GetRelativeSector();
8783 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8784 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8785 //cout<<"can't rotate "<<endl;
8788 t.SetRelativeSector(iSec);
8790 Double_t x= cl->GetX();
8791 if (!t.PropagateTo(x)){
8792 //cout<<"can't propagate to x="<<x<<endl;
8796 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8797 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8800 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8802 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8803 t.SetCurrentCluster(cl);
8806 t.SetErrorY2(shapeY2[nr]);
8807 t.SetErrorZ2(shapeZ2[nr]);
8810 for( int j=0; j<15; j++ ) cov[j]=0;
8816 t.AliExternalTrackParam::AddCovariance(cov);
8818 if( !UpdateTrack(&t,0) ){
8819 //cout<<"Can not update"<<endl;
8821 t.SetClusterIndex2(nr,-1);
8822 t.SetClusterIndex(nr,-1);
8823 t.SetClusterPointer(nr,0);
8826 //t.SetClusterPointer(nr, cl);
8829 //t.SetLastPoint(t0.GetLastPoint());
8830 //t.SetFirstPoint(t0.GetFirstPoint());
8832 //cout<<"Fit: "<<endl;
8833 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8835 if( nr>=fInnerSec->GetNRows()){
8836 lr = nr - fInnerSec->GetNRows();
8838 } else fSectors=fInnerSec;
8841 if( nr == basePoints[0] ) continue;
8842 if( nr == basePoints[1] ) continue;
8843 if( nr == basePoints[2] ) continue;
8845 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8848 int iSec = cl->GetDetector() %fkNIS;
8849 int rotate = iSec - t.GetRelativeSector();
8851 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8852 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8853 //cout<<"can't rotate "<<endl;
8856 t.SetRelativeSector(iSec);
8858 Double_t x= cl->GetX();
8859 if (!t.PropagateTo(x)){
8860 //cout<<"can't propagate to x="<<x<<endl;
8863 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8864 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8868 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8870 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8871 t.SetCurrentCluster(cl);
8873 t.SetErrorY2(shapeY2[nr]);
8874 t.SetErrorZ2(shapeZ2[nr]);
8876 if( !UpdateTrack(&t,0) ){
8877 //cout<<"Can not update"<<endl;
8879 t.SetClusterIndex2(nr,-1);
8880 t.SetClusterIndex(nr,-1);
8883 //t.SetClusterPointer(nr, cl);
8886 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8889 //cout<<"fitted track"<<iSeed<<endl;
8891 //cout<<"Statistics: "<<endl;
8892 Int_t foundable,found,shared;
8893 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8894 t.SetNFoundable(foundable);
8895 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8901 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8906 if( !hltEvent ) return 0;
8909 Int_t nentr=hltEvent->GetNumberOfTracks();
8911 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8913 TObjArray * seeds = new TObjArray(nentr);
8915 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8918 Int_t nTr=hltEvent->GetNumberOfTracks();
8920 for( int itr=0; itr<nTr; itr++ ){
8921 //if( itr!=97 ) continue;
8922 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8923 if( !param ) continue;
8924 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8925 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8927 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8928 tr.SetNumberOfClusters(0);
8929 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8931 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8932 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8933 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8935 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8936 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8938 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8939 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8941 seed->Rotate(alphaSec - alpha);
8943 seed->SetPoolID(fLastSeedID);
8944 seed->SetIsSeeding(kTRUE);
8945 seed->SetSeed1(nup-1);
8946 seed->SetSeed2(nup-2);
8947 seed->SetSeedType(0);
8948 seed->SetFirstPoint(-1);
8949 seed->SetLastPoint(-1);
8950 seeds->AddLast(seed); // note, track is seed, don't free the seed
8952 //if( index>3 ) break;
8956 fSectors = fOuterSec;
8958 TrackFollowingHLT(seeds );
8960 nTr = seeds->GetEntriesFast();
8961 for( int itr=0; itr<nTr; itr++ ){
8962 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8963 if( !seed ) continue;
8964 //FollowBackProlongation(*seed,0);
8965 // cout<<seed->GetNumberOfClusters()<<endl;
8966 Int_t foundable,found,shared;
8967 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8968 seed->SetNFoundable(foundable);
8969 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8970 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8971 //MarkSeedFree(seeds->RemoveAt(itr));
8974 if (seed->GetNumberOfClusters()<30 ||
8975 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8976 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8977 MarkSeedFree(seeds->RemoveAt(itr));
8981 for( int ir=0; ir<nup; ir++){
8982 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8986 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8990 void AliTPCtracker::FillClusterOccupancyInfo()
8992 //fill the cluster occupancy info into the ESD friend
8993 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8994 if (!esdFriend) return;
8996 for (Int_t isector=0; isector<18; isector++){
8997 AliTPCtrackerSector &iroc = fInnerSec[isector];
8998 AliTPCtrackerSector &oroc = fOuterSec[isector];
9000 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
9001 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
9002 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
9003 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
9004 //clusters used in tracking
9005 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
9006 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
9007 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
9008 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));