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