]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TRD/AliTRDseedV1.cxx
store pt in the tracklet instead of momentum
[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)
b25a5e9e 80 ,fPt(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)
b25a5e9e 126 ,fPt(0.)
e3cf3d02 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;
b25a5e9e 203 target.fPt = fPt;
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;
b25a5e9e 266 fPt=0.;
e3cf3d02 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();
b25a5e9e 296 fPt = trk->Pt();
b1957d3c 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[] = {
b25a5e9e 462 1.6402e-01, 7.2917e-02, -6.7848e-02, -1.4529e-01, -1.6279e-01, -1.3116e-01,
463 -8.2712e-02, -4.9453e-02, -2.9501e-02, -1.4543e-02, -6.1749e-03, 3.9221e-04,
464 1.9711e-03, 2.7388e-03, 2.9070e-03, 3.4183e-03, 2.8014e-03, 1.9351e-03,
465 4.9252e-04, 4.5742e-04, 1.2263e-04, -1.2219e-02, -6.9658e-02, -1.6681e-01,
ec3f0161 466 0.0000e+00, };
d937ad7a 467
468 // PRF correction TODO to be replaced by the gaussian
469 // approximation with full error parametrization and // moved to the clusterizer
470 const Float_t cy[AliTRDgeometry::kNlayer][3] = {
471 { 4.014e-04, 8.605e-03, -6.880e+00},
472 {-3.061e-04, 9.663e-03, -6.789e+00},
473 { 1.124e-03, 1.105e-02, -6.825e+00},
474 {-1.527e-03, 1.231e-02, -6.777e+00},
475 { 2.150e-03, 1.387e-02, -6.783e+00},
476 {-1.296e-03, 1.486e-02, -6.825e+00}
477 };
478
479 Int_t ily = AliTRDgeometry::GetLayer(c->GetDetector());
480 x = c->GetX() - cx[c->GetLocalTimeBin()];
481 y = c->GetY() + cy[ily][0] + cy[ily][1] * TMath::Sin(cy[ily][2] * c->GetCenter());
482 return;
483}
b83573da 484
bcb6fb78 485//____________________________________________________________________
486Float_t AliTRDseedV1::GetdQdl(Int_t ic) const
487{
3ee48d6e 488// Using the linear approximation of the track inside one TRD chamber (TRD tracklet)
489// the charge per unit length can be written as:
490// BEGIN_LATEX
491// #frac{dq}{dl} = #frac{q_{c}}{dx * #sqrt{1 + #(){#frac{dy}{dx}}^{2}_{fit} + #(){#frac{dy}{dx}}^{2}_{ref}}}
492// END_LATEX
493// where qc is the total charge collected in the current time bin and dx is the length
494// of the time bin. For the moment (Jan 20 2009) only pad row cross corrections are
495// considered for the charge but none are applied for drift velocity variations along
496// the drift region or assymetry of the TRF
497//
498// Author : Alex Bercuci <A.Bercuci@gsi.de>
499//
500 Float_t dq = 0.;
501 if(fClusters[ic]) dq += TMath::Abs(fClusters[ic]->GetQ());
8e709c82 502 if(fClusters[ic+kNtb]) dq += TMath::Abs(fClusters[ic+kNtb]->GetQ());
503 if(dq<1.e-3 || fdX < 1.e-3) return 0.;
3ee48d6e 504
505 return dq/fdX/TMath::Sqrt(1. + fYfit[1]*fYfit[1] + fZref[1]*fZref[1]);
bcb6fb78 506}
507
0906e73e 508//____________________________________________________________________
3e778975 509Float_t* AliTRDseedV1::GetProbability(Bool_t force)
0906e73e 510{
3e778975 511 if(!force) return &fProb[0];
512 if(!CookPID()) return 0x0;
513 return &fProb[0];
514}
515
516//____________________________________________________________
517Bool_t AliTRDseedV1::CookPID()
518{
0906e73e 519// Fill probability array for tracklet from the DB.
520//
521// Parameters
522//
523// Output
524// returns pointer to the probability array and 0x0 if missing DB access
525//
526// Detailed description
527
29b87567 528
529 // retrive calibration db
0906e73e 530 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
531 if (!calibration) {
532 AliError("No access to calibration data");
3e778975 533 return kFALSE;
0906e73e 534 }
535
3a039a31 536 if (!fReconstructor) {
537 AliError("Reconstructor not set.");
3e778975 538 return kFALSE;
4ba1d6ae 539 }
540
0906e73e 541 // Retrieve the CDB container class with the parametric detector response
3a039a31 542 const AliTRDCalPID *pd = calibration->GetPIDObject(fReconstructor->GetPIDMethod());
0906e73e 543 if (!pd) {
544 AliError("No access to AliTRDCalPID object");
3e778975 545 return kFALSE;
0906e73e 546 }
29b87567 547 //AliInfo(Form("Method[%d] : %s", fReconstructor->GetRecoParam() ->GetPIDMethod(), pd->IsA()->GetName()));
10f75631 548
29b87567 549 // calculate tracklet length TO DO
0906e73e 550 Float_t length = (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick());
551 /// TMath::Sqrt((1.0 - fSnp[iPlane]*fSnp[iPlane]) / (1.0 + fTgl[iPlane]*fTgl[iPlane]));
552
553 //calculate dE/dx
3a039a31 554 CookdEdx(fReconstructor->GetNdEdxSlices());
0906e73e 555
556 // Sets the a priori probabilities
557 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
b25a5e9e 558 fProb[ispec] = pd->GetProbability(ispec, GetMomentum(), &fdEdx[0], length, GetPlane());
0906e73e 559 }
560
3e778975 561 return kTRUE;
0906e73e 562}
563
e4f2f73d 564//____________________________________________________________________
565Float_t AliTRDseedV1::GetQuality(Bool_t kZcorr) const
566{
567 //
568 // Returns a quality measurement of the current seed
569 //
570
dd8059a8 571 Float_t zcorr = kZcorr ? GetTilt() * (fZfit[0] - fZref[0]) : 0.;
29b87567 572 return
3e778975 573 .5 * TMath::Abs(18.0 - GetN())
29b87567 574 + 10.* TMath::Abs(fYfit[1] - fYref[1])
575 + 5. * TMath::Abs(fYfit[0] - fYref[0] + zcorr)
dd8059a8 576 + 2. * TMath::Abs(fZfit[0] - fZref[0]) / GetPadLength();
e4f2f73d 577}
578
0906e73e 579//____________________________________________________________________
d937ad7a 580void AliTRDseedV1::GetCovAt(Double_t x, Double_t *cov) const
0906e73e 581{
d937ad7a 582// Computes covariance in the y-z plane at radial point x (in tracking coordinates)
583// and returns the results in the preallocated array cov[3] as :
584// cov[0] = Var(y)
585// cov[1] = Cov(yz)
586// cov[2] = Var(z)
587//
588// Details
589//
590// For the linear transformation
591// BEGIN_LATEX
592// Y = T_{x} X^{T}
593// END_LATEX
594// The error propagation has the general form
595// BEGIN_LATEX
596// C_{Y} = T_{x} C_{X} T_{x}^{T}
597// END_LATEX
598// We apply this formula 2 times. First to calculate the covariance of the tracklet
599// at point x we consider:
600// BEGIN_LATEX
601// T_{x} = (1 x); X=(y0 dy/dx); C_{X}=#(){#splitline{Var(y0) Cov(y0, dy/dx)}{Cov(y0, dy/dx) Var(dy/dx)}}
602// END_LATEX
603// and secondly to take into account the tilt angle
604// BEGIN_LATEX
605// T_{#alpha} = #(){#splitline{cos(#alpha) __ sin(#alpha)}{-sin(#alpha) __ cos(#alpha)}}; X=(y z); C_{X}=#(){#splitline{Var(y) 0}{0 Var(z)}}
606// END_LATEX
607//
608// using simple trigonometrics one can write for this last case
609// BEGIN_LATEX
610// 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})}}
611// END_LATEX
612// which can be aproximated for small alphas (2 deg) with
613// BEGIN_LATEX
614// 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}}}
615// END_LATEX
616//
617// before applying the tilt rotation we also apply systematic uncertainties to the tracklet
618// position which can be tunned from outside via the AliTRDrecoParam::SetSysCovMatrix(). They might
619// account for extra misalignment/miscalibration uncertainties.
620//
621// Author :
622// Alex Bercuci <A.Bercuci@gsi.de>
623// Date : Jan 8th 2009
624//
b1957d3c 625
626
d937ad7a 627 Double_t xr = fX0-x;
628 Double_t sy2 = fCov[0] +2.*xr*fCov[1] + xr*xr*fCov[2];
dd8059a8 629 Double_t sz2 = GetPadLength()*GetPadLength()/12.;
0906e73e 630
d937ad7a 631 // insert systematic uncertainties
bb2db46c 632 if(fReconstructor){
633 Double_t sys[15]; memset(sys, 0, 15*sizeof(Double_t));
634 fReconstructor->GetRecoParam()->GetSysCovMatrix(sys);
635 sy2 += sys[0];
636 sz2 += sys[1];
637 }
d937ad7a 638 // rotate covariance matrix
dd8059a8 639 Double_t t2 = GetTilt()*GetTilt();
d937ad7a 640 Double_t correction = 1./(1. + t2);
641 cov[0] = (sy2+t2*sz2)*correction;
dd8059a8 642 cov[1] = GetTilt()*(sz2 - sy2)*correction;
d937ad7a 643 cov[2] = (t2*sy2+sz2)*correction;
644}
eb38ed55 645
bb2db46c 646//____________________________________________________________
647Double_t AliTRDseedV1::GetCovSqrt(Double_t *c, Double_t *d)
648{
649// Helper function to calculate the square root of the covariance matrix.
650// The input matrix is stored in the vector c and the result in the vector d.
41b7c7b6 651// Both arrays have to be initialized by the user with at least 3 elements. Return negative in case of failure.
bb2db46c 652//
ec3f0161 653// For calculating the square root of the symmetric matrix c
654// the following relation is used:
bb2db46c 655// BEGIN_LATEX
ec3f0161 656// C^{1/2} = VD^{1/2}V^{-1}
bb2db46c 657// END_LATEX
41b7c7b6 658// with V being the matrix with the n eigenvectors as columns.
ec3f0161 659// In case C is symmetric the followings are true:
660// - matrix D is diagonal with the diagonal given by the eigenvalues of C
41b7c7b6 661// - V = V^{-1}
bb2db46c 662//
663// Author A.Bercuci <A.Bercuci@gsi.de>
664// Date Mar 19 2009
665
41b7c7b6 666 Double_t L[2], // eigenvalues
667 V[3]; // eigenvectors
bb2db46c 668 // the secular equation and its solution :
669 // (c[0]-L)(c[2]-L)-c[1]^2 = 0
670 // L^2 - L*Tr(c)+DET(c) = 0
671 // L12 = [Tr(c) +- sqrt(Tr(c)^2-4*DET(c))]/2
672 Double_t Tr = c[0]+c[2], // trace
673 DET = c[0]*c[2]-c[1]*c[1]; // determinant
41b7c7b6 674 if(TMath::Abs(DET)<1.e-20) return -1.;
bb2db46c 675 Double_t DD = TMath::Sqrt(Tr*Tr - 4*DET);
676 L[0] = .5*(Tr + DD);
677 L[1] = .5*(Tr - DD);
41b7c7b6 678 if(L[0]<0. || L[1]<0.) return -1.;
679
680 // the sym V matrix
681 // | v00 v10|
682 // | v10 v11|
683 Double_t tmp = (L[0]-c[0])/c[1];
684 V[0] = TMath::Sqrt(1./(tmp*tmp+1));
685 V[1] = tmp*V[0];
686 V[2] = V[1]*c[1]/(L[1]-c[2]);
687 // the VD^{1/2}V is:
688 L[0] = TMath::Sqrt(L[0]); L[1] = TMath::Sqrt(L[1]);
689 d[0] = V[0]*V[0]*L[0]+V[1]*V[1]*L[1];
690 d[1] = V[0]*V[1]*L[0]+V[1]*V[2]*L[1];
691 d[2] = V[1]*V[1]*L[0]+V[2]*V[2]*L[1];
bb2db46c 692
693 return 1.;
694}
695
696//____________________________________________________________
697Double_t AliTRDseedV1::GetCovInv(Double_t *c, Double_t *d)
698{
699// Helper function to calculate the inverse of the covariance matrix.
700// The input matrix is stored in the vector c and the result in the vector d.
701// Both arrays have to be initialized by the user with at least 3 elements
702// The return value is the determinant or 0 in case of singularity.
703//
704// Author A.Bercuci <A.Bercuci@gsi.de>
705// Date Mar 19 2009
706
707 Double_t Det = c[0]*c[2] - c[1]*c[1];
708 if(TMath::Abs(Det)<1.e-20) return 0.;
709 Double_t InvDet = 1./Det;
710 d[0] = c[2]*InvDet;
711 d[1] =-c[1]*InvDet;
712 d[2] = c[0]*InvDet;
713 return Det;
714}
0906e73e 715
d937ad7a 716//____________________________________________________________________
e3cf3d02 717void AliTRDseedV1::Calibrate()
d937ad7a 718{
e3cf3d02 719// Retrieve calibration and position parameters from OCDB.
720// The following information are used
d937ad7a 721// - detector index
e3cf3d02 722// - column and row position of first attached cluster. If no clusters are attached
723// to the tracklet a random central chamber position (c=70, r=7) will be used.
724//
725// The following information is cached in the tracklet
726// t0 (trigger delay)
727// drift velocity
728// PRF width
729// omega*tau = tg(a_L)
730// diffusion coefficients (longitudinal and transversal)
d937ad7a 731//
732// Author :
733// Alex Bercuci <A.Bercuci@gsi.de>
734// Date : Jan 8th 2009
735//
eb38ed55 736
d937ad7a 737 AliCDBManager *cdb = AliCDBManager::Instance();
738 if(cdb->GetRun() < 0){
739 AliError("OCDB manager not properly initialized");
740 return;
741 }
0906e73e 742
e3cf3d02 743 AliTRDcalibDB *calib = AliTRDcalibDB::Instance();
744 AliTRDCalROC *vdROC = calib->GetVdriftROC(fDet),
745 *t0ROC = calib->GetT0ROC(fDet);;
746 const AliTRDCalDet *vdDet = calib->GetVdriftDet();
747 const AliTRDCalDet *t0Det = calib->GetT0Det();
d937ad7a 748
749 Int_t col = 70, row = 7;
750 AliTRDcluster **c = &fClusters[0];
3e778975 751 if(GetN()){
d937ad7a 752 Int_t ic = 0;
8d2bec9e 753 while (ic<kNclusters && !(*c)){ic++; c++;}
d937ad7a 754 if(*c){
755 col = (*c)->GetPadCol();
756 row = (*c)->GetPadRow();
757 }
758 }
3a039a31 759
e3cf3d02 760 fT0 = t0Det->GetValue(fDet) + t0ROC->GetValue(col,row);
761 fVD = vdDet->GetValue(fDet) * vdROC->GetValue(col, row);
762 fS2PRF = calib->GetPRFWidth(fDet, col, row); fS2PRF *= fS2PRF;
763 fExB = AliTRDCommonParam::Instance()->GetOmegaTau(fVD);
764 AliTRDCommonParam::Instance()->GetDiffCoeff(fDiffL,
765 fDiffT, fVD);
766 SetBit(kCalib, kTRUE);
0906e73e 767}
768
0906e73e 769//____________________________________________________________________
29b87567 770void AliTRDseedV1::SetOwner()
0906e73e 771{
29b87567 772 //AliInfo(Form("own [%s] fOwner[%s]", own?"YES":"NO", fOwner?"YES":"NO"));
773
774 if(TestBit(kOwner)) return;
8d2bec9e 775 for(int ic=0; ic<kNclusters; ic++){
29b87567 776 if(!fClusters[ic]) continue;
777 fClusters[ic] = new AliTRDcluster(*fClusters[ic]);
778 }
779 SetBit(kOwner);
0906e73e 780}
781
eb2b4f91 782//____________________________________________________________
783void AliTRDseedV1::SetPadPlane(AliTRDpadPlane *p)
784{
785// Shortcut method to initialize pad geometry.
786 if(!p) return;
787 SetTilt(TMath::Tan(TMath::DegToRad()*p->GetTiltingAngle()));
788 SetPadLength(p->GetLengthIPad());
789 SetPadWidth(p->GetWidthIPad());
790}
791
792
f29f13a6 793// //____________________________________________________________________
794// Bool_t AliTRDseedV1::AttachClustersIter(AliTRDtrackingChamber *chamber, Float_t quality, Bool_t kZcorr, AliTRDcluster *c)
795// {
796// //
797// // Iterative process to register clusters to the seed.
798// // In iteration 0 we try only one pad-row and if quality not
799// // sufficient we try 2 pad-rows (about 5% of tracks cross 2 pad-rows)
800// //
801// // debug level 7
802// //
803//
804// if(!fReconstructor->GetRecoParam() ){
805// AliError("Seed can not be used without a valid RecoParam.");
806// return kFALSE;
807// }
808//
809// AliTRDchamberTimeBin *layer = 0x0;
810// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=7){
811// AliTRDtrackingChamber ch(*chamber);
812// ch.SetOwner();
813// TTreeSRedirector &cstreamer = *fReconstructor->GetDebugStream(AliTRDReconstructor::kTracker);
814// cstreamer << "AttachClustersIter"
815// << "chamber.=" << &ch
816// << "tracklet.=" << this
817// << "\n";
818// }
819//
820// Float_t tquality;
821// Double_t kroady = fReconstructor->GetRecoParam() ->GetRoad1y();
dd8059a8 822// Double_t kroadz = GetPadLength() * .5 + 1.;
f29f13a6 823//
824// // initialize configuration parameters
dd8059a8 825// Float_t zcorr = kZcorr ? GetTilt() * (fZfit[0] - fZref[0]) : 0.;
f29f13a6 826// Int_t niter = kZcorr ? 1 : 2;
827//
828// Double_t yexp, zexp;
829// Int_t ncl = 0;
830// // start seed update
831// for (Int_t iter = 0; iter < niter; iter++) {
832// ncl = 0;
833// for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
834// if(!(layer = chamber->GetTB(iTime))) continue;
835// if(!Int_t(*layer)) continue;
836//
837// // define searching configuration
838// Double_t dxlayer = layer->GetX() - fX0;
839// if(c){
840// zexp = c->GetZ();
841// //Try 2 pad-rows in second iteration
842// if (iter > 0) {
843// zexp = fZref[0] + fZref[1] * dxlayer - zcorr;
dd8059a8 844// if (zexp > c->GetZ()) zexp = c->GetZ() + GetPadLength()*0.5;
845// if (zexp < c->GetZ()) zexp = c->GetZ() - GetPadLength()*0.5;
f29f13a6 846// }
847// } else zexp = fZref[0] + (kZcorr ? fZref[1] * dxlayer : 0.);
848// yexp = fYref[0] + fYref[1] * dxlayer - zcorr;
849//
850// // Get and register cluster
851// Int_t index = layer->SearchNearestCluster(yexp, zexp, kroady, kroadz);
852// if (index < 0) continue;
853// AliTRDcluster *cl = (*layer)[index];
854//
855// fIndexes[iTime] = layer->GetGlobalIndex(index);
856// fClusters[iTime] = cl;
857// // fY[iTime] = cl->GetY();
858// // fZ[iTime] = cl->GetZ();
859// ncl++;
860// }
861// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=7) AliInfo(Form("iter = %d ncl [%d] = %d", iter, fDet, ncl));
862//
863// if(ncl>1){
864// // calculate length of the time bin (calibration aware)
865// Int_t irp = 0; Float_t x[2]={0., 0.}; Int_t tb[2] = {0,0};
e3cf3d02 866// for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
867// if(!fClusters[iTime]) continue;
f29f13a6 868// x[irp] = fClusters[iTime]->GetX();
869// tb[irp] = iTime;
870// irp++;
871// if(irp==2) break;
e3cf3d02 872// }
f29f13a6 873// Int_t dtb = tb[1] - tb[0];
874// fdX = dtb ? (x[0] - x[1]) / dtb : 0.15;
875//
876// // update X0 from the clusters (calibration/alignment aware)
877// for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
878// if(!(layer = chamber->GetTB(iTime))) continue;
879// if(!layer->IsT0()) continue;
880// if(fClusters[iTime]){
881// fX0 = fClusters[iTime]->GetX();
882// break;
883// } else { // we have to infere the position of the anode wire from the other clusters
884// for (Int_t jTime = iTime+1; jTime < AliTRDtrackerV1::GetNTimeBins(); jTime++) {
885// if(!fClusters[jTime]) continue;
886// fX0 = fClusters[jTime]->GetX() + fdX * (jTime - iTime);
887// break;
888// }
889// }
890// }
891//
892// // update YZ reference point
893// // TODO
894//
895// // update x reference positions (calibration/alignment aware)
896// // for (Int_t iTime = 0; iTime < AliTRDtrackerV1::GetNTimeBins(); iTime++) {
897// // if(!fClusters[iTime]) continue;
898// // fX[iTime] = fX0 - fClusters[iTime]->GetX();
899// // }
900//
901// FitMI();
902// }
903// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=7) AliInfo(Form("iter = %d nclFit [%d] = %d", iter, fDet, fN2));
904//
905// if(IsOK()){
906// tquality = GetQuality(kZcorr);
907// if(tquality < quality) break;
908// else quality = tquality;
909// }
910// kroadz *= 2.;
911// } // Loop: iter
912// if (!IsOK()) return kFALSE;
913//
914// if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker)>=1) CookLabels();
915//
916// // load calibration params
917// Calibrate();
918// UpdateUsed();
919// return kTRUE;
920// }
e4f2f73d 921
922//____________________________________________________________________
b1957d3c 923Bool_t AliTRDseedV1::AttachClusters(AliTRDtrackingChamber *chamber, Bool_t tilt)
e4f2f73d 924{
925 //
926 // Projective algorithm to attach clusters to seeding tracklets
927 //
928 // Parameters
929 //
930 // Output
931 //
932 // Detailed description
933 // 1. Collapse x coordinate for the full detector plane
934 // 2. truncated mean on y (r-phi) direction
935 // 3. purge clusters
936 // 4. truncated mean on z direction
937 // 5. purge clusters
938 // 6. fit tracklet
939 //
b1957d3c 940 Bool_t kPRINT = kFALSE;
29b87567 941 if(!fReconstructor->GetRecoParam() ){
942 AliError("Seed can not be used without a valid RecoParam.");
943 return kFALSE;
944 }
b1957d3c 945 // Initialize reco params for this tracklet
946 // 1. first time bin in the drift region
947 Int_t t0 = 4;
948 Int_t kClmin = Int_t(fReconstructor->GetRecoParam() ->GetFindableClusters()*AliTRDtrackerV1::GetNTimeBins());
29b87567 949
b1957d3c 950 Double_t syRef = TMath::Sqrt(fRefCov[0]);
29b87567 951 //define roads
b1957d3c 952 Double_t kroady = 1.;
953 //fReconstructor->GetRecoParam() ->GetRoad1y();
dd8059a8 954 Double_t kroadz = GetPadLength() * 1.5 + 1.;
b1957d3c 955 if(kPRINT) printf("AttachClusters() sy[%f] road[%f]\n", syRef, kroady);
29b87567 956
957 // working variables
b1957d3c 958 const Int_t kNrows = 16;
8d2bec9e 959 AliTRDcluster *clst[kNrows][kNclusters];
b1957d3c 960 Double_t cond[4], dx, dy, yt, zt,
8d2bec9e 961 yres[kNrows][kNclusters];
962 Int_t idxs[kNrows][kNclusters], ncl[kNrows], ncls = 0;
b1957d3c 963 memset(ncl, 0, kNrows*sizeof(Int_t));
8d2bec9e 964 memset(clst, 0, kNrows*kNclusters*sizeof(AliTRDcluster*));
b1957d3c 965
29b87567 966 // Do cluster projection
b1957d3c 967 AliTRDcluster *c = 0x0;
29b87567 968 AliTRDchamberTimeBin *layer = 0x0;
b1957d3c 969 Bool_t kBUFFER = kFALSE;
970 for (Int_t it = 0; it < AliTRDtrackerV1::GetNTimeBins(); it++) {
971 if(!(layer = chamber->GetTB(it))) continue;
29b87567 972 if(!Int_t(*layer)) continue;
973
b1957d3c 974 dx = fX0 - layer->GetX();
975 yt = fYref[0] - fYref[1] * dx;
976 zt = fZref[0] - fZref[1] * dx;
977 if(kPRINT) printf("\t%2d dx[%f] yt[%f] zt[%f]\n", it, dx, yt, zt);
978
979 // select clusters on a 5 sigmaKalman level
980 cond[0] = yt; cond[2] = kroady;
981 cond[1] = zt; cond[3] = kroadz;
982 Int_t n=0, idx[6];
983 layer->GetClusters(cond, idx, n, 6);
984 for(Int_t ic = n; ic--;){
985 c = (*layer)[idx[ic]];
986 dy = yt - c->GetY();
dd8059a8 987 dy += tilt ? GetTilt() * (c->GetZ() - zt) : 0.;
b1957d3c 988 // select clusters on a 3 sigmaKalman level
989/* if(tilt && TMath::Abs(dy) > 3.*syRef){
990 printf("too large !!!\n");
991 continue;
992 }*/
993 Int_t r = c->GetPadRow();
994 if(kPRINT) printf("\t\t%d dy[%f] yc[%f] r[%d]\n", ic, TMath::Abs(dy), c->GetY(), r);
995 clst[r][ncl[r]] = c;
996 idxs[r][ncl[r]] = idx[ic];
997 yres[r][ncl[r]] = dy;
998 ncl[r]++; ncls++;
999
8d2bec9e 1000 if(ncl[r] >= kNclusters) {
1001 AliWarning(Form("Cluster candidates reached limit %d. Some may be lost.", kNclusters));
b1957d3c 1002 kBUFFER = kTRUE;
29b87567 1003 break;
1004 }
1005 }
b1957d3c 1006 if(kBUFFER) break;
29b87567 1007 }
b1957d3c 1008 if(kPRINT) printf("Found %d clusters\n", ncls);
1009 if(ncls<kClmin) return kFALSE;
1010
1011 // analyze each row individualy
1012 Double_t mean, syDis;
1013 Int_t nrow[] = {0, 0, 0}, nr = 0, lr=-1;
1014 for(Int_t ir=kNrows; ir--;){
1015 if(!(ncl[ir])) continue;
1016 if(lr>0 && lr-ir != 1){
1017 if(kPRINT) printf("W - gap in rows attached !!\n");
29b87567 1018 }
b1957d3c 1019 if(kPRINT) printf("\tir[%d] lr[%d] n[%d]\n", ir, lr, ncl[ir]);
1020 // Evaluate truncated mean on the y direction
1021 if(ncl[ir] > 3) AliMathBase::EvaluateUni(ncl[ir], yres[ir], mean, syDis, Int_t(ncl[ir]*.8));
1022 else {
1023 mean = 0.; syDis = 0.;
1024 }
1025
1026 // TODO check mean and sigma agains cluster resolution !!
1027 if(kPRINT) printf("\tr[%2d] m[%f %5.3fsigma] s[%f]\n", ir, mean, TMath::Abs(mean/syRef), syDis);
1028 // select clusters on a 3 sigmaDistr level
1029 Bool_t kFOUND = kFALSE;
1030 for(Int_t ic = ncl[ir]; ic--;){
1031 if(yres[ir][ic] - mean > 3. * syDis){
1032 clst[ir][ic] = 0x0; continue;
1033 }
1034 nrow[nr]++; kFOUND = kTRUE;
1035 }
1036 // exit loop
1037 if(kFOUND) nr++;
1038 lr = ir; if(nr>=3) break;
29b87567 1039 }
b1957d3c 1040 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]);
1041
1042 // classify cluster rows
1043 Int_t row = -1;
1044 switch(nr){
1045 case 1:
1046 row = lr;
1047 break;
1048 case 2:
1049 SetBit(kRowCross, kTRUE); // mark pad row crossing
1050 if(nrow[0] > nrow[1]){ row = lr+1; lr = -1;}
1051 else{
1052 row = lr; lr = 1;
1053 nrow[2] = nrow[1];
1054 nrow[1] = nrow[0];
1055 nrow[0] = nrow[2];
29b87567 1056 }
b1957d3c 1057 break;
1058 case 3:
1059 SetBit(kRowCross, kTRUE); // mark pad row crossing
1060 break;
29b87567 1061 }
b1957d3c 1062 if(kPRINT) printf("\trow[%d] n[%d]\n\n", row, nrow[0]);
1063 if(row<0) return kFALSE;
29b87567 1064
b1957d3c 1065 // Select and store clusters
1066 // We should consider here :
1067 // 1. How far is the chamber boundary
1068 // 2. How big is the mean
3e778975 1069 Int_t n = 0;
b1957d3c 1070 for (Int_t ir = 0; ir < nr; ir++) {
1071 Int_t jr = row + ir*lr;
1072 if(kPRINT) printf("\tattach %d clusters for row %d\n", ncl[jr], jr);
1073 for (Int_t ic = 0; ic < ncl[jr]; ic++) {
1074 if(!(c = clst[jr][ic])) continue;
1075 Int_t it = c->GetPadTime();
1076 // TODO proper indexing of clusters !!
e3cf3d02 1077 fIndexes[it+kNtb*ir] = chamber->GetTB(it)->GetGlobalIndex(idxs[jr][ic]);
1078 fClusters[it+kNtb*ir] = c;
29b87567 1079
b1957d3c 1080 //printf("\tid[%2d] it[%d] idx[%d]\n", ic, it, fIndexes[it]);
1081
3e778975 1082 n++;
b1957d3c 1083 }
1084 }
1085
29b87567 1086 // number of minimum numbers of clusters expected for the tracklet
3e778975 1087 if (n < kClmin){
1088 //AliWarning(Form("Not enough clusters to fit the tracklet %d [%d].", n, kClmin));
e4f2f73d 1089 return kFALSE;
1090 }
3e778975 1091 SetN(n);
0906e73e 1092
e3cf3d02 1093 // Load calibration parameters for this tracklet
1094 Calibrate();
b1957d3c 1095
1096 // calculate dx for time bins in the drift region (calibration aware)
e3cf3d02 1097 Int_t irp = 0; Float_t x[2] = {0.,0.}; Int_t tb[2]={0,0};
b1957d3c 1098 for (Int_t it = t0; it < AliTRDtrackerV1::GetNTimeBins(); it++) {
1099 if(!fClusters[it]) continue;
1100 x[irp] = fClusters[it]->GetX();
1101 tb[irp] = it;
1102 irp++;
1103 if(irp==2) break;
e3cf3d02 1104 }
d86ed84c 1105 Int_t dtb = tb[1] - tb[0];
1106 fdX = dtb ? (x[0] - x[1]) / dtb : 0.15;
b1957d3c 1107
29b87567 1108 return kTRUE;
e4f2f73d 1109}
1110
03cef9b2 1111//____________________________________________________________
1112void AliTRDseedV1::Bootstrap(const AliTRDReconstructor *rec)
1113{
1114// Fill in all derived information. It has to be called after recovery from file or HLT.
1115// The primitive data are
1116// - list of clusters
1117// - detector (as the detector will be removed from clusters)
1118// - position of anode wire (fX0) - temporary
1119// - track reference position and direction
1120// - momentum of the track
1121// - time bin length [cm]
1122//
1123// A.Bercuci <A.Bercuci@gsi.de> Oct 30th 2008
1124//
1125 fReconstructor = rec;
1126 AliTRDgeometry g;
1127 AliTRDpadPlane *pp = g.GetPadPlane(fDet);
dd8059a8 1128 fPad[0] = pp->GetLengthIPad();
1129 fPad[1] = pp->GetWidthIPad();
1130 fPad[3] = TMath::Tan(TMath::DegToRad()*pp->GetTiltingAngle());
e3cf3d02 1131 //fSnp = fYref[1]/TMath::Sqrt(1+fYref[1]*fYref[1]);
1132 //fTgl = fZref[1];
3e778975 1133 Int_t n = 0, nshare = 0, nused = 0;
03cef9b2 1134 AliTRDcluster **cit = &fClusters[0];
8d2bec9e 1135 for(Int_t ic = kNclusters; ic--; cit++){
03cef9b2 1136 if(!(*cit)) return;
3e778975 1137 n++;
1138 if((*cit)->IsShared()) nshare++;
1139 if((*cit)->IsUsed()) nused++;
03cef9b2 1140 }
3e778975 1141 SetN(n); SetNUsed(nused); SetNShared(nshare);
e3cf3d02 1142 Fit();
03cef9b2 1143 CookLabels();
1144 GetProbability();
1145}
1146
1147
e4f2f73d 1148//____________________________________________________________________
d937ad7a 1149Bool_t AliTRDseedV1::Fit(Bool_t tilt, Int_t errors)
e4f2f73d 1150{
1151 //
1152 // Linear fit of the tracklet
1153 //
1154 // Parameters :
1155 //
1156 // Output :
1157 // True if successful
1158 //
1159 // Detailed description
1160 // 2. Check if tracklet crosses pad row boundary
1161 // 1. Calculate residuals in the y (r-phi) direction
1162 // 3. Do a Least Square Fit to the data
1163 //
1164
e3cf3d02 1165 if(!IsCalibrated()){
1166 AliWarning("Tracklet fit failed. Call Calibrate().");
1167 return kFALSE;
1168 }
1169
29b87567 1170 const Int_t kClmin = 8;
010d62b0 1171
9462866a 1172
1173 // cluster error parametrization parameters
010d62b0 1174 // 1. sy total charge
9462866a 1175 const Float_t sq0inv = 0.019962; // [1/q0]
1176 const Float_t sqb = 1.0281564; //[cm]
010d62b0 1177 // 2. sy for the PRF
1178 const Float_t scy[AliTRDgeometry::kNlayer][4] = {
d937ad7a 1179 {2.827e-02, 9.600e-04, 4.296e-01, 2.271e-02},
1180 {2.952e-02,-2.198e-04, 4.146e-01, 2.339e-02},
1181 {3.090e-02, 1.514e-03, 4.020e-01, 2.402e-02},
1182 {3.260e-02,-2.037e-03, 3.946e-01, 2.509e-02},
1183 {3.439e-02,-3.601e-04, 3.883e-01, 2.623e-02},
1184 {3.510e-02, 2.066e-03, 3.651e-01, 2.588e-02},
010d62b0 1185 };
1186 // 3. sy parallel to the track
d937ad7a 1187 const Float_t sy0 = 2.649e-02; // [cm]
1188 const Float_t sya = -8.864e-04; // [cm]
1189 const Float_t syb = -2.435e-01; // [cm]
1190
010d62b0 1191 // 4. sx parallel to the track
d937ad7a 1192 const Float_t sxgc = 5.427e-02;
1193 const Float_t sxgm = 7.783e-01;
1194 const Float_t sxgs = 2.743e-01;
1195 const Float_t sxe0 =-2.065e+00;
1196 const Float_t sxe1 =-2.978e-02;
1197
010d62b0 1198 // 5. sx perpendicular to the track
d937ad7a 1199// const Float_t sxd0 = 1.881e-02;
1200// const Float_t sxd1 =-4.101e-01;
1201// const Float_t sxd2 = 1.572e+00;
1202
2f7d6ac8 1203 // get track direction
1204 Double_t y0 = fYref[0];
1205 Double_t dydx = fYref[1];
1206 Double_t z0 = fZref[0];
1207 Double_t dzdx = fZref[1];
1208 Double_t yt, zt;
ae4e8b84 1209
e3cf3d02 1210 // calculation of tg^2(phi - a_L) and tg^2(a_L)
1211 Double_t tgg = (dydx-fExB)/(1.+dydx*fExB); tgg *= tgg;
1212 //Double_t exb2= fExB*fExB;
1213
b1957d3c 1214 //AliTRDtrackerV1::AliTRDLeastSquare fitterZ;
24d8660e 1215 TLinearFitter fitterY(1, "pol1");
29b87567 1216 // convertion factor from square to gauss distribution for sigma
b1957d3c 1217 //Double_t convert = 1./TMath::Sqrt(12.);
ae4e8b84 1218
29b87567 1219 // book cluster information
8d2bec9e 1220 Double_t qc[kNclusters], xc[kNclusters], yc[kNclusters], zc[kNclusters], sy[kNclusters];
e3cf3d02 1221
010d62b0 1222 Int_t ily = AliTRDgeometry::GetLayer(fDet);
dd8059a8 1223 Int_t n = 0;
9eb2d46c 1224 AliTRDcluster *c=0x0, **jc = &fClusters[0];
9eb2d46c 1225 for (Int_t ic=0; ic<kNtb; ic++, ++jc) {
b1957d3c 1226 //zRow[ic] = -1;
29b87567 1227 xc[ic] = -1.;
1228 yc[ic] = 999.;
1229 zc[ic] = 999.;
1230 sy[ic] = 0.;
b1957d3c 1231 //sz[ic] = 0.;
9eb2d46c 1232 if(!(c = (*jc))) continue;
29b87567 1233 if(!c->IsInChamber()) continue;
9462866a 1234
29b87567 1235 Float_t w = 1.;
1236 if(c->GetNPads()>4) w = .5;
1237 if(c->GetNPads()>5) w = .2;
010d62b0 1238
b1957d3c 1239 //zRow[fN] = c->GetPadRow();
dd8059a8 1240 qc[n] = TMath::Abs(c->GetQ());
d937ad7a 1241 // correct cluster position for PRF and v drift
e3cf3d02 1242 //Int_t jc = TMath::Max(fN-3, 0);
1243 //xc[fN] = c->GetXloc(fT0, fVD, &qc[jc], &xc[jc]/*, z0 - c->GetX()*dzdx*/);
1244 //Double_t s2 = fS2PRF + fDiffL*fDiffL*xc[fN]/(1.+2.*exb2)+tgg*xc[fN]*xc[fN]*exb2/12.;
dd8059a8 1245 //yc[fN] = c->GetYloc(s2, GetPadWidth(), xc[fN], fExB);
e3cf3d02 1246
1247 // uncalibrated cluster correction
1248 // TODO remove
ec3f0161 1249 Double_t x, y;
b25a5e9e 1250 //GetClusterXY(c, x, y);
1251 x = c->GetX(); y = c->GetY();
dd8059a8 1252 xc[n] = fX0 - x;
1253 yc[n] = y;
1254 zc[n] = c->GetZ();
2f7d6ac8 1255
1256 // extrapolated y value for the track
dd8059a8 1257 yt = y0 - xc[n]*dydx;
2f7d6ac8 1258 // extrapolated z value for the track
dd8059a8 1259 zt = z0 - xc[n]*dzdx;
2f7d6ac8 1260 // tilt correction
dd8059a8 1261 if(tilt) yc[n] -= GetTilt()*(zc[n] - zt);
2f7d6ac8 1262
010d62b0 1263 // ELABORATE CLUSTER ERROR
1264 // TODO to be moved to AliTRDcluster
010d62b0 1265 // basic y error (|| to track).
dd8059a8 1266 sy[n] = xc[n] < AliTRDgeometry::CamHght() ? 2. : sy0 + sya*TMath::Exp(1./(xc[n]+syb));
d937ad7a 1267 //printf("cluster[%d]\n\tsy[0] = %5.3e [um]\n", fN, sy[fN]*1.e4);
010d62b0 1268 // y error due to total charge
dd8059a8 1269 sy[n] += sqb*(1./qc[n] - sq0inv);
d937ad7a 1270 //printf("\tsy[1] = %5.3e [um]\n", sy[fN]*1.e4);
010d62b0 1271 // y error due to PRF
dd8059a8 1272 sy[n] += scy[ily][0]*TMath::Gaus(c->GetCenter(), scy[ily][1], scy[ily][2]) - scy[ily][3];
d937ad7a 1273 //printf("\tsy[2] = %5.3e [um]\n", sy[fN]*1.e4);
1274
dd8059a8 1275 sy[n] *= sy[n];
010d62b0 1276
1277 // ADD ERROR ON x
9462866a 1278 // error of drift length parallel to the track
dd8059a8 1279 Double_t sx = sxgc*TMath::Gaus(xc[n], sxgm, sxgs) + TMath::Exp(sxe0+sxe1*xc[n]); // [cm]
d937ad7a 1280 //printf("\tsx[0] = %5.3e [um]\n", sx*1.e4);
9462866a 1281 // error of drift length perpendicular to the track
1282 //sx += sxd0 + sxd1*d + sxd2*d*d;
d937ad7a 1283 sx *= sx; // square sx
d937ad7a 1284
9462866a 1285 // add error from ExB
dd8059a8 1286 if(errors>0) sy[n] += fExB*fExB*sx;
d937ad7a 1287 //printf("\tsy[3] = %5.3e [um^2]\n", sy[fN]*1.e8);
1288
1289 // global radial error due to misalignment/miscalibration
1290 Double_t sx0 = 0.; sx0 *= sx0;
1291 // add sx contribution to sy due to track angle
dd8059a8 1292 if(errors>1) sy[n] += tgg*(sx+sx0);
d937ad7a 1293 // TODO we should add tilt pad correction here
1294 //printf("\tsy[4] = %5.3e [um^2]\n", sy[fN]*1.e8);
dd8059a8 1295 c->SetSigmaY2(sy[n]);
d937ad7a 1296
dd8059a8 1297 sy[n] = TMath::Sqrt(sy[n]);
1298 fitterY.AddPoint(&xc[n], yc[n], sy[n]);
1299 n++;
29b87567 1300 }
47d5d320 1301 // to few clusters
dd8059a8 1302 if (n < kClmin) return kFALSE;
2f7d6ac8 1303
d937ad7a 1304 // fit XY
2f7d6ac8 1305 fitterY.Eval();
d937ad7a 1306 fYfit[0] = fitterY.GetParameter(0);
1307 fYfit[1] = -fitterY.GetParameter(1);
1308 // store covariance
1309 Double_t *p = fitterY.GetCovarianceMatrix();
1310 fCov[0] = p[0]; // variance of y0
1311 fCov[1] = p[1]; // covariance of y0, dydx
1312 fCov[2] = p[3]; // variance of dydx
b1957d3c 1313 // the ref radial position is set at the minimum of
1314 // the y variance of the tracklet
f29f13a6 1315 fX = -fCov[1]/fCov[2]; //fXref = fX0 - fXref;
1316 fS2Y = fCov[0] +2.*fX*fCov[1] + fX*fX*fCov[2];
b1957d3c 1317
1318 // fit XZ
1319 if(IsRowCross()){
1320 // TODO pad row cross position estimation !!!
1321 //AliInfo(Form("Padrow cross in detector %d", fDet));
dd8059a8 1322 fZfit[0] = .5*(zc[0]+zc[n-1]); fZfit[1] = 0.;
f29f13a6 1323 fS2Z = 0.02+1.55*fZref[1]; fS2Z *= fS2Z;
b1957d3c 1324 } else {
1325 fZfit[0] = zc[0]; fZfit[1] = 0.;
dd8059a8 1326 fS2Z = GetPadLength()*GetPadLength()/12.;
29b87567 1327 }
1328
29b87567 1329
b1957d3c 1330// // determine z offset of the fit
1331// Float_t zslope = 0.;
1332// Int_t nchanges = 0, nCross = 0;
1333// if(nz==2){ // tracklet is crossing pad row
1334// // Find the break time allowing one chage on pad-rows
1335// // with maximal number of accepted clusters
1336// Int_t padRef = zRow[0];
1337// for (Int_t ic=1; ic<fN; ic++) {
1338// if(zRow[ic] == padRef) continue;
1339//
1340// // debug
1341// if(zRow[ic-1] == zRow[ic]){
1342// printf("ERROR in pad row change!!!\n");
1343// }
1344//
1345// // evaluate parameters of the crossing point
1346// Float_t sx = (xc[ic-1] - xc[ic])*convert;
1347// fCross[0] = .5 * (xc[ic-1] + xc[ic]);
1348// fCross[2] = .5 * (zc[ic-1] + zc[ic]);
1349// fCross[3] = TMath::Max(dzdx * sx, .01);
1350// zslope = zc[ic-1] > zc[ic] ? 1. : -1.;
1351// padRef = zRow[ic];
1352// nCross = ic;
1353// nchanges++;
1354// }
1355// }
1356//
1357// // condition on nCross and reset nchanges TODO
1358//
1359// if(nchanges==1){
1360// if(dzdx * zslope < 0.){
1361// AliInfo("Tracklet-Track mismatch in dzdx. TODO.");
1362// }
1363//
1364//
1365// //zc[nc] = fitterZ.GetFunctionParameter(0);
1366// fCross[1] = fYfit[0] - fCross[0] * fYfit[1];
1367// fCross[0] = fX0 - fCross[0];
1368// }
29b87567 1369
29b87567 1370 return kTRUE;
e4f2f73d 1371}
1372
e4f2f73d 1373
f29f13a6 1374/*
e3cf3d02 1375//_____________________________________________________________________________
1376void AliTRDseedV1::FitMI()
1377{
1378//
1379// Fit the seed.
1380// Marian Ivanov's version
1381//
1382// linear fit on the y direction with respect to the reference direction.
1383// The residuals for each x (x = xc - x0) are deduced from:
1384// dy = y - yt (1)
1385// the tilting correction is written :
1386// y = yc + h*(zc-zt) (2)
1387// yt = y0+dy/dx*x (3)
1388// zt = z0+dz/dx*x (4)
1389// from (1),(2),(3) and (4)
1390// dy = yc - y0 - (dy/dx + h*dz/dx)*x + h*(zc-z0)
1391// the last term introduces the correction on y direction due to tilting pads. There are 2 ways to account for this:
1392// 1. use tilting correction for calculating the y
1393// 2. neglect tilting correction here and account for it in the error parametrization of the tracklet.
1394 const Float_t kRatio = 0.8;
1395 const Int_t kClmin = 5;
1396 const Float_t kmaxtan = 2;
1397
1398 if (TMath::Abs(fYref[1]) > kmaxtan){
1399 //printf("Exit: Abs(fYref[1]) = %3.3f, kmaxtan = %3.3f\n", TMath::Abs(fYref[1]), kmaxtan);
1400 return; // Track inclined too much
1401 }
1402
1403 Float_t sigmaexp = 0.05 + TMath::Abs(fYref[1] * 0.25); // Expected r.m.s in y direction
dd8059a8 1404 Float_t ycrosscor = GetPadLength() * GetTilt() * 0.5; // Y correction for crossing
e3cf3d02 1405 Int_t fNChange = 0;
1406
1407 Double_t sumw;
1408 Double_t sumwx;
1409 Double_t sumwx2;
1410 Double_t sumwy;
1411 Double_t sumwxy;
1412 Double_t sumwz;
1413 Double_t sumwxz;
1414
1415 // Buffering: Leave it constant fot Performance issues
1416 Int_t zints[kNtb]; // Histograming of the z coordinate
1417 // Get 1 and second max probable coodinates in z
1418 Int_t zouts[2*kNtb];
1419 Float_t allowedz[kNtb]; // Allowed z for given time bin
1420 Float_t yres[kNtb]; // Residuals from reference
dd8059a8 1421 //Float_t anglecor = GetTilt() * fZref[1]; // Correction to the angle
e3cf3d02 1422
1423 Float_t pos[3*kNtb]; memset(pos, 0, 3*kNtb*sizeof(Float_t));
1424 Float_t *fX = &pos[0], *fY = &pos[kNtb], *fZ = &pos[2*kNtb];
1425
1426 Int_t fN = 0; AliTRDcluster *c = 0x0;
1427 fN2 = 0;
1428 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1429 yres[i] = 10000.0;
1430 if (!(c = fClusters[i])) continue;
1431 if(!c->IsInChamber()) continue;
1432 // Residual y
dd8059a8 1433 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
e3cf3d02 1434 fX[i] = fX0 - c->GetX();
1435 fY[i] = c->GetY();
1436 fZ[i] = c->GetZ();
dd8059a8 1437 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
e3cf3d02 1438 zints[fN] = Int_t(fZ[i]);
1439 fN++;
1440 }
1441
1442 if (fN < kClmin){
1443 //printf("Exit fN < kClmin: fN = %d\n", fN);
1444 return;
1445 }
1446 Int_t nz = AliTRDtrackerV1::Freq(fN, zints, zouts, kFALSE);
1447 Float_t fZProb = zouts[0];
1448 if (nz <= 1) zouts[3] = 0;
1449 if (zouts[1] + zouts[3] < kClmin) {
1450 //printf("Exit zouts[1] = %d, zouts[3] = %d\n",zouts[1],zouts[3]);
1451 return;
1452 }
1453
1454 // Z distance bigger than pad - length
1455 if (TMath::Abs(zouts[0]-zouts[2]) > 12.0) zouts[3] = 0;
1456
1457 Int_t breaktime = -1;
1458 Bool_t mbefore = kFALSE;
1459 Int_t cumul[kNtb][2];
1460 Int_t counts[2] = { 0, 0 };
1461
1462 if (zouts[3] >= 3) {
1463
1464 //
1465 // Find the break time allowing one chage on pad-rows
1466 // with maximal number of accepted clusters
1467 //
1468 fNChange = 1;
1469 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1470 cumul[i][0] = counts[0];
1471 cumul[i][1] = counts[1];
1472 if (TMath::Abs(fZ[i]-zouts[0]) < 2) counts[0]++;
1473 if (TMath::Abs(fZ[i]-zouts[2]) < 2) counts[1]++;
1474 }
1475 Int_t maxcount = 0;
1476 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1477 Int_t after = cumul[AliTRDtrackerV1::GetNTimeBins()][0] - cumul[i][0];
1478 Int_t before = cumul[i][1];
1479 if (after + before > maxcount) {
1480 maxcount = after + before;
1481 breaktime = i;
1482 mbefore = kFALSE;
1483 }
1484 after = cumul[AliTRDtrackerV1::GetNTimeBins()-1][1] - cumul[i][1];
1485 before = cumul[i][0];
1486 if (after + before > maxcount) {
1487 maxcount = after + before;
1488 breaktime = i;
1489 mbefore = kTRUE;
1490 }
1491 }
1492 breaktime -= 1;
1493 }
1494
1495 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1496 if (i > breaktime) allowedz[i] = mbefore ? zouts[2] : zouts[0];
1497 if (i <= breaktime) allowedz[i] = (!mbefore) ? zouts[2] : zouts[0];
1498 }
1499
1500 if (((allowedz[0] > allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] < 0)) ||
1501 ((allowedz[0] < allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] > 0))) {
1502 //
1503 // Tracklet z-direction not in correspondance with track z direction
1504 //
1505 fNChange = 0;
1506 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1507 allowedz[i] = zouts[0]; // Only longest taken
1508 }
1509 }
1510
1511 if (fNChange > 0) {
1512 //
1513 // Cross pad -row tracklet - take the step change into account
1514 //
1515 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1516 if (!fClusters[i]) continue;
1517 if(!fClusters[i]->IsInChamber()) continue;
1518 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1519 // Residual y
dd8059a8 1520 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
1521 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
f29f13a6 1522// if (TMath::Abs(fZ[i] - fZProb) > 2) {
dd8059a8 1523// if (fZ[i] > fZProb) yres[i] += GetTilt() * GetPadLength();
1524// if (fZ[i] < fZProb) yres[i] -= GetTilt() * GetPadLength();
f29f13a6 1525 }
e3cf3d02 1526 }
1527 }
1528
1529 Double_t yres2[kNtb];
1530 Double_t mean;
1531 Double_t sigma;
1532 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1533 if (!fClusters[i]) continue;
1534 if(!fClusters[i]->IsInChamber()) continue;
1535 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1536 yres2[fN2] = yres[i];
1537 fN2++;
1538 }
1539 if (fN2 < kClmin) {
1540 //printf("Exit fN2 < kClmin: fN2 = %d\n", fN2);
1541 fN2 = 0;
1542 return;
1543 }
1544 AliMathBase::EvaluateUni(fN2,yres2,mean,sigma, Int_t(fN2*kRatio-2.));
1545 if (sigma < sigmaexp * 0.8) {
1546 sigma = sigmaexp;
1547 }
1548 //Float_t fSigmaY = sigma;
1549
1550 // Reset sums
1551 sumw = 0;
1552 sumwx = 0;
1553 sumwx2 = 0;
1554 sumwy = 0;
1555 sumwxy = 0;
1556 sumwz = 0;
1557 sumwxz = 0;
1558
1559 fN2 = 0;
1560 Float_t fMeanz = 0;
1561 Float_t fMPads = 0;
1562 fUsable = 0;
1563 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1564 if (!fClusters[i]) continue;
1565 if (!fClusters[i]->IsInChamber()) continue;
1566 if (TMath::Abs(fZ[i] - allowedz[i]) > 2){fClusters[i] = 0x0; continue;}
1567 if (TMath::Abs(yres[i] - mean) > 4.0 * sigma){fClusters[i] = 0x0; continue;}
1568 SETBIT(fUsable,i);
1569 fN2++;
1570 fMPads += fClusters[i]->GetNPads();
1571 Float_t weight = 1.0;
1572 if (fClusters[i]->GetNPads() > 4) weight = 0.5;
1573 if (fClusters[i]->GetNPads() > 5) weight = 0.2;
1574
1575
1576 Double_t x = fX[i];
1577 //printf("x = %7.3f dy = %7.3f fit %7.3f\n", x, yres[i], fY[i]-yres[i]);
1578
1579 sumw += weight;
1580 sumwx += x * weight;
1581 sumwx2 += x*x * weight;
1582 sumwy += weight * yres[i];
1583 sumwxy += weight * (yres[i]) * x;
1584 sumwz += weight * fZ[i];
1585 sumwxz += weight * fZ[i] * x;
1586
1587 }
1588
1589 if (fN2 < kClmin){
1590 //printf("Exit fN2 < kClmin(2): fN2 = %d\n",fN2);
1591 fN2 = 0;
1592 return;
1593 }
1594 fMeanz = sumwz / sumw;
1595 Float_t correction = 0;
1596 if (fNChange > 0) {
1597 // Tracklet on boundary
1598 if (fMeanz < fZProb) correction = ycrosscor;
1599 if (fMeanz > fZProb) correction = -ycrosscor;
1600 }
1601
1602 Double_t det = sumw * sumwx2 - sumwx * sumwx;
1603 fYfit[0] = (sumwx2 * sumwy - sumwx * sumwxy) / det;
1604 fYfit[1] = (sumw * sumwxy - sumwx * sumwy) / det;
1605
1606 fS2Y = 0;
1607 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1608 if (!TESTBIT(fUsable,i)) continue;
1609 Float_t delta = yres[i] - fYfit[0] - fYfit[1] * fX[i];
1610 fS2Y += delta*delta;
1611 }
1612 fS2Y = TMath::Sqrt(fS2Y / Float_t(fN2-2));
1613 // TEMPORARY UNTIL covariance properly calculated
1614 fS2Y = TMath::Max(fS2Y, Float_t(.1));
1615
1616 fZfit[0] = (sumwx2 * sumwz - sumwx * sumwxz) / det;
1617 fZfit[1] = (sumw * sumwxz - sumwx * sumwz) / det;
1618// fYfitR[0] += fYref[0] + correction;
1619// fYfitR[1] += fYref[1];
1620// fYfit[0] = fYfitR[0];
1621 fYfit[1] = -fYfit[1];
1622
1623 UpdateUsed();
f29f13a6 1624}*/
e3cf3d02 1625
e4f2f73d 1626//___________________________________________________________________
203967fc 1627void AliTRDseedV1::Print(Option_t *o) const
e4f2f73d 1628{
1629 //
1630 // Printing the seedstatus
1631 //
1632
eb2b4f91 1633 AliInfo(Form("Det[%3d] X0[%7.2f] Pad[L[%5.2f] W[%5.2f] Tilt[%+6.2f]]", fDet, fX0, GetPadLength(), GetPadWidth(), GetTilt()));
dd8059a8 1634 AliInfo(Form("N[%2d] Nused[%2d] Nshared[%2d] [%d]", GetN(), GetNUsed(), GetNShared(), fN));
1635
1636 Double_t cov[3], x=GetX();
1637 GetCovAt(x, cov);
1638 AliInfo(" | x[cm] | y[cm] | z[cm] | dydx | dzdx |");
1639 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]));
1640 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 1641
1642
1643 if(strcmp(o, "a")!=0) return;
1644
4dc4dc2e 1645 AliTRDcluster* const* jc = &fClusters[0];
8d2bec9e 1646 for(int ic=0; ic<kNclusters; ic++, jc++) {
4dc4dc2e 1647 if(!(*jc)) continue;
203967fc 1648 (*jc)->Print(o);
4dc4dc2e 1649 }
e4f2f73d 1650}
47d5d320 1651
203967fc 1652
1653//___________________________________________________________________
1654Bool_t AliTRDseedV1::IsEqual(const TObject *o) const
1655{
1656 // Checks if current instance of the class has the same essential members
1657 // as the given one
1658
1659 if(!o) return kFALSE;
1660 const AliTRDseedV1 *inTracklet = dynamic_cast<const AliTRDseedV1*>(o);
1661 if(!inTracklet) return kFALSE;
1662
1663 for (Int_t i = 0; i < 2; i++){
e3cf3d02 1664 if ( fYref[i] != inTracklet->fYref[i] ) return kFALSE;
1665 if ( fZref[i] != inTracklet->fZref[i] ) return kFALSE;
203967fc 1666 }
1667
e3cf3d02 1668 if ( fS2Y != inTracklet->fS2Y ) return kFALSE;
dd8059a8 1669 if ( GetTilt() != inTracklet->GetTilt() ) return kFALSE;
1670 if ( GetPadLength() != inTracklet->GetPadLength() ) return kFALSE;
203967fc 1671
8d2bec9e 1672 for (Int_t i = 0; i < kNclusters; i++){
e3cf3d02 1673// if ( fX[i] != inTracklet->GetX(i) ) return kFALSE;
1674// if ( fY[i] != inTracklet->GetY(i) ) return kFALSE;
1675// if ( fZ[i] != inTracklet->GetZ(i) ) return kFALSE;
1676 if ( fIndexes[i] != inTracklet->fIndexes[i] ) return kFALSE;
203967fc 1677 }
f29f13a6 1678// if ( fUsable != inTracklet->fUsable ) return kFALSE;
203967fc 1679
1680 for (Int_t i=0; i < 2; i++){
e3cf3d02 1681 if ( fYfit[i] != inTracklet->fYfit[i] ) return kFALSE;
1682 if ( fZfit[i] != inTracklet->fZfit[i] ) return kFALSE;
1683 if ( fLabels[i] != inTracklet->fLabels[i] ) return kFALSE;
203967fc 1684 }
1685
e3cf3d02 1686/* if ( fMeanz != inTracklet->GetMeanz() ) return kFALSE;
1687 if ( fZProb != inTracklet->GetZProb() ) return kFALSE;*/
3e778975 1688 if ( fN != inTracklet->fN ) return kFALSE;
1689 //if ( fNUsed != inTracklet->fNUsed ) return kFALSE;
e3cf3d02 1690 //if ( fFreq != inTracklet->GetFreq() ) return kFALSE;
1691 //if ( fNChange != inTracklet->GetNChange() ) return kFALSE;
203967fc 1692
e3cf3d02 1693 if ( fC != inTracklet->fC ) return kFALSE;
1694 //if ( fCC != inTracklet->GetCC() ) return kFALSE;
1695 if ( fChi2 != inTracklet->fChi2 ) return kFALSE;
203967fc 1696 // if ( fChi2Z != inTracklet->GetChi2Z() ) return kFALSE;
1697
e3cf3d02 1698 if ( fDet != inTracklet->fDet ) return kFALSE;
b25a5e9e 1699 if ( fPt != inTracklet->fPt ) return kFALSE;
e3cf3d02 1700 if ( fdX != inTracklet->fdX ) return kFALSE;
203967fc 1701
8d2bec9e 1702 for (Int_t iCluster = 0; iCluster < kNclusters; iCluster++){
203967fc 1703 AliTRDcluster *curCluster = fClusters[iCluster];
e3cf3d02 1704 AliTRDcluster *inCluster = inTracklet->fClusters[iCluster];
203967fc 1705 if (curCluster && inCluster){
1706 if (! curCluster->IsEqual(inCluster) ) {
1707 curCluster->Print();
1708 inCluster->Print();
1709 return kFALSE;
1710 }
1711 } else {
1712 // if one cluster exists, and corresponding
1713 // in other tracklet doesn't - return kFALSE
1714 if(curCluster || inCluster) return kFALSE;
1715 }
1716 }
1717 return kTRUE;
1718}