]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliVertexerTracks.cxx
9261650c3003fc6e9e38cf904c1889d180b943f4
[u/mrichter/AliRoot.git] / STEER / AliVertexerTracks.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 //-----------------------------------------------------------------
17 //    Implementation of the vertexer from tracks
18 //
19 // Origin: AliITSVertexerTracks
20 //         A.Dainese, Padova, 
21 //         andrea.dainese@pd.infn.it
22 //         M.Masera,  Torino, 
23 //         massimo.masera@to.infn.it
24 // Moved to STEER and adapted to ESD tracks: 
25 //         F.Prino,  Torino, prino@to.infn.it
26 //-----------------------------------------------------------------
27
28 //---- Root headers --------
29 #include <TSystem.h>
30 #include <TDirectory.h>
31 #include <TFile.h>
32 #include <TTree.h>
33 #include <TMatrixD.h>
34 //---- AliRoot headers -----
35 #include "AliStrLine.h"
36 #include "AliExternalTrackParam.h"
37 #include "AliESDEvent.h"
38 #include "AliESDtrack.h"
39 #include "AliVertexerTracks.h"
40
41 ClassImp(AliVertexerTracks)
42
43
44 //----------------------------------------------------------------------------
45 AliVertexerTracks::AliVertexerTracks():
46 TObject(),
47 fVert(),
48 fCurrentVertex(0),
49 fMode(0),
50 fFieldkG(-999.),
51 fTrkArraySel(),
52 fIdSel(0),
53 fTrksToSkip(0),
54 fNTrksToSkip(0),
55 fConstraint(kFALSE),
56 fOnlyFitter(kFALSE),
57 fMinTracks(1),
58 fMinITSClusters(5),
59 fDCAcut(0.1),
60 fDCAcutIter0(0.1),
61 fNSigma(3.),
62 fMaxd0z0(0.5),
63 fMinDetFitter(100.),
64 fMaxTgl(1000.),
65 fITSrefit(kTRUE),
66 fnSigmaForUi00(1.5),
67 fDebug(0),
68 fAlgo(1)
69 {
70 //
71 // Default constructor
72 //
73   SetVtxStart();
74   SetVtxStartSigma();
75   SetITSMode();
76 }
77 //----------------------------------------------------------------------------
78 AliVertexerTracks::AliVertexerTracks(Double_t fieldkG):
79 TObject(),
80 fVert(),
81 fCurrentVertex(0),
82 fMode(0),
83 fFieldkG(fieldkG),
84 fTrkArraySel(),
85 fIdSel(0),
86 fTrksToSkip(0),
87 fNTrksToSkip(0),
88 fConstraint(kFALSE),
89 fOnlyFitter(kFALSE),
90 fMinTracks(1),
91 fMinITSClusters(5),
92 fDCAcut(0.1),
93 fDCAcutIter0(0.1),
94 fNSigma(3.),
95 fMaxd0z0(0.5),
96 fMinDetFitter(100.),
97 fMaxTgl(1000.),
98 fITSrefit(kTRUE),
99 fnSigmaForUi00(1.5),
100 fDebug(0),
101 fAlgo(1)
102 {
103 //
104 // Standard constructor
105 //
106   SetVtxStart();
107   SetVtxStartSigma();
108   SetITSMode();
109 }
110 //-----------------------------------------------------------------------------
111 AliVertexerTracks::~AliVertexerTracks() 
112 {
113   // Default Destructor
114   // The objects pointed by the following pointer are not owned
115   // by this class and are not deleted
116   fCurrentVertex = 0;
117   if(fTrksToSkip) { delete [] fTrksToSkip; fTrksToSkip=NULL; }
118   if(fIdSel) { delete [] fIdSel; fIdSel=NULL; }
119 }
120 //----------------------------------------------------------------------------
121 AliESDVertex* AliVertexerTracks::FindPrimaryVertex(const AliESDEvent *esdEvent)
122 {
123 //
124 // Primary vertex for current ESD event
125 // (Two iterations: 
126 //  1st with 5*fNSigma*sigma cut w.r.t. to initial vertex
127 //      + cut on sqrt(d0d0+z0z0) if fConstraint=kFALSE  
128 //  2nd with fNSigma*sigma cut w.r.t. to vertex found in 1st iteration) 
129 //
130   fCurrentVertex = 0;
131
132   // accept 1-track case only if constraint is available
133   if(!fConstraint && fMinTracks==1) fMinTracks=2;
134
135   // read tracks from ESD
136   Int_t nTrks = (Int_t)esdEvent->GetNumberOfTracks();
137   if(nTrks<fMinTracks) {
138     TooFewTracks();
139     return fCurrentVertex;
140   } 
141   //
142
143   TDirectory * olddir = gDirectory;
144   TFile *f = 0;
145   if(nTrks>500) f = new TFile("VertexerTracks.root","recreate");
146   TObjArray trkArrayOrig(nTrks);
147   UShort_t *idOrig = new UShort_t[nTrks];
148
149   Int_t nTrksOrig=0;
150   AliExternalTrackParam *t=0;
151   // loop on ESD tracks
152   for(Int_t i=0; i<nTrks; i++) {
153     AliESDtrack *esdt = esdEvent->GetTrack(i);
154     // check tracks to skip
155     Bool_t skipThis = kFALSE;
156     for(Int_t j=0; j<fNTrksToSkip; j++) { 
157       if(esdt->GetID()==fTrksToSkip[j]) {
158         if(fDebug) printf("skipping track: %d\n",i);
159         skipThis = kTRUE;
160       }
161     }
162     if(skipThis) continue;
163
164     if(fMode==0) {        // ITS mode
165       if(fITSrefit && !(esdt->GetStatus()&AliESDtrack::kITSrefit)) continue;
166       // check number of clusters in ITS
167       if(esdt->GetNcls(0)<fMinITSClusters) continue;
168       Double_t x,p[5],cov[15];
169       esdt->GetExternalParameters(x,p);
170       esdt->GetExternalCovariance(cov);
171       t = new AliExternalTrackParam(x,esdt->GetAlpha(),p,cov);
172     } else if(fMode==1) { // TPC mode
173       t = (AliExternalTrackParam*)esdt->GetTPCInnerParam();
174       if(!t) continue;
175       Double_t radius = 2.8; //something less than the beam pipe radius
176       if(!PropagateTrackTo(t,radius)) continue;
177     }
178     trkArrayOrig.AddLast(t);
179     idOrig[nTrksOrig]=(UShort_t)esdt->GetID();
180     nTrksOrig++;
181   } // end loop on ESD tracks
182   
183   // call method that will reconstruct the vertex
184   FindPrimaryVertex(&trkArrayOrig,idOrig);
185
186   if(fMode==0) trkArrayOrig.Delete();
187   delete [] idOrig; idOrig=NULL;
188
189   if(f) {
190     f->Close(); delete f; f = NULL;
191     gSystem->Unlink("VertexerTracks.root");
192     olddir->cd();
193   }
194
195   return fCurrentVertex;
196 }
197 //----------------------------------------------------------------------------
198 AliESDVertex* AliVertexerTracks::FindPrimaryVertex(TObjArray *trkArrayOrig,
199                                                    UShort_t *idOrig)
200 {
201 //
202 // Primary vertex using the AliExternalTrackParam's in the TObjArray.
203 // idOrig must contain the track IDs from AliESDtrack::GetID()
204 // (Two iterations: 
205 //  1st with 5*fNSigma*sigma cut w.r.t. to initial vertex
206 //      + cut on sqrt(d0d0+z0z0) if fConstraint=kFALSE  
207 //  2nd with fNSigma*sigma cut w.r.t. to vertex found in 1st iteration) 
208 //
209   fCurrentVertex = 0;
210
211   // accept 1-track case only if constraint is available
212   if(!fConstraint && fMinTracks==1) fMinTracks=2;
213
214   // read tracks from array
215   Int_t nTrksOrig = (Int_t)trkArrayOrig->GetEntriesFast();
216   if(fDebug) printf("Initial number of tracks: %d\n",nTrksOrig);
217   if(nTrksOrig<fMinTracks) {
218     if(fDebug) printf("TooFewTracks\n");
219     TooFewTracks();
220     return fCurrentVertex;
221   } 
222
223   // If fConstraint=kFALSE
224   // run VertexFinder(1) to get rough estimate of initVertex (x,y)
225   if(!fConstraint) {
226     // fill fTrkArraySel, for VertexFinder()
227     fIdSel = new UShort_t[nTrksOrig];
228     PrepareTracks(*trkArrayOrig,idOrig,0);
229     if(fIdSel) { delete [] fIdSel; fIdSel=NULL; }
230     Double_t cutsave = fDCAcut;  
231     fDCAcut = fDCAcutIter0;
232     VertexFinder(1); // using weights, cutting dca < fDCAcutIter0
233     fDCAcut = cutsave;
234     if(fVert.GetNContributors()>0) {
235       fVert.GetXYZ(fNominalPos);
236       fNominalPos[0] = fVert.GetXv();
237       fNominalPos[1] = fVert.GetYv();
238       fNominalPos[2] = fVert.GetZv();
239       if(fDebug) printf("No mean vertex: VertexFinder gives (%f, %f, %f)\n",fNominalPos[0],fNominalPos[1],fNominalPos[2]);
240     } else {
241       fNominalPos[0] = 0.;
242       fNominalPos[1] = 0.;
243       fNominalPos[2] = 0.;
244       if(fDebug) printf("No mean vertex and VertexFinder failed\n");
245     }
246   }
247   
248   // TWO ITERATIONS:
249   //
250   // ITERATION 1
251   // propagate tracks to fNominalPos vertex
252   // preselect them:
253   // if(constraint) reject for |d0|>5*fNSigma*sigma w.r.t. fNominal... vertex
254   // else  reject for |d0|\oplus|z0| > 5 mm w.r.t. fNominal... vertex
255   // ITERATION 2
256   // propagate tracks to best between initVertex and fCurrentVertex
257   // preselect tracks (reject for |d0|>fNSigma*sigma w.r.t. best 
258   //                   between initVertex and fCurrentVertex) 
259   for(Int_t iter=1; iter<=2; iter++) {
260     if(fOnlyFitter && iter==1) continue; 
261     if(fIdSel) { delete [] fIdSel; fIdSel=NULL; }
262     fIdSel = new UShort_t[nTrksOrig];
263     Int_t nTrksSel = PrepareTracks(*trkArrayOrig,idOrig,iter);
264     if(fDebug) printf("N tracks selected in iteration %d: %d\n",iter,nTrksSel);
265     if(nTrksSel < fMinTracks) {
266       TooFewTracks();
267       return fCurrentVertex; 
268     }
269
270     // vertex finder
271     if(!fOnlyFitter) {
272       if(nTrksSel==1) {
273         if(fDebug) printf("Just one track\n");
274         OneTrackVertFinder();
275       } else {
276         switch (fAlgo) {
277         case 1: StrLinVertexFinderMinDist(1); break;
278         case 2: StrLinVertexFinderMinDist(0); break;
279         case 3: HelixVertexFinder();          break;
280         case 4: VertexFinder(1);              break;
281         case 5: VertexFinder(0);              break;
282         default: printf("Wrong algorithm\n"); break;  
283         }
284       }
285       if(fDebug) printf(" Vertex finding completed\n");
286     }
287
288     // vertex fitter
289     VertexFitter();
290   } // end loop on the two iterations
291
292     
293   // set indices of used tracks
294   UShort_t *indices = 0;
295   if(fCurrentVertex->GetNContributors()>0) {
296     Int_t nIndices = (Int_t)fTrkArraySel.GetEntriesFast();
297     indices = new UShort_t[nIndices];
298     for(Int_t jj=0; jj<nIndices; jj++)
299       indices[jj] = fIdSel[jj];
300     fCurrentVertex->SetIndices(nIndices,indices);
301   }
302   delete [] indices; indices=NULL;
303   //
304
305   // set vertex title
306   TString title="VertexerTracksNoConstraint";
307   if(fConstraint) {
308     title="VertexerTracksWithConstraint";
309     if(fOnlyFitter) title.Append("OnlyFitter");
310   }
311   fCurrentVertex->SetTitle(title.Data());
312   //
313
314   if(fDebug) {
315     fCurrentVertex->PrintStatus();
316     fCurrentVertex->PrintIndices();
317   }
318
319   // clean up
320   delete [] fIdSel; fIdSel=NULL;
321   fTrkArraySel.Delete();
322   if(fTrksToSkip) { delete [] fTrksToSkip; fTrksToSkip=NULL; }
323   //
324   
325   return fCurrentVertex;
326 }
327 //------------------------------------------------------------------------
328 Double_t AliVertexerTracks::GetDeterminant3X3(Double_t matr[][3])
329 {
330   //
331   Double_t det=matr[0][0]*matr[1][1]*matr[2][2]-matr[0][0]*matr[1][2]*matr[2][1]-matr[0][1]*matr[1][0]*matr[2][2]+matr[0][1]*matr[1][2]*matr[2][0]+matr[0][2]*matr[1][0]*matr[2][1]-matr[0][2]*matr[1][1]*matr[2][0];
332  return det;
333 }
334 //-------------------------------------------------------------------------
335 void AliVertexerTracks::GetStrLinDerivMatrix(Double_t *p0,Double_t *p1,Double_t (*m)[3],Double_t *d)
336 {
337   //
338   Double_t x12=p0[0]-p1[0];
339   Double_t y12=p0[1]-p1[1];
340   Double_t z12=p0[2]-p1[2];
341   Double_t kk=x12*x12+y12*y12+z12*z12;
342   m[0][0]=2-2/kk*x12*x12;
343   m[0][1]=-2/kk*x12*y12;
344   m[0][2]=-2/kk*x12*z12;
345   m[1][0]=-2/kk*x12*y12;
346   m[1][1]=2-2/kk*y12*y12;
347   m[1][2]=-2/kk*y12*z12;
348   m[2][0]=-2/kk*x12*z12;
349   m[2][1]=-2*y12*z12;
350   m[2][2]=2-2/kk*z12*z12;
351   d[0]=2*p0[0]-2/kk*p0[0]*x12*x12-2/kk*p0[2]*x12*z12-2/kk*p0[1]*x12*y12;
352   d[1]=2*p0[1]-2/kk*p0[1]*y12*y12-2/kk*p0[0]*x12*y12-2/kk*p0[2]*z12*y12;
353   d[2]=2*p0[2]-2/kk*p0[2]*z12*z12-2/kk*p0[0]*x12*z12-2/kk*p0[1]*z12*y12;
354
355 }
356 //--------------------------------------------------------------------------  
357 void AliVertexerTracks::GetStrLinDerivMatrix(Double_t *p0,Double_t *p1,Double_t *sigmasq,Double_t (*m)[3],Double_t *d)
358 {
359   //
360   Double_t x12=p1[0]-p0[0];
361   Double_t y12=p1[1]-p0[1];
362   Double_t z12=p1[2]-p0[2];
363
364   Double_t den= x12*x12*sigmasq[1]*sigmasq[2]+y12*y12*sigmasq[0]*sigmasq[2]+z12*z12*sigmasq[0]*sigmasq[1];
365
366   Double_t kk= 2*(x12*x12/sigmasq[0]+y12*y12/sigmasq[1]+z12*z12/sigmasq[2]);
367
368   Double_t cc[3];
369   cc[0]=-x12/sigmasq[0];
370   cc[1]=-y12/sigmasq[1];
371   cc[2]=-z12/sigmasq[2];
372
373   Double_t ww=(-p0[0]*x12*sigmasq[1]*sigmasq[2]-p0[1]*y12*sigmasq[0]*sigmasq[2]-p0[2]*z12*sigmasq[0]*sigmasq[1])/den;
374
375   Double_t ss= -p0[0]*cc[0]-p0[1]*cc[1]-p0[2]*cc[2];
376
377   Double_t aa[3];
378   aa[0]=x12*sigmasq[1]*sigmasq[2]/den;
379   aa[1]=y12*sigmasq[0]*sigmasq[2]/den;
380   aa[2]=z12*sigmasq[0]*sigmasq[1]/den;
381
382   m[0][0]=aa[0]*(aa[0]*kk+2*cc[0])+2*cc[0]*aa[0]+2/sigmasq[0];
383   m[0][1]=aa[1]*(aa[0]*kk+2*cc[0])+2*cc[1]*aa[0];
384   m[0][2]=aa[2]*(aa[0]*kk+2*cc[0])+2*cc[2]*aa[0];
385
386   m[1][0]=aa[0]*(aa[1]*kk+2*cc[1])+2*cc[0]*aa[1];
387   m[1][1]=aa[1]*(aa[1]*kk+2*cc[1])+2*cc[1]*aa[1]+2/sigmasq[1];
388   m[1][2]=aa[2]*(aa[1]*kk+2*cc[1])+2*cc[2]*aa[1];
389
390   m[2][0]=aa[0]*(aa[2]*kk+2*cc[2])+2*cc[0]*aa[2];
391   m[2][1]=aa[1]*(aa[2]*kk+2*cc[2])+2*cc[1]*aa[2];
392   m[2][2]=aa[2]*(aa[2]*kk+2*cc[2])+2*cc[2]*aa[2]+2/sigmasq[2];
393
394   d[0]=-ww*(aa[0]*kk+2*cc[0])-2*ss*aa[0]+2*p0[0]/sigmasq[0];
395   d[1]=-ww*(aa[1]*kk+2*cc[1])-2*ss*aa[1]+2*p0[1]/sigmasq[1];
396   d[2]=-ww*(aa[2]*kk+2*cc[2])-2*ss*aa[2]+2*p0[2]/sigmasq[2];
397
398   }
399 //--------------------------------------------------------------------------   
400 Double_t AliVertexerTracks::GetStrLinMinDist(Double_t *p0,Double_t *p1,Double_t *x0)
401 {
402   //
403   Double_t x12=p0[0]-p1[0];
404   Double_t y12=p0[1]-p1[1];
405   Double_t z12=p0[2]-p1[2];
406   Double_t x10=p0[0]-x0[0];
407   Double_t y10=p0[1]-x0[1];
408   Double_t z10=p0[2]-x0[2];
409   //  return ((x10*x10+y10*y10+z10*z10)*(x12*x12+y12*y12+z12*z12)-(x10*x12+y10*y12+z10*z12)*(x10*x12+y10*y12+z10*z12))/(x12*x12+y12*y12+z12*z12);
410   return ((y10*z12-z10*y12)*(y10*z12-z10*y12)+
411           (z10*x12-x10*z12)*(z10*x12-x10*z12)+
412           (x10*y12-y10*x12)*(x10*y12-y10*x12))
413     /(x12*x12+y12*y12+z12*z12);
414 }
415 //---------------------------------------------------------------------------
416 void AliVertexerTracks::OneTrackVertFinder() 
417 {
418   // find vertex for events with 1 track, using DCA to nominal beam axis
419   if(fDebug) printf("Number of prepared tracks =%d - Call OneTrackVertFinder",fTrkArraySel.GetEntries());
420   AliExternalTrackParam *track1;
421   track1 = (AliExternalTrackParam*)fTrkArraySel.At(0);
422   Double_t alpha=track1->GetAlpha();
423   Double_t mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
424   Double_t pos[3],dir[3]; 
425   track1->GetXYZAt(mindist,GetFieldkG(),pos);
426   track1->GetPxPyPzAt(mindist,GetFieldkG(),dir);
427   AliStrLine *line1 = new AliStrLine(pos,dir);
428   Double_t p1[3]={fNominalPos[0],fNominalPos[1],0.}; 
429   Double_t p2[3]={fNominalPos[0],fNominalPos[1],10.}; 
430   AliStrLine *zeta=new AliStrLine(p1,p2,kTRUE);
431   Double_t crosspoint[3]={0.,0.,0.};
432   Double_t sigma=999.;
433   Int_t nContrib=-1;
434   Int_t retcode = zeta->Cross(line1,crosspoint);
435   if(retcode>=0){
436     sigma=line1->GetDistFromPoint(crosspoint);
437     nContrib=1;
438   }
439   delete zeta;
440   delete line1;
441   fVert.SetXYZ(crosspoint);
442   fVert.SetDispersion(sigma);
443   fVert.SetNContributors(nContrib);  
444 }
445 //---------------------------------------------------------------------------
446 void AliVertexerTracks::HelixVertexFinder() 
447 {
448   // Get estimate of vertex position in (x,y) from tracks DCA
449
450
451   Double_t initPos[3];
452   initPos[2] = 0.;
453   for(Int_t i=0;i<2;i++)initPos[i]=fNominalPos[i];
454
455   Int_t nacc = (Int_t)fTrkArraySel.GetEntriesFast();
456
457   Double_t aver[3]={0.,0.,0.};
458   Double_t averquad[3]={0.,0.,0.};
459   Double_t sigmaquad[3]={0.,0.,0.};
460   Double_t sigma=0;
461   Int_t ncombi = 0;
462   AliExternalTrackParam *track1;
463   AliExternalTrackParam *track2;
464   Double_t distCA;
465   Double_t x;
466   Double_t alpha, cs, sn;
467   Double_t crosspoint[3];
468   for(Int_t i=0; i<nacc; i++){
469     track1 = (AliExternalTrackParam*)fTrkArraySel.At(i);
470     
471
472     for(Int_t j=i+1; j<nacc; j++){
473       track2 = (AliExternalTrackParam*)fTrkArraySel.At(j);
474
475       distCA=track2->PropagateToDCA(track1,GetFieldkG());
476       if(fDCAcut<=0 ||(fDCAcut>0&&distCA<fDCAcut)){
477         x=track1->GetX();
478         alpha=track1->GetAlpha();
479         cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);
480         Double_t x1=x*cs - track1->GetY()*sn;
481         Double_t y1=x*sn + track1->GetY()*cs;
482         Double_t z1=track1->GetZ();
483         
484         Double_t sx1=sn*sn*track1->GetSigmaY2(), sy1=cs*cs*track1->GetSigmaY2(); 
485         x=track2->GetX();
486         alpha=track2->GetAlpha();
487         cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);
488         Double_t x2=x*cs - track2->GetY()*sn;
489         Double_t y2=x*sn + track2->GetY()*cs;
490         Double_t z2=track2->GetZ();
491         Double_t sx2=sn*sn*track2->GetSigmaY2(), sy2=cs*cs*track2->GetSigmaY2();
492         Double_t sz1=track1->GetSigmaZ2(), sz2=track2->GetSigmaZ2();
493         Double_t wx1=sx2/(sx1+sx2), wx2=1.- wx1;
494         Double_t wy1=sy2/(sy1+sy2), wy2=1.- wy1;
495         Double_t wz1=sz2/(sz1+sz2), wz2=1.- wz1;
496         crosspoint[0]=wx1*x1 + wx2*x2; 
497         crosspoint[1]=wy1*y1 + wy2*y2; 
498         crosspoint[2]=wz1*z1 + wz2*z2;
499
500         ncombi++;
501         for(Int_t jj=0;jj<3;jj++)aver[jj]+=crosspoint[jj];
502         for(Int_t jj=0;jj<3;jj++)averquad[jj]+=(crosspoint[jj]*crosspoint[jj]);
503       }
504     }
505       
506   }
507   if(ncombi>0){
508     for(Int_t jj=0;jj<3;jj++){
509       initPos[jj] = aver[jj]/ncombi;
510       averquad[jj]/=ncombi;
511       sigmaquad[jj]=averquad[jj]-initPos[jj]*initPos[jj];
512       sigma+=sigmaquad[jj];
513     }
514     sigma=TMath::Sqrt(TMath::Abs(sigma));
515   }
516   else {
517     Warning("HelixVertexFinder","Finder did not succed");
518     sigma=999;
519   }
520   fVert.SetXYZ(initPos);
521   fVert.SetDispersion(sigma);
522   fVert.SetNContributors(ncombi);
523 }
524 //----------------------------------------------------------------------------
525 Int_t AliVertexerTracks::PrepareTracks(TObjArray &trkArrayOrig,
526                                        UShort_t *idOrig,
527                                        Int_t optImpParCut) 
528 {
529 //
530 // Propagate tracks to initial vertex position and store them in a TObjArray
531 //
532   if(fDebug) printf(" PrepareTracks()\n");
533
534   Int_t nTrksOrig = (Int_t)trkArrayOrig.GetEntriesFast();
535   Int_t nTrksSel = 0;
536   Double_t maxd0rphi; 
537   Double_t fiducialR = 3.0, fiducialZ = 20.0; // pipe and 1.5xSPD
538   Double_t sigmaCurr[3];
539   Double_t normdistx,normdisty;
540   Double_t d0z0[2],covd0z0[3]; 
541   Double_t sigmad0;
542
543   AliESDVertex *initVertex = new AliESDVertex(fNominalPos,fNominalCov,1,1);
544
545   if(!fTrkArraySel.IsEmpty()) fTrkArraySel.Delete();
546
547   AliExternalTrackParam *track=0;
548
549   // loop on tracks
550   for(Int_t i=0; i<nTrksOrig; i++) {
551     track = new AliExternalTrackParam(*(AliExternalTrackParam*)trkArrayOrig.At(i));
552     // tgl cut
553     if(TMath::Abs(track->GetTgl())>fMaxTgl) {
554       if(fDebug) printf(" rejecting track with tgl = %f\n",track->GetTgl());
555       delete track; continue;
556     }
557
558     // propagate track to vertex
559     if(optImpParCut<2 || fOnlyFitter) { // optImpParCut==1 or 0
560       track->PropagateToDCA(initVertex,GetFieldkG(),100.,d0z0,covd0z0);
561     } else {              // optImpParCut==2
562       fCurrentVertex->GetSigmaXYZ(sigmaCurr);
563       normdistx = TMath::Abs(fCurrentVertex->GetXv()-fNominalPos[0])/TMath::Sqrt(sigmaCurr[0]*sigmaCurr[0]+fNominalCov[0]);
564       normdisty = TMath::Abs(fCurrentVertex->GetYv()-fNominalPos[1])/TMath::Sqrt(sigmaCurr[1]*sigmaCurr[1]+fNominalCov[2]);
565       if(normdistx < 3. && normdisty < 3. &&
566          (sigmaCurr[0]+sigmaCurr[1])<(TMath::Sqrt(fNominalCov[0])+TMath::Sqrt(fNominalCov[2]))) {
567         track->PropagateToDCA(fCurrentVertex,GetFieldkG(),100.,d0z0,covd0z0);
568       } else {
569         track->PropagateToDCA(initVertex,GetFieldkG(),100.,d0z0,covd0z0);
570       }
571     }
572
573     sigmad0 = TMath::Sqrt(covd0z0[0]);
574     maxd0rphi = fNSigma*sigmad0;
575     if(optImpParCut==1) maxd0rphi *= 5.;
576     maxd0rphi = TMath::Min(maxd0rphi,fiducialR); 
577     //sigmad0z0 = TMath::Sqrt(covd0z0[0]+covd0z0[2]); // for future improvement
578     //maxd0z0 = 10.*fNSigma*sigmad0z0;
579
580     if(fDebug) printf("trk %d; id %d; |d0| = %f;  d0 cut = %f; |z0| = %f; |d0|oplus|z0| = %f; d0z0 cut = %f\n",i,(Int_t)idOrig[i],TMath::Abs(d0z0[0]),maxd0rphi,TMath::Abs(d0z0[1]),TMath::Sqrt(d0z0[0]*d0z0[0]+d0z0[1]*d0z0[1]),fMaxd0z0);
581
582
583     //---- track selection based on impact parameters ----//
584
585     // always reject tracks outside fiducial volume
586     if(TMath::Abs(d0z0[0])>fiducialR || TMath::Abs(d0z0[1])>fiducialZ) { 
587       if(fDebug) printf("     rejected\n");
588       delete track; continue; 
589     }
590
591     // during iterations 1 and 2 , reject tracks with d0rphi > maxd0rphi
592     if(optImpParCut>0 && TMath::Abs(d0z0[0])>maxd0rphi) { 
593       if(fDebug) printf("     rejected\n");
594       delete track; continue; 
595     }
596
597     // if fConstraint=kFALSE, during iterations 1 and 2 ||
598     // if fConstraint=kTRUE, during iteration 2,
599     // select tracks with d0oplusz0 < fMaxd0z0
600     if((!fConstraint && optImpParCut>0 && fVert.GetNContributors()>0) ||
601        ( fConstraint && optImpParCut==2)) {
602       if(nTrksOrig>=3 && 
603          TMath::Sqrt(d0z0[0]*d0z0[0]+d0z0[1]*d0z0[1])>fMaxd0z0) { 
604         if(fDebug) printf("     rejected\n");
605         delete track; continue; 
606       }
607     }
608     
609     // track passed all selections
610     fTrkArraySel.AddLast(track);
611     fIdSel[nTrksSel] = idOrig[i];
612     nTrksSel++; 
613   } // end loop on tracks
614
615   delete initVertex;
616
617   return nTrksSel;
618
619 //----------------------------------------------------------------------------
620 Bool_t AliVertexerTracks::PropagateTrackTo(AliExternalTrackParam *track,
621                                            Double_t xToGo) {
622   //----------------------------------------------------------------
623   // COPIED from AliTracker
624   //
625   // Propagates the track to the plane X=xk (cm).
626   //
627   //  Origin: Marian Ivanov,  Marian.Ivanov@cern.ch
628   //----------------------------------------------------------------
629
630   const Double_t kEpsilon = 0.00001;
631   Double_t xpos = track->GetX();
632   Double_t dir = (xpos<xToGo) ? 1. : -1.;
633   Double_t maxStep = 5;
634   Double_t maxSnp = 0.8;
635   //
636   while ( (xToGo-xpos)*dir > kEpsilon){
637     Double_t step = dir*TMath::Min(TMath::Abs(xToGo-xpos), maxStep);
638     Double_t x    = xpos+step;
639     Double_t xyz0[3],xyz1[3];
640     track->GetXYZ(xyz0);   //starting global position
641
642     if(!track->GetXYZAt(x,GetFieldkG(),xyz1)) return kFALSE;   // no prolongation
643     xyz1[2]+=kEpsilon; // waiting for bug correction in geo
644
645     if(TMath::Abs(track->GetSnpAt(x,GetFieldkG())) >= maxSnp) return kFALSE;
646     if(!track->PropagateTo(x,GetFieldkG()))  return kFALSE;
647
648     if(TMath::Abs(track->GetSnp()) >= maxSnp) return kFALSE;
649     track->GetXYZ(xyz0);   // global position
650     Double_t alphan = TMath::ATan2(xyz0[1], xyz0[0]); 
651     //
652     Double_t ca=TMath::Cos(alphan-track->GetAlpha()), 
653       sa=TMath::Sin(alphan-track->GetAlpha());
654     Double_t sf=track->GetSnp(), cf=TMath::Sqrt(1.- sf*sf);
655     Double_t sinNew =  sf*ca - cf*sa;
656     if(TMath::Abs(sinNew) >= maxSnp) return kFALSE;
657     if(!track->Rotate(alphan)) return kFALSE;
658  
659     xpos = track->GetX();
660   }
661   return kTRUE;
662 }
663 //---------------------------------------------------------------------------
664 AliESDVertex* AliVertexerTracks::RemoveTracksFromVertex(AliESDVertex *inVtx,
665                                                         TObjArray *trkArray,
666                                                         UShort_t *id,
667                                                         Float_t *diamondxy) 
668 {
669 //
670 // Removes tracks in trksTree from fit of inVtx
671 //
672
673   if(!strstr(inVtx->GetTitle(),"VertexerTracksWithConstraint")) {
674     printf("ERROR: primary vertex has no constraint: cannot remove tracks\n");
675     return 0x0;
676   }
677   if(!strstr(inVtx->GetTitle(),"VertexerTracksWithConstraintOnlyFitter"))
678     printf("WARNING: result of tracks' removal will be only approximately correct\n");
679
680   TMatrixD rv(3,1);
681   rv(0,0) = inVtx->GetXv();
682   rv(1,0) = inVtx->GetYv();
683   rv(2,0) = inVtx->GetZv();
684   TMatrixD vV(3,3);
685   Double_t cov[6];
686   inVtx->GetCovMatrix(cov);
687   vV(0,0) = cov[0];
688   vV(0,1) = cov[1]; vV(1,0) = cov[1];
689   vV(1,1) = cov[2];
690   vV(0,2) = cov[3]; vV(2,0) = cov[3];
691   vV(1,2) = cov[4]; vV(2,1) = cov[4]; 
692   vV(2,2) = cov[5];
693
694   TMatrixD sumWi(TMatrixD::kInverted,vV);
695   TMatrixD sumWiri(sumWi,TMatrixD::kMult,rv);
696
697   Int_t nUsedTrks = inVtx->GetNIndices();
698   Double_t chi2 = inVtx->GetChi2();
699
700   AliExternalTrackParam *track = 0;
701   Int_t ntrks = (Int_t)trkArray->GetEntriesFast();
702   for(Int_t i=0;i<ntrks;i++) {
703     track = (AliExternalTrackParam*)trkArray->At(i);
704     if(!inVtx->UsesTrack(id[i])) {
705       printf("track %d was not used in vertex fit\n",id[i]);
706       continue;
707     }
708     Double_t alpha = track->GetAlpha();
709     Double_t xl = diamondxy[0]*TMath::Cos(alpha)+diamondxy[1]*TMath::Sin(alpha);
710     track->PropagateTo(xl,GetFieldkG()); 
711     // vector of track global coordinates
712     TMatrixD ri(3,1);
713     // covariance matrix of ri
714     TMatrixD wWi(3,3);
715     
716     // get space point from track
717     if(!TrackToPoint(track,ri,wWi)) continue;
718
719     TMatrixD wWiri(wWi,TMatrixD::kMult,ri); 
720
721     sumWi -= wWi;
722     sumWiri -= wWiri;
723
724     // track chi2
725     TMatrixD deltar = rv; deltar -= ri;
726     TMatrixD wWideltar(wWi,TMatrixD::kMult,deltar);
727     Double_t chi2i = deltar(0,0)*wWideltar(0,0)+
728                      deltar(1,0)*wWideltar(1,0)+
729                      deltar(2,0)*wWideltar(2,0);
730     // remove from total chi2
731     chi2 -= chi2i;
732
733     nUsedTrks--;
734     if(nUsedTrks<2) {
735       printf("Trying to remove too many tracks!\n");
736       return 0x0;
737     }
738   }
739
740   TMatrixD rvnew(3,1);
741   TMatrixD vVnew(3,3);
742
743   // new inverted of weights matrix
744   TMatrixD invsumWi(TMatrixD::kInverted,sumWi);
745   vVnew = invsumWi;
746   // new position of primary vertex
747   rvnew.Mult(vVnew,sumWiri);
748
749   Double_t position[3];
750   position[0] = rvnew(0,0);
751   position[1] = rvnew(1,0);
752   position[2] = rvnew(2,0);
753   cov[0] = vVnew(0,0);
754   cov[1] = vVnew(0,1);
755   cov[2] = vVnew(1,1);
756   cov[3] = vVnew(0,2);
757   cov[4] = vVnew(1,2);
758   cov[5] = vVnew(2,2);
759   
760   // store data in the vertex object
761   AliESDVertex *outVtx = new AliESDVertex(position,cov,chi2,nUsedTrks);
762   outVtx->SetTitle(inVtx->GetTitle());
763   UShort_t *inindices = inVtx->GetIndices();
764   Int_t nIndices = nUsedTrks;
765   UShort_t *outindices = new UShort_t[nIndices];
766   Int_t j=0;
767   for(Int_t k=0; k<inVtx->GetNIndices(); k++) {
768     Bool_t copyindex=kTRUE;
769     for(Int_t l=0; l<ntrks; l++) {
770       if(inindices[k]==id[l]) copyindex=kFALSE;
771     }
772     if(copyindex) {
773       outindices[j] = inindices[k]; j++;
774     }
775   }
776   outVtx->SetIndices(nIndices,outindices);
777   delete [] outindices;
778
779   if(fDebug) {
780     printf("Vertex before removing tracks:\n");
781     inVtx->PrintStatus();
782     inVtx->PrintIndices();
783     printf("Vertex after removing tracks:\n");
784     outVtx->PrintStatus();
785     outVtx->PrintIndices();
786   }
787
788   return outVtx;
789 }
790 //---------------------------------------------------------------------------
791 void AliVertexerTracks::SetITSMode(Double_t dcacut,
792                                    Double_t dcacutIter0,
793                                    Double_t maxd0z0,
794                                    Int_t minITScls,
795                                    Int_t mintrks,
796                                    Double_t nsigma,
797                                    Double_t mindetfitter,
798                                    Double_t maxtgl) 
799 {
800 //
801 //  Cut values for ITS mode
802 //
803   fMode = 0;
804   SetITSrefitRequired();
805   SetDCAcut(dcacut);
806   SetDCAcutIter0(dcacutIter0);
807   SetMaxd0z0(maxd0z0);
808   SetMinITSClusters(minITScls);
809   SetMinTracks(mintrks);
810   SetNSigmad0(nsigma);
811   SetMinDetFitter(mindetfitter);
812   SetMaxTgl(maxtgl);
813
814   return; 
815 }
816 //---------------------------------------------------------------------------
817 void AliVertexerTracks::SetTPCMode(Double_t dcacut,
818                                    Double_t dcacutIter0,
819                                    Double_t maxd0z0,
820                                    Int_t minITScls,
821                                    Int_t mintrks,
822                                    Double_t nsigma,
823                                    Double_t mindetfitter,
824                                    Double_t maxtgl) 
825 {
826 //
827 //  Cut values for TPC mode
828 //
829   fMode = 1;
830   SetITSrefitNotRequired();
831   SetDCAcut(dcacut);
832   SetDCAcutIter0(dcacutIter0);
833   SetMaxd0z0(maxd0z0);
834   SetMinITSClusters(minITScls);
835   SetMinTracks(mintrks);
836   SetNSigmad0(nsigma);
837   SetMinDetFitter(mindetfitter);
838   SetMaxTgl(maxtgl);
839
840   return; 
841 }
842 //---------------------------------------------------------------------------
843 void AliVertexerTracks::SetSkipTracks(Int_t n,Int_t *skipped) 
844 {
845 //
846 // Mark the tracks not to be used in the vertex reconstruction.
847 // Tracks are identified by AliESDtrack::GetID()
848 //
849   fNTrksToSkip = n;  fTrksToSkip = new Int_t[n]; 
850   for(Int_t i=0;i<n;i++) fTrksToSkip[i] = skipped[i]; 
851   return; 
852 }
853 //---------------------------------------------------------------------------
854 void  AliVertexerTracks::SetVtxStart(AliESDVertex *vtx) 
855
856 //
857 // Set initial vertex knowledge
858 //
859   vtx->GetXYZ(fNominalPos);
860   vtx->GetCovMatrix(fNominalCov);
861   SetConstraintOn();
862   return; 
863 }
864 //---------------------------------------------------------------------------
865 void AliVertexerTracks::StrLinVertexFinderMinDist(Int_t optUseWeights)
866 {
867   AliExternalTrackParam *track1;
868   const Int_t knacc = (Int_t)fTrkArraySel.GetEntriesFast();
869   static TClonesArray linarray("AliStrLine",knacc);
870   for(Int_t i=0; i<knacc; i++){
871     track1 = (AliExternalTrackParam*)fTrkArraySel.At(i);
872     Double_t alpha=track1->GetAlpha();
873     Double_t mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
874     Double_t pos[3],dir[3],sigmasq[3]; 
875     track1->GetXYZAt(mindist,GetFieldkG(),pos);
876     track1->GetPxPyPzAt(mindist,GetFieldkG(),dir);
877     sigmasq[0]=TMath::Sin(alpha)*TMath::Sin(alpha)*track1->GetSigmaY2();
878     sigmasq[1]=TMath::Cos(alpha)*TMath::Cos(alpha)*track1->GetSigmaY2();
879     sigmasq[2]=track1->GetSigmaZ2();
880     TMatrixD ri(3,1);
881     TMatrixD wWi(3,3);
882     if(!TrackToPoint(track1,ri,wWi)) continue;
883     Double_t wmat[9];
884     Int_t iel=0;
885     for(Int_t ia=0;ia<3;ia++){
886       for(Int_t ib=0;ib<3;ib++){
887         wmat[iel]=wWi(ia,ib);
888         iel++;
889       }    
890     }
891     new(linarray[i]) AliStrLine(pos,sigmasq,wmat,dir);     
892   }
893   fVert=TrackletVertexFinder(&linarray,optUseWeights);
894   linarray.Clear("C");
895 }
896 //---------------------------------------------------------------------------
897 AliESDVertex AliVertexerTracks::TrackletVertexFinder(TClonesArray *lines, Int_t optUseWeights)
898 {
899   // Calculate the point at minimum distance to prepared tracks 
900   
901   const Int_t knacc = (Int_t)lines->GetEntriesFast();
902   Double_t initPos[3]={0.,0.,0.};
903
904   Double_t (*vectP0)[3]=new Double_t [knacc][3];
905   Double_t (*vectP1)[3]=new Double_t [knacc][3];
906   
907   Double_t sum[3][3];
908   Double_t dsum[3]={0,0,0};
909   TMatrixD sumWi(3,3);
910   for(Int_t i=0;i<3;i++){
911     for(Int_t j=0;j<3;j++){
912       sum[i][j]=0;
913       sumWi(i,j)=0.;
914     }
915   }
916
917   for(Int_t i=0; i<knacc; i++){
918     AliStrLine* line1 = (AliStrLine*)lines->At(i); 
919     Double_t p0[3],cd[3],sigmasq[3];
920     Double_t wmat[9];
921     line1->GetP0(p0);
922     line1->GetCd(cd);
923     line1->GetSigma2P0(sigmasq);
924     line1->GetWMatrix(wmat);
925     TMatrixD wWi(3,3);
926     Int_t iel=0;
927     for(Int_t ia=0;ia<3;ia++){
928       for(Int_t ib=0;ib<3;ib++){
929         wWi(ia,ib)=wmat[iel];
930         iel++;
931       }    
932     }
933
934     sumWi+=wWi;
935
936     Double_t p1[3]={p0[0]+cd[0],p0[1]+cd[1],p0[2]+cd[2]};
937     vectP0[i][0]=p0[0];
938     vectP0[i][1]=p0[1];
939     vectP0[i][2]=p0[2];
940     vectP1[i][0]=p1[0];
941     vectP1[i][1]=p1[1];
942     vectP1[i][2]=p1[2];
943     
944     Double_t matr[3][3];
945     Double_t dknow[3];
946     if(optUseWeights==0)GetStrLinDerivMatrix(p0,p1,matr,dknow);
947     else GetStrLinDerivMatrix(p0,p1,sigmasq,matr,dknow);
948
949
950     for(Int_t iii=0;iii<3;iii++){
951       dsum[iii]+=dknow[iii]; 
952       for(Int_t lj=0;lj<3;lj++) sum[iii][lj]+=matr[iii][lj];
953     }
954   }
955  
956   TMatrixD invsumWi(TMatrixD::kInverted,sumWi);
957   Double_t covmatrix[6];
958   covmatrix[0] = invsumWi(0,0);
959   covmatrix[1] = invsumWi(0,1);
960   covmatrix[2] = invsumWi(1,1);
961   covmatrix[3] = invsumWi(0,2);
962   covmatrix[4] = invsumWi(1,2);
963   covmatrix[5] = invsumWi(2,2);
964
965   Double_t vett[3][3];
966   Double_t det=GetDeterminant3X3(sum);
967   Double_t sigma=0;
968   
969   if(det!=0){
970     for(Int_t zz=0;zz<3;zz++){
971       for(Int_t ww=0;ww<3;ww++){
972         for(Int_t kk=0;kk<3;kk++) vett[ww][kk]=sum[ww][kk];
973       }
974       for(Int_t kk=0;kk<3;kk++) vett[kk][zz]=dsum[kk];
975       initPos[zz]=GetDeterminant3X3(vett)/det;
976     }
977
978
979     for(Int_t i=0; i<knacc; i++){
980       Double_t p0[3]={0,0,0},p1[3]={0,0,0};
981       for(Int_t ii=0;ii<3;ii++){
982         p0[ii]=vectP0[i][ii];
983         p1[ii]=vectP1[i][ii];
984       }
985       sigma+=GetStrLinMinDist(p0,p1,initPos);
986     }
987
988     if(sigma>0.) {sigma=TMath::Sqrt(sigma);}else{sigma=999;}
989   }else{
990     sigma=999;
991   }
992   AliESDVertex theVert(initPos,covmatrix,99999.,knacc);
993   theVert.SetDispersion(sigma);
994   delete vectP0;
995   delete vectP1;
996   return theVert;
997 }
998 //---------------------------------------------------------------------------
999 Bool_t AliVertexerTracks::TrackToPoint(AliExternalTrackParam *t,
1000                                        TMatrixD &ri,TMatrixD &wWi,
1001                                        Bool_t uUi3by3) const 
1002 {
1003 //
1004 // Extract from the AliExternalTrackParam the global coordinates ri and covariance matrix
1005 // wWi of the space point that it represents (to be used in VertexFitter())
1006 //
1007
1008   
1009   Double_t rotAngle = t->GetAlpha();
1010   if(rotAngle<0.) rotAngle += 2.*TMath::Pi();
1011   Double_t cosRot = TMath::Cos(rotAngle);
1012   Double_t sinRot = TMath::Sin(rotAngle);
1013
1014   ri(0,0) = t->GetX()*cosRot-t->GetY()*sinRot;
1015   ri(1,0) = t->GetX()*sinRot+t->GetY()*cosRot;
1016   ri(2,0) = t->GetZ();
1017
1018
1019
1020   if(!uUi3by3) {
1021     // matrix to go from global (x,y,z) to local (y,z);
1022     TMatrixD qQi(2,3);
1023     qQi(0,0) = -sinRot;
1024     qQi(0,1) = cosRot;
1025     qQi(0,2) = 0.;
1026     qQi(1,0) = 0.;
1027     qQi(1,1) = 0.;
1028     qQi(1,2) = 1.;
1029
1030     // covariance matrix of local (y,z) - inverted
1031     TMatrixD uUi(2,2);
1032     uUi(0,0) = t->GetSigmaY2();
1033     uUi(0,1) = t->GetSigmaZY();
1034     uUi(1,0) = t->GetSigmaZY();
1035     uUi(1,1) = t->GetSigmaZ2();
1036     //printf(" Ui :\n");
1037     //printf(" %f   %f\n",uUi(0,0),uUi(0,1));
1038     //printf(" %f   %f\n",uUi(1,0),uUi(1,1));
1039
1040     if(uUi.Determinant() <= 0.) return kFALSE;
1041     TMatrixD uUiInv(TMatrixD::kInverted,uUi);
1042   
1043     // weights matrix: wWi = qQiT * uUiInv * qQi
1044     TMatrixD uUiInvQi(uUiInv,TMatrixD::kMult,qQi);
1045     TMatrixD m(qQi,TMatrixD::kTransposeMult,uUiInvQi);
1046     wWi = m;
1047   } else {
1048     if(fVert.GetNContributors()<1) AliFatal("Vertex from finder is empty");
1049     // matrix to go from global (x,y,z) to local (x,y,z);
1050     TMatrixD qQi(3,3);
1051     qQi(0,0) = cosRot;
1052     qQi(0,1) = sinRot;
1053     qQi(0,2) = 0.;
1054     qQi(1,0) = -sinRot;
1055     qQi(1,1) = cosRot;
1056     qQi(1,2) = 0.;
1057     qQi(2,0) = 0.;
1058     qQi(2,1) = 0.;
1059     qQi(2,2) = 1.;
1060    
1061     // covariance of fVert along the track  
1062     Double_t p[3],pt,ptot;
1063     t->GetPxPyPz(p);
1064     pt = TMath::Sqrt(p[0]*p[0]+p[1]*p[1]);
1065     ptot = TMath::Sqrt(pt*pt+p[2]*p[2]);
1066     Double_t cphi = p[0]/pt;               //cos(phi)=px/pt
1067     Double_t sphi = p[1]/pt;               //sin(phi)=py/pt
1068     Double_t clambda = pt/ptot;            //cos(lambda)=pt/ptot
1069     Double_t slambda = p[2]/ptot;            //sin(lambda)=pz/ptot
1070     Double_t covfVert[6];
1071     fVert.GetCovMatrix(covfVert);
1072     Double_t covfVertalongt = 
1073        covfVert[0]*cphi*cphi*clambda*clambda 
1074       +covfVert[1]*2.*cphi*sphi*clambda*clambda
1075       +covfVert[3]*2.*cphi*clambda*slambda 
1076       +covfVert[2]*sphi*sphi*clambda*clambda 
1077       +covfVert[4]*2.*sphi*clambda*slambda 
1078       +covfVert[5]*slambda*slambda; 
1079     // covariance matrix of local (x,y,z) - inverted
1080     TMatrixD uUi(3,3);
1081     uUi(0,0) = covfVertalongt * fnSigmaForUi00 * fnSigmaForUi00;
1082     if(fDebug) printf("=====> sqrtUi00 cm  %f\n",TMath::Sqrt(uUi(0,0)));
1083     uUi(0,1) = 0.;
1084     uUi(0,2) = 0.;
1085     uUi(1,0) = 0.;
1086     uUi(1,1) = t->GetSigmaY2();
1087     uUi(1,2) = t->GetSigmaZY();
1088     uUi(2,0) = 0.;
1089     uUi(2,1) = t->GetSigmaZY();
1090     uUi(2,2) = t->GetSigmaZ2();
1091     //printf(" Ui :\n");
1092     //printf(" %f   %f\n",uUi(0,0),uUi(0,1));
1093     //printf(" %f   %f\n",uUi(1,0),uUi(1,1));
1094   
1095     if(uUi.Determinant() <= 0.) return kFALSE;
1096     TMatrixD uUiInv(TMatrixD::kInverted,uUi);
1097   
1098     // weights matrix: wWi = qQiT * uUiInv * qQi
1099     TMatrixD uUiInvQi(uUiInv,TMatrixD::kMult,qQi);
1100     TMatrixD m(qQi,TMatrixD::kTransposeMult,uUiInvQi);
1101     wWi = m;
1102   }
1103
1104
1105   return kTRUE;
1106
1107 //---------------------------------------------------------------------------
1108 void AliVertexerTracks::TooFewTracks() 
1109 {
1110 //
1111 // When the number of tracks is < fMinTracks,
1112 // deal with vertices not found and prepare to exit
1113 //
1114   if(fDebug) printf("TooFewTracks\n");
1115
1116   Double_t pos[3],err[3];
1117   pos[0] = fNominalPos[0];
1118   err[0] = TMath::Sqrt(fNominalCov[0]);
1119   pos[1] = fNominalPos[1];
1120   err[1] = TMath::Sqrt(fNominalCov[2]);
1121   pos[2] = fNominalPos[2];
1122   err[2] = TMath::Sqrt(fNominalCov[5]);
1123   Int_t    ncontr = (err[0]>1. ? -1 : -3);
1124   fCurrentVertex = 0;
1125   fCurrentVertex = new AliESDVertex(pos,err);
1126   fCurrentVertex->SetNContributors(ncontr);
1127
1128   if(fConstraint) {
1129     fCurrentVertex->SetTitle("VertexerTracksWithConstraint");
1130   } else {
1131     fCurrentVertex->SetTitle("VertexerTracksNoConstraint");
1132   }
1133
1134   if(!fTrkArraySel.IsEmpty()) fTrkArraySel.Delete(); 
1135   if(fIdSel) {delete [] fIdSel; fIdSel=NULL;}
1136   if(fTrksToSkip) {delete [] fTrksToSkip; fTrksToSkip=NULL;}
1137
1138   return;
1139 }
1140 //---------------------------------------------------------------------------
1141 void AliVertexerTracks::VertexFinder(Int_t optUseWeights) 
1142 {
1143
1144   // Get estimate of vertex position in (x,y) from tracks DCA
1145  
1146   Double_t initPos[3];
1147   initPos[2] = 0.;
1148   for(Int_t i=0;i<2;i++)initPos[i]=fNominalPos[i];
1149   Int_t nacc = (Int_t)fTrkArraySel.GetEntriesFast();
1150   Double_t aver[3]={0.,0.,0.};
1151   Double_t aversq[3]={0.,0.,0.};
1152   Double_t sigmasq[3]={0.,0.,0.};
1153   Double_t sigma=0;
1154   Int_t ncombi = 0;
1155   AliExternalTrackParam *track1;
1156   AliExternalTrackParam *track2;
1157   Double_t pos[3],dir[3]; 
1158   Double_t alpha,mindist;
1159
1160   for(Int_t i=0; i<nacc; i++){
1161     track1 = (AliExternalTrackParam*)fTrkArraySel.At(i);
1162     alpha=track1->GetAlpha();
1163     mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
1164     track1->GetXYZAt(mindist,GetFieldkG(),pos);
1165     track1->GetPxPyPzAt(mindist,GetFieldkG(),dir);
1166     AliStrLine *line1 = new AliStrLine(pos,dir); 
1167
1168    //    AliStrLine *line1 = new AliStrLine();
1169    //    track1->ApproximateHelixWithLine(mindist,GetFieldkG(),line1);
1170    
1171     for(Int_t j=i+1; j<nacc; j++){
1172       track2 = (AliExternalTrackParam*)fTrkArraySel.At(j);
1173       alpha=track2->GetAlpha();
1174       mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
1175       track2->GetXYZAt(mindist,GetFieldkG(),pos);
1176       track2->GetPxPyPzAt(mindist,GetFieldkG(),dir);
1177       AliStrLine *line2 = new AliStrLine(pos,dir); 
1178     //      AliStrLine *line2 = new AliStrLine();
1179     //  track2->ApproximateHelixWithLine(mindist,GetFieldkG(),line2);
1180       Double_t distCA=line2->GetDCA(line1);
1181       //printf("%d   %d   %f\n",i,j,distCA);
1182        if(fDCAcut<=0 || (fDCAcut>0&&distCA<fDCAcut)){
1183         Double_t pnt1[3],pnt2[3],crosspoint[3];
1184
1185         if(optUseWeights<=0){
1186           Int_t retcode = line2->Cross(line1,crosspoint);
1187           if(retcode>=0){
1188             ncombi++;
1189             for(Int_t jj=0;jj<3;jj++)aver[jj]+=crosspoint[jj];
1190             for(Int_t jj=0;jj<3;jj++)aversq[jj]+=(crosspoint[jj]*crosspoint[jj]);
1191           }
1192         }
1193         if(optUseWeights>0){
1194           Int_t retcode = line1->CrossPoints(line2,pnt1,pnt2);
1195           if(retcode>=0){
1196             Double_t cs, sn;
1197             alpha=track1->GetAlpha();
1198             cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);   
1199             Double_t sx1=sn*sn*track1->GetSigmaY2(), sy1=cs*cs*track1->GetSigmaY2();
1200             alpha=track2->GetAlpha();
1201             cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);
1202             Double_t sx2=sn*sn*track2->GetSigmaY2(), sy2=cs*cs*track2->GetSigmaY2();
1203             Double_t sz1=track1->GetSigmaZ2(), sz2=track2->GetSigmaZ2();
1204             Double_t wx1=sx2/(sx1+sx2), wx2=1.- wx1;
1205             Double_t wy1=sy2/(sy1+sy2), wy2=1.- wy1;
1206             Double_t wz1=sz2/(sz1+sz2), wz2=1.- wz1;
1207             crosspoint[0]=wx1*pnt1[0] + wx2*pnt2[0]; 
1208             crosspoint[1]=wy1*pnt1[1] + wy2*pnt2[1]; 
1209             crosspoint[2]=wz1*pnt1[2] + wz2*pnt2[2];
1210           
1211             ncombi++;
1212             for(Int_t jj=0;jj<3;jj++)aver[jj]+=crosspoint[jj];
1213             for(Int_t jj=0;jj<3;jj++)aversq[jj]+=(crosspoint[jj]*crosspoint[jj]);
1214           }
1215         }
1216       }
1217       delete line2;
1218     }
1219     delete line1;
1220   }
1221   if(ncombi>0){
1222     for(Int_t jj=0;jj<3;jj++){
1223       initPos[jj] = aver[jj]/ncombi;
1224       //printf("%f\n",initPos[jj]);
1225       aversq[jj]/=ncombi;
1226       sigmasq[jj]=aversq[jj]-initPos[jj]*initPos[jj];
1227       sigma+=sigmasq[jj];
1228     }
1229     sigma=TMath::Sqrt(TMath::Abs(sigma));
1230   }
1231   else {
1232     Warning("VertexFinder","Finder did not succed");
1233     sigma=999;
1234   }
1235   fVert.SetXYZ(initPos);
1236   fVert.SetDispersion(sigma);
1237   fVert.SetNContributors(ncombi);
1238 }
1239 //---------------------------------------------------------------------------
1240 void AliVertexerTracks::VertexFitter() 
1241 {
1242 //
1243 // The optimal estimate of the vertex position is given by a "weighted 
1244 // average of tracks positions".
1245 // Original method: V. Karimaki, CMS Note 97/0051
1246 //
1247   Bool_t useConstraint = fConstraint;
1248   Double_t initPos[3];
1249   if(!fOnlyFitter) {
1250     fVert.GetXYZ(initPos);
1251   } else {
1252     initPos[0]=fNominalPos[0];
1253     initPos[1]=fNominalPos[1];
1254     initPos[2]=fNominalPos[2];
1255   }
1256
1257   Int_t nTrksSel = (Int_t)fTrkArraySel.GetEntries();
1258   if(nTrksSel==1) useConstraint=kTRUE;
1259   if(fDebug) { 
1260     printf("--- VertexFitter(): start\n");
1261     printf(" Number of tracks in array: %d\n",nTrksSel);
1262     printf(" Minimum # tracks required in fit: %d\n",fMinTracks);
1263     printf(" Vertex position after finder: %f,%f,%f\n",initPos[0],initPos[1],initPos[2]);
1264     if(useConstraint) printf(" This vertex will be used in fit: (%f+-%f,%f+-%f)\n",fNominalPos[0],TMath::Sqrt(fNominalCov[0]),fNominalPos[1],TMath::Sqrt(fNominalCov[2])); 
1265   }
1266
1267   // special treatment for few-tracks fits (e.g. secondary vertices)
1268   Bool_t uUi3by3 = kFALSE; if(nTrksSel<5 && !useConstraint) uUi3by3 = kTRUE;
1269
1270   Int_t i,j,k,step=0;
1271   TMatrixD rv(3,1);
1272   TMatrixD vV(3,3);
1273   rv(0,0) = initPos[0];
1274   rv(1,0) = initPos[1];
1275   rv(2,0) = 0.;
1276   Double_t xlStart,alpha;
1277   Int_t nTrksUsed;
1278   Double_t chi2,chi2i,chi2b;
1279   AliExternalTrackParam *t = 0;
1280   Int_t failed = 0;
1281
1282   // initial vertex covariance matrix
1283   TMatrixD vVb(3,3);
1284   vVb(0,0) = fNominalCov[0];
1285   vVb(0,1) = fNominalCov[1];
1286   vVb(0,2) = 0.;
1287   vVb(1,0) = fNominalCov[1];
1288   vVb(1,1) = fNominalCov[2];
1289   vVb(1,2) = 0.;
1290   vVb(2,0) = 0.;
1291   vVb(2,1) = 0.;
1292   vVb(2,2) = fNominalCov[5];
1293   TMatrixD vVbInv(TMatrixD::kInverted,vVb);
1294   TMatrixD rb(3,1);
1295   rb(0,0) = fNominalPos[0];
1296   rb(1,0) = fNominalPos[1];
1297   rb(2,0) = fNominalPos[2];
1298   TMatrixD vVbInvrb(vVbInv,TMatrixD::kMult,rb);
1299
1300
1301   // 2 steps:
1302   // 1st - estimate of vtx using all tracks
1303   // 2nd - estimate of global chi2
1304   for(step=0; step<2; step++) {
1305     if(fDebug) printf(" step = %d\n",step);
1306     chi2 = 0.;
1307     nTrksUsed = 0;
1308
1309     if(step==1) { initPos[0]=rv(0,0); initPos[0]=rv(1,0); }
1310
1311     TMatrixD sumWiri(3,1);
1312     TMatrixD sumWi(3,3);
1313     for(i=0; i<3; i++) {
1314       sumWiri(i,0) = 0.;
1315       for(j=0; j<3; j++) sumWi(j,i) = 0.;
1316     }
1317
1318     // mean vertex constraint
1319     if(useConstraint) {
1320       for(i=0;i<3;i++) {
1321         sumWiri(i,0) += vVbInvrb(i,0);
1322         for(k=0;k<3;k++) sumWi(i,k) += vVbInv(i,k);
1323       }
1324       // chi2
1325       TMatrixD deltar = rv; deltar -= rb;
1326       TMatrixD vVbInvdeltar(vVbInv,TMatrixD::kMult,deltar);
1327       chi2b = deltar(0,0)*vVbInvdeltar(0,0)+
1328               deltar(1,0)*vVbInvdeltar(1,0)+
1329               deltar(2,0)*vVbInvdeltar(2,0);
1330       chi2 += chi2b;
1331     }
1332
1333     // loop on tracks  
1334     for(k=0; k<nTrksSel; k++) {
1335       // get track from track array
1336       t = (AliExternalTrackParam*)fTrkArraySel.At(k);
1337       alpha = t->GetAlpha();
1338       xlStart = initPos[0]*TMath::Cos(alpha)+initPos[1]*TMath::Sin(alpha);
1339       // to vtxSeed (from finder)
1340       t->PropagateTo(xlStart,GetFieldkG());   
1341  
1342       // vector of track global coordinates
1343       TMatrixD ri(3,1);
1344       // covariance matrix of ri
1345       TMatrixD wWi(3,3);
1346
1347       // get space point from track
1348       if(!TrackToPoint(t,ri,wWi,uUi3by3)) continue;
1349       TMatrixD wWiri(wWi,TMatrixD::kMult,ri); 
1350
1351       // track chi2
1352       TMatrixD deltar = rv; deltar -= ri;
1353       TMatrixD wWideltar(wWi,TMatrixD::kMult,deltar);
1354       chi2i = deltar(0,0)*wWideltar(0,0)+
1355               deltar(1,0)*wWideltar(1,0)+
1356               deltar(2,0)*wWideltar(2,0);
1357
1358       // add to total chi2
1359       chi2 += chi2i;
1360
1361       sumWiri += wWiri;
1362       sumWi   += wWi;
1363
1364       nTrksUsed++;
1365     } // end loop on tracks
1366
1367     if(nTrksUsed < fMinTracks) {
1368       failed=1;
1369       continue;
1370     }
1371
1372     Double_t determinant = sumWi.Determinant();
1373     if(determinant < fMinDetFitter)  { 
1374       printf("det(V) = %f (<%f)\n",determinant,fMinDetFitter);       
1375       failed=1;
1376       continue;
1377     }
1378
1379     if(step==0) { 
1380       // inverted of weights matrix
1381       TMatrixD invsumWi(TMatrixD::kInverted,sumWi);
1382       vV = invsumWi;
1383       // position of primary vertex
1384       rv.Mult(vV,sumWiri);
1385     }
1386   } // end loop on the 2 steps
1387
1388   if(failed) { 
1389     TooFewTracks();
1390     return; 
1391   }
1392
1393   Double_t position[3];
1394   position[0] = rv(0,0);
1395   position[1] = rv(1,0);
1396   position[2] = rv(2,0);
1397   Double_t covmatrix[6];
1398   covmatrix[0] = vV(0,0);
1399   covmatrix[1] = vV(0,1);
1400   covmatrix[2] = vV(1,1);
1401   covmatrix[3] = vV(0,2);
1402   covmatrix[4] = vV(1,2);
1403   covmatrix[5] = vV(2,2);
1404   
1405   // for correct chi2/ndf, count constraint as additional "track"
1406   if(fConstraint) nTrksUsed++;
1407   // store data in the vertex object
1408   fCurrentVertex = new AliESDVertex(position,covmatrix,chi2,nTrksUsed);
1409
1410   if(fDebug) {
1411     printf(" Vertex after fit:\n");
1412     fCurrentVertex->PrintStatus();
1413     printf("--- VertexFitter(): finish\n");
1414   }
1415
1416   return;
1417 }
1418 //----------------------------------------------------------------------------
1419 AliESDVertex* AliVertexerTracks::VertexForSelectedTracks(TObjArray *trkArray,
1420                                                          UShort_t *id,
1421                                                          Bool_t optUseFitter,
1422                                                          Bool_t optPropagate) 
1423 {
1424 //
1425 // Return vertex from tracks (AliExternalTrackParam) in array
1426 //
1427
1428   SetConstraintOff();
1429
1430   // get tracks and propagate them to initial vertex position
1431   fIdSel = new UShort_t[(Int_t)trkArray->GetEntriesFast()];
1432   Int_t nTrksSel = PrepareTracks(*trkArray,id,0);
1433   if(nTrksSel <  TMath::Max(2,fMinTracks)) {
1434     TooFewTracks();
1435     return fCurrentVertex;
1436   }
1437  
1438   // vertex finder
1439   switch (fAlgo) {
1440     case 1: StrLinVertexFinderMinDist(1); break;
1441     case 2: StrLinVertexFinderMinDist(0); break;
1442     case 3: HelixVertexFinder();          break;
1443     case 4: VertexFinder(1);              break;
1444     case 5: VertexFinder(0);              break;
1445     default: printf("Wrong algorithm\n"); break;  
1446   }
1447   if(fDebug) printf(" Vertex finding completed\n");
1448
1449   // vertex fitter
1450   if(optUseFitter) {
1451     VertexFitter();
1452   } else {
1453     Double_t position[3]={fVert.GetXv(),fVert.GetYv(),fVert.GetZv()};
1454     Double_t covmatrix[6];
1455     fVert.GetCovMatrix(covmatrix);
1456     Double_t chi2=99999.;
1457     Int_t    nTrksUsed=fVert.GetNContributors();
1458     fCurrentVertex = new AliESDVertex(position,covmatrix,chi2,nTrksUsed);    
1459   }
1460   fCurrentVertex->SetDispersion(fVert.GetDispersion());
1461
1462
1463   // set indices of used tracks and propagate track to found vertex
1464   UShort_t *indices = 0;
1465   Double_t d0z0[2],covd0z0[3];
1466   AliExternalTrackParam *t = 0;
1467   if(fCurrentVertex->GetNContributors()>0) {
1468     indices = new UShort_t[fCurrentVertex->GetNContributors()];
1469     for(Int_t jj=0; jj<(Int_t)fTrkArraySel.GetEntriesFast(); jj++) {
1470       indices[jj] = fIdSel[jj];
1471       t = (AliExternalTrackParam*)fTrkArraySel.At(jj);
1472       if(optPropagate && optUseFitter) {
1473         if(TMath::Sqrt(fCurrentVertex->GetXv()*fCurrentVertex->GetXv()+fCurrentVertex->GetYv()*fCurrentVertex->GetYv())<3.) {
1474           t->PropagateToDCA(fCurrentVertex,GetFieldkG(),100.,d0z0,covd0z0);
1475           if(fDebug) printf("Track %d propagated to found vertex\n",jj);
1476         } else {
1477           AliWarning("Found vertex outside beam pipe!");
1478         }
1479       }
1480     }
1481     fCurrentVertex->SetIndices(fCurrentVertex->GetNContributors(),indices);
1482   }
1483
1484   // clean up
1485   delete [] indices; indices=NULL;
1486   delete [] fIdSel; fIdSel=NULL;
1487   fTrkArraySel.Delete();
1488   
1489   return fCurrentVertex;
1490 }
1491 //----------------------------------------------------------------------------
1492 AliESDVertex* AliVertexerTracks::VertexForSelectedESDTracks(TObjArray *trkArray,
1493                                                          Bool_t optUseFitter,
1494                                                          Bool_t optPropagate) 
1495 {
1496 //
1497 // Return vertex from array of ESD tracks
1498 //
1499
1500   Int_t nTrks = (Int_t)trkArray->GetEntriesFast();
1501   UShort_t *id = new UShort_t[nTrks];
1502
1503   AliESDtrack *esdt = 0;
1504   for(Int_t i=0; i<nTrks; i++){
1505     esdt = (AliESDtrack*)trkArray->At(i);
1506     id[i] = (UShort_t)esdt->GetID();
1507   }
1508     
1509   VertexForSelectedTracks(trkArray,id,optUseFitter,optPropagate);
1510
1511   delete [] id; id=NULL;
1512
1513   return fCurrentVertex;
1514 }
1515 //--------------------------------------------------------------------------