LCOV - code coverage report
Current view: top level - STEER/ESD - AliVertexerTracks.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 722 1359 53.1 %
Date: 2016-06-14 17:26:59 Functions: 25 38 65.8 %

          Line data    Source code
       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 <TClonesArray.h>
      31             : #include <TDirectory.h>
      32             : #include <TFile.h>
      33             : //---- AliRoot headers -----
      34             : #include "AliStrLine.h"
      35             : #include "AliExternalTrackParam.h"
      36             : #include "AliNeutralTrackParam.h"
      37             : #include "AliVEvent.h"
      38             : #include "AliVTrack.h"
      39             : #include "AliESDtrack.h"
      40             : #include "AliESDEvent.h"
      41             : #include "AliVertexerTracks.h"
      42             : 
      43             : 
      44         172 : ClassImp(AliVertexerTracks)
      45             : 
      46             : 
      47             : //----------------------------------------------------------------------------
      48             : AliVertexerTracks::AliVertexerTracks():
      49           0 : TObject(),
      50           0 : fVert(),
      51           0 : fCurrentVertex(0),
      52           0 : fMode(0),
      53           0 : fFieldkG(-999.),
      54           0 : fTrkArraySel(),
      55           0 : fIdSel(0),
      56           0 : fTrksToSkip(0),
      57           0 : fNTrksToSkip(0),
      58           0 : fConstraint(kFALSE),
      59           0 : fOnlyFitter(kFALSE),
      60           0 : fMinTracks(1),
      61           0 : fMinClusters(3),
      62           0 : fDCAcut(0.1),
      63           0 : fDCAcutIter0(0.1),
      64           0 : fNSigma(3.),
      65           0 : fMaxd0z0(0.5),
      66           0 : fMinDetFitter(100.),
      67           0 : fMaxTgl(1000.),
      68           0 : fITSrefit(kTRUE),
      69           0 : fITSpureSA(kFALSE),
      70           0 : fFiducialR(3.),
      71           0 : fFiducialZ(30.),
      72           0 : fnSigmaForUi00(1.5),
      73           0 : fAlgo(1),
      74           0 : fAlgoIter0(4),
      75           0 : fSelectOnTOFBunchCrossing(kFALSE), 
      76           0 : fKeepAlsoUnflaggedTOFBunchCrossing(kTRUE),
      77           0 : fMVWSum(0),
      78           0 : fMVWE2(0),
      79           0 : fMVTukey2(6.),
      80           0 : fMVSigma2(1.),
      81           0 : fMVSig2Ini(1.e3),
      82           0 : fMVMaxSigma2(3.),
      83           0 : fMVMinSig2Red(0.005),
      84           0 : fMVMinDst(10.e-4),
      85           0 : fMVScanStep(3.),
      86           0 : fMVMaxWghNtr(10.),
      87           0 : fMVFinalWBinary(kTRUE),
      88           0 : fBCSpacing(50),
      89           0 : fMVVertices(0),
      90           0 : fDisableBCInCPass0(kTRUE),
      91           0 : fClusterize(kFALSE),
      92           0 : fDeltaZCutForCluster(0.1),
      93           0 : fnSigmaZCutForCluster(999999.)
      94           0 : {
      95             : //
      96             : // Default constructor
      97             : //
      98           0 :   SetVtxStart();
      99           0 :   SetVtxStartSigma();
     100           0 : }
     101             : //----------------------------------------------------------------------------
     102             : AliVertexerTracks::AliVertexerTracks(Double_t fieldkG):
     103           2 : TObject(),
     104           2 : fVert(),
     105           2 : fCurrentVertex(0),
     106           2 : fMode(0),
     107           2 : fFieldkG(fieldkG),
     108           2 : fTrkArraySel(),
     109           2 : fIdSel(0),
     110           2 : fTrksToSkip(0),
     111           2 : fNTrksToSkip(0),
     112           2 : fConstraint(kFALSE),
     113           2 : fOnlyFitter(kFALSE),
     114           2 : fMinTracks(1),
     115           2 : fMinClusters(3),
     116           2 : fDCAcut(0.1),
     117           2 : fDCAcutIter0(0.1),
     118           2 : fNSigma(3.),
     119           2 : fMaxd0z0(0.5),
     120           2 : fMinDetFitter(100.),
     121           2 : fMaxTgl(1000.),
     122           2 : fITSrefit(kTRUE),
     123           2 : fITSpureSA(kFALSE),
     124           2 : fFiducialR(3.),
     125           2 : fFiducialZ(30.),
     126           2 : fnSigmaForUi00(1.5),
     127           2 : fAlgo(1),
     128           2 : fAlgoIter0(4),
     129           2 : fSelectOnTOFBunchCrossing(kFALSE), 
     130           2 : fKeepAlsoUnflaggedTOFBunchCrossing(kTRUE),
     131           2 : fMVWSum(0),
     132           2 : fMVWE2(0),
     133           2 : fMVTukey2(6.),
     134           2 : fMVSigma2(1.),
     135           2 : fMVSig2Ini(1.e3),
     136           2 : fMVMaxSigma2(3.),
     137           2 : fMVMinSig2Red(0.005),
     138           2 : fMVMinDst(10.e-4),
     139           2 : fMVScanStep(3.),
     140           2 : fMVMaxWghNtr(10.),
     141           2 : fMVFinalWBinary(kTRUE),
     142           2 : fBCSpacing(50),
     143           2 : fMVVertices(0),
     144           2 : fDisableBCInCPass0(kTRUE),
     145           2 : fClusterize(kFALSE),
     146           2 : fDeltaZCutForCluster(0.1),
     147           2 : fnSigmaZCutForCluster(999999.)
     148          10 : {
     149             : //
     150             : // Standard constructor
     151             : //
     152           2 :   SetVtxStart();
     153           2 :   SetVtxStartSigma();
     154           4 : }
     155             : //-----------------------------------------------------------------------------
     156             : AliVertexerTracks::~AliVertexerTracks() 
     157          12 : {
     158             :   // Default Destructor
     159             :   // The objects pointed by the following pointer are not owned
     160             :   // by this class and are not deleted
     161           2 :   fCurrentVertex = 0;
     162           2 :   if(fTrksToSkip) { delete [] fTrksToSkip; fTrksToSkip=NULL; fNTrksToSkip=0;}
     163           2 :   if(fIdSel) { delete [] fIdSel; fIdSel=NULL; }
     164           6 :   if(fMVVertices) delete fMVVertices;
     165           6 : }
     166             : 
     167             : //----------------------------------------------------------------------------
     168             : AliESDVertex* AliVertexerTracks::FindPrimaryVertex(const AliVEvent *vEvent)
     169             : {
     170             : //
     171             : // Primary vertex for current ESD or AOD event
     172             : // (Two iterations: 
     173             : //  1st with 5*fNSigma*sigma cut w.r.t. to initial vertex
     174             : //      + cut on sqrt(d0d0+z0z0) if fConstraint=kFALSE  
     175             : //  2nd with fNSigma*sigma cut w.r.t. to vertex found in 1st iteration) 
     176             : //
     177          16 :   fCurrentVertex = 0;
     178           8 :   TString evtype = vEvent->IsA()->GetName();
     179          16 :   Bool_t inputAOD = ((evtype=="AliAODEvent") ? kTRUE : kFALSE);
     180             : 
     181           8 :   if(inputAOD && fMode==1) {
     182           0 :     printf("Error : AliVertexerTracks: no TPC-only vertex from AOD\n"); 
     183           0 :     TooFewTracks(); 
     184           0 :     return fCurrentVertex;
     185             :   }
     186             : 
     187             :   // accept 1-track case only if constraint is available
     188           8 :   if(!fConstraint && fMinTracks==1) fMinTracks=2;
     189             : 
     190             :   // read tracks from AlivEvent
     191           8 :   Int_t nTrks = (Int_t)vEvent->GetNumberOfTracks();
     192           8 :   if(nTrks<fMinTracks) {
     193           0 :     TooFewTracks();
     194           0 :     return fCurrentVertex;
     195             :   } 
     196             :   //
     197           8 :   int bcRound = fBCSpacing/25;   // profit from larger than 25ns spacing and set correct BC
     198           8 :   TDirectory * olddir = gDirectory;
     199             :   //  TFile *f = 0;
     200             :   //  if(nTrks>500) f = new TFile("VertexerTracks.root","recreate");
     201           8 :   TObjArray trkArrayOrig(nTrks);
     202          16 :   UShort_t *idOrig = new UShort_t[nTrks];
     203          16 :   Double_t *zTr = new Double_t[nTrks];
     204          16 :   Double_t *err2zTr = new Double_t[nTrks];
     205             : 
     206             :   Int_t nTrksOrig=0;
     207             :   AliExternalTrackParam *t=0;
     208             :   // loop on tracks
     209         320 :   for(Int_t i=0; i<nTrks; i++) {
     210         304 :     AliVTrack *track = (AliVTrack*)vEvent->GetTrack(i);
     211             :     // check tracks to skip
     212             :     Bool_t skipThis = kFALSE;
     213         304 :     for(Int_t j=0; j<fNTrksToSkip; j++) { 
     214           0 :       if(track->GetID()==fTrksToSkip[j]) {
     215           0 :         AliDebug(1,Form("skipping track: %d",i));
     216             :         skipThis = kTRUE;
     217           0 :       }
     218             :     }
     219         152 :     if(skipThis) continue;
     220             : 
     221             :     // skip pure ITS SA tracks (default)
     222         456 :     if(!fITSpureSA && (track->GetStatus()&AliESDtrack::kITSpureSA)) continue;
     223             :     // or use only pure ITS SA tracks
     224         152 :     if(fITSpureSA && !(track->GetStatus()&AliESDtrack::kITSpureSA)) continue;
     225             : 
     226             :     // kITSrefit
     227         668 :     if(fMode==0 && fITSrefit && !(track->GetStatus()&AliESDtrack::kITSrefit)) continue;
     228             : 
     229          92 :     if(!inputAOD) {  // ESD
     230          92 :       AliESDtrack* esdt = (AliESDtrack*)track;
     231         184 :       if(esdt->GetNcls(fMode) < fMinClusters) continue;
     232          92 :       if(fMode==0) {        // ITS mode
     233          92 :         Double_t x,p[5],cov[15];
     234          92 :         esdt->GetExternalParameters(x,p);
     235          92 :         esdt->GetExternalCovariance(cov);
     236         276 :         t = new AliExternalTrackParam(x,esdt->GetAlpha(),p,cov);
     237          92 :       } else if(fMode==1) { // TPC mode
     238           0 :         t = (AliExternalTrackParam*)esdt->GetTPCInnerParam();
     239           0 :         if(!t) continue;
     240             :         Double_t radius = 2.8; //something less than the beam pipe radius
     241           0 :         if(!PropagateTrackTo(t,radius)) continue;
     242           0 :       }
     243          92 :     } else {          // AOD (only ITS mode)
     244           0 :       if(track->GetID()<0) continue; // exclude global constrained and TPC only tracks (filter bits 128 and 512)
     245             :       Int_t ncls0=0;
     246           0 :       for(Int_t l=0;l<6;l++) if(TESTBIT(track->GetITSClusterMap(),l)) ncls0++;
     247           0 :       if(ncls0 < fMinClusters) continue;
     248           0 :       t = new AliExternalTrackParam(); t->CopyFromVTrack(track);
     249           0 :     }
     250             : 
     251             :     // use TOF info about bunch crossing
     252          92 :     if(fSelectOnTOFBunchCrossing) {
     253          92 :       double tdiff = track->GetTOFExpTDiff(fFieldkG);
     254          92 :       int bc = TMath::Nint(tdiff/25);
     255             :       // use only values with good margin
     256         184 :       if (bc<=AliVTrack::kTOFBCNA || TMath::Abs(tdiff/25.-bc)>0.4) bc = AliVTrack::kTOFBCNA;
     257          59 :       else bc /= bcRound;
     258          92 :       t->SetUniqueID(UInt_t(bc + kTOFBCShift));
     259          92 :     }
     260             :     //
     261          92 :     trkArrayOrig.AddLast(t);
     262         184 :     idOrig[nTrksOrig]=(UShort_t)track->GetID();
     263         184 :     zTr[nTrksOrig]=t->GetZ();
     264          92 :     err2zTr[nTrksOrig]=t->GetSigmaZ2();
     265             : 
     266          92 :     nTrksOrig++;
     267          92 :   } // end loop on tracks
     268             :   
     269             :   // call method that will reconstruct the vertex
     270           8 :   if(fClusterize) FindAllVertices(nTrksOrig,&trkArrayOrig,zTr,err2zTr,idOrig);
     271           8 :   else FindPrimaryVertex(&trkArrayOrig,idOrig);
     272          16 :   if(!inputAOD) AnalyzePileUp((AliESDEvent*)vEvent);
     273             : 
     274          16 :   if(fMode==0) trkArrayOrig.Delete();
     275          16 :   delete [] idOrig; idOrig=NULL;
     276          16 :   delete [] zTr; zTr=NULL;
     277          16 :   delete [] err2zTr; err2zTr=NULL;
     278             : 
     279             :   /*
     280             :   if(f) {
     281             :     f->Close(); delete f; f = NULL;
     282             :     gSystem->Unlink("VertexerTracks.root");
     283             :     olddir->cd();
     284             :   }
     285             :   */
     286             :   // set vertex ID for tracks used in the fit
     287             :   // (only for ESD)
     288          16 :   if(!inputAOD && fCurrentVertex) {
     289           8 :     Int_t nIndices = fCurrentVertex->GetNIndices();
     290           8 :     UShort_t *indices = fCurrentVertex->GetIndices();
     291         192 :     for(Int_t ind=0; ind<nIndices; ind++) {
     292         176 :       AliESDtrack *esdt = (AliESDtrack*)vEvent->GetTrack(indices[ind]);
     293          88 :       esdt->SetVertexID(-1);
     294             :     }
     295           8 :   }
     296             :  
     297           8 :   return fCurrentVertex;
     298          16 : }
     299             : //----------------------------------------------------------------------------
     300             : AliESDVertex* AliVertexerTracks::FindPrimaryVertex(const TObjArray *trkArrayOrig,
     301             :                                                    UShort_t *idOrig)
     302             : {
     303             : //
     304             : // Primary vertex using the AliExternalTrackParam's in the TObjArray.
     305             : // idOrig must contain the track IDs from AliESDtrack::GetID()
     306             : // (Two iterations: 
     307             : //  1st with 5*fNSigma*sigma cut w.r.t. to initial vertex
     308             : //      + cut on sqrt(d0d0+z0z0) if fConstraint=kFALSE  
     309             : //  2nd with fNSigma*sigma cut w.r.t. to vertex found in 1st iteration) 
     310             : //
     311          32 :   fCurrentVertex = 0;
     312             :   // accept 1-track case only if constraint is available
     313          16 :   if(!fConstraint && fMinTracks==1) fMinTracks=2;
     314             : 
     315             :   // read tracks from array
     316          16 :   Int_t nTrksOrig = (Int_t)trkArrayOrig->GetEntriesFast();
     317          48 :   AliDebug(1,Form("Initial number of tracks: %d",nTrksOrig));
     318          16 :   if(nTrksOrig<fMinTracks) {
     319           0 :     AliDebug(1,"TooFewTracks");
     320           0 :     TooFewTracks();
     321           0 :     return fCurrentVertex;
     322             :   } 
     323             : 
     324             :   // If fConstraint=kFALSE
     325             :   // run VertexFinder(1) to get rough estimate of initVertex (x,y)
     326          16 :   if(!fConstraint) {
     327             :     // fill fTrkArraySel, for VertexFinder()
     328           0 :     fIdSel = new UShort_t[nTrksOrig];
     329           0 :     PrepareTracks(*trkArrayOrig,idOrig,0);
     330           0 :     if(fIdSel) { delete [] fIdSel; fIdSel=NULL; }
     331           0 :     Double_t cutsave = fDCAcut;  
     332           0 :     fDCAcut = fDCAcutIter0;
     333             :     // vertex finder
     334           0 :     switch (fAlgoIter0) {
     335           0 :     case 1: StrLinVertexFinderMinDist(1); break;
     336           0 :     case 2: StrLinVertexFinderMinDist(0); break;
     337           0 :     case 3: HelixVertexFinder();          break;
     338           0 :     case 4: VertexFinder(1);              break;
     339           0 :     case 5: VertexFinder(0);              break;
     340           0 :     default: {AliFatal(Form("Wrong seeder algorithm %d",fAlgoIter0));} break;  
     341             :     }
     342           0 :     fDCAcut = cutsave;
     343           0 :     if(fVert.GetNContributors()>0) {
     344           0 :       fVert.GetXYZ(fNominalPos);
     345           0 :       fNominalPos[0] = fVert.GetX();
     346           0 :       fNominalPos[1] = fVert.GetY();
     347           0 :       fNominalPos[2] = fVert.GetZ();
     348           0 :       AliDebug(1,Form("No mean vertex: VertexFinder gives (%f, %f, %f)",fNominalPos[0],fNominalPos[1],fNominalPos[2]));
     349             :     } else {
     350           0 :       fNominalPos[0] = 0.;
     351           0 :       fNominalPos[1] = 0.;
     352           0 :       fNominalPos[2] = 0.;
     353           0 :       AliDebug(1,"No mean vertex and VertexFinder failed");
     354             :     }
     355           0 :   }
     356             :   
     357             :   // TWO ITERATIONS:
     358             :   //
     359             :   // ITERATION 1
     360             :   // propagate tracks to fNominalPos vertex
     361             :   // preselect them:
     362             :   // if(constraint) reject for |d0|>5*fNSigma*sigma w.r.t. fNominal... vertex
     363             :   // else  reject for |d0|\oplus|z0| > 5 mm w.r.t. fNominal... vertex
     364             :   // ITERATION 2
     365             :   // propagate tracks to best between initVertex and fCurrentVertex
     366             :   // preselect tracks (reject for |d0|>fNSigma*sigma w.r.t. best 
     367             :   //                   between initVertex and fCurrentVertex) 
     368             :   Bool_t multiMode = kFALSE;
     369          72 :   for(Int_t iter=1; iter<=2; iter++) {
     370          24 :     if (fAlgo==kMultiVertexer && iter==2) break; // multivertexer does not need 2 iterations
     371          24 :     if(fOnlyFitter && iter==1) continue; 
     372          48 :     if(fIdSel) { delete [] fIdSel; fIdSel=NULL; }
     373          24 :     fIdSel = new UShort_t[nTrksOrig];
     374          24 :     Int_t nTrksSel = PrepareTracks(*trkArrayOrig,idOrig,iter);
     375          72 :     AliDebug(1,Form("N tracks selected in iteration %d: %d",iter,nTrksSel));
     376          24 :     if(nTrksSel < fMinTracks) {
     377           0 :       TooFewTracks();
     378           0 :       return fCurrentVertex; 
     379             :     }
     380             : 
     381             :     // vertex finder
     382          24 :     if(!fOnlyFitter) {
     383          24 :       if(nTrksSel==1 && fAlgo!=kMultiVertexer) {
     384           0 :         AliDebug(1,"Just one track");
     385           0 :         OneTrackVertFinder();
     386           0 :       } else {
     387          24 :         switch (fAlgo) {
     388          16 :         case kStrLinVertexFinderMinDist1: StrLinVertexFinderMinDist(1); break;
     389           0 :         case kStrLinVertexFinderMinDist0: StrLinVertexFinderMinDist(0); break;
     390           0 :         case kHelixVertexFinder         : HelixVertexFinder();          break;
     391           0 :         case kVertexFinder1             : VertexFinder(1);              break;
     392           0 :         case kVertexFinder0             : VertexFinder(0);              break;
     393           8 :         case kMultiVertexer             : FindVerticesMV(); multiMode = kTRUE; break;
     394           0 :         default: {AliFatal(Form("Wrong vertexer algorithm %d",fAlgo));} break;  
     395             :         }
     396             :       }
     397          72 :       AliDebug(1," Vertex finding completed");
     398             :     }
     399          32 :     if (multiMode) break; // // multivertexer does not need 2nd iteration
     400             :     // vertex fitter
     401          16 :     VertexFitter();
     402          16 :   } // end loop on the two iterations
     403             : 
     404          24 :   if (!multiMode || fMVVertices->GetEntries()==0) { // in multi-vertex mode this is already done for found vertices
     405             :     // set indices of used tracks
     406             :     UShort_t *indices = 0;
     407           8 :     if(fCurrentVertex->GetNContributors()>0) {
     408           8 :       Int_t nIndices = (Int_t)fTrkArraySel.GetEntriesFast();
     409           8 :       indices = new UShort_t[nIndices];
     410         180 :       for(Int_t jj=0; jj<nIndices; jj++)
     411          82 :         indices[jj] = fIdSel[jj];
     412           8 :       fCurrentVertex->SetIndices(nIndices,indices);
     413           8 :     }
     414          32 :     if (indices) {delete [] indices; indices=NULL;}
     415             :     //
     416             :     // set vertex title
     417           8 :     TString title="VertexerTracksNoConstraint";
     418           8 :     if(fConstraint) {
     419           8 :       title="VertexerTracksWithConstraint";
     420           8 :       if(fOnlyFitter) title.Append("OnlyFitter");
     421             :     }
     422          16 :     fCurrentVertex->SetTitle(title.Data());
     423             :     //
     424          40 :     AliDebug(1,Form("xyz: %f %f %f; nc %d",fCurrentVertex->GetX(),fCurrentVertex->GetY(),fCurrentVertex->GetZ(),fCurrentVertex->GetNContributors()));
     425           8 :   }
     426             :   // clean up
     427          48 :   delete [] fIdSel; fIdSel=NULL;
     428          16 :   fTrkArraySel.Delete();
     429          16 :   if(fTrksToSkip) { delete [] fTrksToSkip; fTrksToSkip=NULL; }
     430             :   //
     431             :   
     432          16 :   return fCurrentVertex;
     433          16 : }
     434             : //------------------------------------------------------------------------
     435             : Double_t AliVertexerTracks::GetDeterminant3X3(Double_t matr[][3])
     436             : {
     437             :   //
     438         384 :   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];
     439         192 :  return det;
     440             : }
     441             : //-------------------------------------------------------------------------
     442             : void AliVertexerTracks::GetStrLinDerivMatrix(const Double_t *p0,const Double_t *p1,Double_t (*m)[3],Double_t *d)
     443             : {
     444             :   //
     445         384 :   Double_t x12=p0[0]-p1[0];
     446         192 :   Double_t y12=p0[1]-p1[1];
     447         192 :   Double_t z12=p0[2]-p1[2];
     448         192 :   Double_t kk=x12*x12+y12*y12+z12*z12;
     449         192 :   m[0][0]=2-2/kk*x12*x12;
     450         192 :   m[0][1]=-2/kk*x12*y12;
     451         192 :   m[0][2]=-2/kk*x12*z12;
     452         192 :   m[1][0]=-2/kk*x12*y12;
     453         192 :   m[1][1]=2-2/kk*y12*y12;
     454         192 :   m[1][2]=-2/kk*y12*z12;
     455         192 :   m[2][0]=-2/kk*x12*z12;
     456         192 :   m[2][1]=-2/kk*y12*z12;
     457         192 :   m[2][2]=2-2/kk*z12*z12;
     458         192 :   d[0]=2*p0[0]-2/kk*p0[0]*x12*x12-2/kk*p0[2]*x12*z12-2/kk*p0[1]*x12*y12;
     459         192 :   d[1]=2*p0[1]-2/kk*p0[1]*y12*y12-2/kk*p0[0]*x12*y12-2/kk*p0[2]*z12*y12;
     460         192 :   d[2]=2*p0[2]-2/kk*p0[2]*z12*z12-2/kk*p0[0]*x12*z12-2/kk*p0[1]*z12*y12;
     461             : 
     462         192 : }
     463             : //--------------------------------------------------------------------------  
     464             : void AliVertexerTracks::GetStrLinDerivMatrix(const Double_t *p0,const Double_t *p1,const Double_t *sigmasq,Double_t (*m)[3],Double_t *d)
     465             : {
     466             :   //
     467         360 :   Double_t x12=p1[0]-p0[0];
     468         180 :   Double_t y12=p1[1]-p0[1];
     469         180 :   Double_t z12=p1[2]-p0[2];
     470             : 
     471         180 :   Double_t den= x12*x12*sigmasq[1]*sigmasq[2]+y12*y12*sigmasq[0]*sigmasq[2]+z12*z12*sigmasq[0]*sigmasq[1];
     472             : 
     473         180 :   Double_t kk= 2*(x12*x12/sigmasq[0]+y12*y12/sigmasq[1]+z12*z12/sigmasq[2]);
     474             : 
     475             :   Double_t cc[3];
     476         180 :   cc[0]=-x12/sigmasq[0];
     477         180 :   cc[1]=-y12/sigmasq[1];
     478         180 :   cc[2]=-z12/sigmasq[2];
     479             : 
     480         180 :   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;
     481             : 
     482         180 :   Double_t ss= -p0[0]*cc[0]-p0[1]*cc[1]-p0[2]*cc[2];
     483             : 
     484             :   Double_t aa[3];
     485         180 :   aa[0]=x12*sigmasq[1]*sigmasq[2]/den;
     486         180 :   aa[1]=y12*sigmasq[0]*sigmasq[2]/den;
     487         180 :   aa[2]=z12*sigmasq[0]*sigmasq[1]/den;
     488             : 
     489         180 :   m[0][0]=aa[0]*(aa[0]*kk+2*cc[0])+2*cc[0]*aa[0]+2/sigmasq[0];
     490         180 :   m[0][1]=aa[1]*(aa[0]*kk+2*cc[0])+2*cc[1]*aa[0];
     491         180 :   m[0][2]=aa[2]*(aa[0]*kk+2*cc[0])+2*cc[2]*aa[0];
     492             : 
     493         180 :   m[1][0]=aa[0]*(aa[1]*kk+2*cc[1])+2*cc[0]*aa[1];
     494         180 :   m[1][1]=aa[1]*(aa[1]*kk+2*cc[1])+2*cc[1]*aa[1]+2/sigmasq[1];
     495         180 :   m[1][2]=aa[2]*(aa[1]*kk+2*cc[1])+2*cc[2]*aa[1];
     496             : 
     497         180 :   m[2][0]=aa[0]*(aa[2]*kk+2*cc[2])+2*cc[0]*aa[2];
     498         180 :   m[2][1]=aa[1]*(aa[2]*kk+2*cc[2])+2*cc[1]*aa[2];
     499         180 :   m[2][2]=aa[2]*(aa[2]*kk+2*cc[2])+2*cc[2]*aa[2]+2/sigmasq[2];
     500             : 
     501         180 :   d[0]=-ww*(aa[0]*kk+2*cc[0])-2*ss*aa[0]+2*p0[0]/sigmasq[0];
     502         180 :   d[1]=-ww*(aa[1]*kk+2*cc[1])-2*ss*aa[1]+2*p0[1]/sigmasq[1];
     503         180 :   d[2]=-ww*(aa[2]*kk+2*cc[2])-2*ss*aa[2]+2*p0[2]/sigmasq[2];
     504             : 
     505         180 :   }
     506             : //--------------------------------------------------------------------------   
     507             : Double_t AliVertexerTracks::GetStrLinMinDist(const Double_t *p0,const Double_t *p1,const Double_t *x0)
     508             : {
     509             :   //
     510         744 :   Double_t x12=p0[0]-p1[0];
     511         372 :   Double_t y12=p0[1]-p1[1];
     512         372 :   Double_t z12=p0[2]-p1[2];
     513         372 :   Double_t x10=p0[0]-x0[0];
     514         372 :   Double_t y10=p0[1]-x0[1];
     515         372 :   Double_t z10=p0[2]-x0[2];
     516             :   //  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);
     517        1116 :   return ((y10*z12-z10*y12)*(y10*z12-z10*y12)+
     518         744 :           (z10*x12-x10*z12)*(z10*x12-x10*z12)+
     519         372 :           (x10*y12-y10*x12)*(x10*y12-y10*x12))
     520         372 :     /(x12*x12+y12*y12+z12*z12);
     521             : }
     522             : //---------------------------------------------------------------------------
     523             : void AliVertexerTracks::OneTrackVertFinder() 
     524             : {
     525             :   // find vertex for events with 1 track, using DCA to nominal beam axis
     526           0 :   AliDebug(1,Form("Number of prepared tracks =%d - Call OneTrackVertFinder",fTrkArraySel.GetEntries()));
     527             :   AliExternalTrackParam *track1;
     528           0 :   track1 = (AliExternalTrackParam*)fTrkArraySel.At(0);
     529           0 :   Double_t alpha=track1->GetAlpha();
     530           0 :   Double_t mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
     531           0 :   Double_t pos[3],dir[3]; 
     532           0 :   track1->GetXYZAt(mindist,GetFieldkG(),pos);
     533           0 :   track1->GetPxPyPzAt(mindist,GetFieldkG(),dir);
     534           0 :   AliStrLine *line1 = new AliStrLine(pos,dir);
     535           0 :   Double_t p1[3]={fNominalPos[0],fNominalPos[1],0.}; 
     536           0 :   Double_t p2[3]={fNominalPos[0],fNominalPos[1],10.}; 
     537           0 :   AliStrLine *zeta=new AliStrLine(p1,p2,kTRUE);
     538           0 :   Double_t crosspoint[3]={0.,0.,0.};
     539             :   Double_t sigma=999.;
     540             :   Int_t nContrib=-1;
     541           0 :   Int_t retcode = zeta->Cross(line1,crosspoint);
     542           0 :   if(retcode>=0){
     543           0 :     sigma=line1->GetDistFromPoint(crosspoint);
     544             :     nContrib=1;
     545           0 :   }
     546           0 :   delete zeta;
     547           0 :   delete line1;
     548           0 :   fVert.SetXYZ(crosspoint);
     549           0 :   fVert.SetDispersion(sigma);
     550           0 :   fVert.SetNContributors(nContrib);  
     551           0 : }
     552             : //---------------------------------------------------------------------------
     553             : void AliVertexerTracks::HelixVertexFinder() 
     554             : {
     555             :   // Get estimate of vertex position in (x,y) from tracks DCA
     556             : 
     557             : 
     558           0 :   Double_t initPos[3];
     559           0 :   initPos[2] = 0.;
     560           0 :   for(Int_t i=0;i<2;i++)initPos[i]=fNominalPos[i];
     561             : 
     562           0 :   Int_t nacc = (Int_t)fTrkArraySel.GetEntriesFast();
     563             : 
     564           0 :   Double_t aver[3]={0.,0.,0.};
     565           0 :   Double_t averquad[3]={0.,0.,0.};
     566           0 :   Double_t sigmaquad[3]={0.,0.,0.};
     567             :   Double_t sigma=0;
     568             :   Int_t ncombi = 0;
     569             :   AliExternalTrackParam *track1;
     570             :   AliExternalTrackParam *track2;
     571             :   Double_t distCA;
     572             :   Double_t x;
     573             :   Double_t alpha, cs, sn;
     574           0 :   Double_t crosspoint[3];
     575           0 :   for(Int_t i=0; i<nacc; i++){
     576           0 :     track1 = (AliExternalTrackParam*)fTrkArraySel.At(i);
     577             :     
     578             : 
     579           0 :     for(Int_t j=i+1; j<nacc; j++){
     580           0 :       track2 = (AliExternalTrackParam*)fTrkArraySel.At(j);
     581             : 
     582           0 :       distCA=track2->PropagateToDCA(track1,GetFieldkG());
     583           0 :       if(fDCAcut<=0 ||(fDCAcut>0&&distCA<fDCAcut)){
     584           0 :         x=track1->GetX();
     585           0 :         alpha=track1->GetAlpha();
     586           0 :         cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);
     587           0 :         Double_t x1=x*cs - track1->GetY()*sn;
     588           0 :         Double_t y1=x*sn + track1->GetY()*cs;
     589           0 :         Double_t z1=track1->GetZ();
     590             :         
     591           0 :         Double_t sx1=sn*sn*track1->GetSigmaY2(), sy1=cs*cs*track1->GetSigmaY2(); 
     592           0 :         x=track2->GetX();
     593           0 :         alpha=track2->GetAlpha();
     594           0 :         cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);
     595           0 :         Double_t x2=x*cs - track2->GetY()*sn;
     596           0 :         Double_t y2=x*sn + track2->GetY()*cs;
     597           0 :         Double_t z2=track2->GetZ();
     598           0 :         Double_t sx2=sn*sn*track2->GetSigmaY2(), sy2=cs*cs*track2->GetSigmaY2();
     599           0 :         Double_t sz1=track1->GetSigmaZ2(), sz2=track2->GetSigmaZ2();
     600           0 :         Double_t wx1=sx2/(sx1+sx2), wx2=1.- wx1;
     601           0 :         Double_t wy1=sy2/(sy1+sy2), wy2=1.- wy1;
     602           0 :         Double_t wz1=sz2/(sz1+sz2), wz2=1.- wz1;
     603           0 :         crosspoint[0]=wx1*x1 + wx2*x2; 
     604           0 :         crosspoint[1]=wy1*y1 + wy2*y2; 
     605           0 :         crosspoint[2]=wz1*z1 + wz2*z2;
     606             : 
     607           0 :         ncombi++;
     608           0 :         for(Int_t jj=0;jj<3;jj++)aver[jj]+=crosspoint[jj];
     609           0 :         for(Int_t jj=0;jj<3;jj++)averquad[jj]+=(crosspoint[jj]*crosspoint[jj]);
     610           0 :       }
     611             :     }
     612             :       
     613             :   }
     614           0 :   if(ncombi>0){
     615           0 :     for(Int_t jj=0;jj<3;jj++){
     616           0 :       initPos[jj] = aver[jj]/ncombi;
     617           0 :       averquad[jj]/=ncombi;
     618           0 :       sigmaquad[jj]=averquad[jj]-initPos[jj]*initPos[jj];
     619           0 :       sigma+=sigmaquad[jj];
     620             :     }
     621           0 :     sigma=TMath::Sqrt(TMath::Abs(sigma));
     622           0 :   }
     623             :   else {
     624           0 :     Warning("HelixVertexFinder","Finder did not succed");
     625             :     sigma=999;
     626             :   }
     627           0 :   fVert.SetXYZ(initPos);
     628           0 :   fVert.SetDispersion(sigma);
     629           0 :   fVert.SetNContributors(ncombi);
     630           0 : }
     631             : //----------------------------------------------------------------------------
     632             : Int_t AliVertexerTracks::PrepareTracks(const TObjArray &trkArrayOrig,
     633             :                                        const UShort_t *idOrig,
     634             :                                        Int_t optImpParCut) 
     635             : {
     636             : //
     637             : // Propagate tracks to initial vertex position and store them in a TObjArray
     638             : //
     639          96 :   AliDebug(1," PrepareTracks()");
     640             : 
     641          24 :   Int_t nTrksOrig = (Int_t)trkArrayOrig.GetEntriesFast();
     642             :   Int_t nTrksSel = 0;
     643             :   Double_t maxd0rphi; 
     644          24 :   Double_t sigmaCurr[3];
     645             :   Double_t normdistx,normdisty;
     646          24 :   Double_t d0z0[2],covd0z0[3]; 
     647             :   Double_t sigmad0;
     648             : 
     649          24 :   AliESDVertex *initVertex = new AliESDVertex(fNominalPos,fNominalCov,1,1);
     650             : 
     651          32 :   if(!fTrkArraySel.IsEmpty()) fTrkArraySel.Delete();
     652             : 
     653             :   AliExternalTrackParam *track=0;
     654             : 
     655             :   // loop on tracks
     656         744 :   for(Int_t i=0; i<nTrksOrig; i++) {
     657         348 :     AliExternalTrackParam *trackOrig=(AliExternalTrackParam*)trkArrayOrig.At(i);
     658         696 :     if(trackOrig->Charge()!=0) { // normal tracks
     659        1044 :       track = new AliExternalTrackParam(*(AliExternalTrackParam*)trkArrayOrig.At(i));
     660         348 :     } else { // neutral tracks (from a V0)
     661           0 :       track = new AliNeutralTrackParam(*(AliNeutralTrackParam*)trkArrayOrig.At(i));
     662             :     }
     663         348 :     track->SetUniqueID(trackOrig->GetUniqueID());
     664             :     // tgl cut
     665         348 :     if(TMath::Abs(track->GetTgl())>fMaxTgl) {
     666           0 :       AliDebug(1,Form(" rejecting track with tgl = %f",track->GetTgl()));
     667           0 :       delete track; continue;
     668             :     }
     669             : 
     670             :     Bool_t propagateOK = kFALSE, cutond0z0 = kTRUE;
     671             :     // propagate track to vertex
     672         476 :     if(optImpParCut<2 || fOnlyFitter) { // optImpParCut==1 or 0
     673         220 :       propagateOK = track->PropagateToDCA(initVertex,GetFieldkG(),100.,d0z0,covd0z0);
     674         220 :     } else {              // optImpParCut==2
     675         128 :       fCurrentVertex->GetSigmaXYZ(sigmaCurr);
     676         128 :       normdistx = TMath::Abs(fCurrentVertex->GetX()-fNominalPos[0])/TMath::Sqrt(sigmaCurr[0]*sigmaCurr[0]+fNominalCov[0]);
     677         128 :       normdisty = TMath::Abs(fCurrentVertex->GetY()-fNominalPos[1])/TMath::Sqrt(sigmaCurr[1]*sigmaCurr[1]+fNominalCov[2]);
     678         384 :       AliDebug(1,Form("normdistx %f  %f    %f",fCurrentVertex->GetX(),fNominalPos[0],TMath::Sqrt(sigmaCurr[0]*sigmaCurr[0]+fNominalCov[0])));
     679         384 :       AliDebug(1,Form("normdisty %f  %f    %f",fCurrentVertex->GetY(),fNominalPos[1],TMath::Sqrt(sigmaCurr[1]*sigmaCurr[1]+fNominalCov[2])));
     680         384 :       AliDebug(1,Form("sigmaCurr %f %f    %f",sigmaCurr[0],sigmaCurr[1],TMath::Sqrt(fNominalCov[0])+TMath::Sqrt(fNominalCov[2])));
     681         256 :       if(normdistx < 3. && normdisty < 3. &&
     682         128 :          (sigmaCurr[0]+sigmaCurr[1])<(TMath::Sqrt(fNominalCov[0])+TMath::Sqrt(fNominalCov[2]))) {
     683         128 :         propagateOK = track->PropagateToDCA(fCurrentVertex,GetFieldkG(),100.,d0z0,covd0z0);
     684         128 :       } else {
     685           0 :         propagateOK = track->PropagateToDCA(initVertex,GetFieldkG(),100.,d0z0,covd0z0);
     686           0 :         if(fConstraint) cutond0z0=kFALSE;
     687             :       }
     688             :     }
     689             : 
     690         348 :     if(!propagateOK) { 
     691           0 :       AliDebug(1,"     rejected");
     692           0 :       delete track; continue; 
     693             :     }
     694             : 
     695         348 :     sigmad0 = TMath::Sqrt(covd0z0[0]);
     696         348 :     maxd0rphi = fNSigma*sigmad0;
     697         568 :     if(optImpParCut==1) maxd0rphi *= 5.;
     698         348 :     maxd0rphi = TMath::Min(maxd0rphi,fFiducialR); 
     699             :     //sigmad0z0 = TMath::Sqrt(covd0z0[0]+covd0z0[2]);
     700             : 
     701        1044 :     AliDebug(1,Form("trk %d; id %d; |d0| = %f;  d0 cut = %f; |z0| = %f; |d0|oplus|z0| = %f; d0z0 cut = %f",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));
     702             : 
     703             : 
     704             :     //---- track selection based on impact parameters ----//
     705             : 
     706             :     // always reject tracks outside fiducial volume
     707         636 :     if(TMath::Abs(d0z0[0])>fFiducialR || TMath::Abs(d0z0[1])>fFiducialZ) { 
     708         180 :       AliDebug(1,"     rejected");
     709         180 :       delete track; continue; 
     710             :     }
     711             : 
     712             :     // during iterations 1 and 2 , reject tracks with d0rphi > maxd0rphi
     713         576 :     if(optImpParCut>0 && TMath::Abs(d0z0[0])>maxd0rphi) { 
     714          48 :       AliDebug(1,"     rejected");
     715          48 :       delete track; continue; 
     716             :     }
     717             : 
     718             :     // if fConstraint=kFALSE, during iterations 1 and 2 ||
     719             :     // if fConstraint=kTRUE, during iteration 2,
     720             :     // select tracks with d0oplusz0 < fMaxd0z0
     721         354 :     if((!fConstraint && optImpParCut>0 && fVert.GetNContributors()>0) ||
     722         354 :        ( fConstraint && optImpParCut==2 && cutond0z0)) {
     723         164 :       if(nTrksOrig>=3 && 
     724          82 :          TMath::Sqrt(d0z0[0]*d0z0[0]+d0z0[1]*d0z0[1])>fMaxd0z0) { 
     725           0 :         AliDebug(1,"     rejected");
     726           0 :         delete track; continue; 
     727             :       }
     728             :     }
     729             :     
     730             :     // track passed all selections
     731         272 :     fTrkArraySel.AddLast(track);
     732         272 :     fIdSel[nTrksSel] = idOrig[i];
     733         272 :     nTrksSel++; 
     734         272 :   } // end loop on tracks
     735             : 
     736          48 :   delete initVertex;
     737             : 
     738          24 :   return nTrksSel;
     739          24 : } 
     740             : //----------------------------------------------------------------------------
     741             : Bool_t AliVertexerTracks::PropagateTrackTo(AliExternalTrackParam *track,
     742             :                                            Double_t xToGo) {
     743             :   //----------------------------------------------------------------
     744             :   // COPIED from AliTracker
     745             :   //
     746             :   // Propagates the track to the plane X=xk (cm).
     747             :   //
     748             :   //  Origin: Marian Ivanov,  Marian.Ivanov@cern.ch
     749             :   //----------------------------------------------------------------
     750             : 
     751             :   const Double_t kEpsilon = 0.00001;
     752           0 :   Double_t xpos = track->GetX();
     753           0 :   Double_t dir = (xpos<xToGo) ? 1. : -1.;
     754             :   Double_t maxStep = 5;
     755             :   Double_t maxSnp = 0.8;
     756             :   //
     757           0 :   while ( (xToGo-xpos)*dir > kEpsilon){
     758           0 :     Double_t step = dir*TMath::Min(TMath::Abs(xToGo-xpos), maxStep);
     759           0 :     Double_t x    = xpos+step;
     760           0 :     Double_t xyz0[3],xyz1[3];
     761           0 :     track->GetXYZ(xyz0);   //starting global position
     762             : 
     763           0 :     if(!track->GetXYZAt(x,GetFieldkG(),xyz1)) return kFALSE;   // no prolongation
     764           0 :     xyz1[2]+=kEpsilon; // waiting for bug correction in geo
     765             : 
     766           0 :     if(TMath::Abs(track->GetSnpAt(x,GetFieldkG())) >= maxSnp) return kFALSE;
     767           0 :     if(!track->PropagateTo(x,GetFieldkG()))  return kFALSE;
     768             : 
     769           0 :     if(TMath::Abs(track->GetSnp()) >= maxSnp) return kFALSE;
     770           0 :     track->GetXYZ(xyz0);   // global position
     771           0 :     Double_t alphan = TMath::ATan2(xyz0[1], xyz0[0]); 
     772             :     //
     773           0 :     Double_t ca=TMath::Cos(alphan-track->GetAlpha()), 
     774           0 :       sa=TMath::Sin(alphan-track->GetAlpha());
     775           0 :     Double_t sf=track->GetSnp(), cf=TMath::Sqrt((1.-sf)*(1.+sf));
     776           0 :     Double_t sinNew =  sf*ca - cf*sa;
     777           0 :     if(TMath::Abs(sinNew) >= maxSnp) return kFALSE;
     778           0 :     if(!track->Rotate(alphan)) return kFALSE;
     779             :  
     780           0 :     xpos = track->GetX();
     781           0 :   }
     782           0 :   return kTRUE;
     783           0 : }
     784             : //---------------------------------------------------------------------------
     785             : AliESDVertex* AliVertexerTracks::RemoveTracksFromVertex(AliESDVertex *inVtx,
     786             :                                                         const TObjArray *trkArray,
     787             :                                                         UShort_t *id,
     788             :                                                         const Float_t *diamondxy) const
     789             : {
     790             : //
     791             : // Removes tracks in trksTree from fit of inVtx
     792             : //
     793             : 
     794           0 :   if(!strstr(inVtx->GetTitle(),"VertexerTracksWithConstraint")) {
     795           0 :     printf("ERROR: primary vertex has no constraint: cannot remove tracks");
     796           0 :     return 0x0;
     797             :   }
     798           0 :   if(!strstr(inVtx->GetTitle(),"VertexerTracksWithConstraintOnlyFitter"))
     799           0 :     printf("WARNING: result of tracks' removal will be only approximately correct");
     800             : 
     801           0 :   TMatrixD rv(3,1);
     802           0 :   rv(0,0) = inVtx->GetX();
     803           0 :   rv(1,0) = inVtx->GetY();
     804           0 :   rv(2,0) = inVtx->GetZ();
     805           0 :   TMatrixD vV(3,3);
     806           0 :   Double_t cov[6];
     807           0 :   inVtx->GetCovMatrix(cov);
     808           0 :   vV(0,0) = cov[0];
     809           0 :   vV(0,1) = cov[1]; vV(1,0) = cov[1];
     810           0 :   vV(1,1) = cov[2];
     811           0 :   vV(0,2) = cov[3]; vV(2,0) = cov[3];
     812           0 :   vV(1,2) = cov[4]; vV(2,1) = cov[4]; 
     813           0 :   vV(2,2) = cov[5];
     814             : 
     815           0 :   TMatrixD sumWi(TMatrixD::kInverted,vV);
     816           0 :   TMatrixD sumWiri(sumWi,TMatrixD::kMult,rv);
     817             : 
     818           0 :   Int_t nUsedTrks = inVtx->GetNIndices();
     819           0 :   Double_t chi2 = inVtx->GetChi2();
     820             : 
     821             :   AliExternalTrackParam *track = 0;
     822           0 :   Int_t ntrks = (Int_t)trkArray->GetEntriesFast();
     823           0 :   for(Int_t i=0;i<ntrks;i++) {
     824           0 :     track = (AliExternalTrackParam*)trkArray->At(i);
     825           0 :     if(!inVtx->UsesTrack(id[i])) {
     826           0 :       printf("track %d was not used in vertex fit",id[i]);
     827             :       continue;
     828             :     }
     829           0 :     Double_t alpha = track->GetAlpha();
     830           0 :     Double_t xl = diamondxy[0]*TMath::Cos(alpha)+diamondxy[1]*TMath::Sin(alpha);
     831           0 :     track->PropagateTo(xl,GetFieldkG()); 
     832             :     // vector of track global coordinates
     833           0 :     TMatrixD ri(3,1);
     834             :     // covariance matrix of ri
     835           0 :     TMatrixD wWi(3,3);
     836             :     
     837             :     // get space point from track
     838           0 :     if(!TrackToPoint(track,ri,wWi)) continue;
     839             : 
     840           0 :     TMatrixD wWiri(wWi,TMatrixD::kMult,ri); 
     841             : 
     842           0 :     sumWi -= wWi;
     843           0 :     sumWiri -= wWiri;
     844             : 
     845             :     // track contribution to chi2
     846           0 :     TMatrixD deltar = rv; deltar -= ri;
     847           0 :     TMatrixD wWideltar(wWi,TMatrixD::kMult,deltar);
     848           0 :     Double_t chi2i = deltar(0,0)*wWideltar(0,0)+
     849           0 :                      deltar(1,0)*wWideltar(1,0)+
     850           0 :                      deltar(2,0)*wWideltar(2,0);
     851             :     // remove from total chi2
     852           0 :     chi2 -= chi2i;
     853             : 
     854           0 :     nUsedTrks--;
     855           0 :     if(nUsedTrks<2) {
     856           0 :       printf("Trying to remove too many tracks!");
     857           0 :       return 0x0;
     858             :     }
     859           0 :   }
     860             : 
     861           0 :   TMatrixD rvnew(3,1);
     862           0 :   TMatrixD vVnew(3,3);
     863             : 
     864             :   // new inverted of weights matrix
     865           0 :   TMatrixD invsumWi(TMatrixD::kInverted,sumWi);
     866           0 :   vVnew = invsumWi;
     867             :   // new position of primary vertex
     868           0 :   rvnew.Mult(vVnew,sumWiri);
     869             : 
     870           0 :   Double_t position[3];
     871           0 :   position[0] = rvnew(0,0);
     872           0 :   position[1] = rvnew(1,0);
     873           0 :   position[2] = rvnew(2,0);
     874           0 :   cov[0] = vVnew(0,0);
     875           0 :   cov[1] = vVnew(0,1);
     876           0 :   cov[2] = vVnew(1,1);
     877           0 :   cov[3] = vVnew(0,2);
     878           0 :   cov[4] = vVnew(1,2);
     879           0 :   cov[5] = vVnew(2,2);
     880             :   
     881             :   // store data in the vertex object
     882           0 :   AliESDVertex *outVtx = new AliESDVertex(position,cov,chi2,nUsedTrks+1); // the +1 is for the constraint
     883           0 :   outVtx->SetTitle(inVtx->GetTitle());
     884           0 :   UShort_t *inindices = inVtx->GetIndices();
     885             :   Int_t nIndices = nUsedTrks;
     886           0 :   UShort_t *outindices = new UShort_t[nIndices];
     887             :   Int_t j=0;
     888           0 :   for(Int_t k=0; k<inVtx->GetNIndices(); k++) {
     889             :     Bool_t copyindex=kTRUE;
     890           0 :     for(Int_t l=0; l<ntrks; l++) {
     891           0 :       if(inindices[k]==id[l]) {copyindex=kFALSE; break;}
     892             :     }
     893           0 :     if(copyindex) {
     894           0 :       outindices[j] = inindices[k]; j++;
     895           0 :     }
     896             :   }
     897           0 :   outVtx->SetIndices(nIndices,outindices);
     898           0 :   if (outindices) delete [] outindices;
     899             : 
     900             :   /*
     901             :     printf("Vertex before removing tracks:");
     902             :     inVtx->PrintStatus();
     903             :     inVtx->PrintIndices();
     904             :     printf("Vertex after removing tracks:");
     905             :     outVtx->PrintStatus();
     906             :     outVtx->PrintIndices();
     907             :   */
     908             : 
     909             :   return outVtx;
     910           0 : }
     911             : //---------------------------------------------------------------------------
     912             : AliESDVertex* AliVertexerTracks::RemoveConstraintFromVertex(AliESDVertex *inVtx,
     913             :                                                      Float_t *diamondxyz,
     914             :                                                      Float_t *diamondcov) const
     915             : {
     916             : //
     917             : // Removes diamond constraint from fit of inVtx
     918             : //
     919             : 
     920           0 :   if(!strstr(inVtx->GetTitle(),"VertexerTracksWithConstraint")) {
     921           0 :     printf("ERROR: primary vertex has no constraint: cannot remove it\n");
     922           0 :     return 0x0;
     923             :   }
     924           0 :   if(inVtx->GetNContributors()<3) {
     925           0 :     printf("ERROR: primary vertex has less than 2 tracks: cannot remove contraint\n");
     926           0 :     return 0x0;
     927             :   }
     928             : 
     929             :   // diamond constraint 
     930           0 :   TMatrixD vVb(3,3);
     931           0 :   vVb(0,0) = diamondcov[0];
     932           0 :   vVb(0,1) = diamondcov[1];
     933           0 :   vVb(0,2) = 0.;
     934           0 :   vVb(1,0) = diamondcov[1];
     935           0 :   vVb(1,1) = diamondcov[2];
     936           0 :   vVb(1,2) = 0.;
     937           0 :   vVb(2,0) = 0.;
     938           0 :   vVb(2,1) = 0.;
     939           0 :   vVb(2,2) = diamondcov[5];
     940           0 :   TMatrixD vVbInv(TMatrixD::kInverted,vVb);
     941           0 :   TMatrixD rb(3,1);
     942           0 :   rb(0,0) = diamondxyz[0];
     943           0 :   rb(1,0) = diamondxyz[1];
     944           0 :   rb(2,0) = diamondxyz[2];
     945           0 :   TMatrixD vVbInvrb(vVbInv,TMatrixD::kMult,rb);
     946             : 
     947             :   // input vertex
     948           0 :   TMatrixD rv(3,1);
     949           0 :   rv(0,0) = inVtx->GetX();
     950           0 :   rv(1,0) = inVtx->GetY();
     951           0 :   rv(2,0) = inVtx->GetZ();
     952           0 :   TMatrixD vV(3,3);
     953           0 :   Double_t cov[6];
     954           0 :   inVtx->GetCovMatrix(cov);
     955           0 :   vV(0,0) = cov[0];
     956           0 :   vV(0,1) = cov[1]; vV(1,0) = cov[1];
     957           0 :   vV(1,1) = cov[2];
     958           0 :   vV(0,2) = cov[3]; vV(2,0) = cov[3];
     959           0 :   vV(1,2) = cov[4]; vV(2,1) = cov[4]; 
     960           0 :   vV(2,2) = cov[5];
     961           0 :   TMatrixD vVInv(TMatrixD::kInverted,vV);
     962           0 :   TMatrixD vVInvrv(vVInv,TMatrixD::kMult,rv);
     963             : 
     964             : 
     965           0 :   TMatrixD sumWi = vVInv - vVbInv;
     966             : 
     967             : 
     968           0 :   TMatrixD sumWiri = vVInvrv - vVbInvrb;
     969             : 
     970           0 :   TMatrixD rvnew(3,1);
     971           0 :   TMatrixD vVnew(3,3);
     972             : 
     973             :   // new inverted of weights matrix
     974           0 :   TMatrixD invsumWi(TMatrixD::kInverted,sumWi);
     975           0 :   vVnew = invsumWi;
     976             :   // new position of primary vertex
     977           0 :   rvnew.Mult(vVnew,sumWiri);
     978             : 
     979           0 :   Double_t position[3];
     980           0 :   position[0] = rvnew(0,0);
     981           0 :   position[1] = rvnew(1,0);
     982           0 :   position[2] = rvnew(2,0);
     983           0 :   cov[0] = vVnew(0,0);
     984           0 :   cov[1] = vVnew(0,1);
     985           0 :   cov[2] = vVnew(1,1);
     986           0 :   cov[3] = vVnew(0,2);
     987           0 :   cov[4] = vVnew(1,2);
     988           0 :   cov[5] = vVnew(2,2);
     989             : 
     990             : 
     991           0 :   Double_t chi2 = inVtx->GetChi2();
     992             : 
     993             :   // diamond constribution to chi2
     994           0 :   TMatrixD deltar = rv; deltar -= rb;
     995           0 :   TMatrixD vVbInvdeltar(vVbInv,TMatrixD::kMult,deltar);
     996           0 :   Double_t chi2b = deltar(0,0)*vVbInvdeltar(0,0)+
     997           0 :                    deltar(1,0)*vVbInvdeltar(1,0)+
     998           0 :                    deltar(2,0)*vVbInvdeltar(2,0);
     999             :   // remove from total chi2
    1000           0 :   chi2 -= chi2b;
    1001             : 
    1002             :   // store data in the vertex object
    1003           0 :   AliESDVertex *outVtx = new AliESDVertex(position,cov,chi2,inVtx->GetNContributors()-1);
    1004           0 :   outVtx->SetTitle("VertexerTracksNoConstraint");
    1005           0 :   UShort_t *inindices = inVtx->GetIndices();
    1006           0 :   Int_t nIndices = inVtx->GetNIndices();
    1007           0 :   outVtx->SetIndices(nIndices,inindices);
    1008             : 
    1009             :   return outVtx;
    1010           0 : }
    1011             : //---------------------------------------------------------------------------
    1012             : void AliVertexerTracks::SetCuts(Double_t *cuts, Int_t ncuts) 
    1013             : {
    1014             : //
    1015             : //  Cut values
    1016             : //
    1017          48 :   if (ncuts>0) SetDCAcut(cuts[0]);
    1018          32 :   if (ncuts>1) SetDCAcutIter0(cuts[1]);
    1019          32 :   if (ncuts>2) SetMaxd0z0(cuts[2]);
    1020          40 :   if (ncuts>3) if(fMode==0 && cuts[3]<0) SetITSrefitNotRequired();
    1021          32 :   if (ncuts>3) SetMinClusters((Int_t)(TMath::Abs(cuts[3])));
    1022          32 :   if (ncuts>4) SetMinTracks((Int_t)(cuts[4]));
    1023          32 :   if (ncuts>5) SetNSigmad0(cuts[5]);
    1024          32 :   if (ncuts>6) SetMinDetFitter(cuts[6]);
    1025          32 :   if (ncuts>7) SetMaxTgl(cuts[7]);
    1026          32 :   if (ncuts>9) SetFiducialRZ(cuts[8],cuts[9]);
    1027          32 :   if (ncuts>10) fAlgo=(Int_t)(cuts[10]);
    1028          32 :   if (ncuts>11) fAlgoIter0=(Int_t)(cuts[11]);
    1029             :   //
    1030          48 :   if (ncuts>12) if (cuts[12]>1.)   SetMVTukey2(cuts[12]);
    1031          48 :   if (ncuts>13) if (cuts[13]>1.)   SetMVSig2Ini(cuts[13]);
    1032          48 :   if (ncuts>14) if (cuts[14]>0.1)  SetMVMaxSigma2(cuts[14]);
    1033          48 :   if (ncuts>15) if (cuts[15]>1e-5) SetMVMinSig2Red(cuts[15]);
    1034          48 :   if (ncuts>16) if (cuts[16]>1e-5) SetMVMinDst(cuts[16]);
    1035          48 :   if (ncuts>17) if (cuts[17]>0.5)  SetMVScanStep(cuts[17]);
    1036          32 :   if (ncuts>18) SetMVMaxWghNtr(cuts[18]);
    1037          32 :   if (ncuts>19) SetMVFinalWBinary(cuts[19]>0);
    1038          32 :   if (ncuts>20) SetBCSpacing(int(cuts[20]));
    1039             :   //
    1040          16 :   if (ncuts>21) if (cuts[21]>0.5)  SetUseTrackClusterization(kTRUE);
    1041          16 :   if (ncuts>22) SetDeltaZCutForCluster(cuts[22]);
    1042          16 :   if (ncuts>23) SetnSigmaZCutForCluster(cuts[23]);  
    1043             :   //
    1044          40 :   if ( (fAlgo==kMultiVertexer || fClusterize) && fBCSpacing>0) SetSelectOnTOFBunchCrossing(kTRUE,kTRUE);
    1045           8 :   else                       SetSelectOnTOFBunchCrossing(kFALSE,kTRUE);
    1046             :   //
    1047             :   // Don't use BCSpacing in CPass0
    1048          16 :   TString cpass = gSystem->Getenv("CPass");
    1049          32 :   if (cpass=="0" && fDisableBCInCPass0) {
    1050           0 :     AliInfoF("CPass%s declared, switch off using BC from TOF",cpass.Data());
    1051           0 :     SetBCSpacing(-25);
    1052           0 :     SetSelectOnTOFBunchCrossing(kFALSE,kTRUE);
    1053           0 :   }
    1054             : 
    1055             :   return;
    1056          16 : }
    1057             : //---------------------------------------------------------------------------
    1058             : void AliVertexerTracks::SetITSMode(Double_t dcacut,
    1059             :                                    Double_t dcacutIter0,
    1060             :                                    Double_t maxd0z0,
    1061             :                                    Int_t minCls,
    1062             :                                    Int_t mintrks,
    1063             :                                    Double_t nsigma,
    1064             :                                    Double_t mindetfitter,
    1065             :                                    Double_t maxtgl,
    1066             :                                    Double_t fidR,
    1067             :                                    Double_t fidZ,
    1068             :                                    Int_t finderAlgo,
    1069             :                                    Int_t finderAlgoIter0)
    1070             : {
    1071             : //
    1072             : //  Cut values for ITS mode
    1073             : //
    1074          16 :   fMode = 0;
    1075           8 :   if(minCls>0) {
    1076           8 :     SetITSrefitRequired();
    1077           8 :   } else {
    1078           0 :     SetITSrefitNotRequired();
    1079             :   }
    1080           8 :   SetDCAcut(dcacut);
    1081           8 :   SetDCAcutIter0(dcacutIter0);
    1082           8 :   SetMaxd0z0(maxd0z0);
    1083           8 :   SetMinClusters(TMath::Abs(minCls));
    1084           8 :   SetMinTracks(mintrks);
    1085           8 :   SetNSigmad0(nsigma);
    1086           8 :   SetMinDetFitter(mindetfitter);
    1087           8 :   SetMaxTgl(maxtgl);
    1088           8 :   SetFiducialRZ(fidR,fidZ);
    1089           8 :   fAlgo=finderAlgo;
    1090           8 :   fAlgoIter0=finderAlgoIter0;
    1091             : 
    1092           8 :   return; 
    1093             : }
    1094             : //---------------------------------------------------------------------------
    1095             : void AliVertexerTracks::SetTPCMode(Double_t dcacut,
    1096             :                                    Double_t dcacutIter0,
    1097             :                                    Double_t maxd0z0,
    1098             :                                    Int_t minCls,
    1099             :                                    Int_t mintrks,
    1100             :                                    Double_t nsigma,
    1101             :                                    Double_t mindetfitter,
    1102             :                                    Double_t maxtgl,
    1103             :                                    Double_t fidR,
    1104             :                                    Double_t fidZ,
    1105             :                                    Int_t finderAlgo,
    1106             :                                    Int_t finderAlgoIter0) 
    1107             : {
    1108             : //
    1109             : //  Cut values for TPC mode
    1110             : //
    1111          16 :   fMode = 1;
    1112           8 :   SetITSrefitNotRequired();
    1113           8 :   SetDCAcut(dcacut);
    1114           8 :   SetDCAcutIter0(dcacutIter0);
    1115           8 :   SetMaxd0z0(maxd0z0);
    1116           8 :   SetMinClusters(minCls);
    1117           8 :   SetMinTracks(mintrks);
    1118           8 :   SetNSigmad0(nsigma);
    1119           8 :   SetMinDetFitter(mindetfitter);
    1120           8 :   SetMaxTgl(maxtgl);
    1121           8 :   SetFiducialRZ(fidR,fidZ);
    1122           8 :   fAlgo=finderAlgo;
    1123           8 :   fAlgoIter0=finderAlgoIter0;
    1124             : 
    1125           8 :   return; 
    1126             : }
    1127             : //---------------------------------------------------------------------------
    1128             : void AliVertexerTracks::SetSkipTracks(Int_t n,const Int_t *skipped) 
    1129             : {
    1130             : //
    1131             : // Mark the tracks not to be used in the vertex reconstruction.
    1132             : // Tracks are identified by AliESDtrack::GetID()
    1133             : //
    1134           0 :   fNTrksToSkip = n;  fTrksToSkip = new Int_t[n]; 
    1135           0 :   for(Int_t i=0;i<n;i++) fTrksToSkip[i] = skipped[i]; 
    1136           0 :   return; 
    1137             : }
    1138             : //---------------------------------------------------------------------------
    1139             : void  AliVertexerTracks::SetVtxStart(AliESDVertex *vtx) 
    1140             : { 
    1141             : //
    1142             : // Set initial vertex knowledge
    1143             : //
    1144          32 :   vtx->GetXYZ(fNominalPos);
    1145          16 :   vtx->GetCovMatrix(fNominalCov);
    1146          16 :   SetConstraintOn();
    1147          16 :   return; 
    1148             : }
    1149             : //---------------------------------------------------------------------------
    1150             : void AliVertexerTracks::StrLinVertexFinderMinDist(Int_t optUseWeights)
    1151             : {
    1152             :   AliExternalTrackParam *track1;
    1153          32 :   const Int_t knacc = (Int_t)fTrkArraySel.GetEntriesFast();
    1154          16 :   AliStrLine **linarray = new AliStrLine* [knacc];
    1155         392 :   for(Int_t i=0; i<knacc; i++){
    1156         180 :     track1 = (AliExternalTrackParam*)fTrkArraySel.At(i);
    1157         180 :     Double_t alpha=track1->GetAlpha();
    1158         180 :     Double_t mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
    1159         180 :     Double_t pos[3],dir[3],sigmasq[3]; 
    1160         180 :     track1->GetXYZAt(mindist,GetFieldkG(),pos);
    1161         180 :     track1->GetPxPyPzAt(mindist,GetFieldkG(),dir);
    1162         180 :     sigmasq[0]=TMath::Sin(alpha)*TMath::Sin(alpha)*track1->GetSigmaY2();
    1163         180 :     sigmasq[1]=TMath::Cos(alpha)*TMath::Cos(alpha)*track1->GetSigmaY2();
    1164         180 :     sigmasq[2]=track1->GetSigmaZ2();
    1165         180 :     TMatrixD ri(3,1);
    1166         180 :     TMatrixD wWi(3,3);
    1167         360 :     if(!TrackToPoint(track1,ri,wWi)) {
    1168             :       optUseWeights=kFALSE;
    1169           0 :       AliDebug(1,"WARNING: TrackToPoint failed");
    1170             :     }
    1171         180 :     Double_t wmat[9];
    1172             :     Int_t iel=0;
    1173        1440 :     for(Int_t ia=0;ia<3;ia++){
    1174        4320 :       for(Int_t ib=0;ib<3;ib++){
    1175        3240 :         wmat[iel]=wWi(ia,ib);
    1176        1620 :         iel++;
    1177             :       }    
    1178             :     }
    1179         540 :     linarray[i] = new AliStrLine(pos,sigmasq,wmat,dir);
    1180         180 :   }
    1181          32 :   fVert=TrackletVertexFinder(linarray,knacc,optUseWeights);
    1182         752 :   for(Int_t i=0; i<knacc; i++) delete linarray[i];
    1183          32 :   delete [] linarray;
    1184          16 : }
    1185             : //---------------------------------------------------------------------------
    1186             : AliESDVertex AliVertexerTracks::TrackletVertexFinder(const TClonesArray *lines, Int_t optUseWeights)
    1187             : {
    1188             :   // Calculate the point at minimum distance to prepared tracks (TClonesArray)
    1189          64 :   const Int_t knacc = (Int_t)lines->GetEntriesFast();
    1190          32 :   AliStrLine** lines2 = new AliStrLine* [knacc];
    1191         448 :   for(Int_t i=0; i<knacc; i++){
    1192         192 :     lines2[i]= (AliStrLine*)lines->At(i);
    1193             :   }
    1194          32 :   AliESDVertex vert = TrackletVertexFinder(lines2,knacc,optUseWeights); 
    1195          64 :   delete [] lines2;
    1196             :   return vert;
    1197          64 : }
    1198             : 
    1199             : //---------------------------------------------------------------------------
    1200             : AliESDVertex AliVertexerTracks::TrackletVertexFinder(AliStrLine **lines, const Int_t knacc, Int_t optUseWeights)
    1201             : {
    1202             :   // Calculate the point at minimum distance to prepared tracks (array of AliStrLine) 
    1203             : 
    1204          96 :   Double_t initPos[3]={0.,0.,0.};
    1205             : 
    1206          48 :   Double_t (*vectP0)[3]=new Double_t [knacc][3];
    1207          48 :   Double_t (*vectP1)[3]=new Double_t [knacc][3];
    1208             :   
    1209          48 :   Double_t sum[3][3];
    1210          48 :   Double_t dsum[3]={0,0,0};
    1211          48 :   TMatrixD sumWi(3,3);
    1212         384 :   for(Int_t i=0;i<3;i++){
    1213        1152 :     for(Int_t j=0;j<3;j++){
    1214         432 :       sum[i][j]=0;
    1215         864 :       sumWi(i,j)=0.;
    1216             :     }
    1217             :   }
    1218             : 
    1219         840 :   for(Int_t i=0; i<knacc; i++){
    1220         372 :     AliStrLine *line1 = lines[i]; 
    1221         372 :     Double_t p0[3],cd[3],sigmasq[3];
    1222         372 :     Double_t wmat[9];
    1223         372 :     if(!line1) {printf("ERROR %d %d\n",i,knacc); continue;}
    1224         372 :     line1->GetP0(p0);
    1225         372 :     line1->GetCd(cd);
    1226         372 :     line1->GetSigma2P0(sigmasq);
    1227         372 :     line1->GetWMatrix(wmat);
    1228         372 :     TMatrixD wWi(3,3);
    1229             :     Int_t iel=0;
    1230        2976 :     for(Int_t ia=0;ia<3;ia++){
    1231        8928 :       for(Int_t ib=0;ib<3;ib++){
    1232        6696 :         wWi(ia,ib)=wmat[iel];
    1233        3348 :         iel++;
    1234             :       }    
    1235             :     }
    1236             : 
    1237         372 :     sumWi+=wWi;
    1238             : 
    1239         372 :     Double_t p1[3]={p0[0]+cd[0],p0[1]+cd[1],p0[2]+cd[2]};
    1240         372 :     vectP0[i][0]=p0[0];
    1241         372 :     vectP0[i][1]=p0[1];
    1242         372 :     vectP0[i][2]=p0[2];
    1243         372 :     vectP1[i][0]=p1[0];
    1244         372 :     vectP1[i][1]=p1[1];
    1245         372 :     vectP1[i][2]=p1[2];
    1246             :     
    1247         372 :     Double_t matr[3][3];
    1248         372 :     Double_t dknow[3];
    1249         564 :     if(optUseWeights==0)GetStrLinDerivMatrix(p0,p1,matr,dknow);
    1250         180 :     else GetStrLinDerivMatrix(p0,p1,sigmasq,matr,dknow);
    1251             : 
    1252             : 
    1253        2976 :     for(Int_t iii=0;iii<3;iii++){
    1254        1116 :       dsum[iii]+=dknow[iii]; 
    1255        8928 :       for(Int_t lj=0;lj<3;lj++) sum[iii][lj]+=matr[iii][lj];
    1256             :     }
    1257         744 :   }
    1258             :  
    1259          48 :   TMatrixD invsumWi(TMatrixD::kInverted,sumWi);
    1260          48 :   Double_t covmatrix[6];
    1261          96 :   covmatrix[0] = invsumWi(0,0);
    1262          96 :   covmatrix[1] = invsumWi(0,1);
    1263          96 :   covmatrix[2] = invsumWi(1,1);
    1264          96 :   covmatrix[3] = invsumWi(0,2);
    1265          96 :   covmatrix[4] = invsumWi(1,2);
    1266          96 :   covmatrix[5] = invsumWi(2,2);
    1267             : 
    1268          48 :   Double_t vett[3][3];
    1269          48 :   Double_t det=GetDeterminant3X3(sum);
    1270             :   Double_t sigma=0;
    1271             :   
    1272          48 :   if(TMath::Abs(det) > kAlmost0){
    1273         384 :     for(Int_t zz=0;zz<3;zz++){
    1274        1152 :       for(Int_t ww=0;ww<3;ww++){
    1275        3456 :         for(Int_t kk=0;kk<3;kk++) vett[ww][kk]=sum[ww][kk];
    1276             :       }
    1277        1152 :       for(Int_t kk=0;kk<3;kk++) vett[kk][zz]=dsum[kk];
    1278         144 :       initPos[zz]=GetDeterminant3X3(vett)/det;
    1279             :     }
    1280             : 
    1281             : 
    1282         840 :     for(Int_t i=0; i<knacc; i++){
    1283         372 :       Double_t p0[3]={0,0,0},p1[3]={0,0,0};
    1284        2976 :       for(Int_t ii=0;ii<3;ii++){
    1285        1116 :         p0[ii]=vectP0[i][ii];
    1286        1116 :         p1[ii]=vectP1[i][ii];
    1287             :       }
    1288         372 :       sigma+=GetStrLinMinDist(p0,p1,initPos);
    1289         372 :     }
    1290             : 
    1291          96 :     if(sigma>0.) {sigma=TMath::Sqrt(sigma);}else{sigma=999;}
    1292             :   }else{
    1293             :     sigma=999;
    1294             :   }
    1295          48 :   AliESDVertex theVert(initPos,covmatrix,99999.,knacc);
    1296          48 :   theVert.SetDispersion(sigma);
    1297          96 :   delete [] vectP0;
    1298          96 :   delete [] vectP1;
    1299             :   return theVert;
    1300          96 : }
    1301             : 
    1302             : //---------------------------------------------------------------------------
    1303             : Bool_t AliVertexerTracks::TrackToPoint(AliExternalTrackParam *t,
    1304             :                                        TMatrixD &ri,TMatrixD &wWi,
    1305             :                                        Bool_t uUi3by3) const 
    1306             : {
    1307             : //
    1308             : // Extract from the AliExternalTrackParam the global coordinates ri and covariance matrix
    1309             : // wWi of the space point that it represents (to be used in VertexFitter())
    1310             : //
    1311             : 
    1312             :   
    1313        1056 :   Double_t rotAngle = t->GetAlpha();
    1314        1394 :   if(rotAngle<0.) rotAngle += 2.*TMath::Pi();
    1315        1056 :   Double_t cosRot = TMath::Cos(rotAngle);
    1316        1056 :   Double_t sinRot = TMath::Sin(rotAngle);
    1317             :   /*
    1318             :   // RS >>>
    1319             :   Double_t lambda = TMath::ATan(t->GetTgl());
    1320             :   Double_t cosLam   = TMath::Cos(lambda);
    1321             :   Double_t sinLam   = TMath::Sin(lambda);
    1322             :   // RS <<<
    1323             :   */
    1324        1056 :   ri(0,0) = t->GetX()*cosRot-t->GetY()*sinRot;
    1325        1056 :   ri(1,0) = t->GetX()*sinRot+t->GetY()*cosRot;
    1326        1056 :   ri(2,0) = t->GetZ();
    1327             : 
    1328        1056 :   if(!uUi3by3) {
    1329             :     // matrix to go from global (x,y,z) to local (y,z);
    1330        1056 :     TMatrixD qQi(2,3);
    1331        2112 :     qQi(0,0) = -sinRot;
    1332        2112 :     qQi(0,1) = cosRot;
    1333        2112 :     qQi(0,2) = 0.;
    1334             :     //
    1335        2112 :     qQi(1,0) = 0.;
    1336        2112 :     qQi(1,1) = 0.;
    1337        2112 :     qQi(1,2) = 1.;
    1338             :     //
    1339             :     // RS: Added polar inclination
    1340             :     /*
    1341             :     qQi(1,0) = -sinLam*cosRot;
    1342             :     qQi(1,1) = -sinLam*sinRot;
    1343             :     qQi(1,2) = cosLam;
    1344             :     */
    1345             :     // covariance matrix of local (y,z) - inverted
    1346        1056 :     TMatrixD uUi(2,2);
    1347        2112 :     uUi(0,0) = t->GetSigmaY2();
    1348        2112 :     uUi(0,1) = t->GetSigmaZY();
    1349        2112 :     uUi(1,0) = t->GetSigmaZY();
    1350        2112 :     uUi(1,1) = t->GetSigmaZ2();
    1351             :     //printf(" Ui :");
    1352             :     //printf(" %f   %f",uUi(0,0),uUi(0,1));
    1353             :     //printf(" %f   %f",uUi(1,0),uUi(1,1));
    1354             : 
    1355        2112 :     if(uUi.Determinant() <= 0.) return kFALSE;
    1356        1056 :     TMatrixD uUiInv(TMatrixD::kInverted,uUi);
    1357             :   
    1358             :     // weights matrix: wWi = qQiT * uUiInv * qQi
    1359        1056 :     TMatrixD uUiInvQi(uUiInv,TMatrixD::kMult,qQi);
    1360        1056 :     TMatrixD m(qQi,TMatrixD::kTransposeMult,uUiInvQi);
    1361        1056 :     wWi = m;
    1362        2112 :   } else {
    1363           0 :     if(fVert.GetNContributors()<1) AliFatal("Vertex from finder is empty");
    1364             :     // matrix to go from global (x,y,z) to local (x,y,z);
    1365           0 :     TMatrixD qQi(3,3);
    1366           0 :     qQi(0,0) = cosRot;
    1367           0 :     qQi(0,1) = sinRot;
    1368           0 :     qQi(0,2) = 0.;
    1369           0 :     qQi(1,0) = -sinRot;
    1370           0 :     qQi(1,1) = cosRot;
    1371           0 :     qQi(1,2) = 0.;
    1372           0 :     qQi(2,0) = 0.;
    1373           0 :     qQi(2,1) = 0.;
    1374           0 :     qQi(2,2) = 1.;
    1375             :    
    1376             :     // covariance of fVert along the track  
    1377           0 :     Double_t p[3],pt,ptot;
    1378           0 :     t->GetPxPyPz(p);
    1379           0 :     pt = TMath::Sqrt(p[0]*p[0]+p[1]*p[1]);
    1380           0 :     ptot = TMath::Sqrt(pt*pt+p[2]*p[2]);
    1381           0 :     Double_t cphi = p[0]/pt;               //cos(phi)=px/pt
    1382           0 :     Double_t sphi = p[1]/pt;               //sin(phi)=py/pt
    1383           0 :     Double_t clambda = pt/ptot;            //cos(lambda)=pt/ptot
    1384           0 :     Double_t slambda = p[2]/ptot;            //sin(lambda)=pz/ptot
    1385           0 :     Double_t covfVert[6];
    1386           0 :     fVert.GetCovMatrix(covfVert);
    1387             :     Double_t covfVertalongt = 
    1388           0 :        covfVert[0]*cphi*cphi*clambda*clambda 
    1389           0 :       +covfVert[1]*2.*cphi*sphi*clambda*clambda
    1390           0 :       +covfVert[3]*2.*cphi*clambda*slambda 
    1391           0 :       +covfVert[2]*sphi*sphi*clambda*clambda 
    1392           0 :       +covfVert[4]*2.*sphi*clambda*slambda 
    1393           0 :       +covfVert[5]*slambda*slambda; 
    1394             :     // covariance matrix of local (x,y,z) - inverted
    1395           0 :     TMatrixD uUi(3,3);
    1396           0 :     uUi(0,0) = covfVertalongt * fnSigmaForUi00 * fnSigmaForUi00;
    1397           0 :     AliDebug(1,Form("=====> sqrtUi00 cm  %f",TMath::Sqrt(uUi(0,0))));
    1398           0 :     uUi(0,1) = 0.;
    1399           0 :     uUi(0,2) = 0.;
    1400           0 :     uUi(1,0) = 0.;
    1401           0 :     uUi(1,1) = t->GetSigmaY2();
    1402           0 :     uUi(1,2) = t->GetSigmaZY();
    1403           0 :     uUi(2,0) = 0.;
    1404           0 :     uUi(2,1) = t->GetSigmaZY();
    1405           0 :     uUi(2,2) = t->GetSigmaZ2();
    1406             :     //printf(" Ui :\n");
    1407             :     //printf(" %f   %f\n",uUi(0,0),uUi(0,1));
    1408             :     //printf(" %f   %f\n",uUi(1,0),uUi(1,1));
    1409             :   
    1410           0 :     if(uUi.Determinant() <= 0.) return kFALSE;
    1411           0 :     TMatrixD uUiInv(TMatrixD::kInverted,uUi);
    1412             :   
    1413             :     // weights matrix: wWi = qQiT * uUiInv * qQi
    1414           0 :     TMatrixD uUiInvQi(uUiInv,TMatrixD::kMult,qQi);
    1415           0 :     TMatrixD m(qQi,TMatrixD::kTransposeMult,uUiInvQi);
    1416           0 :     wWi = m;
    1417           0 :   }
    1418             : 
    1419             : 
    1420        1056 :   return kTRUE;
    1421        1056 : } 
    1422             : //---------------------------------------------------------------------------
    1423             : void AliVertexerTracks::TooFewTracks() 
    1424             : {
    1425             : //
    1426             : // When the number of tracks is < fMinTracks,
    1427             : // deal with vertices not found and prepare to exit
    1428             : //
    1429           0 :   AliDebug(1,"TooFewTracks");
    1430             : 
    1431           0 :   Double_t pos[3],err[3];
    1432           0 :   pos[0] = fNominalPos[0];
    1433           0 :   err[0] = TMath::Sqrt(fNominalCov[0]);
    1434           0 :   pos[1] = fNominalPos[1];
    1435           0 :   err[1] = TMath::Sqrt(fNominalCov[2]);
    1436           0 :   pos[2] = fNominalPos[2];
    1437           0 :   err[2] = TMath::Sqrt(fNominalCov[5]);
    1438           0 :   Int_t    ncontr = (err[0]>1. ? -1 : -3);
    1439           0 :   if(fCurrentVertex) { delete fCurrentVertex; fCurrentVertex=0; }
    1440           0 :   fCurrentVertex = new AliESDVertex(pos,err);
    1441           0 :   fCurrentVertex->SetNContributors(ncontr);
    1442             : 
    1443           0 :   if(fConstraint) {
    1444           0 :     fCurrentVertex->SetTitle("VertexerTracksWithConstraint");
    1445           0 :   } else {
    1446           0 :     fCurrentVertex->SetTitle("VertexerTracksNoConstraint");
    1447             :   }
    1448             : 
    1449           0 :   if(!fTrkArraySel.IsEmpty()) fTrkArraySel.Delete(); 
    1450           0 :   if(fIdSel) {delete [] fIdSel; fIdSel=NULL;}
    1451           0 :   if(fTrksToSkip) {delete [] fTrksToSkip; fTrksToSkip=NULL;}
    1452             : 
    1453             :   return;
    1454           0 : }
    1455             : //---------------------------------------------------------------------------
    1456             : void AliVertexerTracks::VertexFinder(Int_t optUseWeights) 
    1457             : {
    1458             : 
    1459             :   // Get estimate of vertex position in (x,y) from tracks DCA
    1460             :  
    1461           0 :   Double_t initPos[3];
    1462           0 :   initPos[2] = 0.;
    1463           0 :   for(Int_t i=0;i<2;i++)initPos[i]=fNominalPos[i];
    1464           0 :   Int_t nacc = (Int_t)fTrkArraySel.GetEntriesFast();
    1465           0 :   Double_t aver[3]={0.,0.,0.};
    1466           0 :   Double_t aversq[3]={0.,0.,0.};
    1467           0 :   Double_t sigmasq[3]={0.,0.,0.};
    1468             :   Double_t sigma=0;
    1469             :   Int_t ncombi = 0;
    1470             :   AliExternalTrackParam *track1;
    1471             :   AliExternalTrackParam *track2;
    1472           0 :   Double_t pos[3],dir[3]; 
    1473             :   Double_t alpha,mindist;
    1474             : 
    1475           0 :   for(Int_t i=0; i<nacc; i++){
    1476           0 :     track1 = (AliExternalTrackParam*)fTrkArraySel.At(i);
    1477           0 :     alpha=track1->GetAlpha();
    1478           0 :     mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
    1479           0 :     track1->GetXYZAt(mindist,GetFieldkG(),pos);
    1480           0 :     track1->GetPxPyPzAt(mindist,GetFieldkG(),dir);
    1481           0 :     AliStrLine *line1 = new AliStrLine(pos,dir); 
    1482             : 
    1483             :    //    AliStrLine *line1 = new AliStrLine();
    1484             :    //    track1->ApproximateHelixWithLine(mindist,GetFieldkG(),line1);
    1485             :    
    1486           0 :     for(Int_t j=i+1; j<nacc; j++){
    1487           0 :       track2 = (AliExternalTrackParam*)fTrkArraySel.At(j);
    1488           0 :       alpha=track2->GetAlpha();
    1489           0 :       mindist = TMath::Cos(alpha)*fNominalPos[0]+TMath::Sin(alpha)*fNominalPos[1];
    1490           0 :       track2->GetXYZAt(mindist,GetFieldkG(),pos);
    1491           0 :       track2->GetPxPyPzAt(mindist,GetFieldkG(),dir);
    1492           0 :       AliStrLine *line2 = new AliStrLine(pos,dir); 
    1493             :     //      AliStrLine *line2 = new AliStrLine();
    1494             :     //  track2->ApproximateHelixWithLine(mindist,GetFieldkG(),line2);
    1495           0 :       Double_t distCA=line2->GetDCA(line1);
    1496             :       //printf("%d   %d   %f\n",i,j,distCA);
    1497           0 :        if(fDCAcut<=0 || (fDCAcut>0&&distCA<fDCAcut)){
    1498           0 :         Double_t pnt1[3],pnt2[3],crosspoint[3];
    1499             : 
    1500           0 :         if(optUseWeights<=0){
    1501           0 :           Int_t retcode = line2->Cross(line1,crosspoint);
    1502           0 :           if(retcode>=0){
    1503           0 :             ncombi++;
    1504           0 :             for(Int_t jj=0;jj<3;jj++)aver[jj]+=crosspoint[jj];
    1505           0 :             for(Int_t jj=0;jj<3;jj++)aversq[jj]+=(crosspoint[jj]*crosspoint[jj]);
    1506           0 :           }
    1507           0 :         }
    1508           0 :         if(optUseWeights>0){
    1509           0 :           Int_t retcode = line1->CrossPoints(line2,pnt1,pnt2);
    1510           0 :           if(retcode>=0){
    1511             :             Double_t cs, sn;
    1512           0 :             alpha=track1->GetAlpha();
    1513           0 :             cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);   
    1514           0 :             Double_t sx1=sn*sn*track1->GetSigmaY2(), sy1=cs*cs*track1->GetSigmaY2();
    1515           0 :             alpha=track2->GetAlpha();
    1516           0 :             cs=TMath::Cos(alpha); sn=TMath::Sin(alpha);
    1517           0 :             Double_t sx2=sn*sn*track2->GetSigmaY2(), sy2=cs*cs*track2->GetSigmaY2();
    1518           0 :             Double_t sz1=track1->GetSigmaZ2(), sz2=track2->GetSigmaZ2();
    1519           0 :             Double_t wx1=sx2/(sx1+sx2), wx2=1.- wx1;
    1520           0 :             Double_t wy1=sy2/(sy1+sy2), wy2=1.- wy1;
    1521           0 :             Double_t wz1=sz2/(sz1+sz2), wz2=1.- wz1;
    1522           0 :             crosspoint[0]=wx1*pnt1[0] + wx2*pnt2[0]; 
    1523           0 :             crosspoint[1]=wy1*pnt1[1] + wy2*pnt2[1]; 
    1524           0 :             crosspoint[2]=wz1*pnt1[2] + wz2*pnt2[2];
    1525             :           
    1526           0 :             ncombi++;
    1527           0 :             for(Int_t jj=0;jj<3;jj++)aver[jj]+=crosspoint[jj];
    1528           0 :             for(Int_t jj=0;jj<3;jj++)aversq[jj]+=(crosspoint[jj]*crosspoint[jj]);
    1529           0 :           }
    1530           0 :         }
    1531           0 :       }
    1532           0 :       delete line2;
    1533             :     }
    1534           0 :     delete line1;
    1535             :   }
    1536           0 :   if(ncombi>0){
    1537           0 :     for(Int_t jj=0;jj<3;jj++){
    1538           0 :       initPos[jj] = aver[jj]/ncombi;
    1539             :       //printf("%f\n",initPos[jj]);
    1540           0 :       aversq[jj]/=ncombi;
    1541           0 :       sigmasq[jj]=aversq[jj]-initPos[jj]*initPos[jj];
    1542           0 :       sigma+=sigmasq[jj];
    1543             :     }
    1544           0 :     sigma=TMath::Sqrt(TMath::Abs(sigma));
    1545           0 :   }
    1546             :   else {
    1547           0 :     Warning("VertexFinder","Finder did not succed");
    1548             :     sigma=999;
    1549             :   }
    1550           0 :   fVert.SetXYZ(initPos);
    1551           0 :   fVert.SetDispersion(sigma);
    1552           0 :   fVert.SetNContributors(ncombi);
    1553           0 : }
    1554             : //---------------------------------------------------------------------------
    1555             : void AliVertexerTracks::VertexFitter(Bool_t vfit, Bool_t chiCalc,Int_t useWeights) 
    1556             : {
    1557             : //
    1558             : // The optimal estimate of the vertex position is given by a "weighted 
    1559             : // average of tracks positions".
    1560             : // Original method: V. Karimaki, CMS Note 97/0051
    1561             : //
    1562             :   const double kTiny = 1e-9;
    1563         108 :   Bool_t useConstraint = fConstraint;
    1564         108 :   Double_t initPos[3];
    1565         108 :   if(!fOnlyFitter) {
    1566         108 :     fVert.GetXYZ(initPos);
    1567         108 :   } else {
    1568           0 :     initPos[0]=fNominalPos[0];
    1569           0 :     initPos[1]=fNominalPos[1];
    1570           0 :     initPos[2]=fNominalPos[2];
    1571             :   }
    1572             : 
    1573         108 :   Int_t nTrksSel = (Int_t)fTrkArraySel.GetEntries();
    1574         108 :   if(nTrksSel==1) useConstraint=kTRUE;
    1575         324 :   AliDebug(1,Form("--- VertexFitter(): start (%d,%d,%d)",vfit,chiCalc,useWeights));
    1576         324 :   AliDebug(1,Form(" Number of tracks in array: %d\n",nTrksSel));
    1577         324 :   AliDebug(1,Form(" Minimum # tracks required in fit: %d\n",fMinTracks));
    1578         324 :   AliDebug(1,Form(" Vertex position after finder: %f,%f,%f\n",initPos[0],initPos[1],initPos[2]));
    1579         432 :   if(useConstraint) AliDebug(1,Form(" This vertex will be used in fit: (%f+-%f,%f+-%f)\n",fNominalPos[0],TMath::Sqrt(fNominalCov[0]),fNominalPos[1],TMath::Sqrt(fNominalCov[2]))); 
    1580             : 
    1581             :   // special treatment for few-tracks fits (e.g. secondary vertices)
    1582         108 :   Bool_t uUi3by3 = kFALSE; if(nTrksSel<5 && !useConstraint && !useWeights) uUi3by3 = kTRUE;
    1583             : 
    1584             :   Int_t i,j,k,step=0;
    1585         114 :   static TMatrixD rv(3,1);
    1586         114 :   static TMatrixD vV(3,3);
    1587         108 :   rv(0,0) = initPos[0];
    1588         108 :   rv(1,0) = initPos[1];
    1589         108 :   rv(2,0) = initPos[2];
    1590             :   Double_t xlStart,alpha;
    1591             :   Int_t nTrksUsed = 0;
    1592             :   Double_t chi2=0,chi2i,chi2b;
    1593             :   AliExternalTrackParam *t = 0;
    1594             :   Int_t failed = 0;
    1595             : 
    1596             :   // initial vertex covariance matrix
    1597         108 :   TMatrixD vVb(3,3);
    1598         216 :   vVb(0,0) = fNominalCov[0];
    1599         216 :   vVb(0,1) = fNominalCov[1];
    1600         216 :   vVb(0,2) = 0.;
    1601         216 :   vVb(1,0) = fNominalCov[1];
    1602         216 :   vVb(1,1) = fNominalCov[2];
    1603         216 :   vVb(1,2) = 0.;
    1604         216 :   vVb(2,0) = 0.;
    1605         216 :   vVb(2,1) = 0.;
    1606         216 :   vVb(2,2) = fNominalCov[5];
    1607         108 :   TMatrixD vVbInv(TMatrixD::kInverted,vVb);
    1608         108 :   TMatrixD rb(3,1);
    1609         216 :   rb(0,0) = fNominalPos[0];
    1610         216 :   rb(1,0) = fNominalPos[1];
    1611         216 :   rb(2,0) = fNominalPos[2];
    1612         108 :   TMatrixD vVbInvrb(vVbInv,TMatrixD::kMult,rb);
    1613             :   //
    1614         108 :   int currBC = fVert.GetBC();
    1615             :   //
    1616             :   // 2 steps:
    1617             :   // 1st - estimate of vtx using all tracks
    1618             :   // 2nd - estimate of global chi2
    1619             :   //
    1620         648 :   for(step=0; step<2; step++) {
    1621         324 :     if      (step==0 && !vfit)    continue;
    1622         314 :     else if (step==1 && !chiCalc) continue;
    1623             :     chi2 = 0.;
    1624             :     nTrksUsed = 0;
    1625         124 :     fMVWSum = fMVWE2 = 0;
    1626         228 :     if(step==1) { initPos[0]=rv(0,0); initPos[1]=rv(1,0); initPos[2]=rv(2,0);}
    1627         620 :     AliDebug(2,Form("Step%d: inipos: %+f %+f %+f MinTr: %d, Sig2:%.2f)",step,initPos[0],initPos[1],initPos[2],fMinTracks,fMVSigma2));
    1628             :     //
    1629         124 :     TMatrixD sumWiri(3,1);
    1630         124 :     TMatrixD sumWi(3,3);
    1631         992 :     for(i=0; i<3; i++) {
    1632         744 :       sumWiri(i,0) = 0.;
    1633        4092 :       for(j=0; j<3; j++) sumWi(j,i) = 0.;
    1634             :     }
    1635             : 
    1636             :     // mean vertex constraint
    1637         124 :     if(useConstraint) {
    1638         992 :       for(i=0;i<3;i++) {
    1639        1116 :         sumWiri(i,0) += vVbInvrb(i,0);
    1640        5208 :         for(k=0;k<3;k++) sumWi(i,k) += vVbInv(i,k);
    1641             :       }
    1642             :       // chi2
    1643         248 :       TMatrixD deltar = rv; deltar -= rb;
    1644         124 :       TMatrixD vVbInvdeltar(vVbInv,TMatrixD::kMult,deltar);
    1645         496 :       chi2b = deltar(0,0)*vVbInvdeltar(0,0)+
    1646         496 :               deltar(1,0)*vVbInvdeltar(1,0)+
    1647         372 :               deltar(2,0)*vVbInvdeltar(2,0);
    1648         124 :       chi2 += chi2b;
    1649         124 :     }
    1650             : 
    1651             :     // loop on tracks  
    1652        3216 :     for(k=0; k<nTrksSel; k++) {
    1653             :       //
    1654             :       // get track from track array
    1655        2968 :       t = (AliExternalTrackParam*)fTrkArraySel.At(k);
    1656        2608 :       if (useWeights && t->TestBit(kBitUsed)) continue;
    1657             :       //      
    1658        1752 :       int tBC = int(t->GetUniqueID()) - kTOFBCShift;    // BC assigned to this track
    1659         876 :       if (fSelectOnTOFBunchCrossing) {
    1660         516 :         if (!fKeepAlsoUnflaggedTOFBunchCrossing) continue;   // don't consider tracks with undefined BC 
    1661         770 :         if (currBC!=AliVTrack::kTOFBCNA && tBC!=AliVTrack::kTOFBCNA && tBC!=currBC) continue;  // track does not match to current BCid
    1662             :       }
    1663         876 :       alpha = t->GetAlpha();
    1664         876 :       xlStart = initPos[0]*TMath::Cos(alpha)+initPos[1]*TMath::Sin(alpha);
    1665             :       // to vtxSeed (from finder)
    1666        1752 :       t->PropagateTo(xlStart,GetFieldkG());   
    1667             :  
    1668             :       // vector of track global coordinates
    1669         876 :       TMatrixD ri(3,1);
    1670             :       // covariance matrix of ri
    1671         876 :       TMatrixD wWi(3,3);
    1672             : 
    1673             :       // get space point from track
    1674        1752 :       if(!TrackToPoint(t,ri,wWi,uUi3by3)) continue;
    1675             : 
    1676             :       // track chi2
    1677        1752 :       TMatrixD deltar = rv; deltar -= ri;
    1678         876 :       TMatrixD wWideltar(wWi,TMatrixD::kMult,deltar);
    1679        3504 :       chi2i = deltar(0,0)*wWideltar(0,0)+
    1680        3504 :               deltar(1,0)*wWideltar(1,0)+
    1681        2628 :               deltar(2,0)*wWideltar(2,0);
    1682             :       //
    1683         876 :       if (useWeights) {
    1684             :         //double sg = TMath::Sqrt(fMVSigma2);
    1685             :         //double chi2iw = (deltar(0,0)*wWideltar(0,0)+deltar(1,0)*wWideltar(1,0))/sg + deltar(2,0)*wWideltar(2,0)/fMVSigma2;
    1686             :         //double wgh = (1-chi2iw/fMVTukey2); 
    1687             :         double chi2iw = chi2i;
    1688         516 :         double wgh = (1-chi2iw/fMVTukey2/fMVSigma2); 
    1689             : 
    1690         560 :         if (wgh<kTiny) wgh = 0;
    1691         562 :         else if (useWeights==2) wgh = 1.; // use as binary weight
    1692         610 :         if (step==1) ((AliESDtrack*)t)->SetBit(kBitUsed, wgh>0);
    1693         560 :         if (wgh<kTiny) continue; // discard the track
    1694         472 :         wWi *= wgh;  // RS: use weight?
    1695         472 :         fMVWSum += wgh;
    1696         472 :         fMVWE2  += wgh*chi2iw;
    1697         472 :       }
    1698             :       // add to total chi2
    1699         880 :       if (fSelectOnTOFBunchCrossing && tBC!=AliVTrack::kTOFBCNA && currBC<0) currBC = tBC;
    1700             :       //
    1701         832 :       chi2 += chi2i;
    1702         832 :       TMatrixD wWiri(wWi,TMatrixD::kMult,ri); 
    1703         832 :       sumWiri += wWiri;
    1704         832 :       sumWi   += wWi;
    1705             : 
    1706         832 :       nTrksUsed++;
    1707        2584 :     } // end loop on tracks
    1708             : 
    1709         124 :     if(nTrksUsed < fMinTracks) {
    1710             :       failed=1;
    1711          34 :       continue;
    1712             :     }
    1713             : 
    1714          90 :     Double_t determinant = sumWi.Determinant();
    1715          90 :     if(determinant < fMinDetFitter)  { 
    1716           0 :       AliDebug(1,Form("det(V) = %f (<%f)\n",determinant,fMinDetFitter));       
    1717             :       failed=1;
    1718           0 :       continue;
    1719             :     }
    1720             : 
    1721          90 :     if(step==0) { 
    1722             :       // inverted of weights matrix
    1723          64 :       TMatrixD invsumWi(TMatrixD::kInverted,sumWi);
    1724          64 :       vV = invsumWi;
    1725             :       // position of primary vertex
    1726          64 :       rv.Mult(vV,sumWiri);
    1727          64 :     }
    1728         214 :   } // end loop on the 2 steps
    1729             : 
    1730         108 :   if(failed) { 
    1731          34 :     fVert.SetNContributors(-1);
    1732          34 :     if (chiCalc) {
    1733           0 :       TooFewTracks();
    1734           0 :       if (fCurrentVertex) fVert = *fCurrentVertex;  // RS
    1735             :     }
    1736          34 :     return; 
    1737             :   }
    1738             :   //
    1739          74 :   Double_t position[3];
    1740         148 :   position[0] = rv(0,0);
    1741         148 :   position[1] = rv(1,0);
    1742         148 :   position[2] = rv(2,0);
    1743          74 :   Double_t covmatrix[6];
    1744         148 :   covmatrix[0] = vV(0,0);
    1745         148 :   covmatrix[1] = vV(0,1);
    1746         148 :   covmatrix[2] = vV(1,1);
    1747         148 :   covmatrix[3] = vV(0,2);
    1748         148 :   covmatrix[4] = vV(1,2);
    1749         148 :   covmatrix[5] = vV(2,2);
    1750             :   
    1751             :   // for correct chi2/ndf, count constraint as additional "track"
    1752         148 :   if(fConstraint) nTrksUsed++;
    1753             :   //
    1754         138 :   if (vfit && !chiCalc) { // RS: special mode for multi-vertex finder
    1755          48 :     fVert.SetXYZ(position);
    1756          48 :     fVert.SetCovarianceMatrix(covmatrix);
    1757          48 :     fVert.SetNContributors(nTrksUsed);
    1758          48 :     return;
    1759             :   } 
    1760             :   // store data in the vertex object
    1761          50 :   if(fCurrentVertex) { delete fCurrentVertex; fCurrentVertex=0; }
    1762          78 :   fCurrentVertex = new AliESDVertex(position,covmatrix,chi2,nTrksUsed);
    1763          26 :   fCurrentVertex->SetBC(currBC);
    1764          26 :   fVert = *fCurrentVertex;  // RS
    1765         130 :   AliDebug(1," Vertex after fit:");
    1766         130 :   AliDebug(1,Form("xyz: %f %f %f; nc %d",fCurrentVertex->GetX(),fCurrentVertex->GetY(),fCurrentVertex->GetZ(),fCurrentVertex->GetNContributors()));
    1767         130 :   AliDebug(1,"--- VertexFitter(): finish\n");
    1768             :  
    1769             : 
    1770          26 :   return;
    1771         182 : }
    1772             : //----------------------------------------------------------------------------
    1773             : AliESDVertex* AliVertexerTracks::VertexForSelectedTracks(const TObjArray *trkArray,
    1774             :                                                          UShort_t *id,
    1775             :                                                          Bool_t optUseFitter,
    1776             :                                                          Bool_t optPropagate,
    1777             :                                                          Bool_t optUseDiamondConstraint) 
    1778             : {
    1779             : //
    1780             : // Return vertex from tracks (AliExternalTrackParam) in array
    1781             : //
    1782           0 :   fCurrentVertex = 0;
    1783             :   // set optUseDiamondConstraint=TRUE only if you are reconstructing the 
    1784             :   // primary vertex!
    1785           0 :   if(optUseDiamondConstraint) {
    1786           0 :     SetConstraintOn();
    1787           0 :   } else {    
    1788           0 :     SetConstraintOff();
    1789             :   }
    1790             : 
    1791             :   // get tracks and propagate them to initial vertex position
    1792           0 :   fIdSel = new UShort_t[(Int_t)trkArray->GetEntriesFast()];
    1793           0 :   Int_t nTrksSel = PrepareTracks(*trkArray,id,0);
    1794           0 :   if((!optUseDiamondConstraint && nTrksSel<TMath::Max(2,fMinTracks)) ||
    1795           0 :      (optUseDiamondConstraint && nTrksSel<1)) {
    1796           0 :     TooFewTracks();
    1797           0 :     return fCurrentVertex;
    1798             :   }
    1799             :  
    1800             :   // vertex finder
    1801           0 :   if(nTrksSel==1) {
    1802           0 :     AliDebug(1,"Just one track");
    1803           0 :     OneTrackVertFinder();
    1804           0 :   } else {
    1805           0 :     switch (fAlgo) {
    1806           0 :       case 1: StrLinVertexFinderMinDist(1); break;
    1807           0 :       case 2: StrLinVertexFinderMinDist(0); break;
    1808           0 :       case 3: HelixVertexFinder();          break;
    1809           0 :       case 4: VertexFinder(1);              break;
    1810           0 :       case 5: VertexFinder(0);              break;
    1811           0 :       default: printf("Wrong algorithm\n"); break;  
    1812             :     }
    1813             :   }
    1814           0 :   AliDebug(1," Vertex finding completed\n");
    1815           0 :   Double_t vdispersion=fVert.GetDispersion();
    1816             : 
    1817             :   // vertex fitter
    1818           0 :   if(optUseFitter) {
    1819           0 :     VertexFitter();
    1820           0 :   } else {
    1821           0 :     Double_t position[3]={fVert.GetX(),fVert.GetY(),fVert.GetZ()};
    1822           0 :     Double_t covmatrix[6];
    1823           0 :     fVert.GetCovMatrix(covmatrix);
    1824             :     Double_t chi2=99999.;
    1825           0 :     Int_t    nTrksUsed=fVert.GetNContributors();
    1826           0 :     fCurrentVertex = new AliESDVertex(position,covmatrix,chi2,nTrksUsed);    
    1827           0 :   }
    1828           0 :   fCurrentVertex->SetDispersion(vdispersion);
    1829             : 
    1830             : 
    1831             :   // set indices of used tracks and propagate track to found vertex
    1832             :   UShort_t *indices = 0;
    1833           0 :   Double_t d0z0[2],covd0z0[3];
    1834             :   AliExternalTrackParam *t = 0;
    1835           0 :   if(fCurrentVertex->GetNContributors()>0) {
    1836           0 :     indices = new UShort_t[fTrkArraySel.GetEntriesFast()];
    1837           0 :     for(Int_t jj=0; jj<(Int_t)fTrkArraySel.GetEntriesFast(); jj++) {
    1838           0 :       indices[jj] = fIdSel[jj];
    1839           0 :       t = (AliExternalTrackParam*)fTrkArraySel.At(jj);
    1840           0 :       if(optPropagate && optUseFitter) {
    1841           0 :         if(TMath::Sqrt(fCurrentVertex->GetX()*fCurrentVertex->GetX()+fCurrentVertex->GetY()*fCurrentVertex->GetY())<3.) {
    1842           0 :           t->PropagateToDCA(fCurrentVertex,GetFieldkG(),100.,d0z0,covd0z0);
    1843           0 :           AliDebug(1,Form("Track %d propagated to found vertex",jj));
    1844             :         } else {
    1845           0 :           AliWarning("Found vertex outside beam pipe!");
    1846             :         }
    1847             :       }
    1848             :     }
    1849           0 :     fCurrentVertex->SetIndices(fCurrentVertex->GetNContributors(),indices);
    1850           0 :   }
    1851             : 
    1852             :   // clean up
    1853           0 :   if (indices) {delete [] indices; indices=NULL;}
    1854           0 :   delete [] fIdSel; fIdSel=NULL;
    1855           0 :   fTrkArraySel.Delete();
    1856             :   
    1857           0 :   return fCurrentVertex;
    1858           0 : }
    1859             :  
    1860             : //----------------------------------------------------------------------------
    1861             : AliESDVertex* AliVertexerTracks::VertexForSelectedESDTracks(TObjArray *trkArray,
    1862             :                                                              Bool_t optUseFitter,
    1863             :                                                             Bool_t optPropagate,
    1864             :                                                             Bool_t optUseDiamondConstraint)
    1865             : 
    1866             : {
    1867             : //
    1868             : // Return vertex from array of ESD tracks
    1869             : //
    1870             : 
    1871           0 :   Int_t nTrks = (Int_t)trkArray->GetEntriesFast();
    1872           0 :   UShort_t *id = new UShort_t[nTrks];
    1873             : 
    1874             :   AliESDtrack *esdt = 0;
    1875           0 :   for(Int_t i=0; i<nTrks; i++){
    1876           0 :     esdt = (AliESDtrack*)trkArray->At(i);
    1877           0 :     id[i] = (UShort_t)esdt->GetID();
    1878             :   }
    1879             :     
    1880           0 :   VertexForSelectedTracks(trkArray,id,optUseFitter,optPropagate,optUseDiamondConstraint);
    1881             : 
    1882           0 :   delete [] id; id=NULL;
    1883             : 
    1884           0 :   return fCurrentVertex;
    1885             : }
    1886             :  
    1887             : //______________________________________________________
    1888             : Bool_t AliVertexerTracks::FindNextVertexMV()
    1889             : {
    1890             :   // try to find a new vertex
    1891          88 :   fMVSigma2 = fMVSig2Ini;
    1892             :   double prevSig2 = fMVSigma2;
    1893          44 :   double minDst2 = fMVMinDst*fMVMinDst;
    1894             :   const double kSigLimit = 1.0;
    1895             :   const double kSigLimitE = kSigLimit+1e-6;
    1896             :   const double kPushFactor = 0.5;
    1897             :   const int kMaxIter = 20;
    1898             :   double push = kPushFactor;
    1899             :   //
    1900             :   int iter = 0;
    1901          44 :   double posP[3]={0,0,0},pos[3]={0,0,0};
    1902          44 :   fVert.GetXYZ(posP);
    1903             :   //
    1904             :   
    1905          44 :   do {    
    1906          82 :     fVert.SetBC(AliVTrack::kTOFBCNA);
    1907          82 :     VertexFitter(kTRUE,kFALSE,1);
    1908          82 :     if (fVert.GetNContributors()<fMinTracks) {
    1909         102 :       AliDebug(3,Form("Failed in iteration %d: No Contributirs",iter)); 
    1910             :       break;
    1911             :     } // failed
    1912          96 :     if (fMVWSum>0) fMVSigma2 = TMath::Max(fMVWE2/fMVWSum,kSigLimit);
    1913             :     else {
    1914           0 :       AliDebug(3,Form("Failed %d, no weithgs",iter)); 
    1915             :       iter = kMaxIter+1; 
    1916           0 :       break;
    1917             :     } // failed
    1918             :     //
    1919          48 :     double sigRed = (prevSig2-fMVSigma2)/prevSig2; // reduction of sigma2
    1920             :     //
    1921          48 :     fVert.GetXYZ(pos);
    1922          48 :     double dst2 = (pos[0]-posP[0])*(pos[0]-posP[0])+(pos[1]-posP[1])*(pos[1]-posP[1])+(pos[2]-posP[2])*(pos[2]-posP[2]);
    1923         144 :     AliDebug(3,Form("It#%2d Vtx: %+f %+f %+f Dst:%f Sig: %f [%.2f/%.2f] SigRed:%f",iter,pos[0],pos[1],pos[2],TMath::Sqrt(dst2),fMVSigma2,fMVWE2,fMVWSum,sigRed));
    1924         150 :     if ( (++iter<kMaxIter) && (sigRed<0 || sigRed<fMVMinSig2Red) && fMVSigma2>fMVMaxSigma2) {
    1925           6 :       fMVSigma2 *= push; // stuck, push little bit
    1926           6 :       push *= kPushFactor;
    1927           6 :       if (fMVSigma2<1.) fMVSigma2 = 1.; 
    1928          18 :       AliDebug(3,Form("Pushed sigma2 to %f",fMVSigma2));
    1929             :     }
    1930         126 :     else if (dst2<minDst2 && ((sigRed<0 || sigRed<fMVMinSig2Red) || fMVSigma2<kSigLimitE)) break;
    1931             :     //
    1932          38 :     fVert.GetXYZ(posP); // fetch previous vertex position
    1933          38 :     prevSig2 = fMVSigma2;
    1934          38 :   } while(iter<kMaxIter);
    1935             :   //
    1936          54 :   if (fVert.GetNContributors()<0 || iter>kMaxIter || fMVSigma2>fMVMaxSigma2) {
    1937          34 :     return kFALSE;
    1938             :   }
    1939             :   else {
    1940          10 :     VertexFitter(kFALSE,kTRUE,fMVFinalWBinary ? 2:1); // final chi2 calculation
    1941          10 :     int nv = fMVVertices->GetEntries();
    1942             :     // create indices
    1943          10 :     int ntrk = fTrkArraySel.GetEntries();
    1944          10 :     int nindices = fCurrentVertex->GetNContributors() - (fConstraint ? 1:0);
    1945          10 :     if (nindices<1) {
    1946           0 :       delete fCurrentVertex;
    1947           0 :       fCurrentVertex = 0;
    1948           0 :       return kFALSE;
    1949             :     }
    1950             :     UShort_t *indices = 0;
    1951          20 :     if (nindices>0) indices = new UShort_t[nindices];
    1952             :     int nadded = 0;
    1953         248 :     for (int itr=0;itr<ntrk;itr++) {
    1954         114 :       AliExternalTrackParam* t = (AliExternalTrackParam*)fTrkArraySel[itr];
    1955         232 :       if (t->TestBit(kBitAccounted) || !t->TestBit(kBitUsed)) continue;   // already belongs to some vertex
    1956          90 :       t->SetBit(kBitAccounted);
    1957          90 :       indices[nadded++] = fIdSel[itr];
    1958          90 :     }
    1959          10 :     if (nadded!=nindices) {
    1960           0 :       printf("Mismatch : NInd: %d Nadd: %d\n",nindices,nadded);
    1961           0 :     }
    1962          10 :     fCurrentVertex->SetIndices(nadded,indices);
    1963             :     // set vertex title
    1964          10 :     TString title="VertexerTracksMVNoConstraint";
    1965          20 :     if(fConstraint) title="VertexerTracksMVWithConstraint";
    1966          20 :     fCurrentVertex->SetTitle(title.Data());    
    1967          10 :     fMVVertices->AddLast(fCurrentVertex);
    1968          50 :     AliDebug(3,Form("Added new vertex #%d NCont:%d XYZ: %f %f %f",nindices,nv,fCurrentVertex->GetX(),fCurrentVertex->GetY(),fCurrentVertex->GetZ()));
    1969          30 :     if (indices) delete[] indices;
    1970          10 :     fCurrentVertex = 0; // already attached to fMVVertices
    1971             :     return kTRUE;
    1972          10 :   }
    1973          44 : }
    1974             : 
    1975             : //______________________________________________________
    1976             : void AliVertexerTracks::FindVerticesMV()
    1977             : {
    1978             :   // find and fit multiple vertices
    1979             :   // 
    1980          32 :   double step = fMVScanStep>1 ?  fMVScanStep : 1.;
    1981           8 :   double zmx = 3*TMath::Sqrt(fNominalCov[5]);
    1982           8 :   double zmn = -zmx;
    1983           8 :   int nz = TMath::Nint((zmx-zmn)/step); if (nz<1) nz=1;
    1984           8 :   double dz = (zmx-zmn)/nz;
    1985             :   int izStart=0;
    1986          24 :   AliDebug(2,Form("%d seeds between %f and %f",nz,zmn+dz/2,zmx+dz/2));
    1987             :   //
    1988          12 :   if (!fMVVertices) fMVVertices = new TObjArray(10);
    1989           8 :   fMVVertices->Clear();
    1990             :   //
    1991           8 :   int ntrLeft = (Int_t)fTrkArraySel.GetEntries();
    1992             :   //
    1993           8 :   double sig2Scan = fMVSig2Ini;
    1994             :   Bool_t runMore = kTRUE;
    1995             :   int cntWide = 0;
    1996          28 :   while (runMore) {
    1997          12 :     fMVSig2Ini = sig2Scan*1e3;  // try wide search
    1998             :     Bool_t found = kFALSE;
    1999          12 :     cntWide++;
    2000          12 :     fVert.SetNContributors(-1);
    2001          12 :     fVert.SetXYZ(fNominalPos);
    2002          36 :     AliDebug(3,Form("Wide search #%d Z= %f Sigma2=%f",cntWide,fNominalPos[2],fMVSig2Ini));
    2003          12 :     if (FindNextVertexMV()) { // are there tracks left to consider?
    2004          10 :       AliESDVertex* vtLast = (AliESDVertex*)fMVVertices->Last();
    2005          30 :       if (vtLast && vtLast->GetNContributors()>0) ntrLeft -= vtLast->GetNContributors()-(fConstraint ? 1:0);
    2006          16 :       if (ntrLeft<1) runMore = kFALSE; 
    2007             :       found = kTRUE;
    2008             :       continue;
    2009             :     }  
    2010             :     // if nothing is found, do narrow sig2ini scan
    2011           2 :     fMVSig2Ini = sig2Scan;
    2012          68 :     for (;izStart<nz;izStart++) {
    2013          32 :       double zSeed = zmn+dz*(izStart+0.5);
    2014          96 :       AliDebug(3,Form("Seed %d: Z= %f Sigma2=%f",izStart,zSeed,fMVSig2Ini));
    2015          32 :       fVert.SetNContributors(-1);
    2016          32 :       fVert.SetXYZ(fNominalPos);
    2017          32 :       fVert.SetZv(zSeed);
    2018          32 :       if (FindNextVertexMV()) { // are there tracks left to consider?
    2019           0 :         AliESDVertex* vtLast = (AliESDVertex*)fMVVertices->Last();
    2020           0 :         if (vtLast && vtLast->GetNContributors()>0) ntrLeft -= vtLast->GetNContributors()-(fConstraint ? 1:0);
    2021           0 :         if (ntrLeft<1) runMore = kFALSE;
    2022             :         found = kTRUE;
    2023             :         break;
    2024             :       }    
    2025          32 :     }
    2026           2 :     runMore = found; // if nothing was found, no need for new iteration
    2027           2 :   }
    2028           8 :   fMVSig2Ini = sig2Scan;
    2029           8 :   int nvFound = fMVVertices->GetEntriesFast();
    2030          24 :   AliDebug(2,Form("Number of found vertices: %d",nvFound));
    2031           8 :   if (nvFound<1) TooFewTracks();
    2032           8 :   if (AliLog::GetGlobalDebugLevel()>0) fMVVertices->Print();
    2033             :   //
    2034           8 : }
    2035             : 
    2036             : //______________________________________________________
    2037             : void AliVertexerTracks::AnalyzePileUp(AliESDEvent* esdEv)
    2038             : {
    2039             :   // if multiple vertices are found, try to find the primary one and attach it as fCurrentVertex
    2040             :   // then attach pile-up vertices directly to esdEv
    2041             :   //
    2042          40 :   int nFND = (fMVVertices && fMVVertices->GetEntriesFast()) ? fMVVertices->GetEntriesFast() : 0;
    2043           8 :   if (nFND<1) { if (!fCurrentVertex) TooFewTracks(); return;} // no multiple vertices
    2044             :   //
    2045           8 :   int indCont[nFND];
    2046           8 :   int nIndx[nFND];
    2047          36 :   for (int iv=0;iv<nFND;iv++) {
    2048          10 :     AliESDVertex* fnd = (AliESDVertex*)fMVVertices->At(iv);
    2049          10 :     indCont[iv] = iv;
    2050          10 :     nIndx[iv]   = fnd->GetNIndices();
    2051             :   }
    2052           8 :   TMath::Sort(nFND, nIndx, indCont, kTRUE); // sort in decreasing order of Nindices
    2053           8 :   double dists[nFND];
    2054           8 :   int    distOrd[nFND],indx[nFND];
    2055          36 :   for (int iv=0;iv<nFND;iv++) {
    2056          10 :     AliESDVertex* fndI = (AliESDVertex*)fMVVertices->At(indCont[iv]);
    2057          12 :     if (fndI->GetStatus()<1) continue; // discarded
    2058             :     int ncomp = 0;
    2059          20 :     for (int jv=iv+1;jv<nFND;jv++) {
    2060           2 :       AliESDVertex* fndJ = (AliESDVertex*)fMVVertices->At(indCont[jv]);
    2061           2 :       if (fndJ->GetStatus()<1) continue;
    2062           2 :       dists[ncomp] = fndI->GetWDist(fndJ)*fndJ->GetNIndices();
    2063           2 :       distOrd[ncomp] = indCont[jv];
    2064           2 :       indx[ncomp]  = ncomp;
    2065           2 :       ncomp++;
    2066           2 :     }
    2067          14 :     if (ncomp<1) continue;
    2068           2 :     TMath::Sort(ncomp, dists, indx, kFALSE); // sort in increasing distance order
    2069           8 :     for (int jv0=0;jv0<ncomp;jv0++) {
    2070           2 :       int jv = distOrd[indx[jv0]];
    2071           2 :       AliESDVertex* fndJ = (AliESDVertex*)fMVVertices->At(jv);
    2072           2 :       if (dists[indx[jv0]]<fMVMaxWghNtr) { // candidate for split vertex
    2073             :         //before eliminating the small close vertex, check if we should transfere its BC to largest one
    2074           4 :         if (fndJ->GetBC()!=AliVTrack::kTOFBCNA && fndI->GetBC()==AliVTrack::kTOFBCNA) fndI->SetBC(fndJ->GetBC());
    2075             :         //
    2076             :         // leave the vertex only if both vertices have definit but different BC's, then this is not splitting.
    2077           4 :         if ( (fndJ->GetBC()==fndI->GetBC()) || (fndJ->GetBC()==AliVTrack::kTOFBCNA)) fndJ->SetNContributors(-fndJ->GetNContributors());
    2078             :       }
    2079             :     }
    2080           2 :   }
    2081             :   //
    2082             :   // select as a primary the largest vertex with BC=0, or the largest with BC non-ID
    2083             :   int primBC0=-1,primNoBC=-1;
    2084          36 :   for (int iv0=0;iv0<nFND;iv0++) {
    2085          10 :     int iv = indCont[iv0];
    2086          10 :     AliESDVertex* fndI = (AliESDVertex*)fMVVertices->At(iv);
    2087          10 :     if (!fndI) continue;
    2088          16 :     if (fndI->GetStatus()<1) {fMVVertices->RemoveAt(iv); delete fndI; continue;}
    2089          24 :     if (primBC0<0  && fndI->GetBC()==0) primBC0 = iv;
    2090          16 :     if (primNoBC<0 && fndI->GetBC()==AliVTrack::kTOFBCNA)  primNoBC = iv;
    2091           8 :   }
    2092             :   //
    2093          16 :   if (primBC0>=0) fCurrentVertex = (AliESDVertex*)fMVVertices->At(primBC0);
    2094           8 :   if (!fCurrentVertex && primNoBC>=0) fCurrentVertex = (AliESDVertex*)fMVVertices->At(primNoBC);
    2095          16 :   if (fCurrentVertex) fMVVertices->Remove(fCurrentVertex);
    2096             :   else {  // all vertices have BC>0, no primary vertex
    2097           0 :     fCurrentVertex = new AliESDVertex();
    2098           0 :     fCurrentVertex->SetNContributors(-3);
    2099           0 :     fCurrentVertex->SetBC(AliVTrack::kTOFBCNA);
    2100             :   }
    2101           8 :   fCurrentVertex->SetID(-1);
    2102             :   //
    2103             :   // add pileup vertices
    2104             :   int nadd = 0;
    2105          36 :   for (int iv0=0;iv0<nFND;iv0++) {
    2106          10 :     int iv = indCont[iv0];
    2107          10 :     AliESDVertex* fndI = (AliESDVertex*)fMVVertices->At(iv);
    2108          20 :     if (!fndI) continue;
    2109           0 :     fndI->SetID(++nadd);
    2110           0 :     esdEv->AddPileupVertexTracks(fndI);
    2111           0 :   }
    2112             :   //
    2113           8 :   fMVVertices->Delete();
    2114             :   //
    2115          16 : }
    2116             : 
    2117             : //______________________________________________________
    2118             : void AliVertexerTracks::FindAllVertices(Int_t nTrksOrig, 
    2119             :                                         const TObjArray *trkArrayOrig,
    2120             :                                         Double_t* zTr, 
    2121             :                                         Double_t* err2zTr, 
    2122             :                                         UShort_t* idOrig){
    2123             : 
    2124             :   // clusterize tracks using z coordinates of intersection with beam axis
    2125             :   // and compute all vertices 
    2126             : 
    2127           0 :   UShort_t* posOrig=new UShort_t[nTrksOrig];
    2128           0 :   for(Int_t iTr=0; iTr<nTrksOrig; iTr++) posOrig[iTr]=iTr;
    2129             :  
    2130             : 
    2131             :   // sort points along Z
    2132           0 :   AliDebug(1,Form("Sort points along Z, used tracks %d",nTrksOrig));
    2133           0 :   for(Int_t iTr1=0; iTr1<nTrksOrig; iTr1++){
    2134           0 :     for(Int_t iTr2=iTr1+1; iTr2<nTrksOrig; iTr2++){
    2135           0 :       if(zTr[iTr1]>zTr[iTr2]){
    2136             :         Double_t tmpz=zTr[iTr2];
    2137           0 :         Double_t tmperr=err2zTr[iTr2];
    2138           0 :         UShort_t tmppos=posOrig[iTr2];
    2139           0 :         UShort_t tmpid=idOrig[iTr2];
    2140           0 :         zTr[iTr2]=zTr[iTr1];
    2141           0 :         err2zTr[iTr2]=err2zTr[iTr1];
    2142           0 :         posOrig[iTr2]=posOrig[iTr1];
    2143           0 :         idOrig[iTr2]=idOrig[iTr1];
    2144           0 :         zTr[iTr1]=tmpz;
    2145           0 :         err2zTr[iTr1]=tmperr;
    2146           0 :         idOrig[iTr1]=tmpid;
    2147           0 :         posOrig[iTr1]=tmppos;
    2148           0 :       }
    2149             :     }
    2150             :   }
    2151             : 
    2152             :   // clusterize
    2153             :   Int_t nClusters=0;
    2154           0 :   Int_t* firstTr=new Int_t[nTrksOrig];
    2155           0 :   Int_t* lastTr=new Int_t[nTrksOrig];
    2156             : 
    2157           0 :   firstTr[0]=0;
    2158           0 :   for(Int_t iTr=0; iTr<nTrksOrig-1; iTr++){
    2159           0 :     Double_t distz=zTr[iTr+1]-zTr[iTr];
    2160           0 :     Double_t errdistz=TMath::Sqrt(err2zTr[iTr+1]+err2zTr[iTr]);
    2161           0 :     if(errdistz<=0.000001) errdistz=0.000001;
    2162           0 :     if(distz>fDeltaZCutForCluster || (distz/errdistz)>fnSigmaZCutForCluster){
    2163           0 :       lastTr[nClusters]=iTr;
    2164           0 :       firstTr[nClusters+1]=iTr+1;
    2165             :       nClusters++;
    2166           0 :     }
    2167             :   }
    2168           0 :   lastTr[nClusters]=nTrksOrig-1;
    2169             : 
    2170             :   // Compute vertices
    2171           0 :   AliDebug(1,Form("Number of found clusters %d",nClusters+1));
    2172             :   Int_t nFoundVertices=0;
    2173             : 
    2174           0 :   if (!fMVVertices) fMVVertices = new TObjArray(nClusters+1);
    2175             : 
    2176           0 :   fMVVertices->Clear();
    2177           0 :   TObjArray cluTrackArr(nTrksOrig);
    2178           0 :   UShort_t *idTrkClu=new UShort_t[nTrksOrig];
    2179             :   //  Int_t maxContr=0;
    2180             :   //  Int_t maxPos=-1;
    2181             : 
    2182           0 :   for(Int_t iClu=0; iClu<=nClusters; iClu++){
    2183           0 :     Int_t nCluTracks=lastTr[iClu]-firstTr[iClu]+1;
    2184           0 :     cluTrackArr.Clear();
    2185           0 :     AliDebug(1,Form(" Vertex #%d tracks %d first tr %d  last track %d",iClu,nCluTracks,firstTr[iClu],lastTr[iClu]));
    2186             :     Int_t nSelTr=0;
    2187           0 :     for(Int_t iTr=firstTr[iClu]; iTr<=lastTr[iClu]; iTr++){
    2188           0 :       AliExternalTrackParam* t=(AliExternalTrackParam*)trkArrayOrig->At(posOrig[iTr]);
    2189           0 :       if(TMath::Abs(t->GetZ()-zTr[iTr])>0.00001){
    2190           0 :         AliError(Form("Clu %d Track %d zTrack=%f  zVec=%f\n",iClu,iTr,t->GetZ(),zTr[iTr]));
    2191             :       }
    2192           0 :       cluTrackArr.AddAt(t,nSelTr);
    2193           0 :       idTrkClu[nSelTr]=idOrig[iTr];
    2194           0 :       AliDebug(1,Form("   Add track %d: id %d, z=%f",iTr,idOrig[iTr],zTr[iTr]));
    2195           0 :       nSelTr++;
    2196             :     }
    2197           0 :     AliESDVertex* vert=FindPrimaryVertex(&cluTrackArr,idTrkClu);
    2198           0 :     AliDebug(1,Form("Found vertex in z=%f with %d contributors",vert->GetZ(),
    2199             :                  vert->GetNContributors()));
    2200             : 
    2201           0 :     fCurrentVertex=0;
    2202           0 :     if(vert->GetNContributors()>0){
    2203           0 :       nFoundVertices++;
    2204           0 :       fMVVertices->AddLast(vert);
    2205             :     }
    2206             :     //    if(vert->GetNContributors()>maxContr){
    2207             :     //      maxContr=vert->GetNContributors();
    2208             :     //      maxPos=nFoundVertices-1;
    2209             :     //    }
    2210             :   }
    2211             : 
    2212           0 :   AliDebug(1,Form("Number of found vertices %d (%d)",nFoundVertices,fMVVertices->GetEntriesFast()));
    2213             :   // if(maxPos>=0 && maxContr>0){
    2214             :   //   AliESDVertex* vtxMax=(AliESDVertex*)fMVVertices->At(maxPos);
    2215             :   //   if(fCurrentVertex) delete fCurrentVertex; 
    2216             :   //   fCurrentVertex=new AliESDVertex(*vtxMax);
    2217             :   // }
    2218             : 
    2219           0 :   delete [] firstTr;
    2220           0 :   delete [] lastTr;
    2221           0 :   delete [] idTrkClu;
    2222           0 :   delete [] posOrig;
    2223             : 
    2224             :   return;
    2225             : 
    2226           0 : }

Generated by: LCOV version 1.11