LCOV - code coverage report
Current view: top level - TRD/TRDbase - AliTRDseedV1.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 768 1335 57.5 %
Date: 2016-06-14 17:26:59 Functions: 31 47 66.0 %

          Line data    Source code
       1             : /**************************************************************************
       2             : * Copyright(c) 1998-1999, 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             : /* $Id: AliTRDseedV1.cxx 60233 2013-01-10 09:04:08Z abercuci $ */
      17             : 
      18             : ////////////////////////////////////////////////////////////////////////////
      19             : ////
      20             : //  The TRD offline tracklet
      21             : //
      22             : // The running horse of the TRD reconstruction. The following tasks are preformed:
      23             : //   1. Clusters attachment to tracks based on prior information stored at tracklet level (see AttachClusters)
      24             : //   2. Clusters position recalculation based on track information (see GetClusterXY and Fit)
      25             : //   3. Cluster error parametrization recalculation (see Fit)
      26             : //   4. Linear track approximation (Fit)
      27             : //   5. Optimal position (including z estimate for pad row cross tracklets) and covariance matrix of the track fit inside one TRD chamber (Fit)
      28             : //   6. Tilt pad correction and systematic effects (GetCovAt)
      29             : //   7. dEdx calculation (CookdEdx)
      30             : //   8. PID probabilities estimation (CookPID)
      31             : //
      32             : //  Authors:                                                              //
      33             : //    Alex Bercuci <A.Bercuci@gsi.de>                                     //
      34             : //    Markus Fasel <M.Fasel@gsi.de>                                       //
      35             : //                                                                        //
      36             : ////////////////////////////////////////////////////////////////////////////
      37             : 
      38             : #include "TMath.h"
      39             : #include "TGeoManager.h"
      40             : #include "TTreeStream.h"
      41             : #include "TGraphErrors.h"
      42             : 
      43             : #include "AliLog.h"
      44             : #include "AliMathBase.h"
      45             : #include "AliRieman.h"
      46             : #include "AliCDBManager.h"
      47             : 
      48             : #include "AliTRDReconstructor.h"
      49             : #include "AliTRDpadPlane.h"
      50             : #include "AliTRDtransform.h"
      51             : #include "AliTRDcluster.h"
      52             : #include "AliTRDseedV1.h"
      53             : #include "AliTRDtrackV1.h"
      54             : #include "AliTRDcalibDB.h"
      55             : #include "AliTRDchamberTimeBin.h"
      56             : #include "AliTRDtrackingChamber.h"
      57             : #include "AliTRDtrackerV1.h"
      58             : #include "AliTRDrecoParam.h"
      59             : #include "AliTRDCommonParam.h"
      60             : #include "AliTRDtrackletOflHelper.h"
      61             : 
      62             : #include "AliTRDCalTrkAttach.h"
      63             : #include "AliTRDCalPID.h"
      64             : #include "AliTRDCalROC.h"
      65             : #include "AliTRDCalDet.h"
      66             : 
      67             : class AliTracker;
      68             : 
      69          48 : ClassImp(AliTRDseedV1)
      70             : 
      71             : //____________________________________________________________________
      72             : AliTRDseedV1::AliTRDseedV1(Int_t det) 
      73         369 :   :AliTRDtrackletBase()
      74         369 :   ,fkReconstructor(NULL)
      75         369 :   ,fClusterIter(NULL)
      76         369 :   ,fExB(0.)
      77         369 :   ,fVD(0.)
      78         369 :   ,fT0(0.)
      79         369 :   ,fS2PRF(0.)
      80         369 :   ,fDiffL(0.)
      81         369 :   ,fDiffT(0.)
      82         369 :   ,fClusterIdx(0)
      83         369 :   ,fErrorMsg(0)
      84         369 :   ,fN(0)
      85         369 :   ,fDet(det)
      86         369 :   ,fPt(0.)
      87         369 :   ,fdX(0.)
      88         369 :   ,fX0(0.)
      89         369 :   ,fX(0.)
      90         369 :   ,fY(0.)
      91         369 :   ,fZ(0.)
      92         369 :   ,fS2Y(0.)
      93         369 :   ,fS2Z(0.)
      94         369 :   ,fChi2(0.)
      95        1845 : {
      96             :   //
      97             :   // Constructor
      98             :   //
      99         369 :   memset(fIndexes,0xFF,kNclusters*sizeof(fIndexes[0]));
     100         369 :   memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
     101         369 :   memset(fPad, 0, 4*sizeof(Float_t));
     102         369 :   fYref[0] = 0.; fYref[1] = 0.; 
     103         369 :   fZref[0] = 0.; fZref[1] = 0.; 
     104         369 :   fYfit[0] = 0.; fYfit[1] = 0.; 
     105         369 :   fZfit[0] = 0.; fZfit[1] = 0.; 
     106         369 :   memset(fdEdx, 0, kNdEdxSlices*sizeof(Float_t));
     107        4428 :   for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec]  = -1.;
     108         369 :   fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
     109         369 :   fLabels[2]=0;  // number of different labels for tracklet
     110         369 :   memset(fRefCov, 0, 7*sizeof(Double_t));
     111             :   // stand alone curvature
     112         369 :   fC[0] = 0.; fC[1] = 0.; 
     113             :   // covariance matrix [diagonal]
     114             :   // default sy = 200um and sz = 2.3 cm 
     115         369 :   fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3; 
     116         369 :   SetStandAlone(kFALSE);
     117         738 : }
     118             : 
     119             : //____________________________________________________________________
     120             : AliTRDseedV1::AliTRDseedV1(const AliTRDseedV1 &ref)
     121         412 :   :AliTRDtrackletBase((AliTRDtrackletBase&)ref)
     122         412 :   ,fkReconstructor(NULL)
     123         412 :   ,fClusterIter(NULL)
     124         412 :   ,fExB(0.)
     125         412 :   ,fVD(0.)
     126         412 :   ,fT0(0.)
     127         412 :   ,fS2PRF(0.)
     128         412 :   ,fDiffL(0.)
     129         412 :   ,fDiffT(0.)
     130         412 :   ,fClusterIdx(0)
     131         412 :   ,fErrorMsg(0)
     132         412 :   ,fN(0)
     133         412 :   ,fDet(-1)
     134         412 :   ,fPt(0.)
     135         412 :   ,fdX(0.)
     136         412 :   ,fX0(0.)
     137         412 :   ,fX(0.)
     138         412 :   ,fY(0.)
     139         412 :   ,fZ(0.)
     140         412 :   ,fS2Y(0.)
     141         412 :   ,fS2Z(0.)
     142         412 :   ,fChi2(0.)
     143        2060 : {
     144             :   //
     145             :   // Copy Constructor performing a deep copy
     146             :   //
     147         412 :   if(this != &ref){
     148         412 :     ref.Copy(*this);
     149             :   }
     150         412 :   SetBit(kOwner, kFALSE);
     151         824 :   SetStandAlone(ref.IsStandAlone());
     152         824 : }
     153             : 
     154             : 
     155             : //____________________________________________________________________
     156             : AliTRDseedV1& AliTRDseedV1::operator=(const AliTRDseedV1 &ref)
     157             : {
     158             :   //
     159             :   // Assignment Operator using the copy function
     160             :   //
     161             : 
     162           0 :   if(this != &ref){
     163           0 :     ref.Copy(*this);
     164           0 :   }
     165           0 :   SetBit(kOwner, kFALSE);
     166             : 
     167           0 :   return *this;
     168             : }
     169             : 
     170             : //____________________________________________________________________
     171             : AliTRDseedV1::~AliTRDseedV1()
     172        3950 : {
     173             :   //
     174             :   // Destructor. The RecoParam object belongs to the underlying tracker.
     175             :   //
     176             : 
     177             :   //printf("I-AliTRDseedV1::~AliTRDseedV1() : Owner[%s]\n", IsOwner()?"YES":"NO");
     178             : 
     179        1562 :   if(IsOwner()) {
     180       25956 :     for(int itb=0; itb<kNclusters; itb++){
     181       12772 :       if(!fClusters[itb]) continue; 
     182             :       //AliInfo(Form("deleting c %p @ %d", fClusters[itb], itb));
     183        8960 :       delete fClusters[itb];
     184        4480 :       fClusters[itb] = NULL;
     185        4480 :     }
     186         206 :   }
     187        1975 : }
     188             : 
     189             : //____________________________________________________________________
     190             : void AliTRDseedV1::Copy(TObject &ref) const
     191             : {
     192             :   //
     193             :   // Copy function
     194             :   //
     195             : 
     196             :   //AliInfo("");
     197         824 :   AliTRDseedV1 &target = (AliTRDseedV1 &)ref; 
     198             : 
     199         412 :   target.fkReconstructor = fkReconstructor;
     200         412 :   target.fClusterIter   = NULL;
     201         412 :   target.fExB           = fExB;
     202         412 :   target.fVD            = fVD;
     203         412 :   target.fT0            = fT0;
     204         412 :   target.fS2PRF         = fS2PRF;
     205         412 :   target.fDiffL         = fDiffL;
     206         412 :   target.fDiffT         = fDiffT;
     207         412 :   target.fClusterIdx    = 0;
     208         412 :   target.fErrorMsg      = fErrorMsg;
     209         412 :   target.fN             = fN;
     210         412 :   target.fDet           = fDet;
     211         412 :   target.fPt            = fPt;
     212         412 :   target.fdX            = fdX;
     213         412 :   target.fX0            = fX0;
     214         412 :   target.fX             = fX;
     215         412 :   target.fY             = fY;
     216         412 :   target.fZ             = fZ;
     217         412 :   target.fS2Y           = fS2Y;
     218         412 :   target.fS2Z           = fS2Z;
     219         412 :   target.fChi2          = fChi2;
     220             :   
     221         412 :   memcpy(target.fIndexes, fIndexes, kNclusters*sizeof(Int_t));
     222         412 :   memcpy(target.fClusters, fClusters, kNclusters*sizeof(AliTRDcluster*));
     223         412 :   memcpy(target.fPad, fPad, 4*sizeof(Float_t));
     224         412 :   target.fYref[0] = fYref[0]; target.fYref[1] = fYref[1]; 
     225         412 :   target.fZref[0] = fZref[0]; target.fZref[1] = fZref[1]; 
     226         412 :   target.fYfit[0] = fYfit[0]; target.fYfit[1] = fYfit[1]; 
     227         412 :   target.fZfit[0] = fZfit[0]; target.fZfit[1] = fZfit[1]; 
     228         412 :   memcpy(target.fdEdx, fdEdx, kNdEdxSlices*sizeof(Float_t));
     229         412 :   memcpy(target.fProb, fProb, AliPID::kSPECIES*sizeof(Float_t)); 
     230         412 :   memcpy(target.fLabels, fLabels, 3*sizeof(Int_t)); 
     231         412 :   memcpy(target.fRefCov, fRefCov, 7*sizeof(Double_t)); 
     232         412 :   target.fC[0] = fC[0]; target.fC[1] = fC[1];
     233         412 :   memcpy(target.fCov, fCov, 3*sizeof(Double_t)); 
     234             :   
     235         412 :   TObject::Copy(ref);
     236         412 : }
     237             : 
     238             : 
     239             : //____________________________________________________________
     240             : void AliTRDseedV1::Init(const AliRieman *rieman)
     241             : {
     242             : // Initialize this tracklet using the riemann fit information
     243             : 
     244             : 
     245           0 :   fZref[0] = rieman->GetZat(fX0);
     246           0 :   fZref[1] = rieman->GetDZat(fX0);
     247           0 :   fYref[0] = rieman->GetYat(fX0);
     248           0 :   fYref[1] = rieman->GetDYat(fX0);
     249           0 :   if(fkReconstructor && fkReconstructor->IsHLT()){
     250           0 :     fRefCov[0] = 1;
     251           0 :     fRefCov[2] = 10;
     252           0 :   }else{
     253           0 :     fRefCov[0] = rieman->GetErrY(fX0);
     254           0 :     fRefCov[2] = rieman->GetErrZ(fX0);
     255             :   }
     256           0 :   fC[0]    = rieman->GetC(); 
     257           0 :   fChi2    = rieman->GetChi2();
     258           0 : }
     259             : 
     260             : 
     261             : //____________________________________________________________
     262             : Bool_t AliTRDseedV1::Init(const AliTRDtrackV1 *track)
     263             : {
     264             : // Initialize this tracklet using the track information
     265             : //
     266             : // Parameters:
     267             : //   track - the TRD track used to initialize the tracklet
     268             : // 
     269             : // Detailed description
     270             : // The function sets the starting point and direction of the
     271             : // tracklet according to the information from the TRD track.
     272             : // 
     273             : // Caution
     274             : // The TRD track has to be propagated to the beginning of the
     275             : // chamber where the tracklet will be constructed
     276             : //
     277             : 
     278         524 :   Double_t y, z; 
     279         262 :   if(!track->GetProlongation(fX0, y, z)) return kFALSE;
     280         262 :   Update(track);
     281         262 :   return kTRUE;
     282         262 : }
     283             : 
     284             : 
     285             : //_____________________________________________________________________________
     286             : void AliTRDseedV1::Reset(Option_t *opt)
     287             : {
     288             : //
     289             : // Reset seed. If option opt="c" is given only cluster arrays are cleared.
     290             : //
     291           0 :   for(Int_t ic=kNclusters; ic--;) fIndexes[ic] = -1;
     292           0 :   memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
     293           0 :   fN=0; SetBit(kRowCross, kFALSE);
     294           0 :   if(strcmp(opt, "c")==0) return;
     295             : 
     296           0 :   fExB=0.;fVD=0.;fT0=0.;fS2PRF=0.;
     297           0 :   fDiffL=0.;fDiffT=0.;
     298           0 :   fClusterIdx=0;
     299           0 :   fErrorMsg = 0;
     300           0 :   fDet=-1;
     301           0 :   fPt=0.;
     302           0 :   fdX=0.;fX0=0.; fX=0.; fY=0.; fZ=0.;
     303           0 :   fS2Y=0.; fS2Z=0.;
     304           0 :   fC[0]=0.; fC[1]=0.; 
     305           0 :   fChi2 = 0.;
     306             : 
     307           0 :   memset(fPad, 0, 4*sizeof(Float_t));
     308           0 :   fYref[0] = 0.; fYref[1] = 0.; 
     309           0 :   fZref[0] = 0.; fZref[1] = 0.; 
     310           0 :   fYfit[0] = 0.; fYfit[1] = 0.; 
     311           0 :   fZfit[0] = 0.; fZfit[1] = 0.; 
     312           0 :   memset(fdEdx, 0, kNdEdxSlices*sizeof(Float_t));
     313           0 :   for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec]  = -1.;
     314           0 :   fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
     315           0 :   fLabels[2]=0;  // number of different labels for tracklet
     316           0 :   memset(fRefCov, 0, 7*sizeof(Double_t));
     317             :   // covariance matrix [diagonal]
     318             :   // default sy = 200um and sz = 2.3 cm 
     319           0 :   fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3; 
     320           0 : }
     321             : 
     322             : //____________________________________________________________________
     323             : void AliTRDseedV1::Update(const AliTRDtrackV1 *trk)
     324             : { 
     325             :   // update tracklet reference position from the TRD track
     326             : 
     327         524 :   Double_t fSnp = trk->GetSnp();
     328         262 :   Double_t fTgl = trk->GetTgl();
     329         262 :   fPt = trk->Pt();
     330         262 :   Double_t norm =1./TMath::Sqrt((1.-fSnp)*(1.+fSnp)); 
     331         262 :   fYref[1] = fSnp*norm;
     332         262 :   fZref[1] = fTgl*norm;
     333         262 :   SetCovRef(trk->GetCovariance());
     334             : 
     335         262 :   Double_t dx = trk->GetX() - fX0;
     336         262 :   fYref[0] = trk->GetY() - dx*fYref[1];
     337         262 :   fZref[0] = trk->GetZ() - dx*fZref[1];
     338         262 : }
     339             : 
     340             : //_____________________________________________________________________________
     341             : void AliTRDseedV1::UpdateUsed()
     342             : {
     343             :   //
     344             :   // Calculate number of used clusers in the tracklet
     345             :   //
     346             : 
     347             :   Int_t nused = 0, nshared = 0;
     348       14820 :   for (Int_t i = kNclusters; i--; ) {
     349       14136 :     if (!fClusters[i]) continue;
     350        4968 :     if(fClusters[i]->IsUsed()){ 
     351           0 :       nused++;
     352        4968 :     } else if(fClusters[i]->IsShared()){
     353           0 :       if(IsStandAlone()) nused++;
     354           0 :       else nshared++;
     355             :     }
     356             :   }
     357         228 :   SetNUsed(nused);
     358         228 :   SetNShared(nshared);
     359         228 : }
     360             : 
     361             : //_____________________________________________________________________________
     362             : void AliTRDseedV1::UseClusters()
     363             : {
     364             :   //
     365             :   // Use clusters
     366             :   //
     367             :   // In stand alone mode:
     368             :   // Clusters which are marked as used or shared from another track are
     369             :   // removed from the tracklet
     370             :   //
     371             :   // In barrel mode:
     372             :   // - Clusters which are used by another track become shared
     373             :   // - Clusters which are attached to a kink track become shared
     374             :   //
     375         412 :   AliTRDcluster **c = &fClusters[0];
     376       25956 :   for (Int_t ic=kNclusters; ic--; c++) {
     377       12772 :     if(!(*c)) continue;
     378        8960 :     if(IsStandAlone()){
     379        4480 :       if((*c)->IsShared() || (*c)->IsUsed()){ 
     380           0 :         if((*c)->IsShared()) SetNShared(GetNShared()-1);
     381           0 :         else SetNUsed(GetNUsed()-1);
     382           0 :         (*c) = NULL;
     383           0 :         fIndexes[ic] = -1;
     384           0 :         SetN(GetN()-1);
     385           0 :         continue;
     386             :       }
     387             :     } else {
     388        8960 :       if((*c)->IsUsed() || IsKink()){
     389           0 :         (*c)->SetShared();
     390           0 :         continue;
     391             :       }
     392             :     }
     393        4480 :     (*c)->Use();
     394        4480 :   }
     395         206 : }
     396             : 
     397             : 
     398             : 
     399             : //____________________________________________________________________
     400             : void AliTRDseedV1::CookdEdx(Int_t nslices)
     401             : {
     402             : // Calculates average dE/dx for all slices and store them in the internal array fdEdx. 
     403             : //
     404             : // Parameters:
     405             : //  nslices : number of slices for which dE/dx should be calculated
     406             : // Output:
     407             : //  store results in the internal array fdEdx. This can be accessed with the method
     408             : //  AliTRDseedV1::GetdEdx()
     409             : //
     410             : // Detailed description
     411             : // Calculates average dE/dx for all slices. Depending on the PID methode 
     412             : // the number of slices can be 3 (LQ) or 8(NN). 
     413             : // The calculation of dQ/dl are done using the tracklet fit results (see AliTRDseedV1::GetdQdl(Int_t))
     414             : //
     415             : // The following effects are included in the calculation:
     416             : // 1. calibration values for t0 and vdrift (using x coordinate to calculate slice)
     417             : // 2. cluster sharing (optional see AliTRDrecoParam::SetClusterSharing())
     418             : // 3. cluster size
     419             : //
     420             : 
     421         412 :   memset(fdEdx, 0, kNdEdxSlices*sizeof(Float_t));
     422         206 :   const Double_t kDriftLength = (.5 * AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick());
     423             : 
     424             :   AliTRDcluster *c(NULL);
     425       11536 :   for(int ic=0; ic<AliTRDtrackerV1::GetNTimeBins(); ic++){
     426        6808 :     if(!(c = fClusters[ic]) && !(c = fClusters[ic+kNtb])) continue;
     427        4444 :     Float_t dx = TMath::Abs(fX0 - c->GetX());
     428             : 
     429             :     // Filter clusters for dE/dx calculation
     430             : 
     431             :     // 1.consider calibration effects for slice determination
     432             :     Int_t slice;
     433        4444 :     if(dx<kDriftLength){ // TODO should be replaced by c->IsInChamber()
     434        4300 :       slice = Int_t(dx * nslices / kDriftLength);
     435        4444 :     } else slice = c->GetX() < fX0 ? nslices-1 : 0;
     436             : 
     437             : 
     438             :     // 2. take sharing into account
     439             :     Float_t w = /*c->IsShared() ? .5 :*/ 1.;
     440             : 
     441             :     // 3. take into account large clusters TODO
     442             :     //w *= c->GetNPads() > 3 ? .8 : 1.;
     443             : 
     444             :     //CHECK !!!
     445        4444 :     fdEdx[slice]   += w * GetdQdl(ic); //fdQdl[ic];
     446        4444 :   } // End of loop over clusters
     447         206 : }
     448             : 
     449             : //_____________________________________________________________________________
     450             : void AliTRDseedV1::CookLabels()
     451             : {
     452             :   //
     453             :   // Cook 2 labels for seed
     454             :   //
     455             : 
     456           0 :   Int_t labels[200];
     457           0 :   Int_t out[200];
     458             :   Int_t nlab = 0;
     459           0 :   for (Int_t i = 0; i < kNclusters; i++) {
     460           0 :     if (!fClusters[i]) continue;
     461           0 :     for (Int_t ilab = 0; ilab < 3; ilab++) {
     462           0 :       if (fClusters[i]->GetLabel(ilab) >= 0) {
     463           0 :         labels[nlab] = fClusters[i]->GetLabel(ilab);
     464           0 :         nlab++;
     465           0 :       }
     466             :     }
     467           0 :   }
     468             : 
     469           0 :   fLabels[2] = AliMathBase::Freq(nlab,labels,out,kTRUE);
     470           0 :   fLabels[0] = out[0];
     471           0 :   if ((fLabels[2]  > 1) && (out[3] > 1)) fLabels[1] = out[2];
     472           0 : }
     473             : 
     474             : //____________________________________________________________
     475             : Float_t AliTRDseedV1::GetAnodeWireOffset(Float_t zt)
     476             : {
     477             : // Find position inside the amplification cell for reading drift velocity map
     478             : 
     479           0 :   Float_t d = fPad[3] - zt;
     480           0 :   if(d<0.){
     481           0 :     AliError(Form("Fail AnodeWireOffset calculation z0[%+7.2f] zt[%+7.2f] d[%+7.2f].", fPad[3], zt, d));
     482           0 :     return 0.125;
     483             :   } 
     484           0 :   d -= ((Int_t)(2 * d)) / 2.0;
     485           0 :   if(d > 0.25) d = 0.5 - d;
     486           0 :   return d;
     487           0 : }
     488             : 
     489             : 
     490             : //____________________________________________________________________
     491             : Float_t AliTRDseedV1::GetCharge(Bool_t useOutliers) const
     492             : {
     493             : // Computes total charge attached to tracklet. If "useOutliers" is set clusters 
     494             : // which are not in chamber are also used (default false)
     495             : 
     496             :   AliTRDcluster *c(NULL); Float_t qt(0.);
     497       51912 :   for(int ic=0; ic<kNclusters; ic++){
     498       25544 :     if(!(c=fClusters[ic])) continue;
     499        9516 :     if(!c->IsInChamber() && !useOutliers) continue;
     500        8960 :     qt += TMath::Abs(c->GetQ());
     501        8960 :   }
     502         412 :   return qt;
     503             : }
     504             : 
     505             : //____________________________________________________________________
     506             : Int_t AliTRDseedV1::GetChargeGaps(Float_t sz[kNtb], Float_t pos[kNtb], Int_t isz[kNtb]) const
     507             : {
     508             : // Find number, size and position of charge gaps (consecutive missing time bins).
     509             : // Returns the number of gaps and fills their size in input array "sz" and position in array "pos"
     510             : 
     511             :   Bool_t gap(kFALSE);
     512             :   Int_t n(0);
     513           0 :   Int_t ipos[kNtb]; memset(isz, 0, kNtb*sizeof(Int_t));memset(ipos, 0, kNtb*sizeof(Int_t));
     514           0 :   for(int ic(0); ic<kNtb; ic++){
     515           0 :     if(fClusters[ic] || fClusters[ic+kNtb]){
     516           0 :       if(gap) n++;
     517             :       continue;
     518             :     }
     519             :     gap = kTRUE;
     520           0 :     isz[n]++;
     521           0 :     ipos[n] = ic;
     522           0 :   }
     523           0 :   if(!n) return 0;
     524             : 
     525             :   // write calibrated values
     526           0 :   AliTRDcluster fake;
     527           0 :   for(Int_t igap(0); igap<n; igap++){
     528           0 :     sz[igap] = isz[igap]*fVD/AliTRDCommonParam::Instance()->GetSamplingFrequency();
     529           0 :     fake.SetPadTime(ipos[igap]);
     530           0 :     pos[igap] = fake.GetXloc(fT0, fVD);
     531           0 :     if(isz[igap]>1){
     532           0 :       fake.SetPadTime(ipos[igap]-isz[igap]+1);
     533           0 :       pos[igap] += fake.GetXloc(fT0, fVD);
     534           0 :       pos[igap] /= 2.;
     535           0 :     }
     536             :   }
     537             :   return n;
     538           0 : }
     539             : 
     540             : 
     541             : //____________________________________________________________________
     542             : Double_t AliTRDseedV1::EstimatedCrossPoint(AliTRDpadPlane *pp, Float_t bz)
     543             : {
     544             : // Algorithm to estimate cross point in the x-z plane for pad row cross tracklets or the z coordinate of pad row without pad row cross in the local chamber coordinates.
     545             : // Returns variance of the radial offset from anode wire in case of raw cross or 0 otherwise.
     546             : 
     547             :   Int_t row[] = {-1, -1};
     548         456 :   Double_t zoff(0.5 * (pp->GetRow0() + pp->GetRowEnd())), sx(0.), mean(0.5*pp->GetNrows()-0.5);
     549             :   AliTRDcluster *c(NULL);
     550         228 :   fS2Y = 0.;
     551             :   
     552         228 :   if(!IsRowCross()){ 
     553        1396 :     for(int ic=0; ic<kNtb; ic++){
     554         698 :       if(!(c=fClusters[ic])) continue;
     555         354 :       if(!c->IsInChamber()) continue;
     556         214 :       row[0]   = c->GetPadRow();
     557         428 :       fZfit[0] = Int_t(mean-row[0])*pp->GetLengthIPad() + 
     558         856 :                  0.5*(mean-row[0]>0.?1.:-1.)*(row[0]>0&&row[0]<pp->GetNrows()-1?pp->GetLengthIPad():pp->GetLengthOPad());      
     559         214 :       break;
     560             :     }
     561         214 :   } else {  
     562             :     Float_t tbm[2] = {0.}; // mean value of time bin in rows
     563          14 :     Int_t tb[kNtb]={0}, //array of time bins from first row
     564             :           nc[2] = {0},  // no. of clusters in rows
     565             :           mc(0);  // no. of common clusters
     566             :     Bool_t w[2] = {kFALSE, kFALSE};   // acceptance flag for rows
     567             :     // Find radial range for first row
     568         896 :     for(int ic(0); ic<kNtb; ic++){
     569         434 :       tb[ic]= -1;
     570         618 :       if(!(c=fClusters[ic]) || !c->IsInChamber()) continue;
     571         180 :       if(row[0]<0) row[0] = c->GetPadRow();
     572         166 :       tb[nc[0]++] = ic; tbm[0] += ic;
     573         166 :     }
     574          14 :     if(nc[0]>2){
     575          14 :       tbm[0] /= nc[0];
     576             :       w[0] = kTRUE;
     577          14 :     }
     578             :     // Find radial range for second row
     579         896 :     for(int ic(kNtb), jc(0); ic<kNclusters; ic++, jc++){
     580         598 :       if(!(c=fClusters[ic]) || !c->IsInChamber()) continue;
     581         170 :       if(row[1]<0) row[1] = c->GetPadRow();
     582         156 :       tbm[1] += jc; nc[1]++;
     583        3266 :       for(Int_t kc(0); kc<nc[0]; kc++) 
     584        1450 :         if(tb[kc]==jc){
     585          34 :           tb[kc] += 100; // mark common cluster
     586          34 :           mc++;
     587          34 :           break;
     588             :         }
     589         156 :     }
     590          14 :     if(nc[1]>2){
     591          14 :       tbm[1] /= nc[1];
     592             :       w[1] = kTRUE;
     593          14 :     }
     594             :     //printf("0 : %f[%2d] 1 : %f[%2d] mc[%d]\n", tbm[0], nc[0], tbm[1], nc[1], mc);
     595          14 :     if(!w[0] && !w[1]){
     596           0 :       AliError("Too few clusters to estimate tracklet.");
     597           0 :       return -1;
     598             :     }
     599          28 :     if(!w[0] || !w[1]){ 
     600           0 :       SetBit(kRowCross, kFALSE); // reset RC bit
     601           0 :       if(w[1]) row[0] = row[1];
     602           0 :       fZfit[0] = Int_t(mean-row[0])*pp->GetLengthIPad() + 
     603           0 :                  0.5*(mean-row[0]>0.?1.:-1.)*(row[0]>0&&row[0]<pp->GetNrows()-1?pp->GetLengthIPad():pp->GetLengthOPad());      
     604           0 :     }else{ // find the best matching timebin 
     605          14 :       fZfit[0] = Int_t(mean-0.5*(row[0]+row[1]))*pp->GetLengthIPad(); 
     606             :       Int_t itb(0), dtb(0);
     607          14 :       if(!mc) { // no common range
     608           6 :         itb = Int_t(0.5*(tbm[0] + tbm[1]));
     609           6 :         dtb = Int_t(0.5*TMath::Abs(tbm[0] - tbm[1])); // simple parameterization of the cluster gap
     610           6 :       } else {
     611             :         Double_t rmax(100.); Int_t itbStart(-1), itbStop(0);
     612             :         // compute distance from 
     613         204 :         for(Int_t jc(0); jc<nc[0]; jc++){
     614          94 :           if(tb[jc] < 100) continue;
     615          34 :           Int_t ltb(tb[jc]-100);
     616          34 :           Double_t r = (1. - ltb/tbm[0])*(1. - ltb/tbm[1]);
     617             :           //printf("tb[%2d] dr[%f %f %f] rmax[%f]\n", ltb, r, 1. - ltb/tbm[0], 1. - ltb/tbm[1], rmax);
     618          56 :           if(TMath::Abs(r)<rmax){ rmax = TMath::Abs(r); itb = ltb; }
     619          42 :           if(itbStart<0) itbStart = ltb;
     620             :           itbStop = ltb;
     621          34 :         } 
     622           8 :         dtb = itbStop-itbStart+1;
     623             :       }
     624          14 :       AliTRDCommonParam *cp = AliTRDCommonParam::Instance(); 
     625          42 :       Double_t freq(cp?cp->GetSamplingFrequency():10.);
     626          14 :       fS2Y = ((itb-0.5)/freq - fT0 - 0.189)*fVD; // xOff
     627          14 :       sx   = dtb*0.288675134594812921/freq; sx *= sx; sx += 1.56e-2; sx *= fVD*fVD;
     628             :     }    
     629          28 :   }
     630             : 
     631             :   // estimate dzdx
     632         228 :   Float_t dx(fX0-fS2Y);
     633         228 :   fZfit[1] = (fZfit[0]+zoff)/dx; 
     634             : 
     635             :   // correct dzdx for the bias
     636         228 :   UnbiasDZDX(IsRowCross(), bz);
     637         228 :   if(IsRowCross()){
     638             :     // correct x_cross/sigma(x_cross) for the bias in dzdx
     639          14 :     const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam();
     640          14 :     if(recoParam){ 
     641          14 :       fS2Y += recoParam->GetCorrDZDXxcross()*TMath::Abs(fZfit[1]);
     642          14 :       sx   += recoParam->GetCorrDZDXxcross()*recoParam->GetCorrDZDXxcross()*GetS2DZDX(fZfit[1]);
     643          14 :     }
     644             :     // correct sigma(x_cross) for the width of the crossing area
     645          14 :     sx   += GetS2XcrossDZDX(TMath::Abs(fZfit[1]));
     646             :     
     647             :     // estimate z and error @ anode wire
     648          14 :     fZfit[0] += fZfit[1]*fS2Y;
     649          14 :     fS2Z  = fZfit[1]*fZfit[1]*sx+fS2Y*fS2Y*GetS2DZDX(fZfit[1]); 
     650          14 :   }
     651             :   return sx;
     652         228 : }
     653             : 
     654             : //____________________________________________________________________
     655             : void AliTRDseedV1::UnbiasDZDX(Bool_t rc, Float_t bz)
     656             : {
     657             :   // correct dzdx for the bias in z according to MC
     658         228 :   const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam();
     659         228 :   if(!recoParam) return;
     660         228 :   fZfit[1] *= recoParam->GetCorrDZDX(rc)-(bz>0?0.01:0.);
     661         242 :   if(rc) fZfit[1] += recoParam->GetCorrDZDXbiasRC(fZfit[1]<0);
     662         456 : }
     663             : 
     664             : //____________________________________________________________________
     665             : Double_t AliTRDseedV1::UnbiasY(Bool_t rc, Float_t bz)
     666             : {
     667             : // correct y coordinate for tail cancellation. This should be fixed by considering TC as a function of q/pt. 
     668             : //  rc : TRUE if tracklet crosses rows
     669             : // bz : magnetic field z component
     670             :   
     671         228 :   const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam();
     672         228 :   if(!recoParam) return 0.;
     673         228 :   Double_t par[3]={0.};
     674         228 :   Int_t idx(2*(rc?1:0)+Int_t(bz>0));
     675         228 :   recoParam->GetYcorrTailCancel(idx, par);
     676         228 :   return par[0]*TMath::Sin(par[1]*fYref[1])+par[2];
     677         456 : }
     678             : 
     679             : 
     680             : //____________________________________________________________________
     681             : Float_t AliTRDseedV1::GetQperTB(Int_t tb) const
     682             : {
     683             :   //
     684             :   // Charge of the clusters at timebin
     685             :   //
     686             :   Float_t q = 0;
     687           0 :   if(fClusters[tb] /*&& fClusters[tb]->IsInChamber()*/)
     688           0 :     q += TMath::Abs(fClusters[tb]->GetQ());
     689           0 :   if(fClusters[tb+kNtb] /*&& fClusters[tb+kNtb]->IsInChamber()*/)
     690           0 :     q += TMath::Abs(fClusters[tb+kNtb]->GetQ());
     691           0 :   return q/TMath::Sqrt(1. + fYref[1]*fYref[1] + fZref[1]*fZref[1]);
     692             : }
     693             : 
     694             : //____________________________________________________________________
     695             : Float_t AliTRDseedV1::GetdQdl() const
     696             : {
     697             : // Calculate total charge / tracklet length for 1D PID
     698             : //
     699         824 :   Float_t Q = GetCharge(kTRUE);
     700         412 :   return Q/TMath::Sqrt(1. + fYref[1]*fYref[1] + fZref[1]*fZref[1]);
     701             : }
     702             : 
     703             : //____________________________________________________________________
     704             : Float_t AliTRDseedV1::GetdQdl(Int_t ic, Float_t *dl) const
     705             : {
     706             : // Using the linear approximation of the track inside one TRD chamber (TRD tracklet) 
     707             : // the charge per unit length can be written as:
     708             : // BEGIN_LATEX
     709             : // #frac{dq}{dl} = #frac{q_{c}}{dx * #sqrt{1 + #(){#frac{dy}{dx}}^{2}_{fit} + #(){#frac{dz}{dx}}^{2}_{ref}}}
     710             : // END_LATEX
     711             : // where qc is the total charge collected in the current time bin and dx is the length 
     712             : // of the time bin. 
     713             : // The following correction are applied :
     714             : //   - charge : pad row cross corrections
     715             : //              [diffusion and TRF assymetry] TODO
     716             : //   - dx     : anisochronity, track inclination - see Fit and AliTRDcluster::GetXloc() 
     717             : //              and AliTRDcluster::GetYloc() for the effects taken into account
     718             : // 
     719             : //Begin_Html
     720             : //<img src="TRD/trackletDQDT.gif">
     721             : //End_Html
     722             : // In the picture the energy loss measured on the tracklet as a function of drift time [left] and respectively 
     723             : // drift length [right] for different particle species is displayed.
     724             : // Author : Alex Bercuci <A.Bercuci@gsi.de>
     725             : //
     726             :   Float_t dq = 0.;
     727             :   // check whether both clusters are inside the chamber
     728             :   Bool_t hasClusterInChamber = kFALSE;
     729       13204 :   if(fClusters[ic] && fClusters[ic]->IsInChamber()){
     730             :     hasClusterInChamber = kTRUE;
     731        4046 :     dq += TMath::Abs(fClusters[ic]->GetQ());
     732        4046 :   }
     733        4608 :   if(fClusters[ic+kNtb] && fClusters[ic+kNtb]->IsInChamber()){
     734             :     hasClusterInChamber = kTRUE;
     735         156 :     dq += TMath::Abs(fClusters[ic+kNtb]->GetQ());
     736         156 :   }
     737        4720 :   if(!hasClusterInChamber) return 0.;
     738        4168 :   if(dq<1.e-3) return 0.;
     739             : 
     740        4168 :   Double_t dx = fdX;
     741        8336 :   if(ic-1>=0 && ic+1<kNtb){
     742             :     Float_t x2(0.), x1(0.);
     743             :     // try to estimate upper radial position (find the cluster which is inside the chamber)
     744       11706 :     if(fClusters[ic-1] && fClusters[ic-1]->IsInChamber()) x2 = fClusters[ic-1]->GetX(); 
     745         695 :     else if(fClusters[ic-1+kNtb] && fClusters[ic-1+kNtb]->IsInChamber()) x2 = fClusters[ic-1+kNtb]->GetX(); 
     746        1003 :     else if(fClusters[ic] && fClusters[ic]->IsInChamber()) x2 = fClusters[ic]->GetX()+fdX;
     747          10 :     else x2 = fClusters[ic+kNtb]->GetX()+fdX;
     748             :     // try to estimate lower radial position (find the cluster which is inside the chamber)
     749       11683 :     if(fClusters[ic+1] && fClusters[ic+1]->IsInChamber()) x1 = fClusters[ic+1]->GetX();
     750         677 :     else if(fClusters[ic+1+kNtb] && fClusters[ic+1+kNtb]->IsInChamber()) x1 = fClusters[ic+1+kNtb]->GetX();
     751        1011 :     else if(fClusters[ic] && fClusters[ic]->IsInChamber()) x1 = fClusters[ic]->GetX()-fdX;
     752           6 :     else x1 = fClusters[ic+kNtb]->GetX()-fdX;
     753             : 
     754        4168 :     dx = .5*(x2 - x1);
     755        4168 :   }
     756        4168 :   dx *= TMath::Sqrt(1. + fYfit[1]*fYfit[1] + fZref[1]*fZref[1]);
     757        4168 :   if(dl) (*dl) = dx;
     758        8336 :   if(dx>1.e-9) return dq/dx;
     759           0 :   else return 0.;
     760        4444 : }
     761             : 
     762             : //____________________________________________________________
     763             : Float_t AliTRDseedV1::GetMomentum(Float_t *err) const
     764             : { 
     765             : // Returns momentum of the track after update with the current tracklet as:
     766             : // BEGIN_LATEX
     767             : // p=#frac{1}{1/p_{t}} #sqrt{1+tgl^{2}}
     768             : // END_LATEX
     769             : // and optionally the momentum error (if err is not null). 
     770             : // The estimated variance of the momentum is given by:
     771             : // BEGIN_LATEX
     772             : // #sigma_{p}^{2} = (#frac{dp}{dp_{t}})^{2} #sigma_{p_{t}}^{2}+(#frac{dp}{dtgl})^{2} #sigma_{tgl}^{2}+2#frac{dp}{dp_{t}}#frac{dp}{dtgl} cov(tgl,1/p_{t})
     773             : // END_LATEX
     774             : // which can be simplified to
     775             : // BEGIN_LATEX
     776             : // #sigma_{p}^{2} = p^{2}p_{t}^{4}tgl^{2}#sigma_{tgl}^{2}-2p^{2}p_{t}^{3}tgl cov(tgl,1/p_{t})+p^{2}p_{t}^{2}#sigma_{1/p_{t}}^{2}
     777             : // END_LATEX
     778             : //
     779             : 
     780         824 :   Double_t p = fPt*TMath::Sqrt(1.+fZref[1]*fZref[1]);
     781         412 :   if(err){
     782         206 :     Double_t p2 = p*p;
     783         206 :     Double_t tgl2 = fZref[1]*fZref[1];
     784         206 :     Double_t pt2 = fPt*fPt;
     785             :     Double_t s2 =
     786         206 :       p2*tgl2*pt2*pt2*fRefCov[4]
     787         206 :      -2.*p2*fZref[1]*fPt*pt2*fRefCov[5]
     788         206 :      +p2*pt2*fRefCov[6];
     789         206 :     (*err) = TMath::Sqrt(s2);
     790         206 :   }
     791         412 :   return p;
     792             : }
     793             : 
     794             : 
     795             : //____________________________________________________________________
     796             : Int_t AliTRDseedV1::GetTBoccupancy() const
     797             : {
     798             : // Returns no. of TB occupied by clusters
     799             : 
     800             :   Int_t n(0);
     801       57850 :   for(int ic(0); ic<kNtb; ic++){
     802       36552 :     if(!fClusters[ic] && !fClusters[ic+kNtb]) continue;
     803       19272 :     n++;
     804       19272 :   }
     805         890 :   return n;
     806             : }
     807             : 
     808             : //____________________________________________________________________
     809             : Int_t AliTRDseedV1::GetTBcross() const
     810             : {
     811             : // Returns no. of TB occupied by 2 clusters for pad row cross tracklets
     812             : 
     813          28 :   if(!IsRowCross()) return 0;
     814             :   Int_t n(0);
     815         896 :   for(int ic(0); ic<kNtb; ic++){
     816         654 :     if(fClusters[ic] && fClusters[ic+kNtb]) n++;
     817             :   }
     818             :   return n;
     819          14 : }
     820             : 
     821             : //____________________________________________________________________
     822             : Float_t* AliTRDseedV1::GetProbability(Bool_t force)
     823             : {       
     824           0 :   if(!force) return &fProb[0];
     825           0 :   if(!CookPID()) return NULL;
     826           0 :   return &fProb[0];
     827           0 : }
     828             : 
     829             : //____________________________________________________________
     830             : Bool_t AliTRDseedV1::CookPID()
     831             : {
     832             : // Fill probability array for tracklet from the DB.
     833             : //
     834             : // Parameters
     835             : //
     836             : // Output
     837             : //   returns pointer to the probability array and NULL if missing DB access 
     838             : //
     839             : // Retrieve PID probabilities for e+-, mu+-, K+-, pi+- and p+- from the DB according to tracklet information:
     840             : // - estimated momentum at tracklet reference point 
     841             : // - dE/dx measurements
     842             : // - tracklet length
     843             : // - TRD layer
     844             : // According to the steering settings specified in the reconstruction one of the following methods are used
     845             : // - Neural Network [default] - option "nn"  
     846             : // - 2D Likelihood - option "!nn"  
     847             : 
     848           0 :   AliWarning(Form("Obsolete function. Use AliTRDPIDResponse::GetResponse() instead."));
     849             : 
     850           0 :   AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
     851           0 :   if (!calibration) {
     852           0 :     AliError("No access to calibration data");
     853           0 :     return kFALSE;
     854             :   }
     855             : 
     856           0 :   if (!fkReconstructor) {
     857           0 :     AliError("Reconstructor not set.");
     858           0 :     return kFALSE;
     859             :   }
     860             : 
     861             :   // Retrieve the CDB container class with the parametric detector response
     862           0 :   const AliTRDCalPID *pd = calibration->GetPIDObject(fkReconstructor->GetPIDMethod());
     863           0 :   if (!pd) {
     864           0 :     AliError("No access to AliTRDCalPID object");
     865           0 :     return kFALSE;
     866             :   }
     867             : 
     868             :   // calculate tracklet length TO DO
     869           0 :   Float_t length = (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick())/ TMath::Sqrt((1.0 - GetSnp()*GetSnp()) / (1.0 + GetTgl()*GetTgl()));
     870             :   
     871             :   //calculate dE/dx
     872           0 :   CookdEdx(AliTRDCalPID::kNSlicesNN);
     873           0 :   AliDebug(4, Form("p=%6.4f[GeV/c] dEdx{%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f} l=%4.2f[cm]", GetMomentum(), fdEdx[0], fdEdx[1], fdEdx[2], fdEdx[3], fdEdx[4], fdEdx[5], fdEdx[6], fdEdx[7], length));
     874             : 
     875             :   // Sets the a priori probabilities
     876           0 :   Bool_t kPIDNN(fkReconstructor->GetPIDMethod()==AliTRDpidUtil::kNN);
     877           0 :   for(int ispec=0; ispec<AliPID::kSPECIES; ispec++)
     878           0 :     fProb[ispec] = pd->GetProbability(ispec, GetMomentum(), &fdEdx[0], length, kPIDNN?GetPlane():fkReconstructor->GetRecoParam()->GetPIDLQslices());
     879             :   
     880             :   return kTRUE;
     881           0 : }
     882             : 
     883             : //____________________________________________________________________
     884             : Float_t AliTRDseedV1::GetQuality(Bool_t kZcorr) const
     885             : {
     886             :   //
     887             :   // Returns a quality measurement of the current seed
     888             :   //
     889             : 
     890           0 :   Float_t zcorr = kZcorr ? GetTilt() * (fZfit[0] - fZref[0]) : 0.;
     891           0 :   return 
     892           0 :       .5 * TMath::Abs(18.0 - GetN())
     893           0 :     + 10.* TMath::Abs(fYfit[1] - fYref[1])
     894           0 :     + 5. * TMath::Abs(fYfit[0] - fYref[0] + zcorr)
     895           0 :     + 2. * TMath::Abs(fZfit[0] - fZref[0]) / GetPadLength();
     896             : }
     897             : 
     898             : //____________________________________________________________________
     899             : void AliTRDseedV1::GetCovAt(Double_t /*x*/, Double_t *cov) const
     900             : {
     901             : // Computes covariance in the y-z plane at radial point x (in tracking coordinates) 
     902             : // and returns the results in the preallocated array cov[3] as :
     903             : //   cov[0] = Var(y)
     904             : //   cov[1] = Cov(yz)
     905             : //   cov[2] = Var(z)
     906             : //
     907             : // Details
     908             : //
     909             : // For the linear transformation
     910             : // BEGIN_LATEX
     911             : // Y = T_{x} X^{T}
     912             : // END_LATEX
     913             : //   The error propagation has the general form
     914             : // BEGIN_LATEX
     915             : // C_{Y} = T_{x} C_{X} T_{x}^{T} 
     916             : // END_LATEX
     917             : //  We apply this formula 2 times. First to calculate the covariance of the tracklet 
     918             : // at point x we consider: 
     919             : // BEGIN_LATEX
     920             : // T_{x} = (1 x); X=(y0 dy/dx); C_{X}=#(){#splitline{Var(y0) Cov(y0, dy/dx)}{Cov(y0, dy/dx) Var(dy/dx)}} 
     921             : // END_LATEX
     922             : // and secondly to take into account the tilt angle
     923             : // BEGIN_LATEX
     924             : // T_{#alpha} = #(){#splitline{cos(#alpha) __ sin(#alpha)}{-sin(#alpha) __ cos(#alpha)}}; X=(y z); C_{X}=#(){#splitline{Var(y)    0}{0   Var(z)}} 
     925             : // END_LATEX
     926             : //
     927             : // using simple trigonometrics one can write for this last case
     928             : // BEGIN_LATEX
     929             : // C_{Y}=#frac{1}{1+tg^{2}#alpha} #(){#splitline{(#sigma_{y}^{2}+tg^{2}#alpha#sigma_{z}^{2}) __ tg#alpha(#sigma_{z}^{2}-#sigma_{y}^{2})}{tg#alpha(#sigma_{z}^{2}-#sigma_{y}^{2}) __ (#sigma_{z}^{2}+tg^{2}#alpha#sigma_{y}^{2})}} 
     930             : // END_LATEX
     931             : // which can be aproximated for small alphas (2 deg) with
     932             : // BEGIN_LATEX
     933             : // C_{Y}=#(){#splitline{#sigma_{y}^{2} __ (#sigma_{z}^{2}-#sigma_{y}^{2})tg#alpha}{((#sigma_{z}^{2}-#sigma_{y}^{2})tg#alpha __ #sigma_{z}^{2}}} 
     934             : // END_LATEX
     935             : //
     936             : // before applying the tilt rotation we also apply systematic uncertainties to the tracklet 
     937             : // position which can be tunned from outside via the AliTRDrecoParam::SetSysCovMatrix(). They might 
     938             : // account for extra misalignment/miscalibration uncertainties. 
     939             : //
     940             : // Author :
     941             : // Alex Bercuci <A.Bercuci@gsi.de> 
     942             : // Date : Jan 8th 2009
     943             : //
     944             : 
     945             : 
     946             :   //Double_t xr     = fX0-x; 
     947        1098 :   Double_t sy2    = fCov[0];// +2.*xr*fCov[1] + xr*xr*fCov[2];
     948         549 :   Double_t sz2    = fS2Z;
     949             :   //GetPadLength()*GetPadLength()/12.;
     950             : 
     951             :   // insert systematic uncertainties
     952         549 :   if(fkReconstructor){
     953         549 :     Double_t sys[15]; memset(sys, 0, 15*sizeof(Double_t));
     954         549 :     fkReconstructor->GetRecoParam()->GetSysCovMatrix(sys);
     955             : //    sy2 += sys[0];
     956             : //    sz2 += sys[1];
     957         549 :   }
     958             : 
     959             :   // rotate covariance matrix if no RC
     960         549 :   if(!IsRowCross()){
     961         514 :     Double_t t2 = GetTilt()*GetTilt();
     962         514 :     Double_t correction = 1./(1. + t2);
     963         514 :     cov[0] = (sy2+t2*sz2)*correction;
     964         514 :     cov[1] = GetTilt()*(sz2 - sy2)*correction;
     965         514 :     cov[2] = (t2*sy2+sz2)*correction;
     966         514 :    } else {
     967          35 :      cov[0] = sy2; cov[1] = 0.; cov[2] = sz2;
     968             :    }
     969             : 
     970        1647 :   AliDebug(4, Form("C(%6.1f %+6.3f %6.1f)  RC[%c]", 1.e4*TMath::Sqrt(cov[0]), cov[1], 1.e4*TMath::Sqrt(cov[2]), IsRowCross()?'y':'n'));
     971         549 : }
     972             : 
     973             : //____________________________________________________________
     974             : Int_t AliTRDseedV1::GetCovSqrt(const Double_t * const c, Double_t *d)
     975             : {
     976             : // Helper function to calculate the square root of the covariance matrix. 
     977             : // The input matrix is stored in the vector c and the result in the vector d. 
     978             : // Both arrays have to be initialized by the user with at least 3 elements. Return negative in case of failure.
     979             : // 
     980             : // For calculating the square root of the symmetric matrix c
     981             : // the following relation is used:
     982             : // BEGIN_LATEX
     983             : // C^{1/2} = VD^{1/2}V^{-1}
     984             : // END_LATEX
     985             : // with V being the matrix with the n eigenvectors as columns. 
     986             : // In case C is symmetric the followings are true:
     987             : //   - matrix D is diagonal with the diagonal given by the eigenvalues of C
     988             : //   - V = V^{-1}
     989             : //
     990             : // Author A.Bercuci <A.Bercuci@gsi.de>
     991             : // Date   Mar 19 2009
     992             : 
     993             :   const Double_t kZero(1.e-20);
     994             :   Double_t l[2], // eigenvalues
     995             :            v[3]; // eigenvectors
     996             :   // the secular equation and its solution :
     997             :   // (c[0]-L)(c[2]-L)-c[1]^2 = 0
     998             :   // L^2 - L*Tr(c)+DET(c) = 0
     999             :   // L12 = [Tr(c) +- sqrt(Tr(c)^2-4*DET(c))]/2
    1000           0 :   Double_t tr = c[0]+c[2],           // trace
    1001           0 :           det = c[0]*c[2]-c[1]*c[1]; // determinant
    1002           0 :   if(TMath::Abs(det)<kZero) return 1;
    1003           0 :   Double_t dd = TMath::Sqrt(tr*tr - 4*det);
    1004           0 :   l[0] = .5*(tr + dd*(c[0]>c[2]?-1.:1.));
    1005           0 :   l[1] = .5*(tr + dd*(c[0]>c[2]?1.:-1.));
    1006           0 :   if(l[0]<kZero || l[1]<kZero) return 2;
    1007             :   // the sym V matrix
    1008             :   // | v00   v10|
    1009             :   // | v10   v11|
    1010           0 :   Double_t den = (l[0]-c[0])*(l[0]-c[0])+c[1]*c[1];
    1011           0 :   if(den<kZero){ // almost diagonal
    1012           0 :     v[0] = TMath::Sign(0., c[1]);
    1013           0 :     v[1] = TMath::Sign(1., (l[0]-c[0]));
    1014           0 :     v[2] = TMath::Sign(0., c[1]*(l[0]-c[0])*(l[1]-c[2]));
    1015           0 :   } else {
    1016           0 :     Double_t tmp = 1./TMath::Sqrt(den);
    1017           0 :     v[0] = c[1]* tmp;
    1018           0 :     v[1] = (l[0]-c[0])*tmp;
    1019           0 :     if(TMath::Abs(l[1]-c[2])<kZero) v[2] = TMath::Sign(v[0]*(l[0]-c[0])/kZero, (l[1]-c[2]));
    1020           0 :     else v[2] = v[0]*(l[0]-c[0])/(l[1]-c[2]);
    1021             :   }
    1022             :   // the VD^{1/2}V is: 
    1023           0 :   l[0] = TMath::Sqrt(l[0]); l[1] = TMath::Sqrt(l[1]);
    1024           0 :   d[0] = v[0]*v[0]*l[0]+v[1]*v[1]*l[1];
    1025           0 :   d[1] = v[0]*v[1]*l[0]+v[1]*v[2]*l[1];
    1026           0 :   d[2] = v[1]*v[1]*l[0]+v[2]*v[2]*l[1];
    1027             : 
    1028             :   return 0;
    1029           0 : }
    1030             : 
    1031             : //____________________________________________________________
    1032             : Double_t AliTRDseedV1::GetCovInv(const Double_t * const c, Double_t *d)
    1033             : {
    1034             : // Helper function to calculate the inverse of the covariance matrix.
    1035             : // The input matrix is stored in the vector c and the result in the vector d. 
    1036             : // Both arrays have to be initialized by the user with at least 3 elements
    1037             : // The return value is the determinant or 0 in case of singularity.
    1038             : //
    1039             : // Author A.Bercuci <A.Bercuci@gsi.de>
    1040             : // Date   Mar 19 2009
    1041             : 
    1042           0 :   Double_t det = c[0]*c[2] - c[1]*c[1];
    1043           0 :   if(TMath::Abs(det)<1.e-20) return 0.;
    1044           0 :   Double_t invDet = 1./det;
    1045           0 :   d[0] = c[2]*invDet;
    1046           0 :   d[1] =-c[1]*invDet;
    1047           0 :   d[2] = c[0]*invDet;
    1048             :   return det;
    1049           0 : }
    1050             : 
    1051             : //____________________________________________________________________
    1052             : UShort_t AliTRDseedV1::GetVolumeId() const
    1053             : {
    1054             : // Returns geometry volume id by delegation 
    1055             : 
    1056        1410 :   for(Int_t ic(0);ic<kNclusters; ic++){
    1057         808 :     if(fClusters[ic]) return fClusters[ic]->GetVolumeId();
    1058             :   }
    1059           0 :   return 0;
    1060         206 : }
    1061             : 
    1062             : 
    1063             : //____________________________________________________________________
    1064             : void AliTRDseedV1::Calibrate()
    1065             : {
    1066             : // Retrieve calibration and position parameters from OCDB. 
    1067             : // The following information are used
    1068             : //  - detector index
    1069             : //  - column and row position of first attached cluster. If no clusters are attached 
    1070             : // to the tracklet a random central chamber position (c=70, r=7) will be used.
    1071             : //
    1072             : // The following information is cached in the tracklet
    1073             : //   t0 (trigger delay)
    1074             : //   drift velocity
    1075             : //   PRF width
    1076             : //   omega*tau = tg(a_L)
    1077             : //   diffusion coefficients (longitudinal and transversal)
    1078             : //
    1079             : // Author :
    1080             : // Alex Bercuci <A.Bercuci@gsi.de> 
    1081             : // Date : Jan 8th 2009
    1082             : //
    1083             : 
    1084         524 :   AliCDBManager *cdb = AliCDBManager::Instance();
    1085         262 :   if(cdb->GetRun() < 0){
    1086           0 :     AliError("OCDB manager not properly initialized");
    1087           0 :     return;
    1088             :   }
    1089             : 
    1090         262 :   AliTRDcalibDB *calib = AliTRDcalibDB::Instance();
    1091         262 :   AliTRDCalROC  *vdROC = calib->GetVdriftROC(fDet),
    1092         262 :                 *t0ROC = calib->GetT0ROC(fDet);;
    1093         262 :   const AliTRDCalDet *vdDet = calib->GetVdriftDet();
    1094         262 :   const AliTRDCalDet *t0Det = calib->GetT0Det();
    1095             : 
    1096             :   Int_t col = 70, row = 7;
    1097         262 :   AliTRDcluster **c = &fClusters[0];
    1098         262 :   if(GetN()){ 
    1099             :     Int_t ic = 0;
    1100           0 :     while (ic<kNclusters && !(*c)){ic++; c++;} 
    1101           0 :     if(*c){
    1102           0 :       col = (*c)->GetPadCol();
    1103           0 :       row = (*c)->GetPadRow();
    1104           0 :     }
    1105           0 :   }
    1106             : 
    1107         262 :   fT0    = (t0Det->GetValue(fDet) + t0ROC->GetValue(col,row)) / AliTRDCommonParam::Instance()->GetSamplingFrequency();
    1108         262 :   fVD    = vdDet->GetValue(fDet) * vdROC->GetValue(col, row);
    1109         262 :   fS2PRF = calib->GetPRFWidth(fDet, col, row); fS2PRF *= fS2PRF;
    1110         262 :   fExB   = AliTRDCommonParam::Instance()->GetOmegaTau(fVD);
    1111         524 :   AliTRDCommonParam::Instance()->GetDiffCoeff(fDiffL,
    1112         262 :   fDiffT, fVD);
    1113         786 :   AliDebug(4, Form("Calibration params for Det[%3d] Col[%3d] Row[%2d]\n  t0[%f]  vd[%f]  s2PRF[%f]  ExB[%f]  Dl[%f]  Dt[%f]", fDet, col, row, fT0, fVD, fS2PRF, fExB, fDiffL, fDiffT));
    1114             : 
    1115             : 
    1116         262 :   SetBit(kCalib, kTRUE);
    1117         524 : }
    1118             : 
    1119             : //____________________________________________________________________
    1120             : void AliTRDseedV1::SetOwner()
    1121             : {
    1122             :   //AliInfo(Form("own [%s] fOwner[%s]", own?"YES":"NO", fOwner?"YES":"NO"));
    1123             :   
    1124         412 :   if(TestBit(kOwner)) return;
    1125       25956 :   for(int ic=0; ic<kNclusters; ic++){
    1126       12772 :     if(!fClusters[ic]) continue;
    1127        8960 :     fClusters[ic] = new AliTRDcluster(*fClusters[ic]);
    1128        4480 :   }
    1129         206 :   SetBit(kOwner);
    1130         412 : }
    1131             : 
    1132             : //____________________________________________________________
    1133             : void AliTRDseedV1::SetPadPlane(AliTRDpadPlane * const p)
    1134             : {
    1135             : // Shortcut method to initialize pad geometry.
    1136         524 :   fPad[0] = p->GetLengthIPad();
    1137         262 :   fPad[1] = p->GetWidthIPad();
    1138         262 :   fPad[2] = TMath::Tan(TMath::DegToRad()*p->GetTiltingAngle());
    1139         262 :   fPad[3] = p->GetRow0() + p->GetAnodeWireOffset();
    1140         262 : }
    1141             : 
    1142             : 
    1143             : 
    1144             : //____________________________________________________________________
    1145             : Bool_t  AliTRDseedV1::AttachClusters(AliTRDtrackingChamber *const chamber, Bool_t tilt, Bool_t chgPos, Int_t ev)
    1146             : {
    1147             : //
    1148             : // Projective algorithm to attach clusters to seeding tracklets. The following steps are performed :
    1149             : // 1. Collapse x coordinate for the full detector plane
    1150             : // 2. truncated mean on y (r-phi) direction
    1151             : // 3. purge clusters
    1152             : // 4. truncated mean on z direction
    1153             : // 5. purge clusters
    1154             : //
    1155             : // Parameters
    1156             : //  - chamber : pointer to tracking chamber container used to search the tracklet
    1157             : //  - tilt    : switch for tilt correction during road building [default true]
    1158             : //  - chgPos  : mark same[kFALSE] and opposite[kTRUE] sign tracks with respect to Bz field sign [default true]
    1159             : //  - ev      : event number for debug purposes [default = -1]
    1160             : // Output
    1161             : //  - true    : if tracklet found successfully. Failure can happend because of the following:
    1162             : //      -
    1163             : // Detailed description
    1164             : //  
    1165             : // We start up by defining the track direction in the xy plane and roads. The roads are calculated based
    1166             : // on tracking information (variance in the r-phi direction) and estimated variance of the standard 
    1167             : // clusters (see AliTRDcluster::SetSigmaY2()) corrected for tilt (see GetCovAt()). From this the road is
    1168             : // BEGIN_LATEX
    1169             : // r_{y} = 3*#sqrt{12*(#sigma^{2}_{Trk}(y) + #frac{#sigma^{2}_{cl}(y) + tg^{2}(#alpha_{L})#sigma^{2}_{cl}(z)}{1+tg^{2}(#alpha_{L})})}
    1170             : // r_{z} = 1.5*L_{pad}
    1171             : // END_LATEX
    1172             : // 
    1173             : // Author : Alexandru Bercuci <A.Bercuci@gsi.de>
    1174             : // Debug  : level = 2 for calibration
    1175             : //          level = 3 for visualization in the track SR
    1176             : //          level = 4 for full visualization including digit level
    1177             : 
    1178         262 :   const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam(); //the dynamic cast in GetRecoParam is slow, so caching the pointer to it
    1179             : 
    1180             :   //RS define max cl. per layer to search
    1181             :   const int kMaxClFindPerLayer = 6;
    1182         262 :   int maxClFind = kMaxClFindPerLayer + AliTRDReconstructor::GetExtraMaxClPerLayer();
    1183             : 
    1184             :   //RS define roads with optional extension
    1185             :   const Double_t kroady = 3.; //recoParam->GetRoad1y();
    1186         262 :   const Double_t kroadz = GetPadLength() * recoParam->GetRoadzMultiplicator() + 1.;
    1187         262 :   double extraRoadY = AliTRDReconstructor::GetExtraRoadY();
    1188         262 :   double extraRoadZ = AliTRDReconstructor::GetExtraRoadZ();
    1189             : 
    1190         262 :   if(!recoParam){
    1191           0 :     AliError("Tracklets can not be used without a valid RecoParam.");
    1192           0 :     return kFALSE;
    1193             :   }
    1194         262 :   AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
    1195         262 :   if (!calibration) {
    1196           0 :     AliError("No access to calibration data");
    1197           0 :     return kFALSE;
    1198             :   }
    1199             :   // Retrieve the CDB container class with the parametric likelihood
    1200         262 :   const AliTRDCalTrkAttach *attach = calibration->GetAttachObject();
    1201         262 :   if (!attach) {
    1202           0 :     AliError("No usable AttachClusters calib object.");
    1203           0 :     return kFALSE;
    1204             :   }
    1205             : 
    1206             :   // Initialize reco params for this tracklet
    1207             :   // 1. first time bin in the drift region
    1208             :   Int_t t0 = 14;
    1209         262 :   Int_t kClmin = Int_t(recoParam->GetFindableClusters()*AliTRDtrackerV1::GetNTimeBins());
    1210             :   Int_t kTBmin = 4;
    1211             : 
    1212         262 :   Double_t sysCov[5]; recoParam->GetSysCovMatrix(sysCov); 
    1213         262 :   Double_t s2yTrk= fRefCov[0], 
    1214             :            s2yCl = 0., 
    1215         262 :            s2zCl = GetPadLength()*GetPadLength()/12., 
    1216         262 :            syRef = TMath::Sqrt(s2yTrk),
    1217         262 :            t2    = GetTilt()*GetTilt();
    1218             :   // define probing cluster (the perfect cluster) and default calibration
    1219         262 :   Short_t sig[] = {0, 0, 10, 30, 10, 0,0};
    1220         262 :   AliTRDcluster cp(fDet, 6, 75, 0, sig, 0);
    1221         262 :   if(fkReconstructor->IsHLT()) cp.SetRPhiMethod(AliTRDcluster::kCOG);
    1222         524 :   if(!IsCalibrated()) Calibrate();
    1223             : 
    1224             : /*  Int_t kroadyShift(0);
    1225             :   Float_t bz(AliTrackerBase::GetBz());
    1226             :   if(TMath::Abs(bz)>2.){
    1227             :     if(bz<0.) kroadyShift = chgPos ? +1 : -1;
    1228             :     else kroadyShift = chgPos ? -1 : +1;
    1229             :   }*/
    1230        1310 :   AliDebug(4, Form("\n       syTrk[cm]=%4.2f dydxTrk[deg]=%+6.2f Chg[%c] rY[cm]=%4.2f rZ[cm]=%5.2f TC[%c]", syRef, TMath::ATan(fYref[1])*TMath::RadToDeg(), chgPos?'+':'-', kroady, kroadz, tilt?'y':'n'));
    1231         262 :   Double_t phiTrk(TMath::ATan(fYref[1])),
    1232         262 :            thtTrk(TMath::ATan(fZref[1]));
    1233             : 
    1234             :   // working variables
    1235             :   const Int_t kNrows = 16;
    1236             :   const Int_t kNcls  = 3*kNclusters; // buffer size
    1237        8646 :   TObjArray clst[kNrows];
    1238         262 :   Bool_t blst[kNrows][kNcls];
    1239         262 :   Double_t cond[4],
    1240             :            dx, dy, dz,
    1241             :            yt, zt,
    1242             :            zc[kNrows],
    1243             :            xres[kNrows][kNcls], yres[kNrows][kNcls], zres[kNrows][kNcls], s2y[kNrows][kNcls];
    1244         262 :   Int_t idxs[kNrows][kNcls], ncl[kNrows], ncls = 0;
    1245         262 :   memset(ncl, 0, kNrows*sizeof(Int_t));
    1246         262 :   memset(zc, 0, kNrows*sizeof(Double_t));
    1247         262 :   memset(idxs, 0, kNrows*kNcls*sizeof(Int_t));
    1248         262 :   memset(xres, 0, kNrows*kNcls*sizeof(Double_t));
    1249         262 :   memset(yres, 0, kNrows*kNcls*sizeof(Double_t));
    1250         262 :   memset(zres, 0, kNrows*kNcls*sizeof(Double_t));
    1251         262 :   memset(s2y, 0, kNrows*kNcls*sizeof(Double_t));
    1252         262 :   memset(blst, 0, kNrows*kNcls*sizeof(Bool_t));   //this is 8 times faster to memset than "memset(clst, 0, kNrows*kNcls*sizeof(AliTRDcluster*))"
    1253             : 
    1254         262 :   Double_t roady(0.), s2Mean(0.); Int_t ns2Mean(0);
    1255             : 
    1256             :   // Do cluster projection and pick up cluster candidates
    1257             :   AliTRDcluster *c(NULL);
    1258             :   AliTRDchamberTimeBin *layer(NULL);
    1259             :   Bool_t kBUFFER = kFALSE;
    1260       17030 :   for (Int_t it = 0; it < kNtb; it++) {
    1261        8122 :     if(!(layer = chamber->GetTB(it))) continue;
    1262        8122 :     if(!Int_t(*layer)) continue;
    1263             :     // get track projection at layers position
    1264        5895 :     dx   = fX0 - layer->GetX();
    1265        5895 :     yt = fYref[0] - fYref[1] * dx;
    1266        5895 :     zt = fZref[0] - fZref[1] * dx;
    1267             :     // get standard cluster error corrected for tilt if selected
    1268        5895 :     cp.SetLocalTimeBin(it);
    1269        5895 :     cp.SetSigmaY2(0.02, fDiffT, fExB, dx, -1./*zt*/, fYref[1]);
    1270        5895 :     s2yCl = cp.GetSigmaY2() + sysCov[0]; if(!tilt) s2yCl = (s2yCl + t2*s2zCl)/(1.+t2);
    1271        9117 :     if(TMath::Abs(it-12)<7){ s2Mean += cp.GetSigmaY2(); ns2Mean++;}
    1272             :     // get estimated road in r-phi direction
    1273        5895 :     if (extraRoadY>0) roady = kroady + extraRoadY;
    1274        5895 :     else roady = TMath::Min(3.*TMath::Sqrt(12.*(s2yTrk + s2yCl)), kroady);
    1275       29475 :     AliDebug(5, Form("\n"
    1276             :       "  %2d xd[cm]=%6.3f yt[cm]=%7.2f zt[cm]=%8.2f\n"
    1277             :       "      syTrk[um]=%6.2f syCl[um]=%6.2f syClTlt[um]=%6.2f\n"
    1278             :       "      Ry[mm]=%f"
    1279             :       , it, dx, yt, zt
    1280             :       , 1.e4*TMath::Sqrt(s2yTrk), 1.e4*TMath::Sqrt(cp.GetSigmaY2()+sysCov[0]), 1.e4*TMath::Sqrt(s2yCl)
    1281             :       , 1.e1*roady));
    1282             : 
    1283             :     // get clusters from layer
    1284        5895 :     cond[0] = yt/*+0.5*kroadyShift*kroady*/; cond[2] = roady;
    1285        5895 :     cond[1] = zt; cond[3] = kroadz + extraRoadZ;
    1286        5895 :     Int_t n=0, idx[maxClFind]; layer->GetClusters(cond, idx, n, maxClFind);
    1287       23172 :     for(Int_t ic = n; ic--;){
    1288        5487 :       c  = (*layer)[idx[ic]];
    1289        5487 :       dx = fX0 - c->GetX();
    1290        5487 :       yt = fYref[0] - fYref[1] * dx;
    1291        5487 :       zt = fZref[0] - fZref[1] * dx;
    1292        5487 :       dz = zt - c->GetZ();
    1293       16461 :       dy = yt - (c->GetY() + (tilt ? (GetTilt() * dz) : 0.));
    1294        5487 :       Int_t r = c->GetPadRow();
    1295        5487 :       clst[r].AddAtAndExpand(c, ncl[r]);
    1296        5487 :       blst[r][ncl[r]] = kTRUE;
    1297        5487 :       idxs[r][ncl[r]] = idx[ic];
    1298        5487 :       zres[r][ncl[r]] = dz/GetPadLength();
    1299        5487 :       yres[r][ncl[r]] = dy;
    1300        5487 :       xres[r][ncl[r]] = dx;
    1301        5487 :       zc[r]           = c->GetZ();
    1302             :       // TODO temporary solution to avoid divercences in error parametrization
    1303        5487 :       s2y[r][ncl[r]]  = TMath::Min(c->GetSigmaY2()+sysCov[0], 0.025); 
    1304       27435 :       AliDebug(5, Form("   -> dy[cm]=%+7.4f yc[cm]=%7.2f row[%d] idx[%2d]", dy, c->GetY(), r, ncl[r]));
    1305        5487 :       ncl[r]++; ncls++;
    1306             : 
    1307        5487 :       if(ncl[r] >= kNcls) {
    1308           0 :         AliWarning(Form("Cluster candidates row[%d] reached buffer limit[%d]. Some may be lost.", r, kNcls));
    1309             :         kBUFFER = kTRUE;
    1310           0 :         break;
    1311             :       }
    1312        5487 :     }
    1313        5895 :     if(kBUFFER) break;
    1314       11790 :   }
    1315         262 :   if(ncls<kClmin){ 
    1316         160 :     AliDebug(1, Form("CLUSTERS FOUND %d LESS THAN THRESHOLD %d.", ncls, kClmin));
    1317          32 :     SetErrorMsg(kAttachClFound);
    1318        1088 :     for(Int_t ir(kNrows);ir--;) clst[ir].Clear();
    1319          32 :     return kFALSE;
    1320             :   }
    1321         230 :   if(ns2Mean<kTBmin){
    1322           0 :     AliDebug(1, Form("CLUSTERS IN TimeBins %d LESS THAN THRESHOLD %d.", ns2Mean, kTBmin));
    1323           0 :     SetErrorMsg(kAttachClFound);
    1324           0 :     for(Int_t ir(kNrows);ir--;) clst[ir].Clear();
    1325           0 :     return kFALSE;
    1326             :   }
    1327         230 :   s2Mean /= ns2Mean; //sMean = TMath::Sqrt(s2Mean);
    1328             :   //Double_t sRef(TMath::Sqrt(s2Mean+s2yTrk)); // reference error parameterization
    1329             : 
    1330             :   // organize row candidates
    1331         230 :   Int_t idxRow[kNrows], nrc(0); Double_t zresRow[kNrows];
    1332        7820 :   for(Int_t ir(0); ir<kNrows; ir++){
    1333        3680 :     idxRow[ir]=-1; zresRow[ir] = 999.;
    1334        3680 :     if(!ncl[ir]) continue;
    1335             :     // get mean z resolution
    1336       11745 :     dz = 0.; for(Int_t ic = ncl[ir]; ic--;) dz += zres[ir][ic]; dz/=ncl[ir];
    1337             :     // insert row
    1338         265 :     idxRow[nrc] = ir; zresRow[nrc] = TMath::Abs(dz); nrc++;
    1339         265 :   }
    1340        1150 :   AliDebug(4, Form("Found %d clusters in %d rows. Sorting ...", ncls, nrc));
    1341             : 
    1342             :   // sort row candidates
    1343         230 :   if(nrc>=2){
    1344          33 :     if(nrc==2){
    1345          31 :       if(zresRow[0]>zresRow[1]){ // swap
    1346          14 :         Int_t itmp=idxRow[1]; idxRow[1] = idxRow[0]; idxRow[0] = itmp;
    1347          14 :         Double_t dtmp=zresRow[1]; zresRow[1] = zresRow[0]; zresRow[0] = dtmp;
    1348          14 :       }
    1349          31 :       if(TMath::Abs(idxRow[1] - idxRow[0]) != 1){
    1350           0 :         SetErrorMsg(kAttachRowGap);
    1351           0 :         AliDebug(2, Form("Rows attached not continuous. Select first candidate.\n"
    1352             :                     "       row[%2d] Ncl[%2d] <dz>[cm]=%+8.2f row[%2d] Ncl[%2d] <dz>[cm]=%+8.2f",
    1353             :                     idxRow[0], ncl[idxRow[0]], zresRow[0], idxRow[1], idxRow[1]<0?0:ncl[idxRow[1]], zresRow[1]));
    1354           0 :         nrc=1; idxRow[1] = -1; zresRow[1] = 999.;
    1355           0 :       }
    1356             :     } else {
    1357           2 :       Int_t idx0[kNrows];
    1358           2 :       TMath::Sort(nrc, zresRow, idx0, kFALSE);
    1359             :       nrc = 3; // select only maximum first 3 candidates
    1360           2 :       Int_t iatmp[] = {-1, -1, -1}; Double_t datmp[] = {999., 999., 999.};
    1361          16 :       for(Int_t irc(0); irc<nrc; irc++){
    1362           6 :         iatmp[irc] = idxRow[idx0[irc]];
    1363           6 :         datmp[irc] = zresRow[idx0[irc]];
    1364             :       }
    1365           2 :       idxRow[0] = iatmp[0]; zresRow[0] = datmp[0];
    1366           2 :       idxRow[1] = iatmp[1]; zresRow[1] = datmp[1];
    1367           2 :       idxRow[2] = iatmp[2]; zresRow[2] = datmp[2]; // temporary
    1368           2 :       if(TMath::Abs(idxRow[1] - idxRow[0]) != 1){
    1369           0 :         SetErrorMsg(kAttachRowGap);
    1370           0 :         AliDebug(2, Form("Rows attached not continuous. Turn on selection.\n"
    1371             :                     "row[%2d] Ncl[%2d] <dz>[cm]=%+8.2f\n"
    1372             :                     "row[%2d] Ncl[%2d] <dz>[cm]=%+8.2f\n"
    1373             :                     "row[%2d] Ncl[%2d] <dz>[cm]=%+8.2f",
    1374             :                     idxRow[0], ncl[idxRow[0]], zresRow[0],
    1375             :                     idxRow[1], ncl[idxRow[1]], zresRow[1],
    1376             :                     idxRow[2], ncl[idxRow[2]], zresRow[2]));
    1377           0 :         if(TMath::Abs(idxRow[0] - idxRow[2]) == 1){ // select second candidate
    1378           0 :           AliDebug(2, "Solved ! Remove second candidate.");
    1379             :           nrc = 2;
    1380           0 :           idxRow[1] = idxRow[2]; zresRow[1] = zresRow[2]; // swap
    1381           0 :           idxRow[2] = -1; zresRow[2] = 999.;              // remove
    1382           0 :         } else if(TMath::Abs(idxRow[1] - idxRow[2]) == 1){
    1383           0 :           if(ncl[idxRow[1]]+ncl[idxRow[2]] > ncl[idxRow[0]]){
    1384           0 :             AliDebug(2, "Solved ! Remove first candidate.");
    1385             :             nrc = 2;
    1386           0 :             idxRow[0] = idxRow[1]; zresRow[0] = zresRow[1]; // swap
    1387           0 :             idxRow[1] = idxRow[2]; zresRow[1] = zresRow[2]; // swap
    1388           0 :           } else {
    1389           0 :             AliDebug(2, "Solved ! Remove second and third candidate.");
    1390             :             nrc = 1;
    1391           0 :             idxRow[1] = -1; zresRow[1] = 999.; // remove
    1392           0 :             idxRow[2] = -1; zresRow[2] = 999.; // remove
    1393             :           }
    1394             :         } else {
    1395           0 :           AliDebug(2, "Unsolved !!! Remove second and third candidate.");
    1396             :           nrc = 1;
    1397           0 :           idxRow[1] = -1; zresRow[1] = 999.; // remove
    1398           0 :           idxRow[2] = -1; zresRow[2] = 999.; // remove
    1399             :         }
    1400             :       } else { // remove temporary candidate
    1401             :         nrc = 2;
    1402           2 :         idxRow[2] = -1; zresRow[2] = 999.;
    1403             :       }
    1404           2 :     }
    1405             :   }
    1406        1150 :   AliDebug(4, Form("Sorted row candidates:\n"
    1407             :       "  row[%2d] Ncl[%2d] <dz>[cm]=%+8.2f row[%2d] Ncl[%2d] <dz>[cm]=%+8.2f"
    1408             :       , idxRow[0], ncl[idxRow[0]], zresRow[0], idxRow[1], idxRow[1]<0?0:ncl[idxRow[1]], zresRow[1]));
    1409             : 
    1410             :   // initialize debug streamer
    1411             :   TTreeSRedirector *pstreamer(NULL);
    1412         460 :   if((recoParam->GetStreamLevel(AliTRDrecoParam::kTracker) > 3 && fkReconstructor->IsDebugStreaming())||
    1413         230 :      AliTRDReconstructor::GetStreamLevel()>30) pstreamer = fkReconstructor->GetDebugStream(AliTRDrecoParam::kTracker);
    1414         230 :   if(pstreamer){
    1415             :     // save config. for calibration
    1416           0 :     TVectorD vdy[2], vdx[2], vs2[2];
    1417           0 :     for(Int_t jr(0); jr<nrc; jr++){
    1418           0 :       Int_t ir(idxRow[jr]);
    1419           0 :       vdx[jr].ResizeTo(ncl[ir]); vdy[jr].ResizeTo(ncl[ir]); vs2[jr].ResizeTo(ncl[ir]);
    1420           0 :       for(Int_t ic(ncl[ir]); ic--;){
    1421           0 :         vdx[jr](ic) = xres[ir][ic];
    1422           0 :         vdy[jr](ic) = yres[ir][ic];
    1423           0 :         vs2[jr](ic) = s2y[ir][ic];
    1424             :       }
    1425             :     }
    1426           0 :     (*pstreamer) << "AttachClusters4"
    1427           0 :         << "r0="     << idxRow[0]
    1428           0 :         << "dz0="    << zresRow[0]
    1429           0 :         << "dx0="    << &vdx[0]
    1430           0 :         << "dy0="    << &vdy[0]
    1431           0 :         << "s20="    << &vs2[0]
    1432           0 :         << "r1="     << idxRow[1]
    1433           0 :         << "dz1="    << zresRow[1]
    1434           0 :         << "dx1="    << &vdx[1]
    1435           0 :         << "dy1="    << &vdy[1]
    1436           0 :         << "s21="    << &vs2[1]
    1437           0 :         << "\n";
    1438           0 :     vdx[0].Clear(); vdy[0].Clear(); vs2[0].Clear();
    1439           0 :     vdx[1].Clear(); vdy[1].Clear(); vs2[1].Clear();
    1440           0 :     if(recoParam->GetStreamLevel(AliTRDrecoParam::kTracker) > 4 ||AliTRDReconstructor::GetStreamLevel()>4){    
    1441           0 :       Int_t idx(idxRow[1]);
    1442           0 :       if(idx<0){ 
    1443           0 :         for(Int_t ir(0); ir<kNrows; ir++){ 
    1444           0 :           if(clst[ir].GetEntries()>0) continue;
    1445             :           idx = ir;
    1446           0 :           break;
    1447             :         }
    1448           0 :       }
    1449           0 :       (*pstreamer) << "AttachClusters5"
    1450           0 :           << "c0.="    << &clst[idxRow[0]]
    1451           0 :           << "c1.="    << &clst[idx]
    1452           0 :           << "\n";
    1453           0 :     }
    1454           0 :   }
    1455             : 
    1456             : //=======================================================================================
    1457             :   // Analyse cluster topology
    1458         230 :   Double_t f[kNcls],     // likelihood factors for segments
    1459             :            r[2][kNcls],  // d(dydx) of tracklet candidate with respect to track
    1460             :            xm[2][kNcls], // mean <x>
    1461             :            ym[2][kNcls], // mean <y>
    1462             :            sm[2][kNcls], // mean <s_y>
    1463             :            s[2][kNcls],  // sigma_y
    1464             :            p[2][kNcls],  // prob of Gauss
    1465             :            q[2][kNcls];  // charge/segment
    1466         230 :   memset(f, 0, kNcls*sizeof(Double_t));
    1467         230 :   Int_t index[2][kNcls], n[2][kNcls];
    1468         230 :   memset(n, 0, 2*kNcls*sizeof(Int_t));
    1469         230 :   Int_t mts(0), nts[2] = {0, 0};   // no of tracklet segments in row
    1470         460 :   AliTRDpadPlane *pp(AliTRDtransform::Geometry().GetPadPlane(fDet));
    1471         230 :   AliTRDtrackletOflHelper helper;
    1472         230 :   Int_t lyDet(AliTRDgeometry::GetLayer(fDet));
    1473         986 :   for(Int_t jr(0), n0(0); jr<nrc; jr++){
    1474         263 :     Int_t ir(idxRow[jr]);
    1475             :     // cluster segmentation
    1476             :     Bool_t kInit(kFALSE);
    1477         263 :     if(jr==0){ 
    1478         230 :       n0 = helper.Init(pp, &clst[ir]); kInit = kTRUE;
    1479         690 :       if(!n0 || (helper.ClassifyTopology() == AliTRDtrackletOflHelper::kNormal)){
    1480         216 :         nts[jr] = 1; memset(index[jr], 0, ncl[ir]*sizeof(Int_t));
    1481         216 :         n[jr][0] = ncl[ir];
    1482         216 :       }
    1483             :     }
    1484         263 :     if(!n[jr][0]){
    1485          94 :       nts[jr] = AliTRDtrackletOflHelper::Segmentation(ncl[ir], xres[ir], yres[ir], index[jr]);
    1486        1978 :       for(Int_t ic(ncl[ir]);ic--;) n[jr][index[jr][ic]]++;
    1487          47 :     }
    1488         263 :     mts += nts[jr];
    1489             :     
    1490             :     // tracklet segment processing
    1491        1148 :     for(Int_t its(0); its<nts[jr]; its++){
    1492         311 :       if(n[jr][its]<=2) {   // don't touch small segments
    1493          20 :         xm[jr][its] = 0.;ym[jr][its] = 0.;sm[jr][its] = 0.;
    1494         816 :         for(Int_t ic(ncl[ir]); ic--;){
    1495         752 :           if(its != index[jr][ic]) continue;
    1496          24 :           ym[jr][its] += yres[ir][ic];
    1497          24 :           xm[jr][its] += xres[ir][ic];
    1498          24 :           sm[jr][its] += TMath::Sqrt(s2y[ir][ic]);
    1499             :         }
    1500          24 :         if(n[jr][its]==2){ xm[jr][its] *= 0.5; ym[jr][its] *= 0.5; sm[jr][its] *= 0.5;}
    1501          20 :         xm[jr][its]= fX0 - xm[jr][its];
    1502          20 :         r[jr][its] = 0.;
    1503          20 :         s[jr][its] = 1.e-5;
    1504          20 :         p[jr][its] = 1.;
    1505          20 :         q[jr][its] = -1.;
    1506          20 :         continue;
    1507             :       }
    1508             :       
    1509             :       // for longer tracklet segments
    1510         369 :       if(!kInit) n0 = helper.Init(pp, &clst[ir], index[jr], its);
    1511         291 :       Int_t n1 = helper.GetRMS(r[jr][its], ym[jr][its], s[jr][its], fX0/*xm[jr][its]*/);
    1512         291 :       p[jr][its]  = Double_t(n1)/n0;
    1513         582 :       sm[jr][its] = helper.GetSyMean();
    1514         582 :       q[jr][its]  = helper.GetQ()/TMath::Sqrt(1. + fYref[1]*fYref[1] + fZref[1]*fZref[1]);
    1515         291 :       xm[jr][its] = fX0;
    1516         291 :       Double_t dxm= fX0 - xm[jr][its];
    1517         291 :       yt = fYref[0] - fYref[1]*dxm;
    1518         291 :       zt = fZref[0] - fZref[1]*dxm;
    1519             :       // correct tracklet fit for tilt
    1520         291 :       ym[jr][its]+= GetTilt()*(zt - zc[ir]);
    1521         291 :       r[jr][its] += GetTilt() * fZref[1];
    1522             :       // correct tracklet fit for track position/inclination
    1523         291 :       ym[jr][its] = yt - ym[jr][its];
    1524         291 :       r[jr][its]  = (r[jr][its] - fYref[1])/(1+r[jr][its]*fYref[1]);
    1525             :       // report inclination in radians
    1526         291 :       r[jr][its] = TMath::ATan(r[jr][its]);
    1527         330 :       if(jr) continue; // calculate only for first row likelihoods
    1528             :         
    1529         504 :       f[its] = attach->CookLikelihood(chgPos, lyDet, fPt, phiTrk, n[jr][its], ym[jr][its]/*sRef*/, r[jr][its]*TMath::RadToDeg(), s[jr][its]/sm[jr][its]);
    1530         252 :     }
    1531             :   }
    1532        1150 :   AliDebug(4, Form("   Tracklet candidates: row[%2d] = %2d row[%2d] = %2d:", idxRow[0], nts[0], idxRow[1], nts[1]));
    1533         460 :   if(AliLog::GetDebugLevel("TRD", "AliTRDseedV1")>3){
    1534           0 :     for(Int_t jr(0); jr<nrc; jr++){
    1535           0 :       Int_t ir(idxRow[jr]);
    1536           0 :       for(Int_t its(0); its<nts[jr]; its++){
    1537           0 :         printf("  segId[%2d] row[%2d] Ncl[%2d] x[cm]=%7.2f dz[pu]=%4.2f dy[mm]=%+7.3f r[deg]=%+6.2f p[%%]=%6.2f s[um]=%7.2f\n",
    1538           0 :             its, ir, n[jr][its], xm[jr][its], zresRow[jr], 1.e1*ym[jr][its], r[jr][its]*TMath::RadToDeg(), 100.*p[jr][its], 1.e4*s[jr][its]);
    1539             :       }
    1540             :     }
    1541           0 :   }
    1542         460 :   if(!pstreamer && 
    1543         230 :      ( (recoParam->GetStreamLevel(AliTRDrecoParam::kTracker) > 2 && fkReconstructor->IsDebugStreaming()) ||
    1544         230 :        AliTRDReconstructor::GetStreamLevel()>2 ) 
    1545           0 :      ) pstreamer = fkReconstructor->GetDebugStream(AliTRDrecoParam::kTracker);
    1546         230 :   if(pstreamer){
    1547             :     // save config. for calibration
    1548           0 :     TVectorD vidx, vn, vx, vy, vr, vs, vsm, vp, vf;
    1549           0 :     vidx.ResizeTo(ncl[idxRow[0]]+(idxRow[1]<0?0:ncl[idxRow[1]]));
    1550           0 :     vn.ResizeTo(mts);
    1551           0 :     vx.ResizeTo(mts);
    1552           0 :     vy.ResizeTo(mts);
    1553           0 :     vr.ResizeTo(mts);
    1554           0 :     vs.ResizeTo(mts);
    1555           0 :     vsm.ResizeTo(mts);
    1556           0 :     vp.ResizeTo(mts);
    1557           0 :     vf.ResizeTo(mts);
    1558           0 :     for(Int_t jr(0), jts(0), jc(0); jr<nrc; jr++){
    1559           0 :        Int_t ir(idxRow[jr]);
    1560           0 :        for(Int_t its(0); its<nts[jr]; its++, jts++){
    1561           0 :         vn[jts] = n[jr][its];
    1562           0 :         vx[jts] = xm[jr][its];
    1563           0 :         vy[jts] = ym[jr][its];
    1564           0 :         vr[jts] = r[jr][its];
    1565           0 :         vs[jts] = s[jr][its];
    1566           0 :         vsm[jts]= sm[jr][its];
    1567           0 :         vp[jts] = p[jr][its];
    1568           0 :         vf[jts] = jr?-1.:f[its];
    1569             :       }
    1570           0 :       for(Int_t ic(0); ic<ncl[ir]; ic++, jc++) vidx[jc] = index[jr][ic];
    1571             :     }
    1572           0 :     (*pstreamer) << "AttachClusters3"
    1573           0 :         << "idx="    << &vidx
    1574           0 :         << "n="      << &vn
    1575           0 :         << "x="      << &vx
    1576           0 :         << "y="      << &vy
    1577           0 :         << "r="      << &vr
    1578           0 :         << "s="      << &vs
    1579           0 :         << "sm="     << &vsm
    1580           0 :         << "p="      << &vp
    1581           0 :         << "f="      << &vf
    1582           0 :         << "\n";
    1583           0 :   }
    1584             : 
    1585             : //=========================================================
    1586             :   // Get seed tracklet segment
    1587         230 :   Int_t idx2[kNcls]; memset(idx2, 0, kNcls*sizeof(Int_t)); // seeding indexing
    1588         244 :   if(nts[0]>1) TMath::Sort(nts[0], f, idx2);
    1589         230 :   Int_t is(idx2[0]); // seed index
    1590         230 :   Int_t     idxTrklt[kNcls],
    1591             :             kts(0),
    1592         230 :             nTrklt(n[0][is]);
    1593        1610 :   Double_t  fTrklt(f[is]),
    1594         230 :             rTrklt(r[0][is]), 
    1595         230 :             yTrklt(ym[0][is]), 
    1596         230 :             sTrklt(s[0][is]), 
    1597         230 :             smTrklt(sm[0][is]), 
    1598         230 :             xTrklt(xm[0][is]), 
    1599         230 :             pTrklt(p[0][is]),
    1600         230 :             qTrklt(q[0][is]);
    1601         230 :   memset(idxTrklt, 0, kNcls*sizeof(Int_t));
    1602             :   // check seed idx2[0] exit if not found
    1603         460 :   if(f[is]<1.e-2){
    1604         240 :     AliDebug(1, Form("Seed   seg[%d] row[%2d] n[%2d] f[%f]<0.01.", is, idxRow[0], n[0][is], f[is]));
    1605           2 :     SetErrorMsg(kAttachClAttach);
    1606           4 :     if(!pstreamer && 
    1607           2 :        ( (recoParam->GetStreamLevel(AliTRDrecoParam::kTracker) > 1 && fkReconstructor->IsDebugStreaming()) ||
    1608           2 :          AliTRDReconstructor::GetStreamLevel()>1 ) 
    1609           0 :        ) pstreamer = fkReconstructor->GetDebugStream(AliTRDrecoParam::kTracker);
    1610           2 :     if(pstreamer){
    1611           0 :       UChar_t stat(0);
    1612           0 :       if(IsKink()) SETBIT(stat, 1);
    1613           0 :       if(IsStandAlone()) SETBIT(stat, 2);
    1614           0 :       if(IsRowCross()) SETBIT(stat, 3);
    1615           0 :       SETBIT(stat, 4); // set error bit
    1616           0 :       TVectorD vidx; vidx.ResizeTo(1); vidx[0] = is;
    1617           0 :       (*pstreamer) << "AttachClusters2"
    1618           0 :           << "stat="   << stat
    1619           0 :           << "ev="     << ev
    1620           0 :           << "chg="    << chgPos
    1621           0 :           << "det="    << fDet
    1622           0 :           << "x0="     << fX0
    1623           0 :           << "y0="     << fYref[0]
    1624           0 :           << "z0="     << fZref[0]
    1625           0 :           << "phi="    << phiTrk
    1626           0 :           << "tht="    << thtTrk
    1627           0 :           << "pt="     << fPt
    1628           0 :           << "s2Trk="  << s2yTrk
    1629           0 :           << "s2Cl="   << s2Mean
    1630           0 :           << "idx="    << &vidx
    1631           0 :           << "n="      << nTrklt
    1632           0 :           << "f="      << fTrklt
    1633           0 :           << "x="      << xTrklt
    1634           0 :           << "y="      << yTrklt
    1635           0 :           << "r="      << rTrklt
    1636           0 :           << "s="      << sTrklt
    1637           0 :           << "sm="     << smTrklt
    1638           0 :           << "p="      << pTrklt
    1639           0 :           << "q="      << qTrklt
    1640           0 :           << "\n";
    1641           0 :     }
    1642           2 :     return kFALSE;
    1643             :   }
    1644        1140 :   AliDebug(2, Form("Seed   seg[%d] row[%2d] n[%2d] dy[%f] r[%+5.2f] s[%+5.2f] f[%5.3f] q[%6.2f]", is, idxRow[0], n[0][is], ym[0][is], r[0][is]*TMath::RadToDeg(), s[0][is]/sm[0][is], f[is], q[0][is]));
    1645             : 
    1646             :   // save seeding segment in the helper
    1647         228 :   idxTrklt[kts++] = is;
    1648         228 :   helper.Init(pp, &clst[idxRow[0]], index[0], is);
    1649         228 :   AliTRDtrackletOflHelper test; // helper to test segment expantion
    1650         228 :   Float_t rcLikelihood(0.); SetBit(kRowCross, kFALSE);
    1651         228 :   Double_t dyRez[kNcls]; Int_t idx3[kNcls];
    1652             :   
    1653             :   //=========================================================
    1654             :   // Define filter parameters from OCDB
    1655         228 :   Int_t kNSgmDy[2]; attach->GetNsgmDy(kNSgmDy[0], kNSgmDy[1]);
    1656         228 :   Float_t kLikeMinRelDecrease[2]; attach->GetLikeMinRelDecrease(kLikeMinRelDecrease[0], kLikeMinRelDecrease[1]);
    1657         228 :   Float_t kRClikeLimit(attach->GetRClikeLimit());
    1658             : 
    1659             :   //=========================================================
    1660             :   // Try attaching next segments from first row (if any)
    1661         228 :   if(nts[0]>1){
    1662          14 :     Int_t jr(0), ir(idxRow[jr]);
    1663             :     // organize  secondary sgms. in decreasing order of their distance from seed 
    1664          14 :     memset(dyRez, 0, nts[jr]*sizeof(Double_t));
    1665         108 :     for(Int_t jts(1); jts<nts[jr]; jts++) {
    1666          40 :       Int_t its(idx2[jts]);
    1667          40 :       Double_t rot(TMath::Tan(r[0][is]));
    1668          40 :       dyRez[its] = TMath::Abs(ym[0][is] - ym[jr][its] + rot*(xm[0][is]-xm[jr][its]));
    1669             :     }
    1670          14 :     TMath::Sort(nts[jr], dyRez, idx3, kFALSE);
    1671         108 :     for (Int_t jts(1); jts<nts[jr]; jts++) {
    1672          40 :       Int_t its(idx3[jts]);
    1673          40 :       if(dyRez[its] > kNSgmDy[jr]*smTrklt){
    1674          80 :         AliDebug(2, Form("Reject seg[%d] row[%2d] n[%2d] dy[%f] > %d*s[%f].", its, idxRow[jr], n[jr][its], dyRez[its], kNSgmDy[jr], kNSgmDy[jr]*smTrklt));
    1675          16 :         continue;
    1676             :       }
    1677             :       
    1678          24 :       test = helper;
    1679          24 :       Int_t n0 = test.Expand(&clst[ir], index[jr], its);
    1680          24 :       Double_t rt, dyt, st, xt, smt, pt, qt, ft;
    1681          24 :       Int_t n1 = test.GetRMS(rt, dyt, st, fX0/*xt*/);
    1682          24 :       pt = Double_t(n1)/n0;
    1683          24 :       smt = test.GetSyMean();
    1684          48 :       qt  = test.GetQ()/TMath::Sqrt(1. + fYref[1]*fYref[1] + fZref[1]*fZref[1]);
    1685          24 :       xt  = fX0;
    1686             :       // correct position
    1687          24 :       Double_t dxm= fX0 - xt;
    1688          24 :       yt = fYref[0] - fYref[1]*dxm; 
    1689          24 :       zt = fZref[0] - fZref[1]*dxm;
    1690             :       // correct tracklet fit for tilt
    1691          24 :       dyt+= GetTilt()*(zt - zc[idxRow[0]]);
    1692          24 :       rt += GetTilt() * fZref[1];
    1693             :       // correct tracklet fit for track position/inclination
    1694          24 :       dyt  = yt - dyt;
    1695          24 :       rt   = (rt - fYref[1])/(1+rt*fYref[1]);
    1696             :       // report inclination in radians
    1697          24 :       rt = TMath::ATan(rt);
    1698             :         
    1699          72 :       ft = (n0>=2) ? attach->CookLikelihood(chgPos, lyDet, fPt, phiTrk, n0,  dyt/*sRef*/, rt*TMath::RadToDeg(), st/smt) : 0.;
    1700          24 :       Bool_t kAccept(ft>=fTrklt*(1.-kLikeMinRelDecrease[jr]));
    1701             :       
    1702         120 :       AliDebug(2, Form("%s seg[%d] row[%2d] n[%2d] dy[%f] r[%+5.2f] s[%+5.2f] f[%f] < %4.2f*F[%f].", 
    1703             :         (kAccept?"Adding":"Reject"), its, idxRow[jr], n0, dyt, rt*TMath::RadToDeg(), st/smt, ft, 1.-kLikeMinRelDecrease[jr], fTrklt*(1.-kLikeMinRelDecrease[jr])));
    1704          24 :       if(kAccept){
    1705          16 :         idxTrklt[kts++] = its;
    1706          16 :         nTrklt = n0;
    1707          16 :         fTrklt = ft;
    1708          16 :         rTrklt = rt;
    1709          16 :         yTrklt = dyt;
    1710          16 :         sTrklt = st;
    1711          16 :         smTrklt= smt;
    1712          16 :         xTrklt = xt;
    1713          16 :         pTrklt = pt;
    1714          16 :         qTrklt = qt;
    1715          16 :         helper.Expand(&clst[ir], index[jr], its);
    1716             :       }
    1717          24 :     }
    1718          14 :   }
    1719             :   
    1720             :   //=========================================================
    1721             :   // Try attaching next segments from second row (if any)
    1722         259 :   if(nts[1] && (rcLikelihood = zresRow[0]/zresRow[1]) > kRClikeLimit){
    1723             :     // organize  secondaries in decreasing order of their distance from seed 
    1724          21 :     Int_t jr(1), ir(idxRow[jr]);
    1725          21 :     memset(dyRez, 0, nts[jr]*sizeof(Double_t));
    1726          21 :     Double_t rot(TMath::Tan(r[0][is]));
    1727          88 :     for(Int_t jts(0); jts<nts[jr]; jts++) {
    1728          23 :       dyRez[jts] = TMath::Abs(ym[0][is] - ym[jr][jts] + rot*(xm[0][is]-xm[jr][jts]));
    1729             :     }
    1730          21 :     TMath::Sort(nts[jr], dyRez, idx3, kFALSE);
    1731          88 :     for (Int_t jts(0); jts<nts[jr]; jts++) {
    1732          23 :       Int_t its(idx3[jts]);
    1733          23 :       if(dyRez[its] > kNSgmDy[jr]*smTrklt){
    1734          35 :         AliDebug(2, Form("Reject seg[%d] row[%2d] n[%2d] dy[%f] > %d*s[%f].", its, idxRow[jr], n[jr][its], dyRez[its], kNSgmDy[jr], kNSgmDy[jr]*smTrklt));
    1735           7 :         continue;
    1736             :       }
    1737             :       
    1738          16 :       test = helper;
    1739          16 :       Int_t n0 = test.Expand(&clst[ir], index[jr], its);
    1740          16 :       Double_t rt, dyt, st, xt, smt, pt, qt, ft;
    1741          16 :       Int_t n1 = test.GetRMS(rt, dyt, st, fX0/*xt*/);
    1742          16 :       pt = Double_t(n1)/n0;
    1743          16 :       smt = test.GetSyMean();
    1744          32 :       qt  = test.GetQ()/TMath::Sqrt(1. + fYref[1]*fYref[1] + fZref[1]*fZref[1]);
    1745          16 :       xt  = fX0;
    1746             :       // correct position
    1747          16 :       Double_t dxm= fX0 - xt;
    1748          16 :       yt = fYref[0] - fYref[1]*dxm; 
    1749          16 :       zt = fZref[0] - fZref[1]*dxm;
    1750             :       // correct tracklet fit for tilt
    1751          16 :       dyt+= GetTilt()*(zt - zc[idxRow[0]]);
    1752          16 :       rt += GetTilt() * fZref[1];
    1753             :       // correct tracklet fit for track position/inclination
    1754          16 :       dyt  = yt - dyt;
    1755          16 :       rt   = (rt - fYref[1])/(1+rt*fYref[1]);
    1756             :       // report inclination in radians
    1757          16 :       rt = TMath::ATan(rt);
    1758             :         
    1759          48 :       ft = (n0>=2) ? attach->CookLikelihood(chgPos, lyDet, fPt, phiTrk, n0,  dyt/*sRef*/, rt*TMath::RadToDeg(), st/smt) : 0.;
    1760          16 :       Bool_t kAccept(ft>=fTrklt*(1.-kLikeMinRelDecrease[jr]));
    1761             :       
    1762          80 :       AliDebug(2, Form("%s seg[%d] row[%2d] n[%2d] dy[%f] r[%+5.2f] s[%+5.2f] f[%f] < %4.2f*F[%f].", 
    1763             :         (kAccept?"Adding":"Reject"), its, idxRow[jr], n0, dyt, rt*TMath::RadToDeg(), st/smt, ft, 1.-kLikeMinRelDecrease[jr], fTrklt*(1.-kLikeMinRelDecrease[jr])));
    1764          16 :       if(kAccept){
    1765          16 :         idxTrklt[kts++] = its;
    1766          16 :         nTrklt = n0;
    1767          16 :         fTrklt = ft;
    1768          16 :         rTrklt = rt;
    1769          16 :         yTrklt = dyt;
    1770          16 :         sTrklt = st;
    1771          16 :         smTrklt= smt;
    1772          16 :         xTrklt = xt;
    1773          16 :         pTrklt = pt;
    1774          16 :         qTrklt = qt;
    1775          16 :         helper.Expand(&clst[ir], index[jr], its);
    1776          16 :         SetBit(kRowCross, kTRUE); // mark pad row crossing
    1777             :       }
    1778          16 :     }
    1779          21 :   }
    1780             :   // clear local copy of clusters
    1781       11400 :   for(Int_t ir(0); ir<kNrows; ir++) clst[ir].Clear();
    1782             :   
    1783         456 :   if(!pstreamer && 
    1784         228 :      ((recoParam->GetStreamLevel(AliTRDrecoParam::kTracker) > 1 && fkReconstructor->IsDebugStreaming()) ||
    1785         228 :       AliTRDReconstructor::GetStreamLevel()>1 )
    1786           0 :      ) pstreamer = fkReconstructor->GetDebugStream(AliTRDrecoParam::kTracker);
    1787         228 :   if(pstreamer){
    1788           0 :     UChar_t stat(0);
    1789           0 :     if(IsKink()) SETBIT(stat, 1);
    1790           0 :     if(IsStandAlone()) SETBIT(stat, 2);
    1791           0 :     if(IsRowCross()) SETBIT(stat, 3);
    1792           0 :     TVectorD vidx; vidx.ResizeTo(kts);
    1793           0 :     for(Int_t its(0); its<kts; its++) vidx[its] = idxTrklt[its];
    1794           0 :     (*pstreamer) << "AttachClusters2"
    1795           0 :         << "stat="   << stat
    1796           0 :         << "ev="     << ev
    1797           0 :         << "chg="    << chgPos
    1798           0 :         << "det="    << fDet
    1799           0 :         << "x0="     << fX0
    1800           0 :         << "y0="     << fYref[0]
    1801           0 :         << "z0="     << fZref[0]
    1802           0 :         << "phi="    << phiTrk
    1803           0 :         << "tht="    << thtTrk
    1804           0 :         << "pt="     << fPt
    1805           0 :         << "s2Trk="  << s2yTrk
    1806           0 :         << "s2Cl="   << s2Mean
    1807           0 :         << "idx="    << &vidx
    1808           0 :         << "n="      << nTrklt
    1809           0 :         << "q="      << qTrklt
    1810           0 :         << "f="      << fTrklt
    1811           0 :         << "x="      << xTrklt
    1812           0 :         << "y="      << yTrklt
    1813           0 :         << "r="      << rTrklt
    1814           0 :         << "s="      << sTrklt
    1815           0 :         << "sm="     << smTrklt
    1816           0 :         << "p="      << pTrklt
    1817           0 :         << "\n";
    1818           0 :   }
    1819             :   
    1820             :   
    1821             :   //=========================================================
    1822             :   // Store clusters
    1823             :   Int_t nselected(0), nc(0);
    1824         228 :   TObjArray *selected(helper.GetClusters());
    1825         684 :   if(!selected || !(nselected = selected->GetEntriesFast())){
    1826           0 :     AliError("Cluster candidates missing !!!");
    1827           0 :     SetErrorMsg(kAttachClAttach);
    1828           0 :     return kFALSE;
    1829             :   }
    1830       10662 :   for(Int_t ic(0); ic<nselected; ic++){
    1831       10206 :     if(!(c = (AliTRDcluster*)selected->At(ic))) continue;
    1832        5103 :     Int_t it(c->GetPadTime()),
    1833        5103 :           jr(Int_t(helper.GetRow() != c->GetPadRow())),
    1834        5103 :           idx(it+kNtb*jr);
    1835        5103 :     if(fClusters[idx]){
    1836         675 :       AliDebug(1, Form("Multiple clusters/tb for D[%03d] Tb[%02d] Row[%2d]", fDet, it, c->GetPadRow()));
    1837         135 :       continue; // already booked
    1838             :     }
    1839             :     // TODO proper indexing of clusters !!
    1840        4968 :     fIndexes[idx]  = chamber->GetTB(it)->GetGlobalIndex(idxs[idxRow[jr]][ic]);
    1841        4968 :     fClusters[idx] = c;
    1842        4968 :     nc++;
    1843        4968 :   }
    1844        1140 :   AliDebug(2, Form("Clusters Found[%2d] Attached[%2d] RC[%c]", nselected, nc, IsRowCross()?'y':'n'));
    1845             : 
    1846             :   // number of minimum numbers of clusters expected for the tracklet
    1847         228 :   if (nc < kClmin){
    1848           0 :     AliDebug(1, Form("NOT ENOUGH CLUSTERS %d ATTACHED TO THE TRACKLET [min %d] FROM FOUND %d.", nc, kClmin, ncls));
    1849           0 :     SetErrorMsg(kAttachClAttach);
    1850           0 :     return kFALSE;
    1851             :   }
    1852         228 :   SetN(nc);
    1853             : 
    1854             :   // Load calibration parameters for this tracklet  
    1855             :   //Calibrate();
    1856             : 
    1857             :   // calculate dx for time bins in the drift region (calibration aware)
    1858         228 :   Float_t x[2] = {0.,0.}; Int_t tb[2]={0,0};
    1859        2146 :   for (Int_t it = t0, irp=0; irp<2 && it < AliTRDtrackerV1::GetNTimeBins(); it++) {
    1860         562 :     if(!fClusters[it]) continue;
    1861         448 :     x[irp]  = fClusters[it]->GetX();
    1862         448 :     tb[irp] = fClusters[it]->GetLocalTimeBin();
    1863         448 :     irp++;
    1864         448 :   }  
    1865         228 :   Int_t dtb = tb[1] - tb[0];
    1866         680 :   fdX = dtb ? (x[0] - x[1]) / dtb : 0.15;
    1867             :   return kTRUE;
    1868        5664 : }
    1869             : 
    1870             : //____________________________________________________________
    1871             : void AliTRDseedV1::Bootstrap(const AliTRDReconstructor *rec)
    1872             : {
    1873             : //   Fill in all derived information. It has to be called after recovery from file or HLT.
    1874             : //   The primitive data are
    1875             : //   - list of clusters
    1876             : //   - detector (as the detector will be removed from clusters)
    1877             : //   - position of anode wire (fX0) - temporary
    1878             : //   - track reference position and direction
    1879             : //   - momentum of the track
    1880             : //   - time bin length [cm]
    1881             : // 
    1882             : //   A.Bercuci <A.Bercuci@gsi.de> Oct 30th 2008
    1883             : //
    1884           0 :   fkReconstructor = rec;
    1885           0 :   AliTRDgeometry g;
    1886           0 :   SetPadPlane(g.GetPadPlane(fDet));
    1887             : 
    1888             :   //fSnp = fYref[1]/TMath::Sqrt(1+fYref[1]*fYref[1]);
    1889             :   //fTgl = fZref[1];
    1890             :   Int_t n = 0, nshare = 0, nused = 0;
    1891           0 :   AliTRDcluster **cit = &fClusters[0];
    1892           0 :   for(Int_t ic = kNclusters; ic--; cit++){
    1893           0 :     if(!(*cit)) return;
    1894           0 :     n++;
    1895           0 :     if((*cit)->IsShared()) nshare++;
    1896           0 :     if((*cit)->IsUsed()) nused++;
    1897             :   }
    1898           0 :   SetN(n); SetNUsed(nused); SetNShared(nshare);
    1899           0 :   Fit();
    1900           0 :   CookLabels();
    1901           0 :   GetProbability();
    1902           0 : }
    1903             : 
    1904             : 
    1905             : //____________________________________________________________________
    1906             : Bool_t AliTRDseedV1::Fit(UChar_t opt)
    1907             : {
    1908             : //
    1909             : // Linear fit of the clusters attached to the tracklet
    1910             : //
    1911             : // Parameters :
    1912             : //   - opt : switch for tilt pad correction of cluster y position. Options are
    1913             : //           0 no correction [default]
    1914             : //           1 full tilt correction [dz/dx and z0]
    1915             : //           2 pseudo tilt correction [dz/dx from pad-chamber geometry]
    1916             : //
    1917             : // Output :
    1918             : //  True if successful
    1919             : //
    1920             : // Detailed description
    1921             : //
    1922             : //            Fit in the xy plane
    1923             : // 
    1924             : // The fit is performed to estimate the y position of the tracklet and the track 
    1925             : // angle in the bending plane. The clusters are represented in the chamber coordinate 
    1926             : // system (with respect to the anode wire - see AliTRDtrackerV1::FollowBackProlongation() 
    1927             : // on how this is set). The x and y position of the cluster and also their variances 
    1928             : // are known from clusterizer level (see AliTRDcluster::GetXloc(), AliTRDcluster::GetYloc(), 
    1929             : // AliTRDcluster::GetSX() and AliTRDcluster::GetSY()). 
    1930             : // If gaussian approximation is used to calculate y coordinate of the cluster the position 
    1931             : // is recalculated taking into account the track angle. The general formula to calculate the 
    1932             : // error of cluster position in the gaussian approximation taking into account diffusion and track
    1933             : // inclination is given for TRD by:
    1934             : // BEGIN_LATEX
    1935             : // #sigma^{2}_{y} = #sigma^{2}_{PRF} + #frac{x#delta_{t}^{2}}{(1+tg(#alpha_{L}))^{2}} + #frac{x^{2}tg^{2}(#phi-#alpha_{L})tg^{2}(#alpha_{L})}{12}
    1936             : // END_LATEX
    1937             : //
    1938             : // Since errors are calculated only in the y directions, radial errors (x direction) are mapped to y
    1939             : // by projection i.e.
    1940             : // BEGIN_LATEX
    1941             : // #sigma_{x|y} = tg(#phi) #sigma_{x}
    1942             : // END_LATEX
    1943             : // and also by the lorentz angle correction
    1944             : //
    1945             : //            Fit in the xz plane
    1946             : //
    1947             : // The "fit" is performed to estimate the radial position (x direction) where pad row cross happens. 
    1948             : // If no pad row crossing the z position is taken from geometry and radial position is taken from the xy 
    1949             : // fit (see below).
    1950             : // 
    1951             : // There are two methods to estimate the radial position of the pad row cross:
    1952             : //   1. leading cluster radial position : Here the lower part of the tracklet is considered and the last 
    1953             : // cluster registered (at radial x0) on this segment is chosen to mark the pad row crossing. The error 
    1954             : // of the z estimate is given by :
    1955             : // BEGIN_LATEX
    1956             : // #sigma_{z} = tg(#theta) #Delta x_{x_{0}}/12
    1957             : // END_LATEX
    1958             : // The systematic errors for this estimation are generated by the following sources:
    1959             : //   - no charge sharing between pad rows is considered (sharp cross)
    1960             : //   - missing cluster at row cross (noise peak-up, under-threshold signal etc.).
    1961             : // 
    1962             : //   2. charge fit over the crossing point : Here the full energy deposit along the tracklet is considered 
    1963             : // to estimate the position of the crossing by a fit in the qx plane. The errors in the q directions are 
    1964             : // parameterized as s_q = q^2. The systematic errors for this estimation are generated by the following sources:
    1965             : //   - no general model for the qx dependence
    1966             : //   - physical fluctuations of the charge deposit 
    1967             : //   - gain calibration dependence
    1968             : //
    1969             : //            Estimation of the radial position of the tracklet
    1970             : //
    1971             : // For pad row cross the radial position is taken from the xz fit (see above). Otherwise it is taken as the 
    1972             : // interpolation point of the tracklet i.e. the point where the error in y of the fit is minimum. The error
    1973             : // in the y direction of the tracklet is (see AliTRDseedV1::GetCovAt()):
    1974             : // BEGIN_LATEX
    1975             : // #sigma_{y} = #sigma^{2}_{y_{0}} + 2xcov(y_{0}, dy/dx) + #sigma^{2}_{dy/dx}
    1976             : // END_LATEX
    1977             : // and thus the radial position is:
    1978             : // BEGIN_LATEX
    1979             : // x = - cov(y_{0}, dy/dx)/#sigma^{2}_{dy/dx}
    1980             : // END_LATEX
    1981             : //
    1982             : //            Estimation of tracklet position error 
    1983             : //
    1984             : // The error in y direction is the error of the linear fit at the radial position of the tracklet while in the z 
    1985             : // direction is given by the cluster error or pad row cross error. In case of no pad row cross this is given by:
    1986             : // BEGIN_LATEX
    1987             : // #sigma_{y} = #sigma^{2}_{y_{0}} - 2cov^{2}(y_{0}, dy/dx)/#sigma^{2}_{dy/dx} + #sigma^{2}_{dy/dx}
    1988             : // #sigma_{z} = Pad_{length}/12
    1989             : // END_LATEX
    1990             : // For pad row cross the full error is calculated at the radial position of the crossing (see above) and the error 
    1991             : // in z by the width of the crossing region - being a matter of parameterization. 
    1992             : // BEGIN_LATEX
    1993             : // #sigma_{z} = tg(#theta) #Delta x_{x_{0}}/12
    1994             : // END_LATEX
    1995             : // In case of no tilt correction (default in the barrel tracking) the tilt is taken into account by the rotation of
    1996             : // the covariance matrix. See AliTRDseedV1::GetCovAt() for details.
    1997             : //
    1998             : // Author 
    1999             : // A.Bercuci <A.Bercuci@gsi.de>
    2000             : 
    2001           0 :   if(!fkReconstructor){
    2002           0 :     AliError("The tracklet needs the reconstruction setup. Please initialize by SetReconstructor().");
    2003           0 :     return kFALSE;
    2004             :   }
    2005           0 :   if(!IsCalibrated()) Calibrate();
    2006           0 :   if(opt>2){
    2007           0 :     AliWarning(Form("Option [%d] outside range [0, 2]. Using default",opt));
    2008             :     opt=0;
    2009           0 :   }
    2010             : 
    2011             :   const Int_t kClmin = 8;
    2012             :   const Float_t kScalePulls = 10.; // factor to scale y pulls - NOT UNDERSTOOD
    2013             :   // get track direction
    2014           0 :   Double_t y0   = fYref[0];
    2015           0 :   Double_t dydx = fYref[1]; 
    2016           0 :   Double_t z0   = fZref[0];
    2017           0 :   Double_t dzdx = fZref[1];
    2018             : 
    2019           0 :   AliTRDtrackerV1::AliTRDLeastSquare fitterY;
    2020           0 :   AliTRDtrackerV1::AliTRDLeastSquare fitterZ;
    2021             : 
    2022             :   // book cluster information
    2023           0 :   Double_t qc[kNclusters], xc[kNclusters], yc[kNclusters], zc[kNclusters], sy[kNclusters];
    2024             : 
    2025           0 :   Bool_t tilt(opt==1)       // full tilt correction
    2026           0 :         ,pseudo(opt==2)     // pseudo tilt correction
    2027           0 :         ,rc(IsRowCross())   // row cross candidate 
    2028           0 :         ,kDZDX(IsPrimary());// switch dzdx calculation for barrel primary tracks
    2029             :   Int_t n(0);   // clusters used in fit 
    2030           0 :   AliTRDcluster *c(NULL), *cc(NULL), **jc = &fClusters[0];
    2031           0 :   const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam(); //the dynamic cast in GetRecoParam is slow, so caching the pointer to it
    2032             : 
    2033           0 :   const Char_t *tcName[]={"NONE", "FULL", "HALF"};
    2034           0 :   AliDebug(2, Form("Options : TC[%s] dzdx[%c]", tcName[opt], kDZDX?'Y':'N'));
    2035             : 
    2036             :   
    2037           0 :   for (Int_t ic=0; ic<kNclusters; ic++, ++jc) {
    2038           0 :     xc[ic]  = -1.; yc[ic]  = 999.; zc[ic]  = 999.; sy[ic]  = 0.;
    2039           0 :     if(!(c = (*jc))) continue;
    2040           0 :     if(!c->IsInChamber()) continue;
    2041             :     // compute pseudo tilt correction
    2042           0 :     if(kDZDX){ 
    2043           0 :       fZfit[0] = c->GetZ();
    2044           0 :       if(rc){
    2045           0 :         for(Int_t kc=AliTRDseedV1::kNtb; kc<AliTRDseedV1::kNclusters; kc++){
    2046           0 :           if(!(cc=fClusters[kc])) continue;
    2047           0 :           if(!cc->IsInChamber()) continue;
    2048           0 :           fZfit[0] += cc->GetZ(); fZfit[0] *= 0.5;
    2049           0 :           break;
    2050             :         }
    2051           0 :       }
    2052           0 :       fZfit[1] = fZfit[0]/fX0;
    2053           0 :       if(rc){
    2054           0 :         fZfit[0] += fZfit[1]*0.5*AliTRDgeometry::CdrHght();
    2055           0 :         fZfit[1] = fZfit[0]/fX0;
    2056           0 :       }
    2057             :       kDZDX=kFALSE;
    2058           0 :     }
    2059             : 
    2060             : //   TODO use this information to adjust cluster error parameterization
    2061             : //     Float_t w = 1.;
    2062             : //     if(c->GetNPads()>4) w = .5;
    2063             : //     if(c->GetNPads()>5) w = .2;
    2064             : 
    2065             :     // cluster charge
    2066           0 :     qc[n]   = TMath::Abs(c->GetQ());
    2067             :     // pad row of leading 
    2068             : 
    2069           0 :     xc[n]   = fX0 - c->GetX();
    2070             : 
    2071             :     // Recalculate cluster error based on tracking information
    2072           0 :     c->SetSigmaY2(fS2PRF, fDiffT, fExB, xc[n], -1./*zcorr?zt:-1.*/, dydx);
    2073           0 :     c->SetSigmaZ2(fPad[0]*fPad[0]/12.); // for HLT
    2074           0 :     sy[n]  = TMath::Sqrt(c->GetSigmaY2());
    2075             : 
    2076           0 :     yc[n]  = recoParam->UseGAUS() ? 
    2077           0 :       c->GetYloc(y0, sy[n], GetPadWidth()): c->GetY();
    2078           0 :     zc[n]   = c->GetZ();
    2079             : 
    2080             :     //optional r-phi correction
    2081             :     //printf("   n[%2d] yc[%7.5f] ", n, yc[n]);
    2082             :     Float_t correction(0.);
    2083           0 :     if(tilt) correction = fPad[2]*(xc[n]*dzdx + zc[n] - z0);
    2084           0 :     else if(pseudo) correction = fPad[2]*(xc[n]*fZfit[1] + zc[n]-fZfit[0]);
    2085           0 :     yc[n]-=correction;
    2086             :     //printf("corr(%s%s)[%7.5f] yc1[%7.5f]\n", (tilt?"TC":""), (zcorr?"PC":""), correction, yc[n]);
    2087             : 
    2088           0 :     AliDebug(5, Form("  tb[%2d] dx[%6.3f] y[%6.2f+-%6.3f]", c->GetLocalTimeBin(), xc[n], yc[n], sy[n]));
    2089           0 :     fitterY.AddPoint(&xc[n], yc[n], sy[n]);
    2090           0 :     if(rc) fitterZ.AddPoint(&xc[n], qc[n]*(ic<kNtb?1.:-1.), 1.);
    2091           0 :     n++;
    2092           0 :   }
    2093             : 
    2094             :   // to few clusters
    2095           0 :   if (n < kClmin){ 
    2096           0 :     AliDebug(1, Form("Not enough clusters to fit. Clusters: Attached[%d] Fit[%d].", GetN(), n));
    2097           0 :     SetErrorMsg(kFitCl);
    2098           0 :     return kFALSE; 
    2099             :   }
    2100             :   // fit XY
    2101           0 :   if(!fitterY.Eval()){
    2102           0 :     AliDebug(1, "Fit Y failed.");
    2103           0 :     SetErrorMsg(kFitFailedY);
    2104           0 :     return kFALSE;
    2105             :   }
    2106           0 :   fYfit[0] = fitterY.GetFunctionParameter(0);
    2107           0 :   fYfit[1] = -fitterY.GetFunctionParameter(1);
    2108             :   // store covariance
    2109           0 :   Double_t p[3];
    2110           0 :   fitterY.GetCovarianceMatrix(p);
    2111           0 :   fCov[0] = kScalePulls*p[1]; // variance of y0
    2112           0 :   fCov[1] = kScalePulls*p[2]; // covariance of y0, dydx
    2113           0 :   fCov[2] = kScalePulls*p[0]; // variance of dydx
    2114             :   // the ref radial position is set at the minimum of 
    2115             :   // the y variance of the tracklet
    2116           0 :   fX   = -fCov[1]/fCov[2];
    2117           0 :   fS2Y = fCov[0] +2.*fX*fCov[1] + fX*fX*fCov[2];
    2118             : 
    2119           0 :   Float_t xs=fX+.5*AliTRDgeometry::CamHght();
    2120           0 :   if(xs < 0. || xs > AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght()){
    2121           0 :     AliDebug(1, Form("Ref radial position ouside chamber x[%5.2f].", fX));
    2122           0 :     SetErrorMsg(kFitFailedY);
    2123           0 :     return kFALSE;
    2124             :   }
    2125             : 
    2126             : /*    // THE LEADING CLUSTER METHOD for z fit
    2127             :     Float_t xMin = fX0;
    2128             :     Int_t ic=n=kNclusters-1; jc = &fClusters[ic];
    2129             :     AliTRDcluster *c0 =0x0, **kc = &fClusters[kNtb-1];
    2130             :     for(; ic>kNtb; ic--, --jc, --kc){
    2131             :       if((c0 = (*kc)) && c0->IsInChamber() && (xMin>c0->GetX())) xMin = c0->GetX();
    2132             :       if(!(c = (*jc))) continue;
    2133             :       if(!c->IsInChamber()) continue;
    2134             :       zc[kNclusters-1] = c->GetZ(); 
    2135             :       fX = fX0 - c->GetX();
    2136             :     }
    2137             :     fZfit[0] = .5*(zc[0]+zc[kNclusters-1]); fZfit[1] = 0.;
    2138             :     // Error parameterization
    2139             :     fS2Z     = fdX*fZref[1];
    2140             :     fS2Z    *= fS2Z; fS2Z    *= 0.2887; //  1/sqrt(12)*/
    2141             : 
    2142             :   // fit QZ
    2143           0 :   if(opt!=1 && IsRowCross()){
    2144           0 :     if(!fitterZ.Eval()) SetErrorMsg(kFitFailedZ);
    2145           0 :     if(!HasError(kFitFailedZ) && TMath::Abs(fitterZ.GetFunctionParameter(1))>1.e-10){ 
    2146             :       // TODO - one has to recalculate xy fit based on
    2147             :       // better knowledge of z position
    2148             : //       Double_t x = -fitterZ.GetFunctionParameter(0)/fitterZ.GetFunctionParameter(1);
    2149             : //       Double_t z0 = .5*(zc[0]+zc[n-1]);
    2150             : //       fZfit[0] = z0 + fZfit[1]*x; 
    2151             : //       fZfit[1] = fZfit[0]/fX0; 
    2152             : //       redo fit on xy plane
    2153             :     }
    2154             :     // temporary external error parameterization
    2155           0 :     fS2Z     = 0.05+0.4*TMath::Abs(fZref[1]); fS2Z *= fS2Z;
    2156             :     // TODO correct formula
    2157             :     //fS2Z     = sigma_x*TMath::Abs(fZref[1]);
    2158           0 :   } else {
    2159             :     //fZfit[0] = zc[0] + dzdx*0.5*AliTRDgeometry::CdrHght();
    2160           0 :     fS2Z     = GetPadLength()*GetPadLength()/12.;
    2161             :   }
    2162           0 :   return kTRUE;
    2163           0 : }
    2164             : 
    2165             : 
    2166             : //____________________________________________________________________
    2167             : Bool_t AliTRDseedV1::FitRobust(AliTRDpadPlane *pp, TGeoHMatrix *mDet, Float_t bz, Int_t chg, Int_t opt, Float_t tgl)
    2168             : {
    2169             : //
    2170             : // Linear fit of the clusters attached to the tracklet
    2171             : //   The fit is performed in local chamber coordinates (27.11.2013) to take into account correctly the misalignment
    2172             : //   Also the pad row cross is checked here and some background is removed
    2173             : //
    2174             : // Author 
    2175             : // A.Bercuci <A.Bercuci@gsi.de>
    2176             : 
    2177             :   TTreeSRedirector *pstreamer(NULL);
    2178         228 :   const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam();   
    2179         456 :   if( (recoParam->GetStreamLevel(AliTRDrecoParam::kTracker) > 3 && fkReconstructor->IsDebugStreaming()) ||
    2180         228 :     AliTRDReconstructor::GetStreamLevel()>3 ) pstreamer = fkReconstructor->GetDebugStream(AliTRDrecoParam::kTracker);
    2181             : 
    2182             :   // factor to scale y pulls.
    2183             :   // ideally if error parametrization correct this is 1.
    2184             :   //Float_t lyScaler = 1./(AliTRDgeometry::GetLayer(fDet)+1.);
    2185             :   Float_t kScalePulls = 1.; 
    2186         228 :   AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
    2187         228 :   if(!calibration){ 
    2188           0 :     AliWarning("No access to calibration data");
    2189           0 :   } else {
    2190             :     // Retrieve the CDB container class with the parametric likelihood
    2191         228 :     const AliTRDCalTrkAttach *attach = calibration->GetAttachObject();
    2192         228 :     if(!attach){ 
    2193           0 :       AliWarning("No usable AttachClusters calib object.");
    2194           0 :     } else { 
    2195             :       //kScalePulls = attach->GetScaleCov();//*lyScaler;
    2196             :     }
    2197             :     // Retrieve chamber status
    2198         228 :     SetChmbGood(calibration->IsChamberGood(fDet));
    2199         228 :     if(!IsChmbGood()) kScalePulls*=10.;
    2200             :   }  
    2201         228 :   AliTRDCommonParam *cp = AliTRDCommonParam::Instance(); 
    2202         684 :   Double_t freq(cp?cp->GetSamplingFrequency():10.);
    2203             :       
    2204             :   // evaluate locally z and dzdx from TRD only information
    2205         228 :   if(EstimatedCrossPoint(pp, bz)<0.) return kFALSE;
    2206             :   
    2207             :   //printf("D%03d RC[%c] dzdx[%f %f] opt[%d]\n", fDet, IsRowCross()?'y':'n', fZref[1], fZfit[1], opt);
    2208             :   Double_t //xchmb = 0.5 * AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick(),
    2209             :            //zchmb = 0.5 * (pp->GetRow0() + pp->GetRowEnd()),
    2210         228 :            z0(0.5 * (pp->GetRow0() + pp->GetRowEnd()) + fZfit[0]),  
    2211         228 :            DZ(pp->GetRow0() - pp->GetRowEnd() - pp->GetAnodeWireOffset() + fZfit[0]),
    2212             :            z, d(-1.);
    2213         456 :   Double_t xc[kNclusters], yc[kNclusters], dz(0.), dzdx(0.), 
    2214             :            s2dz(0.), s2dzdx(0.), sy[kNclusters],
    2215         228 :            s2x((8.33e-2/freq/freq+1.56e-2)*fVD*fVD),  // error of 1tb + error of mean time (TRF)
    2216         456 :            t2(fPad[2]*fPad[2]), loc[3]={0.};
    2217         228 :   Int_t n(0),          // clusters used in fit 
    2218             :         row[]={-1, -1};// pad row spanned by the tracklet
    2219         228 :   Double_t ycorr(UnbiasY(IsRowCross(), bz)),
    2220         228 :            kS2Ycorr(recoParam->GetS2Ycorr(IsRowCross(), chg>0));
    2221             :         
    2222         228 :   AliTRDcluster *c(NULL), **jc = &fClusters[0];
    2223       14592 :   for(Int_t ic=0; ic<kNtb; ic++, ++jc) {
    2224        7068 :     if(!(c = (*jc))) continue;
    2225        4804 :     if(!c->IsInChamber()) continue;
    2226        4486 :     if(row[0]<0){ 
    2227         228 :       row[0] = c->GetPadRow();
    2228         228 :       z      = pp->GetRowPos(row[0]) - 0.5*pp->GetRowSize(row[0]);
    2229         228 :       switch(opt){ 
    2230             :         case 0: // no dz correction (only for RC tracklet) and dzdx from chamber position assuming primary
    2231         470 :           dzdx  = IsRowCross()?fZfit[1]:0.; 
    2232         470 :           s2dzdx= IsRowCross()?GetS2DZDX(dzdx):0.;
    2233         470 :           dz    = IsRowCross()?(z - z0):0.;  
    2234         470 :           s2dz  = IsRowCross()?fS2Z:0.;
    2235         228 :           break;
    2236             :         case 1: // dz correction only for RC tracklet and dzdx from reference
    2237           0 :           dzdx = fZref[1];
    2238           0 :           dz   = IsRowCross()?(z - z0):0.; 
    2239           0 :           break;
    2240             :         case 2: // full z correction (z0 & dzdx from reference)
    2241           0 :           dzdx = fZref[1];
    2242           0 :           dz   = c->GetZ()-fZref[0]; 
    2243           0 :           break;
    2244             :         default:
    2245           0 :           AliError(Form("Wrong option fit %d !", opt));
    2246           0 :           break;
    2247             :       }    
    2248             :     }
    2249             :     //Use local cluster coordinates 
    2250             :     //A.Bercuci 27.11.13/30.06.14
    2251        4486 :     Double_t trk[] = {c->GetX(), c->GetY(), c->GetZ()};
    2252        4486 :     mDet->MasterToLocal(trk, loc);
    2253        4486 :     xc[n] = AliTRDgeometry::AnodePos()-loc[0]; //c->GetXloc(fT0, fVD); // c->GetX();
    2254        4486 :     yc[n] = loc[1]; //c->GetYloc(pp->GetColPos(col) + .5*cs, fS2PRF, cs) - xc[n]*fExB; //c->GetY();
    2255        4486 :     yc[n]-= fPad[2]*(dz+xc[n]*dzdx);
    2256        4486 :     yc[n]-= ycorr;
    2257        4486 :     if(IsRowCross()){ // estimate closest distance to anode wire
    2258         166 :       d = DZ-xc[n]*dzdx;
    2259         166 :       d -= ((Int_t)(2 * d)) / 2.0;
    2260         244 :       if (d > 0.25) d  = 0.5 - d;
    2261             :     }
    2262             :     // recalculate cluster error from knowledge of the track inclination in the bending plane 
    2263             :     // and eventually distance to anode wire
    2264        4486 :     c->SetSigmaY2(fS2PRF, fDiffT, fExB, xc[n], d, fYref[1]);
    2265        4486 :     s2x = c->GetSX(c->GetLocalTimeBin(), d); s2x*=s2x;
    2266       13458 :     sy[n] = c->GetSigmaY2()>0?(TMath::Min(Double_t(c->GetSigmaY2()), 6.4e-3)):6.4e-3;
    2267        4486 :     sy[n]+= t2*(s2dz+xc[n]*xc[n]*s2dzdx+dzdx*dzdx*s2x);
    2268        4486 :     sy[n] = TMath::Sqrt(sy[n]);
    2269        4486 :     n++;
    2270        4486 :   }
    2271       14592 :   for(Int_t ic=kNtb; ic<kNclusters; ic++, ++jc) {
    2272        7068 :     if(!(c = (*jc))) continue;
    2273         164 :     if(!c->IsInChamber()) continue;
    2274         156 :     if(row[1]<0){ 
    2275          14 :       row[1] = c->GetPadRow();
    2276          14 :       z      = pp->GetRowPos(row[1]) - 0.5*pp->GetRowSize(row[1]);
    2277          14 :       switch(opt){ 
    2278             :         case 0: // no dz correction (only for RC tracklet) and dzdx from chamber position assuming primary
    2279             :           //dzdx = fZfit[1];
    2280          14 :           dz   = z - z0; 
    2281          14 :           break;
    2282             :         case 1: // dz correction only for RC tracklet and dzdx from reference
    2283             :           //dzdx = fZref[1];
    2284           0 :           dz   = z - z0; 
    2285           0 :           break;
    2286             :         case 2: // full z correction (z0 & dzdx from reference)
    2287             :           //dzdx = fZref[1];
    2288           0 :           dz   = c->GetZ()-fZref[0]; 
    2289           0 :           break;
    2290             :         default:
    2291           0 :           AliError(Form("Wrong option fit %d !", opt));
    2292           0 :           break;
    2293             :       }    
    2294             :     }  
    2295             : 
    2296             :     //Use local cluster coordinates - the code should be identical with AliTRDtransform::Transform() !!!
    2297             :     //A.Bercuci 27.11.13
    2298         156 :     Double_t trk[] = {c->GetX(), c->GetY(), c->GetZ()};
    2299         156 :     mDet->MasterToLocal(trk, loc);
    2300         156 :     xc[n] = AliTRDgeometry::AnodePos()-loc[0]; //c->GetXloc(fT0, fVD); // c->GetX();
    2301         156 :     yc[n] = loc[1]; //c->GetYloc(pp->GetColPos(col) + .5*cs, fS2PRF, cs) - xc[n]*fExB; //c->GetY();
    2302         156 :     yc[n]-= fPad[2]*(dz+xc[n]*dzdx);
    2303         156 :     yc[n]-= ycorr;
    2304             : 
    2305         156 :     d = DZ-xc[n]*dzdx;
    2306         156 :     d -= ((Int_t)(2 * d)) / 2.0;
    2307         262 :     if (d > 0.25) d  = 0.5 - d;
    2308         156 :     c->SetSigmaY2(fS2PRF, fDiffT, fExB, xc[n], d, fYref[1]);
    2309         156 :     s2x = c->GetSX(c->GetLocalTimeBin(), d); s2x*=s2x;
    2310         468 :     sy[n] = c->GetSigmaY2()>0?(TMath::Min(Double_t(c->GetSigmaY2()), 6.4e-3)):6.4e-3;
    2311         156 :     sy[n]+= t2*(s2dz+xc[n]*xc[n]*s2dzdx+dzdx*dzdx*s2x);
    2312         156 :     sy[n] = TMath::Sqrt(sy[n]);
    2313         156 :     n++;
    2314         156 :   }
    2315             : 
    2316         228 :   UChar_t status(0);
    2317             :   // the ref radial position is set close to the minimum of 
    2318             :   // the y variance of the tracklet
    2319         228 :   fX   = 0.;//set reference to anode wire
    2320         228 :   Double_t par[3] = {0.,0.,fX}, cov[3];
    2321         228 :   if(!AliTRDtrackletOflHelper::Fit(n, xc, yc, sy, par, 1.5, cov)) { 
    2322           0 :     AliDebug(1, Form("Tracklet fit failed D[%03d].", fDet));
    2323           0 :     SetErrorMsg(kFitCl);
    2324           0 :     return kFALSE; 
    2325             :   }
    2326         228 :   fYfit[0] = par[0] - fX * par[1];
    2327         228 :   fYfit[1] = -par[1];
    2328             :   //printf(" yfit: %f [%f] x[%e] dydx[%f]\n", fYfit[0], par[0], fX, par[1]);
    2329             :   // store covariance
    2330         228 :   fCov[0] = kScalePulls*kS2Ycorr*cov[0]; // variance of y0
    2331         228 :   fCov[1] = kScalePulls*cov[2]; // covariance of y0, dydx
    2332         228 :   fCov[2] = kScalePulls*cov[1]; // variance of dydx
    2333             :   // check radial position
    2334         228 :   Float_t xs=fX+.5*AliTRDgeometry::CamHght();
    2335         456 :   if(xs < 0. || xs > AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght()){
    2336           0 :     AliDebug(1, Form("Ref radial position x[%5.2f] ouside D[%3d].", fX, fDet));
    2337           0 :     SetErrorMsg(kFitFailedY);
    2338           0 :     return kFALSE;
    2339             :   }
    2340         228 :   if(!IsRowCross()){ 
    2341             :     //    Double_t padEffLength(fPad[0] - TMath::Abs(dzdx));
    2342         214 :     Double_t padEffLength(fPad[0]);
    2343             :     //
    2344             :     // correct Z for most probable value accounting for the fact that it is not RC
    2345         214 :     double zCorrNRC = tgl*recoParam->GetZCorrCoefNRC();
    2346         214 :     padEffLength -= TMath::Abs(zCorrNRC*2);
    2347         214 :     fZfit[0] += zCorrNRC;
    2348         214 :     fYfit[0] += GetTilt()*zCorrNRC;
    2349         214 :     fS2Z = padEffLength*padEffLength/12.;
    2350         214 :   }
    2351         684 :   AliDebug(2, Form("[I]  x[cm]=%6.2f y[cm]=%+5.2f z[cm]=%+6.2f dydx[deg]=%+5.2f", GetX(), GetY(), GetZ(), TMath::ATan(fYfit[1])*TMath::RadToDeg()));
    2352             :   
    2353         228 :   if(pstreamer){
    2354           0 :     Float_t x= fX0 -fX,
    2355           0 :             y = GetY(),
    2356           0 :             yt = fYref[0]-fX*fYref[1];
    2357           0 :     SETBIT(status, 2);
    2358           0 :     TVectorD vcov(3); vcov[0]=cov[0];vcov[1]=cov[1];vcov[2]=cov[2];
    2359           0 :     Double_t sm(0.), chi2(0.), tmp, dy[kNclusters];
    2360           0 :     for(Int_t ic(0); ic<n; ic++){
    2361           0 :       sm   += sy[ic];
    2362           0 :       dy[ic] = yc[ic]-(fYfit[0]+(xc[ic]-fX0)*fYfit[1]); tmp = dy[ic]/sy[ic];
    2363           0 :       chi2 += tmp*tmp;
    2364             :     }
    2365           0 :     sm /= n; chi2 = TMath::Sqrt(chi2);
    2366           0 :     Double_t m(0.), s(0.);
    2367           0 :     AliMathBase::EvaluateUni(n, dy, m, s, 0);
    2368           0 :     (*pstreamer) << "FitRobust4"
    2369           0 :       << "stat=" << status
    2370           0 :       << "opt="  << opt
    2371           0 :       << "ncl="  << n
    2372           0 :       << "det="  << fDet
    2373           0 :       << "x0="   << fX0
    2374           0 :       << "y0="   << fYfit[0]
    2375           0 :       << "x="    << x
    2376           0 :       << "y="    << y
    2377           0 :       << "dydx=" << fYfit[1]
    2378           0 :       << "pt="   << fPt
    2379           0 :       << "yt="   << yt
    2380           0 :       << "dydxt="<< fYref[1]
    2381           0 :       << "cov="  << &vcov
    2382           0 :       << "chi2=" << chi2
    2383           0 :       << "sm="   << sm
    2384           0 :       << "ss="   << s
    2385           0 :       << "\n";
    2386           0 :   }
    2387         228 :   return kTRUE;
    2388         456 : }
    2389             : 
    2390             : //___________________________________________________________________
    2391             : void AliTRDseedV1::SetXYZ(TGeoHMatrix *mDet)
    2392             : {
    2393             : // Apply alignment to the local position of tracklet
    2394             : // A.Bercuci @ 27.11.2013
    2395             : 
    2396         456 :   Double_t loc[] = {AliTRDgeometry::AnodePos(), GetLocalY(), fZfit[0]}, trk[3]={0.};
    2397         228 :   mDet->LocalToMaster(loc, trk);
    2398         228 :   fX0 = trk[0];
    2399         228 :   fY  = trk[1];
    2400         228 :   fZ  = trk[2];
    2401             :   return;
    2402             : //   if(!IsRowCross()){/*fZfit[1] *= 1.09;*/ return;}
    2403             : //   // recalculate local z coordinate assuming primary track for row cross tracklets
    2404             : //   Double_t zoff(fZ-fZfit[0]); // no alignment aware !
    2405             : //   //printf("SetXYZ : zoff[%f] zpp[%f]\n", zoff, zpp);
    2406             : //   fZfit[0] = fX0*fZfit[1] - zoff; 
    2407             : //   // recalculate tracking coordinates based on the new z coordinate
    2408             : //   loc[2] = fZfit[0];
    2409             : //   mDet->LocalToMaster(loc, trk);
    2410             : //   fX0 = trk[0];
    2411             : //   fY  = trk[1];
    2412             : //   fZ  = trk[2];//-zcorr[stk];
    2413             :   //fZfit[1] = /*(IsRowCross()?1.05:1.09)**/fZ/(fX0-fS2Y);
    2414         228 : }
    2415             : 
    2416             : 
    2417             : //___________________________________________________________________
    2418             : void AliTRDseedV1::Print(Option_t *o) const
    2419             : {
    2420             :   //
    2421             :   // Printing the seedstatus
    2422             :   //
    2423             : 
    2424           0 :   AliInfo(Form("Det[%3d] X0[%7.2f] Pad{L[%5.2f] W[%5.2f] Tilt[%+6.2f]}", fDet, fX0, GetPadLength(), GetPadWidth(), GetTilt()));
    2425           0 :   AliInfo(Form("N[%2d] Nused[%2d] Nshared[%2d] [%d]", GetN(), GetNUsed(), GetNShared(), fN));
    2426           0 :   AliInfo(Form("FLAGS : RC[%c] Kink[%c] SA[%c]", IsRowCross()?'y':'n', IsKink()?'y':'n', IsStandAlone()?'y':'n'));
    2427           0 :   AliInfo(Form("CALIB PARAMS :  T0[%5.2f]  Vd[%5.2f]  s2PRF[%5.2f]  ExB[%5.2f]  Dl[%5.2f]  Dt[%5.2f]", fT0, fVD, fS2PRF, fExB, fDiffL, fDiffT));
    2428             : 
    2429           0 :   Double_t cov[3], x=GetX();
    2430           0 :   GetCovAt(x, cov);
    2431           0 :   AliInfo("    |  x[cm]  |      y[cm]       |      z[cm]      |  dydx |  dzdx |");
    2432           0 :   AliInfo(Form("Fit | %7.2f | %7.2f+-%7.2f | %7.2f+-%7.2f| %5.2f | ----- |", x, GetY(), TMath::Sqrt(cov[0]), GetZ(), TMath::Sqrt(cov[2]), fYfit[1]));
    2433           0 :   AliInfo(Form("Ref | %7.2f | %7.2f+-%7.2f | %7.2f+-%7.2f| %5.2f | %5.2f |", x, fYref[0]-fX*fYref[1], TMath::Sqrt(fRefCov[0]), fZref[0]-fX*fYref[1], TMath::Sqrt(fRefCov[2]), fYref[1], fZref[1]));
    2434           0 :   AliInfo(Form("P / Pt [GeV/c] = %f / %f", GetMomentum(), fPt));
    2435           0 :   if(IsStandAlone()) AliInfo(Form("C Rieman / Vertex [1/cm] = %f / %f", fC[0], fC[1]));
    2436           0 :   AliInfo(Form("dEdx [a.u.]    = %f / %f / %f / %f / %f/ %f / %f / %f", fdEdx[0], fdEdx[1], fdEdx[2], fdEdx[3], fdEdx[4], fdEdx[5], fdEdx[6], fdEdx[7]));
    2437           0 :   AliInfo(Form("PID            = %5.3f / %5.3f / %5.3f / %5.3f / %5.3f", fProb[0], fProb[1], fProb[2], fProb[3], fProb[4]));
    2438             : 
    2439           0 :   if(strcmp(o, "a")!=0) return;
    2440             : 
    2441           0 :   AliTRDcluster* const* jc = &fClusters[0];
    2442           0 :   for(int ic=0; ic<kNclusters; ic++, jc++) {
    2443           0 :     if(!(*jc)) continue;
    2444           0 :     (*jc)->Print(o);
    2445           0 :   }
    2446           0 : }
    2447             : 
    2448             : 
    2449             : //___________________________________________________________________
    2450             : Bool_t AliTRDseedV1::IsEqual(const TObject *o) const
    2451             : {
    2452             :   // Checks if current instance of the class has the same essential members
    2453             :   // as the given one
    2454             : 
    2455           0 :   if(!o) return kFALSE;
    2456           0 :   const AliTRDseedV1 *inTracklet = dynamic_cast<const AliTRDseedV1*>(o);
    2457           0 :   if(!inTracklet) return kFALSE;
    2458             : 
    2459           0 :   for (Int_t i = 0; i < 2; i++){
    2460           0 :     if ( fYref[i] != inTracklet->fYref[i] ) return kFALSE;
    2461           0 :     if ( fZref[i] != inTracklet->fZref[i] ) return kFALSE;
    2462             :   }
    2463             :   
    2464           0 :   if ( TMath::Abs(fS2Y - inTracklet->fS2Y)>1.e-10 ) return kFALSE;
    2465           0 :   if ( TMath::Abs(GetTilt() - inTracklet->GetTilt())>1.e-10 ) return kFALSE;
    2466           0 :   if ( TMath::Abs(GetPadLength() - inTracklet->GetPadLength())>1.e-10 ) return kFALSE;
    2467             :   
    2468           0 :   for (Int_t i = 0; i < kNclusters; i++){
    2469             : //     if ( fX[i] != inTracklet->GetX(i) ) return kFALSE;
    2470             : //     if ( fY[i] != inTracklet->GetY(i) ) return kFALSE;
    2471             : //     if ( fZ[i] != inTracklet->GetZ(i) ) return kFALSE;
    2472           0 :     if ( fIndexes[i] != inTracklet->fIndexes[i] ) return kFALSE;
    2473             :   }
    2474             : //   if ( fUsable != inTracklet->fUsable ) return kFALSE;
    2475             : 
    2476           0 :   for (Int_t i=0; i < 2; i++){
    2477           0 :     if ( fYfit[i] != inTracklet->fYfit[i] ) return kFALSE;
    2478           0 :     if ( fZfit[i] != inTracklet->fZfit[i] ) return kFALSE;
    2479           0 :     if ( fLabels[i] != inTracklet->fLabels[i] ) return kFALSE;
    2480             :   }
    2481             :   
    2482             : /*  if ( fMeanz != inTracklet->GetMeanz() ) return kFALSE;
    2483             :   if ( fZProb != inTracklet->GetZProb() ) return kFALSE;*/
    2484           0 :   if ( fN != inTracklet->fN ) return kFALSE;
    2485             :   //if ( fNUsed != inTracklet->fNUsed ) return kFALSE;
    2486             :   //if ( fFreq != inTracklet->GetFreq() ) return kFALSE;
    2487             :   //if ( fNChange != inTracklet->GetNChange() ) return kFALSE;
    2488             :    
    2489           0 :   if ( TMath::Abs(fC[0] - inTracklet->fC[0])>1.e-10 ) return kFALSE;
    2490             :   //if ( fCC != inTracklet->GetCC() ) return kFALSE;
    2491           0 :   if ( TMath::Abs(fChi2 - inTracklet->fChi2)>1.e-10 ) return kFALSE;
    2492             :   //  if ( fChi2Z != inTracklet->GetChi2Z() ) return kFALSE;
    2493             : 
    2494           0 :   if ( fDet != inTracklet->fDet ) return kFALSE;
    2495           0 :   if ( TMath::Abs(fPt - inTracklet->fPt)>1.e-10 ) return kFALSE;
    2496           0 :   if ( TMath::Abs(fdX - inTracklet->fdX)>1.e-10 ) return kFALSE;
    2497             :   
    2498           0 :   for (Int_t iCluster = 0; iCluster < kNclusters; iCluster++){
    2499           0 :     AliTRDcluster *curCluster = fClusters[iCluster];
    2500           0 :     AliTRDcluster *inCluster = inTracklet->fClusters[iCluster];
    2501           0 :     if (curCluster && inCluster){
    2502           0 :       if (! curCluster->IsEqual(inCluster) ) {
    2503           0 :         curCluster->Print();
    2504           0 :         inCluster->Print();
    2505           0 :         return kFALSE;
    2506             :       }
    2507             :     } else {
    2508             :       // if one cluster exists, and corresponding 
    2509             :       // in other tracklet doesn't - return kFALSE
    2510           0 :       if(curCluster || inCluster) return kFALSE;
    2511             :     }
    2512           0 :   }
    2513           0 :   return kTRUE;
    2514           0 : }
    2515             : 

Generated by: LCOV version 1.11