]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TRD/AliTRDseedV1.cxx
Updated geometry including fixes in ITS and FMD
[u/mrichter/AliRoot.git] / TRD / AliTRDseedV1.cxx
CommitLineData
e4f2f73d 1/**************************************************************************
29b87567 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**************************************************************************/
e4f2f73d 15
16/* $Id$ */
17
18////////////////////////////////////////////////////////////////////////////
dd8059a8 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//
e4f2f73d 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 "TLinearFitter.h"
eb38ed55 40#include "TClonesArray.h" // tmp
41#include <TTreeStream.h>
e4f2f73d 42
43#include "AliLog.h"
44#include "AliMathBase.h"
d937ad7a 45#include "AliCDBManager.h"
46#include "AliTracker.h"
e4f2f73d 47
03cef9b2 48#include "AliTRDpadPlane.h"
e4f2f73d 49#include "AliTRDcluster.h"
f3d3af1b 50#include "AliTRDseedV1.h"
51#include "AliTRDtrackV1.h"
e4f2f73d 52#include "AliTRDcalibDB.h"
eb38ed55 53#include "AliTRDchamberTimeBin.h"
54#include "AliTRDtrackingChamber.h"
55#include "AliTRDtrackerV1.h"
56#include "AliTRDReconstructor.h"
e4f2f73d 57#include "AliTRDrecoParam.h"
a076fc2f 58#include "AliTRDCommonParam.h"
d937ad7a 59
0906e73e 60#include "Cal/AliTRDCalPID.h"
d937ad7a 61#include "Cal/AliTRDCalROC.h"
62#include "Cal/AliTRDCalDet.h"
e4f2f73d 63
e4f2f73d 64ClassImp(AliTRDseedV1)
65
66//____________________________________________________________________
ae4e8b84 67AliTRDseedV1::AliTRDseedV1(Int_t det)
3e778975 68 :AliTRDtrackletBase()
3a039a31 69 ,fReconstructor(0x0)
ae4e8b84 70 ,fClusterIter(0x0)
e3cf3d02 71 ,fExB(0.)
72 ,fVD(0.)
73 ,fT0(0.)
74 ,fS2PRF(0.)
75 ,fDiffL(0.)
76 ,fDiffT(0.)
ae4e8b84 77 ,fClusterIdx(0)
3e778975 78 ,fN(0)
ae4e8b84 79 ,fDet(det)
0906e73e 80 ,fMom(0.)
bcb6fb78 81 ,fdX(0.)
e3cf3d02 82 ,fX0(0.)
83 ,fX(0.)
84 ,fY(0.)
85 ,fZ(0.)
86 ,fS2Y(0.)
87 ,fS2Z(0.)
88 ,fC(0.)
89 ,fChi2(0.)
e4f2f73d 90{
91 //
92 // Constructor
93 //
8d2bec9e 94 for(Int_t ic=kNclusters; ic--;) fIndexes[ic] = -1;
95 memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
dd8059a8 96 memset(fPad, 0, 3*sizeof(Float_t));
e3cf3d02 97 fYref[0] = 0.; fYref[1] = 0.;
98 fZref[0] = 0.; fZref[1] = 0.;
99 fYfit[0] = 0.; fYfit[1] = 0.;
100 fZfit[0] = 0.; fZfit[1] = 0.;
8d2bec9e 101 memset(fdEdx, 0, kNslices*sizeof(Float_t));
29b87567 102 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec] = -1.;
e3cf3d02 103 fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
104 fLabels[2]=0; // number of different labels for tracklet
bb2db46c 105 memset(fRefCov, 0, 3*sizeof(Double_t));
d937ad7a 106 // covariance matrix [diagonal]
107 // default sy = 200um and sz = 2.3 cm
108 fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3;
f29f13a6 109 SetStandAlone(kFALSE);
e4f2f73d 110}
111
112//____________________________________________________________________
0906e73e 113AliTRDseedV1::AliTRDseedV1(const AliTRDseedV1 &ref)
3e778975 114 :AliTRDtrackletBase((AliTRDtrackletBase&)ref)
e3cf3d02 115 ,fReconstructor(0x0)
ae4e8b84 116 ,fClusterIter(0x0)
e3cf3d02 117 ,fExB(0.)
118 ,fVD(0.)
119 ,fT0(0.)
120 ,fS2PRF(0.)
121 ,fDiffL(0.)
122 ,fDiffT(0.)
ae4e8b84 123 ,fClusterIdx(0)
3e778975 124 ,fN(0)
e3cf3d02 125 ,fDet(-1)
e3cf3d02 126 ,fMom(0.)
127 ,fdX(0.)
128 ,fX0(0.)
129 ,fX(0.)
130 ,fY(0.)
131 ,fZ(0.)
132 ,fS2Y(0.)
133 ,fS2Z(0.)
134 ,fC(0.)
135 ,fChi2(0.)
e4f2f73d 136{
137 //
138 // Copy Constructor performing a deep copy
139 //
e3cf3d02 140 if(this != &ref){
141 ref.Copy(*this);
142 }
29b87567 143 SetBit(kOwner, kFALSE);
f29f13a6 144 SetStandAlone(ref.IsStandAlone());
fbb2ea06 145}
d9950a5a 146
0906e73e 147
e4f2f73d 148//____________________________________________________________________
149AliTRDseedV1& AliTRDseedV1::operator=(const AliTRDseedV1 &ref)
150{
151 //
152 // Assignment Operator using the copy function
153 //
154
29b87567 155 if(this != &ref){
156 ref.Copy(*this);
157 }
221ab7e0 158 SetBit(kOwner, kFALSE);
159
29b87567 160 return *this;
e4f2f73d 161}
162
163//____________________________________________________________________
164AliTRDseedV1::~AliTRDseedV1()
165{
166 //
167 // Destructor. The RecoParam object belongs to the underlying tracker.
168 //
169
29b87567 170 //printf("I-AliTRDseedV1::~AliTRDseedV1() : Owner[%s]\n", IsOwner()?"YES":"NO");
e4f2f73d 171
e3cf3d02 172 if(IsOwner()) {
8d2bec9e 173 for(int itb=0; itb<kNclusters; itb++){
29b87567 174 if(!fClusters[itb]) continue;
175 //AliInfo(Form("deleting c %p @ %d", fClusters[itb], itb));
176 delete fClusters[itb];
177 fClusters[itb] = 0x0;
178 }
e3cf3d02 179 }
e4f2f73d 180}
181
182//____________________________________________________________________
183void AliTRDseedV1::Copy(TObject &ref) const
184{
185 //
186 // Copy function
187 //
188
29b87567 189 //AliInfo("");
190 AliTRDseedV1 &target = (AliTRDseedV1 &)ref;
191
e3cf3d02 192 target.fReconstructor = fReconstructor;
ae4e8b84 193 target.fClusterIter = 0x0;
e3cf3d02 194 target.fExB = fExB;
195 target.fVD = fVD;
196 target.fT0 = fT0;
197 target.fS2PRF = fS2PRF;
198 target.fDiffL = fDiffL;
199 target.fDiffT = fDiffT;
ae4e8b84 200 target.fClusterIdx = 0;
3e778975 201 target.fN = fN;
ae4e8b84 202 target.fDet = fDet;
29b87567 203 target.fMom = fMom;
29b87567 204 target.fdX = fdX;
e3cf3d02 205 target.fX0 = fX0;
206 target.fX = fX;
207 target.fY = fY;
208 target.fZ = fZ;
209 target.fS2Y = fS2Y;
210 target.fS2Z = fS2Z;
211 target.fC = fC;
212 target.fChi2 = fChi2;
29b87567 213
8d2bec9e 214 memcpy(target.fIndexes, fIndexes, kNclusters*sizeof(Int_t));
215 memcpy(target.fClusters, fClusters, kNclusters*sizeof(AliTRDcluster*));
dd8059a8 216 memcpy(target.fPad, fPad, 3*sizeof(Float_t));
e3cf3d02 217 target.fYref[0] = fYref[0]; target.fYref[1] = fYref[1];
218 target.fZref[0] = fZref[0]; target.fZref[1] = fZref[1];
219 target.fYfit[0] = fYfit[0]; target.fYfit[1] = fYfit[1];
220 target.fZfit[0] = fZfit[0]; target.fZfit[1] = fZfit[1];
8d2bec9e 221 memcpy(target.fdEdx, fdEdx, kNslices*sizeof(Float_t));
e3cf3d02 222 memcpy(target.fProb, fProb, AliPID::kSPECIES*sizeof(Float_t));
223 memcpy(target.fLabels, fLabels, 3*sizeof(Int_t));
224 memcpy(target.fRefCov, fRefCov, 3*sizeof(Double_t));
225 memcpy(target.fCov, fCov, 3*sizeof(Double_t));
29b87567 226
e3cf3d02 227 TObject::Copy(ref);
e4f2f73d 228}
229
0906e73e 230
231//____________________________________________________________
f3d3af1b 232Bool_t AliTRDseedV1::Init(AliTRDtrackV1 *track)
0906e73e 233{
234// Initialize this tracklet using the track information
235//
236// Parameters:
237// track - the TRD track used to initialize the tracklet
238//
239// Detailed description
240// The function sets the starting point and direction of the
241// tracklet according to the information from the TRD track.
242//
243// Caution
244// The TRD track has to be propagated to the beginning of the
245// chamber where the tracklet will be constructed
246//
247
29b87567 248 Double_t y, z;
249 if(!track->GetProlongation(fX0, y, z)) return kFALSE;
b1957d3c 250 UpDate(track);
29b87567 251 return kTRUE;
0906e73e 252}
253
bcb6fb78 254
e3cf3d02 255//_____________________________________________________________________________
256void AliTRDseedV1::Reset()
257{
258 //
259 // Reset seed
260 //
261 fExB=0.;fVD=0.;fT0=0.;fS2PRF=0.;
262 fDiffL=0.;fDiffT=0.;
3e778975 263 fClusterIdx=0;
264 fN=0;
dd8059a8 265 fDet=-1;
e3cf3d02 266 fMom=0.;
267 fdX=0.;fX0=0.; fX=0.; fY=0.; fZ=0.;
268 fS2Y=0.; fS2Z=0.;
269 fC=0.; fChi2 = 0.;
270
8d2bec9e 271 for(Int_t ic=kNclusters; ic--;) fIndexes[ic] = -1;
272 memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
dd8059a8 273 memset(fPad, 0, 3*sizeof(Float_t));
e3cf3d02 274 fYref[0] = 0.; fYref[1] = 0.;
275 fZref[0] = 0.; fZref[1] = 0.;
276 fYfit[0] = 0.; fYfit[1] = 0.;
277 fZfit[0] = 0.; fZfit[1] = 0.;
8d2bec9e 278 memset(fdEdx, 0, kNslices*sizeof(Float_t));
e3cf3d02 279 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec] = -1.;
280 fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
281 fLabels[2]=0; // number of different labels for tracklet
bb2db46c 282 memset(fRefCov, 0, 3*sizeof(Double_t));
e3cf3d02 283 // covariance matrix [diagonal]
284 // default sy = 200um and sz = 2.3 cm
285 fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3;
286}
287
b1957d3c 288//____________________________________________________________________
289void AliTRDseedV1::UpDate(const AliTRDtrackV1 *trk)
290{
291 // update tracklet reference position from the TRD track
292 // Funny name to avoid the clash with the function AliTRDseed::Update() (has to be made obselete)
293
e3cf3d02 294 Double_t fSnp = trk->GetSnp();
295 Double_t fTgl = trk->GetTgl();
b1957d3c 296 fMom = trk->GetP();
297 fYref[1] = fSnp/(1. - fSnp*fSnp);
298 fZref[1] = fTgl;
299 SetCovRef(trk->GetCovariance());
300
301 Double_t dx = trk->GetX() - fX0;
302 fYref[0] = trk->GetY() - dx*fYref[1];
303 fZref[0] = trk->GetZ() - dx*fZref[1];
304}
305
e3cf3d02 306//_____________________________________________________________________________
307void AliTRDseedV1::UpdateUsed()
308{
309 //
f29f13a6 310 // Calculate number of used clusers in the tracklet
e3cf3d02 311 //
312
3e778975 313 Int_t nused = 0, nshared = 0;
8d2bec9e 314 for (Int_t i = kNclusters; i--; ) {
e3cf3d02 315 if (!fClusters[i]) continue;
3e778975 316 if(fClusters[i]->IsUsed()){
317 nused++;
318 } else if(fClusters[i]->IsShared()){
319 if(IsStandAlone()) nused++;
320 else nshared++;
321 }
e3cf3d02 322 }
3e778975 323 SetNUsed(nused);
324 SetNShared(nshared);
e3cf3d02 325}
326
327//_____________________________________________________________________________
328void AliTRDseedV1::UseClusters()
329{
330 //
331 // Use clusters
332 //
f29f13a6 333 // In stand alone mode:
334 // Clusters which are marked as used or shared from another track are
335 // removed from the tracklet
336 //
337 // In barrel mode:
338 // - Clusters which are used by another track become shared
339 // - Clusters which are attached to a kink track become shared
340 //
e3cf3d02 341 AliTRDcluster **c = &fClusters[0];
8d2bec9e 342 for (Int_t ic=kNclusters; ic--; c++) {
e3cf3d02 343 if(!(*c)) continue;
f29f13a6 344 if(IsStandAlone()){
345 if((*c)->IsShared() || (*c)->IsUsed()){
b82b4de1 346 if((*c)->IsShared()) SetNShared(GetNShared()-1);
347 else SetNUsed(GetNUsed()-1);
3e778975 348 (*c) = 0x0;
f29f13a6 349 fIndexes[ic] = -1;
3e778975 350 SetN(GetN()-1);
3e778975 351 continue;
f29f13a6 352 }
3e778975 353 } else {
f29f13a6 354 if((*c)->IsUsed() || IsKink()){
3e778975 355 (*c)->SetShared();
356 continue;
f29f13a6 357 }
358 }
359 (*c)->Use();
e3cf3d02 360 }
361}
362
363
f29f13a6 364
bcb6fb78 365//____________________________________________________________________
366void AliTRDseedV1::CookdEdx(Int_t nslices)
367{
368// Calculates average dE/dx for all slices and store them in the internal array fdEdx.
369//
370// Parameters:
371// nslices : number of slices for which dE/dx should be calculated
372// Output:
373// store results in the internal array fdEdx. This can be accessed with the method
374// AliTRDseedV1::GetdEdx()
375//
376// Detailed description
377// Calculates average dE/dx for all slices. Depending on the PID methode
378// the number of slices can be 3 (LQ) or 8(NN).
3ee48d6e 379// The calculation of dQ/dl are done using the tracklet fit results (see AliTRDseedV1::GetdQdl(Int_t))
bcb6fb78 380//
381// The following effects are included in the calculation:
382// 1. calibration values for t0 and vdrift (using x coordinate to calculate slice)
383// 2. cluster sharing (optional see AliTRDrecoParam::SetClusterSharing())
384// 3. cluster size
385//
386
8d2bec9e 387 Int_t nclusters[kNslices];
388 memset(nclusters, 0, kNslices*sizeof(Int_t));
389 memset(fdEdx, 0, kNslices*sizeof(Float_t));
e3cf3d02 390
e73abf77 391 const Double_t kDriftLength = (.5 * AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick());
29b87567 392
3ee48d6e 393 AliTRDcluster *c = 0x0;
29b87567 394 for(int ic=0; ic<AliTRDtrackerV1::GetNTimeBins(); ic++){
8e709c82 395 if(!(c = fClusters[ic]) && !(c = fClusters[ic+kNtb])) continue;
e73abf77 396 Float_t dx = TMath::Abs(fX0 - c->GetX());
29b87567 397
398 // Filter clusters for dE/dx calculation
399
400 // 1.consider calibration effects for slice determination
e73abf77 401 Int_t slice;
402 if(dx<kDriftLength){ // TODO should be replaced by c->IsInChamber()
403 slice = Int_t(dx * nslices / kDriftLength);
404 } else slice = c->GetX() < fX0 ? nslices-1 : 0;
405
406
29b87567 407 // 2. take sharing into account
3e778975 408 Float_t w = /*c->IsShared() ? .5 :*/ 1.;
29b87567 409
410 // 3. take into account large clusters TODO
411 //w *= c->GetNPads() > 3 ? .8 : 1.;
412
413 //CHECK !!!
414 fdEdx[slice] += w * GetdQdl(ic); //fdQdl[ic];
415 nclusters[slice]++;
416 } // End of loop over clusters
417
cd40b287 418 //if(fReconstructor->GetPIDMethod() == AliTRDReconstructor::kLQPID){
0d83b3a5 419 if(nslices == AliTRDpidUtil::kLQslices){
29b87567 420 // calculate mean charge per slice (only LQ PID)
421 for(int is=0; is<nslices; is++){
422 if(nclusters[is]) fdEdx[is] /= nclusters[is];
423 }
424 }
bcb6fb78 425}
426
e3cf3d02 427//_____________________________________________________________________________
428void AliTRDseedV1::CookLabels()
429{
430 //
431 // Cook 2 labels for seed
432 //
433
434 Int_t labels[200];
435 Int_t out[200];
436 Int_t nlab = 0;
8d2bec9e 437 for (Int_t i = 0; i < kNclusters; i++) {
e3cf3d02 438 if (!fClusters[i]) continue;
439 for (Int_t ilab = 0; ilab < 3; ilab++) {
440 if (fClusters[i]->GetLabel(ilab) >= 0) {
441 labels[nlab] = fClusters[i]->GetLabel(ilab);
442 nlab++;
443 }
444 }
445 }
446
fac58f00 447 fLabels[2] = AliMathBase::Freq(nlab,labels,out,kTRUE);
e3cf3d02 448 fLabels[0] = out[0];
449 if ((fLabels[2] > 1) && (out[3] > 1)) fLabels[1] = out[2];
450}
451
452
d937ad7a 453//____________________________________________________________________
454void AliTRDseedV1::GetClusterXY(const AliTRDcluster *c, Double_t &x, Double_t &y)
455{
456// Return corrected position of the cluster taking into
457// account variation of the drift velocity with drift length.
458
459
460 // drift velocity correction TODO to be moved to the clusterizer
461 const Float_t cx[] = {
462 -9.6280e-02, 1.3091e-01,-1.7415e-02,-9.9221e-02,-1.2040e-01,-9.5493e-02,
463 -5.0041e-02,-1.6726e-02, 3.5756e-03, 1.8611e-02, 2.6378e-02, 3.3823e-02,
464 3.4811e-02, 3.5282e-02, 3.5386e-02, 3.6047e-02, 3.5201e-02, 3.4384e-02,
465 3.2864e-02, 3.1932e-02, 3.2051e-02, 2.2539e-02,-2.5154e-02,-1.2050e-01,
466 -1.2050e-01
467 };
468
469 // PRF correction TODO to be replaced by the gaussian
470 // approximation with full error parametrization and // moved to the clusterizer
471 const Float_t cy[AliTRDgeometry::kNlayer][3] = {
472 { 4.014e-04, 8.605e-03, -6.880e+00},
473 {-3.061e-04, 9.663e-03, -6.789e+00},
474 { 1.124e-03, 1.105e-02, -6.825e+00},
475 {-1.527e-03, 1.231e-02, -6.777e+00},
476 { 2.150e-03, 1.387e-02, -6.783e+00},
477 {-1.296e-03, 1.486e-02, -6.825e+00}
478 };
479
480 Int_t ily = AliTRDgeometry::GetLayer(c->GetDetector());
481 x = c->GetX() - cx[c->GetLocalTimeBin()];
482 y = c->GetY() + cy[ily][0] + cy[ily][1] * TMath::Sin(cy[ily][2] * c->GetCenter());
483 return;
484}
b83573da 485
bcb6fb78 486//____________________________________________________________________
487Float_t AliTRDseedV1::GetdQdl(Int_t ic) const
488{
3ee48d6e 489// Using the linear approximation of the track inside one TRD chamber (TRD tracklet)
490// the charge per unit length can be written as:
491// BEGIN_LATEX
492// #frac{dq}{dl} = #frac{q_{c}}{dx * #sqrt{1 + #(){#frac{dy}{dx}}^{2}_{fit} + #(){#frac{dy}{dx}}^{2}_{ref}}}
493// END_LATEX
494// where qc is the total charge collected in the current time bin and dx is the length
495// of the time bin. For the moment (Jan 20 2009) only pad row cross corrections are
496// considered for the charge but none are applied for drift velocity variations along
497// the drift region or assymetry of the TRF
498//
499// Author : Alex Bercuci <A.Bercuci@gsi.de>
500//
501 Float_t dq = 0.;
502 if(fClusters[ic]) dq += TMath::Abs(fClusters[ic]->GetQ());
8e709c82 503 if(fClusters[ic+kNtb]) dq += TMath::Abs(fClusters[ic+kNtb]->GetQ());
504 if(dq<1.e-3 || fdX < 1.e-3) return 0.;
3ee48d6e 505
506 return dq/fdX/TMath::Sqrt(1. + fYfit[1]*fYfit[1] + fZref[1]*fZref[1]);
bcb6fb78 507}
508
0906e73e 509//____________________________________________________________________
3e778975 510Float_t* AliTRDseedV1::GetProbability(Bool_t force)
0906e73e 511{
3e778975 512 if(!force) return &fProb[0];
513 if(!CookPID()) return 0x0;
514 return &fProb[0];
515}
516
517//____________________________________________________________
518Bool_t AliTRDseedV1::CookPID()
519{
0906e73e 520// Fill probability array for tracklet from the DB.
521//
522// Parameters
523//
524// Output
525// returns pointer to the probability array and 0x0 if missing DB access
526//
527// Detailed description
528
29b87567 529
530 // retrive calibration db
0906e73e 531 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
532 if (!calibration) {
533 AliError("No access to calibration data");
3e778975 534 return kFALSE;
0906e73e 535 }
536
3a039a31 537 if (!fReconstructor) {
538 AliError("Reconstructor not set.");
3e778975 539 return kFALSE;
4ba1d6ae 540 }
541
0906e73e 542 // Retrieve the CDB container class with the parametric detector response
3a039a31 543 const AliTRDCalPID *pd = calibration->GetPIDObject(fReconstructor->GetPIDMethod());
0906e73e 544 if (!pd) {
545 AliError("No access to AliTRDCalPID object");
3e778975 546 return kFALSE;
0906e73e 547 }
29b87567 548 //AliInfo(Form("Method[%d] : %s", fReconstructor->GetRecoParam() ->GetPIDMethod(), pd->IsA()->GetName()));
10f75631 549
29b87567 550 // calculate tracklet length TO DO
0906e73e 551 Float_t length = (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick());
552 /// TMath::Sqrt((1.0 - fSnp[iPlane]*fSnp[iPlane]) / (1.0 + fTgl[iPlane]*fTgl[iPlane]));
553
554 //calculate dE/dx
3a039a31 555 CookdEdx(fReconstructor->GetNdEdxSlices());
0906e73e 556
557 // Sets the a priori probabilities
558 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
ae4e8b84 559 fProb[ispec] = pd->GetProbability(ispec, fMom, &fdEdx[0], length, GetPlane());
0906e73e 560 }
561
3e778975 562 return kTRUE;
0906e73e 563}
564
e4f2f73d 565//____________________________________________________________________
566Float_t AliTRDseedV1::GetQuality(Bool_t kZcorr) const
567{
568 //
569 // Returns a quality measurement of the current seed
570 //
571
dd8059a8 572 Float_t zcorr = kZcorr ? GetTilt() * (fZfit[0] - fZref[0]) : 0.;
29b87567 573 return
3e778975 574 .5 * TMath::Abs(18.0 - GetN())
29b87567 575 + 10.* TMath::Abs(fYfit[1] - fYref[1])
576 + 5. * TMath::Abs(fYfit[0] - fYref[0] + zcorr)
dd8059a8 577 + 2. * TMath::Abs(fZfit[0] - fZref[0]) / GetPadLength();
e4f2f73d 578}
579
0906e73e 580//____________________________________________________________________
d937ad7a 581void AliTRDseedV1::GetCovAt(Double_t x, Double_t *cov) const
0906e73e 582{
d937ad7a 583// Computes covariance in the y-z plane at radial point x (in tracking coordinates)
584// and returns the results in the preallocated array cov[3] as :
585// cov[0] = Var(y)
586// cov[1] = Cov(yz)
587// cov[2] = Var(z)
588//
589// Details
590//
591// For the linear transformation
592// BEGIN_LATEX
593// Y = T_{x} X^{T}
594// END_LATEX
595// The error propagation has the general form
596// BEGIN_LATEX
597// C_{Y} = T_{x} C_{X} T_{x}^{T}
598// END_LATEX
599// We apply this formula 2 times. First to calculate the covariance of the tracklet
600// at point x we consider:
601// BEGIN_LATEX
602// T_{x} = (1 x); X=(y0 dy/dx); C_{X}=#(){#splitline{Var(y0) Cov(y0, dy/dx)}{Cov(y0, dy/dx) Var(dy/dx)}}
603// END_LATEX
604// and secondly to take into account the tilt angle
605// BEGIN_LATEX
606// T_{#alpha} = #(){#splitline{cos(#alpha) __ sin(#alpha)}{-sin(#alpha) __ cos(#alpha)}}; X=(y z); C_{X}=#(){#splitline{Var(y) 0}{0 Var(z)}}
607// END_LATEX
608//
609// using simple trigonometrics one can write for this last case
610// BEGIN_LATEX
611// 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})}}
612// END_LATEX
613// which can be aproximated for small alphas (2 deg) with
614// BEGIN_LATEX
615// 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}}}
616// END_LATEX
617//
618// before applying the tilt rotation we also apply systematic uncertainties to the tracklet
619// position which can be tunned from outside via the AliTRDrecoParam::SetSysCovMatrix(). They might
620// account for extra misalignment/miscalibration uncertainties.
621//
622// Author :
623// Alex Bercuci <A.Bercuci@gsi.de>
624// Date : Jan 8th 2009
625//
b1957d3c 626
627
d937ad7a 628 Double_t xr = fX0-x;
629 Double_t sy2 = fCov[0] +2.*xr*fCov[1] + xr*xr*fCov[2];
dd8059a8 630 Double_t sz2 = GetPadLength()*GetPadLength()/12.;
0906e73e 631
d937ad7a 632 // insert systematic uncertainties
bb2db46c 633 if(fReconstructor){
634 Double_t sys[15]; memset(sys, 0, 15*sizeof(Double_t));
635 fReconstructor->GetRecoParam()->GetSysCovMatrix(sys);
636 sy2 += sys[0];
637 sz2 += sys[1];
638 }
d937ad7a 639 // rotate covariance matrix
dd8059a8 640 Double_t t2 = GetTilt()*GetTilt();
d937ad7a 641 Double_t correction = 1./(1. + t2);
642 cov[0] = (sy2+t2*sz2)*correction;
dd8059a8 643 cov[1] = GetTilt()*(sz2 - sy2)*correction;
d937ad7a 644 cov[2] = (t2*sy2+sz2)*correction;
645}
eb38ed55 646
bb2db46c 647//____________________________________________________________
648Double_t AliTRDseedV1::GetCovSqrt(Double_t *c, Double_t *d)
649{
650// Helper function to calculate the square root of the covariance matrix.
651// The input matrix is stored in the vector c and the result in the vector d.
652// Both arrays have to be initialized by the user with at least 3 elements
653//
654// For calculating the square root of the inverse
655// covariance matrix we use the following relation:
656// BEGIN_LATEX
657// A^{1/2} = VD^{1/2}V^{-1}
658// END_LATEX
659// with V being the matrix with the n eigenvectors as columns. Thus the matrix D is diagonal.
660//
661// Author A.Bercuci <A.Bercuci@gsi.de>
662// Date Mar 19 2009
663
664 Double_t D[2], // diagonalization of the covariance
665 L[2], // eigenvalues
666 V[2]; // eigenvectors
667 // the secular equation and its solution :
668 // (c[0]-L)(c[2]-L)-c[1]^2 = 0
669 // L^2 - L*Tr(c)+DET(c) = 0
670 // L12 = [Tr(c) +- sqrt(Tr(c)^2-4*DET(c))]/2
671 Double_t Tr = c[0]+c[2], // trace
672 DET = c[0]*c[2]-c[1]*c[1]; // determinant
673 Double_t DD = TMath::Sqrt(Tr*Tr - 4*DET);
674 L[0] = .5*(Tr + DD);
675 L[1] = .5*(Tr - DD);
676 // the V matrix is
677 // |1 1|
678 // |v0 v1|
679 V[0] = (L[0]-c[0])/c[1];
680 V[1] = (L[1]-c[0])/c[1];
681 printf("L12[%f %f]\n", L[0], L[1]);
682 printf("V0[%f] V1[%f]\n", V[0], V[1]);
683 DET = 1./(V[1]-V[0]);
684 // the inverse of the V matrix is
685 // 1 |v1 -v0|
686 //(v1-v0) |-1 1|
687 // the diagonal matrix elements are
688 D[0] = c[0]*V[1]+c[1]*(V[1]-1.)-c[2]; D[0]*=DET;
689 D[1] = -c[0]*V[0]*V[0]-c[1]*V[0]*(V[1]-1.)+c[2]*V[1]; D[1]*=DET;
690
691 Double_t tmp = -c[0]*V[0]+c[1]*(1.-V[1])+c[2];
692 printf("D11[%f] D12[%f]\n", D[0], tmp);
693 tmp = c[0]*V[0]*V[1]+c[1]*(V[1]*V[1]-V[0])-c[2]*V[1];
694 printf("D21[%f] D22[%f]\n", tmp, D[1]);
695
696 d[0] = (D[0]*V[1]-D[1])*DET;
697 d[1] = (D[0]*V[0]+D[1])*DET;
698 d[2] = (D[0]*V[0]*V[0]+D[1]*V[1])*DET;
699 tmp = D[0]*V[0]*V[1]-D[1]*V[1];
700 printf("d11[%f] d12[%f]\n", d[0], d[1]);
701 printf("d21[%f] d22[%f]\n", tmp, d[2]);
702
703 return 1.;
704}
705
706//____________________________________________________________
707Double_t AliTRDseedV1::GetCovInv(Double_t *c, Double_t *d)
708{
709// Helper function to calculate the inverse of the covariance matrix.
710// The input matrix is stored in the vector c and the result in the vector d.
711// Both arrays have to be initialized by the user with at least 3 elements
712// The return value is the determinant or 0 in case of singularity.
713//
714// Author A.Bercuci <A.Bercuci@gsi.de>
715// Date Mar 19 2009
716
717 Double_t Det = c[0]*c[2] - c[1]*c[1];
718 if(TMath::Abs(Det)<1.e-20) return 0.;
719 Double_t InvDet = 1./Det;
720 d[0] = c[2]*InvDet;
721 d[1] =-c[1]*InvDet;
722 d[2] = c[0]*InvDet;
723 return Det;
724}
0906e73e 725
d937ad7a 726//____________________________________________________________________
e3cf3d02 727void AliTRDseedV1::Calibrate()
d937ad7a 728{
e3cf3d02 729// Retrieve calibration and position parameters from OCDB.
730// The following information are used
d937ad7a 731// - detector index
e3cf3d02 732// - column and row position of first attached cluster. If no clusters are attached
733// to the tracklet a random central chamber position (c=70, r=7) will be used.
734//
735// The following information is cached in the tracklet
736// t0 (trigger delay)
737// drift velocity
738// PRF width
739// omega*tau = tg(a_L)
740// diffusion coefficients (longitudinal and transversal)
d937ad7a 741//
742// Author :
743// Alex Bercuci <A.Bercuci@gsi.de>
744// Date : Jan 8th 2009
745//
eb38ed55 746
d937ad7a 747 AliCDBManager *cdb = AliCDBManager::Instance();
748 if(cdb->GetRun() < 0){
749 AliError("OCDB manager not properly initialized");
750 return;
751 }
0906e73e 752
e3cf3d02 753 AliTRDcalibDB *calib = AliTRDcalibDB::Instance();
754 AliTRDCalROC *vdROC = calib->GetVdriftROC(fDet),
755 *t0ROC = calib->GetT0ROC(fDet);;
756 const AliTRDCalDet *vdDet = calib->GetVdriftDet();
757 const AliTRDCalDet *t0Det = calib->GetT0Det();
d937ad7a 758
759 Int_t col = 70, row = 7;
760 AliTRDcluster **c = &fClusters[0];
3e778975 761 if(GetN()){
d937ad7a 762 Int_t ic = 0;
8d2bec9e 763 while (ic<kNclusters && !(*c)){ic++; c++;}
d937ad7a 764 if(*c){
765 col = (*c)->GetPadCol();
766 row = (*c)->GetPadRow();
767 }
768 }
3a039a31 769
e3cf3d02 770 fT0 = t0Det->GetValue(fDet) + t0ROC->GetValue(col,row);
771 fVD = vdDet->GetValue(fDet) * vdROC->GetValue(col, row);
772 fS2PRF = calib->GetPRFWidth(fDet, col, row); fS2PRF *= fS2PRF;
773 fExB = AliTRDCommonParam::Instance()->GetOmegaTau(fVD);
774 AliTRDCommonParam::Instance()->GetDiffCoeff(fDiffL,
775 fDiffT, fVD);
776 SetBit(kCalib, kTRUE);
0906e73e 777}
778
0906e73e 779//____________________________________________________________________
29b87567 780void AliTRDseedV1::SetOwner()
0906e73e 781{
29b87567 782 //AliInfo(Form("own [%s] fOwner[%s]", own?"YES":"NO", fOwner?"YES":"NO"));
783
784 if(TestBit(kOwner)) return;
8d2bec9e 785 for(int ic=0; ic<kNclusters; ic++){
29b87567 786 if(!fClusters[ic]) continue;
787 fClusters[ic] = new AliTRDcluster(*fClusters[ic]);
788 }
789 SetBit(kOwner);
0906e73e 790}
791
eb2b4f91 792//____________________________________________________________
793void AliTRDseedV1::SetPadPlane(AliTRDpadPlane *p)
794{
795// Shortcut method to initialize pad geometry.
796 if(!p) return;
797 SetTilt(TMath::Tan(TMath::DegToRad()*p->GetTiltingAngle()));
798 SetPadLength(p->GetLengthIPad());
799 SetPadWidth(p->GetWidthIPad());
800}
801
802
f29f13a6 803// //____________________________________________________________________
804// Bool_t AliTRDseedV1::AttachClustersIter(AliTRDtrackingChamber *chamber, Float_t quality, Bool_t kZcorr, AliTRDcluster *c)
805// {
806// //
807// // Iterative process to register clusters to the seed.
808// // In iteration 0 we try only one pad-row and if quality not
809// // sufficient we try 2 pad-rows (about 5% of tracks cross 2 pad-rows)
810// //
811// // debug level 7
812// //
813//
814// if(!fReconstructor->GetRecoParam() ){
815// AliError("Seed can not be used without a valid RecoParam.");
816// return kFALSE;
817// }
818//
819// AliTRDchamberTimeBin *layer = 0x0;
820// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=7){
821// AliTRDtrackingChamber ch(*chamber);
822// ch.SetOwner();
823// TTreeSRedirector &cstreamer = *fReconstructor->GetDebugStream(AliTRDReconstructor::kTracker);
824// cstreamer << "AttachClustersIter"
825// << "chamber.=" << &ch
826// << "tracklet.=" << this
827// << "\n";
828// }
829//
830// Float_t tquality;
831// Double_t kroady = fReconstructor->GetRecoParam() ->GetRoad1y();
dd8059a8 832// Double_t kroadz = GetPadLength() * .5 + 1.;
f29f13a6 833//
834// // initialize configuration parameters
dd8059a8 835// Float_t zcorr = kZcorr ? GetTilt() * (fZfit[0] - fZref[0]) : 0.;
f29f13a6 836// Int_t niter = kZcorr ? 1 : 2;
837//
838// Double_t yexp, zexp;
839// Int_t ncl = 0;
840// // start seed update
841// for (Int_t iter = 0; iter < niter; iter++) {
842// ncl = 0;
843// for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
844// if(!(layer = chamber->GetTB(iTime))) continue;
845// if(!Int_t(*layer)) continue;
846//
847// // define searching configuration
848// Double_t dxlayer = layer->GetX() - fX0;
849// if(c){
850// zexp = c->GetZ();
851// //Try 2 pad-rows in second iteration
852// if (iter > 0) {
853// zexp = fZref[0] + fZref[1] * dxlayer - zcorr;
dd8059a8 854// if (zexp > c->GetZ()) zexp = c->GetZ() + GetPadLength()*0.5;
855// if (zexp < c->GetZ()) zexp = c->GetZ() - GetPadLength()*0.5;
f29f13a6 856// }
857// } else zexp = fZref[0] + (kZcorr ? fZref[1] * dxlayer : 0.);
858// yexp = fYref[0] + fYref[1] * dxlayer - zcorr;
859//
860// // Get and register cluster
861// Int_t index = layer->SearchNearestCluster(yexp, zexp, kroady, kroadz);
862// if (index < 0) continue;
863// AliTRDcluster *cl = (*layer)[index];
864//
865// fIndexes[iTime] = layer->GetGlobalIndex(index);
866// fClusters[iTime] = cl;
867// // fY[iTime] = cl->GetY();
868// // fZ[iTime] = cl->GetZ();
869// ncl++;
870// }
871// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=7) AliInfo(Form("iter = %d ncl [%d] = %d", iter, fDet, ncl));
872//
873// if(ncl>1){
874// // calculate length of the time bin (calibration aware)
875// Int_t irp = 0; Float_t x[2]={0., 0.}; Int_t tb[2] = {0,0};
e3cf3d02 876// for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
877// if(!fClusters[iTime]) continue;
f29f13a6 878// x[irp] = fClusters[iTime]->GetX();
879// tb[irp] = iTime;
880// irp++;
881// if(irp==2) break;
e3cf3d02 882// }
f29f13a6 883// Int_t dtb = tb[1] - tb[0];
884// fdX = dtb ? (x[0] - x[1]) / dtb : 0.15;
885//
886// // update X0 from the clusters (calibration/alignment aware)
887// for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
888// if(!(layer = chamber->GetTB(iTime))) continue;
889// if(!layer->IsT0()) continue;
890// if(fClusters[iTime]){
891// fX0 = fClusters[iTime]->GetX();
892// break;
893// } else { // we have to infere the position of the anode wire from the other clusters
894// for (Int_t jTime = iTime+1; jTime < AliTRDtrackerV1::GetNTimeBins(); jTime++) {
895// if(!fClusters[jTime]) continue;
896// fX0 = fClusters[jTime]->GetX() + fdX * (jTime - iTime);
897// break;
898// }
899// }
900// }
901//
902// // update YZ reference point
903// // TODO
904//
905// // update x reference positions (calibration/alignment aware)
906// // for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
907// // if(!fClusters[iTime]) continue;
908// // fX[iTime] = fX0 - fClusters[iTime]->GetX();
909// // }
910//
911// FitMI();
912// }
913// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=7) AliInfo(Form("iter = %d nclFit [%d] = %d", iter, fDet, fN2));
914//
915// if(IsOK()){
916// tquality = GetQuality(kZcorr);
917// if(tquality < quality) break;
918// else quality = tquality;
919// }
920// kroadz *= 2.;
921// } // Loop: iter
922// if (!IsOK()) return kFALSE;
923//
924// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=1) CookLabels();
925//
926// // load calibration params
927// Calibrate();
928// UpdateUsed();
929// return kTRUE;
930// }
e4f2f73d 931
932//____________________________________________________________________
b1957d3c 933Bool_t AliTRDseedV1::AttachClusters(AliTRDtrackingChamber *chamber, Bool_t tilt)
e4f2f73d 934{
935 //
936 // Projective algorithm to attach clusters to seeding tracklets
937 //
938 // Parameters
939 //
940 // Output
941 //
942 // Detailed description
943 // 1. Collapse x coordinate for the full detector plane
944 // 2. truncated mean on y (r-phi) direction
945 // 3. purge clusters
946 // 4. truncated mean on z direction
947 // 5. purge clusters
948 // 6. fit tracklet
949 //
b1957d3c 950 Bool_t kPRINT = kFALSE;
29b87567 951 if(!fReconstructor->GetRecoParam() ){
952 AliError("Seed can not be used without a valid RecoParam.");
953 return kFALSE;
954 }
b1957d3c 955 // Initialize reco params for this tracklet
956 // 1. first time bin in the drift region
957 Int_t t0 = 4;
958 Int_t kClmin = Int_t(fReconstructor->GetRecoParam() ->GetFindableClusters()*AliTRDtrackerV1::GetNTimeBins());
29b87567 959
b1957d3c 960 Double_t syRef = TMath::Sqrt(fRefCov[0]);
29b87567 961 //define roads
b1957d3c 962 Double_t kroady = 1.;
963 //fReconstructor->GetRecoParam() ->GetRoad1y();
dd8059a8 964 Double_t kroadz = GetPadLength() * 1.5 + 1.;
b1957d3c 965 if(kPRINT) printf("AttachClusters() sy[%f] road[%f]\n", syRef, kroady);
29b87567 966
967 // working variables
b1957d3c 968 const Int_t kNrows = 16;
8d2bec9e 969 AliTRDcluster *clst[kNrows][kNclusters];
b1957d3c 970 Double_t cond[4], dx, dy, yt, zt,
8d2bec9e 971 yres[kNrows][kNclusters];
972 Int_t idxs[kNrows][kNclusters], ncl[kNrows], ncls = 0;
b1957d3c 973 memset(ncl, 0, kNrows*sizeof(Int_t));
8d2bec9e 974 memset(clst, 0, kNrows*kNclusters*sizeof(AliTRDcluster*));
b1957d3c 975
29b87567 976 // Do cluster projection
b1957d3c 977 AliTRDcluster *c = 0x0;
29b87567 978 AliTRDchamberTimeBin *layer = 0x0;
b1957d3c 979 Bool_t kBUFFER = kFALSE;
980 for (Int_t it = 0; it < AliTRDtrackerV1::GetNTimeBins(); it++) {
981 if(!(layer = chamber->GetTB(it))) continue;
29b87567 982 if(!Int_t(*layer)) continue;
983
b1957d3c 984 dx = fX0 - layer->GetX();
985 yt = fYref[0] - fYref[1] * dx;
986 zt = fZref[0] - fZref[1] * dx;
987 if(kPRINT) printf("\t%2d dx[%f] yt[%f] zt[%f]\n", it, dx, yt, zt);
988
989 // select clusters on a 5 sigmaKalman level
990 cond[0] = yt; cond[2] = kroady;
991 cond[1] = zt; cond[3] = kroadz;
992 Int_t n=0, idx[6];
993 layer->GetClusters(cond, idx, n, 6);
994 for(Int_t ic = n; ic--;){
995 c = (*layer)[idx[ic]];
996 dy = yt - c->GetY();
dd8059a8 997 dy += tilt ? GetTilt() * (c->GetZ() - zt) : 0.;
b1957d3c 998 // select clusters on a 3 sigmaKalman level
999/* if(tilt && TMath::Abs(dy) > 3.*syRef){
1000 printf("too large !!!\n");
1001 continue;
1002 }*/
1003 Int_t r = c->GetPadRow();
1004 if(kPRINT) printf("\t\t%d dy[%f] yc[%f] r[%d]\n", ic, TMath::Abs(dy), c->GetY(), r);
1005 clst[r][ncl[r]] = c;
1006 idxs[r][ncl[r]] = idx[ic];
1007 yres[r][ncl[r]] = dy;
1008 ncl[r]++; ncls++;
1009
8d2bec9e 1010 if(ncl[r] >= kNclusters) {
1011 AliWarning(Form("Cluster candidates reached limit %d. Some may be lost.", kNclusters));
b1957d3c 1012 kBUFFER = kTRUE;
29b87567 1013 break;
1014 }
1015 }
b1957d3c 1016 if(kBUFFER) break;
29b87567 1017 }
b1957d3c 1018 if(kPRINT) printf("Found %d clusters\n", ncls);
1019 if(ncls<kClmin) return kFALSE;
1020
1021 // analyze each row individualy
1022 Double_t mean, syDis;
1023 Int_t nrow[] = {0, 0, 0}, nr = 0, lr=-1;
1024 for(Int_t ir=kNrows; ir--;){
1025 if(!(ncl[ir])) continue;
1026 if(lr>0 && lr-ir != 1){
1027 if(kPRINT) printf("W - gap in rows attached !!\n");
29b87567 1028 }
b1957d3c 1029 if(kPRINT) printf("\tir[%d] lr[%d] n[%d]\n", ir, lr, ncl[ir]);
1030 // Evaluate truncated mean on the y direction
1031 if(ncl[ir] > 3) AliMathBase::EvaluateUni(ncl[ir], yres[ir], mean, syDis, Int_t(ncl[ir]*.8));
1032 else {
1033 mean = 0.; syDis = 0.;
1034 }
1035
1036 // TODO check mean and sigma agains cluster resolution !!
1037 if(kPRINT) printf("\tr[%2d] m[%f %5.3fsigma] s[%f]\n", ir, mean, TMath::Abs(mean/syRef), syDis);
1038 // select clusters on a 3 sigmaDistr level
1039 Bool_t kFOUND = kFALSE;
1040 for(Int_t ic = ncl[ir]; ic--;){
1041 if(yres[ir][ic] - mean > 3. * syDis){
1042 clst[ir][ic] = 0x0; continue;
1043 }
1044 nrow[nr]++; kFOUND = kTRUE;
1045 }
1046 // exit loop
1047 if(kFOUND) nr++;
1048 lr = ir; if(nr>=3) break;
29b87567 1049 }
b1957d3c 1050 if(kPRINT) printf("lr[%d] nr[%d] nrow[0]=%d nrow[1]=%d nrow[2]=%d\n", lr, nr, nrow[0], nrow[1], nrow[2]);
1051
1052 // classify cluster rows
1053 Int_t row = -1;
1054 switch(nr){
1055 case 1:
1056 row = lr;
1057 break;
1058 case 2:
1059 SetBit(kRowCross, kTRUE); // mark pad row crossing
1060 if(nrow[0] > nrow[1]){ row = lr+1; lr = -1;}
1061 else{
1062 row = lr; lr = 1;
1063 nrow[2] = nrow[1];
1064 nrow[1] = nrow[0];
1065 nrow[0] = nrow[2];
29b87567 1066 }
b1957d3c 1067 break;
1068 case 3:
1069 SetBit(kRowCross, kTRUE); // mark pad row crossing
1070 break;
29b87567 1071 }
b1957d3c 1072 if(kPRINT) printf("\trow[%d] n[%d]\n\n", row, nrow[0]);
1073 if(row<0) return kFALSE;
29b87567 1074
b1957d3c 1075 // Select and store clusters
1076 // We should consider here :
1077 // 1. How far is the chamber boundary
1078 // 2. How big is the mean
3e778975 1079 Int_t n = 0;
b1957d3c 1080 for (Int_t ir = 0; ir < nr; ir++) {
1081 Int_t jr = row + ir*lr;
1082 if(kPRINT) printf("\tattach %d clusters for row %d\n", ncl[jr], jr);
1083 for (Int_t ic = 0; ic < ncl[jr]; ic++) {
1084 if(!(c = clst[jr][ic])) continue;
1085 Int_t it = c->GetPadTime();
1086 // TODO proper indexing of clusters !!
e3cf3d02 1087 fIndexes[it+kNtb*ir] = chamber->GetTB(it)->GetGlobalIndex(idxs[jr][ic]);
1088 fClusters[it+kNtb*ir] = c;
29b87567 1089
b1957d3c 1090 //printf("\tid[%2d] it[%d] idx[%d]\n", ic, it, fIndexes[it]);
1091
3e778975 1092 n++;
b1957d3c 1093 }
1094 }
1095
29b87567 1096 // number of minimum numbers of clusters expected for the tracklet
3e778975 1097 if (n < kClmin){
1098 //AliWarning(Form("Not enough clusters to fit the tracklet %d [%d].", n, kClmin));
e4f2f73d 1099 return kFALSE;
1100 }
3e778975 1101 SetN(n);
0906e73e 1102
e3cf3d02 1103 // Load calibration parameters for this tracklet
1104 Calibrate();
b1957d3c 1105
1106 // calculate dx for time bins in the drift region (calibration aware)
e3cf3d02 1107 Int_t irp = 0; Float_t x[2] = {0.,0.}; Int_t tb[2]={0,0};
b1957d3c 1108 for (Int_t it = t0; it < AliTRDtrackerV1::GetNTimeBins(); it++) {
1109 if(!fClusters[it]) continue;
1110 x[irp] = fClusters[it]->GetX();
1111 tb[irp] = it;
1112 irp++;
1113 if(irp==2) break;
e3cf3d02 1114 }
d86ed84c 1115 Int_t dtb = tb[1] - tb[0];
1116 fdX = dtb ? (x[0] - x[1]) / dtb : 0.15;
b1957d3c 1117
29b87567 1118 return kTRUE;
e4f2f73d 1119}
1120
03cef9b2 1121//____________________________________________________________
1122void AliTRDseedV1::Bootstrap(const AliTRDReconstructor *rec)
1123{
1124// Fill in all derived information. It has to be called after recovery from file or HLT.
1125// The primitive data are
1126// - list of clusters
1127// - detector (as the detector will be removed from clusters)
1128// - position of anode wire (fX0) - temporary
1129// - track reference position and direction
1130// - momentum of the track
1131// - time bin length [cm]
1132//
1133// A.Bercuci <A.Bercuci@gsi.de> Oct 30th 2008
1134//
1135 fReconstructor = rec;
1136 AliTRDgeometry g;
1137 AliTRDpadPlane *pp = g.GetPadPlane(fDet);
dd8059a8 1138 fPad[0] = pp->GetLengthIPad();
1139 fPad[1] = pp->GetWidthIPad();
1140 fPad[3] = TMath::Tan(TMath::DegToRad()*pp->GetTiltingAngle());
e3cf3d02 1141 //fSnp = fYref[1]/TMath::Sqrt(1+fYref[1]*fYref[1]);
1142 //fTgl = fZref[1];
3e778975 1143 Int_t n = 0, nshare = 0, nused = 0;
03cef9b2 1144 AliTRDcluster **cit = &fClusters[0];
8d2bec9e 1145 for(Int_t ic = kNclusters; ic--; cit++){
03cef9b2 1146 if(!(*cit)) return;
3e778975 1147 n++;
1148 if((*cit)->IsShared()) nshare++;
1149 if((*cit)->IsUsed()) nused++;
03cef9b2 1150 }
3e778975 1151 SetN(n); SetNUsed(nused); SetNShared(nshare);
e3cf3d02 1152 Fit();
03cef9b2 1153 CookLabels();
1154 GetProbability();
1155}
1156
1157
e4f2f73d 1158//____________________________________________________________________
d937ad7a 1159Bool_t AliTRDseedV1::Fit(Bool_t tilt, Int_t errors)
e4f2f73d 1160{
1161 //
1162 // Linear fit of the tracklet
1163 //
1164 // Parameters :
1165 //
1166 // Output :
1167 // True if successful
1168 //
1169 // Detailed description
1170 // 2. Check if tracklet crosses pad row boundary
1171 // 1. Calculate residuals in the y (r-phi) direction
1172 // 3. Do a Least Square Fit to the data
1173 //
1174
e3cf3d02 1175 if(!IsCalibrated()){
1176 AliWarning("Tracklet fit failed. Call Calibrate().");
1177 return kFALSE;
1178 }
1179
29b87567 1180 const Int_t kClmin = 8;
010d62b0 1181
9462866a 1182
1183 // cluster error parametrization parameters
010d62b0 1184 // 1. sy total charge
9462866a 1185 const Float_t sq0inv = 0.019962; // [1/q0]
1186 const Float_t sqb = 1.0281564; //[cm]
010d62b0 1187 // 2. sy for the PRF
1188 const Float_t scy[AliTRDgeometry::kNlayer][4] = {
d937ad7a 1189 {2.827e-02, 9.600e-04, 4.296e-01, 2.271e-02},
1190 {2.952e-02,-2.198e-04, 4.146e-01, 2.339e-02},
1191 {3.090e-02, 1.514e-03, 4.020e-01, 2.402e-02},
1192 {3.260e-02,-2.037e-03, 3.946e-01, 2.509e-02},
1193 {3.439e-02,-3.601e-04, 3.883e-01, 2.623e-02},
1194 {3.510e-02, 2.066e-03, 3.651e-01, 2.588e-02},
010d62b0 1195 };
1196 // 3. sy parallel to the track
d937ad7a 1197 const Float_t sy0 = 2.649e-02; // [cm]
1198 const Float_t sya = -8.864e-04; // [cm]
1199 const Float_t syb = -2.435e-01; // [cm]
1200
010d62b0 1201 // 4. sx parallel to the track
d937ad7a 1202 const Float_t sxgc = 5.427e-02;
1203 const Float_t sxgm = 7.783e-01;
1204 const Float_t sxgs = 2.743e-01;
1205 const Float_t sxe0 =-2.065e+00;
1206 const Float_t sxe1 =-2.978e-02;
1207
010d62b0 1208 // 5. sx perpendicular to the track
d937ad7a 1209// const Float_t sxd0 = 1.881e-02;
1210// const Float_t sxd1 =-4.101e-01;
1211// const Float_t sxd2 = 1.572e+00;
1212
2f7d6ac8 1213 // get track direction
1214 Double_t y0 = fYref[0];
1215 Double_t dydx = fYref[1];
1216 Double_t z0 = fZref[0];
1217 Double_t dzdx = fZref[1];
1218 Double_t yt, zt;
ae4e8b84 1219
e3cf3d02 1220 // calculation of tg^2(phi - a_L) and tg^2(a_L)
1221 Double_t tgg = (dydx-fExB)/(1.+dydx*fExB); tgg *= tgg;
1222 //Double_t exb2= fExB*fExB;
1223
b1957d3c 1224 //AliTRDtrackerV1::AliTRDLeastSquare fitterZ;
24d8660e 1225 TLinearFitter fitterY(1, "pol1");
29b87567 1226 // convertion factor from square to gauss distribution for sigma
b1957d3c 1227 //Double_t convert = 1./TMath::Sqrt(12.);
ae4e8b84 1228
29b87567 1229 // book cluster information
8d2bec9e 1230 Double_t qc[kNclusters], xc[kNclusters], yc[kNclusters], zc[kNclusters], sy[kNclusters];
e3cf3d02 1231
010d62b0 1232 Int_t ily = AliTRDgeometry::GetLayer(fDet);
dd8059a8 1233 Int_t n = 0;
9eb2d46c 1234 AliTRDcluster *c=0x0, **jc = &fClusters[0];
9eb2d46c 1235 for (Int_t ic=0; ic<kNtb; ic++, ++jc) {
b1957d3c 1236 //zRow[ic] = -1;
29b87567 1237 xc[ic] = -1.;
1238 yc[ic] = 999.;
1239 zc[ic] = 999.;
1240 sy[ic] = 0.;
b1957d3c 1241 //sz[ic] = 0.;
9eb2d46c 1242 if(!(c = (*jc))) continue;
29b87567 1243 if(!c->IsInChamber()) continue;
9462866a 1244
29b87567 1245 Float_t w = 1.;
1246 if(c->GetNPads()>4) w = .5;
1247 if(c->GetNPads()>5) w = .2;
010d62b0 1248
b1957d3c 1249 //zRow[fN] = c->GetPadRow();
dd8059a8 1250 qc[n] = TMath::Abs(c->GetQ());
d937ad7a 1251 // correct cluster position for PRF and v drift
e3cf3d02 1252 //Int_t jc = TMath::Max(fN-3, 0);
1253 //xc[fN] = c->GetXloc(fT0, fVD, &qc[jc], &xc[jc]/*, z0 - c->GetX()*dzdx*/);
1254 //Double_t s2 = fS2PRF + fDiffL*fDiffL*xc[fN]/(1.+2.*exb2)+tgg*xc[fN]*xc[fN]*exb2/12.;
dd8059a8 1255 //yc[fN] = c->GetYloc(s2, GetPadWidth(), xc[fN], fExB);
e3cf3d02 1256
1257 // uncalibrated cluster correction
1258 // TODO remove
d937ad7a 1259 Double_t x, y; GetClusterXY(c, x, y);
dd8059a8 1260 xc[n] = fX0 - x;
1261 yc[n] = y;
1262 zc[n] = c->GetZ();
2f7d6ac8 1263
1264 // extrapolated y value for the track
dd8059a8 1265 yt = y0 - xc[n]*dydx;
2f7d6ac8 1266 // extrapolated z value for the track
dd8059a8 1267 zt = z0 - xc[n]*dzdx;
2f7d6ac8 1268 // tilt correction
dd8059a8 1269 if(tilt) yc[n] -= GetTilt()*(zc[n] - zt);
2f7d6ac8 1270
010d62b0 1271 // ELABORATE CLUSTER ERROR
1272 // TODO to be moved to AliTRDcluster
010d62b0 1273 // basic y error (|| to track).
dd8059a8 1274 sy[n] = xc[n] < AliTRDgeometry::CamHght() ? 2. : sy0 + sya*TMath::Exp(1./(xc[n]+syb));
d937ad7a 1275 //printf("cluster[%d]\n\tsy[0] = %5.3e [um]\n", fN, sy[fN]*1.e4);
010d62b0 1276 // y error due to total charge
dd8059a8 1277 sy[n] += sqb*(1./qc[n] - sq0inv);
d937ad7a 1278 //printf("\tsy[1] = %5.3e [um]\n", sy[fN]*1.e4);
010d62b0 1279 // y error due to PRF
dd8059a8 1280 sy[n] += scy[ily][0]*TMath::Gaus(c->GetCenter(), scy[ily][1], scy[ily][2]) - scy[ily][3];
d937ad7a 1281 //printf("\tsy[2] = %5.3e [um]\n", sy[fN]*1.e4);
1282
dd8059a8 1283 sy[n] *= sy[n];
010d62b0 1284
1285 // ADD ERROR ON x
9462866a 1286 // error of drift length parallel to the track
dd8059a8 1287 Double_t sx = sxgc*TMath::Gaus(xc[n], sxgm, sxgs) + TMath::Exp(sxe0+sxe1*xc[n]); // [cm]
d937ad7a 1288 //printf("\tsx[0] = %5.3e [um]\n", sx*1.e4);
9462866a 1289 // error of drift length perpendicular to the track
1290 //sx += sxd0 + sxd1*d + sxd2*d*d;
d937ad7a 1291 sx *= sx; // square sx
d937ad7a 1292
9462866a 1293 // add error from ExB
dd8059a8 1294 if(errors>0) sy[n] += fExB*fExB*sx;
d937ad7a 1295 //printf("\tsy[3] = %5.3e [um^2]\n", sy[fN]*1.e8);
1296
1297 // global radial error due to misalignment/miscalibration
1298 Double_t sx0 = 0.; sx0 *= sx0;
1299 // add sx contribution to sy due to track angle
dd8059a8 1300 if(errors>1) sy[n] += tgg*(sx+sx0);
d937ad7a 1301 // TODO we should add tilt pad correction here
1302 //printf("\tsy[4] = %5.3e [um^2]\n", sy[fN]*1.e8);
dd8059a8 1303 c->SetSigmaY2(sy[n]);
d937ad7a 1304
dd8059a8 1305 sy[n] = TMath::Sqrt(sy[n]);
1306 fitterY.AddPoint(&xc[n], yc[n], sy[n]);
1307 n++;
29b87567 1308 }
47d5d320 1309 // to few clusters
dd8059a8 1310 if (n < kClmin) return kFALSE;
2f7d6ac8 1311
d937ad7a 1312 // fit XY
2f7d6ac8 1313 fitterY.Eval();
d937ad7a 1314 fYfit[0] = fitterY.GetParameter(0);
1315 fYfit[1] = -fitterY.GetParameter(1);
1316 // store covariance
1317 Double_t *p = fitterY.GetCovarianceMatrix();
1318 fCov[0] = p[0]; // variance of y0
1319 fCov[1] = p[1]; // covariance of y0, dydx
1320 fCov[2] = p[3]; // variance of dydx
b1957d3c 1321 // the ref radial position is set at the minimum of
1322 // the y variance of the tracklet
f29f13a6 1323 fX = -fCov[1]/fCov[2]; //fXref = fX0 - fXref;
1324 fS2Y = fCov[0] +2.*fX*fCov[1] + fX*fX*fCov[2];
b1957d3c 1325
1326 // fit XZ
1327 if(IsRowCross()){
1328 // TODO pad row cross position estimation !!!
1329 //AliInfo(Form("Padrow cross in detector %d", fDet));
dd8059a8 1330 fZfit[0] = .5*(zc[0]+zc[n-1]); fZfit[1] = 0.;
f29f13a6 1331 fS2Z = 0.02+1.55*fZref[1]; fS2Z *= fS2Z;
b1957d3c 1332 } else {
1333 fZfit[0] = zc[0]; fZfit[1] = 0.;
dd8059a8 1334 fS2Z = GetPadLength()*GetPadLength()/12.;
29b87567 1335 }
1336
29b87567 1337
b1957d3c 1338// // determine z offset of the fit
1339// Float_t zslope = 0.;
1340// Int_t nchanges = 0, nCross = 0;
1341// if(nz==2){ // tracklet is crossing pad row
1342// // Find the break time allowing one chage on pad-rows
1343// // with maximal number of accepted clusters
1344// Int_t padRef = zRow[0];
1345// for (Int_t ic=1; ic<fN; ic++) {
1346// if(zRow[ic] == padRef) continue;
1347//
1348// // debug
1349// if(zRow[ic-1] == zRow[ic]){
1350// printf("ERROR in pad row change!!!\n");
1351// }
1352//
1353// // evaluate parameters of the crossing point
1354// Float_t sx = (xc[ic-1] - xc[ic])*convert;
1355// fCross[0] = .5 * (xc[ic-1] + xc[ic]);
1356// fCross[2] = .5 * (zc[ic-1] + zc[ic]);
1357// fCross[3] = TMath::Max(dzdx * sx, .01);
1358// zslope = zc[ic-1] > zc[ic] ? 1. : -1.;
1359// padRef = zRow[ic];
1360// nCross = ic;
1361// nchanges++;
1362// }
1363// }
1364//
1365// // condition on nCross and reset nchanges TODO
1366//
1367// if(nchanges==1){
1368// if(dzdx * zslope < 0.){
1369// AliInfo("Tracklet-Track mismatch in dzdx. TODO.");
1370// }
1371//
1372//
1373// //zc[nc] = fitterZ.GetFunctionParameter(0);
1374// fCross[1] = fYfit[0] - fCross[0] * fYfit[1];
1375// fCross[0] = fX0 - fCross[0];
1376// }
29b87567 1377
29b87567 1378 return kTRUE;
e4f2f73d 1379}
1380
e4f2f73d 1381
f29f13a6 1382/*
e3cf3d02 1383//_____________________________________________________________________________
1384void AliTRDseedV1::FitMI()
1385{
1386//
1387// Fit the seed.
1388// Marian Ivanov's version
1389//
1390// linear fit on the y direction with respect to the reference direction.
1391// The residuals for each x (x = xc - x0) are deduced from:
1392// dy = y - yt (1)
1393// the tilting correction is written :
1394// y = yc + h*(zc-zt) (2)
1395// yt = y0+dy/dx*x (3)
1396// zt = z0+dz/dx*x (4)
1397// from (1),(2),(3) and (4)
1398// dy = yc - y0 - (dy/dx + h*dz/dx)*x + h*(zc-z0)
1399// the last term introduces the correction on y direction due to tilting pads. There are 2 ways to account for this:
1400// 1. use tilting correction for calculating the y
1401// 2. neglect tilting correction here and account for it in the error parametrization of the tracklet.
1402 const Float_t kRatio = 0.8;
1403 const Int_t kClmin = 5;
1404 const Float_t kmaxtan = 2;
1405
1406 if (TMath::Abs(fYref[1]) > kmaxtan){
1407 //printf("Exit: Abs(fYref[1]) = %3.3f, kmaxtan = %3.3f\n", TMath::Abs(fYref[1]), kmaxtan);
1408 return; // Track inclined too much
1409 }
1410
1411 Float_t sigmaexp = 0.05 + TMath::Abs(fYref[1] * 0.25); // Expected r.m.s in y direction
dd8059a8 1412 Float_t ycrosscor = GetPadLength() * GetTilt() * 0.5; // Y correction for crossing
e3cf3d02 1413 Int_t fNChange = 0;
1414
1415 Double_t sumw;
1416 Double_t sumwx;
1417 Double_t sumwx2;
1418 Double_t sumwy;
1419 Double_t sumwxy;
1420 Double_t sumwz;
1421 Double_t sumwxz;
1422
1423 // Buffering: Leave it constant fot Performance issues
1424 Int_t zints[kNtb]; // Histograming of the z coordinate
1425 // Get 1 and second max probable coodinates in z
1426 Int_t zouts[2*kNtb];
1427 Float_t allowedz[kNtb]; // Allowed z for given time bin
1428 Float_t yres[kNtb]; // Residuals from reference
dd8059a8 1429 //Float_t anglecor = GetTilt() * fZref[1]; // Correction to the angle
e3cf3d02 1430
1431 Float_t pos[3*kNtb]; memset(pos, 0, 3*kNtb*sizeof(Float_t));
1432 Float_t *fX = &pos[0], *fY = &pos[kNtb], *fZ = &pos[2*kNtb];
1433
1434 Int_t fN = 0; AliTRDcluster *c = 0x0;
1435 fN2 = 0;
1436 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1437 yres[i] = 10000.0;
1438 if (!(c = fClusters[i])) continue;
1439 if(!c->IsInChamber()) continue;
1440 // Residual y
dd8059a8 1441 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
e3cf3d02 1442 fX[i] = fX0 - c->GetX();
1443 fY[i] = c->GetY();
1444 fZ[i] = c->GetZ();
dd8059a8 1445 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
e3cf3d02 1446 zints[fN] = Int_t(fZ[i]);
1447 fN++;
1448 }
1449
1450 if (fN < kClmin){
1451 //printf("Exit fN < kClmin: fN = %d\n", fN);
1452 return;
1453 }
1454 Int_t nz = AliTRDtrackerV1::Freq(fN, zints, zouts, kFALSE);
1455 Float_t fZProb = zouts[0];
1456 if (nz <= 1) zouts[3] = 0;
1457 if (zouts[1] + zouts[3] < kClmin) {
1458 //printf("Exit zouts[1] = %d, zouts[3] = %d\n",zouts[1],zouts[3]);
1459 return;
1460 }
1461
1462 // Z distance bigger than pad - length
1463 if (TMath::Abs(zouts[0]-zouts[2]) > 12.0) zouts[3] = 0;
1464
1465 Int_t breaktime = -1;
1466 Bool_t mbefore = kFALSE;
1467 Int_t cumul[kNtb][2];
1468 Int_t counts[2] = { 0, 0 };
1469
1470 if (zouts[3] >= 3) {
1471
1472 //
1473 // Find the break time allowing one chage on pad-rows
1474 // with maximal number of accepted clusters
1475 //
1476 fNChange = 1;
1477 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1478 cumul[i][0] = counts[0];
1479 cumul[i][1] = counts[1];
1480 if (TMath::Abs(fZ[i]-zouts[0]) < 2) counts[0]++;
1481 if (TMath::Abs(fZ[i]-zouts[2]) < 2) counts[1]++;
1482 }
1483 Int_t maxcount = 0;
1484 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1485 Int_t after = cumul[AliTRDtrackerV1::GetNTimeBins()][0] - cumul[i][0];
1486 Int_t before = cumul[i][1];
1487 if (after + before > maxcount) {
1488 maxcount = after + before;
1489 breaktime = i;
1490 mbefore = kFALSE;
1491 }
1492 after = cumul[AliTRDtrackerV1::GetNTimeBins()-1][1] - cumul[i][1];
1493 before = cumul[i][0];
1494 if (after + before > maxcount) {
1495 maxcount = after + before;
1496 breaktime = i;
1497 mbefore = kTRUE;
1498 }
1499 }
1500 breaktime -= 1;
1501 }
1502
1503 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1504 if (i > breaktime) allowedz[i] = mbefore ? zouts[2] : zouts[0];
1505 if (i <= breaktime) allowedz[i] = (!mbefore) ? zouts[2] : zouts[0];
1506 }
1507
1508 if (((allowedz[0] > allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] < 0)) ||
1509 ((allowedz[0] < allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] > 0))) {
1510 //
1511 // Tracklet z-direction not in correspondance with track z direction
1512 //
1513 fNChange = 0;
1514 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1515 allowedz[i] = zouts[0]; // Only longest taken
1516 }
1517 }
1518
1519 if (fNChange > 0) {
1520 //
1521 // Cross pad -row tracklet - take the step change into account
1522 //
1523 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1524 if (!fClusters[i]) continue;
1525 if(!fClusters[i]->IsInChamber()) continue;
1526 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1527 // Residual y
dd8059a8 1528 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
1529 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
f29f13a6 1530// if (TMath::Abs(fZ[i] - fZProb) > 2) {
dd8059a8 1531// if (fZ[i] > fZProb) yres[i] += GetTilt() * GetPadLength();
1532// if (fZ[i] < fZProb) yres[i] -= GetTilt() * GetPadLength();
f29f13a6 1533 }
e3cf3d02 1534 }
1535 }
1536
1537 Double_t yres2[kNtb];
1538 Double_t mean;
1539 Double_t sigma;
1540 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1541 if (!fClusters[i]) continue;
1542 if(!fClusters[i]->IsInChamber()) continue;
1543 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1544 yres2[fN2] = yres[i];
1545 fN2++;
1546 }
1547 if (fN2 < kClmin) {
1548 //printf("Exit fN2 < kClmin: fN2 = %d\n", fN2);
1549 fN2 = 0;
1550 return;
1551 }
1552 AliMathBase::EvaluateUni(fN2,yres2,mean,sigma, Int_t(fN2*kRatio-2.));
1553 if (sigma < sigmaexp * 0.8) {
1554 sigma = sigmaexp;
1555 }
1556 //Float_t fSigmaY = sigma;
1557
1558 // Reset sums
1559 sumw = 0;
1560 sumwx = 0;
1561 sumwx2 = 0;
1562 sumwy = 0;
1563 sumwxy = 0;
1564 sumwz = 0;
1565 sumwxz = 0;
1566
1567 fN2 = 0;
1568 Float_t fMeanz = 0;
1569 Float_t fMPads = 0;
1570 fUsable = 0;
1571 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1572 if (!fClusters[i]) continue;
1573 if (!fClusters[i]->IsInChamber()) continue;
1574 if (TMath::Abs(fZ[i] - allowedz[i]) > 2){fClusters[i] = 0x0; continue;}
1575 if (TMath::Abs(yres[i] - mean) > 4.0 * sigma){fClusters[i] = 0x0; continue;}
1576 SETBIT(fUsable,i);
1577 fN2++;
1578 fMPads += fClusters[i]->GetNPads();
1579 Float_t weight = 1.0;
1580 if (fClusters[i]->GetNPads() > 4) weight = 0.5;
1581 if (fClusters[i]->GetNPads() > 5) weight = 0.2;
1582
1583
1584 Double_t x = fX[i];
1585 //printf("x = %7.3f dy = %7.3f fit %7.3f\n", x, yres[i], fY[i]-yres[i]);
1586
1587 sumw += weight;
1588 sumwx += x * weight;
1589 sumwx2 += x*x * weight;
1590 sumwy += weight * yres[i];
1591 sumwxy += weight * (yres[i]) * x;
1592 sumwz += weight * fZ[i];
1593 sumwxz += weight * fZ[i] * x;
1594
1595 }
1596
1597 if (fN2 < kClmin){
1598 //printf("Exit fN2 < kClmin(2): fN2 = %d\n",fN2);
1599 fN2 = 0;
1600 return;
1601 }
1602 fMeanz = sumwz / sumw;
1603 Float_t correction = 0;
1604 if (fNChange > 0) {
1605 // Tracklet on boundary
1606 if (fMeanz < fZProb) correction = ycrosscor;
1607 if (fMeanz > fZProb) correction = -ycrosscor;
1608 }
1609
1610 Double_t det = sumw * sumwx2 - sumwx * sumwx;
1611 fYfit[0] = (sumwx2 * sumwy - sumwx * sumwxy) / det;
1612 fYfit[1] = (sumw * sumwxy - sumwx * sumwy) / det;
1613
1614 fS2Y = 0;
1615 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1616 if (!TESTBIT(fUsable,i)) continue;
1617 Float_t delta = yres[i] - fYfit[0] - fYfit[1] * fX[i];
1618 fS2Y += delta*delta;
1619 }
1620 fS2Y = TMath::Sqrt(fS2Y / Float_t(fN2-2));
1621 // TEMPORARY UNTIL covariance properly calculated
1622 fS2Y = TMath::Max(fS2Y, Float_t(.1));
1623
1624 fZfit[0] = (sumwx2 * sumwz - sumwx * sumwxz) / det;
1625 fZfit[1] = (sumw * sumwxz - sumwx * sumwz) / det;
1626// fYfitR[0] += fYref[0] + correction;
1627// fYfitR[1] += fYref[1];
1628// fYfit[0] = fYfitR[0];
1629 fYfit[1] = -fYfit[1];
1630
1631 UpdateUsed();
f29f13a6 1632}*/
e3cf3d02 1633
e4f2f73d 1634//___________________________________________________________________
203967fc 1635void AliTRDseedV1::Print(Option_t *o) const
e4f2f73d 1636{
1637 //
1638 // Printing the seedstatus
1639 //
1640
eb2b4f91 1641 AliInfo(Form("Det[%3d] X0[%7.2f] Pad[L[%5.2f] W[%5.2f] Tilt[%+6.2f]]", fDet, fX0, GetPadLength(), GetPadWidth(), GetTilt()));
dd8059a8 1642 AliInfo(Form("N[%2d] Nused[%2d] Nshared[%2d] [%d]", GetN(), GetNUsed(), GetNShared(), fN));
1643
1644 Double_t cov[3], x=GetX();
1645 GetCovAt(x, cov);
1646 AliInfo(" | x[cm] | y[cm] | z[cm] | dydx | dzdx |");
1647 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]));
1648 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[2]), fZref[0]-fX*fYref[1], TMath::Sqrt(fRefCov[2]), fYref[1], fZref[1]))
203967fc 1649
1650
1651 if(strcmp(o, "a")!=0) return;
1652
4dc4dc2e 1653 AliTRDcluster* const* jc = &fClusters[0];
8d2bec9e 1654 for(int ic=0; ic<kNclusters; ic++, jc++) {
4dc4dc2e 1655 if(!(*jc)) continue;
203967fc 1656 (*jc)->Print(o);
4dc4dc2e 1657 }
e4f2f73d 1658}
47d5d320 1659
203967fc 1660
1661//___________________________________________________________________
1662Bool_t AliTRDseedV1::IsEqual(const TObject *o) const
1663{
1664 // Checks if current instance of the class has the same essential members
1665 // as the given one
1666
1667 if(!o) return kFALSE;
1668 const AliTRDseedV1 *inTracklet = dynamic_cast<const AliTRDseedV1*>(o);
1669 if(!inTracklet) return kFALSE;
1670
1671 for (Int_t i = 0; i < 2; i++){
e3cf3d02 1672 if ( fYref[i] != inTracklet->fYref[i] ) return kFALSE;
1673 if ( fZref[i] != inTracklet->fZref[i] ) return kFALSE;
203967fc 1674 }
1675
e3cf3d02 1676 if ( fS2Y != inTracklet->fS2Y ) return kFALSE;
dd8059a8 1677 if ( GetTilt() != inTracklet->GetTilt() ) return kFALSE;
1678 if ( GetPadLength() != inTracklet->GetPadLength() ) return kFALSE;
203967fc 1679
8d2bec9e 1680 for (Int_t i = 0; i < kNclusters; i++){
e3cf3d02 1681// if ( fX[i] != inTracklet->GetX(i) ) return kFALSE;
1682// if ( fY[i] != inTracklet->GetY(i) ) return kFALSE;
1683// if ( fZ[i] != inTracklet->GetZ(i) ) return kFALSE;
1684 if ( fIndexes[i] != inTracklet->fIndexes[i] ) return kFALSE;
203967fc 1685 }
f29f13a6 1686// if ( fUsable != inTracklet->fUsable ) return kFALSE;
203967fc 1687
1688 for (Int_t i=0; i < 2; i++){
e3cf3d02 1689 if ( fYfit[i] != inTracklet->fYfit[i] ) return kFALSE;
1690 if ( fZfit[i] != inTracklet->fZfit[i] ) return kFALSE;
1691 if ( fLabels[i] != inTracklet->fLabels[i] ) return kFALSE;
203967fc 1692 }
1693
e3cf3d02 1694/* if ( fMeanz != inTracklet->GetMeanz() ) return kFALSE;
1695 if ( fZProb != inTracklet->GetZProb() ) return kFALSE;*/
3e778975 1696 if ( fN != inTracklet->fN ) return kFALSE;
1697 //if ( fNUsed != inTracklet->fNUsed ) return kFALSE;
e3cf3d02 1698 //if ( fFreq != inTracklet->GetFreq() ) return kFALSE;
1699 //if ( fNChange != inTracklet->GetNChange() ) return kFALSE;
203967fc 1700
e3cf3d02 1701 if ( fC != inTracklet->fC ) return kFALSE;
1702 //if ( fCC != inTracklet->GetCC() ) return kFALSE;
1703 if ( fChi2 != inTracklet->fChi2 ) return kFALSE;
203967fc 1704 // if ( fChi2Z != inTracklet->GetChi2Z() ) return kFALSE;
1705
e3cf3d02 1706 if ( fDet != inTracklet->fDet ) return kFALSE;
1707 if ( fMom != inTracklet->fMom ) return kFALSE;
1708 if ( fdX != inTracklet->fdX ) return kFALSE;
203967fc 1709
8d2bec9e 1710 for (Int_t iCluster = 0; iCluster < kNclusters; iCluster++){
203967fc 1711 AliTRDcluster *curCluster = fClusters[iCluster];
e3cf3d02 1712 AliTRDcluster *inCluster = inTracklet->fClusters[iCluster];
203967fc 1713 if (curCluster && inCluster){
1714 if (! curCluster->IsEqual(inCluster) ) {
1715 curCluster->Print();
1716 inCluster->Print();
1717 return kFALSE;
1718 }
1719 } else {
1720 // if one cluster exists, and corresponding
1721 // in other tracklet doesn't - return kFALSE
1722 if(curCluster || inCluster) return kFALSE;
1723 }
1724 }
1725 return kTRUE;
1726}