1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 //-------------------------------------------------------
18 // Implementation of the TPC tracker
20 // Origin: Marian Ivanov Marian.Ivanov@cern.ch
22 // AliTPC parallel tracker
24 // The track fitting is based on Kalman filtering approach
25 // The track finding steps:
26 // 1. Seeding - with and without vertex constraint
27 // - seeding with vertex constain done at first n^2 proble
28 // - seeding without vertex constraint n^3 problem
29 // 2. Tracking - follow prolongation road - find cluster - update kalman track
30 // The seeding and tracking is repeated several times, in different seeding region.
31 // This approach enables to find the track which cannot be seeded in some region of TPC
32 // This can happen because of low momenta (track do not reach outer radius), or track is currently in the ded region between sectors, or the track is for the moment overlapped with other track (seed quality is poor) ...
34 // With this approach we reach almost 100 % efficiency also for high occupancy events.
35 // (If the seeding efficiency in a region is about 90 % than with logical or of several
36 // regions we will reach 100% (in theory - supposing independence)
38 // Repeating several seeding - tracking procedures some of the tracks can be find
41 // The procedures to remove multi find tacks are impremented:
42 // RemoveUsed2 - fast procedure n problem -
43 // Algorithm - Sorting tracks according quality
44 // remove tracks with some shared fraction
45 // Sharing in respect to all tacks
46 // Signing clusters in gold region
47 // FindSplitted - slower algorithm n^2
48 // Sort the tracks according quality
49 // Loop over pair of tracks
50 // If overlap with other track bigger than threshold - remove track
52 // FindCurling - Finds the pair of tracks which are curling
53 // - About 10% of tracks can be find with this procedure
54 // The combinatorial background is too big to be used in High
55 // multiplicity environment
56 // - n^2 problem - Slow procedure - currently it is disabled because of
59 // The number of splitted tracks can be reduced disabling the sharing of the cluster.
60 // tpcRecoParam-> SetClusterSharing(kFALSE);
61 // IT IS HIGHLY non recomended to use it in high flux enviroonment
62 // Even using this switch some tracks can be found more than once
63 // (because of multiple seeding and low quality tracks which will not cross full chamber)
66 // The tracker itself can be debugged - the information about tracks can be stored in several // phases of the reconstruction
67 // To enable storage of the TPC tracks in the ESD friend track
68 // use AliTPCReconstructor::SetStreamLevel(n);
70 // The debug level - different procedure produce tree for numerical debugging of code and data (see comments foEStreamFlags in AliTPCtracker.h )
74 // Adding systematic errors to the covariance:
76 // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
77 // of the tracks (not to the clusters as they are dependent):
78 // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
79 // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
80 // The default values are 0.
82 // The systematic errors are added to the covariance matrix in following places:
84 // 1. During fisrt itteration - AliTPCtracker::FillESD
85 // 2. Second iteration -
86 // 2.a ITS->TPC - AliTPCtracker::ReadSeeds
87 // 2.b TPC->TRD - AliTPCtracker::PropagateBack
88 // 3. Third iteration -
89 // 3.a TRD->TPC - AliTPCtracker::ReadSeeds
90 // 3.b TPC->ITS - AliTPCtracker::RefitInward
95 #include "Riostream.h"
96 #include <TClonesArray.h>
98 #include <TObjArray.h>
100 #include <TMatrixD.h>
101 #include <TGraphErrors.h>
102 #include <TTimeStamp.h>
104 #include "AliComplexCluster.h"
105 #include "AliESDEvent.h"
106 #include "AliESDtrack.h"
107 #include "AliESDVertex.h"
110 #include "AliHelix.h"
111 #include "AliRunLoader.h"
112 #include "AliTPCClustersRow.h"
113 #include "AliTPCParam.h"
114 #include "AliTPCReconstructor.h"
115 #include "AliTPCpolyTrack.h"
116 #include "AliTPCreco.h"
117 #include "AliTPCseed.h"
119 #include "AliTPCtrackerSector.h"
120 #include "AliTPCtracker.h"
121 #include "TStopwatch.h"
122 #include "AliTPCReconstructor.h"
123 #include "AliAlignObj.h"
124 #include "AliTrackPointArray.h"
126 #include "AliTPCcalibDB.h"
127 #include "AliTPCcalibDButil.h"
128 #include "AliTPCTransform.h"
129 #include "AliTPCClusterParam.h"
130 #include "AliTPCdEdxInfo.h"
131 #include "AliDCSSensorArray.h"
132 #include "AliDCSSensor.h"
134 #include "AliCosmicTracker.h"
135 #include "AliTPCROC.h"
136 #include "AliMathBase.h"
141 ClassImp(AliTPCtracker)
145 class AliTPCFastMath {
148 static Double_t FastAsin(Double_t x);
150 static Double_t fgFastAsin[20000]; //lookup table for fast asin computation
153 Double_t AliTPCFastMath::fgFastAsin[20000];
154 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
156 AliTPCFastMath::AliTPCFastMath(){
158 // initialized lookup table;
159 for (Int_t i=0;i<10000;i++){
160 fgFastAsin[2*i] = TMath::ASin(i/10000.);
161 fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
165 Double_t AliTPCFastMath::FastAsin(Double_t x){
167 // return asin using lookup table
169 Int_t index = int(x*10000);
170 return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
173 Int_t index = int(x*10000);
174 return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
176 //__________________________________________________________________
177 AliTPCtracker::AliTPCtracker()
199 fCrossTalkSignalArray(0),
206 // default constructor
208 for (Int_t irow=0; irow<200; irow++){
214 //_____________________________________________________________________
218 Int_t AliTPCtracker::UpdateTrack(AliTPCseed * track, Int_t accept){
220 //update track information using current cluster - track->fCurrentCluster
223 AliTPCclusterMI* c =track->GetCurrentCluster();
224 if (accept > 0) //sign not accepted clusters
225 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);
226 else // unsign accpeted clusters
227 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);
228 UInt_t i = track->GetCurrentClusterIndex1();
230 Int_t sec=(i&0xff000000)>>24;
231 //Int_t row = (i&0x00ff0000)>>16;
232 track->SetRow((i&0x00ff0000)>>16);
233 track->SetSector(sec);
234 // Int_t index = i&0xFFFF;
235 if (sec>=fkParam->GetNInnerSector()) track->SetRow(track->GetRow()+fkParam->GetNRowLow());
236 track->SetClusterIndex2(track->GetRow(), i);
237 //track->fFirstPoint = row;
238 //if ( track->fLastPoint<row) track->fLastPoint =row;
239 // if (track->fRow<0 || track->fRow>160) {
240 // printf("problem\n");
242 if (track->GetFirstPoint()>track->GetRow())
243 track->SetFirstPoint(track->GetRow());
244 if (track->GetLastPoint()<track->GetRow())
245 track->SetLastPoint(track->GetRow());
248 track->SetClusterPointer(track->GetRow(),c);
251 Double_t angle2 = track->GetSnp()*track->GetSnp();
253 //SET NEW Track Point
255 if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
257 angle2 = TMath::Sqrt(angle2/(1-angle2));
258 AliTPCTrackerPoint &point =*(track->GetTrackPoint(track->GetRow()));
260 point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
261 point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
262 point.SetErrY(sqrt(track->GetErrorY2()));
263 point.SetErrZ(sqrt(track->GetErrorZ2()));
265 point.SetX(track->GetX());
266 point.SetY(track->GetY());
267 point.SetZ(track->GetZ());
268 point.SetAngleY(angle2);
269 point.SetAngleZ(track->GetTgl());
270 if (point.IsShared()){
271 track->SetErrorY2(track->GetErrorY2()*4);
272 track->SetErrorZ2(track->GetErrorZ2()*4);
276 Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
278 // track->SetErrorY2(track->GetErrorY2()*1.3);
279 // track->SetErrorY2(track->GetErrorY2()+0.01);
280 // track->SetErrorZ2(track->GetErrorZ2()*1.3);
281 // track->SetErrorZ2(track->GetErrorZ2()+0.005);
283 if (accept>0) return 0;
284 if (track->GetNumberOfClusters()%20==0){
285 // if (track->fHelixIn){
286 // TClonesArray & larr = *(track->fHelixIn);
287 // Int_t ihelix = larr.GetEntriesFast();
288 // new(larr[ihelix]) AliHelix(*track) ;
291 if (AliTPCReconstructor::StreamLevel()&kStreamUpdateTrack) {
292 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
293 AliExternalTrackParam param(*track);
294 TTreeSRedirector &cstream = *fDebugStreamer;
295 cstream<<"UpdateTrack"<<
301 track->SetNoCluster(0);
302 return track->Update(c,chi2,i);
307 Int_t AliTPCtracker::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
310 // decide according desired precision to accept given
311 // cluster for tracking
313 seed->GetProlongation(cluster->GetX(),yt,zt);
314 Double_t sy2=ErrY2(seed,cluster);
315 Double_t sz2=ErrZ2(seed,cluster);
317 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
318 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
319 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
320 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
321 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
322 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
323 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
324 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
326 Double_t rdistance2 = rdistancey2+rdistancez2;
329 if (AliTPCReconstructor::StreamLevel()>2 && ( (fIteration>0)|| (seed->GetNumberOfClusters()>20))) {
330 // if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
331 Float_t rmsy2 = seed->GetCurrentSigmaY2();
332 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
333 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
334 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
335 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
336 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
337 AliExternalTrackParam param(*seed);
338 static TVectorD gcl(3),gtr(3);
340 param.GetXYZ(gcl.GetMatrixArray());
341 cluster->GetGlobalXYZ(gclf);
342 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
343 Int_t nclSeed=seed->GetNumberOfClusters();
345 if (AliTPCReconstructor::StreamLevel()&kStreamErrParam) { // flag:stream in debug mode cluster and track extrapolation at given row together with error nad shape estimate
346 Int_t eventNr = fEvent->GetEventNumberInFile();
348 (*fDebugStreamer)<<"ErrParam"<<
349 "iter="<<fIteration<<
350 "eventNr="<<eventNr<<
352 "nclSeed="<<nclSeed<<
364 "rmsy2p30="<<rmsy2p30<<
365 "rmsz2p30="<<rmsz2p30<<
366 "rmsy2p30R="<<rmsy2p30R<<
367 "rmsz2p30R="<<rmsz2p30R<<
368 // normalize distance -
369 "rdisty="<<rdistancey2<<
370 "rdistz="<<rdistancez2<<
371 "rdist="<<rdistance2<< //
375 //return 0; // temporary
376 if (rdistance2>32) return 3;
379 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
380 return 2; //suspisiouce - will be changed
382 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
383 // strict cut on overlaped cluster
384 return 2; //suspisiouce - will be changed
386 if ( (rdistancey2>1. || rdistancez2>6.25 )
387 && cluster->GetType()<0){
388 seed->SetNFoundable(seed->GetNFoundable()-1);
392 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
394 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
395 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
408 //_____________________________________________________________________________
409 AliTPCtracker::AliTPCtracker(const AliTPCParam *par):
411 fkNIS(par->GetNInnerSector()/2),
413 fkNOS(par->GetNOuterSector()/2),
431 fCrossTalkSignalArray(0),
437 //---------------------------------------------------------------------
438 // The main TPC tracker constructor
439 //---------------------------------------------------------------------
440 fInnerSec=new AliTPCtrackerSector[fkNIS];
441 fOuterSec=new AliTPCtrackerSector[fkNOS];
444 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
445 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
448 Int_t nrowlow = par->GetNRowLow();
449 Int_t nrowup = par->GetNRowUp();
452 for (i=0;i<nrowlow;i++){
453 fXRow[i] = par->GetPadRowRadiiLow(i);
454 fPadLength[i]= par->GetPadPitchLength(0,i);
455 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
459 for (i=0;i<nrowup;i++){
460 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
461 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
462 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
465 if (AliTPCReconstructor::StreamLevel()>0) {
466 fDebugStreamer = new TTreeSRedirector("TPCdebug.root","recreate");
469 fSeedsPool = new TClonesArray("AliTPCseed",1000);
471 // crosstalk array and matrix initialization
473 Int_t nTimeBinsAll = par->GetMaxTBin();
474 Int_t nWireSegments = 11;
475 fCrossTalkSignalArray = new TObjArray(nROCs*4); //
476 fCrossTalkSignalArray->SetOwner(kTRUE);
477 for (Int_t isector=0; isector<4*nROCs; isector++){
478 TMatrixD * crossTalkSignal = new TMatrixD(nWireSegments,nTimeBinsAll);
479 for (Int_t imatrix = 0; imatrix<11; imatrix++)
480 for (Int_t jmatrix = 0; jmatrix<nTimeBinsAll; jmatrix++){
481 (*crossTalkSignal)[imatrix][jmatrix]=0.;
483 fCrossTalkSignalArray->AddAt(crossTalkSignal,isector);
487 //________________________________________________________________________
488 AliTPCtracker::AliTPCtracker(const AliTPCtracker &t):
510 fCrossTalkSignalArray(0),
516 //------------------------------------
517 // dummy copy constructor
518 //------------------------------------------------------------------
520 for (Int_t irow=0; irow<200; irow++){
527 AliTPCtracker & AliTPCtracker::operator=(const AliTPCtracker& /*r*/)
529 //------------------------------
531 //--------------------------------------------------------------
534 //_____________________________________________________________________________
535 AliTPCtracker::~AliTPCtracker() {
536 //------------------------------------------------------------------
537 // TPC tracker destructor
538 //------------------------------------------------------------------
545 if (fCrossTalkSignalArray) delete fCrossTalkSignalArray;
546 if (fDebugStreamer) delete fDebugStreamer;
547 if (fSeedsPool) delete fSeedsPool;
551 void AliTPCtracker::FillESD(const TObjArray* arr)
555 //fill esds using updated tracks
561 // write tracks to the event
562 // store index of the track
563 Int_t nseed=arr->GetEntriesFast();
564 //FindKinks(arr,fEvent);
565 for (Int_t i=0; i<nseed; i++) {
566 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
570 if (AliTPCReconstructor::StreamLevel()&kStreamFillESD) {
571 (*fDebugStreamer)<<"FillESD"<< // flag: stream track information in FillESD function (after track Iteration 0)
575 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
576 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
577 pt->PropagateTo(fkParam->GetInnerRadiusLow());
580 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
581 iotrack.~AliESDtrack();
582 new(&iotrack) AliESDtrack;
583 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
584 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
585 iotrack.SetTPCPoints(pt->GetPoints());
586 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
587 iotrack.SetV0Indexes(pt->GetV0Indexes());
588 // iotrack.SetTPCpid(pt->fTPCr);
589 //iotrack.SetTPCindex(i);
590 MakeESDBitmaps(pt, &iotrack);
591 fEvent->AddTrack(&iotrack);
595 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
596 iotrack.~AliESDtrack();
597 new(&iotrack) AliESDtrack;
598 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
599 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
600 iotrack.SetTPCPoints(pt->GetPoints());
601 //iotrack.SetTPCindex(i);
602 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
603 iotrack.SetV0Indexes(pt->GetV0Indexes());
604 MakeESDBitmaps(pt, &iotrack);
605 // iotrack.SetTPCpid(pt->fTPCr);
606 fEvent->AddTrack(&iotrack);
610 // short tracks - maybe decays
612 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
613 Int_t found,foundable,shared;
614 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
615 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
616 iotrack.~AliESDtrack();
617 new(&iotrack) AliESDtrack;
618 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
619 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
620 //iotrack.SetTPCindex(i);
621 iotrack.SetTPCPoints(pt->GetPoints());
622 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
623 iotrack.SetV0Indexes(pt->GetV0Indexes());
624 MakeESDBitmaps(pt, &iotrack);
625 //iotrack.SetTPCpid(pt->fTPCr);
626 fEvent->AddTrack(&iotrack);
631 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
632 Int_t found,foundable,shared;
633 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
634 if (found<20) continue;
635 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
637 iotrack.~AliESDtrack();
638 new(&iotrack) AliESDtrack;
639 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
640 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
641 iotrack.SetTPCPoints(pt->GetPoints());
642 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
643 iotrack.SetV0Indexes(pt->GetV0Indexes());
644 MakeESDBitmaps(pt, &iotrack);
645 //iotrack.SetTPCpid(pt->fTPCr);
646 //iotrack.SetTPCindex(i);
647 fEvent->AddTrack(&iotrack);
650 // short tracks - secondaties
652 if ( (pt->GetNumberOfClusters()>30) ) {
653 Int_t found,foundable,shared;
654 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
655 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
656 iotrack.~AliESDtrack();
657 new(&iotrack) AliESDtrack;
658 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
659 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
660 iotrack.SetTPCPoints(pt->GetPoints());
661 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
662 iotrack.SetV0Indexes(pt->GetV0Indexes());
663 MakeESDBitmaps(pt, &iotrack);
664 //iotrack.SetTPCpid(pt->fTPCr);
665 //iotrack.SetTPCindex(i);
666 fEvent->AddTrack(&iotrack);
671 if ( (pt->GetNumberOfClusters()>15)) {
672 Int_t found,foundable,shared;
673 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
674 if (found<15) continue;
675 if (foundable<=0) continue;
676 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
677 if (float(found)/float(foundable)<0.8) continue;
679 iotrack.~AliESDtrack();
680 new(&iotrack) AliESDtrack;
681 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
682 iotrack.SetTPCsignal(pt->GetdEdx(), pt->GetSDEDX(0), pt->GetNCDEDX(0));
683 iotrack.SetTPCPoints(pt->GetPoints());
684 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
685 iotrack.SetV0Indexes(pt->GetV0Indexes());
686 MakeESDBitmaps(pt, &iotrack);
687 // iotrack.SetTPCpid(pt->fTPCr);
688 //iotrack.SetTPCindex(i);
689 fEvent->AddTrack(&iotrack);
693 // >> account for suppressed tracks in the kink indices (RS)
694 int nESDtracks = fEvent->GetNumberOfTracks();
695 for (int it=nESDtracks;it--;) {
696 AliESDtrack* esdTr = fEvent->GetTrack(it);
697 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
698 for (int ik=0;ik<3;ik++) {
700 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
701 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
703 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
706 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
710 // << account for suppressed tracks in the kink indices (RS)
711 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
719 Double_t AliTPCtracker::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
722 // Use calibrated cluster error from OCDB
724 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
726 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
727 Int_t ctype = cl->GetType();
728 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
729 Double_t angle = seed->GetSnp()*seed->GetSnp();
730 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
731 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
733 erry2+=0.5; // edge cluster
737 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
738 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
739 erry2+=addErr*addErr;
740 const Double_t *errCluster = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorCluster();
741 erry2+=errCluster[0]*errCluster[0];
742 seed->SetErrorY2(erry2);
746 //calculate look-up table at the beginning
747 // static Bool_t ginit = kFALSE;
748 // static Float_t gnoise1,gnoise2,gnoise3;
749 // static Float_t ggg1[10000];
750 // static Float_t ggg2[10000];
751 // static Float_t ggg3[10000];
752 // static Float_t glandau1[10000];
753 // static Float_t glandau2[10000];
754 // static Float_t glandau3[10000];
756 // static Float_t gcor01[500];
757 // static Float_t gcor02[500];
758 // static Float_t gcorp[500];
762 // if (ginit==kFALSE){
763 // for (Int_t i=1;i<500;i++){
764 // Float_t rsigma = float(i)/100.;
765 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
766 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
767 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
771 // for (Int_t i=3;i<10000;i++){
775 // Float_t amp = float(i);
776 // Float_t padlength =0.75;
777 // gnoise1 = 0.0004/padlength;
778 // Float_t nel = 0.268*amp;
779 // Float_t nprim = 0.155*amp;
780 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
781 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
782 // if (glandau1[i]>1) glandau1[i]=1;
783 // glandau1[i]*=padlength*padlength/12.;
787 // gnoise2 = 0.0004/padlength;
789 // nprim = 0.133*amp;
790 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
791 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
792 // if (glandau2[i]>1) glandau2[i]=1;
793 // glandau2[i]*=padlength*padlength/12.;
798 // gnoise3 = 0.0004/padlength;
800 // nprim = 0.133*amp;
801 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
802 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
803 // if (glandau3[i]>1) glandau3[i]=1;
804 // glandau3[i]*=padlength*padlength/12.;
812 // Int_t amp = int(TMath::Abs(cl->GetQ()));
814 // seed->SetErrorY2(1.);
818 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
819 // Int_t ctype = cl->GetType();
820 // Float_t padlength= GetPadPitchLength(seed->GetRow());
821 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
822 // angle2 = angle2/(1-angle2);
824 // //cluster "quality"
825 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
828 // if (fSectors==fInnerSec){
829 // snoise2 = gnoise1;
830 // res = ggg1[amp]*z+glandau1[amp]*angle2;
831 // if (ctype==0) res *= gcor01[rsigmay];
834 // res*= gcorp[rsigmay];
838 // if (padlength<1.1){
839 // snoise2 = gnoise2;
840 // res = ggg2[amp]*z+glandau2[amp]*angle2;
841 // if (ctype==0) res *= gcor02[rsigmay];
844 // res*= gcorp[rsigmay];
848 // snoise2 = gnoise3;
849 // res = ggg3[amp]*z+glandau3[amp]*angle2;
850 // if (ctype==0) res *= gcor02[rsigmay];
853 // res*= gcorp[rsigmay];
860 // res*=2.4; // overestimate error 2 times
864 // if (res<2*snoise2)
867 // seed->SetErrorY2(res);
875 Double_t AliTPCtracker::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
878 // Use calibrated cluster error from OCDB
880 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
882 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
883 Int_t ctype = cl->GetType();
884 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
886 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
887 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
888 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
889 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
891 errz2+=0.5; // edge cluster
895 const Double_t *errInner = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorClusterInner();
896 addErr=errInner[0]*TMath::Exp(-TMath::Abs((cl->GetX()-85.)/errInner[1]));
897 errz2+=addErr*addErr;
898 const Double_t *errCluster = AliTPCReconstructor::GetRecoParam()->GetSystematicErrorCluster();
899 errz2+=errCluster[1]*errCluster[1];
900 seed->SetErrorZ2(errz2);
906 // //seed->SetErrorY2(0.1);
908 // //calculate look-up table at the beginning
909 // static Bool_t ginit = kFALSE;
910 // static Float_t gnoise1,gnoise2,gnoise3;
911 // static Float_t ggg1[10000];
912 // static Float_t ggg2[10000];
913 // static Float_t ggg3[10000];
914 // static Float_t glandau1[10000];
915 // static Float_t glandau2[10000];
916 // static Float_t glandau3[10000];
918 // static Float_t gcor01[1000];
919 // static Float_t gcor02[1000];
920 // static Float_t gcorp[1000];
924 // if (ginit==kFALSE){
925 // for (Int_t i=1;i<1000;i++){
926 // Float_t rsigma = float(i)/100.;
927 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
928 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
929 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
933 // for (Int_t i=3;i<10000;i++){
937 // Float_t amp = float(i);
938 // Float_t padlength =0.75;
939 // gnoise1 = 0.0004/padlength;
940 // Float_t nel = 0.268*amp;
941 // Float_t nprim = 0.155*amp;
942 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
943 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
944 // if (glandau1[i]>1) glandau1[i]=1;
945 // glandau1[i]*=padlength*padlength/12.;
949 // gnoise2 = 0.0004/padlength;
951 // nprim = 0.133*amp;
952 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
953 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
954 // if (glandau2[i]>1) glandau2[i]=1;
955 // glandau2[i]*=padlength*padlength/12.;
960 // gnoise3 = 0.0004/padlength;
962 // nprim = 0.133*amp;
963 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
964 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
965 // if (glandau3[i]>1) glandau3[i]=1;
966 // glandau3[i]*=padlength*padlength/12.;
974 // Int_t amp = int(TMath::Abs(cl->GetQ()));
976 // seed->SetErrorY2(1.);
980 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
981 // Int_t ctype = cl->GetType();
982 // Float_t padlength= GetPadPitchLength(seed->GetRow());
984 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
985 // // if (angle2<0.6) angle2 = 0.6;
986 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
988 // //cluster "quality"
989 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
992 // if (fSectors==fInnerSec){
993 // snoise2 = gnoise1;
994 // res = ggg1[amp]*z+glandau1[amp]*angle2;
995 // if (ctype==0) res *= gcor01[rsigmaz];
998 // res*= gcorp[rsigmaz];
1002 // if (padlength<1.1){
1003 // snoise2 = gnoise2;
1004 // res = ggg2[amp]*z+glandau2[amp]*angle2;
1005 // if (ctype==0) res *= gcor02[rsigmaz];
1008 // res*= gcorp[rsigmaz];
1012 // snoise2 = gnoise3;
1013 // res = ggg3[amp]*z+glandau3[amp]*angle2;
1014 // if (ctype==0) res *= gcor02[rsigmaz];
1017 // res*= gcorp[rsigmaz];
1026 // if ((ctype<0) &&<70){
1031 // if (res<2*snoise2)
1033 // if (res>3) res =3;
1034 // seed->SetErrorZ2(res);
1042 void AliTPCtracker::RotateToLocal(AliTPCseed *seed)
1044 //rotate to track "local coordinata
1045 Float_t x = seed->GetX();
1046 Float_t y = seed->GetY();
1047 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
1050 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
1051 if (!seed->Rotate(fSectors->GetAlpha()))
1053 } else if (y <-ymax) {
1054 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
1055 if (!seed->Rotate(-fSectors->GetAlpha()))
1063 //_____________________________________________________________________________
1064 Double_t AliTPCtracker::F1old(Double_t x1,Double_t y1,
1065 Double_t x2,Double_t y2,
1066 Double_t x3,Double_t y3) const
1068 //-----------------------------------------------------------------
1069 // Initial approximation of the track curvature
1070 //-----------------------------------------------------------------
1071 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1072 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1073 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1074 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1075 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1077 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1078 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1079 return -xr*yr/sqrt(xr*xr+yr*yr);
1084 //_____________________________________________________________________________
1085 Double_t AliTPCtracker::F1(Double_t x1,Double_t y1,
1086 Double_t x2,Double_t y2,
1087 Double_t x3,Double_t y3) const
1089 //-----------------------------------------------------------------
1090 // Initial approximation of the track curvature
1091 //-----------------------------------------------------------------
1097 Double_t det = x3*y2-x2*y3;
1098 if (TMath::Abs(det)<1e-10){
1102 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1103 Double_t x0 = x3*0.5-y3*u;
1104 Double_t y0 = y3*0.5+x3*u;
1105 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1111 Double_t AliTPCtracker::F2(Double_t x1,Double_t y1,
1112 Double_t x2,Double_t y2,
1113 Double_t x3,Double_t y3) const
1115 //-----------------------------------------------------------------
1116 // Initial approximation of the track curvature
1117 //-----------------------------------------------------------------
1123 Double_t det = x3*y2-x2*y3;
1124 if (TMath::Abs(det)<1e-10) {
1128 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1129 Double_t x0 = x3*0.5-y3*u;
1130 Double_t y0 = y3*0.5+x3*u;
1131 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1140 //_____________________________________________________________________________
1141 Double_t AliTPCtracker::F2old(Double_t x1,Double_t y1,
1142 Double_t x2,Double_t y2,
1143 Double_t x3,Double_t y3) const
1145 //-----------------------------------------------------------------
1146 // Initial approximation of the track curvature times center of curvature
1147 //-----------------------------------------------------------------
1148 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1149 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1150 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1151 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1152 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1154 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1156 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1159 //_____________________________________________________________________________
1160 Double_t AliTPCtracker::F3(Double_t x1,Double_t y1,
1161 Double_t x2,Double_t y2,
1162 Double_t z1,Double_t z2) const
1164 //-----------------------------------------------------------------
1165 // Initial approximation of the tangent of the track dip angle
1166 //-----------------------------------------------------------------
1167 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1171 Double_t AliTPCtracker::F3n(Double_t x1,Double_t y1,
1172 Double_t x2,Double_t y2,
1173 Double_t z1,Double_t z2, Double_t c) const
1175 //-----------------------------------------------------------------
1176 // Initial approximation of the tangent of the track dip angle
1177 //-----------------------------------------------------------------
1181 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1183 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1184 if (TMath::Abs(d*c*0.5)>1) return 0;
1185 // Double_t angle2 = TMath::ASin(d*c*0.5);
1186 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1187 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1189 angle2 = (z1-z2)*c/(angle2*2.);
1193 Bool_t AliTPCtracker::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1194 {//-----------------------------------------------------------------
1195 // This function find proloncation of a track to a reference plane x=x2.
1196 //-----------------------------------------------------------------
1200 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1204 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1205 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1209 Double_t dy = dx*(c1+c2)/(r1+r2);
1212 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1214 if (TMath::Abs(delta)>0.01){
1215 dz = x[3]*TMath::ASin(delta)/x[4];
1217 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1220 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1228 Int_t AliTPCtracker::LoadClusters (TTree *const tree)
1233 return LoadClusters();
1237 Int_t AliTPCtracker::LoadClusters(const TObjArray *arr)
1240 // load clusters to the memory
1241 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1242 Int_t lower = arr->LowerBound();
1243 Int_t entries = arr->GetEntriesFast();
1245 for (Int_t i=lower; i<entries; i++) {
1246 clrow = (AliTPCClustersRow*) arr->At(i);
1247 if(!clrow) continue;
1248 if(!clrow->GetArray()) continue;
1252 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1254 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1255 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1258 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1259 AliTPCtrackerRow * tpcrow=0;
1262 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1266 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1267 left = (sec-fkNIS*2)/fkNOS;
1270 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1271 for (Int_t j=0;j<tpcrow->GetN1();++j)
1272 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1275 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1276 for (Int_t j=0;j<tpcrow->GetN2();++j)
1277 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1279 clrow->GetArray()->Clear("C");
1288 Int_t AliTPCtracker::LoadClusters(const TClonesArray *arr)
1291 // load clusters to the memory from one
1294 AliTPCclusterMI *clust=0;
1295 Int_t count[72][96] = { {0} , {0} };
1297 // loop over clusters
1298 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1299 clust = (AliTPCclusterMI*)arr->At(icl);
1300 if(!clust) continue;
1301 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1303 // transform clusters
1306 // count clusters per pad row
1307 count[clust->GetDetector()][clust->GetRow()]++;
1310 // insert clusters to sectors
1311 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1312 clust = (AliTPCclusterMI*)arr->At(icl);
1313 if(!clust) continue;
1315 Int_t sec = clust->GetDetector();
1316 Int_t row = clust->GetRow();
1318 // filter overlapping pad rows needed by HLT
1319 if(sec<fkNIS*2) { //IROCs
1320 if(row == 30) continue;
1323 if(row == 27 || row == 76) continue;
1328 // left = sec/fkNIS;
1329 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1332 // left = (sec-fkNIS*2)/fkNOS;
1333 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1337 // Load functions must be called behind LoadCluster(TClonesArray*)
1339 //LoadOuterSectors();
1340 //LoadInnerSectors();
1346 Int_t AliTPCtracker::LoadClusters()
1349 // load clusters to the memory
1350 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1352 // TTree * tree = fClustersArray.GetTree();
1353 AliInfo("LoadClusters()\n");
1355 TTree * tree = fInput;
1356 TBranch * br = tree->GetBranch("Segment");
1357 br->SetAddress(&clrow);
1359 // Conversion of pad, row coordinates in local tracking coords.
1360 // Could be skipped here; is already done in clusterfinder
1362 Int_t j=Int_t(tree->GetEntries());
1363 for (Int_t i=0; i<j; i++) {
1367 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1368 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1369 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1372 AliTPCtrackerRow * tpcrow=0;
1375 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1379 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1380 left = (sec-fkNIS*2)/fkNOS;
1383 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1384 for (Int_t k=0;k<tpcrow->GetN1();++k)
1385 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1388 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1389 for (Int_t k=0;k<tpcrow->GetN2();++k)
1390 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1398 cout << " =================================================================================================================================== " << endl;
1399 cout << " AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection() = " << AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection() << endl;
1400 cout << " AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection() = " << AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection() << endl;
1401 cout << " =================================================================================================================================== " << endl;
1403 if (AliTPCReconstructor::GetRecoParam()->GetUseIonTailCorrection()) ApplyTailCancellation();
1404 if (AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()!=0.) CalculateXtalkCorrection();
1405 if (AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrection()!=0.) ApplyXtalkCorrection();
1406 //if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();
1411 void AliTPCtracker::CalculateXtalkCorrection(){
1413 // Calculate crosstalk estimate
1415 const Int_t nROCs = 72;
1416 const Int_t nIterations=3; //
1417 // 0.) reset crosstalk matrix
1419 for (Int_t isector=0; isector<nROCs*4; isector++){ //set all ellemts of crosstalk matrix to 0
1420 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1421 if (crossTalkMatrix)(*crossTalkMatrix)*=0;
1425 // 1.) Filling part -- loop over clusters
1427 Double_t missingChargeFactor= AliTPCReconstructor::GetRecoParam()->GetCrosstalkCorrectionMissingCharge();
1428 for (Int_t iter=0; iter<nIterations;iter++){
1429 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1430 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1431 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1432 Int_t nrows = sector.GetNRows();
1434 if (isector<18) sec=isector+18*iside;
1435 if (isector>=18) sec=18+isector+18*iside;
1436 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1439 Int_t wireSegmentID = fkParam->GetWireSegment(sec,row);
1440 Float_t nPadsPerSegment = (Float_t)(fkParam->GetNPadsPerSegment(wireSegmentID));
1441 TMatrixD &crossTalkSignal = *((TMatrixD*)fCrossTalkSignalArray->At(sec));
1442 TMatrixD &crossTalkSignalCache = *((TMatrixD*)fCrossTalkSignalArray->At(sec+nROCs*2)); // this is the cache value of the crosstalk from previous iteration
1443 TMatrixD &crossTalkSignalBelow = *((TMatrixD*)fCrossTalkSignalArray->At(sec+nROCs));
1444 Int_t nCols=crossTalkSignal.GetNcols();
1446 AliTPCtrackerRow& tpcrow = sector[row];
1447 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1448 if (iside>0) ncl=tpcrow.GetN2();
1449 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1450 AliTPCclusterMI *clXtalk= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1452 Int_t timeBinXtalk = clXtalk->GetTimeBin();
1453 Double_t rmsPadMin2=0.5*0.5+(fkParam->GetDiffT()*fkParam->GetDiffT())*(TMath::Abs((clXtalk->GetZ()-fkParam->GetZLength())))/(fkParam->GetPadPitchWidth(sec)*fkParam->GetPadPitchWidth(sec)); // minimal PRF width - 0.5 is the PRF in the pad units - we should et it from fkparam getters
1454 Double_t rmsTimeMin2=1+(fkParam->GetDiffL()*fkParam->GetDiffL())*(TMath::Abs((clXtalk->GetZ()-fkParam->GetZLength())))/(fkParam->GetZWidth()*fkParam->GetZWidth()); // minimal PRF width - 1 is the TRF in the time bin units - we should et it from fkParam getters
1455 Double_t rmsTime2 = clXtalk->GetSigmaZ2()/(fkParam->GetZWidth()*fkParam->GetZWidth());
1456 Double_t rmsPad2 = clXtalk->GetSigmaY2()/(fkParam->GetPadPitchWidth(sec)*fkParam->GetPadPitchWidth(sec));
1457 if (rmsPadMin2>rmsPad2){
1460 if (rmsTimeMin2>rmsTime2){
1461 rmsTime2=rmsTimeMin2;
1464 Double_t norm= 2.*TMath::Exp(-1.0/(2.*rmsTime2))+2.*TMath::Exp(-4.0/(2.*rmsTime2))+1.;
1465 Double_t qTotXtalk = 0.;
1466 Double_t qTotXtalkMissing = 0.;
1467 for (Int_t itb=timeBinXtalk-2, idelta=-2; itb<=timeBinXtalk+2; itb++,idelta++) {
1468 if (itb<0 || itb>=nCols) continue;
1469 Double_t missingCharge=0;
1470 Double_t trf= TMath::Exp(-idelta*idelta/(2.*rmsTime2));
1471 if (missingChargeFactor>0) {
1472 for (Int_t dpad=-2; dpad<=2; dpad++){
1473 Double_t qPad = clXtalk->GetMax()*TMath::Exp(-dpad*dpad/(2.*rmsPad2))*trf;
1474 if (TMath::Nint(qPad-crossTalkSignalCache[wireSegmentID][itb])<=fkParam->GetZeroSup()){
1475 missingCharge+=qPad+crossTalkSignalCache[wireSegmentID][itb];
1477 missingCharge+=crossTalkSignalCache[wireSegmentID][itb];
1481 qTotXtalk = clXtalk->GetQ()*trf/norm+missingCharge*missingChargeFactor;
1482 qTotXtalkMissing = missingCharge;
1483 crossTalkSignal[wireSegmentID][itb]+= qTotXtalk/nPadsPerSegment;
1484 crossTalkSignalBelow[wireSegmentID][itb]+= qTotXtalkMissing/nPadsPerSegment;
1485 } // end of time bin loop
1486 } // end of cluster loop
1487 } // end of rows loop
1488 } // end of side loop
1489 } // end of sector loop
1491 // copy crosstalk matrix to cached used for next itteration
1494 // 2.) dump the crosstalk matrices to tree for further investigation
1495 // a.) to estimate fluctuation of pedestal in indiviula wire segments
1496 // b.) to check correlation between regions
1497 // c.) to check relative conribution of signal below threshold to crosstalk
1499 if (AliTPCReconstructor::StreamLevel()&kStreamCrosstalkMatrix) {
1500 for (Int_t isector=0; isector<nROCs; isector++){ //set all ellemts of crosstalk matrix to 0
1501 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1502 TMatrixD * crossTalkMatrixBelow = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs);
1503 TMatrixD * crossTalkMatrixCache = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs*2);
1504 TVectorD vecAll(crossTalkMatrix->GetNrows());
1505 TVectorD vecBelow(crossTalkMatrix->GetNrows());
1506 TVectorD vecCache(crossTalkMatrixCache->GetNrows());
1508 for (Int_t itime=0; itime<crossTalkMatrix->GetNcols(); itime++){
1509 for (Int_t iwire=0; iwire<crossTalkMatrix->GetNrows(); iwire++){
1510 vecAll[iwire]=(*crossTalkMatrix)(iwire,itime);
1511 vecBelow[iwire]=(*crossTalkMatrixBelow)(iwire,itime);
1512 vecCache[iwire]=(*crossTalkMatrixCache)(iwire,itime);
1514 (*fDebugStreamer)<<"crosstalkMatrix"<<
1515 "iter="<<iter<< //iteration
1516 "sector="<<isector<< // sector
1517 "itime="<<itime<< // time bin index
1518 "vecAll.="<<&vecAll<< // crosstalk charge + charge below threshold
1519 "vecCache.="<<&vecCache<< // crosstalk charge + charge below threshold
1520 "vecBelow.="<<&vecBelow<< // crosstalk contribution from signal below threshold
1525 if (iter<nIterations-1) for (Int_t isector=0; isector<nROCs*2; isector++){ //set all ellemts of crosstalk matrix to 0
1526 TMatrixD * crossTalkMatrix = (TMatrixD*)fCrossTalkSignalArray->At(isector);
1527 TMatrixD * crossTalkMatrixCache = (TMatrixD*)fCrossTalkSignalArray->At(isector+nROCs*2);
1528 if (crossTalkMatrix){
1529 (*crossTalkMatrixCache)*=0;
1530 (*crossTalkMatrixCache)+=(*crossTalkMatrix);
1531 (*crossTalkMatrix)*=0;
1542 void AliTPCtracker::FilterOutlierClusters(){
1544 // filter outlier clusters
1547 1.)..... booking part
1549 nTimeBins=fParam->Get....
1550 TH2F hisTime("","", sector,0,sector, nTimeBins,0,nTimeBins);
1551 TH2F hisPadRow("","", sector,0,sector, nPadRows,0,nPadRows);
1552 2.) .... filling part
1553 .... cluster loop { hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin()); }
1555 3.) ...filtering part
1556 sector loop { calculate median,mean80 and rms80 of the nclusters per time bin; calculate median,mean80 and rms80 of the nclusters per par row; .... export values to the debug streamers - to decide which threshold to be used... }
1559 { disable clusters in time bins > mean+ n rms80+ offsetTime disable clusters in padRow > mean+ n rms80+ offsetPadRow // how to dislable clusters? - new bit to introduce }
1561 4. Disabling clusters
1568 // AliTPCcalibDB *db=AliTPCcalibDB::Instance();
1569 Int_t nSectors=AliTPCROC::Instance()->GetNSectors();
1570 Int_t nTimeBins= 1100; // *Bug here - we should get NTimeBins from ALTRO - Parameters not relyable
1571 Int_t nPadRows=(AliTPCROC::Instance()->GetNRows(0) + AliTPCROC::Instance()->GetNRows(36));
1572 // parameters for filtering
1573 const Double_t nSigmaCut=9.; // should be in recoParam ?
1574 const Double_t offsetTime=100; // should be in RecoParam ? -
1575 const Double_t offsetPadRow=300; // should be in RecoParam ?
1576 const Double_t offsetTimeAccept=8; // should be in RecoParam ? - obtained as mean +1 rms in high IR pp
1577 TH2F hisTime("hisSectorTime","hisSectorTime", nSectors,0,nSectors, nTimeBins,0,nTimeBins);
1578 TH2F hisPadRow("hisSectorRow","hisSectorRow", nSectors,0,nSectors, nPadRows,0,nPadRows);
1580 // 2.) Filling part -- loop over clusters
1582 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1583 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1584 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1585 Int_t nrows = sector.GetNRows();
1586 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1587 AliTPCtrackerRow& tpcrow = sector[row];
1588 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1589 if (iside>0) ncl=tpcrow.GetN2();
1590 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1591 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1592 hisTime.Fill(cluster->GetDetector(),cluster->GetTimeBin());
1593 hisPadRow.Fill(cluster->GetDetector(),cluster->GetRow());
1600 // 3. Filtering part
1602 TVectorD vecTime(nTimeBins);
1603 TVectorD vecPadRow(nPadRows);
1604 TVectorD vecMedianSectorTime(nSectors);
1605 TVectorD vecRMSSectorTime(nSectors);
1606 TVectorD vecMedianSectorTimeOut6(nSectors);
1607 TVectorD vecMedianSectorTimeOut9(nSectors);//
1608 TVectorD vecMedianSectorTimeOut(nSectors);//
1609 TVectorD vecMedianSectorPadRow(nSectors);
1610 TVectorD vecRMSSectorPadRow(nSectors);
1611 TVectorD vecMedianSectorPadRowOut6(nSectors);
1612 TVectorD vecMedianSectorPadRowOut9(nSectors);
1613 TVectorD vecMedianSectorPadRowOut(nSectors);
1614 TVectorD vecSectorOut6(nSectors);
1615 TVectorD vecSectorOut9(nSectors);
1616 TMatrixD matSectorCluster(nSectors,2);
1618 // 3.a) median, rms calculations for hisTime
1620 for (Int_t isec=0; isec<nSectors; isec++){
1621 vecMedianSectorTimeOut6[isec]=0;
1622 vecMedianSectorTimeOut9[isec]=0;
1623 for (Int_t itime=0; itime<nTimeBins; itime++){
1624 vecTime[itime]=hisTime.GetBinContent(isec+1, itime+1);
1626 Double_t median= TMath::Mean(nTimeBins,vecTime.GetMatrixArray());
1627 Double_t rms= TMath::RMS(nTimeBins,vecTime.GetMatrixArray());
1628 vecMedianSectorTime[isec]=median;
1629 vecRMSSectorTime[isec]=rms;
1630 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector TimeStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
1633 for (Int_t itime=0; itime<nTimeBins; itime++){
1634 Double_t entries= hisTime.GetBinContent(isec+1, itime+1);
1635 if (entries>median+6.*rms+offsetTime) {
1636 vecMedianSectorTimeOut6[isec]+=1;
1638 if (entries>median+9.*rms+offsetTime) {
1639 vecMedianSectorTimeOut9[isec]+=1;
1644 // 3.b) median, rms calculations for hisPadRow
1646 for (Int_t isec=0; isec<nSectors; isec++){
1647 vecMedianSectorPadRowOut6[isec]=0;
1648 vecMedianSectorPadRowOut9[isec]=0;
1649 for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
1650 vecPadRow[ipadrow]=hisPadRow.GetBinContent(isec+1, ipadrow+1);
1652 Int_t nPadRowsSector= AliTPCROC::Instance()->GetNRows(isec);
1653 Double_t median= TMath::Mean(nPadRowsSector,vecPadRow.GetMatrixArray());
1654 Double_t rms= TMath::RMS(nPadRowsSector,vecPadRow.GetMatrixArray());
1655 vecMedianSectorPadRow[isec]=median;
1656 vecRMSSectorPadRow[isec]=rms;
1657 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector PadRowStat: %d\t%8.0f\t%8.0f",isec,median,rms).Data());
1660 for (Int_t ipadrow=0; ipadrow<nPadRows; ipadrow++){
1661 Double_t entries= hisPadRow.GetBinContent(isec+1, ipadrow+1);
1662 if (entries>median+6.*rms+offsetPadRow) {
1663 vecMedianSectorPadRowOut6[isec]+=1;
1665 if (entries>median+9.*rms+offsetPadRow) {
1666 vecMedianSectorPadRowOut9[isec]+=1;
1671 // 3.c) filter outlier sectors
1673 Double_t medianSectorTime = TMath::Median(nSectors, vecTime.GetMatrixArray());
1674 Double_t mean69SectorTime, rms69SectorTime=0;
1675 AliMathBase::EvaluateUni(nSectors, vecTime.GetMatrixArray(), mean69SectorTime,rms69SectorTime,69);
1676 for (Int_t isec=0; isec<nSectors; isec++){
1677 vecSectorOut6[isec]=0;
1678 vecSectorOut9[isec]=0;
1679 matSectorCluster(isec,0)=0;
1680 matSectorCluster(isec,1)=0;
1681 if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+6.*(rms69SectorTime+ offsetTimeAccept))) {
1682 vecSectorOut6[isec]=1;
1684 if (TMath::Abs(vecMedianSectorTime[isec])>(mean69SectorTime+9.*(rms69SectorTime+ offsetTimeAccept))){
1685 vecSectorOut9[isec]=1;
1688 // light version of export variable
1689 Int_t filteredSector= vecSectorOut9.Sum(); // light version of export variable
1690 Int_t filteredSectorTime= vecMedianSectorTimeOut9.Sum();
1691 Int_t filteredSectorPadRow= vecMedianSectorPadRowOut9.Sum();
1692 if (fEvent) if (fEvent->GetHeader()){
1693 fEvent->GetHeader()->SetTPCNoiseFilterCounter(0,TMath::Min(filteredSector,255));
1694 fEvent->GetHeader()->SetTPCNoiseFilterCounter(1,TMath::Min(filteredSectorTime,255));
1695 fEvent->GetHeader()->SetTPCNoiseFilterCounter(2,TMath::Min(filteredSectorPadRow,255));
1699 // 4. Disabling clusters in outlier layers
1703 for (Int_t isector=0; isector<36; isector++){ // loop over sectors
1704 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1705 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1706 Int_t nrows = sector.GetNRows();
1707 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1708 AliTPCtrackerRow& tpcrow = sector[row];
1709 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1710 if (iside>0) ncl=tpcrow.GetN2();
1711 for (Int_t i=0;i<ncl;i++) { // loop over clusters
1712 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1713 Double_t medianTime=vecMedianSectorTime[cluster->GetDetector()];
1714 Double_t medianPadRow=vecMedianSectorPadRow[cluster->GetDetector()];
1715 Double_t rmsTime=vecRMSSectorTime[cluster->GetDetector()];
1716 Double_t rmsPadRow=vecRMSSectorPadRow[cluster->GetDetector()];
1717 Int_t entriesPadRow=hisPadRow.GetBinContent(cluster->GetDetector()+1, cluster->GetRow()+1);
1718 Int_t entriesTime=hisTime.GetBinContent(cluster->GetDetector()+1, cluster->GetTimeBin()+1);
1719 Bool_t isOut=kFALSE;
1720 if (vecSectorOut9[cluster->GetDetector()]>0.5) {
1724 if (entriesTime>medianTime+nSigmaCut*rmsTime+offsetTime) {
1726 vecMedianSectorTimeOut[cluster->GetDetector()]++;
1728 if (entriesPadRow>medianPadRow+nSigmaCut*rmsPadRow+offsetPadRow) {
1730 vecMedianSectorPadRowOut[cluster->GetDetector()]++;
1733 matSectorCluster(cluster->GetDetector(),0)+=1;
1737 matSectorCluster(cluster->GetDetector(),1)+=1;
1743 for (Int_t isec=0; isec<nSectors; isec++){
1744 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) AliInfo(TString::Format("Sector Stat: %d\t%8.0f\t%8.0f",isec,matSectorCluster(isec,1),matSectorCluster(isec,0)).Data());
1747 // dump info to streamer - for later tuning of cuts
1749 if ((AliTPCReconstructor::StreamLevel()&kStreamFilterClusterInfo)>0) { // stream TPC data ouliers filtering infomation
1751 AliInfo(TString::Format("Cluster counter: (%d/%d) (Filtered/All)",counterOut,counterAll).Data());
1752 for (Int_t iSec=0; iSec<nSectors; iSec++){
1753 if (vecSectorOut9[iSec]>0 || matSectorCluster(iSec,1)>0) {
1754 AliInfo(TString::Format("Filtered sector\t%d",iSec).Data());
1755 Double_t vecMedTime =TMath::Median(72,vecMedianSectorTime.GetMatrixArray());
1756 Double_t vecMedPadRow =TMath::Median(72,vecMedianSectorPadRow.GetMatrixArray());
1757 Double_t vecMedCluster=(counterAll-counterOut)/72;
1758 AliInfo(TString::Format("VecMedianSectorTime\t(%4.4f/%4.4f/%4.4f)", vecMedianSectorTimeOut[iSec],vecMedianSectorTime[iSec],vecMedTime).Data());
1759 AliInfo(TString::Format("VecMedianSectorPadRow\t(%4.4f/%4.4f/%4.4f)", vecMedianSectorPadRowOut[iSec],vecMedianSectorPadRow[iSec],vecMedPadRow).Data());
1760 AliInfo(TString::Format("MatSectorCluster\t(%4.4f/%4.4f/%4.4f)\n", matSectorCluster(iSec,1), matSectorCluster(iSec,0), vecMedCluster).Data());
1765 Int_t eventNr = fEvent->GetEventNumberInFile();
1766 (*fDebugStreamer)<<"filterClusterInfo"<<
1767 // minimal set variables for the ESDevent
1768 "eventNr="<<eventNr<<
1769 "counterAll="<<counterAll<<
1770 "counterOut="<<counterOut<<
1771 "matSectotCluster.="<<&matSectorCluster<< //
1773 "filteredSector="<<filteredSector<< // counter filtered sectors
1774 "filteredSectorTime="<<filteredSectorTime<< // counter filtered time bins
1775 "filteredSectorPadRow="<<filteredSectorPadRow<< // counter filtered pad-rows
1776 // per sector outlier information
1777 "medianSectorTime="<<medianSectorTime<< // median number of clusters per sector/timebin
1778 "mean69SectorTime="<<mean69SectorTime<< // LTM statistic mean of clusters per sector/timebin
1779 "rms69SectorTime="<<rms69SectorTime<< // LTM statistic RMS of clusters per sector/timebin
1780 "vecSectorOut6.="<<&vecSectorOut6<< // flag array sector - 6 sigma +accept margin outlier
1781 "vecSectorOut9.="<<&vecSectorOut9<< // flag array sector - 9 sigma + accept margin outlier
1782 // per sector/timebin outlier detection
1783 "vecMedianSectorTime.="<<&vecMedianSectorTime<<
1784 "vecRMSSectorTime.="<<&vecRMSSectorTime<<
1785 "vecMedianSectorTimeOut6.="<<&vecMedianSectorTimeOut6<<
1786 "vecMedianSectorTimeOut9.="<<&vecMedianSectorTimeOut9<<
1787 "vecMedianSectorTimeOut0.="<<&vecMedianSectorTimeOut<<
1788 // per sector/pad-row outlier detection
1789 "vecMedianSectorPadRow.="<<&vecMedianSectorPadRow<<
1790 "vecRMSSectorPadRow.="<<&vecRMSSectorPadRow<<
1791 "vecMedianSectorPadRowOut6.="<<&vecMedianSectorPadRowOut6<<
1792 "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut9<<
1793 "vecMedianSectorPadRowOut9.="<<&vecMedianSectorPadRowOut<<
1795 ((*fDebugStreamer)<<"filterClusterInfo").GetTree()->Write();
1796 fDebugStreamer->GetFile()->Flush();
1800 void AliTPCtracker::UnloadClusters()
1803 // unload clusters from the memory
1805 Int_t nrows = fOuterSec->GetNRows();
1806 for (Int_t sec = 0;sec<fkNOS;sec++)
1807 for (Int_t row = 0;row<nrows;row++){
1808 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1810 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1811 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1813 tpcrow->ResetClusters();
1816 nrows = fInnerSec->GetNRows();
1817 for (Int_t sec = 0;sec<fkNIS;sec++)
1818 for (Int_t row = 0;row<nrows;row++){
1819 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1821 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1822 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1824 tpcrow->ResetClusters();
1830 void AliTPCtracker::FillClusterArray(TObjArray* array) const{
1832 // Filling cluster to the array - For visualization purposes
1835 nrows = fOuterSec->GetNRows();
1836 for (Int_t sec = 0;sec<fkNOS;sec++)
1837 for (Int_t row = 0;row<nrows;row++){
1838 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1839 if (!tpcrow) continue;
1840 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1841 array->AddLast((TObject*)((*tpcrow)[icl]));
1844 nrows = fInnerSec->GetNRows();
1845 for (Int_t sec = 0;sec<fkNIS;sec++)
1846 for (Int_t row = 0;row<nrows;row++){
1847 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1848 if (!tpcrow) continue;
1849 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1850 array->AddLast((TObject*)(*tpcrow)[icl]);
1856 void AliTPCtracker::Transform(AliTPCclusterMI * cluster){
1860 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1861 AliTPCTransform *transform = calibDB->GetTransform() ;
1863 AliFatal("Tranformations not in calibDB");
1866 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1867 Double_t x[3]={static_cast<Double_t>(cluster->GetRow()),static_cast<Double_t>(cluster->GetPad()),static_cast<Double_t>(cluster->GetTimeBin())};
1868 Int_t i[1]={cluster->GetDetector()};
1869 transform->Transform(x,i,0,1);
1870 // if (cluster->GetDetector()%36>17){
1875 // in debug mode check the transformation
1877 if ((AliTPCReconstructor::StreamLevel()&kStreamTransform)>0) {
1879 cluster->GetGlobalXYZ(gx);
1880 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1881 TTreeSRedirector &cstream = *fDebugStreamer;
1882 cstream<<"Transform"<< // needed for debugging of the cluster transformation, resp. used for later visualization
1893 cluster->SetX(x[0]);
1894 cluster->SetY(x[1]);
1895 cluster->SetZ(x[2]);
1900 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1901 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1902 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1904 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1905 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1906 if (mat) mat->LocalToMaster(pos,posC);
1908 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1910 cluster->SetX(posC[0]);
1911 cluster->SetY(posC[1]);
1912 cluster->SetZ(posC[2]);
1916 void AliTPCtracker::ApplyXtalkCorrection(){
1918 // ApplyXtalk correction
1919 // Loop over all clusters
1920 // add to each cluster signal corresponding to common Xtalk mode for given time bin at given wire segment
1922 for (Int_t isector=0; isector<36; isector++){ //loop tracking sectors
1923 for (Int_t iside=0; iside<2; iside++){ // loop over sides A/C
1924 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1925 Int_t nrows = sector.GetNRows();
1926 for (Int_t row = 0;row<nrows;row++){ // loop over rows
1927 AliTPCtrackerRow& tpcrow = sector[row]; // row object
1928 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
1929 if (iside>0) ncl=tpcrow.GetN2();
1930 Int_t xSector=0; // sector number in the TPC convention 0-72
1931 if (isector<18){ //if IROC
1932 xSector=isector+(iside>0)*18;
1934 xSector=isector+18; // isector -18 +36
1935 if (iside>0) xSector+=18;
1937 TMatrixD &crossTalkMatrix= *((TMatrixD*)fCrossTalkSignalArray->At(xSector));
1938 Int_t wireSegmentID = fkParam->GetWireSegment(xSector,row);
1939 for (Int_t i=0;i<ncl;i++) {
1940 AliTPCclusterMI *cluster= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
1941 Int_t iTimeBin=TMath::Nint(cluster->GetTimeBin());
1942 Double_t xTalk= crossTalkMatrix[wireSegmentID][iTimeBin];
1943 cluster->SetMax(cluster->GetMax()+xTalk);
1944 const Double_t kDummy=4;
1945 Double_t sumxTalk=xTalk*kDummy; // should be calculated via time response function
1946 cluster->SetQ(cluster->GetQ()+sumxTalk);
1949 if ((AliTPCReconstructor::StreamLevel()&kStreamXtalk)>0) { // flag: stream crosstalk correctio as applied to cluster
1950 TTreeSRedirector &cstream = *fDebugStreamer;
1951 if (gRandom->Rndm() > 0.){
1953 "isector=" << isector << // sector [0,36]
1954 "iside=" << iside << // side A or C
1955 "row=" << row << // padrow
1956 "i=" << i << // index of the cluster
1957 "xSector=" << xSector << // sector [0,72]
1958 "wireSegmentID=" << wireSegmentID << // anode wire segment id [0,10]
1959 "iTimeBin=" << iTimeBin << // timebin of the corrected cluster
1960 "xTalk=" << xTalk << // Xtalk contribution added to Qmax
1961 "sumxTalk=" << sumxTalk << // Xtalk contribution added to Qtot (roughly 3*Xtalk)
1962 "cluster.=" << cluster << // corrected cluster object
1965 }// dump the results to the debug streamer if in debug mode
1977 void AliTPCtracker::ApplyTailCancellation(){
1979 // Correct the cluster charge for the ion tail effect
1980 // The TimeResponse function accessed via AliTPCcalibDB (TPC/Calib/IonTail)
1984 TObjArray *ionTailArr = (TObjArray*)AliTPCcalibDB::Instance()->GetIonTailArray();
1985 if (!ionTailArr) {AliFatal("TPC - Missing IonTail OCDB object");}
1986 TObject *rocFactorIROC = ionTailArr->FindObject("factorIROC");
1987 TObject *rocFactorOROC = ionTailArr->FindObject("factorOROC");
1988 Float_t factorIROC = (atof(rocFactorIROC->GetTitle()));
1989 Float_t factorOROC = (atof(rocFactorOROC->GetTitle()));
1991 // find the number of clusters for the whole TPC (nclALL)
1993 for (Int_t isector=0; isector<36; isector++){
1994 AliTPCtrackerSector §or= (isector<18)?fInnerSec[isector%18]:fOuterSec[isector%18];
1995 nclALL += sector.GetNClInSector(0);
1996 nclALL += sector.GetNClInSector(1);
1999 // start looping over all clusters
2000 for (Int_t iside=0; iside<2; iside++){ // loop over sides
2003 for (Int_t secType=0; secType<2; secType++){ //loop over inner or outer sector
2004 // cache experimantal tuning factor for the different chamber type
2005 const Float_t ampfactor = (secType==0)?factorIROC:factorOROC;
2006 std::cout << " ampfactor = " << ampfactor << std::endl;
2008 for (Int_t sec = 0;sec<fkNOS;sec++){ //loop overs sectors
2011 // Cache time response functions and their positons to COG of the cluster
2012 TGraphErrors ** graphRes = new TGraphErrors *[20];
2013 Float_t * indexAmpGraphs = new Float_t[20];
2014 for (Int_t icache=0; icache<20; icache++)
2016 graphRes[icache] = NULL;
2017 indexAmpGraphs[icache] = 0;
2019 ///////////////////////////// --> position fo sie loop
2020 if (!AliTPCcalibDB::Instance()->GetTailcancelationGraphs(sec+36*secType+18*iside,graphRes,indexAmpGraphs))
2025 AliTPCtrackerSector §or= (secType==0)?fInnerSec[sec]:fOuterSec[sec];
2026 Int_t nrows = sector.GetNRows(); // number of rows
2027 Int_t nclSector = sector.GetNClInSector(iside); // ncl per sector to be used for debugging
2029 for (Int_t row = 0;row<nrows;row++){ // loop over rows
2031 AliTPCtrackerRow& tpcrow = sector[row]; // row object
2032 Int_t ncl = tpcrow.GetN1(); // number of clusters in the row
2033 if (iside>0) ncl=tpcrow.GetN2();
2035 // Order clusters in time for the proper correction of ion tail
2036 Float_t qTotArray[ncl]; // arrays to be filled with modified Qtot and Qmax values in order to avoid float->int conversion
2037 Float_t qMaxArray[ncl];
2038 Int_t sortedClusterIndex[ncl];
2039 Float_t sortedClusterTimeBin[ncl];
2040 TObjArray *rowClusterArray = new TObjArray(ncl); // cache clusters for each row
2041 for (Int_t i=0;i<ncl;i++)
2045 sortedClusterIndex[i]=i;
2046 AliTPCclusterMI *rowcl= (iside>0)?(tpcrow.GetCluster2(i)):(tpcrow.GetCluster1(i));
2048 rowClusterArray->AddAt(rowcl,i);
2050 rowClusterArray->RemoveAt(i);
2052 // Fill the timebin info to the array in order to sort wrt tb
2054 sortedClusterTimeBin[i]=0.0;
2056 sortedClusterTimeBin[i] = rowcl->GetTimeBin();
2060 TMath::Sort(ncl,sortedClusterTimeBin,sortedClusterIndex,kFALSE); // sort clusters in time
2062 // Main cluster correction loops over clusters
2063 for (Int_t icl0=0; icl0<ncl;icl0++){ // first loop over clusters
2065 AliTPCclusterMI *cl0= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl0]));
2069 for (Int_t icl1=0; icl1<ncl;icl1++){ // second loop over clusters
2070 AliTPCclusterMI *cl1= static_cast<AliTPCclusterMI*>(rowClusterArray->At(sortedClusterIndex[icl1]));
2072 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())>4) continue; // no contribution if far away in pad direction
2073 if (cl0->GetTimeBin()<= cl1->GetTimeBin()) continue; // no contibution to the tail if later
2074 if (TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin())>600) continue; // out of the range of response function
2076 if (TMath::Abs(cl0->GetPad()-cl1->GetPad())<4) nclPad++; // count ncl for every pad for debugging
2078 // Get the correction values for Qmax and Qtot and find total correction for a given cluster
2079 Double_t ionTailMax=0.;
2080 Double_t ionTailTotal=0.;
2081 GetTailValue(ampfactor,ionTailMax,ionTailTotal,graphRes,indexAmpGraphs,cl0,cl1);
2082 ionTailMax=TMath::Abs(ionTailMax);
2083 ionTailTotal=TMath::Abs(ionTailTotal);
2084 qTotArray[icl0]+=ionTailTotal;
2085 qMaxArray[icl0]+=ionTailMax;
2087 // Dump some info for debugging while clusters are being corrected
2088 if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) { // flag: stream ion tail correction as applied to cluster
2089 TTreeSRedirector &cstream = *fDebugStreamer;
2090 if (gRandom->Rndm() > 0.999){
2091 cstream<<"IonTail"<<
2092 "cl0.=" <<cl0 << // cluster 0 (to be corrected)
2093 "cl1.=" <<cl1 << // cluster 1 (previous cluster)
2094 "ionTailTotal=" <<ionTailTotal << // ion Tail from cluster 1 contribution to cluster0
2095 "ionTailMax=" <<ionTailMax << // ion Tail from cluster 1 contribution to cluster0
2098 }// dump the results to the debug streamer if in debug mode
2100 }//end of second loop over clusters
2102 // Set corrected values of the corrected cluster
2103 cl0->SetQ(TMath::Nint(Float_t(cl0->GetQ())+Float_t(qTotArray[icl0])));
2104 cl0->SetMax(TMath::Nint(Float_t(cl0->GetMax())+qMaxArray[icl0]));
2106 // Dump some info for debugging after clusters are corrected
2107 if ((AliTPCReconstructor::StreamLevel()&kStreamIonTail)>0) {
2108 TTreeSRedirector &cstream = *fDebugStreamer;
2109 if (gRandom->Rndm() > 0.999){
2110 cstream<<"IonTailCorrected"<<
2111 "cl0.=" << cl0 << // cluster 0 with huge Qmax
2112 "ionTailTotalPerCluster=" << qTotArray[icl0] <<
2113 "ionTailMaxPerCluster=" << qMaxArray[icl0] <<
2114 "nclALL=" << nclALL <<
2115 "nclSector=" << nclSector <<
2117 "nclPad=" << nclPad <<
2123 }// dump the results to the debug streamer if in debug mode
2125 }//end of first loop over cluster
2126 delete rowClusterArray;
2127 }//end of loop over rows
2128 for (int i=0; i<20; i++) delete graphRes[i];
2130 delete [] indexAmpGraphs;
2132 }//end of loop over sectors
2133 }//end of loop over IROC/OROC
2134 }// end of side loop
2136 //_____________________________________________________________________________
2137 void AliTPCtracker::GetTailValue(Float_t ampfactor,Double_t &ionTailMax, Double_t &ionTailTotal,TGraphErrors **graphRes,Float_t *indexAmpGraphs,AliTPCclusterMI *cl0,AliTPCclusterMI *cl1){
2140 // Function in order to calculate the amount of the correction to be added for a given cluster, return values are ionTailTaoltal and ionTailMax
2142 // cl0 - cluster to be modified
2143 // cl1 - source cluster ion tail of this cluster will be added to the cl0 (accroding time and pad response function)
2145 const Double_t kMinPRF = 0.5; // minimal PRF width
2146 ionTailTotal = 0.; // correction value to be added to Qtot of cl0
2147 ionTailMax = 0.; // correction value to be added to Qmax of cl0
2149 Float_t qTot0 = cl0->GetQ(); // cl0 Qtot info
2150 Float_t qTot1 = cl1->GetQ(); // cl1 Qtot info
2151 Int_t sectorPad = cl1->GetDetector(); // sector number
2152 Int_t padcl0 = TMath::Nint(cl0->GetPad()); // pad0
2153 Int_t padcl1 = TMath::Nint(cl1->GetPad()); // pad1
2154 Float_t padWidth = (sectorPad < 36)?0.4:0.6; // pad width in cm
2155 const Int_t deltaTimebin = TMath::Nint(TMath::Abs(cl1->GetTimeBin()-cl0->GetTimeBin()))+12; //distance between pads of cl1 and cl0 increased by 12 bins
2156 Double_t rmsPad1 = (cl1->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl1->GetSigmaY2())/padWidth);
2157 Double_t rmsPad0 = (cl0->GetSigmaY2()==0)?kMinPRF:(TMath::Sqrt(cl0->GetSigmaY2())/padWidth);
2161 Double_t sumAmp1=0.;
2162 for (Int_t idelta =-2; idelta<=2;idelta++){
2163 sumAmp1+=TMath::Exp(-idelta*idelta/(2*rmsPad1));
2166 Double_t sumAmp0=0.;
2167 for (Int_t idelta =-2; idelta<=2;idelta++){
2168 sumAmp0+=TMath::Exp(-idelta*idelta/(2*rmsPad0));
2171 // Apply the correction --> cl1 corrects cl0 (loop over cl1's pads and find which pads of cl0 are going to be corrected)
2172 Int_t padScan=2; // +-2 pad-timebin window will be scanned
2173 for (Int_t ipad1=padcl1-padScan; ipad1<=padcl1+padScan; ipad1++) {
2176 Float_t deltaPad1 = TMath::Abs(cl1->GetPad()-(Float_t)ipad1);
2177 Double_t amp1 = (TMath::Exp(-(deltaPad1*deltaPad1)/(2*rmsPad1)))/sumAmp1; // normalized pad response function
2178 Float_t qTotPad1 = amp1*qTot1; // used as a factor to multipliy the response function
2180 // find closest value of cl1 to COG (among the time response functions' amplitude array --> to select proper t.r.f.)
2182 Float_t diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[0]);
2183 for (Int_t j=0;j<20;j++) {
2184 if (diffAmp > TMath::Abs(deltaPad1-indexAmpGraphs[j]) && indexAmpGraphs[j]!=0)
2186 diffAmp = TMath::Abs(deltaPad1-indexAmpGraphs[j]);
2190 if (!graphRes[ampIndex]) continue;
2191 if (deltaTimebin+2 >= graphRes[ampIndex]->GetN()) continue;
2192 if (graphRes[ampIndex]->GetY()[deltaTimebin+2]>=0) continue;
2194 for (Int_t ipad0=padcl0-padScan; ipad0<=padcl0+padScan; ipad0++) {
2197 if (ipad1!=ipad0) continue; // check if ipad1 channel sees ipad0 channel, if not no correction to be applied.
2199 Float_t deltaPad0 = TMath::Abs(cl0->GetPad()-(Float_t)ipad0);
2200 Double_t amp0 = (TMath::Exp(-(deltaPad0*deltaPad0)/(2*rmsPad0)))/sumAmp0; // normalized pad resp function
2201 Float_t qMaxPad0 = amp0*qTot0;
2203 // Add 5 timebin range contribution around the max peak (-+2 tb window)
2204 for (Int_t itb=deltaTimebin-2; itb<=deltaTimebin+2; itb++) {
2206 if (itb<0) continue;
2207 if (itb>=graphRes[ampIndex]->GetN()) continue;
2209 // calculate contribution to qTot
2210 Float_t tailCorr = TMath::Abs((qTotPad1*ampfactor)*(graphRes[ampIndex])->GetY()[itb]);
2211 if (ipad1!=padcl0) {
2212 ionTailTotal += TMath::Min(qMaxPad0,tailCorr); // for side pad
2214 ionTailTotal += tailCorr; // for center pad
2216 // calculate contribution to qMax
2217 if (itb == deltaTimebin && ipad1 == padcl0) ionTailMax += tailCorr;
2219 } // end of tb correction loop which is applied over 5 tb range
2221 } // end of cl0 loop
2222 } // end of cl1 loop
2226 //_____________________________________________________________________________
2227 Int_t AliTPCtracker::LoadOuterSectors() {
2228 //-----------------------------------------------------------------
2229 // This function fills outer TPC sectors with clusters.
2230 //-----------------------------------------------------------------
2231 Int_t nrows = fOuterSec->GetNRows();
2233 for (Int_t sec = 0;sec<fkNOS;sec++)
2234 for (Int_t row = 0;row<nrows;row++){
2235 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
2236 Int_t sec2 = sec+2*fkNIS;
2238 Int_t ncl = tpcrow->GetN1();
2240 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
2241 index=(((sec2<<8)+row)<<16)+ncl;
2242 tpcrow->InsertCluster(c,index);
2245 ncl = tpcrow->GetN2();
2247 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
2248 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
2249 tpcrow->InsertCluster(c,index);
2252 // write indexes for fast acces
2254 for (Int_t i=0;i<510;i++)
2255 tpcrow->SetFastCluster(i,-1);
2256 for (Int_t i=0;i<tpcrow->GetN();i++){
2257 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
2258 tpcrow->SetFastCluster(zi,i); // write index
2261 for (Int_t i=0;i<510;i++){
2262 if (tpcrow->GetFastCluster(i)<0)
2263 tpcrow->SetFastCluster(i,last);
2265 last = tpcrow->GetFastCluster(i);
2274 //_____________________________________________________________________________
2275 Int_t AliTPCtracker::LoadInnerSectors() {
2276 //-----------------------------------------------------------------
2277 // This function fills inner TPC sectors with clusters.
2278 //-----------------------------------------------------------------
2279 Int_t nrows = fInnerSec->GetNRows();
2281 for (Int_t sec = 0;sec<fkNIS;sec++)
2282 for (Int_t row = 0;row<nrows;row++){
2283 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
2286 Int_t ncl = tpcrow->GetN1();
2288 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
2289 index=(((sec<<8)+row)<<16)+ncl;
2290 tpcrow->InsertCluster(c,index);
2293 ncl = tpcrow->GetN2();
2295 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
2296 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
2297 tpcrow->InsertCluster(c,index);
2300 // write indexes for fast acces
2302 for (Int_t i=0;i<510;i++)
2303 tpcrow->SetFastCluster(i,-1);
2304 for (Int_t i=0;i<tpcrow->GetN();i++){
2305 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
2306 tpcrow->SetFastCluster(zi,i); // write index
2309 for (Int_t i=0;i<510;i++){
2310 if (tpcrow->GetFastCluster(i)<0)
2311 tpcrow->SetFastCluster(i,last);
2313 last = tpcrow->GetFastCluster(i);
2325 //_________________________________________________________________________
2326 AliTPCclusterMI *AliTPCtracker::GetClusterMI(Int_t index) const {
2327 //--------------------------------------------------------------------
2328 // Return pointer to a given cluster
2329 //--------------------------------------------------------------------
2330 if (index<0) return 0; // no cluster
2331 Int_t sec=(index&0xff000000)>>24;
2332 Int_t row=(index&0x00ff0000)>>16;
2333 Int_t ncl=(index&0x00007fff)>>00;
2335 const AliTPCtrackerRow * tpcrow=0;
2336 TClonesArray * clrow =0;
2338 if (sec<0 || sec>=fkNIS*4) {
2339 AliWarning(Form("Wrong sector %d",sec));
2344 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
2345 if (tracksec.GetNRows()<=row) return 0;
2346 tpcrow = &(tracksec[row]);
2347 if (tpcrow==0) return 0;
2350 if (tpcrow->GetN1()<=ncl) return 0;
2351 clrow = tpcrow->GetClusters1();
2354 if (tpcrow->GetN2()<=ncl) return 0;
2355 clrow = tpcrow->GetClusters2();
2359 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
2360 if (tracksec.GetNRows()<=row) return 0;
2361 tpcrow = &(tracksec[row]);
2362 if (tpcrow==0) return 0;
2364 if (sec-2*fkNIS<fkNOS) {
2365 if (tpcrow->GetN1()<=ncl) return 0;
2366 clrow = tpcrow->GetClusters1();
2369 if (tpcrow->GetN2()<=ncl) return 0;
2370 clrow = tpcrow->GetClusters2();
2374 return (AliTPCclusterMI*)clrow->At(ncl);
2380 Int_t AliTPCtracker::FollowToNext(AliTPCseed& t, Int_t nr) {
2381 //-----------------------------------------------------------------
2382 // This function tries to find a track prolongation to next pad row
2383 //-----------------------------------------------------------------
2385 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
2388 AliTPCclusterMI *cl=0;
2389 Int_t tpcindex= t.GetClusterIndex2(nr);
2391 // update current shape info every 5 pad-row
2392 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
2396 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
2398 if (tpcindex==-1) return 0; //track in dead zone
2399 if (tpcindex >= 0){ //
2400 cl = t.GetClusterPointer(nr);
2401 //if (cl==0) cl = GetClusterMI(tpcindex);
2402 if (!cl) cl = GetClusterMI(tpcindex);
2403 t.SetCurrentClusterIndex1(tpcindex);
2406 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
2407 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
2409 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
2410 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
2412 if (TMath::Abs(angle-t.GetAlpha())>0.001){
2413 Double_t rotation = angle-t.GetAlpha();
2414 t.SetRelativeSector(relativesector);
2415 if (!t.Rotate(rotation)) {
2416 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
2420 if (!t.PropagateTo(x)) {
2421 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
2425 t.SetCurrentCluster(cl);
2427 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2428 if ((tpcindex&0x8000)==0) accept =0;
2430 //if founded cluster is acceptible
2431 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
2432 t.SetErrorY2(t.GetErrorY2()+0.03);
2433 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2434 t.SetErrorY2(t.GetErrorY2()*3);
2435 t.SetErrorZ2(t.GetErrorZ2()*3);
2437 t.SetNFoundable(t.GetNFoundable()+1);
2438 UpdateTrack(&t,accept);
2441 else { // Remove old cluster from track
2442 t.SetClusterIndex(nr, -3);
2443 t.SetClusterPointer(nr, 0);
2447 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
2448 if (fIteration>1 && IsFindable(t)){
2449 // not look for new cluster during refitting
2450 t.SetNFoundable(t.GetNFoundable()+1);
2455 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
2456 if (!t.PropagateTo(x)) {
2457 if (fIteration==0) t.SetRemoval(10);
2460 Double_t y = t.GetY();
2461 if (TMath::Abs(y)>ymax){
2463 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2464 if (!t.Rotate(fSectors->GetAlpha()))
2466 } else if (y <-ymax) {
2467 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2468 if (!t.Rotate(-fSectors->GetAlpha()))
2471 if (!t.PropagateTo(x)) {
2472 if (fIteration==0) t.SetRemoval(10);
2478 Double_t z=t.GetZ();
2481 if (!IsActive(t.GetRelativeSector(),nr)) {
2483 t.SetClusterIndex2(nr,-1);
2486 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2487 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
2488 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
2490 if (!isActive || !isActive2) return 0;
2492 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2493 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
2495 Double_t roadz = 1.;
2497 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2499 t.SetClusterIndex2(nr,-1);
2505 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2506 t.SetNFoundable(t.GetNFoundable()+1);
2512 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
2513 cl = krow.FindNearest2(y,z,roady,roadz,index);
2514 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
2517 t.SetCurrentCluster(cl);
2519 if (fIteration==2&&cl->IsUsed(10)) return 0;
2520 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2521 if (fIteration==2&&cl->IsUsed(11)) {
2522 t.SetErrorY2(t.GetErrorY2()+0.03);
2523 t.SetErrorZ2(t.GetErrorZ2()+0.03);
2524 t.SetErrorY2(t.GetErrorY2()*3);
2525 t.SetErrorZ2(t.GetErrorZ2()*3);
2528 if (t.fCurrentCluster->IsUsed(10)){
2533 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
2539 if (accept<3) UpdateTrack(&t,accept);
2542 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
2550 //_________________________________________________________________________
2551 Bool_t AliTPCtracker::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
2553 // Get track space point by index
2554 // return false in case the cluster doesn't exist
2555 AliTPCclusterMI *cl = GetClusterMI(index);
2556 if (!cl) return kFALSE;
2557 Int_t sector = (index&0xff000000)>>24;
2558 // Int_t row = (index&0x00ff0000)>>16;
2560 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
2561 xyz[0] = cl->GetX();
2562 xyz[1] = cl->GetY();
2563 xyz[2] = cl->GetZ();
2565 fkParam->AdjustCosSin(sector,cos,sin);
2566 Float_t x = cos*xyz[0]-sin*xyz[1];
2567 Float_t y = cos*xyz[1]+sin*xyz[0];
2569 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
2570 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
2571 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
2572 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
2573 cov[0] = sin*sin*sigmaY2;
2574 cov[1] = -sin*cos*sigmaY2;
2576 cov[3] = cos*cos*sigmaY2;
2579 p.SetXYZ(x,y,xyz[2],cov);
2580 AliGeomManager::ELayerID iLayer;
2582 if (sector < fkParam->GetNInnerSector()) {
2583 iLayer = AliGeomManager::kTPC1;
2587 iLayer = AliGeomManager::kTPC2;
2588 idet = sector - fkParam->GetNInnerSector();
2590 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
2591 p.SetVolumeID(volid);
2597 Int_t AliTPCtracker::UpdateClusters(AliTPCseed& t, Int_t nr) {
2598 //-----------------------------------------------------------------
2599 // This function tries to find a track prolongation to next pad row
2600 //-----------------------------------------------------------------
2601 t.SetCurrentCluster(0);
2602 t.SetCurrentClusterIndex1(-3);
2604 Double_t xt=t.GetX();
2605 Int_t row = GetRowNumber(xt)-1;
2606 Double_t ymax= GetMaxY(nr);
2608 if (row < nr) return 1; // don't prolongate if not information until now -
2609 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
2611 // return 0; // not prolongate strongly inclined tracks
2613 // if (TMath::Abs(t.GetSnp())>0.95) {
2615 // return 0; // not prolongate strongly inclined tracks
2616 // }// patch 28 fev 06
2618 Double_t x= GetXrow(nr);
2620 //t.PropagateTo(x+0.02);
2621 //t.PropagateTo(x+0.01);
2622 if (!t.PropagateTo(x)){
2629 if (TMath::Abs(y)>ymax){
2631 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
2632 if (!t.Rotate(fSectors->GetAlpha()))
2634 } else if (y <-ymax) {
2635 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
2636 if (!t.Rotate(-fSectors->GetAlpha()))
2639 // if (!t.PropagateTo(x)){
2646 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
2648 if (!IsActive(t.GetRelativeSector(),nr)) {
2650 t.SetClusterIndex2(nr,-1);
2653 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
2655 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
2657 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
2659 t.SetClusterIndex2(nr,-1);
2665 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
2666 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
2672 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
2673 // t.fCurrentSigmaY = GetSigmaY(&t);
2674 //t.fCurrentSigmaZ = GetSigmaZ(&t);
2678 AliTPCclusterMI *cl=0;
2681 Double_t roady = 1.;
2682 Double_t roadz = 1.;
2686 index = t.GetClusterIndex2(nr);
2687 if ( (index >= 0) && (index&0x8000)==0){
2688 cl = t.GetClusterPointer(nr);
2689 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
2690 t.SetCurrentClusterIndex1(index);
2692 t.SetCurrentCluster(cl);
2698 // if (index<0) return 0;
2699 UInt_t uindex = TMath::Abs(index);
2702 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
2703 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
2706 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
2707 t.SetCurrentCluster(cl);
2713 Int_t AliTPCtracker::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
2714 //-----------------------------------------------------------------
2715 // This function tries to find a track prolongation to next pad row
2716 //-----------------------------------------------------------------
2718 //update error according neighborhoud
2720 if (t.GetCurrentCluster()) {
2722 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
2724 if (t.GetCurrentCluster()->IsUsed(10)){
2729 t.SetNShared(t.GetNShared()+1);
2730 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
2735 if (fIteration>0) accept = 0;
2736 if (accept<3) UpdateTrack(&t,accept);
2740 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
2741 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
2743 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
2751 //_____________________________________________________________________________
2752 Int_t AliTPCtracker::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
2753 //-----------------------------------------------------------------
2754 // This function tries to find a track prolongation.
2755 //-----------------------------------------------------------------
2756 Double_t xt=t.GetX();
2758 Double_t alpha=t.GetAlpha();
2759 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2760 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2762 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2764 Int_t first = GetRowNumber(xt);
2769 for (Int_t nr= first; nr>=rf; nr-=step) {
2771 if (t.GetKinkIndexes()[0]>0){
2772 for (Int_t i=0;i<3;i++){
2773 Int_t index = t.GetKinkIndexes()[i];
2774 if (index==0) break;
2775 if (index<0) continue;
2777 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2779 printf("PROBLEM\n");
2782 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2784 AliExternalTrackParam paramd(t);
2785 kink->SetDaughter(paramd);
2786 kink->SetStatus(2,5);
2793 if (nr==80) t.UpdateReference();
2794 if (nr<fInnerSec->GetNRows())
2795 fSectors = fInnerSec;
2797 fSectors = fOuterSec;
2798 if (FollowToNext(t,nr)==0)
2811 Int_t AliTPCtracker::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2812 //-----------------------------------------------------------------
2813 // This function tries to find a track prolongation.
2814 //-----------------------------------------------------------------
2816 Double_t xt=t.GetX();
2817 Double_t alpha=t.GetAlpha();
2818 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2819 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2820 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2822 Int_t first = t.GetFirstPoint();
2823 Int_t ri = GetRowNumber(xt);
2827 if (first<ri) first = ri;
2829 if (first<0) first=0;
2830 for (Int_t nr=first; nr<=rf; nr++) {
2831 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2832 if (t.GetKinkIndexes()[0]<0){
2833 for (Int_t i=0;i<3;i++){
2834 Int_t index = t.GetKinkIndexes()[i];
2835 if (index==0) break;
2836 if (index>0) continue;
2837 index = TMath::Abs(index);
2838 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2840 printf("PROBLEM\n");
2843 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2845 AliExternalTrackParam paramm(t);
2846 kink->SetMother(paramm);
2847 kink->SetStatus(2,1);
2854 if (nr<fInnerSec->GetNRows())
2855 fSectors = fInnerSec;
2857 fSectors = fOuterSec;
2868 Float_t AliTPCtracker::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2870 // overlapping factor
2876 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2879 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2881 Float_t distance = TMath::Sqrt(dz2+dy2);
2882 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2885 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2886 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2891 if (firstpoint>lastpoint) {
2892 firstpoint =lastpoint;
2897 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2898 if (s1->GetClusterIndex2(i)>0) sum1++;
2899 if (s2->GetClusterIndex2(i)>0) sum2++;
2900 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2904 if (sum<5) return 0;
2906 Float_t summin = TMath::Min(sum1+1,sum2+1);
2907 Float_t ratio = (sum+1)/Float_t(summin);
2911 void AliTPCtracker::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2915 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2916 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2917 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2918 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2923 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2924 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2925 Int_t firstpoint = 0;
2926 Int_t lastpoint = 160;
2928 // if (firstpoint>=lastpoint-5) return;;
2930 for (Int_t i=firstpoint;i<lastpoint;i++){
2931 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2932 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2936 if (sumshared>cutN0){
2939 for (Int_t i=firstpoint;i<lastpoint;i++){
2940 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2941 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2942 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2943 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2944 if (s1->IsActive()&&s2->IsActive()){
2945 p1->SetShared(kTRUE);
2946 p2->SetShared(kTRUE);
2952 if (sumshared>cutN0){
2953 for (Int_t i=0;i<4;i++){
2954 if (s1->GetOverlapLabel(3*i)==0){
2955 s1->SetOverlapLabel(3*i, s2->GetLabel());
2956 s1->SetOverlapLabel(3*i+1,sumshared);
2957 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2961 for (Int_t i=0;i<4;i++){
2962 if (s2->GetOverlapLabel(3*i)==0){
2963 s2->SetOverlapLabel(3*i, s1->GetLabel());
2964 s2->SetOverlapLabel(3*i+1,sumshared);
2965 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2972 void AliTPCtracker::SignShared(TObjArray * arr)
2975 //sort trackss according sectors
2977 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2978 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2980 //if (pt) RotateToLocal(pt);
2984 arr->Sort(); // sorting according relative sectors
2985 arr->Expand(arr->GetEntries());
2988 Int_t nseed=arr->GetEntriesFast();
2989 for (Int_t i=0; i<nseed; i++) {
2990 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2992 for (Int_t j=0;j<12;j++){
2993 pt->SetOverlapLabel(j,0);
2996 for (Int_t i=0; i<nseed; i++) {
2997 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2999 if (pt->GetRemoval()>10) continue;
3000 for (Int_t j=i+1; j<nseed; j++){
3001 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
3002 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
3004 if (pt2->GetRemoval()<=10) {
3005 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
3013 void AliTPCtracker::SortTracks(TObjArray * arr, Int_t mode) const
3016 //sort tracks in array according mode criteria
3017 Int_t nseed = arr->GetEntriesFast();
3018 for (Int_t i=0; i<nseed; i++) {
3019 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3030 void AliTPCtracker::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
3033 // Loop over all tracks and remove overlaped tracks (with lower quality)
3035 // 1. Unsign clusters
3036 // 2. Sort tracks according quality
3037 // Quality is defined by the number of cluster between first and last points
3039 // 3. Loop over tracks - decreasing quality order
3040 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
3041 // b.) remove - If the minimal number of clusters less than minimal and not ITS
3042 // c.) if track accepted - sign clusters
3044 //Called in - AliTPCtracker::Clusters2Tracks()
3045 // - AliTPCtracker::PropagateBack()
3046 // - AliTPCtracker::RefitInward()
3049 // factor1 - factor for constrained
3050 // factor2 - for non constrained tracks
3051 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
3055 Int_t nseed = arr->GetEntriesFast();
3056 Float_t * quality = new Float_t[nseed];
3057 Int_t * indexes = new Int_t[nseed];
3061 for (Int_t i=0; i<nseed; i++) {
3062 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3067 pt->UpdatePoints(); //select first last max dens points
3068 Float_t * points = pt->GetPoints();
3069 if (points[3]<0.8) quality[i] =-1;
3070 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
3071 //prefer high momenta tracks if overlaps
3072 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
3074 TMath::Sort(nseed,quality,indexes);
3077 for (Int_t itrack=0; itrack<nseed; itrack++) {
3078 Int_t trackindex = indexes[itrack];
3079 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
3082 if (quality[trackindex]<0){
3083 MarkSeedFree( arr->RemoveAt(trackindex) );
3088 Int_t first = Int_t(pt->GetPoints()[0]);
3089 Int_t last = Int_t(pt->GetPoints()[2]);
3090 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
3092 Int_t found,foundable,shared;
3093 pt->GetClusterStatistic(first,last, found, foundable,shared,kFALSE); // better to get statistic in "high-dens" region do't use full track as in line bellow
3094 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
3095 Bool_t itsgold =kFALSE;
3098 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
3102 if (Float_t(shared+1)/Float_t(found+1)>factor){
3103 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
3104 if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveUsed)>0){ // flag:stream information about TPC tracks which were descarded (double track removal)
3105 TTreeSRedirector &cstream = *fDebugStreamer;
3106 cstream<<"RemoveUsed"<<
3107 "iter="<<fIteration<<
3111 MarkSeedFree( arr->RemoveAt(trackindex) );
3114 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
3115 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
3116 if( (AliTPCReconstructor::StreamLevel()&kStreamRemoveShort)>0){ // flag:stream information about TPC tracks which were discarded (short track removal)
3117 TTreeSRedirector &cstream = *fDebugStreamer;
3118 cstream<<"RemoveShort"<<
3119 "iter="<<fIteration<<
3123 MarkSeedFree( arr->RemoveAt(trackindex) );
3129 //if (sharedfactor>0.4) continue;
3130 if (pt->GetKinkIndexes()[0]>0) continue;
3131 //Remove tracks with undefined properties - seems
3132 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
3134 for (Int_t i=first; i<last; i++) {
3135 Int_t index=pt->GetClusterIndex2(i);
3136 // if (index<0 || index&0x8000 ) continue;
3137 if (index<0 || index&0x8000 ) continue;
3138 AliTPCclusterMI *c= pt->GetClusterPointer(i);
3145 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
3151 void AliTPCtracker::DumpClusters(Int_t iter, TObjArray *trackArray)
3154 // Dump clusters after reco
3155 // signed and unsigned cluster can be visualized
3156 // 1. Unsign all cluster
3157 // 2. Sign all used clusters
3160 Int_t nseed = trackArray->GetEntries();
3161 for (Int_t i=0; i<nseed; i++){
3162 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
3166 Bool_t isKink=pt->GetKinkIndex(0)!=0;
3167 for (Int_t j=0; j<160; ++j) {
3168 Int_t index=pt->GetClusterIndex2(j);
3169 if (index<0) continue;
3170 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3172 if (isKink) c->Use(100); // kink
3173 c->Use(10); // by default usage 10
3177 Int_t eventNr = fEvent->GetEventNumberInFile();
3179 for (Int_t sec=0;sec<fkNIS;sec++){
3180 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
3181 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
3182 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
3183 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
3184 Float_t gx[3]; cl->GetGlobalXYZ(gx);
3185 (*fDebugStreamer)<<"clDump"<<
3186 "eventNr="<<eventNr<<
3194 cla = fInnerSec[sec][row].GetClusters2();
3195 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
3196 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
3197 Float_t gx[3]; cl->GetGlobalXYZ(gx);
3198 (*fDebugStreamer)<<"clDump"<<
3199 "eventNr="<<eventNr<<
3210 for (Int_t sec=0;sec<fkNOS;sec++){
3211 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
3212 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
3213 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
3215 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
3216 cl->GetGlobalXYZ(gx);
3217 (*fDebugStreamer)<<"clDump"<<
3218 "eventNr="<<eventNr<<
3226 cla = fOuterSec[sec][row].GetClusters2();
3227 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
3229 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
3230 cl->GetGlobalXYZ(gx);
3231 (*fDebugStreamer)<<"clDump"<<
3232 "eventNr="<<eventNr<<
3244 void AliTPCtracker::UnsignClusters()
3247 // loop over all clusters and unsign them
3250 for (Int_t sec=0;sec<fkNIS;sec++){
3251 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
3252 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
3253 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
3254 // if (cl[icl].IsUsed(10))
3255 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3256 cla = fInnerSec[sec][row].GetClusters2();
3257 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
3258 //if (cl[icl].IsUsed(10))
3259 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3263 for (Int_t sec=0;sec<fkNOS;sec++){
3264 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
3265 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
3266 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
3267 //if (cl[icl].IsUsed(10))
3268 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3269 cla = fOuterSec[sec][row].GetClusters2();
3270 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
3271 //if (cl[icl].IsUsed(10))
3272 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
3280 void AliTPCtracker::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
3283 //sign clusters to be "used"
3285 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
3286 // loop over "primaries"
3300 Int_t nseed = arr->GetEntriesFast();
3301 for (Int_t i=0; i<nseed; i++) {
3302 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3306 if (!(pt->IsActive())) continue;
3307 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
3308 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
3310 sumdens2+= dens*dens;
3311 sumn += pt->GetNumberOfClusters();
3312 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
3313 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
3316 sumchi2 +=chi2*chi2;
3321 Float_t mdensity = 0.9;
3322 Float_t meann = 130;
3323 Float_t meanchi = 1;
3324 Float_t sdensity = 0.1;
3325 Float_t smeann = 10;
3326 Float_t smeanchi =0.4;
3330 mdensity = sumdens/sum;
3332 meanchi = sumchi/sum;
3334 sdensity = sumdens2/sum-mdensity*mdensity;
3336 sdensity = TMath::Sqrt(sdensity);
3340 smeann = sumn2/sum-meann*meann;
3342 smeann = TMath::Sqrt(smeann);
3346 smeanchi = sumchi2/sum - meanchi*meanchi;
3348 smeanchi = TMath::Sqrt(smeanchi);
3354 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
3356 for (Int_t i=0; i<nseed; i++) {
3357 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3361 if (pt->GetBSigned()) continue;
3362 if (pt->GetBConstrain()) continue;
3363 //if (!(pt->IsActive())) continue;
3365 Int_t found,foundable,shared;
3366 pt->GetClusterStatistic(0,160,found, foundable,shared);
3367 if (shared/float(found)>0.3) {
3368 if (shared/float(found)>0.9 ){
3369 //MarkSeedFree( arr->RemoveAt(i) );
3374 Bool_t isok =kFALSE;
3375 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
3377 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
3379 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
3381 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
3385 for (Int_t j=0; j<160; ++j) {
3386 Int_t index=pt->GetClusterIndex2(j);
3387 if (index<0) continue;
3388 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3390 //if (!(c->IsUsed(10))) c->Use();
3397 Double_t maxchi = meanchi+2.*smeanchi;
3399 for (Int_t i=0; i<nseed; i++) {
3400 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
3404 //if (!(pt->IsActive())) continue;
3405 if (pt->GetBSigned()) continue;
3406 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
3407 if (chi>maxchi) continue;
3410 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
3412 //sign only tracks with enoug big density at the beginning
3414 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
3417 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
3418 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
3420 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
3421 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
3424 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
3425 //Int_t noc=pt->GetNumberOfClusters();
3426 pt->SetBSigned(kTRUE);
3427 for (Int_t j=0; j<160; ++j) {
3429 Int_t index=pt->GetClusterIndex2(j);
3430 if (index<0) continue;
3431 AliTPCclusterMI *c= pt->GetClusterPointer(j);
3433 // if (!(c->IsUsed(10))) c->Use();
3438 // gLastCheck = nseed;
3447 Int_t AliTPCtracker::RefitInward(AliESDEvent *event)
3450 // back propagation of ESD tracks
3453 if (!event) return 0;
3454 const Int_t kMaxFriendTracks=2000;
3457 // extract correction object for multiplicity dependence of dEdx
3458 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
3460 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
3462 AliFatal("Tranformations not in RefitInward");
3465 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
3466 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
3467 Int_t nContribut = event->GetNumberOfTracks();
3468 TGraphErrors * graphMultDependenceDeDx = 0x0;
3469 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
3470 if (recoParam->GetUseTotCharge()) {
3471 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
3473 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
3479 //PrepareForProlongation(fSeeds,1);
3480 PropagateForward2(fSeeds);
3481 RemoveUsed2(fSeeds,0.4,0.4,20);
3483 Int_t entriesSeed=fSeeds->GetEntries();
3484 TObjArray arraySeed(entriesSeed);
3485 for (Int_t i=0;i<entriesSeed;i++) {
3486 arraySeed.AddAt(fSeeds->At(i),i);
3488 SignShared(&arraySeed);
3489 // FindCurling(fSeeds, event,2); // find multi found tracks
3490 FindSplitted(fSeeds, event,2); // find multi found tracks
3491 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) FindMultiMC(fSeeds, fEvent,2); // flag: stream MC infomation about the multiple find track (ONLY for MC data)
3494 Int_t nseed = fSeeds->GetEntriesFast();
3495 for (Int_t i=0;i<nseed;i++){
3496 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3497 if (!seed) continue;
3498 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
3499 AliESDtrack *esd=event->GetTrack(i);
3501 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3502 AliExternalTrackParam paramIn;
3503 AliExternalTrackParam paramOut;
3504 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3505 if ((AliTPCReconstructor::StreamLevel() & kStreamRecoverIn)>0) { // flag: stream track information for track failing in RefitInward function and recovered back
3506 (*fDebugStreamer)<<"RecoverIn"<<
3510 "pout.="<<¶mOut<<
3515 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
3516 seed->SetNumberOfClusters(ncl);
3520 seed->PropagateTo(fkParam->GetInnerRadiusLow());
3521 seed->UpdatePoints();
3522 AddCovariance(seed);
3523 MakeESDBitmaps(seed, esd);
3524 seed->CookdEdx(0.02,0.6);
3525 CookLabel(seed,0.1); //For comparison only
3527 if (((AliTPCReconstructor::StreamLevel()&kStreamRefitInward)>0) && seed!=0) {
3528 TTreeSRedirector &cstream = *fDebugStreamer;
3529 cstream<<"RefitInward"<< // flag: stream track information in RefitInward function (after tracking Iteration 2)
3535 if (seed->GetNumberOfClusters()>15){
3536 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
3537 esd->SetTPCPoints(seed->GetPoints());
3538 esd->SetTPCPointsF(seed->GetNFoundable());
3539 Int_t ndedx = seed->GetNCDEDX(0);
3540 Float_t sdedx = seed->GetSDEDX(0);
3541 Float_t dedx = seed->GetdEdx();
3542 // apply mutliplicity dependent dEdx correction if available
3543 if (graphMultDependenceDeDx) {
3544 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
3545 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
3547 esd->SetTPCsignal(dedx, sdedx, ndedx);
3549 // fill new dEdx information
3551 Double32_t signal[4];
3552 Double32_t signalMax[4];
3556 for(Int_t iarr=0;iarr<3;iarr++) {
3557 signal[iarr] = seed->GetDEDXregion(iarr+1);
3558 signalMax[iarr] = seed->GetDEDXregion(iarr+5);
3559 ncl[iarr] = seed->GetNCDEDX(iarr+1);
3560 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
3562 signal[3] = seed->GetDEDXregion(4);
3563 signalMax[3] = seed->GetDEDXregion(8);
3566 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
3567 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
3568 infoTpcPid->SetTPCSignalsQmax(signalMax);
3569 esd->SetTPCdEdxInfo(infoTpcPid);
3571 // add seed to the esd track in Calib level
3573 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
3574 // if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
3575 if (storeFriend){ // RS: seed is needed for calibration, regardless on streamlevel
3576 // RS: this is the only place where the seed is created not in the pool,
3577 // since it should belong to ESDevent
3578 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
3579 esd->AddCalibObject(seedCopy);
3584 //printf("problem\n");
3587 //FindKinks(fSeeds,event);
3588 if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0) DumpClusters(2,fSeeds); // dump clusters at the end of process (signed with useage flags)
3589 Info("RefitInward","Number of refitted tracks %d",ntracks);
3591 AliCosmicTracker::FindCosmic(event, kTRUE);
3593 FillClusterOccupancyInfo();
3599 Int_t AliTPCtracker::PropagateBack(AliESDEvent *event)
3602 // back propagation of ESD tracks
3604 if (!event) return 0;
3609 PropagateBack(fSeeds);
3610 RemoveUsed2(fSeeds,0.4,0.4,20);
3611 //FindCurling(fSeeds, fEvent,1);
3612 FindSplitted(fSeeds, event,1); // find multi found tracks
3613 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
3616 Int_t nseed = fSeeds->GetEntriesFast();
3618 for (Int_t i=0;i<nseed;i++){
3619 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
3620 if (!seed) continue;
3621 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
3622 seed->UpdatePoints();
3623 AddCovariance(seed);
3624 AliESDtrack *esd=event->GetTrack(i);
3625 if (!esd) continue; //never happen
3626 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
3627 AliExternalTrackParam paramIn;
3628 AliExternalTrackParam paramOut;
3629 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
3630 if ((AliTPCReconstructor::StreamLevel()&kStreamRecoverBack)>0) { // flag: stream track information for track faling PropagateBack function and recovered back (RefitTrack)
3631 (*fDebugStreamer)<<"RecoverBack"<<
3635 "pout.="<<¶mOut<<
3640 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
3641 seed->SetNumberOfClusters(ncl);
3644 seed->CookdEdx(0.02,0.6);
3645 CookLabel(seed,0.1); //For comparison only
3646 if (seed->GetNumberOfClusters()>15){
3647 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
3648 esd->SetTPCPoints(seed->GetPoints());
3649 esd->SetTPCPointsF(seed->GetNFoundable());
3650 Int_t ndedx = seed->GetNCDEDX(0);
3651 Float_t sdedx = seed->GetSDEDX(0);
3652 Float_t dedx = seed->GetdEdx();
3653 esd->SetTPCsignal(dedx, sdedx, ndedx);
3655 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
3656 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
3657 if (((AliTPCReconstructor::StreamLevel()&kStreamCPropagateBack)>0) && esd) {
3658 (*fDebugStreamer)<<"PropagateBack"<< // flag: stream track information in PropagateBack function (after tracking Iteration 1)
3661 "EventNrInFile="<<eventnumber<<
3666 if (AliTPCReconstructor::StreamLevel()&kStreamClDump) DumpClusters(1,fSeeds); // flag:stream clusters at the end of process (signed with usage flag)
3667 //FindKinks(fSeeds,event);
3668 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
3676 Int_t AliTPCtracker::PostProcess(AliESDEvent *event)
3679 // Post process events
3681 if (!event) return 0;
3684 // Set TPC event status
3687 // event affected by HV dip
3689 if(IsTPCHVDipEvent(event)) {
3690 event->ResetDetectorStatus(AliDAQ::kTPC);
3693 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
3699 void AliTPCtracker::DeleteSeeds()
3708 void AliTPCtracker::ReadSeeds(const AliESDEvent *const event, Int_t direction)
3711 //read seeds from the event
3713 Int_t nentr=event->GetNumberOfTracks();
3715 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
3720 fSeeds = new TObjArray(nentr);
3724 for (Int_t i=0; i<nentr; i++) {
3725 AliESDtrack *esd=event->GetTrack(i);
3726 ULong_t status=esd->GetStatus();
3727 if (!(status&AliESDtrack::kTPCin)) continue;
3728 AliTPCtrack t(*esd);
3729 t.SetNumberOfClusters(0);
3730 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
3731 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
3732 seed->SetPoolID(fLastSeedID);
3733 seed->SetUniqueID(esd->GetID());
3734 AddCovariance(seed); //add systematic ucertainty
3735 for (Int_t ikink=0;ikink<3;ikink++) {
3736 Int_t index = esd->GetKinkIndex(ikink);
3737 seed->GetKinkIndexes()[ikink] = index;
3738 if (index==0) continue;
3739 index = TMath::Abs(index);
3740 AliESDkink * kink = fEvent->GetKink(index-1);
3741 if (kink&&esd->GetKinkIndex(ikink)<0){
3742 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
3743 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
3745 if (kink&&esd->GetKinkIndex(ikink)>0){
3746 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
3747 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
3751 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
3752 //RS if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3753 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
3754 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
3755 // fSeeds->AddAt(0,i);
3756 // MarkSeedFree( seed );
3762 // rotate to the local coordinate system
3764 fSectors=fInnerSec; fN=fkNIS;
3765 Double_t alpha=seed->GetAlpha();
3766 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
3767 if (alpha < 0. ) alpha += 2.*TMath::Pi();
3768 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3769 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3770 alpha-=seed->GetAlpha();
3771 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3772 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3773 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3774 AliWarning(Form("Rotating track over %f",alpha));
3775 if (!seed->Rotate(alpha)) {
3776 MarkSeedFree( seed );
3782 if (esd->GetKinkIndex(0)<=0){
3783 for (Int_t irow=0;irow<160;irow++){
3784 Int_t index = seed->GetClusterIndex2(irow);
3787 AliTPCclusterMI * cl = GetClusterMI(index);
3788 seed->SetClusterPointer(irow,cl);
3790 if ((index & 0x8000)==0){
3791 cl->Use(10); // accepted cluster
3793 cl->Use(6); // close cluster not accepted
3796 Info("ReadSeeds","Not found cluster");
3801 fSeeds->AddAt(seed,i);
3807 //_____________________________________________________________________________
3808 void AliTPCtracker::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3809 Float_t deltay, Int_t ddsec) {
3810 //-----------------------------------------------------------------
3811 // This function creates track seeds.
3812 // SEEDING WITH VERTEX CONSTRAIN
3813 //-----------------------------------------------------------------
3814 // cuts[0] - fP4 cut
3815 // cuts[1] - tan(phi) cut
3816 // cuts[2] - zvertex cut
3817 // cuts[3] - fP3 cut
3825 Double_t x[5], c[15];
3826 // Int_t di = i1-i2;
3828 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3829 seed->SetPoolID(fLastSeedID);
3830 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3831 Double_t cs=cos(alpha), sn=sin(alpha);
3833 // Double_t x1 =fOuterSec->GetX(i1);
3834 //Double_t xx2=fOuterSec->GetX(i2);
3836 Double_t x1 =GetXrow(i1);
3837 Double_t xx2=GetXrow(i2);
3839 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3841 Int_t imiddle = (i2+i1)/2; //middle pad row index
3842 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3843 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3847 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3848 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3849 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3852 // change cut on curvature if it can't reach this layer
3853 // maximal curvature set to reach it
3854 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3855 if (dvertexmax*0.5*cuts[0]>0.85){
3856 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3858 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3861 if (deltay>0) ddsec = 0;
3862 // loop over clusters
3863 for (Int_t is=0; is < kr1; is++) {
3865 if (kr1[is]->IsUsed(10)) continue;
3866 if (kr1[is]->IsDisabled()) {
3870 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3871 //if (TMath::Abs(y1)>ymax) continue;
3873 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3875 // find possible directions
3876 Float_t anglez = (z1-z3)/(x1-x3);
3877 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3880 //find rotation angles relative to line given by vertex and point 1
3881 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3882 Double_t dvertex = TMath::Sqrt(dvertex2);
3883 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3884 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3887 // loop over 2 sectors
3893 Double_t dddz1=0; // direction of delta inclination in z axis
3900 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3901 Int_t sec2 = sec + dsec;
3903 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3904 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3905 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3906 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3907 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3908 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3910 // rotation angles to p1-p3
3911 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3912 Double_t x2, y2, z2;
3914 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3917 Double_t dxx0 = (xx2-x3)*cs13r;
3918 Double_t dyy0 = (xx2-x3)*sn13r;
3919 for (Int_t js=index1; js < index2; js++) {
3920 const AliTPCclusterMI *kcl = kr2[js];
3921 if (kcl->IsUsed(10)) continue;
3922 if (kcl->IsDisabled()) {
3926 //calcutate parameters
3928 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3930 if (TMath::Abs(yy0)<0.000001) continue;
3931 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3932 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3933 Double_t r02 = (0.25+y0*y0)*dvertex2;
3934 //curvature (radius) cut
3935 if (r02<r2min) continue;
3939 Double_t c0 = 1/TMath::Sqrt(r02);
3943 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3944 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3945 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3946 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3949 Double_t z0 = kcl->GetZ();
3950 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3951 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3954 Double_t dip = (z1-z0)*c0/dfi1;
3955 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3966 x2= xx2*cs-y2*sn*dsec;
3967 y2=+xx2*sn*dsec+y2*cs;
3977 // do we have cluster at the middle ?
3979 GetProlongation(x1,xm,x,ym,zm);
3981 AliTPCclusterMI * cm=0;
3982 if (TMath::Abs(ym)-ymaxm<0){
3983 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3984 if ((!cm) || (cm->IsUsed(10))) {
3989 // rotate y1 to system 0
3990 // get state vector in rotated system
3991 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3992 Double_t xr2 = x0*cs+yr1*sn*dsec;
3993 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3995 GetProlongation(xx2,xm,xr,ym,zm);
3996 if (TMath::Abs(ym)-ymaxm<0){
3997 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3998 if ((!cm) || (cm->IsUsed(10))) {
4005 // Double_t dym = 0;
4006 // Double_t dzm = 0;
4008 // dym = ym - cm->GetY();
4009 // dzm = zm - cm->GetZ();
4016 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
4017 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
4018 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
4019 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4020 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
4022 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4023 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4024 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4025 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4026 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4027 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4029 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4030 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4031 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4032 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4036 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4037 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4038 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4039 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4040 c[13]=f30*sy1*f40+f32*sy2*f42;
4041 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4043 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4045 UInt_t index=kr1.GetIndex(is);
4046 if (seed) {MarkSeedFree(seed); seed = 0;}
4047 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
4048 seed->SetPoolID(fLastSeedID);
4049 track->SetIsSeeding(kTRUE);
4050 track->SetSeed1(i1);
4051 track->SetSeed2(i2);
4052 track->SetSeedType(3);
4056 FollowProlongation(*track, (i1+i2)/2,1);
4057 Int_t foundable,found,shared;
4058 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
4059 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
4060 MarkSeedFree(seed); seed = 0;
4066 FollowProlongation(*track, i2,1);
4070 track->SetBConstrain(1);
4071 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
4072 track->SetLastPoint(i1); // first cluster in track position
4073 track->SetFirstPoint(track->GetLastPoint());
4075 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4076 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4077 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
4078 MarkSeedFree(seed); seed = 0;
4082 // Z VERTEX CONDITION
4083 Double_t zv, bz=GetBz();
4084 if ( !track->GetZAt(0.,bz,zv) ) continue;
4085 if (TMath::Abs(zv-z3)>cuts[2]) {
4086 FollowProlongation(*track, TMath::Max(i2-20,0));
4087 if ( !track->GetZAt(0.,bz,zv) ) continue;
4088 if (TMath::Abs(zv-z3)>cuts[2]){
4089 FollowProlongation(*track, TMath::Max(i2-40,0));
4090 if ( !track->GetZAt(0.,bz,zv) ) continue;
4091 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
4092 // make seed without constrain
4093 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
4094 FollowProlongation(*track2, i2,1);
4095 track2->SetBConstrain(kFALSE);
4096 track2->SetSeedType(1);
4097 arr->AddLast(track2);
4098 MarkSeedFree( seed ); seed = 0;
4102 MarkSeedFree( seed ); seed = 0;
4109 track->SetSeedType(0);
4110 arr->AddLast(track); // note, track is seed, don't free the seed
4111 seed = new( NextFreeSeed() ) AliTPCseed;
4112 seed->SetPoolID(fLastSeedID);
4114 // don't consider other combinations
4115 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
4121 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
4123 if (seed) MarkSeedFree( seed );
4127 void AliTPCtracker::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
4132 //-----------------------------------------------------------------
4133 // This function creates track seeds.
4134 //-----------------------------------------------------------------
4135 // cuts[0] - fP4 cut
4136 // cuts[1] - tan(phi) cut
4137 // cuts[2] - zvertex cut
4138 // cuts[3] - fP3 cut
4148 Double_t x[5], c[15];
4150 // make temporary seed
4151 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4152 seed->SetPoolID(fLastSeedID);
4153 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4154 // Double_t cs=cos(alpha), sn=sin(alpha);
4159 Double_t x1 = GetXrow(i1-1);
4160 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
4161 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
4163 Double_t x1p = GetXrow(i1);
4164 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
4166 Double_t x1m = GetXrow(i1-2);
4167 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
4170 //last 3 padrow for seeding
4171 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
4172 Double_t x3 = GetXrow(i1-7);
4173 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
4175 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
4176 Double_t x3p = GetXrow(i1-6);
4178 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
4179 Double_t x3m = GetXrow(i1-8);
4184 Int_t im = i1-4; //middle pad row index
4185 Double_t xm = GetXrow(im); // radius of middle pad-row
4186 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
4187 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
4190 Double_t deltax = x1-x3;
4191 Double_t dymax = deltax*cuts[1];
4192 Double_t dzmax = deltax*cuts[3];
4194 // loop over clusters
4195 for (Int_t is=0; is < kr1; is++) {
4197 if (kr1[is]->IsUsed(10)) continue;
4198 if (kr1[is]->IsDisabled()) {
4202 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
4204 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
4206 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
4207 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
4213 for (Int_t js=index1; js < index2; js++) {
4214 const AliTPCclusterMI *kcl = kr3[js];
4215 if (kcl->IsDisabled()) {
4219 if (kcl->IsUsed(10)) continue;
4221 // apply angular cuts
4222 if (TMath::Abs(y1-y3)>dymax) continue;
4225 if (TMath::Abs(z1-z3)>dzmax) continue;
4227 Double_t angley = (y1-y3)/(x1-x3);
4228 Double_t anglez = (z1-z3)/(x1-x3);
4230 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
4231 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
4233 Double_t yyym = angley*(xm-x1)+y1;
4234 Double_t zzzm = anglez*(xm-x1)+z1;
4236 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
4238 if (kcm->IsUsed(10)) continue;
4239 if (kcm->IsDisabled()) {
4243 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
4244 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
4251 // look around first
4252 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
4258 if (kc1m->IsUsed(10)) used++;
4260 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
4266 if (kc1p->IsUsed(10)) used++;
4268 if (used>1) continue;
4269 if (found<1) continue;
4273 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
4279 if (kc3m->IsUsed(10)) used++;
4283 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
4289 if (kc3p->IsUsed(10)) used++;
4293 if (used>1) continue;
4294 if (found<3) continue;
4304 x[4]=F1(x1,y1,x2,y2,x3,y3);
4305 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
4308 x[2]=F2(x1,y1,x2,y2,x3,y3);
4311 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
4312 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4316 Double_t sy1=0.1, sz1=0.1;
4317 Double_t sy2=0.1, sz2=0.1;
4318 Double_t sy3=0.1, sy=0.1, sz=0.1;
4320 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4321 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4322 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4323 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4324 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4325 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4327 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
4328 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
4329 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
4330 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
4334 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4335 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4336 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4337 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4338 c[13]=f30*sy1*f40+f32*sy2*f42;
4339 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4341 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
4343 index=kr1.GetIndex(is);
4344 if (seed) {MarkSeedFree( seed ); seed = 0;}
4345 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
4346 seed->SetPoolID(fLastSeedID);
4348 track->SetIsSeeding(kTRUE);
4351 FollowProlongation(*track, i1-7,1);
4352 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
4353 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
4354 MarkSeedFree( seed ); seed = 0;
4360 FollowProlongation(*track, i2,1);
4361 track->SetBConstrain(0);
4362 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
4363 track->SetFirstPoint(track->GetLastPoint());
4365 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4366 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
4367 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
4368 MarkSeedFree( seed ); seed = 0;
4373 FollowProlongation(*track, TMath::Max(i2-10,0),1);
4374 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
4375 FollowProlongation(*track2, i2,1);
4376 track2->SetBConstrain(kFALSE);
4377 track2->SetSeedType(4);
4378 arr->AddLast(track2);
4379 MarkSeedFree( seed ); seed = 0;
4383 //arr->AddLast(track);
4384 //seed = new AliTPCseed;
4390 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);
4392 if (seed) MarkSeedFree(seed);
4396 //_____________________________________________________________________________
4397 void AliTPCtracker::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
4398 Float_t deltay, Bool_t /*bconstrain*/) {
4399 //-----------------------------------------------------------------
4400 // This function creates track seeds - without vertex constraint
4401 //-----------------------------------------------------------------
4402 // cuts[0] - fP4 cut - not applied
4403 // cuts[1] - tan(phi) cut
4404 // cuts[2] - zvertex cut - not applied
4405 // cuts[3] - fP3 cut
4415 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
4416 // Double_t cs=cos(alpha), sn=sin(alpha);
4417 Int_t row0 = (i1+i2)/2;
4418 Int_t drow = (i1-i2)/2;
4419 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
4420 AliTPCtrackerRow * kr=0;
4422 AliTPCpolyTrack polytrack;
4423 Int_t nclusters=fSectors[sec][row0];
4424 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
4425 seed->SetPoolID(fLastSeedID);
4430 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
4432 Int_t nfoundable =0;
4433 for (Int_t iter =1; iter<2; iter++){ //iterations
4434 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
4435 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
4436 const AliTPCclusterMI * cl= kr0[is];
4437 if (cl->IsDisabled()) {
4441 if (cl->IsUsed(10)) {
4447 Double_t x = kr0.GetX();
4448 // Initialization of the polytrack
4453 Double_t y0= cl->GetY();
4454 Double_t z0= cl->GetZ();
4458 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
4459 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
4461 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
4462 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
4463 polytrack.AddPoint(x,y0,z0,erry, errz);
4466 if (cl->IsUsed(10)) sumused++;
4469 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
4470 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
4473 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
4474 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
4475 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
4476 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
4477 if (cl1->IsUsed(10)) sumused++;
4478 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
4482 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
4484 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
4485 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
4486 if (cl2->IsUsed(10)) sumused++;
4487 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
4490 if (sumused>0) continue;
4492 polytrack.UpdateParameters();
4498 nfoundable = polytrack.GetN();
4499 nfound = nfoundable;
4501 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
4502 Float_t maxdist = 0.8*(1.+3./(ddrow));
4503 for (Int_t delta = -1;delta<=1;delta+=2){
4504 Int_t row = row0+ddrow*delta;
4505 kr = &(fSectors[sec][row]);
4506 Double_t xn = kr->GetX();
4507 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
4508 polytrack.GetFitPoint(xn,yn,zn);
4509 if (TMath::Abs(yn)>ymax1) continue;
4511 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
4513 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
4516 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4517 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
4518 if (cln->IsUsed(10)) {
4519 // printf("used\n");
4527 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
4532 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
4533 polytrack.UpdateParameters();
4536 if ( (sumused>3) || (sumused>0.5*nfound)) {
4537 //printf("sumused %d\n",sumused);
4542 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
4543 AliTPCpolyTrack track2;
4545 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
4546 if (track2.GetN()<0.5*nfoundable) continue;
4549 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
4551 // test seed with and without constrain
4552 for (Int_t constrain=0; constrain<=0;constrain++){
4553 // add polytrack candidate
4555 Double_t x[5], c[15];
4556 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
4557 track2.GetBoundaries(x3,x1);
4559 track2.GetFitPoint(x1,y1,z1);
4560 track2.GetFitPoint(x2,y2,z2);
4561 track2.GetFitPoint(x3,y3,z3);
4563 //is track pointing to the vertex ?
4566 polytrack.GetFitPoint(x0,y0,z0);
4579 x[4]=F1(x1,y1,x2,y2,x3,y3);
4581 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
4582 x[2]=F2(x1,y1,x2,y2,x3,y3);
4584 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
4585 //x[3]=F3(x1,y1,x2,y2,z1,z2);
4586 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
4587 //if (TMath::Abs(x[3]) > cuts[3]) continue;
4590 Double_t sy =0.1, sz =0.1;
4591 Double_t sy1=0.02, sz1=0.02;
4592 Double_t sy2=0.02, sz2=0.02;
4596 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
4599 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
4600 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
4601 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
4602 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
4603 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
4604 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
4606 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
4607 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
4608 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
4609 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
4614 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4615 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4616 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4617 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4618 c[13]=f30*sy1*f40+f32*sy2*f42;
4619 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4621 //Int_t row1 = fSectors->GetRowNumber(x1);
4622 Int_t row1 = GetRowNumber(x1);
4626 if (seed) {MarkSeedFree( seed ); seed = 0;}
4627 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
4628 seed->SetPoolID(fLastSeedID);
4629 track->SetIsSeeding(kTRUE);
4630 Int_t rc=FollowProlongation(*track, i2);
4631 if (constrain) track->SetBConstrain(1);
4633 track->SetBConstrain(0);
4634 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
4635 track->SetFirstPoint(track->GetLastPoint());
4637 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
4638 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
4639 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
4640 MarkSeedFree( seed ); seed = 0;
4643 arr->AddLast(track); // track IS seed, don't free seed
4644 seed = new( NextFreeSeed() ) AliTPCseed;
4645 seed->SetPoolID(fLastSeedID);
4649 } // if accepted seed
4652 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
4654 if (seed) MarkSeedFree( seed );
4658 AliTPCseed *AliTPCtracker::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
4662 //reseed using track points
4663 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
4664 Int_t p1 = int(r1*track->GetNumberOfClusters());
4665 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
4667 Double_t x0[3],x1[3],x2[3];
4668 for (Int_t i=0;i<3;i++){
4674 // find track position at given ratio of the length
4675 Int_t sec0=0, sec1=0, sec2=0;
4678 for (Int_t i=0;i<160;i++){
4679 if (track->GetClusterPointer(i)){
4681 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
4682 if ( (index<p0) || x0[0]<0 ){
4683 if (trpoint->GetX()>1){
4684 clindex = track->GetClusterIndex2(i);
4686 x0[0] = trpoint->GetX();
4687 x0[1] = trpoint->GetY();
4688 x0[2] = trpoint->GetZ();
4689 sec0 = ((clindex&0xff000000)>>24)%18;
4694 if ( (index<p1) &&(trpoint->GetX()>1)){
4695 clindex = track->GetClusterIndex2(i);
4697 x1[0] = trpoint->GetX();
4698 x1[1] = trpoint->GetY();
4699 x1[2] = trpoint->GetZ();
4700 sec1 = ((clindex&0xff000000)>>24)%18;
4703 if ( (index<p2) &&(trpoint->GetX()>1)){
4704 clindex = track->GetClusterIndex2(i);
4706 x2[0] = trpoint->GetX();
4707 x2[1] = trpoint->GetY();
4708 x2[2] = trpoint->GetZ();
4709 sec2 = ((clindex&0xff000000)>>24)%18;
4716 Double_t alpha, cs,sn, xx2,yy2;
4718 alpha = (sec1-sec2)*fSectors->GetAlpha();
4719 cs = TMath::Cos(alpha);
4720 sn = TMath::Sin(alpha);
4721 xx2= x1[0]*cs-x1[1]*sn;
4722 yy2= x1[0]*sn+x1[1]*cs;
4726 alpha = (sec0-sec2)*fSectors->GetAlpha();
4727 cs = TMath::Cos(alpha);
4728 sn = TMath::Sin(alpha);
4729 xx2= x0[0]*cs-x0[1]*sn;
4730 yy2= x0[0]*sn+x0[1]*cs;
4736 Double_t x[5],c[15];
4740 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4741 // if (x[4]>1) return 0;
4742 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
4743 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
4744 //if (TMath::Abs(x[3]) > 2.2) return 0;
4745 //if (TMath::Abs(x[2]) > 1.99) return 0;
4747 Double_t sy =0.1, sz =0.1;
4749 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
4750 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
4751 Double_t sy3=0.01+track->GetSigmaY2();
4753 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
4754 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
4755 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
4756 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
4757 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
4758 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
4760 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
4761 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
4762 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
4763 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
4768 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4769 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4770 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4771 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4772 c[13]=f30*sy1*f40+f32*sy2*f42;
4773 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4775 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
4776 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4777 seed->SetPoolID(fLastSeedID);
4778 // Double_t y0,z0,y1,z1, y2,z2;
4779 //seed->GetProlongation(x0[0],y0,z0);
4780 // seed->GetProlongation(x1[0],y1,z1);
4781 //seed->GetProlongation(x2[0],y2,z2);
4783 seed->SetLastPoint(pp2);
4784 seed->SetFirstPoint(pp2);
4791 AliTPCseed *AliTPCtracker::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4795 //reseed using founded clusters
4797 // Find the number of clusters
4798 Int_t nclusters = 0;
4799 for (Int_t irow=0;irow<160;irow++){
4800 if (track->GetClusterIndex(irow)>0) nclusters++;
4804 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4805 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4806 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4809 Double_t xyz[3][3]={{0}};
4810 Int_t row[3]={0},sec[3]={0,0,0};
4812 // find track row position at given ratio of the length
4814 for (Int_t irow=0;irow<160;irow++){
4815 if (track->GetClusterIndex2(irow)<0) continue;
4817 for (Int_t ipoint=0;ipoint<3;ipoint++){
4818 if (index<=ipos[ipoint]) row[ipoint] = irow;
4822 //Get cluster and sector position
4823 for (Int_t ipoint=0;ipoint<3;ipoint++){
4824 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4825 AliTPCclusterMI * cl = GetClusterMI(clindex);
4828 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4831 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4832 xyz[ipoint][0] = GetXrow(row[ipoint]);
4833 xyz[ipoint][1] = cl->GetY();
4834 xyz[ipoint][2] = cl->GetZ();
4838 // Calculate seed state vector and covariance matrix
4840 Double_t alpha, cs,sn, xx2,yy2;
4842 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4843 cs = TMath::Cos(alpha);
4844 sn = TMath::Sin(alpha);
4845 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4846 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4850 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4851 cs = TMath::Cos(alpha);
4852 sn = TMath::Sin(alpha);
4853 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4854 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4860 Double_t x[5],c[15];
4864 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4865 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4866 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4868 Double_t sy =0.1, sz =0.1;
4870 Double_t sy1=0.2, sz1=0.2;
4871 Double_t sy2=0.2, sz2=0.2;
4874 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;
4875 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;
4876 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;
4877 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;
4878 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;
4879 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;
4881 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;
4882 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;
4883 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;
4884 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;
4889 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4890 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4891 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4892 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4893 c[13]=f30*sy1*f40+f32*sy2*f42;
4894 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4896 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4897 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4898 seed->SetPoolID(fLastSeedID);
4899 seed->SetLastPoint(row[2]);
4900 seed->SetFirstPoint(row[2]);
4905 AliTPCseed *AliTPCtracker::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4909 //reseed using founded clusters
4912 Int_t row[3]={0,0,0};
4913 Int_t sec[3]={0,0,0};
4915 // forward direction
4917 for (Int_t irow=r0;irow<160;irow++){
4918 if (track->GetClusterIndex(irow)>0){
4923 for (Int_t irow=160;irow>r0;irow--){
4924 if (track->GetClusterIndex(irow)>0){
4929 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4930 if (track->GetClusterIndex(irow)>0){
4938 for (Int_t irow=0;irow<r0;irow++){
4939 if (track->GetClusterIndex(irow)>0){
4944 for (Int_t irow=r0;irow>0;irow--){
4945 if (track->GetClusterIndex(irow)>0){
4950 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4951 if (track->GetClusterIndex(irow)>0){
4958 if ((row[2]-row[0])<20) return 0;
4959 if (row[1]==0) return 0;
4962 //Get cluster and sector position
4963 for (Int_t ipoint=0;ipoint<3;ipoint++){
4964 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4965 AliTPCclusterMI * cl = GetClusterMI(clindex);
4968 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4971 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4972 xyz[ipoint][0] = GetXrow(row[ipoint]);
4973 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4974 if (point&&ipoint<2){
4976 xyz[ipoint][1] = point->GetY();
4977 xyz[ipoint][2] = point->GetZ();
4980 xyz[ipoint][1] = cl->GetY();
4981 xyz[ipoint][2] = cl->GetZ();
4988 // Calculate seed state vector and covariance matrix
4990 Double_t alpha, cs,sn, xx2,yy2;
4992 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4993 cs = TMath::Cos(alpha);
4994 sn = TMath::Sin(alpha);
4995 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4996 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
5000 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
5001 cs = TMath::Cos(alpha);
5002 sn = TMath::Sin(alpha);
5003 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
5004 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
5010 Double_t x[5],c[15];
5014 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5015 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
5016 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
5018 Double_t sy =0.1, sz =0.1;
5020 Double_t sy1=0.2, sz1=0.2;
5021 Double_t sy2=0.2, sz2=0.2;
5024 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;
5025 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;
5026 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;
5027 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;
5028 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;
5029 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;
5031 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;
5032 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;
5033 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;
5034 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;
5039 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
5040 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
5041 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
5042 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
5043 c[13]=f30*sy1*f40+f32*sy2*f42;
5044 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
5046 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
5047 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
5048 seed->SetPoolID(fLastSeedID);
5049 seed->SetLastPoint(row[2]);
5050 seed->SetFirstPoint(row[2]);
5051 for (Int_t i=row[0];i<row[2];i++){
5052 seed->SetClusterIndex(i, track->GetClusterIndex(i));
5060 void AliTPCtracker::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5063 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
5065 // Use AliTPCReconstructor::StreamLevel()& kStreamFindMultiMC if you want to tune parameters - cuts
5067 // Two reasons to have multiple find tracks
5068 // 1. Curling tracks can be find more than once
5069 // 2. Splitted tracks
5070 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
5071 // b.) Edge effect on the sector boundaries
5074 // Algorithm done in 2 phases - because of CPU consumption
5075 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
5077 // Algorihm for curling tracks sign:
5078 // 1 phase -makes a very rough fast cuts to minimize combinatorics
5079 // a.) opposite sign
5080 // b.) one of the tracks - not pointing to the primary vertex -
5081 // c.) delta tan(theta)
5083 // 2 phase - calculates DCA between tracks - time consument
5088 // General cuts - for splitted tracks and for curling tracks
5090 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
5092 // Curling tracks cuts
5097 Int_t nentries = array->GetEntriesFast();
5098 AliHelix *helixes = new AliHelix[nentries];
5099 Float_t *xm = new Float_t[nentries];
5100 Float_t *dz0 = new Float_t[nentries];
5101 Float_t *dz1 = new Float_t[nentries];
5107 // Find track COG in x direction - point with best defined parameters
5109 for (Int_t i=0;i<nentries;i++){
5110 AliTPCseed* track = (AliTPCseed*)array->At(i);
5111 if (!track) continue;
5112 track->SetCircular(0);
5113 new (&helixes[i]) AliHelix(*track);
5117 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
5120 for (Int_t icl=0; icl<160; icl++){
5121 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
5127 if (ncl>0) xm[i]/=Float_t(ncl);
5130 for (Int_t i0=0;i0<nentries;i0++){
5131 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5132 if (!track0) continue;
5133 Float_t xc0 = helixes[i0].GetHelix(6);
5134 Float_t yc0 = helixes[i0].GetHelix(7);
5135 Float_t r0 = helixes[i0].GetHelix(8);
5136 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5137 Float_t fi0 = TMath::ATan2(yc0,xc0);
5139 for (Int_t i1=i0+1;i1<nentries;i1++){
5140 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5141 if (!track1) continue;
5142 Int_t lab0=track0->GetLabel();
5143 Int_t lab1=track1->GetLabel();
5144 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
5146 Float_t xc1 = helixes[i1].GetHelix(6);
5147 Float_t yc1 = helixes[i1].GetHelix(7);
5148 Float_t r1 = helixes[i1].GetHelix(8);
5149 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5150 Float_t fi1 = TMath::ATan2(yc1,xc1);
5152 Float_t dfi = fi0-fi1;
5155 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
5156 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
5157 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
5159 // if short tracks with undefined sign
5160 fi1 = -TMath::ATan2(yc1,-xc1);
5163 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5166 // debug stream to tune "fast cuts"
5168 Double_t dist[3]; // distance at X
5169 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
5170 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
5171 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5172 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
5173 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5174 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
5175 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
5176 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
5180 for (Int_t icl=0; icl<160; icl++){
5181 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
5182 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
5185 if (cl0==cl1) sums++;
5189 if ((AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC)>0) { // flag: stream MC infomation about the multiple find track (ONLY for MC data)
5190 TTreeSRedirector &cstream = *fDebugStreamer;
5195 "Tr0.="<<track0<< // seed0
5196 "Tr1.="<<track1<< // seed1
5197 "h0.="<<&helixes[i0]<<
5198 "h1.="<<&helixes[i1]<<
5200 "sum="<<sum<< //the sum of rows with cl in both
5201 "sums="<<sums<< //the sum of shared clusters
5202 "xm0="<<xm[i0]<< // the center of track
5203 "xm1="<<xm[i1]<< // the x center of track
5204 // General cut variables
5205 "dfi="<<dfi<< // distance in fi angle
5206 "dtheta="<<dtheta<< // distance int theta angle
5212 "dist0="<<dist[0]<< //distance x
5213 "dist1="<<dist[1]<< //distance y
5214 "dist2="<<dist[2]<< //distance z
5215 "mdist0="<<mdist[0]<< //distance x
5216 "mdist1="<<mdist[1]<< //distance y
5217 "mdist2="<<mdist[2]<< //distance z
5233 if (AliTPCReconstructor::StreamLevel()>0) {
5234 AliInfo("Time for curling tracks removal DEBUGGING MC");
5241 void AliTPCtracker::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
5243 // Find Splitted tracks and remove the one with worst quality
5244 // Corresponding debug streamer to tune selections - "Splitted2"
5246 // 0. Sort tracks according quality
5247 // 1. Propagate the tracks to the reference radius
5248 // 2. Double_t loop to select close tracks (only to speed up process)
5249 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
5250 // 4. Delete temporary parameters
5252 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
5254 const Double_t kCutP1=10; // delta Z cut 10 cm
5255 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
5256 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
5257 const Double_t kCutAlpha=0.15; // delta alpha cut
5258 Int_t firstpoint = 0;
5259 Int_t lastpoint = 160;
5261 Int_t nentries = array->GetEntriesFast();
5262 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
5268 //0. Sort tracks according quality
5269 //1. Propagate the ext. param to reference radius
5270 Int_t nseed = array->GetEntriesFast();
5271 if (nseed<=0) return;
5272 Float_t * quality = new Float_t[nseed];
5273 Int_t * indexes = new Int_t[nseed];
5274 for (Int_t i=0; i<nseed; i++) {
5275 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
5280 pt->UpdatePoints(); //select first last max dens points
5281 Float_t * points = pt->GetPoints();
5282 if (points[3]<0.8) quality[i] =-1;
5283 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
5284 //prefer high momenta tracks if overlaps
5285 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
5287 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
5288 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
5290 TMath::Sort(nseed,quality,indexes);
5292 // 3. Loop over pair of tracks
5294 for (Int_t i0=0; i0<nseed; i0++) {
5295 Int_t index0=indexes[i0];
5296 if (!(array->UncheckedAt(index0))) continue;
5297 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
5298 if (!s1->IsActive()) continue;
5299 AliExternalTrackParam &par0=params[index0];
5300 for (Int_t i1=i0+1; i1<nseed; i1++) {
5301 Int_t index1=indexes[i1];
5302 if (!(array->UncheckedAt(index1))) continue;
5303 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
5304 if (!s2->IsActive()) continue;
5305 if (s2->GetKinkIndexes()[0]!=0)
5306 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
5307 AliExternalTrackParam &par1=params[index1];
5308 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
5309 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
5310 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
5311 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
5312 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
5313 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
5318 Int_t firstShared=lastpoint, lastShared=firstpoint;
5319 Int_t firstRow=lastpoint, lastRow=firstpoint;
5321 for (Int_t i=firstpoint;i<lastpoint;i++){
5322 if (s1->GetClusterIndex2(i)>0) nall0++;
5323 if (s2->GetClusterIndex2(i)>0) nall1++;
5324 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
5325 if (i<firstRow) firstRow=i;
5326 if (i>lastRow) lastRow=i;
5328 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
5329 if (i<firstShared) firstShared=i;
5330 if (i>lastShared) lastShared=i;
5334 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
5335 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
5337 if ((AliTPCReconstructor::StreamLevel()&kStreamSplitted2)>0){ // flag:stream information about discarded TPC tracks pair algorithm
5338 TTreeSRedirector &cstream = *fDebugStreamer;
5339 Int_t n0=s1->GetNumberOfClusters();
5340 Int_t n1=s2->GetNumberOfClusters();
5341 Int_t n0F=s1->GetNFoundable();
5342 Int_t n1F=s2->GetNFoundable();
5343 Int_t lab0=s1->GetLabel();
5344 Int_t lab1=s2->GetLabel();
5346 cstream<<"Splitted2"<< // flag:stream information about discarded TPC tracks pair algorithm
5347 "iter="<<fIteration<<
5348 "lab0="<<lab0<< // MC label if exist
5349 "lab1="<<lab1<< // MC label if exist
5352 "ratio0="<<ratio0<< // shared ratio
5353 "ratio1="<<ratio1<< // shared ratio
5354 "p0.="<<&par0<< // track parameters
5356 "s0.="<<s1<< // full seed
5358 "n0="<<n0<< // number of clusters track 0
5359 "n1="<<n1<< // number of clusters track 1
5360 "nall0="<<nall0<< // number of clusters track 0
5361 "nall1="<<nall1<< // number of clusters track 1
5362 "n0F="<<n0F<< // number of findable
5363 "n1F="<<n1F<< // number of findable
5364 "shared="<<sumShared<< // number of shared clusters
5365 "firstS="<<firstShared<< // first and the last shared row
5366 "lastS="<<lastShared<<
5367 "firstRow="<<firstRow<< // first and the last row with cluster
5368 "lastRow="<<lastRow<< //
5372 // remove track with lower quality
5374 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
5375 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
5379 MarkSeedFree( array->RemoveAt(index1) );
5384 // 4. Delete temporary array
5394 void AliTPCtracker::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
5397 // find Curling tracks
5398 // Use AliTPCReconstructor::StreamLevel()&kStreamFindCurling if you want to tune parameters - cuts
5401 // Algorithm done in 2 phases - because of CPU consumption
5402 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
5403 // see detal in MC part what can be used to cut
5407 const Float_t kMaxC = 400; // maximal curvature to of the track
5408 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
5409 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
5410 const Float_t kPtRatio = 0.3; // ratio between pt
5411 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
5414 // Curling tracks cuts
5417 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
5418 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
5419 const Float_t kMinAngle = 2.9; // angle between tracks
5420 const Float_t kMaxDist = 5; // biggest distance
5422 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
5425 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
5426 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
5427 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
5428 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
5429 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
5431 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
5432 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
5434 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
5435 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
5437 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
5443 Int_t nentries = array->GetEntriesFast();
5444 AliHelix *helixes = new AliHelix[nentries];
5445 for (Int_t i=0;i<nentries;i++){
5446 AliTPCseed* track = (AliTPCseed*)array->At(i);
5447 if (!track) continue;
5448 track->SetCircular(0);
5449 new (&helixes[i]) AliHelix(*track);
5455 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5461 for (Int_t i0=0;i0<nentries;i0++){
5462 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5463 if (!track0) continue;
5464 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
5465 Float_t xc0 = helixes[i0].GetHelix(6);
5466 Float_t yc0 = helixes[i0].GetHelix(7);
5467 Float_t r0 = helixes[i0].GetHelix(8);
5468 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
5469 Float_t fi0 = TMath::ATan2(yc0,xc0);
5471 for (Int_t i1=i0+1;i1<nentries;i1++){
5472 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5473 if (!track1) continue;
5474 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
5475 Float_t xc1 = helixes[i1].GetHelix(6);
5476 Float_t yc1 = helixes[i1].GetHelix(7);
5477 Float_t r1 = helixes[i1].GetHelix(8);
5478 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
5479 Float_t fi1 = TMath::ATan2(yc1,xc1);
5481 Float_t dfi = fi0-fi1;
5484 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
5485 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
5486 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
5490 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
5491 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
5492 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
5493 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
5494 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
5496 Float_t pt0 = track0->GetSignedPt();
5497 Float_t pt1 = track1->GetSignedPt();
5498 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
5499 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
5500 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
5501 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
5504 // Now find closest approach
5508 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5509 if (npoints==0) continue;
5510 helixes[i0].GetClosestPhases(helixes[i1], phase);
5514 Double_t hangles[3];
5515 helixes[i0].Evaluate(phase[0][0],xyz0);
5516 helixes[i1].Evaluate(phase[0][1],xyz1);
5518 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5519 Double_t deltah[2],deltabest;
5520 if (TMath::Abs(hangles[2])<kMinAngle) continue;
5524 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5526 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5527 if (deltah[1]<deltah[0]) ibest=1;
5529 deltabest = TMath::Sqrt(deltah[ibest]);
5530 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5531 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5532 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5533 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5535 if (deltabest>kMaxDist) continue;
5536 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
5537 Bool_t sign =kFALSE;
5538 if (hangles[2]>kMinAngle) sign =kTRUE;
5541 // circular[i0] = kTRUE;
5542 // circular[i1] = kTRUE;
5543 if (track0->OneOverPt()<track1->OneOverPt()){
5544 track0->SetCircular(track0->GetCircular()+1);
5545 track1->SetCircular(track1->GetCircular()+2);
5548 track1->SetCircular(track1->GetCircular()+1);
5549 track0->SetCircular(track0->GetCircular()+2);
5552 if ((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0){ // flag: stream track infroamtion if the FindCurling tracks method
5554 //debug stream to tune "fine" cuts
5555 Int_t lab0=track0->GetLabel();
5556 Int_t lab1=track1->GetLabel();
5557 TTreeSRedirector &cstream = *fDebugStreamer;
5558 cstream<<"Curling2"<<
5574 "npoints="<<npoints<<
5575 "hangles0="<<hangles[0]<<
5576 "hangles1="<<hangles[1]<<
5577 "hangles2="<<hangles[2]<<
5580 "radius="<<radiusbest<<
5581 "deltabest="<<deltabest<<
5582 "phase0="<<phase[ibest][0]<<
5583 "phase1="<<phase[ibest][1]<<
5591 if (AliTPCReconstructor::StreamLevel()>1) {
5592 AliInfo("Time for curling tracks removal");
5598 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
5604 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
5607 TObjArray *kinks= new TObjArray(10000);
5608 // TObjArray *v0s= new TObjArray(10000);
5609 Int_t nentries = array->GetEntriesFast();
5610 AliHelix *helixes = new AliHelix[nentries];
5611 Int_t *sign = new Int_t[nentries];
5612 Int_t *nclusters = new Int_t[nentries];
5613 Float_t *alpha = new Float_t[nentries];
5614 AliKink *kink = new AliKink();
5615 Int_t * usage = new Int_t[nentries];
5616 Float_t *zm = new Float_t[nentries];
5617 Float_t *z0 = new Float_t[nentries];
5618 Float_t *fim = new Float_t[nentries];
5619 Float_t *shared = new Float_t[nentries];
5620 Bool_t *circular = new Bool_t[nentries];
5621 Float_t *dca = new Float_t[nentries];
5622 //const AliESDVertex * primvertex = esd->GetVertex();
5624 // nentries = array->GetEntriesFast();
5629 for (Int_t i=0;i<nentries;i++){
5632 AliTPCseed* track = (AliTPCseed*)array->At(i);
5633 if (!track) continue;
5634 track->SetCircular(0);
5636 track->UpdatePoints();
5637 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5639 nclusters[i]=track->GetNumberOfClusters();
5640 alpha[i] = track->GetAlpha();
5641 new (&helixes[i]) AliHelix(*track);
5643 helixes[i].Evaluate(0,xyz);
5644 sign[i] = (track->GetC()>0) ? -1:1;
5647 if (track->GetProlongation(x,y,z)){
5649 fim[i] = alpha[i]+TMath::ATan2(y,x);
5652 zm[i] = track->GetZ();
5656 circular[i]= kFALSE;
5657 if (track->GetProlongation(0,y,z)) z0[i] = z;
5658 dca[i] = track->GetD(0,0);
5664 Int_t ncandidates =0;
5667 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5670 // Find circling track
5672 for (Int_t i0=0;i0<nentries;i0++){
5673 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5674 if (!track0) continue;
5675 if (track0->GetNumberOfClusters()<40) continue;
5676 if (TMath::Abs(1./track0->GetC())>200) continue;
5677 for (Int_t i1=i0+1;i1<nentries;i1++){
5678 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5679 if (!track1) continue;
5680 if (track1->GetNumberOfClusters()<40) continue;
5681 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5682 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5683 if (TMath::Abs(1./track1->GetC())>200) continue;
5684 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5685 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5686 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5687 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5688 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5690 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5691 if (mindcar<5) continue;
5692 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5693 if (mindcaz<5) continue;
5694 if (mindcar+mindcaz<20) continue;
5697 Float_t xc0 = helixes[i0].GetHelix(6);
5698 Float_t yc0 = helixes[i0].GetHelix(7);
5699 Float_t r0 = helixes[i0].GetHelix(8);
5700 Float_t xc1 = helixes[i1].GetHelix(6);
5701 Float_t yc1 = helixes[i1].GetHelix(7);
5702 Float_t r1 = helixes[i1].GetHelix(8);
5704 Float_t rmean = (r0+r1)*0.5;
5705 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5706 //if (delta>30) continue;
5707 if (delta>rmean*0.25) continue;
5708 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5710 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5711 if (npoints==0) continue;
5712 helixes[i0].GetClosestPhases(helixes[i1], phase);
5716 Double_t hangles[3];
5717 helixes[i0].Evaluate(phase[0][0],xyz0);
5718 helixes[i1].Evaluate(phase[0][1],xyz1);
5720 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5721 Double_t deltah[2],deltabest;
5722 if (hangles[2]<2.8) continue;
5725 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5727 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5728 if (deltah[1]<deltah[0]) ibest=1;
5730 deltabest = TMath::Sqrt(deltah[ibest]);
5731 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5732 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5733 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5734 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5736 if (deltabest>6) continue;
5737 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5738 Bool_t lsign =kFALSE;
5739 if (hangles[2]>3.06) lsign =kTRUE;
5742 circular[i0] = kTRUE;
5743 circular[i1] = kTRUE;
5744 if (track0->OneOverPt()<track1->OneOverPt()){
5745 track0->SetCircular(track0->GetCircular()+1);
5746 track1->SetCircular(track1->GetCircular()+2);
5749 track1->SetCircular(track1->GetCircular()+1);
5750 track0->SetCircular(track0->GetCircular()+2);
5753 if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindCurling)>0)){
5755 Int_t lab0=track0->GetLabel();
5756 Int_t lab1=track1->GetLabel();
5757 TTreeSRedirector &cstream = *fDebugStreamer;
5758 cstream<<"Curling"<<
5765 "mindcar="<<mindcar<<
5766 "mindcaz="<<mindcaz<<
5769 "npoints="<<npoints<<
5770 "hangles0="<<hangles[0]<<
5771 "hangles2="<<hangles[2]<<
5776 "radius="<<radiusbest<<
5777 "deltabest="<<deltabest<<
5778 "phase0="<<phase[ibest][0]<<
5779 "phase1="<<phase[ibest][1]<<
5789 for (Int_t i =0;i<nentries;i++){
5790 if (sign[i]==0) continue;
5791 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5798 Double_t cradius0 = 40*40;
5799 Double_t cradius1 = 270*270;
5802 Double_t cdist3=0.55;
5803 for (Int_t j =i+1;j<nentries;j++){
5805 if (sign[j]*sign[i]<1) continue;
5806 if ( (nclusters[i]+nclusters[j])>200) continue;
5807 if ( (nclusters[i]+nclusters[j])<80) continue;
5808 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5809 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5810 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5811 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5812 if (npoints<1) continue;
5815 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5818 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5821 Double_t delta1=10000,delta2=10000;
5822 // cuts on the intersection radius
5823 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5824 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5825 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5827 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5828 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5829 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5832 Double_t distance1 = TMath::Min(delta1,delta2);
5833 if (distance1>cdist1) continue; // cut on DCA linear approximation
5835 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5836 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5837 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5838 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5841 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5842 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5843 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5845 distance1 = TMath::Min(delta1,delta2);
5848 rkink = TMath::Sqrt(radius[0]);
5851 rkink = TMath::Sqrt(radius[1]);
5853 if (distance1>cdist2) continue;
5856 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5859 Int_t row0 = GetRowNumber(rkink);
5860 if (row0<10) continue;
5861 if (row0>150) continue;
5864 Float_t dens00=-1,dens01=-1;
5865 Float_t dens10=-1,dens11=-1;
5867 Int_t found,foundable,ishared;
5868 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5869 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5870 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5871 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5873 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5874 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5875 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5876 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5878 if (dens00<dens10 && dens01<dens11) continue;
5879 if (dens00>dens10 && dens01>dens11) continue;
5880 if (TMath::Max(dens00,dens10)<0.1) continue;
5881 if (TMath::Max(dens01,dens11)<0.3) continue;
5883 if (TMath::Min(dens00,dens10)>0.6) continue;
5884 if (TMath::Min(dens01,dens11)>0.6) continue;
5887 AliTPCseed * ktrack0, *ktrack1;
5896 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5897 AliExternalTrackParam paramm(*ktrack0);
5898 AliExternalTrackParam paramd(*ktrack1);
5899 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5902 kink->SetMother(paramm);
5903 kink->SetDaughter(paramd);
5906 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])};
5908 fkParam->Transform0to1(x,index);
5909 fkParam->Transform1to2(x,index);
5910 row0 = GetRowNumber(x[0]);
5912 if (kink->GetR()<100) continue;
5913 if (kink->GetR()>240) continue;
5914 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5915 if (kink->GetDistance()>cdist3) continue;
5916 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5917 if (dird<0) continue;
5919 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5920 if (dirm<0) continue;
5921 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5922 if (mpt<0.2) continue;
5925 //for high momenta momentum not defined well in first iteration
5926 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5927 if (qt>0.35) continue;
5930 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5931 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5933 kink->SetTPCDensity(dens00,0,0);
5934 kink->SetTPCDensity(dens01,0,1);
5935 kink->SetTPCDensity(dens10,1,0);
5936 kink->SetTPCDensity(dens11,1,1);
5937 kink->SetIndex(i,0);
5938 kink->SetIndex(j,1);
5941 kink->SetTPCDensity(dens10,0,0);
5942 kink->SetTPCDensity(dens11,0,1);
5943 kink->SetTPCDensity(dens00,1,0);
5944 kink->SetTPCDensity(dens01,1,1);
5945 kink->SetIndex(j,0);
5946 kink->SetIndex(i,1);
5949 if (mpt<1||kink->GetAngle(2)>0.1){
5950 // angle and densities not defined yet
5951 if (kink->GetTPCDensityFactor()<0.8) continue;
5952 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5953 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5954 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5955 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5957 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5958 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5959 criticalangle= 3*TMath::Sqrt(criticalangle);
5960 if (criticalangle>0.02) criticalangle=0.02;
5961 if (kink->GetAngle(2)<criticalangle) continue;
5964 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5965 Float_t shapesum =0;
5967 for ( Int_t row = row0-drow; row<row0+drow;row++){
5968 if (row<0) continue;
5969 if (row>155) continue;
5970 if (ktrack0->GetClusterPointer(row)){
5971 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5972 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5975 if (ktrack1->GetClusterPointer(row)){
5976 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5977 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5982 kink->SetShapeFactor(-1.);
5985 kink->SetShapeFactor(shapesum/sum);
5987 // esd->AddKink(kink);
5989 // kink->SetMother(paramm);
5990 //kink->SetDaughter(paramd);
5992 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5994 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5995 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5997 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5999 if ((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0) { // flag: stream track infroamtion in the FindKinks method
6000 (*fDebugStreamer)<<"kinkLpt"<<
6008 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6012 kinks->AddLast(kink);
6018 // sort the kinks according quality - and refit them towards vertex
6020 Int_t nkinks = kinks->GetEntriesFast();
6021 Float_t *quality = new Float_t[nkinks];
6022 Int_t *indexes = new Int_t[nkinks];
6023 AliTPCseed *mothers = new AliTPCseed[nkinks];
6024 AliTPCseed *daughters = new AliTPCseed[nkinks];
6027 for (Int_t i=0;i<nkinks;i++){
6029 AliKink *kinkl = (AliKink*)kinks->At(i);
6031 // refit kinks towards vertex
6033 Int_t index0 = kinkl->GetIndex(0);
6034 Int_t index1 = kinkl->GetIndex(1);
6035 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6036 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6038 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6040 // Refit Kink under if too small angle
6042 if (kinkl->GetAngle(2)<0.05){
6043 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6044 Int_t row0 = kinkl->GetTPCRow0();
6045 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6048 Int_t last = row0-drow;
6049 if (last<40) last=40;
6050 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6051 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6054 Int_t first = row0+drow;
6055 if (first>130) first=130;
6056 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6057 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6059 if (seed0 && seed1){
6060 kinkl->SetStatus(1,8);
6061 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6062 row0 = GetRowNumber(kinkl->GetR());
6063 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6064 mothers[i] = *seed0;
6065 daughters[i] = *seed1;
6068 delete kinks->RemoveAt(i);
6069 if (seed0) MarkSeedFree( seed0 );
6070 if (seed1) MarkSeedFree( seed1 );
6073 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6074 delete kinks->RemoveAt(i);
6075 if (seed0) MarkSeedFree( seed0 );
6076 if (seed1) MarkSeedFree( seed1 );
6080 MarkSeedFree( seed0 );
6081 MarkSeedFree( seed1 );
6084 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6086 TMath::Sort(nkinks,quality,indexes,kFALSE);
6088 //remove double find kinks
6090 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6091 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6092 if (!kink0) continue;
6094 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6095 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6096 if (!kink0) continue;
6097 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6098 if (!kink1) continue;
6099 // if not close kink continue
6100 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6101 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6102 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6104 AliTPCseed &mother0 = mothers[indexes[ikink0]];
6105 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
6106 AliTPCseed &mother1 = mothers[indexes[ikink1]];
6107 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
6108 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6117 for (Int_t i=0;i<row0;i++){
6118 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6121 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6128 for (Int_t i=row0;i<158;i++){
6129 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6130 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6133 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6139 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6140 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6141 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6142 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6143 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6144 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6146 shared[kink0->GetIndex(0)]= kTRUE;
6147 shared[kink0->GetIndex(1)]= kTRUE;
6148 delete kinks->RemoveAt(indexes[ikink0]);
6152 shared[kink1->GetIndex(0)]= kTRUE;
6153 shared[kink1->GetIndex(1)]= kTRUE;
6154 delete kinks->RemoveAt(indexes[ikink1]);
6161 for (Int_t i=0;i<nkinks;i++){
6162 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6163 if (!kinkl) continue;
6164 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6165 Int_t index0 = kinkl->GetIndex(0);
6166 Int_t index1 = kinkl->GetIndex(1);
6167 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6168 kinkl->SetMultiple(usage[index0],0);
6169 kinkl->SetMultiple(usage[index1],1);
6170 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6171 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6172 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6173 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6175 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6176 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6177 if (!ktrack0 || !ktrack1) continue;
6178 Int_t index = esd->AddKink(kinkl);
6181 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6182 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
6183 *ktrack0 = mothers[indexes[i]];
6184 *ktrack1 = daughters[indexes[i]];
6188 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6189 ktrack1->SetKinkIndex(usage[index1], (index+1));
6194 // Remove tracks corresponding to shared kink's
6196 for (Int_t i=0;i<nentries;i++){
6197 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6198 if (!track0) continue;
6199 if (track0->GetKinkIndex(0)!=0) continue;
6200 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6205 RemoveUsed2(array,0.5,0.4,30);
6207 for (Int_t i=0;i<nentries;i++){
6208 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6209 if (!track0) continue;
6210 track0->CookdEdx(0.02,0.6);
6214 for (Int_t i=0;i<nentries;i++){
6215 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6216 if (!track0) continue;
6217 if (track0->Pt()<1.4) continue;
6218 //remove double high momenta tracks - overlapped with kink candidates
6221 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6222 if (track0->GetClusterPointer(icl)!=0){
6224 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6227 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6228 MarkSeedFree( array->RemoveAt(i) );
6232 if (track0->GetKinkIndex(0)!=0) continue;
6233 if (track0->GetNumberOfClusters()<80) continue;
6235 AliTPCseed *pmother = new AliTPCseed();
6236 AliTPCseed *pdaughter = new AliTPCseed();
6237 AliKink *pkink = new AliKink;
6239 AliTPCseed & mother = *pmother;
6240 AliTPCseed & daughter = *pdaughter;
6241 AliKink & kinkl = *pkink;
6242 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6243 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6247 continue; //too short tracks
6249 if (mother.Pt()<1.4) {
6255 Int_t row0= kinkl.GetTPCRow0();
6256 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6263 Int_t index = esd->AddKink(&kinkl);
6264 mother.SetKinkIndex(0,-(index+1));
6265 daughter.SetKinkIndex(0,index+1);
6266 if (mother.GetNumberOfClusters()>50) {
6267 MarkSeedFree( array->RemoveAt(i) );
6268 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6269 mtc->SetPoolID(fLastSeedID);
6270 array->AddAt(mtc,i);
6273 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6274 mtc->SetPoolID(fLastSeedID);
6275 array->AddLast(mtc);
6277 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6278 dtc->SetPoolID(fLastSeedID);
6279 array->AddLast(dtc);
6280 for (Int_t icl=0;icl<row0;icl++) {
6281 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6284 for (Int_t icl=row0;icl<158;icl++) {
6285 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6294 delete [] daughters;
6316 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6322 void AliTPCtracker::FindKinks(TObjArray * array, AliESDEvent *esd)
6329 TObjArray *kinks= new TObjArray(10000);
6330 // TObjArray *v0s= new TObjArray(10000);
6331 Int_t nentries = array->GetEntriesFast();
6332 AliHelix *helixes = new AliHelix[nentries];
6333 Int_t *sign = new Int_t[nentries];
6334 Int_t *nclusters = new Int_t[nentries];
6335 Float_t *alpha = new Float_t[nentries];
6336 AliKink *kink = new AliKink();
6337 Int_t * usage = new Int_t[nentries];
6338 Float_t *zm = new Float_t[nentries];
6339 Float_t *z0 = new Float_t[nentries];
6340 Float_t *fim = new Float_t[nentries];
6341 Float_t *shared = new Float_t[nentries];
6342 Bool_t *circular = new Bool_t[nentries];
6343 Float_t *dca = new Float_t[nentries];
6344 //const AliESDVertex * primvertex = esd->GetVertex();
6346 // nentries = array->GetEntriesFast();
6351 for (Int_t i=0;i<nentries;i++){
6354 AliTPCseed* track = (AliTPCseed*)array->At(i);
6355 if (!track) continue;
6356 track->SetCircular(0);
6358 track->UpdatePoints();
6359 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
6361 nclusters[i]=track->GetNumberOfClusters();
6362 alpha[i] = track->GetAlpha();
6363 new (&helixes[i]) AliHelix(*track);
6365 helixes[i].Evaluate(0,xyz);
6366 sign[i] = (track->GetC()>0) ? -1:1;
6369 if (track->GetProlongation(x,y,z)){
6371 fim[i] = alpha[i]+TMath::ATan2(y,x);
6374 zm[i] = track->GetZ();
6378 circular[i]= kFALSE;
6379 if (track->GetProlongation(0,y,z)) z0[i] = z;
6380 dca[i] = track->GetD(0,0);
6386 Int_t ncandidates =0;
6389 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
6392 // Find circling track
6394 for (Int_t i0=0;i0<nentries;i0++){
6395 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
6396 if (!track0) continue;
6397 if (track0->GetNumberOfClusters()<40) continue;
6398 if (TMath::Abs(1./track0->GetC())>200) continue;
6399 for (Int_t i1=i0+1;i1<nentries;i1++){
6400 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
6401 if (!track1) continue;
6402 if (track1->GetNumberOfClusters()<40) continue;
6403 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
6404 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
6405 if (TMath::Abs(1./track1->GetC())>200) continue;
6406 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
6407 if (track1->GetTgl()*track0->GetTgl()>0) continue;
6408 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
6409 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
6410 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
6412 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
6413 if (mindcar<5) continue;
6414 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
6415 if (mindcaz<5) continue;
6416 if (mindcar+mindcaz<20) continue;
6419 Float_t xc0 = helixes[i0].GetHelix(6);
6420 Float_t yc0 = helixes[i0].GetHelix(7);
6421 Float_t r0 = helixes[i0].GetHelix(8);
6422 Float_t xc1 = helixes[i1].GetHelix(6);
6423 Float_t yc1 = helixes[i1].GetHelix(7);
6424 Float_t r1 = helixes[i1].GetHelix(8);
6426 Float_t rmean = (r0+r1)*0.5;
6427 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
6428 //if (delta>30) continue;
6429 if (delta>rmean*0.25) continue;
6430 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
6432 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
6433 if (npoints==0) continue;
6434 helixes[i0].GetClosestPhases(helixes[i1], phase);
6438 Double_t hangles[3];
6439 helixes[i0].Evaluate(phase[0][0],xyz0);
6440 helixes[i1].Evaluate(phase[0][1],xyz1);
6442 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
6443 Double_t deltah[2],deltabest;
6444 if (hangles[2]<2.8) continue;
6447 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
6449 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
6450 if (deltah[1]<deltah[0]) ibest=1;
6452 deltabest = TMath::Sqrt(deltah[ibest]);
6453 helixes[i0].Evaluate(phase[ibest][0],xyz0);
6454 helixes[i1].Evaluate(phase[ibest][1],xyz1);
6455 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
6456 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
6458 if (deltabest>6) continue;
6459 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
6460 Bool_t lsign =kFALSE;
6461 if (hangles[2]>3.06) lsign =kTRUE;
6464 circular[i0] = kTRUE;
6465 circular[i1] = kTRUE;
6466 if (track0->OneOverPt()<track1->OneOverPt()){
6467 track0->SetCircular(track0->GetCircular()+1);
6468 track1->SetCircular(track1->GetCircular()+2);
6471 track1->SetCircular(track1->GetCircular()+1);
6472 track0->SetCircular(track0->GetCircular()+2);
6475 if (lsign&&((AliTPCReconstructor::StreamLevel()&kStreamFindKinks)>0)){// flag: stream track infroamtion in the FindKinks method
6477 Int_t lab0=track0->GetLabel();
6478 Int_t lab1=track1->GetLabel();
6479 TTreeSRedirector &cstream = *fDebugStreamer;
6480 cstream<<"Curling"<<
6487 "mindcar="<<mindcar<<
6488 "mindcaz="<<mindcaz<<
6491 "npoints="<<npoints<<
6492 "hangles0="<<hangles[0]<<
6493 "hangles2="<<hangles[2]<<
6498 "radius="<<radiusbest<<
6499 "deltabest="<<deltabest<<
6500 "phase0="<<phase[ibest][0]<<
6501 "phase1="<<phase[ibest][1]<<
6511 for (Int_t i =0;i<nentries;i++){
6512 if (sign[i]==0) continue;
6513 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6520 Double_t cradius0 = 40*40;
6521 Double_t cradius1 = 270*270;
6524 Double_t cdist3=0.55;
6525 for (Int_t j =i+1;j<nentries;j++){
6527 if (sign[j]*sign[i]<1) continue;
6528 if ( (nclusters[i]+nclusters[j])>200) continue;
6529 if ( (nclusters[i]+nclusters[j])<80) continue;
6530 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
6531 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
6532 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
6533 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6534 if (npoints<1) continue;
6537 if (radius[0]<cradius0||radius[0]>cradius1) continue;
6540 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
6543 Double_t delta1=10000,delta2=10000;
6544 // cuts on the intersection radius
6545 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6546 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6547 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6549 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6550 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6551 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6554 Double_t distance1 = TMath::Min(delta1,delta2);
6555 if (distance1>cdist1) continue; // cut on DCA linear approximation
6557 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
6558 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
6559 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
6560 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
6563 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
6564 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
6565 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
6567 distance1 = TMath::Min(delta1,delta2);
6570 rkink = TMath::Sqrt(radius[0]);
6573 rkink = TMath::Sqrt(radius[1]);
6575 if (distance1>cdist2) continue;
6578 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
6581 Int_t row0 = GetRowNumber(rkink);
6582 if (row0<10) continue;
6583 if (row0>150) continue;
6586 Float_t dens00=-1,dens01=-1;
6587 Float_t dens10=-1,dens11=-1;
6589 Int_t found,foundable,ishared;
6590 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6591 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
6592 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6593 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
6595 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
6596 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
6597 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
6598 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
6600 if (dens00<dens10 && dens01<dens11) continue;
6601 if (dens00>dens10 && dens01>dens11) continue;
6602 if (TMath::Max(dens00,dens10)<0.1) continue;
6603 if (TMath::Max(dens01,dens11)<0.3) continue;
6605 if (TMath::Min(dens00,dens10)>0.6) continue;
6606 if (TMath::Min(dens01,dens11)>0.6) continue;
6609 AliTPCseed * ktrack0, *ktrack1;
6618 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
6619 AliExternalTrackParam paramm(*ktrack0);
6620 AliExternalTrackParam paramd(*ktrack1);
6621 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
6624 kink->SetMother(paramm);
6625 kink->SetDaughter(paramd);
6628 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])};
6630 fkParam->Transform0to1(x,index);
6631 fkParam->Transform1to2(x,index);
6632 row0 = GetRowNumber(x[0]);
6634 if (kink->GetR()<100) continue;
6635 if (kink->GetR()>240) continue;
6636 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
6637 if (kink->GetDistance()>cdist3) continue;
6638 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
6639 if (dird<0) continue;
6641 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
6642 if (dirm<0) continue;
6643 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
6644 if (mpt<0.2) continue;
6647 //for high momenta momentum not defined well in first iteration
6648 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
6649 if (qt>0.35) continue;
6652 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
6653 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
6655 kink->SetTPCDensity(dens00,0,0);
6656 kink->SetTPCDensity(dens01,0,1);
6657 kink->SetTPCDensity(dens10,1,0);
6658 kink->SetTPCDensity(dens11,1,1);
6659 kink->SetIndex(i,0);
6660 kink->SetIndex(j,1);
6663 kink->SetTPCDensity(dens10,0,0);
6664 kink->SetTPCDensity(dens11,0,1);
6665 kink->SetTPCDensity(dens00,1,0);
6666 kink->SetTPCDensity(dens01,1,1);
6667 kink->SetIndex(j,0);
6668 kink->SetIndex(i,1);
6671 if (mpt<1||kink->GetAngle(2)>0.1){
6672 // angle and densities not defined yet
6673 if (kink->GetTPCDensityFactor()<0.8) continue;
6674 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
6675 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
6676 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
6677 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
6679 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
6680 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
6681 criticalangle= 3*TMath::Sqrt(criticalangle);
6682 if (criticalangle>0.02) criticalangle=0.02;
6683 if (kink->GetAngle(2)<criticalangle) continue;
6686 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
6687 Float_t shapesum =0;
6689 for ( Int_t row = row0-drow; row<row0+drow;row++){
6690 if (row<0) continue;
6691 if (row>155) continue;
6692 if (ktrack0->GetClusterPointer(row)){
6693 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
6694 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6697 if (ktrack1->GetClusterPointer(row)){
6698 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
6699 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
6704 kink->SetShapeFactor(-1.);
6707 kink->SetShapeFactor(shapesum/sum);
6709 // esd->AddKink(kink);
6711 // kink->SetMother(paramm);
6712 //kink->SetDaughter(paramd);
6714 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
6716 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
6717 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
6719 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
6721 if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) {// flag: stream track infroamtion in the FindKinks method
6722 (*fDebugStreamer)<<"kinkLpt"<<
6730 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6734 kinks->AddLast(kink);
6740 // sort the kinks according quality - and refit them towards vertex
6742 Int_t nkinks = kinks->GetEntriesFast();
6743 Float_t *quality = new Float_t[nkinks];
6744 Int_t *indexes = new Int_t[nkinks];
6745 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
6746 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
6749 for (Int_t i=0;i<nkinks;i++){
6751 AliKink *kinkl = (AliKink*)kinks->At(i);
6753 // refit kinks towards vertex
6755 Int_t index0 = kinkl->GetIndex(0);
6756 Int_t index1 = kinkl->GetIndex(1);
6757 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6758 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6760 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
6762 // Refit Kink under if too small angle
6764 if (kinkl->GetAngle(2)<0.05){
6765 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6766 Int_t row0 = kinkl->GetTPCRow0();
6767 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
6770 Int_t last = row0-drow;
6771 if (last<40) last=40;
6772 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
6773 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
6776 Int_t first = row0+drow;
6777 if (first>130) first=130;
6778 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
6779 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
6781 if (seed0 && seed1){
6782 kinkl->SetStatus(1,8);
6783 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
6784 row0 = GetRowNumber(kinkl->GetR());
6785 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
6786 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
6787 mothers[i]->SetPoolID(fLastSeedID);
6788 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
6789 daughters[i]->SetPoolID(fLastSeedID);
6792 delete kinks->RemoveAt(i);
6793 if (seed0) MarkSeedFree( seed0 );
6794 if (seed1) MarkSeedFree( seed1 );
6797 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6798 delete kinks->RemoveAt(i);
6799 if (seed0) MarkSeedFree( seed0 );
6800 if (seed1) MarkSeedFree( seed1 );
6804 MarkSeedFree( seed0 );
6805 MarkSeedFree( seed1 );
6808 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6810 TMath::Sort(nkinks,quality,indexes,kFALSE);
6812 //remove double find kinks
6814 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6815 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6816 if (!kink0) continue;
6818 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6819 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6820 if (!kink0) continue;
6821 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6822 if (!kink1) continue;
6823 // if not close kink continue
6824 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6825 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6826 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6828 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6829 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6830 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6831 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6832 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6841 for (Int_t i=0;i<row0;i++){
6842 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6845 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6852 for (Int_t i=row0;i<158;i++){
6853 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6854 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6857 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6863 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6864 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6865 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6866 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6867 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6868 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6870 shared[kink0->GetIndex(0)]= kTRUE;
6871 shared[kink0->GetIndex(1)]= kTRUE;
6872 delete kinks->RemoveAt(indexes[ikink0]);
6876 shared[kink1->GetIndex(0)]= kTRUE;
6877 shared[kink1->GetIndex(1)]= kTRUE;
6878 delete kinks->RemoveAt(indexes[ikink1]);
6885 for (Int_t i=0;i<nkinks;i++){
6886 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6887 if (!kinkl) continue;
6888 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6889 Int_t index0 = kinkl->GetIndex(0);
6890 Int_t index1 = kinkl->GetIndex(1);
6891 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6892 kinkl->SetMultiple(usage[index0],0);
6893 kinkl->SetMultiple(usage[index1],1);
6894 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6895 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6896 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6897 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6899 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6900 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6901 if (!ktrack0 || !ktrack1) continue;
6902 Int_t index = esd->AddKink(kinkl);
6905 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6906 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6907 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6908 *ktrack0 = *mothers[indexes[i]];
6909 *ktrack1 = *daughters[indexes[i]];
6913 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6914 ktrack1->SetKinkIndex(usage[index1], (index+1));
6919 // Remove tracks corresponding to shared kink's
6921 for (Int_t i=0;i<nentries;i++){
6922 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6923 if (!track0) continue;
6924 if (track0->GetKinkIndex(0)!=0) continue;
6925 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6930 RemoveUsed2(array,0.5,0.4,30);
6932 for (Int_t i=0;i<nentries;i++){
6933 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6934 if (!track0) continue;
6935 track0->CookdEdx(0.02,0.6);
6939 for (Int_t i=0;i<nentries;i++){
6940 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6941 if (!track0) continue;
6942 if (track0->Pt()<1.4) continue;
6943 //remove double high momenta tracks - overlapped with kink candidates
6946 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6947 if (track0->GetClusterPointer(icl)!=0){
6949 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6952 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6953 MarkSeedFree( array->RemoveAt(i) );
6957 if (track0->GetKinkIndex(0)!=0) continue;
6958 if (track0->GetNumberOfClusters()<80) continue;
6960 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6961 pmother->SetPoolID(fLastSeedID);
6962 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6963 pdaughter->SetPoolID(fLastSeedID);
6964 AliKink *pkink = new AliKink;
6966 AliTPCseed & mother = *pmother;
6967 AliTPCseed & daughter = *pdaughter;
6968 AliKink & kinkl = *pkink;
6969 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6970 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6971 MarkSeedFree( pmother );
6972 MarkSeedFree( pdaughter );
6974 continue; //too short tracks
6976 if (mother.Pt()<1.4) {
6977 MarkSeedFree( pmother );
6978 MarkSeedFree( pdaughter );
6982 Int_t row0= kinkl.GetTPCRow0();
6983 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6984 MarkSeedFree( pmother );
6985 MarkSeedFree( pdaughter );
6990 Int_t index = esd->AddKink(&kinkl);
6991 mother.SetKinkIndex(0,-(index+1));
6992 daughter.SetKinkIndex(0,index+1);
6993 if (mother.GetNumberOfClusters()>50) {
6994 MarkSeedFree( array->RemoveAt(i) );
6995 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6996 mtc->SetPoolID(fLastSeedID);
6997 array->AddAt(mtc,i);
7000 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
7001 mtc->SetPoolID(fLastSeedID);
7002 array->AddLast(mtc);
7004 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
7005 dtc->SetPoolID(fLastSeedID);
7006 array->AddLast(dtc);
7007 for (Int_t icl=0;icl<row0;icl++) {
7008 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
7011 for (Int_t icl=row0;icl<158;icl++) {
7012 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
7016 MarkSeedFree( pmother );
7017 MarkSeedFree( pdaughter );
7021 delete [] daughters;
7043 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
7048 Int_t AliTPCtracker::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7051 // refit kink towards to the vertex
7054 AliKink &kink=(AliKink &)knk;
7056 Int_t row0 = GetRowNumber(kink.GetR());
7057 FollowProlongation(mother,0);
7058 mother.Reset(kFALSE);
7060 FollowProlongation(daughter,row0);
7061 daughter.Reset(kFALSE);
7062 FollowBackProlongation(daughter,158);
7063 daughter.Reset(kFALSE);
7064 Int_t first = TMath::Max(row0-20,30);
7065 Int_t last = TMath::Min(row0+20,140);
7067 const Int_t kNdiv =5;
7068 AliTPCseed param0[kNdiv]; // parameters along the track
7069 AliTPCseed param1[kNdiv]; // parameters along the track
7070 AliKink kinks[kNdiv]; // corresponding kink parameters
7073 for (Int_t irow=0; irow<kNdiv;irow++){
7074 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
7076 // store parameters along the track
7078 for (Int_t irow=0;irow<kNdiv;irow++){
7079 FollowBackProlongation(mother, rows[irow]);
7080 FollowProlongation(daughter,rows[kNdiv-1-irow]);
7081 param0[irow] = mother;
7082 param1[kNdiv-1-irow] = daughter;
7086 for (Int_t irow=0; irow<kNdiv-1;irow++){
7087 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
7088 kinks[irow].SetMother(param0[irow]);
7089 kinks[irow].SetDaughter(param1[irow]);
7090 kinks[irow].Update();
7093 // choose kink with best "quality"
7095 Double_t mindist = 10000;
7096 for (Int_t irow=0;irow<kNdiv;irow++){
7097 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
7098 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7099 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
7101 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
7102 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
7103 if (normdist < mindist){
7109 if (index==-1) return 0;
7112 param0[index].Reset(kTRUE);
7113 FollowProlongation(param0[index],0);
7115 mother = param0[index];
7116 daughter = param1[index]; // daughter in vertex
7118 kink.SetMother(mother);
7119 kink.SetDaughter(daughter);
7121 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
7122 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7123 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7124 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
7125 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
7126 mother.SetLabel(kink.GetLabel(0));
7127 daughter.SetLabel(kink.GetLabel(1));
7133 void AliTPCtracker::UpdateKinkQualityM(AliTPCseed * seed){
7135 // update Kink quality information for mother after back propagation
7137 if (seed->GetKinkIndex(0)>=0) return;
7138 for (Int_t ikink=0;ikink<3;ikink++){
7139 Int_t index = seed->GetKinkIndex(ikink);
7140 if (index>=0) break;
7141 index = TMath::Abs(index)-1;
7142 AliESDkink * kink = fEvent->GetKink(index);
7143 kink->SetTPCDensity(-1,0,0);
7144 kink->SetTPCDensity(1,0,1);
7146 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7147 if (row0<15) row0=15;
7149 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7150 if (row1>145) row1=145;
7152 Int_t found,foundable,shared;
7153 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7154 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
7155 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7156 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
7161 void AliTPCtracker::UpdateKinkQualityD(AliTPCseed * seed){
7163 // update Kink quality information for daughter after refit
7165 if (seed->GetKinkIndex(0)<=0) return;
7166 for (Int_t ikink=0;ikink<3;ikink++){
7167 Int_t index = seed->GetKinkIndex(ikink);
7168 if (index<=0) break;
7169 index = TMath::Abs(index)-1;
7170 AliESDkink * kink = fEvent->GetKink(index);
7171 kink->SetTPCDensity(-1,1,0);
7172 kink->SetTPCDensity(-1,1,1);
7174 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7175 if (row0<15) row0=15;
7177 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
7178 if (row1>145) row1=145;
7180 Int_t found,foundable,shared;
7181 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
7182 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
7183 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
7184 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
7190 Int_t AliTPCtracker::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
7193 // check kink point for given track
7194 // if return value=0 kink point not found
7195 // otherwise seed0 correspond to mother particle
7196 // seed1 correspond to daughter particle
7197 // kink parameter of kink point
7198 AliKink &kink=(AliKink &)knk;
7200 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
7201 Int_t first = seed->GetFirstPoint();
7202 Int_t last = seed->GetLastPoint();
7203 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
7206 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
7207 if (!seed1) return 0;
7208 FollowProlongation(*seed1,seed->GetLastPoint()-20);
7209 seed1->Reset(kTRUE);
7210 FollowProlongation(*seed1,158);
7211 seed1->Reset(kTRUE);
7212 last = seed1->GetLastPoint();
7214 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
7215 seed0->SetPoolID(fLastSeedID);
7216 seed0->Reset(kFALSE);
7219 AliTPCseed param0[20]; // parameters along the track
7220 AliTPCseed param1[20]; // parameters along the track
7221 AliKink kinks[20]; // corresponding kink parameters
7223 for (Int_t irow=0; irow<20;irow++){
7224 rows[irow] = first +((last-first)*irow)/19;
7226 // store parameters along the track
7228 for (Int_t irow=0;irow<20;irow++){
7229 FollowBackProlongation(*seed0, rows[irow]);
7230 FollowProlongation(*seed1,rows[19-irow]);
7231 param0[irow] = *seed0;
7232 param1[19-irow] = *seed1;
7236 for (Int_t irow=0; irow<19;irow++){
7237 kinks[irow].SetMother(param0[irow]);
7238 kinks[irow].SetDaughter(param1[irow]);
7239 kinks[irow].Update();
7242 // choose kink with biggest change of angle
7244 Double_t maxchange= 0;
7245 for (Int_t irow=1;irow<19;irow++){
7246 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
7247 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
7248 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7249 if ( quality > maxchange){
7250 maxchange = quality;
7255 MarkSeedFree( seed0 );
7256 MarkSeedFree( seed1 );
7257 if (index<0) return 0;
7259 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
7260 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
7261 seed0->SetPoolID(fLastSeedID);
7262 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
7263 seed1->SetPoolID(fLastSeedID);
7264 seed0->Reset(kFALSE);
7265 seed1->Reset(kFALSE);
7266 seed0->ResetCovariance(10.);
7267 seed1->ResetCovariance(10.);
7268 FollowProlongation(*seed0,0);
7269 FollowBackProlongation(*seed1,158);
7270 mother = *seed0; // backup mother at position 0
7271 seed0->Reset(kFALSE);
7272 seed1->Reset(kFALSE);
7273 seed0->ResetCovariance(10.);
7274 seed1->ResetCovariance(10.);
7276 first = TMath::Max(row0-20,0);
7277 last = TMath::Min(row0+20,158);
7279 for (Int_t irow=0; irow<20;irow++){
7280 rows[irow] = first +((last-first)*irow)/19;
7282 // store parameters along the track
7284 for (Int_t irow=0;irow<20;irow++){
7285 FollowBackProlongation(*seed0, rows[irow]);
7286 FollowProlongation(*seed1,rows[19-irow]);
7287 param0[irow] = *seed0;
7288 param1[19-irow] = *seed1;
7292 for (Int_t irow=0; irow<19;irow++){
7293 kinks[irow].SetMother(param0[irow]);
7294 kinks[irow].SetDaughter(param1[irow]);
7295 // param0[irow].Dump();
7296 //param1[irow].Dump();
7297 kinks[irow].Update();
7300 // choose kink with biggest change of angle
7303 for (Int_t irow=0;irow<20;irow++){
7304 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
7305 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
7306 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
7307 if ( quality > maxchange){
7308 maxchange = quality;
7315 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
7316 MarkSeedFree( seed0 );
7317 MarkSeedFree( seed1 );
7321 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
7323 kink.SetMother(param0[index]);
7324 kink.SetDaughter(param1[index]);
7327 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
7329 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
7330 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
7332 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
7334 if (AliTPCReconstructor::StreamLevel()&kStreamFindKinks) { // flag: stream track infroamtion in the FindKinks method
7335 (*fDebugStreamer)<<"kinkHpt"<<
7338 "p0.="<<¶m0[index]<<
7339 "p1.="<<¶m1[index]<<
7343 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
7344 MarkSeedFree( seed0 );
7345 MarkSeedFree( seed1 );
7350 row0 = GetRowNumber(kink.GetR());
7351 kink.SetTPCRow0(row0);
7352 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
7353 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
7354 kink.SetIndex(-10,0);
7355 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
7356 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
7357 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
7360 // new (&mother) AliTPCseed(param0[index]);
7361 daughter = param1[index];
7362 daughter.SetLabel(kink.GetLabel(1));
7363 param0[index].Reset(kTRUE);
7364 FollowProlongation(param0[index],0);
7365 mother = param0[index];
7366 mother.SetLabel(kink.GetLabel(0));
7367 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
7370 MarkSeedFree( seed0 );
7371 MarkSeedFree( seed1 );
7379 AliTPCseed* AliTPCtracker::ReSeed(AliTPCseed *t)
7382 // reseed - refit - track
7385 // Int_t last = fSectors->GetNRows()-1;
7387 if (fSectors == fOuterSec){
7388 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
7392 first = t->GetFirstPoint();
7394 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
7395 FollowBackProlongation(*t,fSectors->GetNRows()-1);
7397 FollowProlongation(*t,first);
7407 //_____________________________________________________________________________
7408 Int_t AliTPCtracker::ReadSeeds(const TFile *inp) {
7409 //-----------------------------------------------------------------
7410 // This function reades track seeds.
7411 //-----------------------------------------------------------------
7412 TDirectory *savedir=gDirectory;
7414 TFile *in=(TFile*)inp;
7415 if (!in->IsOpen()) {
7416 cerr<<"AliTPCtracker::ReadSeeds(): input file is not open !\n";
7421 TTree *seedTree=(TTree*)in->Get("Seeds");
7423 cerr<<"AliTPCtracker::ReadSeeds(): ";
7424 cerr<<"can't get a tree with track seeds !\n";
7427 AliTPCtrack *seed=new AliTPCtrack;
7428 seedTree->SetBranchAddress("tracks",&seed);
7430 if (fSeeds==0) fSeeds=new TObjArray(15000);
7432 Int_t n=(Int_t)seedTree->GetEntries();
7433 for (Int_t i=0; i<n; i++) {
7434 seedTree->GetEvent(i);
7435 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
7436 sdc->SetPoolID(fLastSeedID);
7437 fSeeds->AddLast(sdc);
7440 delete seed; // RS: this seed is not from the pool, delete it !!!
7446 Int_t AliTPCtracker::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
7449 // clusters to tracks
7450 if (fSeeds) DeleteSeeds();
7451 else ResetSeedsPool();
7453 fEventHLT = hltEvent;
7454 if (AliTPCReconstructor::GetRecoParam()->GetUseOulierClusterFilter()) FilterOutlierClusters();
7455 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
7456 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
7457 transform->SetCurrentRun(esd->GetRunNumber());
7462 if (!fSeeds) return 1;
7464 if ((AliTPCReconstructor::StreamLevel()&kStreamClDump)>0) DumpClusters(0,fSeeds);
7469 Int_t AliTPCtracker::Clusters2Tracks(AliESDEvent *const esd)
7472 // clusters to tracks
7473 return Clusters2TracksHLT( esd, 0);
7476 //_____________________________________________________________________________
7477 Int_t AliTPCtracker::Clusters2Tracks() {
7478 //-----------------------------------------------------------------
7479 // This is a track finder.
7480 //-----------------------------------------------------------------
7481 TDirectory *savedir=gDirectory;
7485 fSeeds = Tracking();
7488 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
7490 //activate again some tracks
7491 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
7492 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7494 Int_t nc=t.GetNumberOfClusters();
7496 MarkSeedFree( fSeeds->RemoveAt(i) );
7500 if (pt->GetRemoval()==10) {
7501 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7502 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
7504 pt->Desactivate(20);
7505 MarkSeedFree( fSeeds->RemoveAt(i) );
7510 RemoveUsed2(fSeeds,0.85,0.85,0);
7511 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
7512 //FindCurling(fSeeds, fEvent,0);
7513 if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
7514 RemoveUsed2(fSeeds,0.5,0.4,20);
7515 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
7516 if (AliTPCReconstructor::StreamLevel()&kStreamFindMultiMC) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
7519 // // refit short tracks
7521 Int_t nseed=fSeeds->GetEntriesFast();
7524 for (Int_t i=0; i<nseed; i++) {
7525 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7527 Int_t nc=t.GetNumberOfClusters();
7529 MarkSeedFree( fSeeds->RemoveAt(i) );
7532 CookLabel(pt,0.1); //For comparison only
7533 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7534 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7536 if (fDebug>0) cerr<<found<<'\r';
7540 MarkSeedFree( fSeeds->RemoveAt(i) );
7544 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
7546 //RemoveUsed(fSeeds,0.9,0.9,6);
7548 nseed=fSeeds->GetEntriesFast();
7550 for (Int_t i=0; i<nseed; i++) {
7551 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7553 Int_t nc=t.GetNumberOfClusters();
7555 MarkSeedFree( fSeeds->RemoveAt(i) );
7559 t.CookdEdx(0.02,0.6);
7560 // CheckKinkPoint(&t,0.05);
7561 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7562 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
7570 MarkSeedFree( fSeeds->RemoveAt(i) );
7571 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
7573 // FollowProlongation(*seed1,0);
7574 // Int_t n = seed1->GetNumberOfClusters();
7575 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
7576 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
7579 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
7583 SortTracks(fSeeds, 1);
7587 PrepareForBackProlongation(fSeeds,5.);
7588 PropagateBack(fSeeds);
7589 printf("Time for back propagation: \t");timer.Print();timer.Start();
7593 PrepareForProlongation(fSeeds,5.);
7594 PropagateForard2(fSeeds);
7596 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
7597 // RemoveUsed(fSeeds,0.7,0.7,6);
7598 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
7600 nseed=fSeeds->GetEntriesFast();
7602 for (Int_t i=0; i<nseed; i++) {
7603 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
7605 Int_t nc=t.GetNumberOfClusters();
7607 MarkSeedFree( fSeeds->RemoveAt(i) );
7610 t.CookdEdx(0.02,0.6);
7611 // CookLabel(pt,0.1); //For comparison only
7612 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
7613 if ((pt->IsActive() || (pt->fRemoval==10) )){
7614 cerr<<found++<<'\r';
7617 MarkSeedFree( fSeeds->RemoveAt(i) );
7622 // fNTracks = found;
7624 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
7627 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
7628 Info("Clusters2Tracks","Number of found tracks %d",found);
7630 // UnloadClusters();
7635 void AliTPCtracker::Tracking(TObjArray * arr)
7638 // tracking of the seeds
7641 fSectors = fOuterSec;
7642 ParallelTracking(arr,150,63);
7643 fSectors = fOuterSec;
7644 ParallelTracking(arr,63,0);
7647 TObjArray * AliTPCtracker::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
7652 static TObjArray arrTracks;
7653 TObjArray * arr = &arrTracks;
7655 fSectors = fOuterSec;
7658 for (Int_t sec=0;sec<fkNOS;sec++){
7659 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
7660 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
7661 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
7664 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
7676 TObjArray * AliTPCtracker::Tracking()
7680 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
7683 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7685 TObjArray * seeds = new TObjArray;
7687 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
7688 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
7689 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
7697 Float_t fnumber = 3.0;
7698 Float_t fdensity = 3.0;
7701 if (AliTPCReconstructor::GetRecoParam()->GetUseHLTPreSeeding()) {
7702 arr = MakeSeedsHLT( fEventHLT );
7704 SumTracks(seeds,arr);
7707 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
7708 //SignClusters(seeds,fnumber,fdensity);
7715 for (Int_t delta = 0; delta<18; delta+=gapPrim){
7719 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
7720 SumTracks(seeds,arr);
7721 SignClusters(seeds,fnumber,fdensity);
7723 for (Int_t i=2;i<6;i+=2){
7724 // seed high pt tracks
7727 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
7728 SumTracks(seeds,arr);
7729 SignClusters(seeds,fnumber,fdensity);
7734 // RemoveUsed(seeds,0.9,0.9,1);
7735 // UnsignClusters();
7736 // SignClusters(seeds,fnumber,fdensity);
7740 for (Int_t delta = 20; delta<120; delta+=gapPrim){
7742 // seed high pt tracks
7746 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
7747 SumTracks(seeds,arr);
7748 SignClusters(seeds,fnumber,fdensity);
7753 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
7754 SumTracks(seeds,arr);
7755 SignClusters(seeds,fnumber,fdensity);
7766 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
7770 // RemoveUsed(seeds,0.75,0.75,1);
7772 //SignClusters(seeds,fnumber,fdensity);
7781 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
7782 SumTracks(seeds,arr);
7783 SignClusters(seeds,fnumber,fdensity);
7785 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
7786 SumTracks(seeds,arr);
7787 SignClusters(seeds,fnumber,fdensity);
7789 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
7790 SumTracks(seeds,arr);
7791 SignClusters(seeds,fnumber,fdensity);
7793 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7794 SumTracks(seeds,arr);
7795 SignClusters(seeds,fnumber,fdensity);
7797 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7798 SumTracks(seeds,arr);
7799 SignClusters(seeds,fnumber,fdensity);
7802 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7803 SumTracks(seeds,arr);
7804 SignClusters(seeds,fnumber,fdensity);
7808 for (Int_t delta = 9; delta<30; delta+=gapSec){
7814 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7815 SumTracks(seeds,arr);
7816 SignClusters(seeds,fnumber,fdensity);
7818 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7819 SumTracks(seeds,arr);
7820 SignClusters(seeds,fnumber,fdensity);
7833 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7839 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7840 SumTracks(seeds,arr);
7841 SignClusters(seeds,fnumber,fdensity);
7843 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7844 SumTracks(seeds,arr);
7845 SignClusters(seeds,fnumber,fdensity);
7849 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7860 TObjArray * AliTPCtracker::TrackingSpecial()
7863 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7864 // no primary vertex seeding tried
7868 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7870 TObjArray * seeds = new TObjArray;
7875 Float_t fnumber = 3.0;
7876 Float_t fdensity = 3.0;
7879 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7880 cuts[1] = 3.5; // max tan(phi) angle for seeding
7881 cuts[2] = 3.; // not used (cut on z primary vertex)
7882 cuts[3] = 3.5; // max tan(theta) angle for seeding
7884 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7886 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7887 SumTracks(seeds,arr);
7888 SignClusters(seeds,fnumber,fdensity);
7892 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7903 void AliTPCtracker::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7906 //sum tracks to common container
7907 //remove suspicious tracks
7908 // RS: Attention: supplied tracks come in the static array, don't delete them
7909 Int_t nseed = arr2->GetEntriesFast();
7910 for (Int_t i=0;i<nseed;i++){
7911 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7914 // remove tracks with too big curvature
7916 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7917 MarkSeedFree( arr2->RemoveAt(i) );
7920 // REMOVE VERY SHORT TRACKS
7921 if (pt->GetNumberOfClusters()<20){
7922 MarkSeedFree( arr2->RemoveAt(i) );
7925 // NORMAL ACTIVE TRACK
7926 if (pt->IsActive()){
7927 arr1->AddLast(arr2->RemoveAt(i));
7930 //remove not usable tracks
7931 if (pt->GetRemoval()!=10){
7932 MarkSeedFree( arr2->RemoveAt(i) );
7936 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7937 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7938 arr1->AddLast(arr2->RemoveAt(i));
7940 MarkSeedFree( arr2->RemoveAt(i) );
7944 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7949 void AliTPCtracker::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7952 // try to track in parralel
7954 Int_t nseed=arr->GetEntriesFast();
7955 //prepare seeds for tracking
7956 for (Int_t i=0; i<nseed; i++) {
7957 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7959 if (!t.IsActive()) continue;
7960 // follow prolongation to the first layer
7961 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7962 FollowProlongation(t, rfirst+1);
7967 for (Int_t nr=rfirst; nr>=rlast; nr--){
7968 if (nr<fInnerSec->GetNRows())
7969 fSectors = fInnerSec;
7971 fSectors = fOuterSec;
7972 // make indexes with the cluster tracks for given
7974 // find nearest cluster
7975 for (Int_t i=0; i<nseed; i++) {
7976 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7978 if (nr==80) pt->UpdateReference();
7979 if (!pt->IsActive()) continue;
7980 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7981 if (pt->GetRelativeSector()>17) {
7984 UpdateClusters(t,nr);
7986 // prolonagate to the nearest cluster - if founded
7987 for (Int_t i=0; i<nseed; i++) {
7988 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7990 if (!pt->IsActive()) continue;
7991 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7992 if (pt->GetRelativeSector()>17) {
7995 FollowToNextCluster(*pt,nr);
8000 void AliTPCtracker::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
8004 // if we use TPC track itself we have to "update" covariance
8006 Int_t nseed= arr->GetEntriesFast();
8007 for (Int_t i=0;i<nseed;i++){
8008 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8012 //rotate to current local system at first accepted point
8013 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
8014 Int_t sec = (index&0xff000000)>>24;
8016 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
8017 if (angle1>TMath::Pi())
8018 angle1-=2.*TMath::Pi();
8019 Float_t angle2 = pt->GetAlpha();
8021 if (TMath::Abs(angle1-angle2)>0.001){
8022 if (!pt->Rotate(angle1-angle2)) return;
8023 //angle2 = pt->GetAlpha();
8024 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
8025 //if (pt->GetAlpha()<0)
8026 // pt->fRelativeSector+=18;
8027 //sec = pt->fRelativeSector;
8036 void AliTPCtracker::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
8040 // if we use TPC track itself we have to "update" covariance
8042 Int_t nseed= arr->GetEntriesFast();
8043 for (Int_t i=0;i<nseed;i++){
8044 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8047 pt->SetFirstPoint(pt->GetLastPoint());
8055 Int_t AliTPCtracker::PropagateBack(const TObjArray *const arr)
8058 // make back propagation
8060 Int_t nseed= arr->GetEntriesFast();
8061 for (Int_t i=0;i<nseed;i++){
8062 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8063 if (pt&& pt->GetKinkIndex(0)<=0) {
8064 //AliTPCseed *pt2 = new AliTPCseed(*pt);
8065 fSectors = fInnerSec;
8066 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
8067 //fSectors = fOuterSec;
8068 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
8069 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
8070 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
8071 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
8074 if (pt&& pt->GetKinkIndex(0)>0) {
8075 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
8076 pt->SetFirstPoint(kink->GetTPCRow0());
8077 fSectors = fInnerSec;
8078 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
8086 Int_t AliTPCtracker::PropagateForward2(const TObjArray *const arr)
8089 // make forward propagation
8091 Int_t nseed= arr->GetEntriesFast();
8093 for (Int_t i=0;i<nseed;i++){
8094 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
8096 FollowProlongation(*pt,0,1,1);
8105 Int_t AliTPCtracker::PropagateForward()
8108 // propagate track forward
8110 Int_t nseed = fSeeds->GetEntriesFast();
8111 for (Int_t i=0;i<nseed;i++){
8112 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
8114 AliTPCseed &t = *pt;
8115 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
8116 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8117 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8118 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8122 fSectors = fOuterSec;
8123 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
8124 fSectors = fInnerSec;
8125 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
8134 Int_t AliTPCtracker::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
8137 // make back propagation, in between row0 and row1
8141 fSectors = fInnerSec;
8144 if (row1<fSectors->GetNRows())
8147 r1 = fSectors->GetNRows()-1;
8149 if (row0<fSectors->GetNRows()&& r1>0 )
8150 FollowBackProlongation(*pt,r1);
8151 if (row1<=fSectors->GetNRows())
8154 r1 = row1 - fSectors->GetNRows();
8155 if (r1<=0) return 0;
8156 if (r1>=fOuterSec->GetNRows()) return 0;
8157 fSectors = fOuterSec;
8158 return FollowBackProlongation(*pt,r1);
8166 void AliTPCtracker::GetShape(AliTPCseed * seed, Int_t row)
8168 // gets cluster shape
8170 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
8171 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
8172 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
8173 Double_t angulary = seed->GetSnp();
8175 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
8176 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
8179 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
8180 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
8182 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
8183 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
8184 seed->SetCurrentSigmaY2(sigmay*sigmay);
8185 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
8186 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
8187 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
8188 // Float_t padlength = GetPadPitchLength(row);
8190 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
8191 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
8193 // Float_t sresz = fkParam->GetZSigma();
8194 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
8196 Float_t wy = GetSigmaY(seed);
8197 Float_t wz = GetSigmaZ(seed);
8200 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
8201 printf("problem\n");
8208 //__________________________________________________________________________
8209 void AliTPCtracker::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
8210 //--------------------------------------------------------------------
8211 //This function "cooks" a track label. If label<0, this track is fake.
8212 //--------------------------------------------------------------------
8213 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
8215 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
8219 Int_t noc=t->GetNumberOfClusters();
8221 //printf("\nnot founded prolongation\n\n\n");
8227 AliTPCclusterMI *clusters[160];
8229 for (Int_t i=0;i<160;i++) {
8236 for (i=0; i<160 && current<noc; i++) {
8238 Int_t index=t->GetClusterIndex2(i);
8239 if (index<=0) continue;
8240 if (index&0x8000) continue;
8242 //clusters[current]=GetClusterMI(index);
8243 if (t->GetClusterPointer(i)){
8244 clusters[current]=t->GetClusterPointer(i);
8250 Int_t lab=123456789;
8251 for (i=0; i<noc; i++) {
8252 AliTPCclusterMI *c=clusters[i];
8254 lab=TMath::Abs(c->GetLabel(0));
8256 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8262 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8264 for (i=0; i<noc; i++) {
8265 AliTPCclusterMI *c=clusters[i];
8267 if (TMath::Abs(c->GetLabel(1)) == lab ||
8268 TMath::Abs(c->GetLabel(2)) == lab ) max++;
8270 if (noc<=0) { lab=-1; return;}
8271 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8274 Int_t tail=Int_t(0.10*noc);
8277 for (i=1; i<160&&ind<tail; i++) {
8278 // AliTPCclusterMI *c=clusters[noc-i];
8279 AliTPCclusterMI *c=clusters[i];
8281 if (lab == TMath::Abs(c->GetLabel(0)) ||
8282 lab == TMath::Abs(c->GetLabel(1)) ||
8283 lab == TMath::Abs(c->GetLabel(2))) max++;
8286 if (max < Int_t(0.5*tail)) lab=-lab;
8293 //delete[] clusters;
8297 //__________________________________________________________________________
8298 Int_t AliTPCtracker::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
8299 //--------------------------------------------------------------------
8300 //This function "cooks" a track label. If label<0, this track is fake.
8301 //--------------------------------------------------------------------
8302 Int_t noc=t->GetNumberOfClusters();
8304 //printf("\nnot founded prolongation\n\n\n");
8310 AliTPCclusterMI *clusters[160];
8312 for (Int_t i=0;i<160;i++) {
8319 for (i=0; i<160 && current<noc; i++) {
8320 if (i<first) continue;
8321 if (i>last) continue;
8322 Int_t index=t->GetClusterIndex2(i);
8323 if (index<=0) continue;
8324 if (index&0x8000) continue;
8326 //clusters[current]=GetClusterMI(index);
8327 if (t->GetClusterPointer(i)){
8328 clusters[current]=t->GetClusterPointer(i);
8333 //if (noc<5) return -1;
8334 Int_t lab=123456789;
8335 for (i=0; i<noc; i++) {
8336 AliTPCclusterMI *c=clusters[i];
8338 lab=TMath::Abs(c->GetLabel(0));
8340 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
8346 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
8348 for (i=0; i<noc; i++) {
8349 AliTPCclusterMI *c=clusters[i];
8351 if (TMath::Abs(c->GetLabel(1)) == lab ||
8352 TMath::Abs(c->GetLabel(2)) == lab ) max++;
8354 if (noc<=0) { lab=-1; return -1;}
8355 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
8358 Int_t tail=Int_t(0.10*noc);
8361 for (i=1; i<160&&ind<tail; i++) {
8362 // AliTPCclusterMI *c=clusters[noc-i];
8363 AliTPCclusterMI *c=clusters[i];
8365 if (lab == TMath::Abs(c->GetLabel(0)) ||
8366 lab == TMath::Abs(c->GetLabel(1)) ||
8367 lab == TMath::Abs(c->GetLabel(2))) max++;
8370 if (max < Int_t(0.5*tail)) lab=-lab;
8373 // t->SetLabel(lab);
8377 //delete[] clusters;
8381 Int_t AliTPCtracker::GetRowNumber(Double_t x[3]) const
8383 //return pad row number for given x vector
8384 Float_t phi = TMath::ATan2(x[1],x[0]);
8385 if(phi<0) phi=2.*TMath::Pi()+phi;
8386 // Get the local angle in the sector philoc
8387 const Float_t kRaddeg = 180/3.14159265358979312;
8388 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
8389 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
8390 return GetRowNumber(localx);
8395 void AliTPCtracker::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
8397 //-----------------------------------------------------------------------
8398 // Fill the cluster and sharing bitmaps of the track
8399 //-----------------------------------------------------------------------
8401 Int_t firstpoint = 0;
8402 Int_t lastpoint = 159;
8403 AliTPCTrackerPoint *point;
8404 AliTPCclusterMI *cluster;
8407 TBits clusterMap(159);
8408 TBits sharedMap(159);
8410 for (int iter=firstpoint; iter<lastpoint; iter++) {
8411 // Change to cluster pointers to see if we have a cluster at given padrow
8413 cluster = t->GetClusterPointer(iter);
8415 clusterMap.SetBitNumber(iter, kTRUE);
8416 point = t->GetTrackPoint(iter);
8417 if (point->IsShared())
8418 sharedMap.SetBitNumber(iter,kTRUE);
8420 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
8421 fitMap.SetBitNumber(iter, kTRUE);
8425 esd->SetTPCClusterMap(clusterMap);
8426 esd->SetTPCSharedMap(sharedMap);
8427 esd->SetTPCFitMap(fitMap);
8428 if (nclsf != t->GetNumberOfClusters())
8429 AliDebug(3,Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
8432 Bool_t AliTPCtracker::IsFindable(AliTPCseed & track){
8434 // return flag if there is findable cluster at given position
8437 Float_t z = track.GetZ();
8439 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
8440 TMath::Abs(z)<fkParam->GetZLength(0) &&
8441 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
8447 void AliTPCtracker::AddCovariance(AliTPCseed * seed){
8449 // Adding systematic error estimate to the covariance matrix
8450 // !!!! the systematic error for element 4 is in 1/GeV
8451 // 03.03.2012 MI changed in respect to the previous versions
8452 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8454 // use only the diagonal part if not specified otherwise
8455 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
8457 Double_t *covarS= (Double_t*)seed->GetCovariance();
8458 Double_t factor[5]={1,1,1,1,1};
8459 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
8460 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
8461 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
8462 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
8463 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
8465 factor[0]=factor[2];
8466 factor[4]=factor[2];
8472 for (Int_t i=0; i<5; i++){
8473 for (Int_t j=i; j<5; j++){
8474 Int_t index=seed->GetIndex(i,j);
8475 covarS[index]*=factor[i]*factor[j];
8481 void AliTPCtracker::AddCovarianceAdd(AliTPCseed * seed){
8483 // Adding systematic error - as additive factor without correlation
8485 // !!!! the systematic error for element 4 is in 1/GeV
8486 // 03.03.2012 MI changed in respect to the previous versions
8488 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
8489 Double_t *covarIn= (Double_t*)seed->GetCovariance();
8491 for (Int_t i=0;i<15;i++) covar[i]=0;
8497 covar[0] = param[0]*param[0];
8498 covar[2] = param[1]*param[1];
8499 covar[5] = param[2]*param[2];
8500 covar[9] = param[3]*param[3];
8501 covar[14]= param[4]*param[4];
8503 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
8505 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
8506 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
8508 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
8509 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
8510 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
8512 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
8513 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
8514 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
8515 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
8517 seed->AddCovariance(covar);
8520 //_____________________________________________________________________________
8521 Bool_t AliTPCtracker::IsTPCHVDipEvent(AliESDEvent const *esdEvent)
8524 // check events affected by TPC HV dip
8526 if(!esdEvent) return kFALSE;
8529 AliTPCcalibDB *db=AliTPCcalibDB::Instance();
8530 if(!db) return kFALSE;
8531 db->SetRun(esdEvent->GetRunNumber());
8533 // maximum allowed voltage before an event is identified as a dip event
8534 // and scanning period
8535 const Double_t kTPCHVdip = db->GetParameters()->GetMaxDipVoltage();
8536 const Double_t dipEventScanPeriod = db->GetParameters()->GetVoltageDipScanPeriod();
8537 const Double_t tevSec = esdEvent->GetTimeStamp();
8539 for(Int_t sector=0; sector<72; sector++)
8541 // don't use excluded chambers, since the state is not defined at all
8542 if (!db->GetChamberHVStatus(sector)) continue;
8544 // get hv sensor of the chamber
8545 AliDCSSensor *sensor = db->GetChamberHVSensor(sector);
8546 if (!sensor) continue;
8547 TGraph *grSensor=sensor->GetGraph();
8548 if (!grSensor) continue;
8549 if (grSensor->GetN()<1) continue;
8552 const Double_t median = db->GetChamberHighVoltageMedian(sector);
8553 if(median < 1.) continue;
8555 for (Int_t ipoint=0; ipoint<grSensor->GetN()-1; ++ipoint){
8556 Double_t nextTime=grSensor->GetX()[ipoint+1]*3600+sensor->GetStartTime();
8557 if (tevSec-dipEventScanPeriod>nextTime) continue;
8558 const Float_t deltaV=TMath::Abs(grSensor->GetY()[ipoint]-median);
8559 if (deltaV>kTPCHVdip) {
8560 AliDebug(3,Form("HV dip detected in ROC '%02d' with dV '%.2f' at time stamp '%.0f'",sector,deltaV,tevSec));
8563 if (nextTime>tevSec+dipEventScanPeriod) break;
8570 //________________________________________
8571 void AliTPCtracker::MarkSeedFree(TObject *sd)
8573 // account that this seed is "deleted"
8574 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
8576 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
8579 int id = seed->GetPoolID();
8581 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
8584 // AliInfo(Form("%d %p",id, seed));
8585 fSeedsPool->RemoveAt(id);
8586 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
8587 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
8590 //________________________________________
8591 TObject *&AliTPCtracker::NextFreeSeed()
8593 // return next free slot where the seed can be created
8594 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
8595 // AliInfo(Form("%d",fLastSeedID));
8596 return (*fSeedsPool)[ fLastSeedID ];
8600 //________________________________________
8601 void AliTPCtracker::ResetSeedsPool()
8603 // mark all seeds in the pool as unused
8604 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
8606 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
8609 Int_t AliTPCtracker::PropagateToRowHLT(AliTPCseed *pt, int nrow)
8612 Double_t x= GetXrow(nrow);
8613 Double_t ymax= GetMaxY(nrow);
8619 if (!t.PropagateTo(x) ){
8620 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
8626 Double_t y = t.GetY();
8628 if( rotate!=-1 ) rotate=1;
8629 } else if (y <-ymax) {
8630 if( rotate!=1 ) rotate = -1;
8632 if( rotate==0 ) break;
8633 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
8634 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
8635 //cout<<"can't rotate "<<endl;
8639 nRotations+= rotate;
8641 if( nRotations!=0 ){
8642 int newSec= t.GetRelativeSector()+nRotations;
8643 if( newSec>=fN ) newSec-=fN;
8644 else if( newSec<0 ) newSec +=fN;
8645 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
8646 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
8647 t.SetRelativeSector(newSec);
8652 void AliTPCtracker::TrackFollowingHLT(TObjArray *const arr )
8655 // try to track in parralel
8657 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8660 Int_t nseed=arr->GetEntriesFast();
8661 //cout<<"Parallel tracking My.."<<endl;
8662 double shapeY2[160], shapeZ2[160];
8663 Int_t clusterIndex[160];
8665 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
8666 //if( iSeed!=1 ) continue;
8667 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
8671 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
8675 for( int iter=0; iter<3; iter++ ){
8678 t.SetLastPoint(0); // first cluster in track position
8679 t.SetFirstPoint(nRows-1);
8680 t.ResetCovariance(.1);
8681 t.SetNumberOfClusters(0);
8682 for( int i=0; i<nRows; i++ ){
8686 t.SetClusterIndex2(i,-1);
8687 t.SetClusterIndex(i,-1);
8690 // pick up the clusters
8692 Double_t roady = 20.;
8693 Double_t roadz = 20.;
8700 t0.SetRelativeSector(t.GetRelativeSector());
8701 t0.SetLastPoint(0); // first cluster in track position
8702 t0.SetFirstPoint(159);
8703 for (Int_t nr=0; nr<nRows; nr++){
8704 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
8705 else fSectors=fOuterSec;
8707 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
8708 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8709 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
8712 if (!IsActive(t0.GetRelativeSector(),nr)) {
8718 shapeY2[nr]=t0.GetCurrentSigmaY2();
8719 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
8722 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
8723 if( !krow ) continue;
8725 t.SetClusterIndex2(nr,-3); // foundable
8726 t.SetClusterIndex(nr,-3);
8728 AliTPCclusterMI *cl=0;
8730 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
8732 double dy = cl->GetY()-t0.GetY();
8733 double dz = cl->GetZ()-t0.GetZ();
8734 double dr = sqrt(dy*dy+dz*dz);
8736 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8739 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
8741 t0.SetClusterPointer(nr, cl);
8742 clusterIndex[nr] = krow.GetIndex(uindex);
8743 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
8744 t0.SetLastPoint(nr);
8750 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
8753 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
8757 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
8759 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
8760 if( !t0.GetClusterPointer(nr) ) continue;
8761 int d = TMath::Abs(nr-midRow);
8769 // first fit 3 base points
8771 //cout<<"Fit3: "<<endl;
8772 for( int icl=0; icl<3; icl++){
8773 int nr = basePoints[icl];
8775 if( nr>=fInnerSec->GetNRows()){
8776 lr = nr - fInnerSec->GetNRows();
8778 } else fSectors=fInnerSec;
8780 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8782 //cout<<"WRONG!!!!"<<endl;
8785 int iSec = cl->GetDetector() %fkNIS;
8786 int rotate = iSec - t.GetRelativeSector();
8788 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8789 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8790 //cout<<"can't rotate "<<endl;
8793 t.SetRelativeSector(iSec);
8795 Double_t x= cl->GetX();
8796 if (!t.PropagateTo(x)){
8797 //cout<<"can't propagate to x="<<x<<endl;
8801 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8802 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8805 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8807 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8808 t.SetCurrentCluster(cl);
8811 t.SetErrorY2(shapeY2[nr]);
8812 t.SetErrorZ2(shapeZ2[nr]);
8815 for( int j=0; j<15; j++ ) cov[j]=0;
8821 t.AliExternalTrackParam::AddCovariance(cov);
8823 if( !UpdateTrack(&t,0) ){
8824 //cout<<"Can not update"<<endl;
8826 t.SetClusterIndex2(nr,-1);
8827 t.SetClusterIndex(nr,-1);
8828 t.SetClusterPointer(nr,0);
8831 //t.SetClusterPointer(nr, cl);
8834 //t.SetLastPoint(t0.GetLastPoint());
8835 //t.SetFirstPoint(t0.GetFirstPoint());
8837 //cout<<"Fit: "<<endl;
8838 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8840 if( nr>=fInnerSec->GetNRows()){
8841 lr = nr - fInnerSec->GetNRows();
8843 } else fSectors=fInnerSec;
8846 if( nr == basePoints[0] ) continue;
8847 if( nr == basePoints[1] ) continue;
8848 if( nr == basePoints[2] ) continue;
8850 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8853 int iSec = cl->GetDetector() %fkNIS;
8854 int rotate = iSec - t.GetRelativeSector();
8856 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8857 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8858 //cout<<"can't rotate "<<endl;
8861 t.SetRelativeSector(iSec);
8863 Double_t x= cl->GetX();
8864 if (!t.PropagateTo(x)){
8865 //cout<<"can't propagate to x="<<x<<endl;
8868 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8869 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8873 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8875 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8876 t.SetCurrentCluster(cl);
8878 t.SetErrorY2(shapeY2[nr]);
8879 t.SetErrorZ2(shapeZ2[nr]);
8881 if( !UpdateTrack(&t,0) ){
8882 //cout<<"Can not update"<<endl;
8884 t.SetClusterIndex2(nr,-1);
8885 t.SetClusterIndex(nr,-1);
8888 //t.SetClusterPointer(nr, cl);
8891 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8894 //cout<<"fitted track"<<iSeed<<endl;
8896 //cout<<"Statistics: "<<endl;
8897 Int_t foundable,found,shared;
8898 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8899 t.SetNFoundable(foundable);
8900 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8906 TObjArray * AliTPCtracker::MakeSeedsHLT(const AliESDEvent *hltEvent)
8911 if( !hltEvent ) return 0;
8914 Int_t nentr=hltEvent->GetNumberOfTracks();
8916 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8918 TObjArray * seeds = new TObjArray(nentr);
8920 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8923 Int_t nTr=hltEvent->GetNumberOfTracks();
8925 for( int itr=0; itr<nTr; itr++ ){
8926 //if( itr!=97 ) continue;
8927 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8928 if( !param ) continue;
8929 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8930 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8932 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8933 tr.SetNumberOfClusters(0);
8934 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8936 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8937 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8938 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8940 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8941 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8943 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8944 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8946 seed->Rotate(alphaSec - alpha);
8948 seed->SetPoolID(fLastSeedID);
8949 seed->SetIsSeeding(kTRUE);
8950 seed->SetSeed1(nup-1);
8951 seed->SetSeed2(nup-2);
8952 seed->SetSeedType(0);
8953 seed->SetFirstPoint(-1);
8954 seed->SetLastPoint(-1);
8955 seeds->AddLast(seed); // note, track is seed, don't free the seed
8957 //if( index>3 ) break;
8961 fSectors = fOuterSec;
8963 TrackFollowingHLT(seeds );
8965 nTr = seeds->GetEntriesFast();
8966 for( int itr=0; itr<nTr; itr++ ){
8967 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8968 if( !seed ) continue;
8969 //FollowBackProlongation(*seed,0);
8970 // cout<<seed->GetNumberOfClusters()<<endl;
8971 Int_t foundable,found,shared;
8972 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8973 seed->SetNFoundable(foundable);
8974 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8975 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8976 //MarkSeedFree(seeds->RemoveAt(itr));
8979 if (seed->GetNumberOfClusters()<30 ||
8980 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8981 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8982 MarkSeedFree(seeds->RemoveAt(itr));
8986 for( int ir=0; ir<nup; ir++){
8987 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8991 std::cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;
8995 void AliTPCtracker::FillClusterOccupancyInfo()
8997 //fill the cluster occupancy info into the ESD friend
8998 AliESDfriend* esdFriend = static_cast<AliESDfriend*>(fEvent->FindListObject("AliESDfriend"));
8999 if (!esdFriend) return;
9001 for (Int_t isector=0; isector<18; isector++){
9002 AliTPCtrackerSector &iroc = fInnerSec[isector];
9003 AliTPCtrackerSector &oroc = fOuterSec[isector];
9005 esdFriend->SetNclustersTPC(isector, iroc.GetNClInSector(0));
9006 esdFriend->SetNclustersTPC(isector+18,iroc.GetNClInSector(1));
9007 esdFriend->SetNclustersTPC(isector+36,oroc.GetNClInSector(0));
9008 esdFriend->SetNclustersTPC(isector+54,oroc.GetNClInSector(1));
9009 //clusters used in tracking
9010 esdFriend->SetNclustersTPCused(isector, iroc.GetNClUsedInSector(0));
9011 esdFriend->SetNclustersTPCused(isector+18, iroc.GetNClUsedInSector(1));
9012 esdFriend->SetNclustersTPCused(isector+36, oroc.GetNClUsedInSector(0));
9013 esdFriend->SetNclustersTPCused(isector+54, oroc.GetNClUsedInSector(1));