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