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 Kalaman filtering approach
26 // The track finding steps:
27 // 1. Seeding - with and without vertex constraint
28 // - seeding with vertex constain done at first n^2 proble
29 // - seeding without vertex constraint n^3 problem
30 // 2. Tracking - follow prolongation road - find cluster - update kalman track
32 // The seeding and tracking is repeated several times, in different seeding region.
33 // This approach enables to find the track which cannot be seeded in some region of TPC
34 // This can happen because of low momenta (track do not reach outer radius), or track is currently in the ded region between sectors, or the track is for the moment overlapped with other track (seed quality is poor) ...
36 // With this approach we reach almost 100 % efficiency also for high occupancy events.
37 // (If the seeding efficiency in a region is about 90 % than with logical or of several
38 // regions we will reach 100% (in theory - supposing independence)
40 // Repeating several seeding - tracking procedures some of the tracks can be find
43 // The procedures to remove multi find tacks are impremented:
44 // RemoveUsed2 - fast procedure n problem -
45 // Algorithm - Sorting tracks according quality
46 // remove tracks with some shared fraction
47 // Sharing in respect to all tacks
48 // Signing clusters in gold region
49 // FindSplitted - slower algorithm n^2
50 // Sort the tracks according quality
51 // Loop over pair of tracks
52 // If overlap with other track bigger than threshold - remove track
54 // FindCurling - Finds the pair of tracks which are curling
55 // - About 10% of tracks can be find with this procedure
56 // The combinatorial background is too big to be used in High
57 // multiplicity environment
58 // - n^2 problem - Slow procedure - currently it is disabled because of
61 // The number of splitted tracks can be reduced disabling the sharing of the cluster.
62 // tpcRecoParam-> SetClusterSharing(kFALSE);
63 // IT IS HIGHLY non recomended to use it in high flux enviroonment
64 // Even using this switch some tracks can be found more than once
65 // (because of multiple seeding and low quality tracks which will not cross full chamber)
68 // The tracker itself can be debugged - the information about tracks can be stored in several // phases of the reconstruction
69 // To enable storage of the TPC tracks in the ESD friend track
70 // use AliTPCReconstructor::SetStreamLevel(n);
72 // The debug level - different procedure produce tree for numerical debugging
73 // To enable them set AliTPCReconstructor::SetStreamLevel(n); where nis bigger 1
77 // Adding systematic errors to the covariance:
79 // The systematic errors due to the misalignment and miscalibration are added to the covariance matrix
80 // of the tracks (not to the clusters as they are dependent):
81 // The parameters form AliTPCRecoParam are used AliTPCRecoParam::GetSystematicError
82 // The systematic errors are expressed there in RMS - position (cm), angle (rad), curvature (1/GeV)
83 // The default values are 0.
85 // The sytematic errors are added to the covariance matrix in following places:
87 // 1. During fisrt itteration - AliTPCtrackerMI::FillESD
88 // 2. Second iteration -
89 // 2.a ITS->TPC - AliTPCtrackerMI::ReadSeeds
90 // 2.b TPC->TRD - AliTPCtrackerMI::PropagateBack
91 // 3. Third iteration -
92 // 3.a TRD->TPC - AliTPCtrackerMI::ReadSeeds
93 // 3.b TPC->ITS - AliTPCtrackerMI::RefitInward
95 // There are several places in the code which can be numerically debuged
96 // This code is keeped in order to enable code development and to check the calibration implementtion
98 // 1. ErrParam stream - dump information about
100 // 2.a) cluster error estimate
101 // 3.a) cluster shape estimate
104 // Debug streamer levels:
106 //-------------------------------------------------------
111 #include "Riostream.h"
112 #include <TClonesArray.h>
114 #include <TObjArray.h>
116 #include <TGraphErrors.h>
118 #include "AliComplexCluster.h"
119 #include "AliESDEvent.h"
120 #include "AliESDtrack.h"
121 #include "AliESDVertex.h"
124 #include "AliHelix.h"
125 #include "AliRunLoader.h"
126 #include "AliTPCClustersRow.h"
127 #include "AliTPCParam.h"
128 #include "AliTPCReconstructor.h"
129 #include "AliTPCpolyTrack.h"
130 #include "AliTPCreco.h"
131 #include "AliTPCseed.h"
133 #include "AliTPCtrackerSector.h"
134 #include "AliTPCtrackerMI.h"
135 #include "TStopwatch.h"
136 #include "AliTPCReconstructor.h"
137 #include "AliAlignObj.h"
138 #include "AliTrackPointArray.h"
140 #include "AliTPCcalibDB.h"
141 #include "AliTPCcalibDButil.h"
142 #include "AliTPCTransform.h"
143 #include "AliTPCClusterParam.h"
144 #include "AliTPCdEdxInfo.h"
145 #include "AliDCSSensorArray.h"
146 #include "AliDCSSensor.h"
148 #include "AliCosmicTracker.h"
154 ClassImp(AliTPCtrackerMI)
158 class AliTPCFastMath {
161 static Double_t FastAsin(Double_t x);
163 static Double_t fgFastAsin[20000]; //lookup table for fast asin computation
166 Double_t AliTPCFastMath::fgFastAsin[20000];
167 AliTPCFastMath gAliTPCFastMath; // needed to fill the LUT
169 AliTPCFastMath::AliTPCFastMath(){
171 // initialized lookup table;
172 for (Int_t i=0;i<10000;i++){
173 fgFastAsin[2*i] = TMath::ASin(i/10000.);
174 fgFastAsin[2*i+1] = (TMath::ASin((i+1)/10000.)-fgFastAsin[2*i]);
178 Double_t AliTPCFastMath::FastAsin(Double_t x){
180 // return asin using lookup table
182 Int_t index = int(x*10000);
183 return fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1];
186 Int_t index = int(x*10000);
187 return -(fgFastAsin[2*index]+(x*10000.-index)*fgFastAsin[2*index+1]);
189 //__________________________________________________________________
190 AliTPCtrackerMI::AliTPCtrackerMI()
218 // default constructor
220 for (Int_t irow=0; irow<200; irow++){
227 //_____________________________________________________________________
231 Int_t AliTPCtrackerMI::UpdateTrack(AliTPCseed * track, Int_t accept){
233 //update track information using current cluster - track->fCurrentCluster
236 AliTPCclusterMI* c =track->GetCurrentCluster();
237 if (accept > 0) //sign not accepted clusters
238 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() | 0x8000);
239 else // unsign accpeted clusters
240 track->SetCurrentClusterIndex1(track->GetCurrentClusterIndex1() & 0xffff7fff);
241 UInt_t i = track->GetCurrentClusterIndex1();
243 Int_t sec=(i&0xff000000)>>24;
244 //Int_t row = (i&0x00ff0000)>>16;
245 track->SetRow((i&0x00ff0000)>>16);
246 track->SetSector(sec);
247 // Int_t index = i&0xFFFF;
248 if (sec>=fkParam->GetNInnerSector()) track->SetRow(track->GetRow()+fkParam->GetNRowLow());
249 track->SetClusterIndex2(track->GetRow(), i);
250 //track->fFirstPoint = row;
251 //if ( track->fLastPoint<row) track->fLastPoint =row;
252 // if (track->fRow<0 || track->fRow>160) {
253 // printf("problem\n");
255 if (track->GetFirstPoint()>track->GetRow())
256 track->SetFirstPoint(track->GetRow());
257 if (track->GetLastPoint()<track->GetRow())
258 track->SetLastPoint(track->GetRow());
261 track->SetClusterPointer(track->GetRow(),c);
264 Double_t angle2 = track->GetSnp()*track->GetSnp();
266 //SET NEW Track Point
268 if (angle2<1) //PH sometimes angle2 is very big. To be investigated...
270 angle2 = TMath::Sqrt(angle2/(1-angle2));
271 AliTPCTrackerPoint &point =*(track->GetTrackPoint(track->GetRow()));
273 point.SetSigmaY(c->GetSigmaY2()/track->GetCurrentSigmaY2());
274 point.SetSigmaZ(c->GetSigmaZ2()/track->GetCurrentSigmaZ2());
275 point.SetErrY(sqrt(track->GetErrorY2()));
276 point.SetErrZ(sqrt(track->GetErrorZ2()));
278 point.SetX(track->GetX());
279 point.SetY(track->GetY());
280 point.SetZ(track->GetZ());
281 point.SetAngleY(angle2);
282 point.SetAngleZ(track->GetTgl());
283 if (point.IsShared()){
284 track->SetErrorY2(track->GetErrorY2()*4);
285 track->SetErrorZ2(track->GetErrorZ2()*4);
289 Double_t chi2 = track->GetPredictedChi2(track->GetCurrentCluster());
291 // track->SetErrorY2(track->GetErrorY2()*1.3);
292 // track->SetErrorY2(track->GetErrorY2()+0.01);
293 // track->SetErrorZ2(track->GetErrorZ2()*1.3);
294 // track->SetErrorZ2(track->GetErrorZ2()+0.005);
296 if (accept>0) return 0;
297 if (track->GetNumberOfClusters()%20==0){
298 // if (track->fHelixIn){
299 // TClonesArray & larr = *(track->fHelixIn);
300 // Int_t ihelix = larr.GetEntriesFast();
301 // new(larr[ihelix]) AliHelix(*track) ;
304 track->SetNoCluster(0);
305 return track->Update(c,chi2,i);
310 Int_t AliTPCtrackerMI::AcceptCluster(AliTPCseed * seed, AliTPCclusterMI * cluster)
313 // decide according desired precision to accept given
314 // cluster for tracking
316 seed->GetProlongation(cluster->GetX(),yt,zt);
317 Double_t sy2=ErrY2(seed,cluster);
318 Double_t sz2=ErrZ2(seed,cluster);
320 Double_t sdistancey2 = sy2+seed->GetSigmaY2();
321 Double_t sdistancez2 = sz2+seed->GetSigmaZ2();
322 Double_t dy=seed->GetCurrentCluster()->GetY()-yt;
323 Double_t dz=seed->GetCurrentCluster()->GetZ()-zt;
324 Double_t rdistancey2 = (seed->GetCurrentCluster()->GetY()-yt)*
325 (seed->GetCurrentCluster()->GetY()-yt)/sdistancey2;
326 Double_t rdistancez2 = (seed->GetCurrentCluster()->GetZ()-zt)*
327 (seed->GetCurrentCluster()->GetZ()-zt)/sdistancez2;
329 Double_t rdistance2 = rdistancey2+rdistancez2;
332 if (AliTPCReconstructor::StreamLevel()>2 && seed->GetNumberOfClusters()>20) {
333 Float_t rmsy2 = seed->GetCurrentSigmaY2();
334 Float_t rmsz2 = seed->GetCurrentSigmaZ2();
335 Float_t rmsy2p30 = seed->GetCMeanSigmaY2p30();
336 Float_t rmsz2p30 = seed->GetCMeanSigmaZ2p30();
337 Float_t rmsy2p30R = seed->GetCMeanSigmaY2p30R();
338 Float_t rmsz2p30R = seed->GetCMeanSigmaZ2p30R();
339 AliExternalTrackParam param(*seed);
340 static TVectorD gcl(3),gtr(3);
342 param.GetXYZ(gcl.GetMatrixArray());
343 cluster->GetGlobalXYZ(gclf);
344 gcl[0]=gclf[0]; gcl[1]=gclf[1]; gcl[2]=gclf[2];
347 if (AliTPCReconstructor::StreamLevel()>2) {
348 (*fDebugStreamer)<<"ErrParam"<<
361 "rmsy2p30="<<rmsy2p30<<
362 "rmsz2p30="<<rmsz2p30<<
363 "rmsy2p30R="<<rmsy2p30R<<
364 "rmsz2p30R="<<rmsz2p30R<<
365 // normalize distance -
366 "rdisty="<<rdistancey2<<
367 "rdistz="<<rdistancez2<<
368 "rdist="<<rdistance2<< //
372 //return 0; // temporary
373 if (rdistance2>32) return 3;
376 if ((rdistancey2>9. || rdistancez2>9.) && cluster->GetType()==0)
377 return 2; //suspisiouce - will be changed
379 if ((rdistancey2>6.25 || rdistancez2>6.25) && cluster->GetType()>0)
380 // strict cut on overlaped cluster
381 return 2; //suspisiouce - will be changed
383 if ( (rdistancey2>1. || rdistancez2>6.25 )
384 && cluster->GetType()<0){
385 seed->SetNFoundable(seed->GetNFoundable()-1);
389 if (fUseHLTClusters == 3 || fUseHLTClusters == 4) {
391 if(!AliTPCReconstructor::GetRecoParam()->GetUseHLTOnePadCluster()) {
392 if (TMath::Abs(cluster->GetSigmaY2()) < kAlmost0)
405 //_____________________________________________________________________________
406 AliTPCtrackerMI::AliTPCtrackerMI(const AliTPCParam *par):
408 fkNIS(par->GetNInnerSector()/2),
410 fkNOS(par->GetNOuterSector()/2),
433 //---------------------------------------------------------------------
434 // The main TPC tracker constructor
435 //---------------------------------------------------------------------
436 fInnerSec=new AliTPCtrackerSector[fkNIS];
437 fOuterSec=new AliTPCtrackerSector[fkNOS];
440 for (i=0; i<fkNIS; i++) fInnerSec[i].Setup(par,0);
441 for (i=0; i<fkNOS; i++) fOuterSec[i].Setup(par,1);
444 Int_t nrowlow = par->GetNRowLow();
445 Int_t nrowup = par->GetNRowUp();
448 for (i=0;i<nrowlow;i++){
449 fXRow[i] = par->GetPadRowRadiiLow(i);
450 fPadLength[i]= par->GetPadPitchLength(0,i);
451 fYMax[i] = fXRow[i]*TMath::Tan(0.5*par->GetInnerAngle());
455 for (i=0;i<nrowup;i++){
456 fXRow[i+nrowlow] = par->GetPadRowRadiiUp(i);
457 fPadLength[i+nrowlow] = par->GetPadPitchLength(60,i);
458 fYMax[i+nrowlow] = fXRow[i+nrowlow]*TMath::Tan(0.5*par->GetOuterAngle());
461 if (AliTPCReconstructor::StreamLevel()>0) {
462 fDebugStreamer = new TTreeSRedirector("TPCdebug.root");
465 fSeedsPool = new TClonesArray("AliTPCseed",1000);
467 //________________________________________________________________________
468 AliTPCtrackerMI::AliTPCtrackerMI(const AliTPCtrackerMI &t):
495 //------------------------------------
496 // dummy copy constructor
497 //------------------------------------------------------------------
499 for (Int_t irow=0; irow<200; irow++){
506 AliTPCtrackerMI & AliTPCtrackerMI::operator=(const AliTPCtrackerMI& /*r*/)
508 //------------------------------
510 //--------------------------------------------------------------
513 //_____________________________________________________________________________
514 AliTPCtrackerMI::~AliTPCtrackerMI() {
515 //------------------------------------------------------------------
516 // TPC tracker destructor
517 //------------------------------------------------------------------
524 if (fDebugStreamer) delete fDebugStreamer;
525 if (fSeedsPool) delete fSeedsPool;
529 void AliTPCtrackerMI::FillESD(const TObjArray* arr)
533 //fill esds using updated tracks
536 // write tracks to the event
537 // store index of the track
538 Int_t nseed=arr->GetEntriesFast();
539 //FindKinks(arr,fEvent);
540 for (Int_t i=0; i<nseed; i++) {
541 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
545 if (AliTPCReconstructor::StreamLevel()>1) {
546 (*fDebugStreamer)<<"Track0"<<
550 // pt->PropagateTo(fkParam->GetInnerRadiusLow());
551 if (pt->GetKinkIndex(0)<=0){ //don't propagate daughter tracks
552 pt->PropagateTo(fkParam->GetInnerRadiusLow());
555 if (( pt->GetPoints()[2]- pt->GetPoints()[0])>5 && pt->GetPoints()[3]>0.8){
557 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
558 iotrack.SetTPCPoints(pt->GetPoints());
559 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
560 iotrack.SetV0Indexes(pt->GetV0Indexes());
561 // iotrack.SetTPCpid(pt->fTPCr);
562 //iotrack.SetTPCindex(i);
563 fEvent->AddTrack(&iotrack);
567 if ( (pt->GetNumberOfClusters()>70)&& (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.55) {
569 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
570 iotrack.SetTPCPoints(pt->GetPoints());
571 //iotrack.SetTPCindex(i);
572 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
573 iotrack.SetV0Indexes(pt->GetV0Indexes());
574 // iotrack.SetTPCpid(pt->fTPCr);
575 fEvent->AddTrack(&iotrack);
579 // short tracks - maybe decays
581 if ( (pt->GetNumberOfClusters()>30) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.70) {
582 Int_t found,foundable,shared;
583 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
584 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2)){
586 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
587 //iotrack.SetTPCindex(i);
588 iotrack.SetTPCPoints(pt->GetPoints());
589 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
590 iotrack.SetV0Indexes(pt->GetV0Indexes());
591 //iotrack.SetTPCpid(pt->fTPCr);
592 fEvent->AddTrack(&iotrack);
597 if ( (pt->GetNumberOfClusters()>20) && (Float_t(pt->GetNumberOfClusters())/Float_t(pt->GetNFoundable()))>0.8) {
598 Int_t found,foundable,shared;
599 pt->GetClusterStatistic(0,60,found, foundable,shared,kFALSE);
600 if (found<20) continue;
601 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
604 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
605 iotrack.SetTPCPoints(pt->GetPoints());
606 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
607 iotrack.SetV0Indexes(pt->GetV0Indexes());
608 //iotrack.SetTPCpid(pt->fTPCr);
609 //iotrack.SetTPCindex(i);
610 fEvent->AddTrack(&iotrack);
613 // short tracks - secondaties
615 if ( (pt->GetNumberOfClusters()>30) ) {
616 Int_t found,foundable,shared;
617 pt->GetClusterStatistic(128,158,found, foundable,shared,kFALSE);
618 if ( (found>20) && (pt->GetNShared()/float(pt->GetNumberOfClusters())<0.2) &&float(found)/float(foundable)>0.8){
620 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
621 iotrack.SetTPCPoints(pt->GetPoints());
622 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
623 iotrack.SetV0Indexes(pt->GetV0Indexes());
624 //iotrack.SetTPCpid(pt->fTPCr);
625 //iotrack.SetTPCindex(i);
626 fEvent->AddTrack(&iotrack);
631 if ( (pt->GetNumberOfClusters()>15)) {
632 Int_t found,foundable,shared;
633 pt->GetClusterStatistic(138,158,found, foundable,shared,kFALSE);
634 if (found<15) continue;
635 if (foundable<=0) continue;
636 if (pt->GetNShared()/float(pt->GetNumberOfClusters())>0.2) continue;
637 if (float(found)/float(foundable)<0.8) continue;
640 iotrack.UpdateTrackParams(pt,AliESDtrack::kTPCin);
641 iotrack.SetTPCPoints(pt->GetPoints());
642 iotrack.SetKinkIndexes(pt->GetKinkIndexes());
643 iotrack.SetV0Indexes(pt->GetV0Indexes());
644 // iotrack.SetTPCpid(pt->fTPCr);
645 //iotrack.SetTPCindex(i);
646 fEvent->AddTrack(&iotrack);
650 // >> account for suppressed tracks in the kink indices (RS)
651 int nESDtracks = fEvent->GetNumberOfTracks();
652 for (int it=nESDtracks;it--;) {
653 AliESDtrack* esdTr = fEvent->GetTrack(it);
654 if (!esdTr || !esdTr->GetKinkIndex(0)) continue;
655 for (int ik=0;ik<3;ik++) {
657 if (!(knkId=esdTr->GetKinkIndex(ik))) break; // no more kinks for this track
658 AliESDkink* kink = fEvent->GetKink(TMath::Abs(knkId)-1);
660 AliError(Form("ESDTrack%d refers to non-existing kink %d",it,TMath::Abs(knkId)-1));
663 kink->SetIndex(it, knkId<0 ? 0:1); // update track index of the kink: mother at 0, daughter at 1
666 // << account for suppressed tracks in the kink indices (RS)
667 AliInfo(Form("Number of filled ESDs-\t%d\n",fEvent->GetNumberOfTracks()));
675 Double_t AliTPCtrackerMI::ErrY2(AliTPCseed* seed, const AliTPCclusterMI * cl){
678 // Use calibrated cluster error from OCDB
680 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
682 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
683 Int_t ctype = cl->GetType();
684 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
685 Double_t angle = seed->GetSnp()*seed->GetSnp();
686 angle = TMath::Sqrt(TMath::Abs(angle/(1.-angle)));
687 Double_t erry2 = clparam->GetError0Par(0,type, z,angle);
689 erry2+=0.5; // edge cluster
692 seed->SetErrorY2(erry2);
696 //calculate look-up table at the beginning
697 // static Bool_t ginit = kFALSE;
698 // static Float_t gnoise1,gnoise2,gnoise3;
699 // static Float_t ggg1[10000];
700 // static Float_t ggg2[10000];
701 // static Float_t ggg3[10000];
702 // static Float_t glandau1[10000];
703 // static Float_t glandau2[10000];
704 // static Float_t glandau3[10000];
706 // static Float_t gcor01[500];
707 // static Float_t gcor02[500];
708 // static Float_t gcorp[500];
712 // if (ginit==kFALSE){
713 // for (Int_t i=1;i<500;i++){
714 // Float_t rsigma = float(i)/100.;
715 // gcor02[i] = TMath::Max(0.78 +TMath::Exp(7.4*(rsigma-1.2)),0.6);
716 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(3.36*(rsigma-1.2)),0.6);
717 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
721 // for (Int_t i=3;i<10000;i++){
725 // Float_t amp = float(i);
726 // Float_t padlength =0.75;
727 // gnoise1 = 0.0004/padlength;
728 // Float_t nel = 0.268*amp;
729 // Float_t nprim = 0.155*amp;
730 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
731 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
732 // if (glandau1[i]>1) glandau1[i]=1;
733 // glandau1[i]*=padlength*padlength/12.;
737 // gnoise2 = 0.0004/padlength;
739 // nprim = 0.133*amp;
740 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
741 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
742 // if (glandau2[i]>1) glandau2[i]=1;
743 // glandau2[i]*=padlength*padlength/12.;
748 // gnoise3 = 0.0004/padlength;
750 // nprim = 0.133*amp;
751 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
752 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
753 // if (glandau3[i]>1) glandau3[i]=1;
754 // glandau3[i]*=padlength*padlength/12.;
762 // Int_t amp = int(TMath::Abs(cl->GetQ()));
764 // seed->SetErrorY2(1.);
768 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
769 // Int_t ctype = cl->GetType();
770 // Float_t padlength= GetPadPitchLength(seed->GetRow());
771 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
772 // angle2 = angle2/(1-angle2);
774 // //cluster "quality"
775 // Int_t rsigmay = int(100.*cl->GetSigmaY2()/(seed->GetCurrentSigmaY2()));
778 // if (fSectors==fInnerSec){
779 // snoise2 = gnoise1;
780 // res = ggg1[amp]*z+glandau1[amp]*angle2;
781 // if (ctype==0) res *= gcor01[rsigmay];
784 // res*= gcorp[rsigmay];
788 // if (padlength<1.1){
789 // snoise2 = gnoise2;
790 // res = ggg2[amp]*z+glandau2[amp]*angle2;
791 // if (ctype==0) res *= gcor02[rsigmay];
794 // res*= gcorp[rsigmay];
798 // snoise2 = gnoise3;
799 // res = ggg3[amp]*z+glandau3[amp]*angle2;
800 // if (ctype==0) res *= gcor02[rsigmay];
803 // res*= gcorp[rsigmay];
810 // res*=2.4; // overestimate error 2 times
814 // if (res<2*snoise2)
817 // seed->SetErrorY2(res);
825 Double_t AliTPCtrackerMI::ErrZ2(AliTPCseed* seed, const AliTPCclusterMI * cl){
828 // Use calibrated cluster error from OCDB
830 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
832 Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
833 Int_t ctype = cl->GetType();
834 Int_t type = (cl->GetRow()<63) ? 0: (cl->GetRow()>126) ? 1:2;
836 Double_t angle2 = seed->GetSnp()*seed->GetSnp();
837 angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
838 Double_t angle = TMath::Sqrt(TMath::Abs(angle2));
839 Double_t errz2 = clparam->GetError0Par(1,type, z,angle);
841 errz2+=0.5; // edge cluster
844 seed->SetErrorZ2(errz2);
850 // //seed->SetErrorY2(0.1);
852 // //calculate look-up table at the beginning
853 // static Bool_t ginit = kFALSE;
854 // static Float_t gnoise1,gnoise2,gnoise3;
855 // static Float_t ggg1[10000];
856 // static Float_t ggg2[10000];
857 // static Float_t ggg3[10000];
858 // static Float_t glandau1[10000];
859 // static Float_t glandau2[10000];
860 // static Float_t glandau3[10000];
862 // static Float_t gcor01[1000];
863 // static Float_t gcor02[1000];
864 // static Float_t gcorp[1000];
868 // if (ginit==kFALSE){
869 // for (Int_t i=1;i<1000;i++){
870 // Float_t rsigma = float(i)/100.;
871 // gcor02[i] = TMath::Max(0.81 +TMath::Exp(6.8*(rsigma-1.2)),0.6);
872 // gcor01[i] = TMath::Max(0.72 +TMath::Exp(2.04*(rsigma-1.2)),0.6);
873 // gcorp[i] = TMath::Max(TMath::Power((rsigma+0.5),1.5),1.2);
877 // for (Int_t i=3;i<10000;i++){
881 // Float_t amp = float(i);
882 // Float_t padlength =0.75;
883 // gnoise1 = 0.0004/padlength;
884 // Float_t nel = 0.268*amp;
885 // Float_t nprim = 0.155*amp;
886 // ggg1[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.001*nel/(padlength*padlength))/nel;
887 // glandau1[i] = (2.+0.12*nprim)*0.5* (2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
888 // if (glandau1[i]>1) glandau1[i]=1;
889 // glandau1[i]*=padlength*padlength/12.;
893 // gnoise2 = 0.0004/padlength;
895 // nprim = 0.133*amp;
896 // ggg2[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
897 // glandau2[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
898 // if (glandau2[i]>1) glandau2[i]=1;
899 // glandau2[i]*=padlength*padlength/12.;
904 // gnoise3 = 0.0004/padlength;
906 // nprim = 0.133*amp;
907 // ggg3[i] = fkParam->GetDiffT()*fkParam->GetDiffT()*(2+0.0008*nel/(padlength*padlength))/nel;
908 // glandau3[i] = (2.+0.12*nprim)*0.5*(2.+nprim*nprim*0.001/(padlength*padlength))/nprim;
909 // if (glandau3[i]>1) glandau3[i]=1;
910 // glandau3[i]*=padlength*padlength/12.;
918 // Int_t amp = int(TMath::Abs(cl->GetQ()));
920 // seed->SetErrorY2(1.);
924 // Float_t z = TMath::Abs(fkParam->GetZLength(0)-TMath::Abs(seed->GetZ()));
925 // Int_t ctype = cl->GetType();
926 // Float_t padlength= GetPadPitchLength(seed->GetRow());
928 // Double_t angle2 = seed->GetSnp()*seed->GetSnp();
929 // // if (angle2<0.6) angle2 = 0.6;
930 // angle2 = seed->GetTgl()*seed->GetTgl()*(1+angle2/(1-angle2));
932 // //cluster "quality"
933 // Int_t rsigmaz = int(100.*cl->GetSigmaZ2()/(seed->GetCurrentSigmaZ2()));
936 // if (fSectors==fInnerSec){
937 // snoise2 = gnoise1;
938 // res = ggg1[amp]*z+glandau1[amp]*angle2;
939 // if (ctype==0) res *= gcor01[rsigmaz];
942 // res*= gcorp[rsigmaz];
946 // if (padlength<1.1){
947 // snoise2 = gnoise2;
948 // res = ggg2[amp]*z+glandau2[amp]*angle2;
949 // if (ctype==0) res *= gcor02[rsigmaz];
952 // res*= gcorp[rsigmaz];
956 // snoise2 = gnoise3;
957 // res = ggg3[amp]*z+glandau3[amp]*angle2;
958 // if (ctype==0) res *= gcor02[rsigmaz];
961 // res*= gcorp[rsigmaz];
970 // if ((ctype<0) &&<70){
975 // if (res<2*snoise2)
977 // if (res>3) res =3;
978 // seed->SetErrorZ2(res);
986 void AliTPCtrackerMI::RotateToLocal(AliTPCseed *seed)
988 //rotate to track "local coordinata
989 Float_t x = seed->GetX();
990 Float_t y = seed->GetY();
991 Float_t ymax = x*TMath::Tan(0.5*fSectors->GetAlpha());
994 seed->SetRelativeSector((seed->GetRelativeSector()+1) % fN);
995 if (!seed->Rotate(fSectors->GetAlpha()))
997 } else if (y <-ymax) {
998 seed->SetRelativeSector((seed->GetRelativeSector()-1+fN) % fN);
999 if (!seed->Rotate(-fSectors->GetAlpha()))
1007 //_____________________________________________________________________________
1008 Double_t AliTPCtrackerMI::F1old(Double_t x1,Double_t y1,
1009 Double_t x2,Double_t y2,
1010 Double_t x3,Double_t y3) const
1012 //-----------------------------------------------------------------
1013 // Initial approximation of the track curvature
1014 //-----------------------------------------------------------------
1015 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1016 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1017 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1018 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1019 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1021 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1022 if ( xr*xr+yr*yr<=0.00000000000001) return 100;
1023 return -xr*yr/sqrt(xr*xr+yr*yr);
1028 //_____________________________________________________________________________
1029 Double_t AliTPCtrackerMI::F1(Double_t x1,Double_t y1,
1030 Double_t x2,Double_t y2,
1031 Double_t x3,Double_t y3) const
1033 //-----------------------------------------------------------------
1034 // Initial approximation of the track curvature
1035 //-----------------------------------------------------------------
1041 Double_t det = x3*y2-x2*y3;
1042 if (TMath::Abs(det)<1e-10){
1046 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1047 Double_t x0 = x3*0.5-y3*u;
1048 Double_t y0 = y3*0.5+x3*u;
1049 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1055 Double_t AliTPCtrackerMI::F2(Double_t x1,Double_t y1,
1056 Double_t x2,Double_t y2,
1057 Double_t x3,Double_t y3) const
1059 //-----------------------------------------------------------------
1060 // Initial approximation of the track curvature
1061 //-----------------------------------------------------------------
1067 Double_t det = x3*y2-x2*y3;
1068 if (TMath::Abs(det)<1e-10) {
1072 Double_t u = 0.5* (x2*(x2-x3)+y2*(y2-y3))/det;
1073 Double_t x0 = x3*0.5-y3*u;
1074 Double_t y0 = y3*0.5+x3*u;
1075 Double_t c2 = 1/TMath::Sqrt(x0*x0+y0*y0);
1084 //_____________________________________________________________________________
1085 Double_t AliTPCtrackerMI::F2old(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 times center of curvature
1091 //-----------------------------------------------------------------
1092 Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1);
1093 Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)-
1094 (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2));
1095 Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)-
1096 (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1));
1098 Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b);
1100 return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr);
1103 //_____________________________________________________________________________
1104 Double_t AliTPCtrackerMI::F3(Double_t x1,Double_t y1,
1105 Double_t x2,Double_t y2,
1106 Double_t z1,Double_t z2) const
1108 //-----------------------------------------------------------------
1109 // Initial approximation of the tangent of the track dip angle
1110 //-----------------------------------------------------------------
1111 return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1115 Double_t AliTPCtrackerMI::F3n(Double_t x1,Double_t y1,
1116 Double_t x2,Double_t y2,
1117 Double_t z1,Double_t z2, Double_t c) const
1119 //-----------------------------------------------------------------
1120 // Initial approximation of the tangent of the track dip angle
1121 //-----------------------------------------------------------------
1125 //angle1 = (z1-z2)*c/(TMath::ASin(c*x1-ni)-TMath::ASin(c*x2-ni));
1127 Double_t d = TMath::Sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
1128 if (TMath::Abs(d*c*0.5)>1) return 0;
1129 // Double_t angle2 = TMath::ASin(d*c*0.5);
1130 // Double_t angle2 = AliTPCFastMath::FastAsin(d*c*0.5);
1131 Double_t angle2 = (d*c*0.5>0.1)? TMath::ASin(d*c*0.5): AliTPCFastMath::FastAsin(d*c*0.5);
1133 angle2 = (z1-z2)*c/(angle2*2.);
1137 Bool_t AliTPCtrackerMI::GetProlongation(Double_t x1, Double_t x2, Double_t x[5], Double_t &y, Double_t &z) const
1138 {//-----------------------------------------------------------------
1139 // This function find proloncation of a track to a reference plane x=x2.
1140 //-----------------------------------------------------------------
1144 if (TMath::Abs(x[4]*x1 - x[2]) >= 0.999) {
1148 Double_t c1=x[4]*x1 - x[2], r1=TMath::Sqrt((1.-c1)*(1.+c1));
1149 Double_t c2=x[4]*x2 - x[2], r2=TMath::Sqrt((1.-c2)*(1.+c2));
1153 Double_t dy = dx*(c1+c2)/(r1+r2);
1156 Double_t delta = x[4]*dx*(c1+c2)/(c1*r2 + c2*r1);
1158 if (TMath::Abs(delta)>0.01){
1159 dz = x[3]*TMath::ASin(delta)/x[4];
1161 dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1164 //dz = x[3]*AliTPCFastMath::FastAsin(delta)/x[4];
1172 Int_t AliTPCtrackerMI::LoadClusters (TTree *const tree)
1177 return LoadClusters();
1181 Int_t AliTPCtrackerMI::LoadClusters(const TObjArray *arr)
1184 // load clusters to the memory
1185 AliTPCClustersRow *clrow = new AliTPCClustersRow("AliTPCclusterMI");
1186 Int_t lower = arr->LowerBound();
1187 Int_t entries = arr->GetEntriesFast();
1189 for (Int_t i=lower; i<entries; i++) {
1190 clrow = (AliTPCClustersRow*) arr->At(i);
1191 if(!clrow) continue;
1192 if(!clrow->GetArray()) continue;
1196 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1198 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1199 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1202 if (clrow->GetArray()->GetEntriesFast()<=0) continue;
1203 AliTPCtrackerRow * tpcrow=0;
1206 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1210 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1211 left = (sec-fkNIS*2)/fkNOS;
1214 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1215 for (Int_t j=0;j<tpcrow->GetN1();++j)
1216 tpcrow->SetCluster1(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1219 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1220 for (Int_t j=0;j<tpcrow->GetN2();++j)
1221 tpcrow->SetCluster2(j, *(AliTPCclusterMI*)(clrow->GetArray()->At(j)));
1223 clrow->GetArray()->Clear("C");
1232 Int_t AliTPCtrackerMI::LoadClusters(const TClonesArray *arr)
1235 // load clusters to the memory from one
1238 AliTPCclusterMI *clust=0;
1239 Int_t count[72][96] = { {0} , {0} };
1241 // loop over clusters
1242 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1243 clust = (AliTPCclusterMI*)arr->At(icl);
1244 if(!clust) continue;
1245 //printf("cluster: det %d, row %d \n", clust->GetDetector(),clust->GetRow());
1247 // transform clusters
1250 // count clusters per pad row
1251 count[clust->GetDetector()][clust->GetRow()]++;
1254 // insert clusters to sectors
1255 for (Int_t icl=0; icl<arr->GetEntriesFast(); icl++) {
1256 clust = (AliTPCclusterMI*)arr->At(icl);
1257 if(!clust) continue;
1259 Int_t sec = clust->GetDetector();
1260 Int_t row = clust->GetRow();
1262 // filter overlapping pad rows needed by HLT
1263 if(sec<fkNIS*2) { //IROCs
1264 if(row == 30) continue;
1267 if(row == 27 || row == 76) continue;
1272 // left = sec/fkNIS;
1273 fInnerSec[sec%fkNIS].InsertCluster(clust, count[sec][row], fkParam);
1276 // left = (sec-fkNIS*2)/fkNOS;
1277 fOuterSec[(sec-fkNIS*2)%fkNOS].InsertCluster(clust, count[sec][row], fkParam);
1281 // Load functions must be called behind LoadCluster(TClonesArray*)
1283 //LoadOuterSectors();
1284 //LoadInnerSectors();
1290 Int_t AliTPCtrackerMI::LoadClusters()
1293 // load clusters to the memory
1294 static AliTPCClustersRow *clrow= new AliTPCClustersRow("AliTPCclusterMI");
1296 // TTree * tree = fClustersArray.GetTree();
1298 TTree * tree = fInput;
1299 TBranch * br = tree->GetBranch("Segment");
1300 br->SetAddress(&clrow);
1302 // Conversion of pad, row coordinates in local tracking coords.
1303 // Could be skipped here; is already done in clusterfinder
1305 Int_t j=Int_t(tree->GetEntries());
1306 for (Int_t i=0; i<j; i++) {
1310 fkParam->AdjustSectorRow(clrow->GetID(),sec,row);
1311 for (Int_t icl=0; icl<clrow->GetArray()->GetEntriesFast(); icl++){
1312 Transform((AliTPCclusterMI*)(clrow->GetArray()->At(icl)));
1315 AliTPCtrackerRow * tpcrow=0;
1318 tpcrow = &(fInnerSec[sec%fkNIS][row]);
1322 tpcrow = &(fOuterSec[(sec-fkNIS*2)%fkNOS][row]);
1323 left = (sec-fkNIS*2)/fkNOS;
1326 tpcrow->SetN1(clrow->GetArray()->GetEntriesFast());
1327 for (Int_t k=0;k<tpcrow->GetN1();++k)
1328 tpcrow->SetCluster1(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1331 tpcrow->SetN2(clrow->GetArray()->GetEntriesFast());
1332 for (Int_t k=0;k<tpcrow->GetN2();++k)
1333 tpcrow->SetCluster2(k, *(AliTPCclusterMI*)(clrow->GetArray()->At(k)));
1344 void AliTPCtrackerMI::UnloadClusters()
1347 // unload clusters from the memory
1349 Int_t nrows = fOuterSec->GetNRows();
1350 for (Int_t sec = 0;sec<fkNOS;sec++)
1351 for (Int_t row = 0;row<nrows;row++){
1352 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1354 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1355 // if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1357 tpcrow->ResetClusters();
1360 nrows = fInnerSec->GetNRows();
1361 for (Int_t sec = 0;sec<fkNIS;sec++)
1362 for (Int_t row = 0;row<nrows;row++){
1363 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1365 // if (tpcrow->fClusters1) delete []tpcrow->fClusters1;
1366 //if (tpcrow->fClusters2) delete []tpcrow->fClusters2;
1368 tpcrow->ResetClusters();
1374 void AliTPCtrackerMI::FillClusterArray(TObjArray* array) const{
1376 // Filling cluster to the array - For visualization purposes
1379 nrows = fOuterSec->GetNRows();
1380 for (Int_t sec = 0;sec<fkNOS;sec++)
1381 for (Int_t row = 0;row<nrows;row++){
1382 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1383 if (!tpcrow) continue;
1384 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1385 array->AddLast((TObject*)((*tpcrow)[icl]));
1388 nrows = fInnerSec->GetNRows();
1389 for (Int_t sec = 0;sec<fkNIS;sec++)
1390 for (Int_t row = 0;row<nrows;row++){
1391 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1392 if (!tpcrow) continue;
1393 for (Int_t icl = 0;icl<tpcrow->GetN();icl++){
1394 array->AddLast((TObject*)(*tpcrow)[icl]);
1400 void AliTPCtrackerMI::Transform(AliTPCclusterMI * cluster){
1404 AliTPCcalibDB * calibDB = AliTPCcalibDB::Instance();
1405 AliTPCTransform *transform = calibDB->GetTransform() ;
1407 AliFatal("Tranformations not in calibDB");
1410 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
1411 Double_t x[3]={cluster->GetRow(),cluster->GetPad(),cluster->GetTimeBin()};
1412 Int_t i[1]={cluster->GetDetector()};
1413 transform->Transform(x,i,0,1);
1414 // if (cluster->GetDetector()%36>17){
1419 // in debug mode check the transformation
1421 if (AliTPCReconstructor::StreamLevel()>2) {
1423 cluster->GetGlobalXYZ(gx);
1424 Int_t event = (fEvent==NULL)? 0: fEvent->GetEventNumberInFile();
1425 TTreeSRedirector &cstream = *fDebugStreamer;
1426 cstream<<"Transform"<<
1437 cluster->SetX(x[0]);
1438 cluster->SetY(x[1]);
1439 cluster->SetZ(x[2]);
1444 //if (!fkParam->IsGeoRead()) fkParam->ReadGeoMatrices();
1445 if (AliTPCReconstructor::GetRecoParam()->GetUseSectorAlignment() && (!calibDB->HasAlignmentOCDB())){
1446 TGeoHMatrix *mat = fkParam->GetClusterMatrix(cluster->GetDetector());
1448 Double_t pos[3]= {cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1449 Double_t posC[3]={cluster->GetX(),cluster->GetY(),cluster->GetZ()};
1450 if (mat) mat->LocalToMaster(pos,posC);
1452 // chack Loading of Geo matrices from GeoManager - TEMPORARY FIX
1454 cluster->SetX(posC[0]);
1455 cluster->SetY(posC[1]);
1456 cluster->SetZ(posC[2]);
1460 //_____________________________________________________________________________
1461 Int_t AliTPCtrackerMI::LoadOuterSectors() {
1462 //-----------------------------------------------------------------
1463 // This function fills outer TPC sectors with clusters.
1464 //-----------------------------------------------------------------
1465 Int_t nrows = fOuterSec->GetNRows();
1467 for (Int_t sec = 0;sec<fkNOS;sec++)
1468 for (Int_t row = 0;row<nrows;row++){
1469 AliTPCtrackerRow* tpcrow = &(fOuterSec[sec%fkNOS][row]);
1470 Int_t sec2 = sec+2*fkNIS;
1472 Int_t ncl = tpcrow->GetN1();
1474 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1475 index=(((sec2<<8)+row)<<16)+ncl;
1476 tpcrow->InsertCluster(c,index);
1479 ncl = tpcrow->GetN2();
1481 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1482 index=((((sec2+fkNOS)<<8)+row)<<16)+ncl;
1483 tpcrow->InsertCluster(c,index);
1486 // write indexes for fast acces
1488 for (Int_t i=0;i<510;i++)
1489 tpcrow->SetFastCluster(i,-1);
1490 for (Int_t i=0;i<tpcrow->GetN();i++){
1491 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1492 tpcrow->SetFastCluster(zi,i); // write index
1495 for (Int_t i=0;i<510;i++){
1496 if (tpcrow->GetFastCluster(i)<0)
1497 tpcrow->SetFastCluster(i,last);
1499 last = tpcrow->GetFastCluster(i);
1508 //_____________________________________________________________________________
1509 Int_t AliTPCtrackerMI::LoadInnerSectors() {
1510 //-----------------------------------------------------------------
1511 // This function fills inner TPC sectors with clusters.
1512 //-----------------------------------------------------------------
1513 Int_t nrows = fInnerSec->GetNRows();
1515 for (Int_t sec = 0;sec<fkNIS;sec++)
1516 for (Int_t row = 0;row<nrows;row++){
1517 AliTPCtrackerRow* tpcrow = &(fInnerSec[sec%fkNIS][row]);
1520 Int_t ncl = tpcrow->GetN1();
1522 AliTPCclusterMI *c= (tpcrow->GetCluster1(ncl));
1523 index=(((sec<<8)+row)<<16)+ncl;
1524 tpcrow->InsertCluster(c,index);
1527 ncl = tpcrow->GetN2();
1529 AliTPCclusterMI *c= (tpcrow->GetCluster2(ncl));
1530 index=((((sec+fkNIS)<<8)+row)<<16)+ncl;
1531 tpcrow->InsertCluster(c,index);
1534 // write indexes for fast acces
1536 for (Int_t i=0;i<510;i++)
1537 tpcrow->SetFastCluster(i,-1);
1538 for (Int_t i=0;i<tpcrow->GetN();i++){
1539 Int_t zi = Int_t((*tpcrow)[i]->GetZ()+255.);
1540 tpcrow->SetFastCluster(zi,i); // write index
1543 for (Int_t i=0;i<510;i++){
1544 if (tpcrow->GetFastCluster(i)<0)
1545 tpcrow->SetFastCluster(i,last);
1547 last = tpcrow->GetFastCluster(i);
1559 //_________________________________________________________________________
1560 AliTPCclusterMI *AliTPCtrackerMI::GetClusterMI(Int_t index) const {
1561 //--------------------------------------------------------------------
1562 // Return pointer to a given cluster
1563 //--------------------------------------------------------------------
1564 if (index<0) return 0; // no cluster
1565 Int_t sec=(index&0xff000000)>>24;
1566 Int_t row=(index&0x00ff0000)>>16;
1567 Int_t ncl=(index&0x00007fff)>>00;
1569 const AliTPCtrackerRow * tpcrow=0;
1570 TClonesArray * clrow =0;
1572 if (sec<0 || sec>=fkNIS*4) {
1573 AliWarning(Form("Wrong sector %d",sec));
1578 AliTPCtrackerSector& tracksec = fInnerSec[sec%fkNIS];
1579 if (tracksec.GetNRows()<=row) return 0;
1580 tpcrow = &(tracksec[row]);
1581 if (tpcrow==0) return 0;
1584 if (tpcrow->GetN1()<=ncl) return 0;
1585 clrow = tpcrow->GetClusters1();
1588 if (tpcrow->GetN2()<=ncl) return 0;
1589 clrow = tpcrow->GetClusters2();
1593 AliTPCtrackerSector& tracksec = fOuterSec[(sec-fkNIS*2)%fkNOS];
1594 if (tracksec.GetNRows()<=row) return 0;
1595 tpcrow = &(tracksec[row]);
1596 if (tpcrow==0) return 0;
1598 if (sec-2*fkNIS<fkNOS) {
1599 if (tpcrow->GetN1()<=ncl) return 0;
1600 clrow = tpcrow->GetClusters1();
1603 if (tpcrow->GetN2()<=ncl) return 0;
1604 clrow = tpcrow->GetClusters2();
1608 return (AliTPCclusterMI*)clrow->At(ncl);
1614 Int_t AliTPCtrackerMI::FollowToNext(AliTPCseed& t, Int_t nr) {
1615 //-----------------------------------------------------------------
1616 // This function tries to find a track prolongation to next pad row
1617 //-----------------------------------------------------------------
1619 Double_t x= GetXrow(nr), ymax=GetMaxY(nr);
1622 AliTPCclusterMI *cl=0;
1623 Int_t tpcindex= t.GetClusterIndex2(nr);
1625 // update current shape info every 5 pad-row
1626 // if ( (nr%5==0) || t.GetNumberOfClusters()<2 || (t.fCurrentSigmaY2<0.0001) ){
1630 if (fIteration>0 && tpcindex>=-1){ //if we have already clusters
1632 if (tpcindex==-1) return 0; //track in dead zone
1633 if (tpcindex >= 0){ //
1634 cl = t.GetClusterPointer(nr);
1635 //if (cl==0) cl = GetClusterMI(tpcindex);
1636 if (!cl) cl = GetClusterMI(tpcindex);
1637 t.SetCurrentClusterIndex1(tpcindex);
1640 Int_t relativesector = ((tpcindex&0xff000000)>>24)%18; // if previously accepted cluster in different sector
1641 Float_t angle = relativesector*fSectors->GetAlpha()+fSectors->GetAlphaShift();
1643 if (angle<-TMath::Pi()) angle += 2*TMath::Pi();
1644 if (angle>=TMath::Pi()) angle -= 2*TMath::Pi();
1646 if (TMath::Abs(angle-t.GetAlpha())>0.001){
1647 Double_t rotation = angle-t.GetAlpha();
1648 t.SetRelativeSector(relativesector);
1649 if (!t.Rotate(rotation)) {
1650 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1654 if (!t.PropagateTo(x)) {
1655 t.SetClusterIndex(nr, t.GetClusterIndex(nr) | 0x8000);
1659 t.SetCurrentCluster(cl);
1661 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1662 if ((tpcindex&0x8000)==0) accept =0;
1664 //if founded cluster is acceptible
1665 if (cl->IsUsed(11)) { // id cluster is shared inrease uncertainty
1666 t.SetErrorY2(t.GetErrorY2()+0.03);
1667 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1668 t.SetErrorY2(t.GetErrorY2()*3);
1669 t.SetErrorZ2(t.GetErrorZ2()*3);
1671 t.SetNFoundable(t.GetNFoundable()+1);
1672 UpdateTrack(&t,accept);
1675 else { // Remove old cluster from track
1676 t.SetClusterIndex(nr, -3);
1677 t.SetClusterPointer(nr, 0);
1681 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0; // cut on angle
1682 if (fIteration>1 && IsFindable(t)){
1683 // not look for new cluster during refitting
1684 t.SetNFoundable(t.GetNFoundable()+1);
1689 // if (TMath::Abs(t.GetSnp())>0.95 || TMath::Abs(x*t.GetC()-t.GetEta())>0.95) return 0;// patch 28 fev 06
1690 if (!t.PropagateTo(x)) {
1691 if (fIteration==0) t.SetRemoval(10);
1694 Double_t y = t.GetY();
1695 if (TMath::Abs(y)>ymax){
1697 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1698 if (!t.Rotate(fSectors->GetAlpha()))
1700 } else if (y <-ymax) {
1701 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1702 if (!t.Rotate(-fSectors->GetAlpha()))
1705 if (!t.PropagateTo(x)) {
1706 if (fIteration==0) t.SetRemoval(10);
1712 Double_t z=t.GetZ();
1715 if (!IsActive(t.GetRelativeSector(),nr)) {
1717 t.SetClusterIndex2(nr,-1);
1720 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1721 Bool_t isActive = IsActive(t.GetRelativeSector(),nr);
1722 Bool_t isActive2 = (nr>=fInnerSec->GetNRows()) ? fOuterSec[t.GetRelativeSector()][nr-fInnerSec->GetNRows()].GetN()>0:fInnerSec[t.GetRelativeSector()][nr].GetN()>0;
1724 if (!isActive || !isActive2) return 0;
1726 const AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
1727 if ( (t.GetSigmaY2()<0) || t.GetSigmaZ2()<0) return 0;
1729 Double_t roadz = 1.;
1731 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1733 t.SetClusterIndex2(nr,-1);
1739 // if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*x+10) && TMath::Abs(z)<fkParam->GetZLength(0) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
1740 t.SetNFoundable(t.GetNFoundable()+1);
1746 // cl = krow.FindNearest2(y+10.,z,roady,roadz,index);
1747 cl = krow.FindNearest2(y,z,roady,roadz,index);
1748 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(index));
1751 t.SetCurrentCluster(cl);
1753 if (fIteration==2&&cl->IsUsed(10)) return 0;
1754 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1755 if (fIteration==2&&cl->IsUsed(11)) {
1756 t.SetErrorY2(t.GetErrorY2()+0.03);
1757 t.SetErrorZ2(t.GetErrorZ2()+0.03);
1758 t.SetErrorY2(t.GetErrorY2()*3);
1759 t.SetErrorZ2(t.GetErrorZ2()*3);
1762 if (t.fCurrentCluster->IsUsed(10)){
1767 if (t.fNShared>0.7*t.GetNumberOfClusters()) {
1773 if (accept<3) UpdateTrack(&t,accept);
1776 if ( fIteration==0 && t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) t.SetRemoval(10);
1784 //_________________________________________________________________________
1785 Bool_t AliTPCtrackerMI::GetTrackPoint(Int_t index, AliTrackPoint &p ) const
1787 // Get track space point by index
1788 // return false in case the cluster doesn't exist
1789 AliTPCclusterMI *cl = GetClusterMI(index);
1790 if (!cl) return kFALSE;
1791 Int_t sector = (index&0xff000000)>>24;
1792 // Int_t row = (index&0x00ff0000)>>16;
1794 // xyz[0] = fkParam->GetPadRowRadii(sector,row);
1795 xyz[0] = cl->GetX();
1796 xyz[1] = cl->GetY();
1797 xyz[2] = cl->GetZ();
1799 fkParam->AdjustCosSin(sector,cos,sin);
1800 Float_t x = cos*xyz[0]-sin*xyz[1];
1801 Float_t y = cos*xyz[1]+sin*xyz[0];
1803 Float_t sigmaY2 = 0.027*cl->GetSigmaY2();
1804 if (sector < fkParam->GetNInnerSector()) sigmaY2 *= 2.07;
1805 Float_t sigmaZ2 = 0.066*cl->GetSigmaZ2();
1806 if (sector < fkParam->GetNInnerSector()) sigmaZ2 *= 1.77;
1807 cov[0] = sin*sin*sigmaY2;
1808 cov[1] = -sin*cos*sigmaY2;
1810 cov[3] = cos*cos*sigmaY2;
1813 p.SetXYZ(x,y,xyz[2],cov);
1814 AliGeomManager::ELayerID iLayer;
1816 if (sector < fkParam->GetNInnerSector()) {
1817 iLayer = AliGeomManager::kTPC1;
1821 iLayer = AliGeomManager::kTPC2;
1822 idet = sector - fkParam->GetNInnerSector();
1824 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,idet);
1825 p.SetVolumeID(volid);
1831 Int_t AliTPCtrackerMI::UpdateClusters(AliTPCseed& t, Int_t nr) {
1832 //-----------------------------------------------------------------
1833 // This function tries to find a track prolongation to next pad row
1834 //-----------------------------------------------------------------
1835 t.SetCurrentCluster(0);
1836 t.SetCurrentClusterIndex1(-3);
1838 Double_t xt=t.GetX();
1839 Int_t row = GetRowNumber(xt)-1;
1840 Double_t ymax= GetMaxY(nr);
1842 if (row < nr) return 1; // don't prolongate if not information until now -
1843 // if (TMath::Abs(t.GetSnp())>0.9 && t.GetNumberOfClusters()>40. && fIteration!=2) {
1845 // return 0; // not prolongate strongly inclined tracks
1847 // if (TMath::Abs(t.GetSnp())>0.95) {
1849 // return 0; // not prolongate strongly inclined tracks
1850 // }// patch 28 fev 06
1852 Double_t x= GetXrow(nr);
1854 //t.PropagateTo(x+0.02);
1855 //t.PropagateTo(x+0.01);
1856 if (!t.PropagateTo(x)){
1863 if (TMath::Abs(y)>ymax){
1865 t.SetRelativeSector((t.GetRelativeSector()+1) % fN);
1866 if (!t.Rotate(fSectors->GetAlpha()))
1868 } else if (y <-ymax) {
1869 t.SetRelativeSector((t.GetRelativeSector()-1+fN) % fN);
1870 if (!t.Rotate(-fSectors->GetAlpha()))
1873 // if (!t.PropagateTo(x)){
1880 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()) return 0;
1882 if (!IsActive(t.GetRelativeSector(),nr)) {
1884 t.SetClusterIndex2(nr,-1);
1887 //AliInfo(Form("A - Sector%d phi %f - alpha %f", t.fRelativeSector,y/x, t.GetAlpha()));
1889 AliTPCtrackerRow &krow=GetRow(t.GetRelativeSector(),nr);
1891 if (TMath::Abs(TMath::Abs(y)-ymax)<krow.GetDeadZone()){
1893 t.SetClusterIndex2(nr,-1);
1899 // if (TMath::Abs(t.GetZ())<(AliTPCReconstructor::GetCtgRange()*t.GetX()+10) && (TMath::Abs(t.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
1900 if (IsFindable(t)) t.SetNFoundable(t.GetNFoundable()+1);
1906 if ( (nr%2==0) || t.GetNumberOfClusters()<2){
1907 // t.fCurrentSigmaY = GetSigmaY(&t);
1908 //t.fCurrentSigmaZ = GetSigmaZ(&t);
1912 AliTPCclusterMI *cl=0;
1915 Double_t roady = 1.;
1916 Double_t roadz = 1.;
1920 index = t.GetClusterIndex2(nr);
1921 if ( (index >= 0) && (index&0x8000)==0){
1922 cl = t.GetClusterPointer(nr);
1923 if ( (cl==0) && (index >= 0)) cl = GetClusterMI(index);
1924 t.SetCurrentClusterIndex1(index);
1926 t.SetCurrentCluster(cl);
1932 // if (index<0) return 0;
1933 UInt_t uindex = TMath::Abs(index);
1936 //cl = krow.FindNearest2(y+10,z,roady,roadz,uindex);
1937 cl = krow.FindNearest2(y,z,roady,roadz,uindex);
1940 if (cl) t.SetCurrentClusterIndex1(krow.GetIndex(uindex));
1941 t.SetCurrentCluster(cl);
1947 Int_t AliTPCtrackerMI::FollowToNextCluster(AliTPCseed & t, Int_t nr) {
1948 //-----------------------------------------------------------------
1949 // This function tries to find a track prolongation to next pad row
1950 //-----------------------------------------------------------------
1952 //update error according neighborhoud
1954 if (t.GetCurrentCluster()) {
1956 Int_t accept = AcceptCluster(&t,t.GetCurrentCluster());
1958 if (t.GetCurrentCluster()->IsUsed(10)){
1963 t.SetNShared(t.GetNShared()+1);
1964 if (t.GetNShared()>0.7*t.GetNumberOfClusters()) {
1969 if (fIteration>0) accept = 0;
1970 if (accept<3) UpdateTrack(&t,accept);
1974 if ( t.GetNumberOfClusters()>18 && ( (t.GetSigmaY2()+t.GetSigmaZ2())>0.16)) t.SetRemoval(10);
1975 if ( t.GetNumberOfClusters()>18 && t.GetChi2()/t.GetNumberOfClusters()>6 ) t.SetRemoval(10);
1977 if (( (t.GetNFoundable()*0.5 > t.GetNumberOfClusters()) || t.GetNoCluster()>15)) t.SetRemoval(10);
1985 //_____________________________________________________________________________
1986 Int_t AliTPCtrackerMI::FollowProlongation(AliTPCseed& t, Int_t rf, Int_t step, Bool_t fromSeeds) {
1987 //-----------------------------------------------------------------
1988 // This function tries to find a track prolongation.
1989 //-----------------------------------------------------------------
1990 Double_t xt=t.GetX();
1992 Double_t alpha=t.GetAlpha();
1993 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
1994 if (alpha < 0. ) alpha += 2.*TMath::Pi();
1996 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
1998 Int_t first = GetRowNumber(xt);
2003 for (Int_t nr= first; nr>=rf; nr-=step) {
2005 if (t.GetKinkIndexes()[0]>0){
2006 for (Int_t i=0;i<3;i++){
2007 Int_t index = t.GetKinkIndexes()[i];
2008 if (index==0) break;
2009 if (index<0) continue;
2011 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2013 printf("PROBLEM\n");
2016 Int_t kinkrow = kink->GetTPCRow0()+2+Int_t(0.5/(0.05+kink->GetAngle(2)));
2018 AliExternalTrackParam paramd(t);
2019 kink->SetDaughter(paramd);
2020 kink->SetStatus(2,5);
2027 if (nr==80) t.UpdateReference();
2028 if (nr<fInnerSec->GetNRows())
2029 fSectors = fInnerSec;
2031 fSectors = fOuterSec;
2032 if (FollowToNext(t,nr)==0)
2045 Int_t AliTPCtrackerMI::FollowBackProlongation(AliTPCseed& t, Int_t rf, Bool_t fromSeeds) {
2046 //-----------------------------------------------------------------
2047 // This function tries to find a track prolongation.
2048 //-----------------------------------------------------------------
2050 Double_t xt=t.GetX();
2051 Double_t alpha=t.GetAlpha();
2052 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2053 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2054 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
2056 Int_t first = t.GetFirstPoint();
2057 Int_t ri = GetRowNumber(xt);
2061 if (first<ri) first = ri;
2063 if (first<0) first=0;
2064 for (Int_t nr=first; nr<=rf; nr++) {
2065 // if ( (TMath::Abs(t.GetSnp())>0.95)) break;//patch 28 fev 06
2066 if (t.GetKinkIndexes()[0]<0){
2067 for (Int_t i=0;i<3;i++){
2068 Int_t index = t.GetKinkIndexes()[i];
2069 if (index==0) break;
2070 if (index>0) continue;
2071 index = TMath::Abs(index);
2072 AliKink * kink = (AliKink*)fEvent->GetKink(index-1);
2074 printf("PROBLEM\n");
2077 Int_t kinkrow = kink->GetTPCRow0()-2-Int_t(0.5/(0.05+kink->GetAngle(2)));
2079 AliExternalTrackParam paramm(t);
2080 kink->SetMother(paramm);
2081 kink->SetStatus(2,1);
2088 if (nr<fInnerSec->GetNRows())
2089 fSectors = fInnerSec;
2091 fSectors = fOuterSec;
2102 Float_t AliTPCtrackerMI::OverlapFactor(AliTPCseed * s1, AliTPCseed * s2, Int_t &sum1, Int_t & sum2)
2104 // overlapping factor
2110 Float_t dz2 =(s1->GetZ() - s2->GetZ());
2113 Float_t dy2 =TMath::Abs((s1->GetY() - s2->GetY()));
2115 Float_t distance = TMath::Sqrt(dz2+dy2);
2116 if (distance>4.) return 0; // if there are far away - not overlap - to reduce combinatorics
2119 Int_t firstpoint = TMath::Min(s1->GetFirstPoint(),s2->GetFirstPoint());
2120 Int_t lastpoint = TMath::Max(s1->GetLastPoint(),s2->GetLastPoint());
2125 if (firstpoint>lastpoint) {
2126 firstpoint =lastpoint;
2131 for (Int_t i=firstpoint-1;i<lastpoint+1;i++){
2132 if (s1->GetClusterIndex2(i)>0) sum1++;
2133 if (s2->GetClusterIndex2(i)>0) sum2++;
2134 if (s1->GetClusterIndex2(i)==s2->GetClusterIndex2(i) && s1->GetClusterIndex2(i)>0) {
2138 if (sum<5) return 0;
2140 Float_t summin = TMath::Min(sum1+1,sum2+1);
2141 Float_t ratio = (sum+1)/Float_t(summin);
2145 void AliTPCtrackerMI::SignShared(AliTPCseed * s1, AliTPCseed * s2)
2149 Float_t thetaCut = 0.2;//+10.*TMath::Sqrt(s1->GetSigmaTglZ()+ s2->GetSigmaTglZ());
2150 if (TMath::Abs(s1->GetTgl()-s2->GetTgl())>thetaCut) return;
2151 Float_t minCl = TMath::Min(s1->GetNumberOfClusters(),s2->GetNumberOfClusters());
2152 Int_t cutN0 = TMath::Max(5,TMath::Nint(0.1*minCl));
2157 //Int_t firstpoint = TMath::Max(s1->GetFirstPoint(),s2->GetFirstPoint());
2158 //Int_t lastpoint = TMath::Min(s1->GetLastPoint(),s2->GetLastPoint());
2159 Int_t firstpoint = 0;
2160 Int_t lastpoint = 160;
2162 // if (firstpoint>=lastpoint-5) return;;
2164 for (Int_t i=firstpoint;i<lastpoint;i++){
2165 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2166 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2170 if (sumshared>cutN0){
2173 for (Int_t i=firstpoint;i<lastpoint;i++){
2174 // if ( (s1->GetClusterIndex2(i)&0xFFFF8FFF)==(s2->GetClusterIndex2(i)&0xFFFF8FFF) && s1->GetClusterIndex2(i)>0) {
2175 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
2176 AliTPCTrackerPoint *p1 = s1->GetTrackPoint(i);
2177 AliTPCTrackerPoint *p2 = s2->GetTrackPoint(i);;
2178 if (s1->IsActive()&&s2->IsActive()){
2179 p1->SetShared(kTRUE);
2180 p2->SetShared(kTRUE);
2186 if (sumshared>cutN0){
2187 for (Int_t i=0;i<4;i++){
2188 if (s1->GetOverlapLabel(3*i)==0){
2189 s1->SetOverlapLabel(3*i, s2->GetLabel());
2190 s1->SetOverlapLabel(3*i+1,sumshared);
2191 s1->SetOverlapLabel(3*i+2,s2->GetUniqueID());
2195 for (Int_t i=0;i<4;i++){
2196 if (s2->GetOverlapLabel(3*i)==0){
2197 s2->SetOverlapLabel(3*i, s1->GetLabel());
2198 s2->SetOverlapLabel(3*i+1,sumshared);
2199 s2->SetOverlapLabel(3*i+2,s1->GetUniqueID());
2206 void AliTPCtrackerMI::SignShared(TObjArray * arr)
2209 //sort trackss according sectors
2211 for (Int_t i=0; i<arr->GetEntriesFast(); i++) {
2212 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2214 //if (pt) RotateToLocal(pt);
2218 arr->Sort(); // sorting according relative sectors
2219 arr->Expand(arr->GetEntries());
2222 Int_t nseed=arr->GetEntriesFast();
2223 for (Int_t i=0; i<nseed; i++) {
2224 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2226 for (Int_t j=0;j<12;j++){
2227 pt->SetOverlapLabel(j,0);
2230 for (Int_t i=0; i<nseed; i++) {
2231 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2233 if (pt->GetRemoval()>10) continue;
2234 for (Int_t j=i+1; j<nseed; j++){
2235 AliTPCseed *pt2=(AliTPCseed*)arr->UncheckedAt(j);
2236 if (TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>1) continue;
2238 if (pt2->GetRemoval()<=10) {
2239 //if ( TMath::Abs(pt->GetRelativeSector()-pt2->GetRelativeSector())>0) break;
2247 void AliTPCtrackerMI::SortTracks(TObjArray * arr, Int_t mode) const
2250 //sort tracks in array according mode criteria
2251 Int_t nseed = arr->GetEntriesFast();
2252 for (Int_t i=0; i<nseed; i++) {
2253 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2264 void AliTPCtrackerMI::RemoveUsed2(TObjArray * arr, Float_t factor1, Float_t factor2, Int_t minimal)
2267 // Loop over all tracks and remove overlaped tracks (with lower quality)
2269 // 1. Unsign clusters
2270 // 2. Sort tracks according quality
2271 // Quality is defined by the number of cluster between first and last points
2273 // 3. Loop over tracks - decreasing quality order
2274 // a.) remove - If the fraction of shared cluster less than factor (1- n or 2)
2275 // b.) remove - If the minimal number of clusters less than minimal and not ITS
2276 // c.) if track accepted - sign clusters
2278 //Called in - AliTPCtrackerMI::Clusters2Tracks()
2279 // - AliTPCtrackerMI::PropagateBack()
2280 // - AliTPCtrackerMI::RefitInward()
2283 // factor1 - factor for constrained
2284 // factor2 - for non constrained tracks
2285 // if (Float_t(shared+1)/Float_t(found+1)>factor) - DELETE
2289 Int_t nseed = arr->GetEntriesFast();
2290 Float_t * quality = new Float_t[nseed];
2291 Int_t * indexes = new Int_t[nseed];
2295 for (Int_t i=0; i<nseed; i++) {
2296 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2301 pt->UpdatePoints(); //select first last max dens points
2302 Float_t * points = pt->GetPoints();
2303 if (points[3]<0.8) quality[i] =-1;
2304 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
2305 //prefer high momenta tracks if overlaps
2306 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
2308 TMath::Sort(nseed,quality,indexes);
2311 for (Int_t itrack=0; itrack<nseed; itrack++) {
2312 Int_t trackindex = indexes[itrack];
2313 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(trackindex);
2316 if (quality[trackindex]<0){
2317 MarkSeedFree( arr->RemoveAt(trackindex) );
2322 Int_t first = Int_t(pt->GetPoints()[0]);
2323 Int_t last = Int_t(pt->GetPoints()[2]);
2324 Double_t factor = (pt->GetBConstrain()) ? factor1: factor2;
2326 Int_t found,foundable,shared;
2327 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
2328 // pt->GetClusterStatistic(0,160, found, foundable,shared,kFALSE);
2329 Bool_t itsgold =kFALSE;
2332 if (pt->GetESD()->GetITSclusters(dummy)>4) itsgold= kTRUE;
2336 if (Float_t(shared+1)/Float_t(found+1)>factor){
2337 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2338 if( AliTPCReconstructor::StreamLevel()>3){
2339 TTreeSRedirector &cstream = *fDebugStreamer;
2340 cstream<<"RemoveUsed"<<
2341 "iter="<<fIteration<<
2345 MarkSeedFree( arr->RemoveAt(trackindex) );
2348 if (pt->GetNumberOfClusters()<50&&(found-0.5*shared)<minimal){ //remove short tracks
2349 if (pt->GetKinkIndexes()[0]!=0) continue; //don't remove tracks - part of the kinks
2350 if( AliTPCReconstructor::StreamLevel()>3){
2351 TTreeSRedirector &cstream = *fDebugStreamer;
2352 cstream<<"RemoveShort"<<
2353 "iter="<<fIteration<<
2357 MarkSeedFree( arr->RemoveAt(trackindex) );
2363 //if (sharedfactor>0.4) continue;
2364 if (pt->GetKinkIndexes()[0]>0) continue;
2365 //Remove tracks with undefined properties - seems
2366 if (pt->GetSigmaY2()<kAlmost0) continue; // ? what is the origin ?
2368 for (Int_t i=first; i<last; i++) {
2369 Int_t index=pt->GetClusterIndex2(i);
2370 // if (index<0 || index&0x8000 ) continue;
2371 if (index<0 || index&0x8000 ) continue;
2372 AliTPCclusterMI *c= pt->GetClusterPointer(i);
2379 Info("RemoveUsed","\n*****\nNumber of good tracks after shared removal\t%d\n",fNtracks);
2385 void AliTPCtrackerMI::DumpClusters(Int_t iter, TObjArray *trackArray)
2388 // Dump clusters after reco
2389 // signed and unsigned cluster can be visualized
2390 // 1. Unsign all cluster
2391 // 2. Sign all used clusters
2394 Int_t nseed = trackArray->GetEntries();
2395 for (Int_t i=0; i<nseed; i++){
2396 AliTPCseed *pt=(AliTPCseed*)trackArray->UncheckedAt(i);
2400 Bool_t isKink=pt->GetKinkIndex(0)!=0;
2401 for (Int_t j=0; j<160; ++j) {
2402 Int_t index=pt->GetClusterIndex2(j);
2403 if (index<0) continue;
2404 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2406 if (isKink) c->Use(100); // kink
2407 c->Use(10); // by default usage 10
2412 for (Int_t sec=0;sec<fkNIS;sec++){
2413 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2414 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2415 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++){
2416 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2417 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2418 (*fDebugStreamer)<<"clDump"<<
2426 cla = fInnerSec[sec][row].GetClusters2();
2427 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++){
2428 AliTPCclusterMI* cl = (AliTPCclusterMI*)cla->At(icl);
2429 Float_t gx[3]; cl->GetGlobalXYZ(gx);
2430 (*fDebugStreamer)<<"clDump"<<
2441 for (Int_t sec=0;sec<fkNOS;sec++){
2442 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2443 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2444 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++){
2446 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2447 cl->GetGlobalXYZ(gx);
2448 (*fDebugStreamer)<<"clDump"<<
2456 cla = fOuterSec[sec][row].GetClusters2();
2457 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++){
2459 AliTPCclusterMI* cl = (AliTPCclusterMI*) cla->At(icl);
2460 cl->GetGlobalXYZ(gx);
2461 (*fDebugStreamer)<<"clDump"<<
2473 void AliTPCtrackerMI::UnsignClusters()
2476 // loop over all clusters and unsign them
2479 for (Int_t sec=0;sec<fkNIS;sec++){
2480 for (Int_t row=0;row<fInnerSec->GetNRows();row++){
2481 TClonesArray *cla = fInnerSec[sec][row].GetClusters1();
2482 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN1();icl++)
2483 // if (cl[icl].IsUsed(10))
2484 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2485 cla = fInnerSec[sec][row].GetClusters2();
2486 for (Int_t icl =0;icl< fInnerSec[sec][row].GetN2();icl++)
2487 //if (cl[icl].IsUsed(10))
2488 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2492 for (Int_t sec=0;sec<fkNOS;sec++){
2493 for (Int_t row=0;row<fOuterSec->GetNRows();row++){
2494 TClonesArray *cla = fOuterSec[sec][row].GetClusters1();
2495 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN1();icl++)
2496 //if (cl[icl].IsUsed(10))
2497 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2498 cla = fOuterSec[sec][row].GetClusters2();
2499 for (Int_t icl =0;icl< fOuterSec[sec][row].GetN2();icl++)
2500 //if (cl[icl].IsUsed(10))
2501 ((AliTPCclusterMI*) cla->At(icl))->Use(-1);
2509 void AliTPCtrackerMI::SignClusters(const TObjArray * arr, Float_t fnumber, Float_t fdensity)
2512 //sign clusters to be "used"
2514 // snumber and sdensity sign number of sigmas - bellow mean value to be accepted
2515 // loop over "primaries"
2529 Int_t nseed = arr->GetEntriesFast();
2530 for (Int_t i=0; i<nseed; i++) {
2531 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2535 if (!(pt->IsActive())) continue;
2536 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2537 if ( (dens>0.7) && (pt->GetNumberOfClusters()>70)){
2539 sumdens2+= dens*dens;
2540 sumn += pt->GetNumberOfClusters();
2541 sumn2 += pt->GetNumberOfClusters()*pt->GetNumberOfClusters();
2542 Float_t chi2 = pt->GetChi2()/pt->GetNumberOfClusters();
2545 sumchi2 +=chi2*chi2;
2550 Float_t mdensity = 0.9;
2551 Float_t meann = 130;
2552 Float_t meanchi = 1;
2553 Float_t sdensity = 0.1;
2554 Float_t smeann = 10;
2555 Float_t smeanchi =0.4;
2559 mdensity = sumdens/sum;
2561 meanchi = sumchi/sum;
2563 sdensity = sumdens2/sum-mdensity*mdensity;
2565 sdensity = TMath::Sqrt(sdensity);
2569 smeann = sumn2/sum-meann*meann;
2571 smeann = TMath::Sqrt(smeann);
2575 smeanchi = sumchi2/sum - meanchi*meanchi;
2577 smeanchi = TMath::Sqrt(smeanchi);
2583 //REMOVE SHORT DELTAS or tracks going out of sensitive volume of TPC
2585 for (Int_t i=0; i<nseed; i++) {
2586 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2590 if (pt->GetBSigned()) continue;
2591 if (pt->GetBConstrain()) continue;
2592 //if (!(pt->IsActive())) continue;
2594 Int_t found,foundable,shared;
2595 pt->GetClusterStatistic(0,160,found, foundable,shared);
2596 if (shared/float(found)>0.3) {
2597 if (shared/float(found)>0.9 ){
2598 //MarkSeedFree( arr->RemoveAt(i) );
2603 Bool_t isok =kFALSE;
2604 if ( (pt->GetNShared()/pt->GetNumberOfClusters()<0.5) &&pt->GetNumberOfClusters()>60)
2606 if ((TMath::Abs(1/pt->GetC())<100.) && (pt->GetNShared()/pt->GetNumberOfClusters()<0.7))
2608 if (TMath::Abs(pt->GetZ()/pt->GetX())>1.1)
2610 if ( (TMath::Abs(pt->GetSnp()>0.7) && pt->GetD(0,0)>60.))
2614 for (Int_t j=0; j<160; ++j) {
2615 Int_t index=pt->GetClusterIndex2(j);
2616 if (index<0) continue;
2617 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2619 //if (!(c->IsUsed(10))) c->Use();
2626 Double_t maxchi = meanchi+2.*smeanchi;
2628 for (Int_t i=0; i<nseed; i++) {
2629 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
2633 //if (!(pt->IsActive())) continue;
2634 if (pt->GetBSigned()) continue;
2635 Double_t chi = pt->GetChi2()/pt->GetNumberOfClusters();
2636 if (chi>maxchi) continue;
2639 Float_t dens = pt->GetNumberOfClusters()/Float_t(pt->GetNFoundable());
2641 //sign only tracks with enoug big density at the beginning
2643 if ((pt->GetDensityFirst(40)<0.75) && pt->GetNumberOfClusters()<meann) continue;
2646 Double_t mindens = TMath::Max(double(mdensity-sdensity*fdensity*bfactor),0.65);
2647 Double_t minn = TMath::Max(Int_t(meann-fnumber*smeann*bfactor),50);
2649 // if (pt->fBConstrain) mindens = TMath::Max(mdensity-sdensity*fdensity*bfactor,0.65);
2650 if ( (pt->GetRemoval()==10) && (pt->GetSnp()>0.8)&&(dens>mindens))
2653 if ((dens>mindens && pt->GetNumberOfClusters()>minn) && chi<maxchi ){
2654 //Int_t noc=pt->GetNumberOfClusters();
2655 pt->SetBSigned(kTRUE);
2656 for (Int_t j=0; j<160; ++j) {
2658 Int_t index=pt->GetClusterIndex2(j);
2659 if (index<0) continue;
2660 AliTPCclusterMI *c= pt->GetClusterPointer(j);
2662 // if (!(c->IsUsed(10))) c->Use();
2667 // gLastCheck = nseed;
2676 Int_t AliTPCtrackerMI::RefitInward(AliESDEvent *event)
2679 // back propagation of ESD tracks
2682 if (!event) return 0;
2683 const Int_t kMaxFriendTracks=2000;
2686 // extract correction object for multiplicity dependence of dEdx
2687 TObjArray * gainCalibArray = AliTPCcalibDB::Instance()->GetTimeGainSplinesRun(event->GetRunNumber());
2689 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
2691 AliFatal("Tranformations not in RefitInward");
2694 transform->SetCurrentRecoParam((AliTPCRecoParam*)AliTPCReconstructor::GetRecoParam());
2695 const AliTPCRecoParam * recoParam = AliTPCcalibDB::Instance()->GetTransform()->GetCurrentRecoParam();
2696 Int_t nContribut = event->GetNumberOfTracks();
2697 TGraphErrors * graphMultDependenceDeDx = 0x0;
2698 if (recoParam && recoParam->GetUseMultiplicityCorrectionDedx() && gainCalibArray) {
2699 if (recoParam->GetUseTotCharge()) {
2700 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQTOT_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2702 graphMultDependenceDeDx = (TGraphErrors *) gainCalibArray->FindObject("TGRAPHERRORS_MEANQMAX_MULTIPLICITYDEPENDENCE_BEAM_ALL");
2708 //PrepareForProlongation(fSeeds,1);
2709 PropagateForward2(fSeeds);
2710 RemoveUsed2(fSeeds,0.4,0.4,20);
2712 TObjArray arraySeed(fSeeds->GetEntries());
2713 for (Int_t i=0;i<fSeeds->GetEntries();i++) {
2714 arraySeed.AddAt(fSeeds->At(i),i);
2716 SignShared(&arraySeed);
2717 // FindCurling(fSeeds, event,2); // find multi found tracks
2718 FindSplitted(fSeeds, event,2); // find multi found tracks
2719 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,2); // find multi found tracks
2722 Int_t nseed = fSeeds->GetEntriesFast();
2723 for (Int_t i=0;i<nseed;i++){
2724 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2725 if (!seed) continue;
2726 if (seed->GetKinkIndex(0)>0) UpdateKinkQualityD(seed); // update quality informations for kinks
2727 AliESDtrack *esd=event->GetTrack(i);
2729 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
2730 AliExternalTrackParam paramIn;
2731 AliExternalTrackParam paramOut;
2732 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
2733 if (AliTPCReconstructor::StreamLevel()>2) {
2734 (*fDebugStreamer)<<"RecoverIn"<<
2738 "pout.="<<¶mOut<<
2743 seed->Set(paramIn.GetX(),paramIn.GetAlpha(),paramIn.GetParameter(),paramIn.GetCovariance());
2744 seed->SetNumberOfClusters(ncl);
2748 seed->PropagateTo(fkParam->GetInnerRadiusLow());
2749 seed->UpdatePoints();
2750 AddCovariance(seed);
2751 MakeESDBitmaps(seed, esd);
2752 seed->CookdEdx(0.02,0.6);
2753 CookLabel(seed,0.1); //For comparison only
2755 if (AliTPCReconstructor::StreamLevel()>1 && seed!=0) {
2756 TTreeSRedirector &cstream = *fDebugStreamer;
2763 if (seed->GetNumberOfClusters()>15){
2764 esd->UpdateTrackParams(seed,AliESDtrack::kTPCrefit);
2765 esd->SetTPCPoints(seed->GetPoints());
2766 esd->SetTPCPointsF(seed->GetNFoundable());
2767 Int_t ndedx = seed->GetNCDEDX(0);
2768 Float_t sdedx = seed->GetSDEDX(0);
2769 Float_t dedx = seed->GetdEdx();
2770 // apply mutliplicity dependent dEdx correction if available
2771 if (graphMultDependenceDeDx) {
2772 Double_t corrGain = AliTPCcalibDButil::EvalGraphConst(graphMultDependenceDeDx, nContribut);
2773 dedx += (1 - corrGain)*50.; // MIP is normalized to 50
2775 esd->SetTPCsignal(dedx, sdedx, ndedx);
2777 // fill new dEdx information
2779 Double32_t signal[4];
2783 for(Int_t iarr=0;iarr<3;iarr++) {
2784 signal[iarr] = seed->GetDEDXregion(iarr+1);
2785 ncl[iarr] = seed->GetNCDEDX(iarr+1);
2786 nrows[iarr] = seed->GetNCDEDXInclThres(iarr+1);
2788 signal[3] = seed->GetDEDXregion(4);
2790 AliTPCdEdxInfo * infoTpcPid = new AliTPCdEdxInfo();
2791 infoTpcPid->SetTPCSignalRegionInfo(signal, ncl, nrows);
2792 esd->SetTPCdEdxInfo(infoTpcPid);
2794 // add seed to the esd track in Calib level
2796 Bool_t storeFriend = gRandom->Rndm()<(kMaxFriendTracks)/Float_t(nseed);
2797 if (AliTPCReconstructor::StreamLevel()>0 &&storeFriend){
2798 // RS: this is the only place where the seed is created not in the pool,
2799 // since it should belong to ESDevent
2800 AliTPCseed * seedCopy = new AliTPCseed(*seed, kTRUE);
2801 esd->AddCalibObject(seedCopy);
2806 //printf("problem\n");
2809 //FindKinks(fSeeds,event);
2810 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(2,fSeeds);
2811 Info("RefitInward","Number of refitted tracks %d",ntracks);
2813 AliCosmicTracker::FindCosmic(event, kTRUE);
2819 Int_t AliTPCtrackerMI::PropagateBack(AliESDEvent *event)
2822 // back propagation of ESD tracks
2824 if (!event) return 0;
2829 PropagateBack(fSeeds);
2830 RemoveUsed2(fSeeds,0.4,0.4,20);
2831 //FindCurling(fSeeds, fEvent,1);
2832 FindSplitted(fSeeds, event,1); // find multi found tracks
2833 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,1); // find multi found tracks
2836 Int_t nseed = fSeeds->GetEntriesFast();
2838 for (Int_t i=0;i<nseed;i++){
2839 AliTPCseed * seed = (AliTPCseed*) fSeeds->UncheckedAt(i);
2840 if (!seed) continue;
2841 if (seed->GetKinkIndex(0)<0) UpdateKinkQualityM(seed); // update quality informations for kinks
2842 seed->UpdatePoints();
2843 AddCovariance(seed);
2844 AliESDtrack *esd=event->GetTrack(i);
2845 if (!esd) continue; //never happen
2846 if (seed->GetNumberOfClusters()<60 && seed->GetNumberOfClusters()<(esd->GetTPCclusters(0) -5)*0.8){
2847 AliExternalTrackParam paramIn;
2848 AliExternalTrackParam paramOut;
2849 Int_t ncl = seed->RefitTrack(seed,¶mIn,¶mOut);
2850 if (AliTPCReconstructor::StreamLevel()>2) {
2851 (*fDebugStreamer)<<"RecoverBack"<<
2855 "pout.="<<¶mOut<<
2860 seed->Set(paramOut.GetX(),paramOut.GetAlpha(),paramOut.GetParameter(),paramOut.GetCovariance());
2861 seed->SetNumberOfClusters(ncl);
2864 seed->CookdEdx(0.02,0.6);
2865 CookLabel(seed,0.1); //For comparison only
2866 if (seed->GetNumberOfClusters()>15){
2867 esd->UpdateTrackParams(seed,AliESDtrack::kTPCout);
2868 esd->SetTPCPoints(seed->GetPoints());
2869 esd->SetTPCPointsF(seed->GetNFoundable());
2870 Int_t ndedx = seed->GetNCDEDX(0);
2871 Float_t sdedx = seed->GetSDEDX(0);
2872 Float_t dedx = seed->GetdEdx();
2873 esd->SetTPCsignal(dedx, sdedx, ndedx);
2875 Int_t eventnumber = event->GetEventNumberInFile();// patch 28 fev 06
2876 // This is most likely NOT the event number you'd like to use. It has nothing to do with the 'real' event number
2877 if (AliTPCReconstructor::StreamLevel()>1 && esd) {
2878 (*fDebugStreamer)<<"Cback"<<
2881 "EventNrInFile="<<eventnumber<<
2886 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(1,fSeeds);
2887 //FindKinks(fSeeds,event);
2888 Info("PropagateBack","Number of back propagated tracks %d",ntracks);
2896 Int_t AliTPCtrackerMI::PostProcess(AliESDEvent *event)
2899 // Post process events
2901 if (!event) return 0;
2904 // Set TPC event status
2907 // event affected by HV dip
2909 if(IsTPCHVDipEvent(event)) {
2910 event->ResetDetectorStatus(AliDAQ::kTPC);
2913 //printf("Status %d \n", event->IsDetectorOn(AliDAQ::kTPC));
2919 void AliTPCtrackerMI::DeleteSeeds()
2928 void AliTPCtrackerMI::ReadSeeds(const AliESDEvent *const event, Int_t direction)
2931 //read seeds from the event
2933 Int_t nentr=event->GetNumberOfTracks();
2935 Info("ReadSeeds", "Number of ESD tracks: %d\n", nentr);
2940 fSeeds = new TObjArray(nentr);
2944 for (Int_t i=0; i<nentr; i++) {
2945 AliESDtrack *esd=event->GetTrack(i);
2946 ULong_t status=esd->GetStatus();
2947 if (!(status&AliESDtrack::kTPCin)) continue;
2948 AliTPCtrack t(*esd);
2949 t.SetNumberOfClusters(0);
2950 // AliTPCseed *seed = new AliTPCseed(t,t.GetAlpha());
2951 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(t/*,t.GetAlpha()*/);
2952 seed->SetPoolID(fLastSeedID);
2953 seed->SetUniqueID(esd->GetID());
2954 AddCovariance(seed); //add systematic ucertainty
2955 for (Int_t ikink=0;ikink<3;ikink++) {
2956 Int_t index = esd->GetKinkIndex(ikink);
2957 seed->GetKinkIndexes()[ikink] = index;
2958 if (index==0) continue;
2959 index = TMath::Abs(index);
2960 AliESDkink * kink = fEvent->GetKink(index-1);
2961 if (kink&&esd->GetKinkIndex(ikink)<0){
2962 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,2);
2963 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,0);
2965 if (kink&&esd->GetKinkIndex(ikink)>0){
2966 if ((status & AliESDtrack::kTRDrefit) != 0) kink->SetStatus(1,6);
2967 if ((status & AliESDtrack::kITSout) != 0) kink->SetStatus(1,4);
2971 if (((status&AliESDtrack::kITSout)==0)&&(direction==1)) seed->ResetCovariance(10.);
2972 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) == 0 ) seed->ResetCovariance(10.);
2973 //if ( direction ==2 && ((status & AliESDtrack::kTPCout) == 0) ) {
2974 // fSeeds->AddAt(0,i);
2975 // MarkSeedFree( seed );
2978 if ( direction ==2 &&(status & AliESDtrack::kTRDrefit) > 0 ) {
2979 Double_t par0[5],par1[5],alpha,x;
2980 esd->GetInnerExternalParameters(alpha,x,par0);
2981 esd->GetExternalParameters(x,par1);
2982 Double_t delta1 = TMath::Abs(par0[4]-par1[4])/(0.000000001+TMath::Abs(par0[4]+par1[4]));
2983 Double_t delta2 = TMath::Abs(par0[3]-par1[3]);
2985 if (esd->GetTRDncls()>0) trdchi2 = esd->GetTRDchi2()/esd->GetTRDncls();
2986 //reset covariance if suspicious
2987 if ( (delta1>0.1) || (delta2>0.006) ||trdchi2>7.)
2988 seed->ResetCovariance(10.);
2993 // rotate to the local coordinate system
2995 fSectors=fInnerSec; fN=fkNIS;
2996 Double_t alpha=seed->GetAlpha();
2997 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
2998 if (alpha < 0. ) alpha += 2.*TMath::Pi();
2999 Int_t ns=Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN;
3000 alpha =ns*fSectors->GetAlpha() + fSectors->GetAlphaShift();
3001 alpha-=seed->GetAlpha();
3002 if (alpha<-TMath::Pi()) alpha += 2*TMath::Pi();
3003 if (alpha>=TMath::Pi()) alpha -= 2*TMath::Pi();
3004 if (TMath::Abs(alpha) > 0.001) { // This should not happen normally
3005 AliWarning(Form("Rotating track over %f",alpha));
3006 if (!seed->Rotate(alpha)) {
3007 MarkSeedFree( seed );
3013 if (esd->GetKinkIndex(0)<=0){
3014 for (Int_t irow=0;irow<160;irow++){
3015 Int_t index = seed->GetClusterIndex2(irow);
3018 AliTPCclusterMI * cl = GetClusterMI(index);
3019 seed->SetClusterPointer(irow,cl);
3021 if ((index & 0x8000)==0){
3022 cl->Use(10); // accepted cluster
3024 cl->Use(6); // close cluster not accepted
3027 Info("ReadSeeds","Not found cluster");
3032 fSeeds->AddAt(seed,i);
3038 //_____________________________________________________________________________
3039 void AliTPCtrackerMI::MakeSeeds3(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3040 Float_t deltay, Int_t ddsec) {
3041 //-----------------------------------------------------------------
3042 // This function creates track seeds.
3043 // SEEDING WITH VERTEX CONSTRAIN
3044 //-----------------------------------------------------------------
3045 // cuts[0] - fP4 cut
3046 // cuts[1] - tan(phi) cut
3047 // cuts[2] - zvertex cut
3048 // cuts[3] - fP3 cut
3056 Double_t x[5], c[15];
3057 // Int_t di = i1-i2;
3059 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed();
3060 seed->SetPoolID(fLastSeedID);
3061 Double_t alpha=fSectors->GetAlpha(), shift=fSectors->GetAlphaShift();
3062 Double_t cs=cos(alpha), sn=sin(alpha);
3064 // Double_t x1 =fOuterSec->GetX(i1);
3065 //Double_t xx2=fOuterSec->GetX(i2);
3067 Double_t x1 =GetXrow(i1);
3068 Double_t xx2=GetXrow(i2);
3070 Double_t x3=GetX(), y3=GetY(), z3=GetZ();
3072 Int_t imiddle = (i2+i1)/2; //middle pad row index
3073 Double_t xm = GetXrow(imiddle); // radius of middle pad-row
3074 const AliTPCtrackerRow& krm=GetRow(sec,imiddle); //middle pad -row
3078 const AliTPCtrackerRow& kr1=GetRow(ns,i1);
3079 Double_t ymax = GetMaxY(i1)-kr1.GetDeadZone()-1.5;
3080 Double_t ymaxm = GetMaxY(imiddle)-kr1.GetDeadZone()-1.5;
3083 // change cut on curvature if it can't reach this layer
3084 // maximal curvature set to reach it
3085 Double_t dvertexmax = TMath::Sqrt((x1-x3)*(x1-x3)+(ymax+5-y3)*(ymax+5-y3));
3086 if (dvertexmax*0.5*cuts[0]>0.85){
3087 cuts[0] = 0.85/(dvertexmax*0.5+1.);
3089 Double_t r2min = 1/(cuts[0]*cuts[0]); //minimal square of radius given by cut
3092 if (deltay>0) ddsec = 0;
3093 // loop over clusters
3094 for (Int_t is=0; is < kr1; is++) {
3096 if (kr1[is]->IsUsed(10)) continue;
3097 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3098 //if (TMath::Abs(y1)>ymax) continue;
3100 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3102 // find possible directions
3103 Float_t anglez = (z1-z3)/(x1-x3);
3104 Float_t extraz = z1 - anglez*(x1-xx2); // extrapolated z
3107 //find rotation angles relative to line given by vertex and point 1
3108 Double_t dvertex2 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
3109 Double_t dvertex = TMath::Sqrt(dvertex2);
3110 Double_t angle13 = TMath::ATan((y1-y3)/(x1-x3));
3111 Double_t cs13 = cos(-angle13), sn13 = sin(-angle13);
3114 // loop over 2 sectors
3120 Double_t dddz1=0; // direction of delta inclination in z axis
3127 for (Int_t dsec = dsec1; dsec<=dsec2;dsec++){
3128 Int_t sec2 = sec + dsec;
3130 // AliTPCtrackerRow& kr2 = fOuterSec[(sec2+fkNOS)%fkNOS][i2];
3131 //AliTPCtrackerRow& kr2m = fOuterSec[(sec2+fkNOS)%fkNOS][imiddle];
3132 AliTPCtrackerRow& kr2 = GetRow((sec2+fkNOS)%fkNOS,i2);
3133 AliTPCtrackerRow& kr2m = GetRow((sec2+fkNOS)%fkNOS,imiddle);
3134 Int_t index1 = TMath::Max(kr2.Find(extraz-0.6-dddz1*TMath::Abs(z1)*0.05)-1,0);
3135 Int_t index2 = TMath::Min(kr2.Find(extraz+0.6+dddz2*TMath::Abs(z1)*0.05)+1,kr2);
3137 // rotation angles to p1-p3
3138 Double_t cs13r = cos(-angle13+dsec*alpha)/dvertex, sn13r = sin(-angle13+dsec*alpha)/dvertex;
3139 Double_t x2, y2, z2;
3141 // Double_t dymax = maxangle*TMath::Abs(x1-xx2);
3144 Double_t dxx0 = (xx2-x3)*cs13r;
3145 Double_t dyy0 = (xx2-x3)*sn13r;
3146 for (Int_t js=index1; js < index2; js++) {
3147 const AliTPCclusterMI *kcl = kr2[js];
3148 if (kcl->IsUsed(10)) continue;
3150 //calcutate parameters
3152 Double_t yy0 = dyy0 +(kcl->GetY()-y3)*cs13r;
3154 if (TMath::Abs(yy0)<0.000001) continue;
3155 Double_t xx0 = dxx0 -(kcl->GetY()-y3)*sn13r;
3156 Double_t y0 = 0.5*(xx0*xx0+yy0*yy0-xx0)/yy0;
3157 Double_t r02 = (0.25+y0*y0)*dvertex2;
3158 //curvature (radius) cut
3159 if (r02<r2min) continue;
3163 Double_t c0 = 1/TMath::Sqrt(r02);
3167 //Double_t dfi0 = 2.*TMath::ASin(dvertex*c0*0.5);
3168 //Double_t dfi1 = 2.*TMath::ASin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3169 Double_t dfi0 = 2.*AliTPCFastMath::FastAsin(dvertex*c0*0.5);
3170 Double_t dfi1 = 2.*AliTPCFastMath::FastAsin(TMath::Sqrt(yy0*yy0+(1-xx0)*(1-xx0))*dvertex*c0*0.5);
3173 Double_t z0 = kcl->GetZ();
3174 Double_t zzzz2 = z1-(z1-z3)*dfi1/dfi0;
3175 if (TMath::Abs(zzzz2-z0)>0.5) continue;
3178 Double_t dip = (z1-z0)*c0/dfi1;
3179 Double_t x0 = (0.5*cs13+y0*sn13)*dvertex*c0;
3190 x2= xx2*cs-y2*sn*dsec;
3191 y2=+xx2*sn*dsec+y2*cs;
3201 // do we have cluster at the middle ?
3203 GetProlongation(x1,xm,x,ym,zm);
3205 AliTPCclusterMI * cm=0;
3206 if (TMath::Abs(ym)-ymaxm<0){
3207 cm = krm.FindNearest2(ym,zm,1.0,0.6,dummy);
3208 if ((!cm) || (cm->IsUsed(10))) {
3213 // rotate y1 to system 0
3214 // get state vector in rotated system
3215 Double_t yr1 = (-0.5*sn13+y0*cs13)*dvertex*c0;
3216 Double_t xr2 = x0*cs+yr1*sn*dsec;
3217 Double_t xr[5]={kcl->GetY(),kcl->GetZ(), xr2, dip, c0};
3219 GetProlongation(xx2,xm,xr,ym,zm);
3220 if (TMath::Abs(ym)-ymaxm<0){
3221 cm = kr2m.FindNearest2(ym,zm,1.0,0.6,dummy);
3222 if ((!cm) || (cm->IsUsed(10))) {
3229 // Double_t dym = 0;
3230 // Double_t dzm = 0;
3232 // dym = ym - cm->GetY();
3233 // dzm = zm - cm->GetZ();
3240 Double_t sy1=kr1[is]->GetSigmaY2()*2., sz1=kr1[is]->GetSigmaZ2()*2.;
3241 Double_t sy2=kcl->GetSigmaY2()*2., sz2=kcl->GetSigmaZ2()*2.;
3242 //Double_t sy3=400*3./12., sy=0.1, sz=0.1;
3243 Double_t sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3244 //Double_t sy3=25000*x[4]*x[4]*60+0.5, sy=0.1, sz=0.1;
3246 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3247 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3248 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3249 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3250 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3251 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3253 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3254 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3255 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3256 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3260 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3261 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3262 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3263 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3264 c[13]=f30*sy1*f40+f32*sy2*f42;
3265 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3267 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3269 UInt_t index=kr1.GetIndex(is);
3270 if (seed) {MarkSeedFree(seed); seed = 0;}
3271 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, ns*alpha+shift, x, c, index);
3272 seed->SetPoolID(fLastSeedID);
3273 track->SetIsSeeding(kTRUE);
3274 track->SetSeed1(i1);
3275 track->SetSeed2(i2);
3276 track->SetSeedType(3);
3280 FollowProlongation(*track, (i1+i2)/2,1);
3281 Int_t foundable,found,shared;
3282 track->GetClusterStatistic((i1+i2)/2,i1, found, foundable, shared, kTRUE);
3283 if ((found<0.55*foundable) || shared>0.5*found || (track->GetSigmaY2()+track->GetSigmaZ2())>0.5){
3284 MarkSeedFree(seed); seed = 0;
3290 FollowProlongation(*track, i2,1);
3294 track->SetBConstrain(1);
3295 // track->fLastPoint = i1+fInnerSec->GetNRows(); // first cluster in track position
3296 track->SetLastPoint(i1); // first cluster in track position
3297 track->SetFirstPoint(track->GetLastPoint());
3299 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3300 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3301 track->GetNShared()>0.4*track->GetNumberOfClusters() ) {
3302 MarkSeedFree(seed); seed = 0;
3306 // Z VERTEX CONDITION
3307 Double_t zv, bz=GetBz();
3308 if ( !track->GetZAt(0.,bz,zv) ) continue;
3309 if (TMath::Abs(zv-z3)>cuts[2]) {
3310 FollowProlongation(*track, TMath::Max(i2-20,0));
3311 if ( !track->GetZAt(0.,bz,zv) ) continue;
3312 if (TMath::Abs(zv-z3)>cuts[2]){
3313 FollowProlongation(*track, TMath::Max(i2-40,0));
3314 if ( !track->GetZAt(0.,bz,zv) ) continue;
3315 if (TMath::Abs(zv-z3)>cuts[2] &&(track->GetNumberOfClusters() > track->GetNFoundable()*0.7)){
3316 // make seed without constrain
3317 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,1.);
3318 FollowProlongation(*track2, i2,1);
3319 track2->SetBConstrain(kFALSE);
3320 track2->SetSeedType(1);
3321 arr->AddLast(track2);
3322 MarkSeedFree( seed ); seed = 0;
3326 MarkSeedFree( seed ); seed = 0;
3333 track->SetSeedType(0);
3334 arr->AddLast(track); // note, track is seed, don't free the seed
3335 seed = new( NextFreeSeed() ) AliTPCseed;
3336 seed->SetPoolID(fLastSeedID);
3338 // don't consider other combinations
3339 if (track->GetNumberOfClusters() > track->GetNFoundable()*0.8)
3345 Info("MakeSeeds3","\nSeeding statistic:\t%d\t%d\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin,nout1,nout2);
3347 if (seed) MarkSeedFree( seed );
3351 void AliTPCtrackerMI::MakeSeeds5(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t cuts[4],
3356 //-----------------------------------------------------------------
3357 // This function creates track seeds.
3358 //-----------------------------------------------------------------
3359 // cuts[0] - fP4 cut
3360 // cuts[1] - tan(phi) cut
3361 // cuts[2] - zvertex cut
3362 // cuts[3] - fP3 cut
3372 Double_t x[5], c[15];
3374 // make temporary seed
3375 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3376 seed->SetPoolID(fLastSeedID);
3377 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3378 // Double_t cs=cos(alpha), sn=sin(alpha);
3383 Double_t x1 = GetXrow(i1-1);
3384 const AliTPCtrackerRow& kr1=GetRow(sec,i1-1);
3385 Double_t y1max = GetMaxY(i1-1)-kr1.GetDeadZone()-1.5;
3387 Double_t x1p = GetXrow(i1);
3388 const AliTPCtrackerRow& kr1p=GetRow(sec,i1);
3390 Double_t x1m = GetXrow(i1-2);
3391 const AliTPCtrackerRow& kr1m=GetRow(sec,i1-2);
3394 //last 3 padrow for seeding
3395 AliTPCtrackerRow& kr3 = GetRow((sec+fkNOS)%fkNOS,i1-7);
3396 Double_t x3 = GetXrow(i1-7);
3397 // Double_t y3max= GetMaxY(i1-7)-kr3.fDeadZone-1.5;
3399 AliTPCtrackerRow& kr3p = GetRow((sec+fkNOS)%fkNOS,i1-6);
3400 Double_t x3p = GetXrow(i1-6);
3402 AliTPCtrackerRow& kr3m = GetRow((sec+fkNOS)%fkNOS,i1-8);
3403 Double_t x3m = GetXrow(i1-8);
3408 Int_t im = i1-4; //middle pad row index
3409 Double_t xm = GetXrow(im); // radius of middle pad-row
3410 const AliTPCtrackerRow& krm=GetRow(sec,im); //middle pad -row
3411 // Double_t ymmax = GetMaxY(im)-kr1.fDeadZone-1.5;
3414 Double_t deltax = x1-x3;
3415 Double_t dymax = deltax*cuts[1];
3416 Double_t dzmax = deltax*cuts[3];
3418 // loop over clusters
3419 for (Int_t is=0; is < kr1; is++) {
3421 if (kr1[is]->IsUsed(10)) continue;
3422 Double_t y1=kr1[is]->GetY(), z1=kr1[is]->GetZ();
3424 if (deltay>0 && TMath::Abs(y1max-TMath::Abs(y1))> deltay ) continue; // seed only at the edge
3426 Int_t index1 = TMath::Max(kr3.Find(z1-dzmax)-1,0);
3427 Int_t index2 = TMath::Min(kr3.Find(z1+dzmax)+1,kr3);
3433 for (Int_t js=index1; js < index2; js++) {
3434 const AliTPCclusterMI *kcl = kr3[js];
3435 if (kcl->IsUsed(10)) continue;
3437 // apply angular cuts
3438 if (TMath::Abs(y1-y3)>dymax) continue;
3441 if (TMath::Abs(z1-z3)>dzmax) continue;
3443 Double_t angley = (y1-y3)/(x1-x3);
3444 Double_t anglez = (z1-z3)/(x1-x3);
3446 Double_t erry = TMath::Abs(angley)*(x1-x1m)*0.5+0.5;
3447 Double_t errz = TMath::Abs(anglez)*(x1-x1m)*0.5+0.5;
3449 Double_t yyym = angley*(xm-x1)+y1;
3450 Double_t zzzm = anglez*(xm-x1)+z1;
3452 const AliTPCclusterMI *kcm = krm.FindNearest2(yyym,zzzm,erry,errz,index);
3454 if (kcm->IsUsed(10)) continue;
3456 erry = TMath::Abs(angley)*(x1-x1m)*0.4+0.5;
3457 errz = TMath::Abs(anglez)*(x1-x1m)*0.4+0.5;
3464 // look around first
3465 const AliTPCclusterMI *kc1m = kr1m.FindNearest2(angley*(x1m-x1)+y1,
3471 if (kc1m->IsUsed(10)) used++;
3473 const AliTPCclusterMI *kc1p = kr1p.FindNearest2(angley*(x1p-x1)+y1,
3479 if (kc1p->IsUsed(10)) used++;
3481 if (used>1) continue;
3482 if (found<1) continue;
3486 const AliTPCclusterMI *kc3m = kr3m.FindNearest2(angley*(x3m-x3)+y3,
3492 if (kc3m->IsUsed(10)) used++;
3496 const AliTPCclusterMI *kc3p = kr3p.FindNearest2(angley*(x3p-x3)+y3,
3502 if (kc3p->IsUsed(10)) used++;
3506 if (used>1) continue;
3507 if (found<3) continue;
3517 x[4]=F1(x1,y1,x2,y2,x3,y3);
3518 //if (TMath::Abs(x[4]) >= cuts[0]) continue;
3521 x[2]=F2(x1,y1,x2,y2,x3,y3);
3524 x[3]=F3n(x1,y1,x2,y2,z1,z2,x[4]);
3525 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3529 Double_t sy1=0.1, sz1=0.1;
3530 Double_t sy2=0.1, sz2=0.1;
3531 Double_t sy3=0.1, sy=0.1, sz=0.1;
3533 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3534 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3535 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3536 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3537 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3538 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3540 Double_t f30=(F3(x1,y1+sy,x2,y2,z1,z2)-x[3])/sy;
3541 Double_t f31=(F3(x1,y1,x2,y2,z1+sz,z2)-x[3])/sz;
3542 Double_t f32=(F3(x1,y1,x2,y2+sy,z1,z2)-x[3])/sy;
3543 Double_t f34=(F3(x1,y1,x2,y2,z1,z2+sz)-x[3])/sz;
3547 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3548 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3549 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3550 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3551 c[13]=f30*sy1*f40+f32*sy2*f42;
3552 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3554 // if (!BuildSeed(kr1[is],kcl,0,x1,x2,x3,x,c)) continue;
3556 index=kr1.GetIndex(is);
3557 if (seed) {MarkSeedFree( seed ); seed = 0;}
3558 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1, sec*alpha+shift, x, c, index);
3559 seed->SetPoolID(fLastSeedID);
3561 track->SetIsSeeding(kTRUE);
3564 FollowProlongation(*track, i1-7,1);
3565 if (track->GetNumberOfClusters() < track->GetNFoundable()*0.75 ||
3566 track->GetNShared()>0.6*track->GetNumberOfClusters() || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.6){
3567 MarkSeedFree( seed ); seed = 0;
3573 FollowProlongation(*track, i2,1);
3574 track->SetBConstrain(0);
3575 track->SetLastPoint(i1+fInnerSec->GetNRows()); // first cluster in track position
3576 track->SetFirstPoint(track->GetLastPoint());
3578 if (track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3579 track->GetNumberOfClusters()<track->GetNFoundable()*0.7 ||
3580 track->GetNShared()>2. || track->GetChi2()/track->GetNumberOfClusters()>6 || ( track->GetSigmaY2()+ track->GetSigmaZ2())>0.5 ) {
3581 MarkSeedFree( seed ); seed = 0;
3586 FollowProlongation(*track, TMath::Max(i2-10,0),1);
3587 AliTPCseed * track2 = MakeSeed(track,0.2,0.5,0.9);
3588 FollowProlongation(*track2, i2,1);
3589 track2->SetBConstrain(kFALSE);
3590 track2->SetSeedType(4);
3591 arr->AddLast(track2);
3592 MarkSeedFree( seed ); seed = 0;
3596 //arr->AddLast(track);
3597 //seed = new AliTPCseed;
3603 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);
3605 if (seed) MarkSeedFree(seed);
3609 //_____________________________________________________________________________
3610 void AliTPCtrackerMI::MakeSeeds2(TObjArray * arr, Int_t sec, Int_t i1, Int_t i2, Float_t */*cuts[4]*/,
3611 Float_t deltay, Bool_t /*bconstrain*/) {
3612 //-----------------------------------------------------------------
3613 // This function creates track seeds - without vertex constraint
3614 //-----------------------------------------------------------------
3615 // cuts[0] - fP4 cut - not applied
3616 // cuts[1] - tan(phi) cut
3617 // cuts[2] - zvertex cut - not applied
3618 // cuts[3] - fP3 cut
3628 Double_t alpha=fOuterSec->GetAlpha(), shift=fOuterSec->GetAlphaShift();
3629 // Double_t cs=cos(alpha), sn=sin(alpha);
3630 Int_t row0 = (i1+i2)/2;
3631 Int_t drow = (i1-i2)/2;
3632 const AliTPCtrackerRow& kr0=fSectors[sec][row0];
3633 AliTPCtrackerRow * kr=0;
3635 AliTPCpolyTrack polytrack;
3636 Int_t nclusters=fSectors[sec][row0];
3637 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed;
3638 seed->SetPoolID(fLastSeedID);
3643 for (Int_t is=0; is < nclusters; is++) { //LOOP over clusters
3645 Int_t nfoundable =0;
3646 for (Int_t iter =1; iter<2; iter++){ //iterations
3647 const AliTPCtrackerRow& krm=fSectors[sec][row0-iter];
3648 const AliTPCtrackerRow& krp=fSectors[sec][row0+iter];
3649 const AliTPCclusterMI * cl= kr0[is];
3651 if (cl->IsUsed(10)) {
3657 Double_t x = kr0.GetX();
3658 // Initialization of the polytrack
3663 Double_t y0= cl->GetY();
3664 Double_t z0= cl->GetZ();
3668 Double_t ymax = fSectors->GetMaxY(row0)-kr0.GetDeadZone()-1.5;
3669 if (deltay>0 && TMath::Abs(ymax-TMath::Abs(y0))> deltay ) continue; // seed only at the edge
3671 erry = (0.5)*cl->GetSigmaY2()/TMath::Sqrt(cl->GetQ())*6;
3672 errz = (0.5)*cl->GetSigmaZ2()/TMath::Sqrt(cl->GetQ())*6;
3673 polytrack.AddPoint(x,y0,z0,erry, errz);
3676 if (cl->IsUsed(10)) sumused++;
3679 Float_t roady = (5*TMath::Sqrt(cl->GetSigmaY2()+0.2)+1.)*iter;
3680 Float_t roadz = (5*TMath::Sqrt(cl->GetSigmaZ2()+0.2)+1.)*iter;
3683 AliTPCclusterMI * cl1 = krm.FindNearest(y0,z0,roady,roadz);
3684 if (cl1 && TMath::Abs(ymax-TMath::Abs(y0))) {
3685 erry = (0.5)*cl1->GetSigmaY2()/TMath::Sqrt(cl1->GetQ())*3;
3686 errz = (0.5)*cl1->GetSigmaZ2()/TMath::Sqrt(cl1->GetQ())*3;
3687 if (cl1->IsUsed(10)) sumused++;
3688 polytrack.AddPoint(x,cl1->GetY(),cl1->GetZ(),erry,errz);
3692 AliTPCclusterMI * cl2 = krp.FindNearest(y0,z0,roady,roadz);
3694 erry = (0.5)*cl2->GetSigmaY2()/TMath::Sqrt(cl2->GetQ())*3;
3695 errz = (0.5)*cl2->GetSigmaZ2()/TMath::Sqrt(cl2->GetQ())*3;
3696 if (cl2->IsUsed(10)) sumused++;
3697 polytrack.AddPoint(x,cl2->GetY(),cl2->GetZ(),erry,errz);
3700 if (sumused>0) continue;
3702 polytrack.UpdateParameters();
3708 nfoundable = polytrack.GetN();
3709 nfound = nfoundable;
3711 for (Int_t ddrow = iter+1; ddrow<drow;ddrow++){
3712 Float_t maxdist = 0.8*(1.+3./(ddrow));
3713 for (Int_t delta = -1;delta<=1;delta+=2){
3714 Int_t row = row0+ddrow*delta;
3715 kr = &(fSectors[sec][row]);
3716 Double_t xn = kr->GetX();
3717 Double_t ymax1 = fSectors->GetMaxY(row)-kr->GetDeadZone()-1.5;
3718 polytrack.GetFitPoint(xn,yn,zn);
3719 if (TMath::Abs(yn)>ymax1) continue;
3721 AliTPCclusterMI * cln = kr->FindNearest(yn,zn,roady,roadz);
3723 Float_t dist = TMath::Sqrt( (yn-cln->GetY())*(yn-cln->GetY())+(zn-cln->GetZ())*(zn-cln->GetZ()));
3726 erry = (dist+0.3)*cln->GetSigmaY2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3727 errz = (dist+0.3)*cln->GetSigmaZ2()/TMath::Sqrt(cln->GetQ())*(1.+1./(ddrow));
3728 if (cln->IsUsed(10)) {
3729 // printf("used\n");
3737 polytrack.AddPoint(xn,cln->GetY(),cln->GetZ(),erry, errz);
3742 if ( (sumused>3) || (sumused>0.5*nfound) || (nfound<0.6*nfoundable)) break;
3743 polytrack.UpdateParameters();
3746 if ( (sumused>3) || (sumused>0.5*nfound)) {
3747 //printf("sumused %d\n",sumused);
3752 polytrack.GetFitDerivation(kr0.GetX(),dy,dz);
3753 AliTPCpolyTrack track2;
3755 polytrack.Refit(track2,0.5+TMath::Abs(dy)*0.3,0.4+TMath::Abs(dz)*0.3);
3756 if (track2.GetN()<0.5*nfoundable) continue;
3759 if ((nfound>0.6*nfoundable) &&( nfoundable>0.4*(i1-i2))) {
3761 // test seed with and without constrain
3762 for (Int_t constrain=0; constrain<=0;constrain++){
3763 // add polytrack candidate
3765 Double_t x[5], c[15];
3766 Double_t x1,x2,x3,y1,y2,y3,z1,z2,z3;
3767 track2.GetBoundaries(x3,x1);
3769 track2.GetFitPoint(x1,y1,z1);
3770 track2.GetFitPoint(x2,y2,z2);
3771 track2.GetFitPoint(x3,y3,z3);
3773 //is track pointing to the vertex ?
3776 polytrack.GetFitPoint(x0,y0,z0);
3789 x[4]=F1(x1,y1,x2,y2,x3,y3);
3791 // if (TMath::Abs(x[4]) >= cuts[0]) continue; //
3792 x[2]=F2(x1,y1,x2,y2,x3,y3);
3794 //if (TMath::Abs(x[4]*x1-x[2]) >= cuts[1]) continue;
3795 //x[3]=F3(x1,y1,x2,y2,z1,z2);
3796 x[3]=F3n(x1,y1,x3,y3,z1,z3,x[4]);
3797 //if (TMath::Abs(x[3]) > cuts[3]) continue;
3800 Double_t sy =0.1, sz =0.1;
3801 Double_t sy1=0.02, sz1=0.02;
3802 Double_t sy2=0.02, sz2=0.02;
3806 sy3=25000*x[4]*x[4]+0.1, sy=0.1, sz=0.1;
3809 Double_t f40=(F1(x1,y1+sy,x2,y2,x3,y3)-x[4])/sy;
3810 Double_t f42=(F1(x1,y1,x2,y2+sy,x3,y3)-x[4])/sy;
3811 Double_t f43=(F1(x1,y1,x2,y2,x3,y3+sy)-x[4])/sy;
3812 Double_t f20=(F2(x1,y1+sy,x2,y2,x3,y3)-x[2])/sy;
3813 Double_t f22=(F2(x1,y1,x2,y2+sy,x3,y3)-x[2])/sy;
3814 Double_t f23=(F2(x1,y1,x2,y2,x3,y3+sy)-x[2])/sy;
3816 Double_t f30=(F3(x1,y1+sy,x3,y3,z1,z3)-x[3])/sy;
3817 Double_t f31=(F3(x1,y1,x3,y3,z1+sz,z3)-x[3])/sz;
3818 Double_t f32=(F3(x1,y1,x3,y3+sy,z1,z3)-x[3])/sy;
3819 Double_t f34=(F3(x1,y1,x3,y3,z1,z3+sz)-x[3])/sz;
3824 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3825 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3826 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3827 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3828 c[13]=f30*sy1*f40+f32*sy2*f42;
3829 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3831 //Int_t row1 = fSectors->GetRowNumber(x1);
3832 Int_t row1 = GetRowNumber(x1);
3836 if (seed) {MarkSeedFree( seed ); seed = 0;}
3837 AliTPCseed *track = seed = new( NextFreeSeed() ) AliTPCseed(x1,sec*alpha+shift,x,c,index);
3838 seed->SetPoolID(fLastSeedID);
3839 track->SetIsSeeding(kTRUE);
3840 Int_t rc=FollowProlongation(*track, i2);
3841 if (constrain) track->SetBConstrain(1);
3843 track->SetBConstrain(0);
3844 track->SetLastPoint(row1+fInnerSec->GetNRows()); // first cluster in track position
3845 track->SetFirstPoint(track->GetLastPoint());
3847 if (rc==0 || track->GetNumberOfClusters()<(i1-i2)*0.5 ||
3848 track->GetNumberOfClusters() < track->GetNFoundable()*0.6 ||
3849 track->GetNShared()>0.4*track->GetNumberOfClusters()) {
3850 MarkSeedFree( seed ); seed = 0;
3853 arr->AddLast(track); // track IS seed, don't free seed
3854 seed = new( NextFreeSeed() ) AliTPCseed;
3855 seed->SetPoolID(fLastSeedID);
3859 } // if accepted seed
3862 Info("MakeSeeds2","\nSeeding statiistic:\t%d\t%d\t%d\t%d",nin0,nin1,nin2,nin3);
3864 if (seed) MarkSeedFree( seed );
3868 AliTPCseed *AliTPCtrackerMI::MakeSeed(AliTPCseed *const track, Float_t r0, Float_t r1, Float_t r2)
3872 //reseed using track points
3873 Int_t p0 = int(r0*track->GetNumberOfClusters()); // point 0
3874 Int_t p1 = int(r1*track->GetNumberOfClusters());
3875 Int_t p2 = int(r2*track->GetNumberOfClusters()); // last point
3877 Double_t x0[3],x1[3],x2[3];
3878 for (Int_t i=0;i<3;i++){
3884 // find track position at given ratio of the length
3885 Int_t sec0=0, sec1=0, sec2=0;
3888 for (Int_t i=0;i<160;i++){
3889 if (track->GetClusterPointer(i)){
3891 AliTPCTrackerPoint *trpoint =track->GetTrackPoint(i);
3892 if ( (index<p0) || x0[0]<0 ){
3893 if (trpoint->GetX()>1){
3894 clindex = track->GetClusterIndex2(i);
3896 x0[0] = trpoint->GetX();
3897 x0[1] = trpoint->GetY();
3898 x0[2] = trpoint->GetZ();
3899 sec0 = ((clindex&0xff000000)>>24)%18;
3904 if ( (index<p1) &&(trpoint->GetX()>1)){
3905 clindex = track->GetClusterIndex2(i);
3907 x1[0] = trpoint->GetX();
3908 x1[1] = trpoint->GetY();
3909 x1[2] = trpoint->GetZ();
3910 sec1 = ((clindex&0xff000000)>>24)%18;
3913 if ( (index<p2) &&(trpoint->GetX()>1)){
3914 clindex = track->GetClusterIndex2(i);
3916 x2[0] = trpoint->GetX();
3917 x2[1] = trpoint->GetY();
3918 x2[2] = trpoint->GetZ();
3919 sec2 = ((clindex&0xff000000)>>24)%18;
3926 Double_t alpha, cs,sn, xx2,yy2;
3928 alpha = (sec1-sec2)*fSectors->GetAlpha();
3929 cs = TMath::Cos(alpha);
3930 sn = TMath::Sin(alpha);
3931 xx2= x1[0]*cs-x1[1]*sn;
3932 yy2= x1[0]*sn+x1[1]*cs;
3936 alpha = (sec0-sec2)*fSectors->GetAlpha();
3937 cs = TMath::Cos(alpha);
3938 sn = TMath::Sin(alpha);
3939 xx2= x0[0]*cs-x0[1]*sn;
3940 yy2= x0[0]*sn+x0[1]*cs;
3946 Double_t x[5],c[15];
3950 x[4]=F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3951 // if (x[4]>1) return 0;
3952 x[2]=F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]);
3953 x[3]=F3n(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2],x[4]);
3954 //if (TMath::Abs(x[3]) > 2.2) return 0;
3955 //if (TMath::Abs(x[2]) > 1.99) return 0;
3957 Double_t sy =0.1, sz =0.1;
3959 Double_t sy1=0.02+track->GetSigmaY2(), sz1=0.02+track->GetSigmaZ2();
3960 Double_t sy2=0.01+track->GetSigmaY2(), sz2=0.01+track->GetSigmaZ2();
3961 Double_t sy3=0.01+track->GetSigmaY2();
3963 Double_t f40=(F1(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[4])/sy;
3964 Double_t f42=(F1(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[4])/sy;
3965 Double_t f43=(F1(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[4])/sy;
3966 Double_t f20=(F2(x2[0],x2[1]+sy,x1[0],x1[1],x0[0],x0[1])-x[2])/sy;
3967 Double_t f22=(F2(x2[0],x2[1],x1[0],x1[1]+sy,x0[0],x0[1])-x[2])/sy;
3968 Double_t f23=(F2(x2[0],x2[1],x1[0],x1[1],x0[0],x0[1]+sy)-x[2])/sy;
3970 Double_t f30=(F3(x2[0],x2[1]+sy,x0[0],x0[1],x2[2],x0[2])-x[3])/sy;
3971 Double_t f31=(F3(x2[0],x2[1],x0[0],x0[1],x2[2]+sz,x0[2])-x[3])/sz;
3972 Double_t f32=(F3(x2[0],x2[1],x0[0],x0[1]+sy,x2[2],x0[2])-x[3])/sy;
3973 Double_t f34=(F3(x2[0],x2[1],x0[0],x0[1],x2[2],x0[2]+sz)-x[3])/sz;
3978 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
3979 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
3980 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
3981 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
3982 c[13]=f30*sy1*f40+f32*sy2*f42;
3983 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
3985 // Int_t row1 = fSectors->GetRowNumber(x2[0]);
3986 AliTPCseed *seed = new( NextFreeSeed() ) AliTPCseed(x2[0], sec2*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
3987 seed->SetPoolID(fLastSeedID);
3988 // Double_t y0,z0,y1,z1, y2,z2;
3989 //seed->GetProlongation(x0[0],y0,z0);
3990 // seed->GetProlongation(x1[0],y1,z1);
3991 //seed->GetProlongation(x2[0],y2,z2);
3993 seed->SetLastPoint(pp2);
3994 seed->SetFirstPoint(pp2);
4001 AliTPCseed *AliTPCtrackerMI::ReSeed(const AliTPCseed *track, Float_t r0, Float_t r1, Float_t r2)
4005 //reseed using founded clusters
4007 // Find the number of clusters
4008 Int_t nclusters = 0;
4009 for (Int_t irow=0;irow<160;irow++){
4010 if (track->GetClusterIndex(irow)>0) nclusters++;
4014 ipos[0] = TMath::Max(int(r0*nclusters),0); // point 0 cluster
4015 ipos[1] = TMath::Min(int(r1*nclusters),nclusters-1); //
4016 ipos[2] = TMath::Min(int(r2*nclusters),nclusters-1); // last point
4019 Double_t xyz[3][3]={{0}};
4020 Int_t row[3]={0},sec[3]={0,0,0};
4022 // find track row position at given ratio of the length
4024 for (Int_t irow=0;irow<160;irow++){
4025 if (track->GetClusterIndex2(irow)<0) continue;
4027 for (Int_t ipoint=0;ipoint<3;ipoint++){
4028 if (index<=ipos[ipoint]) row[ipoint] = irow;
4032 //Get cluster and sector position
4033 for (Int_t ipoint=0;ipoint<3;ipoint++){
4034 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4035 AliTPCclusterMI * cl = GetClusterMI(clindex);
4038 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4041 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4042 xyz[ipoint][0] = GetXrow(row[ipoint]);
4043 xyz[ipoint][1] = cl->GetY();
4044 xyz[ipoint][2] = cl->GetZ();
4048 // Calculate seed state vector and covariance matrix
4050 Double_t alpha, cs,sn, xx2,yy2;
4052 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4053 cs = TMath::Cos(alpha);
4054 sn = TMath::Sin(alpha);
4055 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4056 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4060 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4061 cs = TMath::Cos(alpha);
4062 sn = TMath::Sin(alpha);
4063 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4064 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4070 Double_t x[5],c[15];
4074 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4075 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4076 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4078 Double_t sy =0.1, sz =0.1;
4080 Double_t sy1=0.2, sz1=0.2;
4081 Double_t sy2=0.2, sz2=0.2;
4084 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;
4085 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;
4086 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;
4087 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;
4088 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;
4089 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;
4091 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;
4092 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;
4093 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;
4094 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;
4099 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4100 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4101 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4102 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4103 c[13]=f30*sy1*f40+f32*sy2*f42;
4104 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4106 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4107 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4108 seed->SetPoolID(fLastSeedID);
4109 seed->SetLastPoint(row[2]);
4110 seed->SetFirstPoint(row[2]);
4115 AliTPCseed *AliTPCtrackerMI::ReSeed(AliTPCseed *track,Int_t r0, Bool_t forward)
4119 //reseed using founded clusters
4122 Int_t row[3]={0,0,0};
4123 Int_t sec[3]={0,0,0};
4125 // forward direction
4127 for (Int_t irow=r0;irow<160;irow++){
4128 if (track->GetClusterIndex(irow)>0){
4133 for (Int_t irow=160;irow>r0;irow--){
4134 if (track->GetClusterIndex(irow)>0){
4139 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4140 if (track->GetClusterIndex(irow)>0){
4148 for (Int_t irow=0;irow<r0;irow++){
4149 if (track->GetClusterIndex(irow)>0){
4154 for (Int_t irow=r0;irow>0;irow--){
4155 if (track->GetClusterIndex(irow)>0){
4160 for (Int_t irow=row[2]-15;irow>row[0];irow--){
4161 if (track->GetClusterIndex(irow)>0){
4168 if ((row[2]-row[0])<20) return 0;
4169 if (row[1]==0) return 0;
4172 //Get cluster and sector position
4173 for (Int_t ipoint=0;ipoint<3;ipoint++){
4174 Int_t clindex = track->GetClusterIndex2(row[ipoint]);
4175 AliTPCclusterMI * cl = GetClusterMI(clindex);
4178 // AliTPCclusterMI * cl = GetClusterMI(clindex);
4181 sec[ipoint] = ((clindex&0xff000000)>>24)%18;
4182 xyz[ipoint][0] = GetXrow(row[ipoint]);
4183 AliTPCTrackerPoint * point = track->GetTrackPoint(row[ipoint]);
4184 if (point&&ipoint<2){
4186 xyz[ipoint][1] = point->GetY();
4187 xyz[ipoint][2] = point->GetZ();
4190 xyz[ipoint][1] = cl->GetY();
4191 xyz[ipoint][2] = cl->GetZ();
4198 // Calculate seed state vector and covariance matrix
4200 Double_t alpha, cs,sn, xx2,yy2;
4202 alpha = (sec[1]-sec[2])*fSectors->GetAlpha();
4203 cs = TMath::Cos(alpha);
4204 sn = TMath::Sin(alpha);
4205 xx2= xyz[1][0]*cs-xyz[1][1]*sn;
4206 yy2= xyz[1][0]*sn+xyz[1][1]*cs;
4210 alpha = (sec[0]-sec[2])*fSectors->GetAlpha();
4211 cs = TMath::Cos(alpha);
4212 sn = TMath::Sin(alpha);
4213 xx2= xyz[0][0]*cs-xyz[0][1]*sn;
4214 yy2= xyz[0][0]*sn+xyz[0][1]*cs;
4220 Double_t x[5],c[15];
4224 x[4]=F1(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4225 x[2]=F2(xyz[2][0],xyz[2][1],xyz[1][0],xyz[1][1],xyz[0][0],xyz[0][1]);
4226 x[3]=F3n(xyz[2][0],xyz[2][1],xyz[0][0],xyz[0][1],xyz[2][2],xyz[0][2],x[4]);
4228 Double_t sy =0.1, sz =0.1;
4230 Double_t sy1=0.2, sz1=0.2;
4231 Double_t sy2=0.2, sz2=0.2;
4234 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;
4235 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;
4236 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;
4237 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;
4238 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;
4239 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;
4241 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;
4242 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;
4243 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;
4244 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;
4249 c[3]=f20*sy1; c[4]=0.; c[5]=f20*sy1*f20+f22*sy2*f22+f23*sy3*f23;
4250 c[6]=f30*sy1; c[7]=f31*sz1; c[8]=f30*sy1*f20+f32*sy2*f22;
4251 c[9]=f30*sy1*f30+f31*sz1*f31+f32*sy2*f32+f34*sz2*f34;
4252 c[10]=f40*sy1; c[11]=0.; c[12]=f40*sy1*f20+f42*sy2*f22+f43*sy3*f23;
4253 c[13]=f30*sy1*f40+f32*sy2*f42;
4254 c[14]=f40*sy1*f40+f42*sy2*f42+f43*sy3*f43;
4256 // Int_t row1 = fSectors->GetRowNumber(xyz[2][0]);
4257 AliTPCseed *seed=new( NextFreeSeed() ) AliTPCseed(xyz[2][0], sec[2]*fSectors->GetAlpha()+fSectors->GetAlphaShift(), x, c, 0);
4258 seed->SetPoolID(fLastSeedID);
4259 seed->SetLastPoint(row[2]);
4260 seed->SetFirstPoint(row[2]);
4261 for (Int_t i=row[0];i<row[2];i++){
4262 seed->SetClusterIndex(i, track->GetClusterIndex(i));
4270 void AliTPCtrackerMI::FindMultiMC(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4273 // find multi tracks - THIS FUNCTION IS ONLY FOR DEBUG PURPOSES
4275 // Use AliTPCReconstructor::StreamLevel()>2 if you want to tune parameters - cuts
4277 // Two reasons to have multiple find tracks
4278 // 1. Curling tracks can be find more than once
4279 // 2. Splitted tracks
4280 // a.) Multiple seeding to increase tracking efficiency - (~ 100% reached)
4281 // b.) Edge effect on the sector boundaries
4284 // Algorithm done in 2 phases - because of CPU consumption
4285 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4287 // Algorihm for curling tracks sign:
4288 // 1 phase -makes a very rough fast cuts to minimize combinatorics
4289 // a.) opposite sign
4290 // b.) one of the tracks - not pointing to the primary vertex -
4291 // c.) delta tan(theta)
4293 // 2 phase - calculates DCA between tracks - time consument
4298 // General cuts - for splitted tracks and for curling tracks
4300 const Float_t kMaxdPhi = 0.2; // maximal distance in phi
4302 // Curling tracks cuts
4307 Int_t nentries = array->GetEntriesFast();
4308 AliHelix *helixes = new AliHelix[nentries];
4309 Float_t *xm = new Float_t[nentries];
4310 Float_t *dz0 = new Float_t[nentries];
4311 Float_t *dz1 = new Float_t[nentries];
4317 // Find track COG in x direction - point with best defined parameters
4319 for (Int_t i=0;i<nentries;i++){
4320 AliTPCseed* track = (AliTPCseed*)array->At(i);
4321 if (!track) continue;
4322 track->SetCircular(0);
4323 new (&helixes[i]) AliHelix(*track);
4327 track->GetDZ(GetX(),GetY(),GetZ(),GetBz(),dz);
4330 for (Int_t icl=0; icl<160; icl++){
4331 AliTPCclusterMI * cl = track->GetClusterPointer(icl);
4337 if (ncl>0) xm[i]/=Float_t(ncl);
4340 for (Int_t i0=0;i0<nentries;i0++){
4341 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4342 if (!track0) continue;
4343 Float_t xc0 = helixes[i0].GetHelix(6);
4344 Float_t yc0 = helixes[i0].GetHelix(7);
4345 Float_t r0 = helixes[i0].GetHelix(8);
4346 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4347 Float_t fi0 = TMath::ATan2(yc0,xc0);
4349 for (Int_t i1=i0+1;i1<nentries;i1++){
4350 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4351 if (!track1) continue;
4352 Int_t lab0=track0->GetLabel();
4353 Int_t lab1=track1->GetLabel();
4354 if (TMath::Abs(lab0)!=TMath::Abs(lab1)) continue;
4356 Float_t xc1 = helixes[i1].GetHelix(6);
4357 Float_t yc1 = helixes[i1].GetHelix(7);
4358 Float_t r1 = helixes[i1].GetHelix(8);
4359 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4360 Float_t fi1 = TMath::ATan2(yc1,xc1);
4362 Float_t dfi = fi0-fi1;
4365 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4366 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4367 if (TMath::Abs(dfi)>kMaxdPhi&&helixes[i0].GetHelix(4)*helixes[i1].GetHelix(4)<0){
4369 // if short tracks with undefined sign
4370 fi1 = -TMath::ATan2(yc1,-xc1);
4373 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4376 // debug stream to tune "fast cuts"
4378 Double_t dist[3]; // distance at X
4379 Double_t mdist[3]={0,0,0}; // mean distance X+-40cm
4380 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])-40.,dist,AliTracker::GetBz());
4381 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4382 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1])+40.,dist,AliTracker::GetBz());
4383 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4384 track0->GetDistance(track1,0.5*(xm[i0]+xm[i1]),dist,AliTracker::GetBz());
4385 for (Int_t i=0;i<3;i++) mdist[i]+=TMath::Abs(dist[i]);
4386 for (Int_t i=0;i<3;i++) mdist[i]*=0.33333;
4390 for (Int_t icl=0; icl<160; icl++){
4391 AliTPCclusterMI * cl0 = track0->GetClusterPointer(icl);
4392 AliTPCclusterMI * cl1 = track1->GetClusterPointer(icl);
4395 if (cl0==cl1) sums++;
4399 if (AliTPCReconstructor::StreamLevel()>5) {
4400 TTreeSRedirector &cstream = *fDebugStreamer;
4405 "Tr0.="<<track0<< // seed0
4406 "Tr1.="<<track1<< // seed1
4407 "h0.="<<&helixes[i0]<<
4408 "h1.="<<&helixes[i1]<<
4410 "sum="<<sum<< //the sum of rows with cl in both
4411 "sums="<<sums<< //the sum of shared clusters
4412 "xm0="<<xm[i0]<< // the center of track
4413 "xm1="<<xm[i1]<< // the x center of track
4414 // General cut variables
4415 "dfi="<<dfi<< // distance in fi angle
4416 "dtheta="<<dtheta<< // distance int theta angle
4422 "dist0="<<dist[0]<< //distance x
4423 "dist1="<<dist[1]<< //distance y
4424 "dist2="<<dist[2]<< //distance z
4425 "mdist0="<<mdist[0]<< //distance x
4426 "mdist1="<<mdist[1]<< //distance y
4427 "mdist2="<<mdist[2]<< //distance z
4443 if (AliTPCReconstructor::StreamLevel()>1) {
4444 AliInfo("Time for curling tracks removal DEBUGGING MC");
4451 void AliTPCtrackerMI::FindSplitted(TObjArray * array, AliESDEvent */*esd*/, Int_t /*iter*/){
4453 // Find Splitted tracks and remove the one with worst quality
4454 // Corresponding debug streamer to tune selections - "Splitted2"
4456 // 0. Sort tracks according quility
4457 // 1. Propagate the tracks to the reference radius
4458 // 2. Double_t loop to select close tracks (only to speed up process)
4459 // 3. Calculate cluster overlap ratio - and remove the track if bigger than a threshold
4460 // 4. Delete temporary parameters
4462 const Double_t xref=GetXrow(63); // reference radius -IROC/OROC boundary
4464 const Double_t kCutP1=10; // delta Z cut 10 cm
4465 const Double_t kCutP2=0.15; // delta snp(fi) cut 0.15
4466 const Double_t kCutP3=0.15; // delta tgl(theta) cut 0.15
4467 const Double_t kCutAlpha=0.15; // delta alpha cut
4468 Int_t firstpoint = 0;
4469 Int_t lastpoint = 160;
4471 Int_t nentries = array->GetEntriesFast();
4472 AliExternalTrackParam *params = new AliExternalTrackParam[nentries];
4478 //0. Sort tracks according quality
4479 //1. Propagate the ext. param to reference radius
4480 Int_t nseed = array->GetEntriesFast();
4481 if (nseed<=0) return;
4482 Float_t * quality = new Float_t[nseed];
4483 Int_t * indexes = new Int_t[nseed];
4484 for (Int_t i=0; i<nseed; i++) {
4485 AliTPCseed *pt=(AliTPCseed*)array->UncheckedAt(i);
4490 pt->UpdatePoints(); //select first last max dens points
4491 Float_t * points = pt->GetPoints();
4492 if (points[3]<0.8) quality[i] =-1;
4493 quality[i] = (points[2]-points[0])+pt->GetNumberOfClusters();
4494 //prefer high momenta tracks if overlaps
4495 quality[i] *= TMath::Sqrt(TMath::Abs(pt->Pt())+0.5);
4497 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),5.,kTRUE);
4498 AliTracker::PropagateTrackToBxByBz(&(params[i]),xref,pt->GetMass(),1.,kTRUE);
4500 TMath::Sort(nseed,quality,indexes);
4502 // 3. Loop over pair of tracks
4504 for (Int_t i0=0; i0<nseed; i0++) {
4505 Int_t index0=indexes[i0];
4506 if (!(array->UncheckedAt(index0))) continue;
4507 AliTPCseed *s1 = (AliTPCseed*)array->UncheckedAt(index0);
4508 if (!s1->IsActive()) continue;
4509 AliExternalTrackParam &par0=params[index0];
4510 for (Int_t i1=i0+1; i1<nseed; i1++) {
4511 Int_t index1=indexes[i1];
4512 if (!(array->UncheckedAt(index1))) continue;
4513 AliTPCseed *s2 = (AliTPCseed*)array->UncheckedAt(index1);
4514 if (!s2->IsActive()) continue;
4515 if (s2->GetKinkIndexes()[0]!=0)
4516 if (s2->GetKinkIndexes()[0] == -s1->GetKinkIndexes()[0]) continue;
4517 AliExternalTrackParam &par1=params[index1];
4518 if (TMath::Abs(par0.GetParameter()[3]-par1.GetParameter()[3])>kCutP3) continue;
4519 if (TMath::Abs(par0.GetParameter()[1]-par1.GetParameter()[1])>kCutP1) continue;
4520 if (TMath::Abs(par0.GetParameter()[2]-par1.GetParameter()[2])>kCutP2) continue;
4521 Double_t dAlpha= TMath::Abs(par0.GetAlpha()-par1.GetAlpha());
4522 if (dAlpha>TMath::Pi()) dAlpha-=TMath::Pi();
4523 if (TMath::Abs(dAlpha)>kCutAlpha) continue;
4528 Int_t firstShared=lastpoint, lastShared=firstpoint;
4529 Int_t firstRow=lastpoint, lastRow=firstpoint;
4531 for (Int_t i=firstpoint;i<lastpoint;i++){
4532 if (s1->GetClusterIndex2(i)>0) nall0++;
4533 if (s2->GetClusterIndex2(i)>0) nall1++;
4534 if (s1->GetClusterIndex2(i)>0 && s2->GetClusterIndex2(i)>0) {
4535 if (i<firstRow) firstRow=i;
4536 if (i>lastRow) lastRow=i;
4538 if ( (s1->GetClusterIndex2(i))==(s2->GetClusterIndex2(i)) && s1->GetClusterIndex2(i)>0) {
4539 if (i<firstShared) firstShared=i;
4540 if (i>lastShared) lastShared=i;
4544 Double_t ratio0 = Float_t(sumShared)/Float_t(TMath::Min(nall0+1,nall1+1));
4545 Double_t ratio1 = Float_t(sumShared)/Float_t(TMath::Max(nall0+1,nall1+1));
4547 if( AliTPCReconstructor::StreamLevel()>1){
4548 TTreeSRedirector &cstream = *fDebugStreamer;
4549 Int_t n0=s1->GetNumberOfClusters();
4550 Int_t n1=s2->GetNumberOfClusters();
4551 Int_t n0F=s1->GetNFoundable();
4552 Int_t n1F=s2->GetNFoundable();
4553 Int_t lab0=s1->GetLabel();
4554 Int_t lab1=s2->GetLabel();
4556 cstream<<"Splitted2"<<
4557 "iter="<<fIteration<<
4558 "lab0="<<lab0<< // MC label if exist
4559 "lab1="<<lab1<< // MC label if exist
4562 "ratio0="<<ratio0<< // shared ratio
4563 "ratio1="<<ratio1<< // shared ratio
4564 "p0.="<<&par0<< // track parameters
4566 "s0.="<<s1<< // full seed
4568 "n0="<<n0<< // number of clusters track 0
4569 "n1="<<n1<< // number of clusters track 1
4570 "nall0="<<nall0<< // number of clusters track 0
4571 "nall1="<<nall1<< // number of clusters track 1
4572 "n0F="<<n0F<< // number of findable
4573 "n1F="<<n1F<< // number of findable
4574 "shared="<<sumShared<< // number of shared clusters
4575 "firstS="<<firstShared<< // first and the last shared row
4576 "lastS="<<lastShared<<
4577 "firstRow="<<firstRow<< // first and the last row with cluster
4578 "lastRow="<<lastRow<< //
4582 // remove track with lower quality
4584 if (ratio0>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(0) ||
4585 ratio1>AliTPCReconstructor::GetRecoParam()->GetCutSharedClusters(1)){
4589 MarkSeedFree( array->RemoveAt(index1) );
4594 // 4. Delete temporary array
4604 void AliTPCtrackerMI::FindCurling(const TObjArray * array, AliESDEvent */*esd*/, Int_t iter)
4607 // find Curling tracks
4608 // Use AliTPCReconstructor::StreamLevel()>1 if you want to tune parameters - cuts
4611 // Algorithm done in 2 phases - because of CPU consumption
4612 // it is n^2 algorithm - for lead-lead 20000x20000 combination are investigated
4613 // see detal in MC part what can be used to cut
4617 const Float_t kMaxC = 400; // maximal curvature to of the track
4618 const Float_t kMaxdTheta = 0.15; // maximal distance in theta
4619 const Float_t kMaxdPhi = 0.15; // maximal distance in phi
4620 const Float_t kPtRatio = 0.3; // ratio between pt
4621 const Float_t kMinDCAR = 2.; // distance to the primary vertex in r - see cpipe cut
4624 // Curling tracks cuts
4627 const Float_t kMaxDeltaRMax = 40; // distance in outer radius
4628 const Float_t kMaxDeltaRMin = 5.; // distance in lower radius - see cpipe cut
4629 const Float_t kMinAngle = 2.9; // angle between tracks
4630 const Float_t kMaxDist = 5; // biggest distance
4632 // The cuts can be tuned using the "MC information stored in Multi tree ==> see FindMultiMC
4635 TCut csign("csign","Tr0.fP[4]*Tr1.fP[4]<0"); //opposite sign
4636 TCut cmax("cmax","abs(Tr0.GetC())>1/400");
4637 TCut cda("cda","sqrt(dtheta^2+dfi^2)<0.15");
4638 TCut ccratio("ccratio","abs((Tr0.fP[4]+Tr1.fP[4])/(abs(Tr0.fP[4])+abs(Tr1.fP[4])))<0.3");
4639 TCut cpipe("cpipe", "min(abs(r0-rc0),abs(r1-rc1))>5");
4641 TCut cdrmax("cdrmax","abs(abs(rc0+r0)-abs(rc1+r1))<40")
4642 TCut cdrmin("cdrmin","abs(abs(rc0+r0)-abs(rc1+r1))<10")
4644 Multi->Draw("dfi","iter==0"+csign+cmax+cda+ccratio); ~94% of curling tracks fulfill
4645 Multi->Draw("min(abs(r0-rc0),abs(r1-rc1))","iter==0&&abs(lab1)==abs(lab0)"+csign+cmax+cda+ccratio+cpipe+cdrmin+cdrmax); //80%
4647 Curling2->Draw("dfi","iter==0&&abs(lab0)==abs(lab1)"+csign+cmax+cdtheta+cdfi+ccratio)
4653 Int_t nentries = array->GetEntriesFast();
4654 AliHelix *helixes = new AliHelix[nentries];
4655 for (Int_t i=0;i<nentries;i++){
4656 AliTPCseed* track = (AliTPCseed*)array->At(i);
4657 if (!track) continue;
4658 track->SetCircular(0);
4659 new (&helixes[i]) AliHelix(*track);
4665 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4671 for (Int_t i0=0;i0<nentries;i0++){
4672 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4673 if (!track0) continue;
4674 if (TMath::Abs(track0->GetC())<1/kMaxC) continue;
4675 Float_t xc0 = helixes[i0].GetHelix(6);
4676 Float_t yc0 = helixes[i0].GetHelix(7);
4677 Float_t r0 = helixes[i0].GetHelix(8);
4678 Float_t rc0 = TMath::Sqrt(xc0*xc0+yc0*yc0);
4679 Float_t fi0 = TMath::ATan2(yc0,xc0);
4681 for (Int_t i1=i0+1;i1<nentries;i1++){
4682 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4683 if (!track1) continue;
4684 if (TMath::Abs(track1->GetC())<1/kMaxC) continue;
4685 Float_t xc1 = helixes[i1].GetHelix(6);
4686 Float_t yc1 = helixes[i1].GetHelix(7);
4687 Float_t r1 = helixes[i1].GetHelix(8);
4688 Float_t rc1 = TMath::Sqrt(xc1*xc1+yc1*yc1);
4689 Float_t fi1 = TMath::ATan2(yc1,xc1);
4691 Float_t dfi = fi0-fi1;
4694 if (dfi>1.5*TMath::Pi()) dfi-=TMath::Pi(); // take care about edge effect
4695 if (dfi<-1.5*TMath::Pi()) dfi+=TMath::Pi(); //
4696 Float_t dtheta = TMath::Abs(track0->GetTgl()-track1->GetTgl())<TMath::Abs(track0->GetTgl()+track1->GetTgl())? track0->GetTgl()-track1->GetTgl():track0->GetTgl()+track1->GetTgl();
4700 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue; // not constrained
4701 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue; // not the same sign
4702 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>kMaxdTheta) continue; //distance in the Theta
4703 if ( TMath::Abs(dfi)>kMaxdPhi) continue; //distance in phi
4704 if ( TMath::Sqrt(dfi*dfi+dtheta*dtheta)>kMaxdPhi) continue; //common angular offset
4706 Float_t pt0 = track0->GetSignedPt();
4707 Float_t pt1 = track1->GetSignedPt();
4708 if ((TMath::Abs(pt0+pt1)/(TMath::Abs(pt0)+TMath::Abs(pt1)))>kPtRatio) continue;
4709 if ((iter==1) && TMath::Abs(TMath::Abs(rc0+r0)-TMath::Abs(rc1+r1))>kMaxDeltaRMax) continue;
4710 if ((iter!=1) &&TMath::Abs(TMath::Abs(rc0-r0)-TMath::Abs(rc1-r1))>kMaxDeltaRMin) continue;
4711 if (TMath::Min(TMath::Abs(rc0-r0),TMath::Abs(rc1-r1))<kMinDCAR) continue;
4714 // Now find closest approach
4718 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4719 if (npoints==0) continue;
4720 helixes[i0].GetClosestPhases(helixes[i1], phase);
4724 Double_t hangles[3];
4725 helixes[i0].Evaluate(phase[0][0],xyz0);
4726 helixes[i1].Evaluate(phase[0][1],xyz1);
4728 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4729 Double_t deltah[2],deltabest;
4730 if (TMath::Abs(hangles[2])<kMinAngle) continue;
4734 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
4736 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
4737 if (deltah[1]<deltah[0]) ibest=1;
4739 deltabest = TMath::Sqrt(deltah[ibest]);
4740 helixes[i0].Evaluate(phase[ibest][0],xyz0);
4741 helixes[i1].Evaluate(phase[ibest][1],xyz1);
4742 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
4743 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
4745 if (deltabest>kMaxDist) continue;
4746 // if (mindcar+mindcaz<40 && (TMath::Abs(hangles[2])<kMinAngle ||deltabest>3)) continue;
4747 Bool_t sign =kFALSE;
4748 if (hangles[2]>kMinAngle) sign =kTRUE;
4751 // circular[i0] = kTRUE;
4752 // circular[i1] = kTRUE;
4753 if (track0->OneOverPt()<track1->OneOverPt()){
4754 track0->SetCircular(track0->GetCircular()+1);
4755 track1->SetCircular(track1->GetCircular()+2);
4758 track1->SetCircular(track1->GetCircular()+1);
4759 track0->SetCircular(track0->GetCircular()+2);
4762 if (AliTPCReconstructor::StreamLevel()>2){
4764 //debug stream to tune "fine" cuts
4765 Int_t lab0=track0->GetLabel();
4766 Int_t lab1=track1->GetLabel();
4767 TTreeSRedirector &cstream = *fDebugStreamer;
4768 cstream<<"Curling2"<<
4784 "npoints="<<npoints<<
4785 "hangles0="<<hangles[0]<<
4786 "hangles1="<<hangles[1]<<
4787 "hangles2="<<hangles[2]<<
4790 "radius="<<radiusbest<<
4791 "deltabest="<<deltabest<<
4792 "phase0="<<phase[ibest][0]<<
4793 "phase1="<<phase[ibest][1]<<
4801 if (AliTPCReconstructor::StreamLevel()>1) {
4802 AliInfo("Time for curling tracks removal");
4808 void AliTPCtrackerMI::FindKinks(TObjArray * array, AliESDEvent *esd)
4814 // RS something is wrong in this routine: not all seeds are assigned to daughters and mothers array, but they all are queried
4817 TObjArray *kinks= new TObjArray(10000);
4818 // TObjArray *v0s= new TObjArray(10000);
4819 Int_t nentries = array->GetEntriesFast();
4820 AliHelix *helixes = new AliHelix[nentries];
4821 Int_t *sign = new Int_t[nentries];
4822 Int_t *nclusters = new Int_t[nentries];
4823 Float_t *alpha = new Float_t[nentries];
4824 AliKink *kink = new AliKink();
4825 Int_t * usage = new Int_t[nentries];
4826 Float_t *zm = new Float_t[nentries];
4827 Float_t *z0 = new Float_t[nentries];
4828 Float_t *fim = new Float_t[nentries];
4829 Float_t *shared = new Float_t[nentries];
4830 Bool_t *circular = new Bool_t[nentries];
4831 Float_t *dca = new Float_t[nentries];
4832 //const AliESDVertex * primvertex = esd->GetVertex();
4834 // nentries = array->GetEntriesFast();
4839 for (Int_t i=0;i<nentries;i++){
4842 AliTPCseed* track = (AliTPCseed*)array->At(i);
4843 if (!track) continue;
4844 track->SetCircular(0);
4846 track->UpdatePoints();
4847 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
4849 nclusters[i]=track->GetNumberOfClusters();
4850 alpha[i] = track->GetAlpha();
4851 new (&helixes[i]) AliHelix(*track);
4853 helixes[i].Evaluate(0,xyz);
4854 sign[i] = (track->GetC()>0) ? -1:1;
4857 if (track->GetProlongation(x,y,z)){
4859 fim[i] = alpha[i]+TMath::ATan2(y,x);
4862 zm[i] = track->GetZ();
4866 circular[i]= kFALSE;
4867 if (track->GetProlongation(0,y,z)) z0[i] = z;
4868 dca[i] = track->GetD(0,0);
4874 Int_t ncandidates =0;
4877 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
4880 // Find circling track
4882 for (Int_t i0=0;i0<nentries;i0++){
4883 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
4884 if (!track0) continue;
4885 if (track0->GetNumberOfClusters()<40) continue;
4886 if (TMath::Abs(1./track0->GetC())>200) continue;
4887 for (Int_t i1=i0+1;i1<nentries;i1++){
4888 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
4889 if (!track1) continue;
4890 if (track1->GetNumberOfClusters()<40) continue;
4891 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
4892 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
4893 if (TMath::Abs(1./track1->GetC())>200) continue;
4894 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
4895 if (track1->GetTgl()*track0->GetTgl()>0) continue;
4896 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
4897 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
4898 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
4900 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
4901 if (mindcar<5) continue;
4902 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
4903 if (mindcaz<5) continue;
4904 if (mindcar+mindcaz<20) continue;
4907 Float_t xc0 = helixes[i0].GetHelix(6);
4908 Float_t yc0 = helixes[i0].GetHelix(7);
4909 Float_t r0 = helixes[i0].GetHelix(8);
4910 Float_t xc1 = helixes[i1].GetHelix(6);
4911 Float_t yc1 = helixes[i1].GetHelix(7);
4912 Float_t r1 = helixes[i1].GetHelix(8);
4914 Float_t rmean = (r0+r1)*0.5;
4915 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
4916 //if (delta>30) continue;
4917 if (delta>rmean*0.25) continue;
4918 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
4920 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
4921 if (npoints==0) continue;
4922 helixes[i0].GetClosestPhases(helixes[i1], phase);
4926 Double_t hangles[3];
4927 helixes[i0].Evaluate(phase[0][0],xyz0);
4928 helixes[i1].Evaluate(phase[0][1],xyz1);
4930 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
4931 Double_t deltah[2],deltabest;
4932 if (hangles[2]<2.8) continue;
4935 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
4937 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
4938 if (deltah[1]<deltah[0]) ibest=1;
4940 deltabest = TMath::Sqrt(deltah[ibest]);
4941 helixes[i0].Evaluate(phase[ibest][0],xyz0);
4942 helixes[i1].Evaluate(phase[ibest][1],xyz1);
4943 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
4944 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
4946 if (deltabest>6) continue;
4947 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
4948 Bool_t lsign =kFALSE;
4949 if (hangles[2]>3.06) lsign =kTRUE;
4952 circular[i0] = kTRUE;
4953 circular[i1] = kTRUE;
4954 if (track0->OneOverPt()<track1->OneOverPt()){
4955 track0->SetCircular(track0->GetCircular()+1);
4956 track1->SetCircular(track1->GetCircular()+2);
4959 track1->SetCircular(track1->GetCircular()+1);
4960 track0->SetCircular(track0->GetCircular()+2);
4963 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
4965 Int_t lab0=track0->GetLabel();
4966 Int_t lab1=track1->GetLabel();
4967 TTreeSRedirector &cstream = *fDebugStreamer;
4968 cstream<<"Curling"<<
4975 "mindcar="<<mindcar<<
4976 "mindcaz="<<mindcaz<<
4979 "npoints="<<npoints<<
4980 "hangles0="<<hangles[0]<<
4981 "hangles2="<<hangles[2]<<
4986 "radius="<<radiusbest<<
4987 "deltabest="<<deltabest<<
4988 "phase0="<<phase[ibest][0]<<
4989 "phase1="<<phase[ibest][1]<<
4999 for (Int_t i =0;i<nentries;i++){
5000 if (sign[i]==0) continue;
5001 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5008 Double_t cradius0 = 40*40;
5009 Double_t cradius1 = 270*270;
5012 Double_t cdist3=0.55;
5013 for (Int_t j =i+1;j<nentries;j++){
5015 if (sign[j]*sign[i]<1) continue;
5016 if ( (nclusters[i]+nclusters[j])>200) continue;
5017 if ( (nclusters[i]+nclusters[j])<80) continue;
5018 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5019 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5020 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5021 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5022 if (npoints<1) continue;
5025 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5028 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5031 Double_t delta1=10000,delta2=10000;
5032 // cuts on the intersection radius
5033 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5034 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5035 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5037 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5038 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5039 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5042 Double_t distance1 = TMath::Min(delta1,delta2);
5043 if (distance1>cdist1) continue; // cut on DCA linear approximation
5045 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5046 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5047 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5048 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5051 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5052 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5053 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5055 distance1 = TMath::Min(delta1,delta2);
5058 rkink = TMath::Sqrt(radius[0]);
5061 rkink = TMath::Sqrt(radius[1]);
5063 if (distance1>cdist2) continue;
5066 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5069 Int_t row0 = GetRowNumber(rkink);
5070 if (row0<10) continue;
5071 if (row0>150) continue;
5074 Float_t dens00=-1,dens01=-1;
5075 Float_t dens10=-1,dens11=-1;
5077 Int_t found,foundable,ishared;
5078 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5079 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5080 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5081 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5083 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5084 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5085 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5086 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5088 if (dens00<dens10 && dens01<dens11) continue;
5089 if (dens00>dens10 && dens01>dens11) continue;
5090 if (TMath::Max(dens00,dens10)<0.1) continue;
5091 if (TMath::Max(dens01,dens11)<0.3) continue;
5093 if (TMath::Min(dens00,dens10)>0.6) continue;
5094 if (TMath::Min(dens01,dens11)>0.6) continue;
5097 AliTPCseed * ktrack0, *ktrack1;
5106 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5107 AliExternalTrackParam paramm(*ktrack0);
5108 AliExternalTrackParam paramd(*ktrack1);
5109 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5112 kink->SetMother(paramm);
5113 kink->SetDaughter(paramd);
5116 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
5118 fkParam->Transform0to1(x,index);
5119 fkParam->Transform1to2(x,index);
5120 row0 = GetRowNumber(x[0]);
5122 if (kink->GetR()<100) continue;
5123 if (kink->GetR()>240) continue;
5124 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5125 if (kink->GetDistance()>cdist3) continue;
5126 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5127 if (dird<0) continue;
5129 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5130 if (dirm<0) continue;
5131 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5132 if (mpt<0.2) continue;
5135 //for high momenta momentum not defined well in first iteration
5136 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5137 if (qt>0.35) continue;
5140 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5141 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5143 kink->SetTPCDensity(dens00,0,0);
5144 kink->SetTPCDensity(dens01,0,1);
5145 kink->SetTPCDensity(dens10,1,0);
5146 kink->SetTPCDensity(dens11,1,1);
5147 kink->SetIndex(i,0);
5148 kink->SetIndex(j,1);
5151 kink->SetTPCDensity(dens10,0,0);
5152 kink->SetTPCDensity(dens11,0,1);
5153 kink->SetTPCDensity(dens00,1,0);
5154 kink->SetTPCDensity(dens01,1,1);
5155 kink->SetIndex(j,0);
5156 kink->SetIndex(i,1);
5159 if (mpt<1||kink->GetAngle(2)>0.1){
5160 // angle and densities not defined yet
5161 if (kink->GetTPCDensityFactor()<0.8) continue;
5162 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5163 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5164 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5165 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5167 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5168 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5169 criticalangle= 3*TMath::Sqrt(criticalangle);
5170 if (criticalangle>0.02) criticalangle=0.02;
5171 if (kink->GetAngle(2)<criticalangle) continue;
5174 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5175 Float_t shapesum =0;
5177 for ( Int_t row = row0-drow; row<row0+drow;row++){
5178 if (row<0) continue;
5179 if (row>155) continue;
5180 if (ktrack0->GetClusterPointer(row)){
5181 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5182 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5185 if (ktrack1->GetClusterPointer(row)){
5186 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5187 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5192 kink->SetShapeFactor(-1.);
5195 kink->SetShapeFactor(shapesum/sum);
5197 // esd->AddKink(kink);
5199 // kink->SetMother(paramm);
5200 //kink->SetDaughter(paramd);
5202 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5204 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5205 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5207 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5209 if (AliTPCReconstructor::StreamLevel()>1) {
5210 (*fDebugStreamer)<<"kinkLpt"<<
5218 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5222 kinks->AddLast(kink);
5228 // sort the kinks according quality - and refit them towards vertex
5230 Int_t nkinks = kinks->GetEntriesFast();
5231 Float_t *quality = new Float_t[nkinks];
5232 Int_t *indexes = new Int_t[nkinks];
5233 AliTPCseed *mothers = new AliTPCseed[nkinks];
5234 AliTPCseed *daughters = new AliTPCseed[nkinks];
5237 for (Int_t i=0;i<nkinks;i++){
5239 AliKink *kinkl = (AliKink*)kinks->At(i);
5241 // refit kinks towards vertex
5243 Int_t index0 = kinkl->GetIndex(0);
5244 Int_t index1 = kinkl->GetIndex(1);
5245 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5246 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5248 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5250 // Refit Kink under if too small angle
5252 if (kinkl->GetAngle(2)<0.05){
5253 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5254 Int_t row0 = kinkl->GetTPCRow0();
5255 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5258 Int_t last = row0-drow;
5259 if (last<40) last=40;
5260 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5261 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5264 Int_t first = row0+drow;
5265 if (first>130) first=130;
5266 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5267 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5269 if (seed0 && seed1){
5270 kinkl->SetStatus(1,8);
5271 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5272 row0 = GetRowNumber(kinkl->GetR());
5273 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5274 mothers[i] = *seed0;
5275 daughters[i] = *seed1;
5278 delete kinks->RemoveAt(i);
5279 if (seed0) MarkSeedFree( seed0 );
5280 if (seed1) MarkSeedFree( seed1 );
5283 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
5284 delete kinks->RemoveAt(i);
5285 if (seed0) MarkSeedFree( seed0 );
5286 if (seed1) MarkSeedFree( seed1 );
5290 MarkSeedFree( seed0 );
5291 MarkSeedFree( seed1 );
5294 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
5296 TMath::Sort(nkinks,quality,indexes,kFALSE);
5298 //remove double find kinks
5300 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
5301 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5302 if (!kink0) continue;
5304 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
5305 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
5306 if (!kink0) continue;
5307 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
5308 if (!kink1) continue;
5309 // if not close kink continue
5310 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
5311 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
5312 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
5314 AliTPCseed &mother0 = mothers[indexes[ikink0]];
5315 AliTPCseed &daughter0 = daughters[indexes[ikink0]];
5316 AliTPCseed &mother1 = mothers[indexes[ikink1]];
5317 AliTPCseed &daughter1 = daughters[indexes[ikink1]];
5318 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
5327 for (Int_t i=0;i<row0;i++){
5328 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
5331 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5338 for (Int_t i=row0;i<158;i++){
5339 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
5340 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
5343 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
5349 Float_t ratio = Float_t(same+1)/Float_t(both+1);
5350 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
5351 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
5352 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
5353 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
5354 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
5356 shared[kink0->GetIndex(0)]= kTRUE;
5357 shared[kink0->GetIndex(1)]= kTRUE;
5358 delete kinks->RemoveAt(indexes[ikink0]);
5362 shared[kink1->GetIndex(0)]= kTRUE;
5363 shared[kink1->GetIndex(1)]= kTRUE;
5364 delete kinks->RemoveAt(indexes[ikink1]);
5371 for (Int_t i=0;i<nkinks;i++){
5372 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
5373 if (!kinkl) continue;
5374 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5375 Int_t index0 = kinkl->GetIndex(0);
5376 Int_t index1 = kinkl->GetIndex(1);
5377 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
5378 kinkl->SetMultiple(usage[index0],0);
5379 kinkl->SetMultiple(usage[index1],1);
5380 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
5381 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
5382 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
5383 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
5385 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5386 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5387 if (!ktrack0 || !ktrack1) continue;
5388 Int_t index = esd->AddKink(kinkl);
5391 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
5392 if (mothers[indexes[i]].GetNumberOfClusters()>20 && daughters[indexes[i]].GetNumberOfClusters()>20 && (mothers[indexes[i]].GetNumberOfClusters()+daughters[indexes[i]].GetNumberOfClusters())>100){
5393 *ktrack0 = mothers[indexes[i]];
5394 *ktrack1 = daughters[indexes[i]];
5398 ktrack0->SetKinkIndex(usage[index0],-(index+1));
5399 ktrack1->SetKinkIndex(usage[index1], (index+1));
5404 // Remove tracks corresponding to shared kink's
5406 for (Int_t i=0;i<nentries;i++){
5407 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5408 if (!track0) continue;
5409 if (track0->GetKinkIndex(0)!=0) continue;
5410 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
5415 RemoveUsed2(array,0.5,0.4,30);
5417 for (Int_t i=0;i<nentries;i++){
5418 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5419 if (!track0) continue;
5420 track0->CookdEdx(0.02,0.6);
5424 for (Int_t i=0;i<nentries;i++){
5425 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5426 if (!track0) continue;
5427 if (track0->Pt()<1.4) continue;
5428 //remove double high momenta tracks - overlapped with kink candidates
5431 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
5432 if (track0->GetClusterPointer(icl)!=0){
5434 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
5437 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
5438 MarkSeedFree( array->RemoveAt(i) );
5442 if (track0->GetKinkIndex(0)!=0) continue;
5443 if (track0->GetNumberOfClusters()<80) continue;
5445 AliTPCseed *pmother = new AliTPCseed();
5446 AliTPCseed *pdaughter = new AliTPCseed();
5447 AliKink *pkink = new AliKink;
5449 AliTPCseed & mother = *pmother;
5450 AliTPCseed & daughter = *pdaughter;
5451 AliKink & kinkl = *pkink;
5452 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
5453 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
5457 continue; //too short tracks
5459 if (mother.Pt()<1.4) {
5465 Int_t row0= kinkl.GetTPCRow0();
5466 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
5473 Int_t index = esd->AddKink(&kinkl);
5474 mother.SetKinkIndex(0,-(index+1));
5475 daughter.SetKinkIndex(0,index+1);
5476 if (mother.GetNumberOfClusters()>50) {
5477 MarkSeedFree( array->RemoveAt(i) );
5478 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5479 mtc->SetPoolID(fLastSeedID);
5480 array->AddAt(mtc,i);
5483 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
5484 mtc->SetPoolID(fLastSeedID);
5485 array->AddLast(mtc);
5487 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
5488 dtc->SetPoolID(fLastSeedID);
5489 array->AddLast(dtc);
5490 for (Int_t icl=0;icl<row0;icl++) {
5491 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
5494 for (Int_t icl=row0;icl<158;icl++) {
5495 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
5504 delete [] daughters;
5526 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
5532 void AliTPCtrackerMI::FindKinks(TObjArray * array, AliESDEvent *esd)
5539 TObjArray *kinks= new TObjArray(10000);
5540 // TObjArray *v0s= new TObjArray(10000);
5541 Int_t nentries = array->GetEntriesFast();
5542 AliHelix *helixes = new AliHelix[nentries];
5543 Int_t *sign = new Int_t[nentries];
5544 Int_t *nclusters = new Int_t[nentries];
5545 Float_t *alpha = new Float_t[nentries];
5546 AliKink *kink = new AliKink();
5547 Int_t * usage = new Int_t[nentries];
5548 Float_t *zm = new Float_t[nentries];
5549 Float_t *z0 = new Float_t[nentries];
5550 Float_t *fim = new Float_t[nentries];
5551 Float_t *shared = new Float_t[nentries];
5552 Bool_t *circular = new Bool_t[nentries];
5553 Float_t *dca = new Float_t[nentries];
5554 //const AliESDVertex * primvertex = esd->GetVertex();
5556 // nentries = array->GetEntriesFast();
5561 for (Int_t i=0;i<nentries;i++){
5564 AliTPCseed* track = (AliTPCseed*)array->At(i);
5565 if (!track) continue;
5566 track->SetCircular(0);
5568 track->UpdatePoints();
5569 if (( track->GetPoints()[2]- track->GetPoints()[0])>5 && track->GetPoints()[3]>0.8){
5571 nclusters[i]=track->GetNumberOfClusters();
5572 alpha[i] = track->GetAlpha();
5573 new (&helixes[i]) AliHelix(*track);
5575 helixes[i].Evaluate(0,xyz);
5576 sign[i] = (track->GetC()>0) ? -1:1;
5579 if (track->GetProlongation(x,y,z)){
5581 fim[i] = alpha[i]+TMath::ATan2(y,x);
5584 zm[i] = track->GetZ();
5588 circular[i]= kFALSE;
5589 if (track->GetProlongation(0,y,z)) z0[i] = z;
5590 dca[i] = track->GetD(0,0);
5596 Int_t ncandidates =0;
5599 Double_t phase[2][2]={{0,0},{0,0}},radius[2]={0,0};
5602 // Find circling track
5604 for (Int_t i0=0;i0<nentries;i0++){
5605 AliTPCseed * track0 = (AliTPCseed*)array->At(i0);
5606 if (!track0) continue;
5607 if (track0->GetNumberOfClusters()<40) continue;
5608 if (TMath::Abs(1./track0->GetC())>200) continue;
5609 for (Int_t i1=i0+1;i1<nentries;i1++){
5610 AliTPCseed * track1 = (AliTPCseed*)array->At(i1);
5611 if (!track1) continue;
5612 if (track1->GetNumberOfClusters()<40) continue;
5613 if ( TMath::Abs(track1->GetTgl()+track0->GetTgl())>0.1) continue;
5614 if (track0->GetBConstrain()&&track1->GetBConstrain()) continue;
5615 if (TMath::Abs(1./track1->GetC())>200) continue;
5616 if (track1->GetSigned1Pt()*track0->GetSigned1Pt()>0) continue;
5617 if (track1->GetTgl()*track0->GetTgl()>0) continue;
5618 if (TMath::Max(TMath::Abs(1./track0->GetC()),TMath::Abs(1./track1->GetC()))>190) continue;
5619 if (track0->GetBConstrain()&&track1->OneOverPt()<track0->OneOverPt()) continue; //returning - lower momenta
5620 if (track1->GetBConstrain()&&track0->OneOverPt()<track1->OneOverPt()) continue; //returning - lower momenta
5622 Float_t mindcar = TMath::Min(TMath::Abs(dca[i0]),TMath::Abs(dca[i1]));
5623 if (mindcar<5) continue;
5624 Float_t mindcaz = TMath::Min(TMath::Abs(z0[i0]-GetZ()),TMath::Abs(z0[i1]-GetZ()));
5625 if (mindcaz<5) continue;
5626 if (mindcar+mindcaz<20) continue;
5629 Float_t xc0 = helixes[i0].GetHelix(6);
5630 Float_t yc0 = helixes[i0].GetHelix(7);
5631 Float_t r0 = helixes[i0].GetHelix(8);
5632 Float_t xc1 = helixes[i1].GetHelix(6);
5633 Float_t yc1 = helixes[i1].GetHelix(7);
5634 Float_t r1 = helixes[i1].GetHelix(8);
5636 Float_t rmean = (r0+r1)*0.5;
5637 Float_t delta =TMath::Sqrt((xc1-xc0)*(xc1-xc0)+(yc1-yc0)*(yc1-yc0));
5638 //if (delta>30) continue;
5639 if (delta>rmean*0.25) continue;
5640 if (TMath::Abs(r0-r1)/rmean>0.3) continue;
5642 Int_t npoints = helixes[i0].GetRPHIintersections(helixes[i1], phase, radius,10);
5643 if (npoints==0) continue;
5644 helixes[i0].GetClosestPhases(helixes[i1], phase);
5648 Double_t hangles[3];
5649 helixes[i0].Evaluate(phase[0][0],xyz0);
5650 helixes[i1].Evaluate(phase[0][1],xyz1);
5652 helixes[i0].GetAngle(phase[0][0],helixes[i1],phase[0][1],hangles);
5653 Double_t deltah[2],deltabest;
5654 if (hangles[2]<2.8) continue;
5657 helixes[i0].ParabolicDCA(helixes[i1],phase[0][0],phase[0][1],radius[0],deltah[0],2);
5659 helixes[i0].ParabolicDCA(helixes[i1],phase[1][0],phase[1][1],radius[1],deltah[1],2);
5660 if (deltah[1]<deltah[0]) ibest=1;
5662 deltabest = TMath::Sqrt(deltah[ibest]);
5663 helixes[i0].Evaluate(phase[ibest][0],xyz0);
5664 helixes[i1].Evaluate(phase[ibest][1],xyz1);
5665 helixes[i0].GetAngle(phase[ibest][0],helixes[i1],phase[ibest][1],hangles);
5666 Double_t radiusbest = TMath::Sqrt(radius[ibest]);
5668 if (deltabest>6) continue;
5669 if (mindcar+mindcaz<40 && (hangles[2]<3.12||deltabest>3)) continue;
5670 Bool_t lsign =kFALSE;
5671 if (hangles[2]>3.06) lsign =kTRUE;
5674 circular[i0] = kTRUE;
5675 circular[i1] = kTRUE;
5676 if (track0->OneOverPt()<track1->OneOverPt()){
5677 track0->SetCircular(track0->GetCircular()+1);
5678 track1->SetCircular(track1->GetCircular()+2);
5681 track1->SetCircular(track1->GetCircular()+1);
5682 track0->SetCircular(track0->GetCircular()+2);
5685 if (lsign&&AliTPCReconstructor::StreamLevel()>1){
5687 Int_t lab0=track0->GetLabel();
5688 Int_t lab1=track1->GetLabel();
5689 TTreeSRedirector &cstream = *fDebugStreamer;
5690 cstream<<"Curling"<<
5697 "mindcar="<<mindcar<<
5698 "mindcaz="<<mindcaz<<
5701 "npoints="<<npoints<<
5702 "hangles0="<<hangles[0]<<
5703 "hangles2="<<hangles[2]<<
5708 "radius="<<radiusbest<<
5709 "deltabest="<<deltabest<<
5710 "phase0="<<phase[ibest][0]<<
5711 "phase1="<<phase[ibest][1]<<
5721 for (Int_t i =0;i<nentries;i++){
5722 if (sign[i]==0) continue;
5723 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
5730 Double_t cradius0 = 40*40;
5731 Double_t cradius1 = 270*270;
5734 Double_t cdist3=0.55;
5735 for (Int_t j =i+1;j<nentries;j++){
5737 if (sign[j]*sign[i]<1) continue;
5738 if ( (nclusters[i]+nclusters[j])>200) continue;
5739 if ( (nclusters[i]+nclusters[j])<80) continue;
5740 if ( TMath::Abs(zm[i]-zm[j])>60.) continue;
5741 if ( TMath::Abs(fim[i]-fim[j])>0.6 && TMath::Abs(fim[i]-fim[j])<5.7 ) continue;
5742 //AliTPCseed * track1 = (AliTPCseed*)array->At(j); Double_t phase[2][2],radius[2];
5743 Int_t npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5744 if (npoints<1) continue;
5747 if (radius[0]<cradius0||radius[0]>cradius1) continue;
5750 if ( (radius[0]<cradius0||radius[0]>cradius1) && (radius[1]<cradius0||radius[1]>cradius1) ) continue;
5753 Double_t delta1=10000,delta2=10000;
5754 // cuts on the intersection radius
5755 helixes[i].LinearDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5756 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5757 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5759 helixes[i].LinearDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5760 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5761 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5764 Double_t distance1 = TMath::Min(delta1,delta2);
5765 if (distance1>cdist1) continue; // cut on DCA linear approximation
5767 npoints = helixes[i].GetRPHIintersections(helixes[j], phase, radius,20);
5768 helixes[i].ParabolicDCA(helixes[j],phase[0][0],phase[0][1],radius[0],delta1);
5769 if (radius[0]<20&&delta1<1) continue; //intersection at vertex
5770 if (radius[0]<10&&delta1<3) continue; //intersection at vertex
5773 helixes[i].ParabolicDCA(helixes[j],phase[1][0],phase[1][1],radius[1],delta2);
5774 if (radius[1]<20&&delta2<1) continue; //intersection at vertex
5775 if (radius[1]<10&&delta2<3) continue; //intersection at vertex
5777 distance1 = TMath::Min(delta1,delta2);
5780 rkink = TMath::Sqrt(radius[0]);
5783 rkink = TMath::Sqrt(radius[1]);
5785 if (distance1>cdist2) continue;
5788 AliTPCseed * track1 = (AliTPCseed*)array->At(j);
5791 Int_t row0 = GetRowNumber(rkink);
5792 if (row0<10) continue;
5793 if (row0>150) continue;
5796 Float_t dens00=-1,dens01=-1;
5797 Float_t dens10=-1,dens11=-1;
5799 Int_t found,foundable,ishared;
5800 track0->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5801 if (foundable>5) dens00 = Float_t(found)/Float_t(foundable);
5802 track0->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5803 if (foundable>5) dens01 = Float_t(found)/Float_t(foundable);
5805 track1->GetClusterStatistic(0,row0-5, found, foundable,ishared,kFALSE);
5806 if (foundable>10) dens10 = Float_t(found)/Float_t(foundable);
5807 track1->GetClusterStatistic(row0+5,155, found, foundable,ishared,kFALSE);
5808 if (foundable>10) dens11 = Float_t(found)/Float_t(foundable);
5810 if (dens00<dens10 && dens01<dens11) continue;
5811 if (dens00>dens10 && dens01>dens11) continue;
5812 if (TMath::Max(dens00,dens10)<0.1) continue;
5813 if (TMath::Max(dens01,dens11)<0.3) continue;
5815 if (TMath::Min(dens00,dens10)>0.6) continue;
5816 if (TMath::Min(dens01,dens11)>0.6) continue;
5819 AliTPCseed * ktrack0, *ktrack1;
5828 if (TMath::Abs(ktrack0->GetC())>5) continue; // cut on the curvature for mother particle
5829 AliExternalTrackParam paramm(*ktrack0);
5830 AliExternalTrackParam paramd(*ktrack1);
5831 if (row0>60&&ktrack1->GetReference().GetX()>90.)new (¶md) AliExternalTrackParam(ktrack1->GetReference());
5834 kink->SetMother(paramm);
5835 kink->SetDaughter(paramd);
5838 Float_t x[3] = { kink->GetPosition()[0],kink->GetPosition()[1],kink->GetPosition()[2]};
5840 fkParam->Transform0to1(x,index);
5841 fkParam->Transform1to2(x,index);
5842 row0 = GetRowNumber(x[0]);
5844 if (kink->GetR()<100) continue;
5845 if (kink->GetR()>240) continue;
5846 if (kink->GetPosition()[2]/kink->GetR()>AliTPCReconstructor::GetCtgRange()) continue; //out of fiducial volume
5847 if (kink->GetDistance()>cdist3) continue;
5848 Float_t dird = kink->GetDaughterP()[0]*kink->GetPosition()[0]+kink->GetDaughterP()[1]*kink->GetPosition()[1]; // rough direction estimate
5849 if (dird<0) continue;
5851 Float_t dirm = kink->GetMotherP()[0]*kink->GetPosition()[0]+kink->GetMotherP()[1]*kink->GetPosition()[1]; // rough direction estimate
5852 if (dirm<0) continue;
5853 Float_t mpt = TMath::Sqrt(kink->GetMotherP()[0]*kink->GetMotherP()[0]+kink->GetMotherP()[1]*kink->GetMotherP()[1]);
5854 if (mpt<0.2) continue;
5857 //for high momenta momentum not defined well in first iteration
5858 Double_t qt = TMath::Sin(kink->GetAngle(2))*ktrack1->GetP();
5859 if (qt>0.35) continue;
5862 kink->SetLabel(CookLabel(ktrack0,0.4,0,row0),0);
5863 kink->SetLabel(CookLabel(ktrack1,0.4,row0,160),1);
5865 kink->SetTPCDensity(dens00,0,0);
5866 kink->SetTPCDensity(dens01,0,1);
5867 kink->SetTPCDensity(dens10,1,0);
5868 kink->SetTPCDensity(dens11,1,1);
5869 kink->SetIndex(i,0);
5870 kink->SetIndex(j,1);
5873 kink->SetTPCDensity(dens10,0,0);
5874 kink->SetTPCDensity(dens11,0,1);
5875 kink->SetTPCDensity(dens00,1,0);
5876 kink->SetTPCDensity(dens01,1,1);
5877 kink->SetIndex(j,0);
5878 kink->SetIndex(i,1);
5881 if (mpt<1||kink->GetAngle(2)>0.1){
5882 // angle and densities not defined yet
5883 if (kink->GetTPCDensityFactor()<0.8) continue;
5884 if ((2-kink->GetTPCDensityFactor())*kink->GetDistance() >0.25) continue;
5885 if (kink->GetAngle(2)*ktrack0->GetP()<0.003) continue; //too small angle
5886 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensityFactor()<1.15) continue;
5887 if (kink->GetAngle(2)>0.2&&kink->GetTPCDensity(0,1)>0.05) continue;
5889 Float_t criticalangle = track0->GetSigmaSnp2()+track0->GetSigmaTgl2();
5890 criticalangle+= track1->GetSigmaSnp2()+track1->GetSigmaTgl2();
5891 criticalangle= 3*TMath::Sqrt(criticalangle);
5892 if (criticalangle>0.02) criticalangle=0.02;
5893 if (kink->GetAngle(2)<criticalangle) continue;
5896 Int_t drow = Int_t(2.+0.5/(0.05+kink->GetAngle(2))); // overlap region defined
5897 Float_t shapesum =0;
5899 for ( Int_t row = row0-drow; row<row0+drow;row++){
5900 if (row<0) continue;
5901 if (row>155) continue;
5902 if (ktrack0->GetClusterPointer(row)){
5903 AliTPCTrackerPoint *point =ktrack0->GetTrackPoint(row);
5904 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5907 if (ktrack1->GetClusterPointer(row)){
5908 AliTPCTrackerPoint *point =ktrack1->GetTrackPoint(row);
5909 shapesum+=point->GetSigmaY()+point->GetSigmaZ();
5914 kink->SetShapeFactor(-1.);
5917 kink->SetShapeFactor(shapesum/sum);
5919 // esd->AddKink(kink);
5921 // kink->SetMother(paramm);
5922 //kink->SetDaughter(paramd);
5924 Double_t chi2P2 = paramm.GetParameter()[2]-paramd.GetParameter()[2];
5926 chi2P2/=paramm.GetCovariance()[5]+paramd.GetCovariance()[5];
5927 Double_t chi2P3 = paramm.GetParameter()[3]-paramd.GetParameter()[3];
5929 chi2P3/=paramm.GetCovariance()[9]+paramd.GetCovariance()[9];
5931 if (AliTPCReconstructor::StreamLevel()>1) {
5932 (*fDebugStreamer)<<"kinkLpt"<<
5940 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
5944 kinks->AddLast(kink);
5950 // sort the kinks according quality - and refit them towards vertex
5952 Int_t nkinks = kinks->GetEntriesFast();
5953 Float_t *quality = new Float_t[nkinks];
5954 Int_t *indexes = new Int_t[nkinks];
5955 AliTPCseed **mothers = new AliTPCseed*[nkinks]; memset(mothers, 0, nkinks*sizeof(AliTPCseed*));
5956 AliTPCseed **daughters = new AliTPCseed*[nkinks]; memset(daughters, 0, nkinks*sizeof(AliTPCseed*));
5959 for (Int_t i=0;i<nkinks;i++){
5961 AliKink *kinkl = (AliKink*)kinks->At(i);
5963 // refit kinks towards vertex
5965 Int_t index0 = kinkl->GetIndex(0);
5966 Int_t index1 = kinkl->GetIndex(1);
5967 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
5968 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
5970 Int_t sumn=ktrack0->GetNumberOfClusters()+ktrack1->GetNumberOfClusters();
5972 // Refit Kink under if too small angle
5974 if (kinkl->GetAngle(2)<0.05){
5975 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
5976 Int_t row0 = kinkl->GetTPCRow0();
5977 Int_t drow = Int_t(2.+0.5/(0.05+kinkl->GetAngle(2)));
5980 Int_t last = row0-drow;
5981 if (last<40) last=40;
5982 if (last<ktrack0->GetFirstPoint()+25) last = ktrack0->GetFirstPoint()+25;
5983 AliTPCseed* seed0 = ReSeed(ktrack0,last,kFALSE);
5986 Int_t first = row0+drow;
5987 if (first>130) first=130;
5988 if (first>ktrack1->GetLastPoint()-25) first = TMath::Max(ktrack1->GetLastPoint()-25,30);
5989 AliTPCseed* seed1 = ReSeed(ktrack1,first,kTRUE);
5991 if (seed0 && seed1){
5992 kinkl->SetStatus(1,8);
5993 if (RefitKink(*seed0,*seed1,*kinkl)) kinkl->SetStatus(1,9);
5994 row0 = GetRowNumber(kinkl->GetR());
5995 sumn = seed0->GetNumberOfClusters()+seed1->GetNumberOfClusters();
5996 mothers[i] = new ( NextFreeSeed() ) AliTPCseed(*seed0);
5997 mothers[i]->SetPoolID(fLastSeedID);
5998 daughters[i] = new (NextFreeSeed() ) AliTPCseed(*seed1);
5999 daughters[i]->SetPoolID(fLastSeedID);
6002 delete kinks->RemoveAt(i);
6003 if (seed0) MarkSeedFree( seed0 );
6004 if (seed1) MarkSeedFree( seed1 );
6007 if (kinkl->GetDistance()>0.5 || kinkl->GetR()<110 || kinkl->GetR()>240) {
6008 delete kinks->RemoveAt(i);
6009 if (seed0) MarkSeedFree( seed0 );
6010 if (seed1) MarkSeedFree( seed1 );
6014 MarkSeedFree( seed0 );
6015 MarkSeedFree( seed1 );
6018 if (kinkl) quality[i] = 160*((0.1+kinkl->GetDistance())*(2.-kinkl->GetTPCDensityFactor()))/(sumn+40.); //the longest -clossest will win
6020 TMath::Sort(nkinks,quality,indexes,kFALSE);
6022 //remove double find kinks
6024 for (Int_t ikink0=1;ikink0<nkinks;ikink0++){
6025 AliKink * kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6026 if (!kink0) continue;
6028 for (Int_t ikink1=0;ikink1<ikink0;ikink1++){
6029 kink0 = (AliKink*) kinks->At(indexes[ikink0]);
6030 if (!kink0) continue;
6031 AliKink * kink1 = (AliKink*) kinks->At(indexes[ikink1]);
6032 if (!kink1) continue;
6033 // if not close kink continue
6034 if (TMath::Abs(kink1->GetPosition()[2]-kink0->GetPosition()[2])>10) continue;
6035 if (TMath::Abs(kink1->GetPosition()[1]-kink0->GetPosition()[1])>10) continue;
6036 if (TMath::Abs(kink1->GetPosition()[0]-kink0->GetPosition()[0])>10) continue;
6038 AliTPCseed &mother0 = *mothers[indexes[ikink0]];
6039 AliTPCseed &daughter0 = *daughters[indexes[ikink0]];
6040 AliTPCseed &mother1 = *mothers[indexes[ikink1]];
6041 AliTPCseed &daughter1 = *daughters[indexes[ikink1]];
6042 Int_t row0 = (kink0->GetTPCRow0()+kink1->GetTPCRow0())/2;
6051 for (Int_t i=0;i<row0;i++){
6052 if (mother0.GetClusterIndex(i)>0 && mother1.GetClusterIndex(i)>0){
6055 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6062 for (Int_t i=row0;i<158;i++){
6063 //if (daughter0.GetClusterIndex(i)>0 && daughter0.GetClusterIndex(i)>0){ // RS: Bug?
6064 if (daughter0.GetClusterIndex(i)>0 && daughter1.GetClusterIndex(i)>0){
6067 if (mother0.GetClusterIndex(i)==mother1.GetClusterIndex(i)){
6073 Float_t ratio = Float_t(same+1)/Float_t(both+1);
6074 Float_t ratiom = Float_t(samem+1)/Float_t(bothm+1);
6075 Float_t ratiod = Float_t(samed+1)/Float_t(bothd+1);
6076 if (ratio>0.3 && ratiom>0.5 &&ratiod>0.5) {
6077 Int_t sum0 = mother0.GetNumberOfClusters()+daughter0.GetNumberOfClusters();
6078 Int_t sum1 = mother1.GetNumberOfClusters()+daughter1.GetNumberOfClusters();
6080 shared[kink0->GetIndex(0)]= kTRUE;
6081 shared[kink0->GetIndex(1)]= kTRUE;
6082 delete kinks->RemoveAt(indexes[ikink0]);
6086 shared[kink1->GetIndex(0)]= kTRUE;
6087 shared[kink1->GetIndex(1)]= kTRUE;
6088 delete kinks->RemoveAt(indexes[ikink1]);
6095 for (Int_t i=0;i<nkinks;i++){
6096 AliKink * kinkl = (AliKink*) kinks->At(indexes[i]);
6097 if (!kinkl) continue;
6098 kinkl->SetTPCRow0(GetRowNumber(kinkl->GetR()));
6099 Int_t index0 = kinkl->GetIndex(0);
6100 Int_t index1 = kinkl->GetIndex(1);
6101 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.2)) continue;
6102 kinkl->SetMultiple(usage[index0],0);
6103 kinkl->SetMultiple(usage[index1],1);
6104 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>2) continue;
6105 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && quality[indexes[i]]>0.2) continue;
6106 if (kinkl->GetMultiple()[0]+kinkl->GetMultiple()[1]>0 && kinkl->GetDistance()>0.2) continue;
6107 if (circular[index0]||(circular[index1]&&kinkl->GetDistance()>0.1)) continue;
6109 AliTPCseed * ktrack0 = (AliTPCseed*)array->At(index0);
6110 AliTPCseed * ktrack1 = (AliTPCseed*)array->At(index1);
6111 if (!ktrack0 || !ktrack1) continue;
6112 Int_t index = esd->AddKink(kinkl);
6115 if ( ktrack0->GetKinkIndex(0)==0 && ktrack1->GetKinkIndex(0)==0) { //best kink
6116 if (mothers[indexes[i]]->GetNumberOfClusters()>20 && daughters[indexes[i]]->GetNumberOfClusters()>20 &&
6117 (mothers[indexes[i]]->GetNumberOfClusters()+daughters[indexes[i]]->GetNumberOfClusters())>100){
6118 *ktrack0 = *mothers[indexes[i]];
6119 *ktrack1 = *daughters[indexes[i]];
6123 ktrack0->SetKinkIndex(usage[index0],-(index+1));
6124 ktrack1->SetKinkIndex(usage[index1], (index+1));
6129 // Remove tracks corresponding to shared kink's
6131 for (Int_t i=0;i<nentries;i++){
6132 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6133 if (!track0) continue;
6134 if (track0->GetKinkIndex(0)!=0) continue;
6135 if (shared[i]) MarkSeedFree( array->RemoveAt(i) );
6140 RemoveUsed2(array,0.5,0.4,30);
6142 for (Int_t i=0;i<nentries;i++){
6143 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6144 if (!track0) continue;
6145 track0->CookdEdx(0.02,0.6);
6149 for (Int_t i=0;i<nentries;i++){
6150 AliTPCseed * track0 = (AliTPCseed*)array->At(i);
6151 if (!track0) continue;
6152 if (track0->Pt()<1.4) continue;
6153 //remove double high momenta tracks - overlapped with kink candidates
6156 for (Int_t icl=track0->GetFirstPoint();icl<track0->GetLastPoint(); icl++){
6157 if (track0->GetClusterPointer(icl)!=0){
6159 if (track0->GetClusterPointer(icl)->IsUsed(10)) ishared++;
6162 if (Float_t(ishared+1)/Float_t(all+1)>0.5) {
6163 MarkSeedFree( array->RemoveAt(i) );
6167 if (track0->GetKinkIndex(0)!=0) continue;
6168 if (track0->GetNumberOfClusters()<80) continue;
6170 AliTPCseed *pmother = new( NextFreeSeed() ) AliTPCseed();
6171 pmother->SetPoolID(fLastSeedID);
6172 AliTPCseed *pdaughter = new( NextFreeSeed() ) AliTPCseed();
6173 pdaughter->SetPoolID(fLastSeedID);
6174 AliKink *pkink = new AliKink;
6176 AliTPCseed & mother = *pmother;
6177 AliTPCseed & daughter = *pdaughter;
6178 AliKink & kinkl = *pkink;
6179 if (CheckKinkPoint(track0,mother,daughter, kinkl)){
6180 if (mother.GetNumberOfClusters()<30||daughter.GetNumberOfClusters()<20) {
6181 MarkSeedFree( pmother );
6182 MarkSeedFree( pdaughter );
6184 continue; //too short tracks
6186 if (mother.Pt()<1.4) {
6187 MarkSeedFree( pmother );
6188 MarkSeedFree( pdaughter );
6192 Int_t row0= kinkl.GetTPCRow0();
6193 if (kinkl.GetDistance()>0.5 || kinkl.GetR()<110. || kinkl.GetR()>240.) {
6194 MarkSeedFree( pmother );
6195 MarkSeedFree( pdaughter );
6200 Int_t index = esd->AddKink(&kinkl);
6201 mother.SetKinkIndex(0,-(index+1));
6202 daughter.SetKinkIndex(0,index+1);
6203 if (mother.GetNumberOfClusters()>50) {
6204 MarkSeedFree( array->RemoveAt(i) );
6205 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6206 mtc->SetPoolID(fLastSeedID);
6207 array->AddAt(mtc,i);
6210 AliTPCseed* mtc = new( NextFreeSeed() ) AliTPCseed(mother);
6211 mtc->SetPoolID(fLastSeedID);
6212 array->AddLast(mtc);
6214 AliTPCseed* dtc = new( NextFreeSeed() ) AliTPCseed(daughter);
6215 dtc->SetPoolID(fLastSeedID);
6216 array->AddLast(dtc);
6217 for (Int_t icl=0;icl<row0;icl++) {
6218 if (mother.GetClusterPointer(icl)) mother.GetClusterPointer(icl)->Use(20);
6221 for (Int_t icl=row0;icl<158;icl++) {
6222 if (daughter.GetClusterPointer(icl)) daughter.GetClusterPointer(icl)->Use(20);
6226 MarkSeedFree( pmother );
6227 MarkSeedFree( pdaughter );
6231 delete [] daughters;
6253 AliInfo(Form("Ncandidates=\t%d\t%d\t%d\t%d\n",esd->GetNumberOfKinks(),ncandidates,ntracks,nall));
6258 Int_t AliTPCtrackerMI::RefitKink(AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6261 // refit kink towards to the vertex
6264 AliKink &kink=(AliKink &)knk;
6266 Int_t row0 = GetRowNumber(kink.GetR());
6267 FollowProlongation(mother,0);
6268 mother.Reset(kFALSE);
6270 FollowProlongation(daughter,row0);
6271 daughter.Reset(kFALSE);
6272 FollowBackProlongation(daughter,158);
6273 daughter.Reset(kFALSE);
6274 Int_t first = TMath::Max(row0-20,30);
6275 Int_t last = TMath::Min(row0+20,140);
6277 const Int_t kNdiv =5;
6278 AliTPCseed param0[kNdiv]; // parameters along the track
6279 AliTPCseed param1[kNdiv]; // parameters along the track
6280 AliKink kinks[kNdiv]; // corresponding kink parameters
6283 for (Int_t irow=0; irow<kNdiv;irow++){
6284 rows[irow] = first +((last-first)*irow)/(kNdiv-1);
6286 // store parameters along the track
6288 for (Int_t irow=0;irow<kNdiv;irow++){
6289 FollowBackProlongation(mother, rows[irow]);
6290 FollowProlongation(daughter,rows[kNdiv-1-irow]);
6291 param0[irow] = mother;
6292 param1[kNdiv-1-irow] = daughter;
6296 for (Int_t irow=0; irow<kNdiv-1;irow++){
6297 if (param0[irow].GetNumberOfClusters()<kNdiv||param1[irow].GetNumberOfClusters()<kNdiv) continue;
6298 kinks[irow].SetMother(param0[irow]);
6299 kinks[irow].SetDaughter(param1[irow]);
6300 kinks[irow].Update();
6303 // choose kink with best "quality"
6305 Double_t mindist = 10000;
6306 for (Int_t irow=0;irow<kNdiv;irow++){
6307 if (param0[irow].GetNumberOfClusters()<20||param1[irow].GetNumberOfClusters()<20) continue;
6308 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6309 if (TMath::Abs(kinks[irow].GetR())<100.) continue;
6311 Float_t normdist = TMath::Abs(param0[irow].GetX()-kinks[irow].GetR())*(0.1+kink.GetDistance());
6312 normdist/= (param0[irow].GetNumberOfClusters()+param1[irow].GetNumberOfClusters()+40.);
6313 if (normdist < mindist){
6319 if (index==-1) return 0;
6322 param0[index].Reset(kTRUE);
6323 FollowProlongation(param0[index],0);
6325 mother = param0[index];
6326 daughter = param1[index]; // daughter in vertex
6328 kink.SetMother(mother);
6329 kink.SetDaughter(daughter);
6331 kink.SetTPCRow0(GetRowNumber(kink.GetR()));
6332 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6333 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6334 kink.SetLabel(CookLabel(&mother,0.4, 0,kink.GetTPCRow0()),0);
6335 kink.SetLabel(CookLabel(&daughter,0.4, kink.GetTPCRow0(),160),1);
6336 mother.SetLabel(kink.GetLabel(0));
6337 daughter.SetLabel(kink.GetLabel(1));
6343 void AliTPCtrackerMI::UpdateKinkQualityM(AliTPCseed * seed){
6345 // update Kink quality information for mother after back propagation
6347 if (seed->GetKinkIndex(0)>=0) return;
6348 for (Int_t ikink=0;ikink<3;ikink++){
6349 Int_t index = seed->GetKinkIndex(ikink);
6350 if (index>=0) break;
6351 index = TMath::Abs(index)-1;
6352 AliESDkink * kink = fEvent->GetKink(index);
6353 kink->SetTPCDensity(-1,0,0);
6354 kink->SetTPCDensity(1,0,1);
6356 Int_t row0 = kink->GetTPCRow0() - 2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6357 if (row0<15) row0=15;
6359 Int_t row1 = kink->GetTPCRow0() + 2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6360 if (row1>145) row1=145;
6362 Int_t found,foundable,shared;
6363 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6364 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,0);
6365 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6366 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),0,1);
6371 void AliTPCtrackerMI::UpdateKinkQualityD(AliTPCseed * seed){
6373 // update Kink quality information for daughter after refit
6375 if (seed->GetKinkIndex(0)<=0) return;
6376 for (Int_t ikink=0;ikink<3;ikink++){
6377 Int_t index = seed->GetKinkIndex(ikink);
6378 if (index<=0) break;
6379 index = TMath::Abs(index)-1;
6380 AliESDkink * kink = fEvent->GetKink(index);
6381 kink->SetTPCDensity(-1,1,0);
6382 kink->SetTPCDensity(-1,1,1);
6384 Int_t row0 = kink->GetTPCRow0() -2 - Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6385 if (row0<15) row0=15;
6387 Int_t row1 = kink->GetTPCRow0() +2 + Int_t( 0.5/ (0.05+kink->GetAngle(2)));
6388 if (row1>145) row1=145;
6390 Int_t found,foundable,shared;
6391 seed->GetClusterStatistic(0,row0, found, foundable,shared,kFALSE);
6392 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,0);
6393 seed->GetClusterStatistic(row1,155, found, foundable,shared,kFALSE);
6394 if (foundable>5) kink->SetTPCDensity(Float_t(found)/Float_t(foundable),1,1);
6400 Int_t AliTPCtrackerMI::CheckKinkPoint(AliTPCseed*seed,AliTPCseed &mother, AliTPCseed &daughter, const AliESDkink &knk)
6403 // check kink point for given track
6404 // if return value=0 kink point not found
6405 // otherwise seed0 correspond to mother particle
6406 // seed1 correspond to daughter particle
6407 // kink parameter of kink point
6408 AliKink &kink=(AliKink &)knk;
6410 Int_t middlerow = (seed->GetFirstPoint()+seed->GetLastPoint())/2;
6411 Int_t first = seed->GetFirstPoint();
6412 Int_t last = seed->GetLastPoint();
6413 if (last-first<20) return 0; // shortest length - 2*30 = 60 pad-rows
6416 AliTPCseed *seed1 = ReSeed(seed,middlerow+20, kTRUE); //middle of chamber
6417 if (!seed1) return 0;
6418 FollowProlongation(*seed1,seed->GetLastPoint()-20);
6419 seed1->Reset(kTRUE);
6420 FollowProlongation(*seed1,158);
6421 seed1->Reset(kTRUE);
6422 last = seed1->GetLastPoint();
6424 AliTPCseed *seed0 = new( NextFreeSeed() ) AliTPCseed(*seed);
6425 seed0->SetPoolID(fLastSeedID);
6426 seed0->Reset(kFALSE);
6429 AliTPCseed param0[20]; // parameters along the track
6430 AliTPCseed param1[20]; // parameters along the track
6431 AliKink kinks[20]; // corresponding kink parameters
6433 for (Int_t irow=0; irow<20;irow++){
6434 rows[irow] = first +((last-first)*irow)/19;
6436 // store parameters along the track
6438 for (Int_t irow=0;irow<20;irow++){
6439 FollowBackProlongation(*seed0, rows[irow]);
6440 FollowProlongation(*seed1,rows[19-irow]);
6441 param0[irow] = *seed0;
6442 param1[19-irow] = *seed1;
6446 for (Int_t irow=0; irow<19;irow++){
6447 kinks[irow].SetMother(param0[irow]);
6448 kinks[irow].SetDaughter(param1[irow]);
6449 kinks[irow].Update();
6452 // choose kink with biggest change of angle
6454 Double_t maxchange= 0;
6455 for (Int_t irow=1;irow<19;irow++){
6456 if (TMath::Abs(kinks[irow].GetR())>240.) continue;
6457 if (TMath::Abs(kinks[irow].GetR())<110.) continue;
6458 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6459 if ( quality > maxchange){
6460 maxchange = quality;
6465 MarkSeedFree( seed0 );
6466 MarkSeedFree( seed1 );
6467 if (index<0) return 0;
6469 Int_t row0 = GetRowNumber(kinks[index].GetR()); //row 0 estimate
6470 seed0 = new( NextFreeSeed() ) AliTPCseed(param0[index]);
6471 seed0->SetPoolID(fLastSeedID);
6472 seed1 = new( NextFreeSeed() ) AliTPCseed(param1[index]);
6473 seed1->SetPoolID(fLastSeedID);
6474 seed0->Reset(kFALSE);
6475 seed1->Reset(kFALSE);
6476 seed0->ResetCovariance(10.);
6477 seed1->ResetCovariance(10.);
6478 FollowProlongation(*seed0,0);
6479 FollowBackProlongation(*seed1,158);
6480 mother = *seed0; // backup mother at position 0
6481 seed0->Reset(kFALSE);
6482 seed1->Reset(kFALSE);
6483 seed0->ResetCovariance(10.);
6484 seed1->ResetCovariance(10.);
6486 first = TMath::Max(row0-20,0);
6487 last = TMath::Min(row0+20,158);
6489 for (Int_t irow=0; irow<20;irow++){
6490 rows[irow] = first +((last-first)*irow)/19;
6492 // store parameters along the track
6494 for (Int_t irow=0;irow<20;irow++){
6495 FollowBackProlongation(*seed0, rows[irow]);
6496 FollowProlongation(*seed1,rows[19-irow]);
6497 param0[irow] = *seed0;
6498 param1[19-irow] = *seed1;
6502 for (Int_t irow=0; irow<19;irow++){
6503 kinks[irow].SetMother(param0[irow]);
6504 kinks[irow].SetDaughter(param1[irow]);
6505 // param0[irow].Dump();
6506 //param1[irow].Dump();
6507 kinks[irow].Update();
6510 // choose kink with biggest change of angle
6513 for (Int_t irow=0;irow<20;irow++){
6514 if (TMath::Abs(kinks[irow].GetR())>250.) continue;
6515 if (TMath::Abs(kinks[irow].GetR())<90.) continue;
6516 Float_t quality = TMath::Abs(kinks[irow].GetAngle(2))/(3.+TMath::Abs(kinks[irow].GetR()-param0[irow].GetX()));
6517 if ( quality > maxchange){
6518 maxchange = quality;
6525 if (index==-1 || param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()<100){
6526 MarkSeedFree( seed0 );
6527 MarkSeedFree( seed1 );
6531 // Float_t anglesigma = TMath::Sqrt(param0[index].fC22+param0[index].fC33+param1[index].fC22+param1[index].fC33);
6533 kink.SetMother(param0[index]);
6534 kink.SetDaughter(param1[index]);
6537 Double_t chi2P2 = param0[index].GetParameter()[2]-param1[index].GetParameter()[2];
6539 chi2P2/=param0[index].GetCovariance()[5]+param1[index].GetCovariance()[5];
6540 Double_t chi2P3 = param0[index].GetParameter()[3]-param1[index].GetParameter()[3];
6542 chi2P3/=param0[index].GetCovariance()[9]+param1[index].GetCovariance()[9];
6544 if (AliTPCReconstructor::StreamLevel()>1) {
6545 (*fDebugStreamer)<<"kinkHpt"<<
6548 "p0.="<<¶m0[index]<<
6549 "p1.="<<¶m1[index]<<
6553 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(0)){
6554 MarkSeedFree( seed0 );
6555 MarkSeedFree( seed1 );
6560 row0 = GetRowNumber(kink.GetR());
6561 kink.SetTPCRow0(row0);
6562 kink.SetLabel(CookLabel(seed0,0.5,0,row0),0);
6563 kink.SetLabel(CookLabel(seed1,0.5,row0,158),1);
6564 kink.SetIndex(-10,0);
6565 kink.SetIndex(int(param0[index].GetNumberOfClusters()+param1[index].GetNumberOfClusters()),1);
6566 kink.SetTPCncls(param0[index].GetNumberOfClusters(),0);
6567 kink.SetTPCncls(param1[index].GetNumberOfClusters(),1);
6570 // new (&mother) AliTPCseed(param0[index]);
6571 daughter = param1[index];
6572 daughter.SetLabel(kink.GetLabel(1));
6573 param0[index].Reset(kTRUE);
6574 FollowProlongation(param0[index],0);
6575 mother = param0[index];
6576 mother.SetLabel(kink.GetLabel(0));
6577 if ( chi2P2+chi2P3<AliTPCReconstructor::GetRecoParam()->GetKinkAngleCutChi2(1)){
6580 MarkSeedFree( seed0 );
6581 MarkSeedFree( seed1 );
6589 AliTPCseed* AliTPCtrackerMI::ReSeed(AliTPCseed *t)
6592 // reseed - refit - track
6595 // Int_t last = fSectors->GetNRows()-1;
6597 if (fSectors == fOuterSec){
6598 first = TMath::Max(first, t->GetFirstPoint()-fInnerSec->GetNRows());
6602 first = t->GetFirstPoint();
6604 AliTPCseed * seed = MakeSeed(t,0.1,0.5,0.9);
6605 FollowBackProlongation(*t,fSectors->GetNRows()-1);
6607 FollowProlongation(*t,first);
6617 //_____________________________________________________________________________
6618 Int_t AliTPCtrackerMI::ReadSeeds(const TFile *inp) {
6619 //-----------------------------------------------------------------
6620 // This function reades track seeds.
6621 //-----------------------------------------------------------------
6622 TDirectory *savedir=gDirectory;
6624 TFile *in=(TFile*)inp;
6625 if (!in->IsOpen()) {
6626 cerr<<"AliTPCtrackerMI::ReadSeeds(): input file is not open !\n";
6631 TTree *seedTree=(TTree*)in->Get("Seeds");
6633 cerr<<"AliTPCtrackerMI::ReadSeeds(): ";
6634 cerr<<"can't get a tree with track seeds !\n";
6637 AliTPCtrack *seed=new AliTPCtrack;
6638 seedTree->SetBranchAddress("tracks",&seed);
6640 if (fSeeds==0) fSeeds=new TObjArray(15000);
6642 Int_t n=(Int_t)seedTree->GetEntries();
6643 for (Int_t i=0; i<n; i++) {
6644 seedTree->GetEvent(i);
6645 AliTPCseed* sdc = new( NextFreeSeed() ) AliTPCseed(*seed/*,seed->GetAlpha()*/);
6646 sdc->SetPoolID(fLastSeedID);
6647 fSeeds->AddLast(sdc);
6650 delete seed; // RS: this seed is not from the pool, delete it !!!
6656 Int_t AliTPCtrackerMI::Clusters2TracksHLT (AliESDEvent *const esd, const AliESDEvent *hltEvent)
6659 // clusters to tracks
6660 if (fSeeds) DeleteSeeds();
6661 else ResetSeedsPool();
6663 fEventHLT = hltEvent;
6665 AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
6666 transform->SetCurrentTimeStamp( esd->GetTimeStamp());
6667 transform->SetCurrentRun(esd->GetRunNumber());
6671 if (!fSeeds) return 1;
6673 if (AliTPCReconstructor::StreamLevel()>3) DumpClusters(0,fSeeds);
6678 Int_t AliTPCtrackerMI::Clusters2Tracks(AliESDEvent *const esd)
6681 // clusters to tracks
6682 return Clusters2TracksHLT( esd, 0);
6685 //_____________________________________________________________________________
6686 Int_t AliTPCtrackerMI::Clusters2Tracks() {
6687 //-----------------------------------------------------------------
6688 // This is a track finder.
6689 //-----------------------------------------------------------------
6690 TDirectory *savedir=gDirectory;
6694 fSeeds = Tracking();
6697 Info("Clusters2Tracks","Time for tracking: \t");timer.Print();timer.Start();
6699 //activate again some tracks
6700 for (Int_t i=0; i<fSeeds->GetEntriesFast(); i++) {
6701 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6703 Int_t nc=t.GetNumberOfClusters();
6705 MarkSeedFree( fSeeds->RemoveAt(i) );
6709 if (pt->GetRemoval()==10) {
6710 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
6711 pt->Desactivate(10); // make track again active // MvL: should be 0 ?
6713 pt->Desactivate(20);
6714 MarkSeedFree( fSeeds->RemoveAt(i) );
6719 RemoveUsed2(fSeeds,0.85,0.85,0);
6720 if (AliTPCReconstructor::GetRecoParam()->GetDoKinks()) FindKinks(fSeeds,fEvent);
6721 //FindCurling(fSeeds, fEvent,0);
6722 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,-1); // find multi found tracks
6723 RemoveUsed2(fSeeds,0.5,0.4,20);
6724 FindSplitted(fSeeds, fEvent,0); // find multi found tracks
6725 if (AliTPCReconstructor::StreamLevel()>5) FindMultiMC(fSeeds, fEvent,0); // find multi found tracks
6728 // // refit short tracks
6730 Int_t nseed=fSeeds->GetEntriesFast();
6733 for (Int_t i=0; i<nseed; i++) {
6734 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6736 Int_t nc=t.GetNumberOfClusters();
6738 MarkSeedFree( fSeeds->RemoveAt(i) );
6741 CookLabel(pt,0.1); //For comparison only
6742 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
6743 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
6745 if (fDebug>0) cerr<<found<<'\r';
6749 MarkSeedFree( fSeeds->RemoveAt(i) );
6753 //RemoveOverlap(fSeeds,0.99,7,kTRUE);
6755 //RemoveUsed(fSeeds,0.9,0.9,6);
6757 nseed=fSeeds->GetEntriesFast();
6759 for (Int_t i=0; i<nseed; i++) {
6760 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6762 Int_t nc=t.GetNumberOfClusters();
6764 MarkSeedFree( fSeeds->RemoveAt(i) );
6768 t.CookdEdx(0.02,0.6);
6769 // CheckKinkPoint(&t,0.05);
6770 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
6771 if ((pt->IsActive() || (pt->GetRemoval()==10) )){
6779 MarkSeedFree( fSeeds->RemoveAt(i) );
6780 //AliTPCseed * seed1 = ReSeed(pt,0.05,0.5,1);
6782 // FollowProlongation(*seed1,0);
6783 // Int_t n = seed1->GetNumberOfClusters();
6784 // printf("fP4\t%f\t%f\n",seed1->GetC(),pt->GetC());
6785 // printf("fN\t%d\t%d\n", seed1->GetNumberOfClusters(),pt->GetNumberOfClusters());
6788 //AliTPCseed * seed2 = ReSeed(pt,0.95,0.5,0.05);
6792 SortTracks(fSeeds, 1);
6796 PrepareForBackProlongation(fSeeds,5.);
6797 PropagateBack(fSeeds);
6798 printf("Time for back propagation: \t");timer.Print();timer.Start();
6802 PrepareForProlongation(fSeeds,5.);
6803 PropagateForard2(fSeeds);
6805 printf("Time for FORWARD propagation: \t");timer.Print();timer.Start();
6806 // RemoveUsed(fSeeds,0.7,0.7,6);
6807 //RemoveOverlap(fSeeds,0.9,7,kTRUE);
6809 nseed=fSeeds->GetEntriesFast();
6811 for (Int_t i=0; i<nseed; i++) {
6812 AliTPCseed *pt=(AliTPCseed*)fSeeds->UncheckedAt(i), &t=*pt;
6814 Int_t nc=t.GetNumberOfClusters();
6816 MarkSeedFree( fSeeds->RemoveAt(i) );
6819 t.CookdEdx(0.02,0.6);
6820 // CookLabel(pt,0.1); //For comparison only
6821 //if ((pt->IsActive() || (pt->fRemoval==10) )&& nc>50 &&pt->GetNumberOfClusters()>0.4*pt->fNFoundable){
6822 if ((pt->IsActive() || (pt->fRemoval==10) )){
6823 cerr<<found++<<'\r';
6826 MarkSeedFree( fSeeds->RemoveAt(i) );
6831 // fNTracks = found;
6833 Info("Clusters2Tracks","Time for overlap removal, track writing and dedx cooking: \t"); timer.Print();timer.Start();
6836 // cerr<<"Number of found tracks : "<<"\t"<<found<<endl;
6837 Info("Clusters2Tracks","Number of found tracks %d",found);
6839 // UnloadClusters();
6844 void AliTPCtrackerMI::Tracking(TObjArray * arr)
6847 // tracking of the seeds
6850 fSectors = fOuterSec;
6851 ParallelTracking(arr,150,63);
6852 fSectors = fOuterSec;
6853 ParallelTracking(arr,63,0);
6856 TObjArray * AliTPCtrackerMI::Tracking(Int_t seedtype, Int_t i1, Int_t i2, Float_t cuts[4], Float_t dy, Int_t dsec)
6861 static TObjArray arrTracks;
6862 TObjArray * arr = &arrTracks;
6864 fSectors = fOuterSec;
6867 for (Int_t sec=0;sec<fkNOS;sec++){
6868 if (seedtype==3) MakeSeeds3(arr,sec,i1,i2,cuts,dy, dsec);
6869 if (seedtype==4) MakeSeeds5(arr,sec,i1,i2,cuts,dy);
6870 if (seedtype==2) MakeSeeds2(arr,sec,i1,i2,cuts,dy);
6873 Info("Tracking","\nSeeding - %d\t%d\t%d\t%d\n",seedtype,i1,i2,arr->GetEntriesFast());
6885 TObjArray * AliTPCtrackerMI::Tracking()
6889 if (AliTPCReconstructor::GetRecoParam()->GetSpecialSeeding()) return TrackingSpecial();
6892 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
6894 TObjArray * seeds = new TObjArray;
6896 Int_t fLastSeedRowSec=AliTPCReconstructor::GetRecoParam()->GetLastSeedRowSec();
6897 Int_t gapPrim = AliTPCReconstructor::GetRecoParam()->GetSeedGapPrim();
6898 Int_t gapSec = AliTPCReconstructor::GetRecoParam()->GetSeedGapSec();
6906 Float_t fnumber = 3.0;
6907 Float_t fdensity = 3.0;
6911 arr = MakeSeedsHLT( fEventHLT );
6913 SumTracks(seeds,arr);
6916 //cout<<"HLT tracks left after sorting: "<<seeds->GetEntriesFast()<<endl;
6917 //SignClusters(seeds,fnumber,fdensity);
6924 for (Int_t delta = 0; delta<18; delta+=gapPrim){
6928 arr = Tracking(3,nup-1-delta,nup-1-delta-gap,cuts,-1,1);
6929 SumTracks(seeds,arr);
6930 SignClusters(seeds,fnumber,fdensity);
6932 for (Int_t i=2;i<6;i+=2){
6933 // seed high pt tracks
6936 arr = Tracking(3,nup-i-delta,nup-i-delta-gap,cuts,-1,0);
6937 SumTracks(seeds,arr);
6938 SignClusters(seeds,fnumber,fdensity);
6943 // RemoveUsed(seeds,0.9,0.9,1);
6944 // UnsignClusters();
6945 // SignClusters(seeds,fnumber,fdensity);
6949 for (Int_t delta = 20; delta<120; delta+=gapPrim){
6951 // seed high pt tracks
6955 arr = Tracking(3,nup-delta,nup-delta-gap,cuts,-1);
6956 SumTracks(seeds,arr);
6957 SignClusters(seeds,fnumber,fdensity);
6962 arr = Tracking(3,nup-delta-5,nup-delta-5-gap,cuts,-1);
6963 SumTracks(seeds,arr);
6964 SignClusters(seeds,fnumber,fdensity);
6975 Info("Tracking()","\n\nPrimary seeding\t%d\n\n",seeds->GetEntriesFast());
6979 // RemoveUsed(seeds,0.75,0.75,1);
6981 //SignClusters(seeds,fnumber,fdensity);
6990 arr = Tracking(4,nup-1,nup-1-gap,cuts,-1);
6991 SumTracks(seeds,arr);
6992 SignClusters(seeds,fnumber,fdensity);
6994 arr = Tracking(4,nup-2,nup-2-gap,cuts,-1);
6995 SumTracks(seeds,arr);
6996 SignClusters(seeds,fnumber,fdensity);
6998 arr = Tracking(4,nup-3,nup-3-gap,cuts,-1);
6999 SumTracks(seeds,arr);
7000 SignClusters(seeds,fnumber,fdensity);
7002 arr = Tracking(4,nup-5,nup-5-gap,cuts,-1);
7003 SumTracks(seeds,arr);
7004 SignClusters(seeds,fnumber,fdensity);
7006 arr = Tracking(4,nup-7,nup-7-gap,cuts,-1);
7007 SumTracks(seeds,arr);
7008 SignClusters(seeds,fnumber,fdensity);
7011 arr = Tracking(4,nup-9,nup-9-gap,cuts,-1);
7012 SumTracks(seeds,arr);
7013 SignClusters(seeds,fnumber,fdensity);
7017 for (Int_t delta = 9; delta<30; delta+=gapSec){
7023 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7024 SumTracks(seeds,arr);
7025 SignClusters(seeds,fnumber,fdensity);
7027 arr = Tracking(4,nup-3-delta,nup-5-delta-gap,cuts,4);
7028 SumTracks(seeds,arr);
7029 SignClusters(seeds,fnumber,fdensity);
7042 for (Int_t delta = 30; delta<fLastSeedRowSec; delta+=gapSec){
7048 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7049 SumTracks(seeds,arr);
7050 SignClusters(seeds,fnumber,fdensity);
7052 arr = Tracking(4,nup-5-delta,nup-5-delta-gap,cuts,5 );
7053 SumTracks(seeds,arr);
7054 SignClusters(seeds,fnumber,fdensity);
7058 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7069 TObjArray * AliTPCtrackerMI::TrackingSpecial()
7072 // seeding adjusted for laser and cosmic tests - short tracks with big inclination angle
7073 // no primary vertex seeding tried
7077 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7079 TObjArray * seeds = new TObjArray;
7084 Float_t fnumber = 3.0;
7085 Float_t fdensity = 3.0;
7088 cuts[0] = AliTPCReconstructor::GetRecoParam()->GetMaxC(); // max curvature
7089 cuts[1] = 3.5; // max tan(phi) angle for seeding
7090 cuts[2] = 3.; // not used (cut on z primary vertex)
7091 cuts[3] = 3.5; // max tan(theta) angle for seeding
7093 for (Int_t delta = 0; nup-delta-gap-1>0; delta+=3){
7095 arr = Tracking(4,nup-1-delta,nup-1-delta-gap,cuts,-1);
7096 SumTracks(seeds,arr);
7097 SignClusters(seeds,fnumber,fdensity);
7101 Info("Tracking()","\n\nSecondary seeding\t%d\n\n",seeds->GetEntriesFast());
7112 void AliTPCtrackerMI::SumTracks(TObjArray *arr1,TObjArray *&arr2)
7115 //sum tracks to common container
7116 //remove suspicious tracks
7117 // RS: Attention: supplied tracks come in the static array, don't delete them
7118 Int_t nseed = arr2->GetEntriesFast();
7119 for (Int_t i=0;i<nseed;i++){
7120 AliTPCseed *pt=(AliTPCseed*)arr2->UncheckedAt(i);
7123 // remove tracks with too big curvature
7125 if (TMath::Abs(pt->GetC())>AliTPCReconstructor::GetRecoParam()->GetMaxC()){
7126 MarkSeedFree( arr2->RemoveAt(i) );
7129 // REMOVE VERY SHORT TRACKS
7130 if (pt->GetNumberOfClusters()<20){
7131 MarkSeedFree( arr2->RemoveAt(i) );
7134 // NORMAL ACTIVE TRACK
7135 if (pt->IsActive()){
7136 arr1->AddLast(arr2->RemoveAt(i));
7139 //remove not usable tracks
7140 if (pt->GetRemoval()!=10){
7141 MarkSeedFree( arr2->RemoveAt(i) );
7145 // ENABLE ONLY ENOUGH GOOD STOPPED TRACKS
7146 if (pt->GetDensityFirst(20)>0.8 || pt->GetDensityFirst(30)>0.8 || pt->GetDensityFirst(40)>0.7)
7147 arr1->AddLast(arr2->RemoveAt(i));
7149 MarkSeedFree( arr2->RemoveAt(i) );
7153 // delete arr2; arr2 = 0; // RS: this is static array, don't delete it
7158 void AliTPCtrackerMI::ParallelTracking(TObjArray *const arr, Int_t rfirst, Int_t rlast)
7161 // try to track in parralel
7163 Int_t nseed=arr->GetEntriesFast();
7164 //prepare seeds for tracking
7165 for (Int_t i=0; i<nseed; i++) {
7166 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7168 if (!t.IsActive()) continue;
7169 // follow prolongation to the first layer
7170 if ( (fSectors ==fInnerSec) || (t.GetFirstPoint()-fkParam->GetNRowLow()>rfirst+1) )
7171 FollowProlongation(t, rfirst+1);
7176 for (Int_t nr=rfirst; nr>=rlast; nr--){
7177 if (nr<fInnerSec->GetNRows())
7178 fSectors = fInnerSec;
7180 fSectors = fOuterSec;
7181 // make indexes with the cluster tracks for given
7183 // find nearest cluster
7184 for (Int_t i=0; i<nseed; i++) {
7185 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i), &t=*pt;
7187 if (nr==80) pt->UpdateReference();
7188 if (!pt->IsActive()) continue;
7189 // if ( (fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7190 if (pt->GetRelativeSector()>17) {
7193 UpdateClusters(t,nr);
7195 // prolonagate to the nearest cluster - if founded
7196 for (Int_t i=0; i<nseed; i++) {
7197 AliTPCseed *pt=(AliTPCseed*)arr->UncheckedAt(i);
7199 if (!pt->IsActive()) continue;
7200 // if ((fSectors ==fOuterSec) && (pt->fFirstPoint-fkParam->GetNRowLow())<nr) continue;
7201 if (pt->GetRelativeSector()>17) {
7204 FollowToNextCluster(*pt,nr);
7209 void AliTPCtrackerMI::PrepareForBackProlongation(const TObjArray *const arr,Float_t fac) const
7213 // if we use TPC track itself we have to "update" covariance
7215 Int_t nseed= arr->GetEntriesFast();
7216 for (Int_t i=0;i<nseed;i++){
7217 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7221 //rotate to current local system at first accepted point
7222 Int_t index = pt->GetClusterIndex2(pt->GetFirstPoint());
7223 Int_t sec = (index&0xff000000)>>24;
7225 Float_t angle1 = fInnerSec->GetAlpha()*sec+fInnerSec->GetAlphaShift();
7226 if (angle1>TMath::Pi())
7227 angle1-=2.*TMath::Pi();
7228 Float_t angle2 = pt->GetAlpha();
7230 if (TMath::Abs(angle1-angle2)>0.001){
7231 if (!pt->Rotate(angle1-angle2)) return;
7232 //angle2 = pt->GetAlpha();
7233 //pt->fRelativeSector = pt->GetAlpha()/fInnerSec->GetAlpha();
7234 //if (pt->GetAlpha()<0)
7235 // pt->fRelativeSector+=18;
7236 //sec = pt->fRelativeSector;
7245 void AliTPCtrackerMI::PrepareForProlongation(TObjArray *const arr, Float_t fac) const
7249 // if we use TPC track itself we have to "update" covariance
7251 Int_t nseed= arr->GetEntriesFast();
7252 for (Int_t i=0;i<nseed;i++){
7253 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7256 pt->SetFirstPoint(pt->GetLastPoint());
7264 Int_t AliTPCtrackerMI::PropagateBack(const TObjArray *const arr)
7267 // make back propagation
7269 Int_t nseed= arr->GetEntriesFast();
7270 for (Int_t i=0;i<nseed;i++){
7271 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7272 if (pt&& pt->GetKinkIndex(0)<=0) {
7273 //AliTPCseed *pt2 = new AliTPCseed(*pt);
7274 fSectors = fInnerSec;
7275 //FollowBackProlongation(*pt,fInnerSec->GetNRows()-1);
7276 //fSectors = fOuterSec;
7277 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7278 //if (pt->GetNumberOfClusters()<(pt->fEsd->GetTPCclusters(0)) ){
7279 // Error("PropagateBack","Not prolonged track %d",pt->GetLabel());
7280 // FollowBackProlongation(*pt2,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1);
7283 if (pt&& pt->GetKinkIndex(0)>0) {
7284 AliESDkink * kink = fEvent->GetKink(pt->GetKinkIndex(0)-1);
7285 pt->SetFirstPoint(kink->GetTPCRow0());
7286 fSectors = fInnerSec;
7287 FollowBackProlongation(*pt,fInnerSec->GetNRows()+fOuterSec->GetNRows()-1,1);
7295 Int_t AliTPCtrackerMI::PropagateForward2(const TObjArray *const arr)
7298 // make forward propagation
7300 Int_t nseed= arr->GetEntriesFast();
7302 for (Int_t i=0;i<nseed;i++){
7303 AliTPCseed *pt = (AliTPCseed*)arr->UncheckedAt(i);
7305 FollowProlongation(*pt,0,1,1);
7314 Int_t AliTPCtrackerMI::PropagateForward()
7317 // propagate track forward
7319 Int_t nseed = fSeeds->GetEntriesFast();
7320 for (Int_t i=0;i<nseed;i++){
7321 AliTPCseed *pt = (AliTPCseed*)fSeeds->UncheckedAt(i);
7323 AliTPCseed &t = *pt;
7324 Double_t alpha=t.GetAlpha() - fSectors->GetAlphaShift();
7325 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
7326 if (alpha < 0. ) alpha += 2.*TMath::Pi();
7327 t.SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
7331 fSectors = fOuterSec;
7332 ParallelTracking(fSeeds,fOuterSec->GetNRows()+fInnerSec->GetNRows()-1,fInnerSec->GetNRows());
7333 fSectors = fInnerSec;
7334 ParallelTracking(fSeeds,fInnerSec->GetNRows()-1,0);
7343 Int_t AliTPCtrackerMI::PropagateBack(AliTPCseed *const pt, Int_t row0, Int_t row1)
7346 // make back propagation, in between row0 and row1
7350 fSectors = fInnerSec;
7353 if (row1<fSectors->GetNRows())
7356 r1 = fSectors->GetNRows()-1;
7358 if (row0<fSectors->GetNRows()&& r1>0 )
7359 FollowBackProlongation(*pt,r1);
7360 if (row1<=fSectors->GetNRows())
7363 r1 = row1 - fSectors->GetNRows();
7364 if (r1<=0) return 0;
7365 if (r1>=fOuterSec->GetNRows()) return 0;
7366 fSectors = fOuterSec;
7367 return FollowBackProlongation(*pt,r1);
7375 void AliTPCtrackerMI::GetShape(AliTPCseed * seed, Int_t row)
7377 // gets cluster shape
7379 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
7380 Float_t zdrift = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())));
7381 Int_t type = (seed->GetSector() < fkParam->GetNSector()/2) ? 0: (row>126) ? 1:2;
7382 Double_t angulary = seed->GetSnp();
7384 if (TMath::Abs(angulary)>AliTPCReconstructor::GetMaxSnpTracker()) {
7385 angulary = TMath::Sign(AliTPCReconstructor::GetMaxSnpTracker(),angulary);
7388 angulary = angulary*angulary/((1.-angulary)*(1.+angulary));
7389 Double_t angularz = seed->GetTgl()*seed->GetTgl()*(1.+angulary);
7391 Double_t sigmay = clparam->GetRMS0(0,type,zdrift,TMath::Sqrt(TMath::Abs(angulary)));
7392 Double_t sigmaz = clparam->GetRMS0(1,type,zdrift,TMath::Sqrt(TMath::Abs(angularz)));
7393 seed->SetCurrentSigmaY2(sigmay*sigmay);
7394 seed->SetCurrentSigmaZ2(sigmaz*sigmaz);
7395 // Float_t sd2 = TMath::Abs((fkParam->GetZLength(0)-TMath::Abs(seed->GetZ())))*fkParam->GetDiffL()*fkParam->GetDiffL();
7396 // // Float_t padlength = fkParam->GetPadPitchLength(seed->fSector);
7397 // Float_t padlength = GetPadPitchLength(row);
7399 // Float_t sresy = (seed->GetSector() < fkParam->GetNSector()/2) ? 0.2 :0.3;
7400 // seed->SetCurrentSigmaY2(sd2+padlength*padlength*angulary/12.+sresy*sresy);
7402 // Float_t sresz = fkParam->GetZSigma();
7403 // seed->SetCurrentSigmaZ2(sd2+padlength*padlength*angularz*angularz*(1+angulary)/12.+sresz*sresz);
7405 Float_t wy = GetSigmaY(seed);
7406 Float_t wz = GetSigmaZ(seed);
7409 if (TMath::Abs(wy/seed->fCurrentSigmaY2-1)>0.0001 || TMath::Abs(wz/seed->fCurrentSigmaZ2-1)>0.0001 ){
7410 printf("problem\n");
7417 //__________________________________________________________________________
7418 void AliTPCtrackerMI::CookLabel(AliKalmanTrack *tk, Float_t wrong) const {
7419 //--------------------------------------------------------------------
7420 //This function "cooks" a track label. If label<0, this track is fake.
7421 //--------------------------------------------------------------------
7422 AliTPCseed * t = dynamic_cast<AliTPCseed*>(tk);
7424 printf("%s:%d wrong type \n",(char*)__FILE__,__LINE__);
7428 Int_t noc=t->GetNumberOfClusters();
7430 //printf("\nnot founded prolongation\n\n\n");
7436 AliTPCclusterMI *clusters[160];
7438 for (Int_t i=0;i<160;i++) {
7445 for (i=0; i<160 && current<noc; i++) {
7447 Int_t index=t->GetClusterIndex2(i);
7448 if (index<=0) continue;
7449 if (index&0x8000) continue;
7451 //clusters[current]=GetClusterMI(index);
7452 if (t->GetClusterPointer(i)){
7453 clusters[current]=t->GetClusterPointer(i);
7459 Int_t lab=123456789;
7460 for (i=0; i<noc; i++) {
7461 AliTPCclusterMI *c=clusters[i];
7463 lab=TMath::Abs(c->GetLabel(0));
7465 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7471 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7473 for (i=0; i<noc; i++) {
7474 AliTPCclusterMI *c=clusters[i];
7476 if (TMath::Abs(c->GetLabel(1)) == lab ||
7477 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7479 if (noc<=0) { lab=-1; return;}
7480 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7483 Int_t tail=Int_t(0.10*noc);
7486 for (i=1; i<160&&ind<tail; i++) {
7487 // AliTPCclusterMI *c=clusters[noc-i];
7488 AliTPCclusterMI *c=clusters[i];
7490 if (lab == TMath::Abs(c->GetLabel(0)) ||
7491 lab == TMath::Abs(c->GetLabel(1)) ||
7492 lab == TMath::Abs(c->GetLabel(2))) max++;
7495 if (max < Int_t(0.5*tail)) lab=-lab;
7502 //delete[] clusters;
7506 //__________________________________________________________________________
7507 Int_t AliTPCtrackerMI::CookLabel(AliTPCseed *const t, Float_t wrong,Int_t first, Int_t last) const {
7508 //--------------------------------------------------------------------
7509 //This function "cooks" a track label. If label<0, this track is fake.
7510 //--------------------------------------------------------------------
7511 Int_t noc=t->GetNumberOfClusters();
7513 //printf("\nnot founded prolongation\n\n\n");
7519 AliTPCclusterMI *clusters[160];
7521 for (Int_t i=0;i<160;i++) {
7528 for (i=0; i<160 && current<noc; i++) {
7529 if (i<first) continue;
7530 if (i>last) continue;
7531 Int_t index=t->GetClusterIndex2(i);
7532 if (index<=0) continue;
7533 if (index&0x8000) continue;
7535 //clusters[current]=GetClusterMI(index);
7536 if (t->GetClusterPointer(i)){
7537 clusters[current]=t->GetClusterPointer(i);
7542 //if (noc<5) return -1;
7543 Int_t lab=123456789;
7544 for (i=0; i<noc; i++) {
7545 AliTPCclusterMI *c=clusters[i];
7547 lab=TMath::Abs(c->GetLabel(0));
7549 for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
7555 for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
7557 for (i=0; i<noc; i++) {
7558 AliTPCclusterMI *c=clusters[i];
7560 if (TMath::Abs(c->GetLabel(1)) == lab ||
7561 TMath::Abs(c->GetLabel(2)) == lab ) max++;
7563 if (noc<=0) { lab=-1; return -1;}
7564 if ((1.- Float_t(max)/(noc)) > wrong) lab=-lab;
7567 Int_t tail=Int_t(0.10*noc);
7570 for (i=1; i<160&&ind<tail; i++) {
7571 // AliTPCclusterMI *c=clusters[noc-i];
7572 AliTPCclusterMI *c=clusters[i];
7574 if (lab == TMath::Abs(c->GetLabel(0)) ||
7575 lab == TMath::Abs(c->GetLabel(1)) ||
7576 lab == TMath::Abs(c->GetLabel(2))) max++;
7579 if (max < Int_t(0.5*tail)) lab=-lab;
7582 // t->SetLabel(lab);
7586 //delete[] clusters;
7590 Int_t AliTPCtrackerMI::GetRowNumber(Double_t x[3]) const
7592 //return pad row number for given x vector
7593 Float_t phi = TMath::ATan2(x[1],x[0]);
7594 if(phi<0) phi=2.*TMath::Pi()+phi;
7595 // Get the local angle in the sector philoc
7596 const Float_t kRaddeg = 180/3.14159265358979312;
7597 Float_t phiangle = (Int_t (phi*kRaddeg/20.) + 0.5)*20./kRaddeg;
7598 Double_t localx = x[0]*TMath::Cos(phiangle)-x[1]*TMath::Sin(phiangle);
7599 return GetRowNumber(localx);
7604 void AliTPCtrackerMI::MakeESDBitmaps(AliTPCseed *t, AliESDtrack *esd)
7606 //-----------------------------------------------------------------------
7607 // Fill the cluster and sharing bitmaps of the track
7608 //-----------------------------------------------------------------------
7610 Int_t firstpoint = 0;
7611 Int_t lastpoint = 159;
7612 AliTPCTrackerPoint *point;
7613 AliTPCclusterMI *cluster;
7616 TBits clusterMap(159);
7617 TBits sharedMap(159);
7619 for (int iter=firstpoint; iter<lastpoint; iter++) {
7620 // Change to cluster pointers to see if we have a cluster at given padrow
7622 cluster = t->GetClusterPointer(iter);
7624 clusterMap.SetBitNumber(iter, kTRUE);
7625 point = t->GetTrackPoint(iter);
7626 if (point->IsShared())
7627 sharedMap.SetBitNumber(iter,kTRUE);
7629 if (t->GetClusterIndex(iter) >= 0 && (t->GetClusterIndex(iter) & 0x8000) == 0) {
7630 fitMap.SetBitNumber(iter, kTRUE);
7634 esd->SetTPCClusterMap(clusterMap);
7635 esd->SetTPCSharedMap(sharedMap);
7636 esd->SetTPCFitMap(fitMap);
7637 if (nclsf != t->GetNumberOfClusters())
7638 AliWarning(Form("Inconsistency between ncls %d and indices %d (found %d)",t->GetNumberOfClusters(),nclsf,esd->GetTPCClusterMap().CountBits()));
7641 Bool_t AliTPCtrackerMI::IsFindable(AliTPCseed & track){
7643 // return flag if there is findable cluster at given position
7646 Float_t z = track.GetZ();
7648 if (TMath::Abs(z)<(AliTPCReconstructor::GetCtgRange()*track.GetX()+kDeltaZ) &&
7649 TMath::Abs(z)<fkParam->GetZLength(0) &&
7650 (TMath::Abs(track.GetSnp())<AliTPCReconstructor::GetMaxSnpTracker()))
7656 void AliTPCtrackerMI::AddCovariance(AliTPCseed * seed){
7658 // Adding systematic error estimate to the covariance matrix
7659 // !!!! the systematic error for element 4 is in 1/GeV
7660 // 03.03.2012 MI changed in respect to the previous versions
7661 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7663 // use only the diagonal part if not specified otherwise
7664 if (!AliTPCReconstructor::GetRecoParam()->GetUseSystematicCorrelation()) return AddCovarianceAdd(seed);
7666 Double_t *covarS= (Double_t*)seed->GetCovariance();
7667 Double_t factor[5]={1,1,1,1,1};
7668 factor[0]= TMath::Sqrt(TMath::Abs((covarS[0] + param[0]*param[0])/covarS[0]));
7669 factor[1]= TMath::Sqrt(TMath::Abs((covarS[2] + param[1]*param[1])/covarS[2]));
7670 factor[2]= TMath::Sqrt(TMath::Abs((covarS[5] + param[2]*param[2])/covarS[5]));
7671 factor[3]= TMath::Sqrt(TMath::Abs((covarS[9] + param[3]*param[3])/covarS[9]));
7672 factor[4]= TMath::Sqrt(TMath::Abs((covarS[14] +param[4]*param[4])/covarS[14]));
7674 factor[0]=factor[2];
7675 factor[4]=factor[2];
7681 for (Int_t i=0; i<5; i++){
7682 for (Int_t j=i; j<5; j++){
7683 Int_t index=seed->GetIndex(i,j);
7684 covarS[index]*=factor[i]*factor[j];
7690 void AliTPCtrackerMI::AddCovarianceAdd(AliTPCseed * seed){
7692 // Adding systematic error - as additive factor without correlation
7694 // !!!! the systematic error for element 4 is in 1/GeV
7695 // 03.03.2012 MI changed in respect to the previous versions
7697 const Double_t *param = AliTPCReconstructor::GetRecoParam()->GetSystematicError();
7698 Double_t *covarIn= (Double_t*)seed->GetCovariance();
7700 for (Int_t i=0;i<15;i++) covar[i]=0;
7706 covar[0] = param[0]*param[0];
7707 covar[2] = param[1]*param[1];
7708 covar[5] = param[2]*param[2];
7709 covar[9] = param[3]*param[3];
7710 covar[14]= param[4]*param[4];
7712 covar[1]=TMath::Sqrt((covar[0]*covar[2]))*covarIn[1]/TMath::Sqrt((covarIn[0]*covarIn[2]));
7714 covar[3]=TMath::Sqrt((covar[0]*covar[5]))*covarIn[3]/TMath::Sqrt((covarIn[0]*covarIn[5]));
7715 covar[4]=TMath::Sqrt((covar[2]*covar[5]))*covarIn[4]/TMath::Sqrt((covarIn[2]*covarIn[5]));
7717 covar[6]=TMath::Sqrt((covar[0]*covar[9]))*covarIn[6]/TMath::Sqrt((covarIn[0]*covarIn[9]));
7718 covar[7]=TMath::Sqrt((covar[2]*covar[9]))*covarIn[7]/TMath::Sqrt((covarIn[2]*covarIn[9]));
7719 covar[8]=TMath::Sqrt((covar[5]*covar[9]))*covarIn[8]/TMath::Sqrt((covarIn[5]*covarIn[9]));
7721 covar[10]=TMath::Sqrt((covar[0]*covar[14]))*covarIn[10]/TMath::Sqrt((covarIn[0]*covarIn[14]));
7722 covar[11]=TMath::Sqrt((covar[2]*covar[14]))*covarIn[11]/TMath::Sqrt((covarIn[2]*covarIn[14]));
7723 covar[12]=TMath::Sqrt((covar[5]*covar[14]))*covarIn[12]/TMath::Sqrt((covarIn[5]*covarIn[14]));
7724 covar[13]=TMath::Sqrt((covar[9]*covar[14]))*covarIn[13]/TMath::Sqrt((covarIn[9]*covarIn[14]));
7726 seed->AddCovariance(covar);
7729 //_____________________________________________________________________________
7730 Bool_t AliTPCtrackerMI::IsTPCHVDipEvent(AliESDEvent const *esdEvent) {
7732 // check events affected by TPC HV dip
7734 if(!esdEvent) return kFALSE;
7737 if(!AliTPCcalibDB::Instance()) return kFALSE;
7738 AliTPCcalibDB::Instance()->SetRun(esdEvent->GetRunNumber());
7740 // Get HV TPC chamber sensors and calculate the median
7741 AliDCSSensorArray *voltageArray= AliTPCcalibDB::Instance()->GetVoltageSensors(esdEvent->GetRunNumber());
7742 if(!voltageArray) return kFALSE;
7744 TString sensorName="";
7745 Double_t kTPCHVdip = 2.0; // allow for 2V dip as compared to median from given sensor
7748 for(Int_t sector=0; sector<72; sector++)
7750 Char_t sideName='A';
7751 if ((sector/18)%2==1) sideName='C';
7754 sensorName=Form("TPC_ANODE_I_%c%02d_VMEAS",sideName,sector%18);
7757 sensorName=Form("TPC_ANODE_O_%c%02d_0_VMEAS",sideName,sector%18);
7760 AliDCSSensor* sensor = voltageArray->GetSensor(sensorName.Data());
7761 if(!sensor) continue;
7762 TGraph *graph = sensor->GetGraph();
7763 if(!graph) continue;
7764 Double_t median = TMath::Median(graph->GetN(), graph->GetY());
7765 if(median == 0) continue;
7767 //printf("chamber %d, sensor %s, HV %f, median %f\n", sector, sensorName.Data(), sensor->GetValue(esdEvent->GetTimeStamp()), median);
7769 if(TMath::Abs(sensor->GetValue(esdEvent->GetTimeStamp())-median)>kTPCHVdip) {
7777 //________________________________________
7778 void AliTPCtrackerMI::MarkSeedFree(TObject *sd)
7780 // account that this seed is "deleted"
7781 AliTPCseed* seed = dynamic_cast<AliTPCseed*>(sd);
7783 AliError(Form("Freeing of non-AliTPCseed %p from the pool is requested",sd));
7786 int id = seed->GetPoolID();
7788 AliError(Form("Freeing of seed %p NOT from the pool is requested",sd));
7791 // AliInfo(Form("%d %p",id, seed));
7792 fSeedsPool->RemoveAt(id);
7793 if (fFreeSeedsID.GetSize()<=fNFreeSeeds) fFreeSeedsID.Set( 2*fNFreeSeeds + 100 );
7794 fFreeSeedsID.GetArray()[fNFreeSeeds++] = id;
7797 //________________________________________
7798 TObject *&AliTPCtrackerMI::NextFreeSeed()
7800 // return next free slot where the seed can be created
7801 fLastSeedID = fNFreeSeeds ? fFreeSeedsID.GetArray()[--fNFreeSeeds] : fSeedsPool->GetEntriesFast();
7802 // AliInfo(Form("%d",fLastSeedID));
7803 return (*fSeedsPool)[ fLastSeedID ];
7807 //________________________________________
7808 void AliTPCtrackerMI::ResetSeedsPool()
7810 // mark all seeds in the pool as unused
7811 AliInfo(Form("CurrentSize: %d, BookedUpTo: %d, free: %d",fSeedsPool->GetSize(),fSeedsPool->GetEntriesFast(),fNFreeSeeds));
7813 fSeedsPool->Clear("C"); // RS: nominally the seeds may allocate memory...
7816 Int_t AliTPCtrackerMI::PropagateToRowHLT(AliTPCseed *pt, int nrow)
7819 Double_t x= GetXrow(nrow);
7820 Double_t ymax= GetMaxY(nrow);
7826 if (!t.PropagateTo(x) ){
7827 //cout<<"can't propagate to row "<<nrow<<", x="<<t.GetX()<<" -> "<<x<<endl;
7833 Double_t y = t.GetY();
7835 if( rotate!=-1 ) rotate=1;
7836 } else if (y <-ymax) {
7837 if( rotate!=1 ) rotate = -1;
7839 if( rotate==0 ) break;
7840 //cout<<"rotate at row "<<nrow<<": "<<rotate<<endl;
7841 if (!t.Rotate( rotate==1 ?fSectors->GetAlpha() :-fSectors->GetAlpha())) {
7842 //cout<<"can't rotate "<<endl;
7846 nRotations+= rotate;
7848 if( nRotations!=0 ){
7849 int newSec= t.GetRelativeSector()+nRotations;
7850 if( newSec>=fN ) newSec-=fN;
7851 else if( newSec<0 ) newSec +=fN;
7852 //cout<<"rotate at row "<<nrow<<": "<<nRotations<<" times "<<" sec "
7853 //<< t.GetRelativeSector()<<" -> "<<newSec<<endl;
7854 t.SetRelativeSector(newSec);
7859 void AliTPCtrackerMI::TrackFollowingHLT(TObjArray *const arr )
7862 // try to track in parralel
7864 Int_t nRows=fOuterSec->GetNRows()+fInnerSec->GetNRows();
7867 Int_t nseed=arr->GetEntriesFast();
7868 //cout<<"Parallel tracking My.."<<endl;
7869 double shapeY2[160], shapeZ2[160];
7870 Int_t clusterIndex[160];
7872 for (Int_t iSeed=0; iSeed<nseed; iSeed++) {
7873 //if( iSeed!=1 ) continue;
7874 AliTPCseed *pt=(AliTPCseed*) (arr->UncheckedAt(iSeed));
7878 //cout <<"Pt "<<t.GetSigned1Pt()<<endl;
7882 for( int iter=0; iter<3; iter++ ){
7885 t.SetLastPoint(0); // first cluster in track position
7886 t.SetFirstPoint(nRows-1);
7887 t.ResetCovariance(.1);
7888 t.SetNumberOfClusters(0);
7889 for( int i=0; i<nRows; i++ ){
7893 t.SetClusterIndex2(i,-1);
7894 t.SetClusterIndex(i,-1);
7897 // pick up the clusters
7899 Double_t roady = 20.;
7900 Double_t roadz = 20.;
7907 t0.SetRelativeSector(t.GetRelativeSector());
7908 t0.SetLastPoint(0); // first cluster in track position
7909 t0.SetFirstPoint(159);
7910 for (Int_t nr=0; nr<nRows; nr++){
7911 if( nr<fInnerSec->GetNRows() ) fSectors=fInnerSec;
7912 else fSectors=fOuterSec;
7914 if( !PropagateToRowHLT(&t0, nr ) ){ break; }
7915 if (TMath::Abs(t0.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
7916 //cout<<"Snp is too big: "<<t0.GetSnp()<<endl;
7919 if (!IsActive(t0.GetRelativeSector(),nr)) {
7925 shapeY2[nr]=t0.GetCurrentSigmaY2();
7926 shapeZ2[nr]=t0.GetCurrentSigmaZ2();
7929 AliTPCtrackerRow &krow=GetRow(t0.GetRelativeSector(),nr);
7930 if( !krow ) continue;
7932 t.SetClusterIndex2(nr,-3); // foundable
7933 t.SetClusterIndex(nr,-3);
7935 AliTPCclusterMI *cl=0;
7937 cl = krow.FindNearest2(t0.GetY(),t0.GetZ(),roady,roadz,uindex);
7939 double dy = cl->GetY()-t0.GetY();
7940 double dz = cl->GetZ()-t0.GetZ();
7941 double dr = sqrt(dy*dy+dz*dz);
7943 //cout<<"row "<<nr<<", best cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
7946 //cout<<"row "<<nr<<", found cluster r= "<<dr<<" y,z = "<<dy<<" "<<dz<<endl;
7948 t0.SetClusterPointer(nr, cl);
7949 clusterIndex[nr] = krow.GetIndex(uindex);
7950 if( t0.GetFirstPoint()>nr ) t0.SetFirstPoint(nr);
7951 t0.SetLastPoint(nr);
7957 //cout<<"NOT ENOUGTH CLUSTERS: "<<nClusters<<endl;
7960 Int_t basePoints[3] = {t0.GetFirstPoint(),t0.GetFirstPoint(),t0.GetLastPoint()};
7964 Int_t midRow = (t0.GetLastPoint()-t0.GetFirstPoint())/2;
7966 for( int nr=t0.GetFirstPoint()+1; nr< t0.GetLastPoint(); nr++){
7967 if( !t0.GetClusterPointer(nr) ) continue;
7968 int d = TMath::Abs(nr-midRow);
7976 // first fit 3 base points
7978 //cout<<"Fit3: "<<endl;
7979 for( int icl=0; icl<3; icl++){
7980 int nr = basePoints[icl];
7982 if( nr>=fInnerSec->GetNRows()){
7983 lr = nr - fInnerSec->GetNRows();
7985 } else fSectors=fInnerSec;
7987 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
7989 //cout<<"WRONG!!!!"<<endl;
7992 int iSec = cl->GetDetector() %fkNIS;
7993 int rotate = iSec - t.GetRelativeSector();
7995 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
7996 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
7997 //cout<<"can't rotate "<<endl;
8000 t.SetRelativeSector(iSec);
8002 Double_t x= cl->GetX();
8003 if (!t.PropagateTo(x)){
8004 //cout<<"can't propagate to x="<<x<<endl;
8008 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8009 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8012 //cout<<"fit3 : row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8014 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8015 t.SetCurrentCluster(cl);
8018 t.SetErrorY2(shapeY2[nr]);
8019 t.SetErrorZ2(shapeZ2[nr]);
8022 for( int j=0; j<15; j++ ) cov[j]=0;
8028 t.AliExternalTrackParam::AddCovariance(cov);
8030 if( !UpdateTrack(&t,0) ){
8031 //cout<<"Can not update"<<endl;
8033 t.SetClusterIndex2(nr,-1);
8034 t.SetClusterIndex(nr,-1);
8035 t.SetClusterPointer(nr,0);
8038 //t.SetClusterPointer(nr, cl);
8041 //t.SetLastPoint(t0.GetLastPoint());
8042 //t.SetFirstPoint(t0.GetFirstPoint());
8044 //cout<<"Fit: "<<endl;
8045 for (Int_t nr=t0.GetLastPoint(); nr>=t0.GetFirstPoint(); nr-- ){
8047 if( nr>=fInnerSec->GetNRows()){
8048 lr = nr - fInnerSec->GetNRows();
8050 } else fSectors=fInnerSec;
8053 if( nr == basePoints[0] ) continue;
8054 if( nr == basePoints[1] ) continue;
8055 if( nr == basePoints[2] ) continue;
8057 AliTPCclusterMI *cl=t0.GetClusterPointer(nr);
8060 int iSec = cl->GetDetector() %fkNIS;
8061 int rotate = iSec - t.GetRelativeSector();
8063 //cout<<"Rotate at row"<<nr<<" to "<<rotate<<" sectors"<<endl;
8064 if (!t.Rotate( rotate*fSectors->GetAlpha()) ) {
8065 //cout<<"can't rotate "<<endl;
8068 t.SetRelativeSector(iSec);
8070 Double_t x= cl->GetX();
8071 if (!t.PropagateTo(x)){
8072 //cout<<"can't propagate to x="<<x<<endl;
8075 if (TMath::Abs(t.GetSnp())>AliTPCReconstructor::GetMaxSnpTracker()){
8076 //cout<<"Snp is too big: "<<t.GetSnp()<<endl;
8080 //cout<<"fit: row "<<nr<<" ind = "<<clusterIndex[nr]<<endl;
8082 t.SetCurrentClusterIndex1(clusterIndex[nr]);
8083 t.SetCurrentCluster(cl);
8085 t.SetErrorY2(shapeY2[nr]);
8086 t.SetErrorZ2(shapeZ2[nr]);
8088 if( !UpdateTrack(&t,0) ){
8089 //cout<<"Can not update"<<endl;
8091 t.SetClusterIndex2(nr,-1);
8092 t.SetClusterIndex(nr,-1);
8095 //t.SetClusterPointer(nr, cl);
8098 //cout<<"After iter "<<iter<<": N clusters="<<t.GetNumberOfClusters()<<" : "<<nClusters<<endl;
8101 //cout<<"fitted track"<<iSeed<<endl;
8103 //cout<<"Statistics: "<<endl;
8104 Int_t foundable,found,shared;
8105 t.GetClusterStatistic(0,nRows, found, foundable, shared, kTRUE);
8106 t.SetNFoundable(foundable);
8107 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8113 TObjArray * AliTPCtrackerMI::MakeSeedsHLT(const AliESDEvent *hltEvent)
8118 if( !hltEvent ) return 0;
8121 Int_t nentr=hltEvent->GetNumberOfTracks();
8123 AliInfo(Form("Using %d HLT tracks for seeding",nentr));
8125 TObjArray * seeds = new TObjArray(nentr);
8127 Int_t nup=fOuterSec->GetNRows()+fInnerSec->GetNRows();
8130 Int_t nTr=hltEvent->GetNumberOfTracks();
8132 for( int itr=0; itr<nTr; itr++ ){
8133 //if( itr!=97 ) continue;
8134 const AliExternalTrackParam *param = hltEvent->GetTrack(itr)->GetTPCInnerParam();
8135 if( !param ) continue;
8136 //if( TMath::Abs(esdTr->GetSigned1Pt())>1 ) continue;
8137 //if( TMath::Abs(esdTr->GetTgl())>1. ) continue;
8139 tr.Set(param->GetX(),param->GetAlpha(),param->GetParameter(),param->GetCovariance());
8140 tr.SetNumberOfClusters(0);
8141 AliTPCseed * seed = new( NextFreeSeed() ) AliTPCseed(tr);
8143 Double_t alpha=seed->GetAlpha();// - fSectors->GetAlphaShift();
8144 if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi();
8145 if (alpha < 0. ) alpha += 2.*TMath::Pi();
8147 seed->SetRelativeSector(Int_t(alpha/fSectors->GetAlpha()+0.0001)%fN);
8148 Double_t alphaSec = fSectors->GetAlpha() * seed->GetRelativeSector() + fSectors->GetAlphaShift();
8150 if (alphaSec >= TMath::Pi()) alphaSec -= 2.*TMath::Pi();
8151 if (alphaSec < -TMath::Pi()) alphaSec += 2.*TMath::Pi();
8153 seed->Rotate(alphaSec - alpha);
8155 seed->SetPoolID(fLastSeedID);
8156 seed->SetIsSeeding(kTRUE);
8157 seed->SetSeed1(nup-1);
8158 seed->SetSeed2(nup-2);
8159 seed->SetSeedType(0);
8160 seed->SetFirstPoint(-1);
8161 seed->SetLastPoint(-1);
8162 seeds->AddLast(seed); // note, track is seed, don't free the seed
8164 //if( index>3 ) break;
8168 fSectors = fOuterSec;
8170 TrackFollowingHLT(seeds );
8172 nTr = seeds->GetEntriesFast();
8173 for( int itr=0; itr<nTr; itr++ ){
8174 AliTPCseed * seed = (AliTPCseed*) seeds->UncheckedAt(itr);
8175 if( !seed ) continue;
8176 //FollowBackProlongation(*seed,0);
8177 // cout<<seed->GetNumberOfClusters()<<endl;
8178 Int_t foundable,found,shared;
8179 seed->GetClusterStatistic(0,nup, found, foundable, shared, kTRUE);
8180 seed->SetNFoundable(foundable);
8181 //cout<<"found "<<found<<" foundable "<<foundable<<" shared "<<shared<<endl;
8182 //if ((found<0.55*foundable) || shared>0.5*found ){// || (seed->GetSigmaY2()+seed->GetSigmaZ2())>0.5){
8183 //MarkSeedFree(seeds->RemoveAt(itr));
8186 if (seed->GetNumberOfClusters()<30 ||
8187 seed->GetNumberOfClusters() < seed->GetNFoundable()*0.6 ||
8188 seed->GetNShared()>0.4*seed->GetNumberOfClusters() ) {
8189 MarkSeedFree(seeds->RemoveAt(itr));
8193 for( int ir=0; ir<nup; ir++){
8194 AliTPCclusterMI *c = seed->GetClusterPointer(ir);
8198 cout<<"\n\nHLT tracks left: "<<seeds->GetEntries()<<" out of "<<hltEvent->GetNumberOfTracks()<<endl<<endl;